@@ -58,7 +58,10 @@ public void TestVerifyCertificateAsUnrevoked()
5858 MockByteResponseForGet ( restRequester , DigiCertCrlUrl2 , crlBytes ) ;
5959 var crlRepository = new CrlRepository ( config . EnableCRLInMemoryCaching , config . EnableCRLDiskCaching ) ;
6060 var environmentOperation = new Mock < EnvironmentOperations > ( ) ;
61- var verifier = new CertificateRevocationVerifier ( config , TimeProvider . Instance , restRequester . Object , CertificateCrlDistributionPointsExtractor . Instance , new CrlParser ( environmentOperation . Object ) , crlRepository ) ;
61+ var timeProvider = new Mock < TimeProvider > ( ) ;
62+ var testTime = DateTimeOffset . Parse ( DigiCertThisUpdateString ) . UtcDateTime . AddHours ( 1 ) ;
63+ timeProvider . Setup ( tp => tp . UtcNow ( ) ) . Returns ( testTime ) ;
64+ var verifier = new CertificateRevocationVerifier ( config , timeProvider . Object , restRequester . Object , CertificateCrlDistributionPointsExtractor . Instance , new CrlParser ( environmentOperation . Object ) , crlRepository ) ;
6265
6366 // act
6467 var result = verifier . CheckCertRevocation ( certificate , expectedCrlUrls , parentCertificate ) ;
@@ -81,7 +84,10 @@ public void TestVerifyCertificateAsErrorWhenCouldNotDownloadCrl()
8184 MockErrorResponseForGet ( restRequester , DigiCertCrlUrl2 , NotFoundHttpExceptionProvider ) ;
8285 var crlRepository = new CrlRepository ( config . EnableCRLInMemoryCaching , config . EnableCRLDiskCaching ) ;
8386 var environmentOperation = new Mock < EnvironmentOperations > ( ) ;
84- var verifier = new CertificateRevocationVerifier ( config , TimeProvider . Instance , restRequester . Object , CertificateCrlDistributionPointsExtractor . Instance , new CrlParser ( environmentOperation . Object ) , crlRepository ) ;
87+ var timeProvider = new Mock < TimeProvider > ( ) ;
88+ var testTime = DateTimeOffset . Parse ( DigiCertThisUpdateString ) . UtcDateTime . AddHours ( 1 ) ;
89+ timeProvider . Setup ( tp => tp . UtcNow ( ) ) . Returns ( testTime ) ;
90+ var verifier = new CertificateRevocationVerifier ( config , timeProvider . Object , restRequester . Object , CertificateCrlDistributionPointsExtractor . Instance , new CrlParser ( environmentOperation . Object ) , crlRepository ) ;
8591
8692 // act
8793 var result = verifier . CheckCertRevocation ( certificate , expectedCrlUrls , parentCertificate ) ;
@@ -105,7 +111,10 @@ public void TestVerifyCertificateAsErrorWhenOneOfCrlsIsNotParsable()
105111 MockByteResponseForGet ( restRequester , DigiCertCrlUrl1 , notParsableCrlBytes ) ;
106112 var crlRepository = new CrlRepository ( config . EnableCRLInMemoryCaching , config . EnableCRLDiskCaching ) ;
107113 var environmentOperation = new Mock < EnvironmentOperations > ( ) ;
108- var verifier = new CertificateRevocationVerifier ( config , TimeProvider . Instance , restRequester . Object , CertificateCrlDistributionPointsExtractor . Instance , new CrlParser ( environmentOperation . Object ) , crlRepository ) ;
114+ var timeProvider = new Mock < TimeProvider > ( ) ;
115+ var testTime = DateTimeOffset . Parse ( DigiCertThisUpdateString ) . UtcDateTime . AddHours ( 1 ) ;
116+ timeProvider . Setup ( tp => tp . UtcNow ( ) ) . Returns ( testTime ) ;
117+ var verifier = new CertificateRevocationVerifier ( config , timeProvider . Object , restRequester . Object , CertificateCrlDistributionPointsExtractor . Instance , new CrlParser ( environmentOperation . Object ) , crlRepository ) ;
109118
110119 // act
111120 var result = verifier . CheckCertRevocation ( certificate , expectedCrlUrls , parentCertificate ) ;
@@ -141,7 +150,10 @@ public void TestVerifyCertificateAsErrorWhenCrlExceedsMaxSize()
141150
142151 var crlRepository = new CrlRepository ( config . EnableCRLInMemoryCaching , config . EnableCRLDiskCaching ) ;
143152 var environmentOperation = new Mock < EnvironmentOperations > ( ) ;
144- var verifier = new CertificateRevocationVerifier ( config , TimeProvider . Instance , restRequester . Object , CertificateCrlDistributionPointsExtractor . Instance , new CrlParser ( environmentOperation . Object ) , crlRepository ) ;
153+ var timeProvider = new Mock < TimeProvider > ( ) ;
154+ var testTime = DateTimeOffset . Parse ( DigiCertThisUpdateString ) . UtcDateTime . AddHours ( 1 ) ;
155+ timeProvider . Setup ( tp => tp . UtcNow ( ) ) . Returns ( testTime ) ;
156+ var verifier = new CertificateRevocationVerifier ( config , timeProvider . Object , restRequester . Object , CertificateCrlDistributionPointsExtractor . Instance , new CrlParser ( environmentOperation . Object ) , crlRepository ) ;
145157
146158 // act
147159 var result = verifier . CheckCertRevocation ( certificate , expectedCrlUrls , parentCertificate ) ;
@@ -339,6 +351,99 @@ private static void MockErrorResponseForGet(Mock<IRestRequester> restRequester,
339351 . Throws ( exceptionProvider ) ;
340352 }
341353
354+ [ Test ]
355+ public void TestDownloadedCrlIsExpiredAndNoneValidExists ( )
356+ {
357+ // arrange
358+ var now = DateTime . UtcNow ;
359+ var timeProvider = new Mock < TimeProvider > ( ) ;
360+ timeProvider . Setup ( tp => tp . UtcNow ( ) ) . Returns ( now ) ;
361+ var expectedCrlUrls = new [ ] { "http://test.crl" } ;
362+
363+ var certKeys = CertificateGenerator . GenerateKeysForCertAndItsParent ( ) ;
364+ var certSubject = "CN=Test Cert CN, O=Snowflake, OU=Drivers, L=Warsaw, ST=Masovian, C=Poland" ;
365+ var rootSubject = "CN=Test Root CA, O=Snowflake, OU=Drivers, L=Warsaw, ST=Masovian, C=Poland" ;
366+ var certificate = CertificateGenerator . GenerateCertificate ( certSubject , rootSubject , DateTimeOffset . Now . AddDays ( - 1 ) , DateTimeOffset . Now . AddDays ( 300 ) , new [ ] { expectedCrlUrls } , certKeys [ 0 ] ) ;
367+ var parentCertificate = CertificateGenerator . GenerateCertificate ( rootSubject , rootSubject , DateTimeOffset . Now . AddDays ( - 1 ) , DateTimeOffset . Now . AddDays ( 300 ) , null , certKeys [ 1 ] ) ;
368+ var config = GetHttpConfig ( ) ;
369+
370+ var expiredCrl = CertificateGenerator . GenerateCrl (
371+ CertificateGenerator . SHA256WithRsaAlgorithm ,
372+ certKeys [ 1 ] . Private ,
373+ rootSubject ,
374+ now . AddHours ( - 2 ) ,
375+ now . AddHours ( - 1 ) ,
376+ now . AddHours ( - 2 )
377+ ) ;
378+ var crlBytes = expiredCrl . GetEncoded ( ) ;
379+
380+ var restRequester = new Mock < IRestRequester > ( ) ;
381+ MockByteResponseForGet ( restRequester , expectedCrlUrls [ 0 ] , crlBytes ) ;
382+ var crlRepository = new CrlRepository ( config . EnableCRLInMemoryCaching , config . EnableCRLDiskCaching ) ;
383+ var environmentOperation = new Mock < EnvironmentOperations > ( ) ;
384+ var verifier = new CertificateRevocationVerifier ( config , timeProvider . Object , restRequester . Object , CertificateCrlDistributionPointsExtractor . Instance , new CrlParser ( environmentOperation . Object ) , crlRepository ) ;
385+
386+ // act
387+ var result = verifier . CheckCertRevocation ( certificate , expectedCrlUrls , parentCertificate ) ;
388+
389+ // assert
390+ Assert . AreEqual ( CertRevocationCheckResult . CertError , result ) ;
391+ }
392+
393+ [ Test ]
394+ public void TestDownloadedCrlIsExpiredButTheValidExists ( )
395+ {
396+ // arrange
397+ var now = DateTime . UtcNow ;
398+ var timeProvider = new Mock < TimeProvider > ( ) ;
399+ timeProvider . Setup ( tp => tp . UtcNow ( ) ) . Returns ( now ) ;
400+ var expectedCrlUrls = new [ ] { "http://test.crl" } ;
401+
402+ var certKeys = CertificateGenerator . GenerateKeysForCertAndItsParent ( ) ;
403+ var certSubject = "CN=Test Cert CN, O=Snowflake, OU=Drivers, L=Warsaw, ST=Masovian, C=Poland" ;
404+ var rootSubject = "CN=Test Root CA, O=Snowflake, OU=Drivers, L=Warsaw, ST=Masovian, C=Poland" ;
405+ var certificate = CertificateGenerator . GenerateCertificate ( certSubject , rootSubject , DateTimeOffset . Now . AddDays ( - 1 ) , DateTimeOffset . Now . AddDays ( 300 ) , new [ ] { expectedCrlUrls } , certKeys [ 0 ] ) ;
406+ var parentCertificate = CertificateGenerator . GenerateCertificate ( rootSubject , rootSubject , DateTimeOffset . Now . AddDays ( - 1 ) , DateTimeOffset . Now . AddDays ( 300 ) , null , certKeys [ 1 ] ) ;
407+ var config = GetHttpConfig ( ) ;
408+
409+ var validCrl = CertificateGenerator . GenerateCrl (
410+ CertificateGenerator . SHA256WithRsaAlgorithm ,
411+ certKeys [ 1 ] . Private ,
412+ rootSubject ,
413+ now . AddDays ( - 2 ) ,
414+ now . AddHours ( 2 ) , // NextUpdate in future
415+ now . AddDays ( - 2 )
416+ ) ;
417+
418+ var expiredCrl = CertificateGenerator . GenerateCrl (
419+ CertificateGenerator . SHA256WithRsaAlgorithm ,
420+ certKeys [ 1 ] . Private ,
421+ rootSubject ,
422+ now . AddHours ( - 2 ) ,
423+ now . AddHours ( - 1 ) ,
424+ now . AddHours ( - 2 )
425+ ) ;
426+ var expiredCrlBytes = expiredCrl . GetEncoded ( ) ;
427+
428+ var restRequester = new Mock < IRestRequester > ( ) ;
429+ MockByteResponseForGet ( restRequester , expectedCrlUrls [ 0 ] , expiredCrlBytes ) ;
430+ var crlRepository = new CrlRepository ( config . EnableCRLInMemoryCaching , config . EnableCRLDiskCaching ) ;
431+ var environmentOperation = new Mock < EnvironmentOperations > ( ) ;
432+ var crlParser = new CrlParser ( environmentOperation . Object ) ;
433+
434+ // Pre-populate cache with valid CRL
435+ var cachedCrlObject = crlParser . Create ( validCrl , now . AddHours ( - 25 ) ) ;
436+ crlRepository . Set ( expectedCrlUrls [ 0 ] , cachedCrlObject ) ;
437+
438+ var verifier = new CertificateRevocationVerifier ( config , timeProvider . Object , restRequester . Object , CertificateCrlDistributionPointsExtractor . Instance , crlParser , crlRepository ) ;
439+
440+ // act
441+ var result = verifier . CheckCertRevocation ( certificate , expectedCrlUrls , parentCertificate ) ;
442+
443+ // assert
444+ Assert . AreEqual ( CertRevocationCheckResult . CertUnrevoked , result ) ;
445+ }
446+
342447 private HttpClientConfig GetHttpConfig ( CertRevocationCheckMode checkMode = CertRevocationCheckMode . Enabled , long crlDownloadMaxSize = 209715200 ) =>
343448 new HttpClientConfig (
344449 null ,
@@ -353,7 +458,7 @@ private HttpClientConfig GetHttpConfig(CertRevocationCheckMode checkMode = CertR
353458 true ,
354459 checkMode . ToString ( ) ,
355460 false ,
356- false ,
461+ true ,
357462 false ,
358463 10 ,
359464 crlDownloadMaxSize ) ;
0 commit comments