@@ -360,14 +360,14 @@ func checkOCSPCacheServer(
360
360
headers := make (map [string ]string )
361
361
res , err := newRetryHTTP (ctx , client , req , ocspServerHost , headers , totalTimeout , defaultTimeProvider ).execute ()
362
362
if err != nil {
363
- logger .Errorf ("failed to get OCSP cache from OCSP Cache Server. %v\n " , err )
363
+ logger .Errorf ("failed to get OCSP cache from OCSP Cache Server. %v" , err )
364
364
return nil , & ocspStatus {
365
365
code : ocspFailedSubmit ,
366
366
err : err ,
367
367
}
368
368
}
369
369
defer res .Body .Close ()
370
- logger .Debugf ("StatusCode from OCSP Cache Server: %v\n " , res .StatusCode )
370
+ logger .Debugf ("StatusCode from OCSP Cache Server: %v" , res .StatusCode )
371
371
if res .StatusCode != http .StatusOK {
372
372
return nil , & ocspStatus {
373
373
code : ocspFailedResponse ,
@@ -381,7 +381,7 @@ func checkOCSPCacheServer(
381
381
if err := dec .Decode (& respd ); err == io .EOF {
382
382
break
383
383
} else if err != nil {
384
- logger .Errorf ("failed to decode OCSP cache. %v\n " , err )
384
+ logger .Errorf ("failed to decode OCSP cache. %v" , err )
385
385
return nil , & ocspStatus {
386
386
code : ocspFailedExtractResponse ,
387
387
err : err ,
@@ -428,15 +428,66 @@ func retryOCSP(
428
428
err : fmt .Errorf ("HTTP code is not OK. %v: %v" , res .StatusCode , res .Status ),
429
429
}
430
430
}
431
- logger .Debug ("reading contents" )
432
431
ocspResBytes , err = io .ReadAll (res .Body )
433
432
if err != nil {
434
433
return ocspRes , ocspResBytes , & ocspStatus {
435
434
code : ocspFailedExtractResponse ,
436
435
err : err ,
437
436
}
438
437
}
439
- logger .Debug ("parsing OCSP response" )
438
+ ocspRes , err = ocsp .ParseResponse (ocspResBytes , issuer )
439
+ if err != nil {
440
+ logger .Warnf ("error when parsing ocsp response: %v" , err )
441
+ logger .Warnf ("performing GET fallback request to OCSP" )
442
+ return fallbackRetryOCSPToGETRequest (ctx , client , req , ocspHost , headers , issuer , totalTimeout )
443
+ }
444
+
445
+ logger .Debugf ("OCSP Status from server: %v" , printStatus (ocspRes ))
446
+ return ocspRes , ocspResBytes , & ocspStatus {
447
+ code : ocspSuccess ,
448
+ }
449
+ }
450
+
451
+ // fallbackRetryOCSPToGETRequest is the third level of retry method. Some OCSP responders do not support POST requests
452
+ // and will return with a "malformed" request error. In that case we also try to perform a GET request
453
+ func fallbackRetryOCSPToGETRequest (
454
+ ctx context.Context ,
455
+ client clientInterface ,
456
+ req requestFunc ,
457
+ ocspHost * url.URL ,
458
+ headers map [string ]string ,
459
+ issuer * x509.Certificate ,
460
+ totalTimeout time.Duration ) (
461
+ ocspRes * ocsp.Response ,
462
+ ocspResBytes []byte ,
463
+ ocspS * ocspStatus ) {
464
+ multiplier := 1
465
+ if atomic .LoadUint32 ((* uint32 )(& ocspFailOpen )) == (uint32 )(OCSPFailOpenFalse ) {
466
+ multiplier = 3 // up to 3 times for Fail Close mode
467
+ }
468
+ res , err := newRetryHTTP (ctx , client , req , ocspHost , headers ,
469
+ totalTimeout * time .Duration (multiplier ), defaultTimeProvider ).execute ()
470
+ if err != nil {
471
+ return ocspRes , ocspResBytes , & ocspStatus {
472
+ code : ocspFailedSubmit ,
473
+ err : err ,
474
+ }
475
+ }
476
+ defer res .Body .Close ()
477
+ logger .Debugf ("GET fallback StatusCode from OCSP Server: %v" , res .StatusCode )
478
+ if res .StatusCode != http .StatusOK {
479
+ return ocspRes , ocspResBytes , & ocspStatus {
480
+ code : ocspFailedResponse ,
481
+ err : fmt .Errorf ("HTTP code is not OK. %v: %v" , res .StatusCode , res .Status ),
482
+ }
483
+ }
484
+ ocspResBytes , err = io .ReadAll (res .Body )
485
+ if err != nil {
486
+ return ocspRes , ocspResBytes , & ocspStatus {
487
+ code : ocspFailedExtractResponse ,
488
+ err : err ,
489
+ }
490
+ }
440
491
ocspRes , err = ocsp .ParseResponse (ocspResBytes , issuer )
441
492
if err != nil {
442
493
return ocspRes , ocspResBytes , & ocspStatus {
@@ -445,14 +496,39 @@ func retryOCSP(
445
496
}
446
497
}
447
498
499
+ logger .Debugf ("GET fallback OCSP Status from server: %v" , printStatus (ocspRes ))
448
500
return ocspRes , ocspResBytes , & ocspStatus {
449
501
code : ocspSuccess ,
450
502
}
451
503
}
452
504
505
+ func printStatus (response * ocsp.Response ) string {
506
+ switch response .Status {
507
+ case ocsp .Good :
508
+ return "Good"
509
+ case ocsp .Revoked :
510
+ return "Revoked"
511
+ case ocsp .Unknown :
512
+ return "Unknown"
513
+ default :
514
+ return fmt .Sprintf ("%d" , response .Status )
515
+ }
516
+ }
517
+
518
+ func fullOCSPURL (url * url.URL ) string {
519
+ fullURL := url .Hostname ()
520
+ if url .Path != "" {
521
+ if ! strings .HasPrefix (url .Path , "/" ) {
522
+ fullURL += "/"
523
+ }
524
+ fullURL += url .Path
525
+ }
526
+ return fullURL
527
+ }
528
+
453
529
// getRevocationStatus checks the certificate revocation status for subject using issuer certificate.
454
530
func getRevocationStatus (ctx context.Context , subject , issuer * x509.Certificate ) * ocspStatus {
455
- logger .Infof ("Subject: %v, Issuer: %v\n " , subject .Subject , issuer .Subject )
531
+ logger .Infof ("Subject: %v, Issuer: %v" , subject .Subject , issuer .Subject )
456
532
457
533
status , ocspReq , encodedCertID := validateWithCache (subject , issuer )
458
534
if isValidOCSPStatus (status .code ) {
@@ -461,8 +537,8 @@ func getRevocationStatus(ctx context.Context, subject, issuer *x509.Certificate)
461
537
if ocspReq == nil || encodedCertID == nil {
462
538
return status
463
539
}
464
- logger .Infof ("cache missed\n " )
465
- logger .Infof ("OCSP Server: %v\n " , subject .OCSPServer )
540
+ logger .Infof ("cache missed" )
541
+ logger .Infof ("OCSP Server: %v" , subject .OCSPServer )
466
542
if len (subject .OCSPServer ) == 0 || isTestNoOCSPURL () {
467
543
return & ocspStatus {
468
544
code : ocspNoServer ,
@@ -484,9 +560,14 @@ func getRevocationStatus(ctx context.Context, subject, issuer *x509.Certificate)
484
560
hostnameStr := os .Getenv (ocspTestResponderURLEnv )
485
561
var hostname string
486
562
if retryURL := os .Getenv (ocspRetryURLEnv ); retryURL != "" {
487
- hostname = fmt .Sprintf (retryURL , u .Hostname (), base64 .StdEncoding .EncodeToString (ocspReq ))
563
+ hostname = fmt .Sprintf (retryURL , fullOCSPURL (u ), base64 .StdEncoding .EncodeToString (ocspReq ))
564
+ u0 , err := url .Parse (hostname )
565
+ if err == nil {
566
+ hostname = u0 .Hostname ()
567
+ u = u0
568
+ }
488
569
} else {
489
- hostname = u . Hostname ( )
570
+ hostname = fullOCSPURL ( u )
490
571
}
491
572
if hostnameStr != "" {
492
573
u0 , err := url .Parse (hostnameStr )
@@ -495,6 +576,10 @@ func getRevocationStatus(ctx context.Context, subject, issuer *x509.Certificate)
495
576
u = u0
496
577
}
497
578
}
579
+
580
+ logger .Debugf ("Fetching OCSP response from server: %v" , u )
581
+ logger .Debugf ("Host in headers: %v" , hostname )
582
+
498
583
headers := make (map [string ]string )
499
584
headers [httpHeaderContentType ] = "application/ocsp-request"
500
585
headers [httpHeaderAccept ] = "application/ocsp-response"
0 commit comments