@@ -470,22 +470,100 @@ _get_issuer (X509 *cert, STACK_OF (X509) * chain)
470
470
issuer = candidate ;
471
471
}
472
472
}
473
- return issuer ;
473
+ RETURN ( issuer ) ;
474
474
}
475
475
476
476
#define ERR_STR (ERR_error_string (ERR_get_error (), NULL))
477
477
478
+ OCSP_RESPONSE *
479
+ _contact_ocsp_responder (OCSP_CERTID * id , X509 * peer )
480
+ {
481
+ STACK_OF (OPENSSL_STRING ) * url_stack = NULL ;
482
+ OPENSSL_STRING url = NULL , host = NULL , path = NULL , port = NULL ;
483
+ OCSP_REQUEST * req = NULL ;
484
+ OCSP_RESPONSE * resp = NULL ;
485
+ BIO * bio = NULL ;
486
+ int i , ssl ;
487
+
488
+ url_stack = X509_get1_ocsp (peer );
489
+ for (i = 0 ; i < sk_OPENSSL_STRING_num (url_stack ) && !resp ; i ++ ) {
490
+ url = sk_OPENSSL_STRING_value (url_stack , i );
491
+ MONGOC_DEBUG ("Contacting OCSP responder '%s'" , url );
492
+
493
+ /* splits the given url into its host, port and path components */
494
+ if (!OCSP_parse_url (url , & host , & port , & path , & ssl )) {
495
+ MONGOC_DEBUG ("Could not parse URL" );
496
+ GOTO (retry );
497
+ }
498
+
499
+ if (!(req = OCSP_REQUEST_new ())) {
500
+ MONGOC_DEBUG ("Could not create new OCSP request" );
501
+ GOTO (retry );
502
+ }
503
+
504
+ /* add the cert ID to the OCSP request object */
505
+ if (!id || !OCSP_request_add0_id (req , OCSP_CERTID_dup (id ))) {
506
+ MONGOC_DEBUG ("Could not add cert ID to the OCSP request object" );
507
+ GOTO (retry );
508
+ }
509
+
510
+ /* add nonce to OCSP request object */
511
+ if (!OCSP_request_add1_nonce (req , 0 /* use random nonce */ , -1 )) {
512
+ MONGOC_DEBUG ("Could not add nonce to OCSP request object" );
513
+ GOTO (retry );
514
+ }
515
+
516
+ if (!(bio = BIO_new_connect (host ))) {
517
+ MONGOC_DEBUG ("Could not create new BIO object" );
518
+ GOTO (retry );
519
+ }
520
+
521
+ BIO_set_conn_port (bio , port );
522
+ if (BIO_do_connect (bio ) <= 0 ) {
523
+ MONGOC_DEBUG ("Could not connect to url '%s'" , url );
524
+ GOTO (retry );
525
+ }
526
+
527
+ if (!(resp = OCSP_sendreq_bio (bio , path , req ))) {
528
+ MONGOC_DEBUG (
529
+ "Could not perform an OCSP request for url '%s'. Error: %s" ,
530
+ url ,
531
+ ERR_STR );
532
+ }
533
+ retry :
534
+ if (bio )
535
+ BIO_free_all (bio );
536
+ if (host )
537
+ OPENSSL_free (host );
538
+ if (port )
539
+ OPENSSL_free (port );
540
+ if (path )
541
+ OPENSSL_free (path );
542
+ if (req )
543
+ OCSP_REQUEST_free (req );
544
+ }
545
+
546
+ if (url_stack )
547
+ X509_email_free (url_stack );
548
+ RETURN (resp );
549
+ }
550
+
551
+ #define SOFT_FAIL (...) \
552
+ ((stapled_response) ? MONGOC_ERROR (__VA_ARGS__) \
553
+ : MONGOC_DEBUG (__VA_ARGS__))
554
+
478
555
int
479
556
_mongoc_ocsp_tlsext_status_cb (SSL * ssl , void * arg )
480
557
{
481
- const int ERROR = -1 , FAILURE = 0 , SUCCESS = 1 ;
558
+ enum { ERROR = -1 , REVOKED , SUCCESS } ret ;
559
+ bool stapled_response = true;
482
560
OCSP_RESPONSE * resp = NULL ;
483
561
OCSP_BASICRESP * basic = NULL ;
484
562
X509_STORE * store = NULL ;
485
563
X509 * peer = NULL , * issuer = NULL ;
486
564
STACK_OF (X509 ) * cert_chain = NULL ;
487
565
const unsigned char * r = NULL ;
488
- int cert_status , reason , len , status , ret ;
566
+ int cert_status , reason , len , status ;
489
567
OCSP_CERTID * id = NULL ;
490
568
mongoc_openssl_ocsp_opt_t * opts = (mongoc_openssl_ocsp_opt_t * ) arg ;
491
569
ASN1_GENERALIZEDTIME * produced_at = NULL , * this_update = NULL ,
@@ -496,60 +574,81 @@ _mongoc_ocsp_tlsext_status_cb (SSL *ssl, void *arg)
496
574
}
497
575
498
576
if (!(peer = SSL_get_peer_certificate (ssl ))) {
499
- MONGOC_ERROR ("No certificate was presented by the peer: %s" , ERR_STR );
577
+ MONGOC_ERROR ("No certificate was presented by the peer" );
578
+ ret = ERROR ;
579
+ GOTO (done );
580
+ }
581
+
582
+ /* Get a STACK_OF(X509) certs forming the cert chain of the peer, including
583
+ * the peer's cert */
584
+ if (!(cert_chain = SSL_get0_verified_chain (ssl ))) {
585
+ MONGOC_ERROR ("No certificate was presented by the peer" );
586
+ ret = REVOKED ;
587
+ GOTO (done );
588
+ }
589
+
590
+ if (!(issuer = _get_issuer (peer , cert_chain ))) {
591
+ MONGOC_ERROR ("Could not get issuer from peer cert" );
500
592
ret = ERROR ;
501
- goto done ;
593
+ GOTO (done );
594
+ }
595
+
596
+ if (!(id = OCSP_cert_to_id (NULL /* SHA1 */ , peer , issuer ))) {
597
+ MONGOC_ERROR ("Could not obtain a valid OCSP_CERTID for peer" );
598
+ ret = ERROR ;
599
+ GOTO (done );
502
600
}
503
601
504
602
/* Get the stapled OCSP response returned by the server */
505
603
len = SSL_get_tlsext_status_ocsp_resp (ssl , & r );
506
- if (!r ) {
604
+ stapled_response = !!r ;
605
+ if (stapled_response ) {
606
+ /* obtain an OCSP_RESPONSE object from the OCSP response */
607
+ if (!d2i_OCSP_RESPONSE (& resp , & r , len )) {
608
+ MONGOC_ERROR ("Failed to parse OCSP response" );
609
+ ret = ERROR ;
610
+ GOTO (done );
611
+ }
612
+ } else {
613
+ MONGOC_DEBUG ("Server does not contain a stapled response" );
507
614
bool must_staple = X509_get_ext_d2i (peer , NID_tlsfeature , 0 , 0 ) != NULL ;
508
615
if (must_staple ) {
509
- MONGOC_ERROR ("Server must contain a stapled response: %s" , ERR_STR );
510
- ret = FAILURE ;
511
- goto done ;
616
+ MONGOC_ERROR ("Server must contain a stapled response" );
617
+ ret = REVOKED ;
618
+ GOTO ( done ) ;
512
619
}
513
- ret = SUCCESS ; // TODO: contact OCSP responder
514
- goto done ;
515
- }
516
620
517
- /* obtain an OCSP_RESPONSE object from the OCSP response */
518
- if (! d2i_OCSP_RESPONSE ( & resp , & r , len )) {
519
- MONGOC_ERROR ( "Failed to parse OCSP response: %s" , ERR_STR ) ;
520
- ret = ERROR ;
521
- goto done ;
621
+ if (!( resp = _contact_ocsp_responder ( id , peer ))) {
622
+ MONGOC_DEBUG ( "Soft-fail: No OCSP responder could be reached" );
623
+ ret = SUCCESS ;
624
+ GOTO ( done ) ;
625
+ }
522
626
}
523
627
628
+ MONGOC_DEBUG ("Validating OCSP response" );
524
629
/* Validate the OCSP response status of the OCSP_RESPONSE object */
525
630
status = OCSP_response_status (resp );
526
631
if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL ) {
527
- MONGOC_ERROR ("OCSP response error %d %s" ,
528
- status ,
529
- OCSP_response_status_str (status ));
632
+ SOFT_FAIL ("OCSP response error %d %s" ,
633
+ status ,
634
+ OCSP_response_status_str (status ));
530
635
ret = ERROR ;
531
- goto done ;
636
+ GOTO ( done ) ;
532
637
}
533
638
639
+ MONGOC_DEBUG ("OCSP response status successful" );
640
+
534
641
/* Get the OCSP_BASICRESP structure contained in OCSP_RESPONSE object for the
535
642
* peer cert */
536
643
basic = OCSP_response_get1_basic (resp );
537
644
if (!basic ) {
538
- MONGOC_ERROR ("Could not find BasicOCSPResponse: %s" , ERR_STR );
645
+ SOFT_FAIL ("Could not find BasicOCSPResponse: %s" , ERR_STR );
539
646
ret = ERROR ;
540
- goto done ;
647
+ GOTO ( done ) ;
541
648
}
542
649
543
650
store = SSL_CTX_get_cert_store (SSL_get_SSL_CTX (ssl ));
544
651
545
- /* Get a STACK_OF(X509) certs forming the cert chain of the peer, including
546
- * the peer's cert */
547
- if (!(cert_chain = SSL_get0_verified_chain (ssl ))) {
548
- MONGOC_ERROR ("No certificate was presented by the peer: %s" , ERR_STR );
549
- ret = ERROR ;
550
- goto done ;
551
- }
552
-
553
652
/*
554
653
* checks that the basic response message is correctly signed and that the
555
654
* signer certificate can be validated.
@@ -560,22 +659,9 @@ _mongoc_ocsp_tlsext_status_cb (SSL *ssl, void *arg)
560
659
* validation path via the untrusted cert chain.
561
660
*/
562
661
if (SUCCESS != OCSP_basic_verify (basic , cert_chain , store , 0 )) {
563
- MONGOC_ERROR ("OCSP response failed verification: %s" , ERR_STR );
564
- ret = ERROR ;
565
- goto done ;
566
- }
567
-
568
- if (!(issuer = _get_issuer (peer , cert_chain ))) {
569
- MONGOC_ERROR ("Could not get issuer from peer cert" );
662
+ SOFT_FAIL ("OCSP response failed verification: %s" , ERR_STR );
570
663
ret = ERROR ;
571
- goto done ;
572
- }
573
-
574
- if (!(id = OCSP_cert_to_id (NULL /* SHA1 */ , peer , issuer ))) {
575
- MONGOC_ERROR ("Could not obtain a valid OCSP_CERTID for peer: %s" ,
576
- ERR_STR );
577
- ret = ERROR ;
578
- goto done ;
664
+ GOTO (done );
579
665
}
580
666
581
667
/* searches the basic response for an OCSP response for the given cert ID */
@@ -586,54 +672,57 @@ _mongoc_ocsp_tlsext_status_cb (SSL *ssl, void *arg)
586
672
& produced_at ,
587
673
& this_update ,
588
674
& next_update )) {
589
- MONGOC_ERROR ("No OCSP response found for the peer certificate: %s" ,
590
- ERR_STR );
675
+ SOFT_FAIL ("No OCSP response found for the peer certificate" );
591
676
ret = ERROR ;
592
- goto done ;
677
+ GOTO ( done ) ;
593
678
}
594
679
595
680
/* checks the validity of this_update and next_update values */
596
681
if (!OCSP_check_validity (this_update , next_update , 0L , -1L )) {
597
- MONGOC_ERROR ("OCSP response has expired: %s" , ERR_STR );
682
+ SOFT_FAIL ("OCSP response has expired: %s" , ERR_STR );
598
683
ret = ERROR ;
599
- goto done ;
684
+ GOTO ( done ) ;
600
685
}
601
686
602
687
switch (cert_status ) {
603
688
case V_OCSP_CERTSTATUS_GOOD :
689
+ MONGOC_DEBUG ("OCSP Certificate Status: Good" );
604
690
/* TODO: cache response */
605
691
break ;
606
692
607
693
case V_OCSP_CERTSTATUS_REVOKED :
608
- MONGOC_ERROR ("OCSP Certificate Status: Revoked. Reason %d" , reason );
609
- ret = FAILURE ;
610
- goto done ;
694
+ MONGOC_ERROR ("OCSP Certificate Status: Revoked. Reason: %s" ,
695
+ OCSP_crl_reason_str (reason ));
696
+ ret = REVOKED ;
697
+ GOTO (done );
611
698
612
- default : /* V_OCSP_CERTSTATUS_UNKNOWN */
699
+ default :
700
+ MONGOC_DEBUG ("OCSP Certificate Status: Unknown" );
613
701
break ;
614
702
}
615
703
616
704
/* Validate hostname matches cert */
617
705
if (!opts -> allow_invalid_hostname &&
618
706
X509_check_host (peer , opts -> host , 0 , 0 , NULL ) != SUCCESS &&
619
707
X509_check_ip_asc (peer , opts -> host , 0 ) != SUCCESS ) {
620
- ret = FAILURE ;
621
- goto done ;
708
+ ret = REVOKED ;
709
+ GOTO ( done ) ;
622
710
}
623
711
624
712
ret = SUCCESS ;
625
713
done :
714
+ if (ret == ERROR && !stapled_response ) {
715
+ ret = SUCCESS ;
716
+ }
626
717
if (basic )
627
718
OCSP_BASICRESP_free (basic );
628
719
if (resp )
629
720
OCSP_RESPONSE_free (resp );
630
721
if (id )
631
- OCSP_CERTID_free (id );
722
+ OCSP_CERTID_free (id );
632
723
if (peer )
633
- X509_free (peer );
634
- if (issuer )
635
- X509_free (issuer );
636
- return ret ;
724
+ X509_free (peer );
725
+ RETURN (ret );
637
726
}
638
727
#endif
639
728
0 commit comments