@@ -162,9 +162,27 @@ func (c *Client) getHashAlgorithmFromOID(target pkix.AlgorithmIdentifier) crypto
162162 return crypto .SHA1
163163}
164164
165- // isInValidityRange checks the validity
166- func isInValidityRange (currTime , nextUpdate time.Time ) bool {
167- return ! nextUpdate .IsZero () && ! currTime .After (nextUpdate )
165+ // isInValidityRange checks the validity times of the OCSP response making sure
166+ // that thisUpdate and nextUpdate values are bounded within currTime
167+ func isInValidityRange (currTime time.Time , ocspRes * ocsp.Response ) bool {
168+ thisUpdate := ocspRes .ThisUpdate
169+
170+ // If the thisUpdate value in the OCSP response wasn't set or greater than current time fail this check
171+ if thisUpdate .IsZero () || thisUpdate .After (currTime ) {
172+ return false
173+ }
174+
175+ nextUpdate := ocspRes .NextUpdate
176+ if nextUpdate .IsZero () {
177+ // We don't have a nextUpdate field set, assume we are okay.
178+ return true
179+ }
180+
181+ if currTime .After (nextUpdate ) || thisUpdate .After (nextUpdate ) {
182+ return false
183+ }
184+
185+ return true
168186}
169187
170188func extractCertIDKeyFromRequest (ocspReq []byte ) (* certIDKey , * ocspStatus ) {
@@ -209,7 +227,7 @@ func (c *Client) encodeCertIDKey(certIDKeyBase64 string) (*certIDKey, error) {
209227 }, nil
210228}
211229
212- func (c * Client ) checkOCSPResponseCache (encodedCertID * certIDKey , subject , issuer * x509.Certificate ) (* ocspStatus , error ) {
230+ func (c * Client ) checkOCSPResponseCache (encodedCertID * certIDKey , subject , issuer * x509.Certificate , config * VerifyConfig ) (* ocspStatus , error ) {
213231 c .ocspResponseCacheLock .RLock ()
214232 var cacheValue * ocspCachedResponse
215233 v , ok := c .ocspResponseCache .Get (* encodedCertID )
@@ -218,7 +236,7 @@ func (c *Client) checkOCSPResponseCache(encodedCertID *certIDKey, subject, issue
218236 }
219237 c .ocspResponseCacheLock .RUnlock ()
220238
221- status , err := c .extractOCSPCacheResponseValue (cacheValue , subject , issuer )
239+ status , err := c .extractOCSPCacheResponseValue (cacheValue , subject , issuer , config )
222240 if err != nil {
223241 return nil , err
224242 }
@@ -235,18 +253,25 @@ func (c *Client) deleteOCSPCache(encodedCertID *certIDKey) {
235253 c .ocspResponseCacheLock .Unlock ()
236254}
237255
238- func validateOCSP (ocspRes * ocsp.Response ) (* ocspStatus , error ) {
256+ func validateOCSP (conf * VerifyConfig , ocspRes * ocsp.Response ) (* ocspStatus , error ) {
239257 curTime := time .Now ()
240258
241259 if ocspRes == nil {
242260 return nil , errors .New ("OCSP Response is nil" )
243261 }
244- if ! isInValidityRange (curTime , ocspRes . NextUpdate ) {
262+ if ! isInValidityRange (curTime , ocspRes ) {
245263 return & ocspStatus {
246264 code : ocspInvalidValidity ,
247265 err : fmt .Errorf ("invalid validity: producedAt: %v, thisUpdate: %v, nextUpdate: %v" , ocspRes .ProducedAt , ocspRes .ThisUpdate , ocspRes .NextUpdate ),
248266 }, nil
249267 }
268+
269+ if conf .OcspThisUpdateMaxAge > 0 && curTime .Sub (ocspRes .ThisUpdate ) > conf .OcspThisUpdateMaxAge {
270+ return & ocspStatus {
271+ code : ocspInvalidValidity ,
272+ err : fmt .Errorf ("invalid validity: thisUpdate: %v is greater than max age: %s" , ocspRes .ThisUpdate , conf .OcspThisUpdateMaxAge ),
273+ }, nil
274+ }
250275 return returnOCSPStatus (ocspRes ), nil
251276}
252277
@@ -450,7 +475,7 @@ func (c *Client) retryOCSP(
450475
451476// GetRevocationStatus checks the certificate revocation status for subject using issuer certificate.
452477func (c * Client ) GetRevocationStatus (ctx context.Context , subject , issuer * x509.Certificate , conf * VerifyConfig ) (* ocspStatus , error ) {
453- status , ocspReq , encodedCertID , err := c .validateWithCache (subject , issuer )
478+ status , ocspReq , encodedCertID , err := c .validateWithCache (subject , issuer , conf )
454479 if err != nil {
455480 return nil , err
456481 }
@@ -510,7 +535,7 @@ func (c *Client) GetRevocationStatus(ctx context.Context, subject, issuer *x509.
510535 return nil
511536 }
512537
513- ret , err := validateOCSP (ocspRes )
538+ ret , err := validateOCSP (conf , ocspRes )
514539 if err != nil {
515540 errors [i ] = err
516541 return err
@@ -582,6 +607,12 @@ func (c *Client) GetRevocationStatus(ctx context.Context, subject, issuer *x509.
582607 if ! isValidOCSPStatus (ret .code ) {
583608 return ret , nil
584609 }
610+
611+ if ocspRes .NextUpdate .IsZero () {
612+ // We should not cache values with no NextUpdate values
613+ return ret , nil
614+ }
615+
585616 v := ocspCachedResponse {
586617 status : ret .code ,
587618 time : float64 (time .Now ().UTC ().Unix ()),
@@ -602,11 +633,12 @@ func isValidOCSPStatus(status ocspStatusCode) bool {
602633}
603634
604635type VerifyConfig struct {
605- OcspEnabled bool
606- ExtraCas []* x509.Certificate
607- OcspServersOverride []string
608- OcspFailureMode FailOpenMode
609- QueryAllServers bool
636+ OcspEnabled bool
637+ ExtraCas []* x509.Certificate
638+ OcspServersOverride []string
639+ OcspFailureMode FailOpenMode
640+ QueryAllServers bool
641+ OcspThisUpdateMaxAge time.Duration
610642}
611643
612644// VerifyLeafCertificate verifies just the subject against it's direct issuer
@@ -692,12 +724,12 @@ func (c *Client) canEarlyExitForOCSP(results []*ocspStatus, chainSize int, conf
692724 return nil
693725}
694726
695- func (c * Client ) validateWithCacheForAllCertificates (verifiedChains []* x509.Certificate ) (bool , error ) {
727+ func (c * Client ) validateWithCacheForAllCertificates (verifiedChains []* x509.Certificate , config * VerifyConfig ) (bool , error ) {
696728 n := len (verifiedChains ) - 1
697729 for j := 0 ; j < n ; j ++ {
698730 subject := verifiedChains [j ]
699731 issuer := verifiedChains [j + 1 ]
700- status , _ , _ , err := c .validateWithCache (subject , issuer )
732+ status , _ , _ , err := c .validateWithCache (subject , issuer , config )
701733 if err != nil {
702734 return false , err
703735 }
@@ -708,7 +740,7 @@ func (c *Client) validateWithCacheForAllCertificates(verifiedChains []*x509.Cert
708740 return true , nil
709741}
710742
711- func (c * Client ) validateWithCache (subject , issuer * x509.Certificate ) (* ocspStatus , []byte , * certIDKey , error ) {
743+ func (c * Client ) validateWithCache (subject , issuer * x509.Certificate , config * VerifyConfig ) (* ocspStatus , []byte , * certIDKey , error ) {
712744 ocspReq , err := ocsp .CreateRequest (subject , issuer , & ocsp.RequestOptions {})
713745 if err != nil {
714746 return nil , nil , nil , fmt .Errorf ("failed to create OCSP request from the certificates: %v" , err )
@@ -717,15 +749,15 @@ func (c *Client) validateWithCache(subject, issuer *x509.Certificate) (*ocspStat
717749 if ocspS .code != ocspSuccess {
718750 return nil , nil , nil , fmt .Errorf ("failed to extract CertID from OCSP Request: %v" , err )
719751 }
720- status , err := c .checkOCSPResponseCache (encodedCertID , subject , issuer )
752+ status , err := c .checkOCSPResponseCache (encodedCertID , subject , issuer , config )
721753 if err != nil {
722754 return nil , nil , nil , err
723755 }
724756 return status , ocspReq , encodedCertID , nil
725757}
726758
727759func (c * Client ) GetAllRevocationStatus (ctx context.Context , verifiedChains []* x509.Certificate , conf * VerifyConfig ) ([]* ocspStatus , error ) {
728- _ , err := c .validateWithCacheForAllCertificates (verifiedChains )
760+ _ , err := c .validateWithCacheForAllCertificates (verifiedChains , conf )
729761 if err != nil {
730762 return nil , err
731763 }
@@ -750,11 +782,11 @@ func (c *Client) verifyPeerCertificateSerial(conf *VerifyConfig) func(_ [][]byte
750782 }
751783}
752784
753- func (c * Client ) extractOCSPCacheResponseValueWithoutSubject (cacheValue ocspCachedResponse ) (* ocspStatus , error ) {
754- return c .extractOCSPCacheResponseValue (& cacheValue , nil , nil )
785+ func (c * Client ) extractOCSPCacheResponseValueWithoutSubject (cacheValue ocspCachedResponse , conf * VerifyConfig ) (* ocspStatus , error ) {
786+ return c .extractOCSPCacheResponseValue (& cacheValue , nil , nil , conf )
755787}
756788
757- func (c * Client ) extractOCSPCacheResponseValue (cacheValue * ocspCachedResponse , subject , issuer * x509.Certificate ) (* ocspStatus , error ) {
789+ func (c * Client ) extractOCSPCacheResponseValue (cacheValue * ocspCachedResponse , subject , issuer * x509.Certificate , conf * VerifyConfig ) (* ocspStatus , error ) {
758790 subjectName := "Unknown"
759791 if subject != nil {
760792 subjectName = subject .Subject .CommonName
@@ -778,7 +810,7 @@ func (c *Client) extractOCSPCacheResponseValue(cacheValue *ocspCachedResponse, s
778810
779811 sdkOcspStatus := internalStatusCodeToSDK (cacheValue .status )
780812
781- return validateOCSP (& ocsp.Response {
813+ return validateOCSP (conf , & ocsp.Response {
782814 ProducedAt : time .Unix (int64 (cacheValue .producedAt ), 0 ).UTC (),
783815 ThisUpdate : time .Unix (int64 (cacheValue .thisUpdate ), 0 ).UTC (),
784816 NextUpdate : time .Unix (int64 (cacheValue .nextUpdate ), 0 ).UTC (),
0 commit comments