@@ -519,46 +519,35 @@ int SSL_CTX_get_issuer(SSL_CTX* ctx, X509* cert, X509** issuer) {
519519}
520520
521521
522- // Read a file that contains our certificate in "PEM" format,
523- // possibly followed by a sequence of CA certificates that should be
524- // sent to the peer in the Certificate message.
525- //
526- // Taken from OpenSSL - editted for style.
527522int SSL_CTX_use_certificate_chain (SSL_CTX* ctx,
528- BIO* in,
523+ X509* x,
524+ STACK_OF (X509)* extra_certs,
529525 X509** cert,
530526 X509** issuer) {
531- int ret = 0 ;
532- X509* x = nullptr ;
527+ CHECK_EQ (*issuer, nullptr ) ;
528+ CHECK_EQ (*cert, nullptr ) ;
533529
534- x = PEM_read_bio_X509_AUX (in, nullptr , CryptoPemCallback, nullptr );
535-
536- if (x == nullptr ) {
537- SSLerr (SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
538- goto end;
539- }
540-
541- ret = SSL_CTX_use_certificate (ctx, x);
530+ int ret = SSL_CTX_use_certificate (ctx, x);
542531
543532 if (ret) {
544533 // If we could set up our certificate, now proceed to
545534 // the CA certificates.
546- X509 *ca;
547535 int r;
548- unsigned long err;
549536
550537 if (ctx->extra_certs != nullptr ) {
551538 sk_X509_pop_free (ctx->extra_certs , X509_free);
552539 ctx->extra_certs = nullptr ;
553540 }
554541
555- while ((ca = PEM_read_bio_X509 (in, nullptr , CryptoPemCallback, nullptr ))) {
542+ for (int i = 0 ; i < sk_X509_num (extra_certs); i++) {
543+ X509* ca = sk_X509_value (extra_certs, i);
544+
556545 // NOTE: Increments reference count on `ca`
557546 r = SSL_CTX_add1_chain_cert (ctx, ca);
558547
559548 if (!r) {
560- X509_free (ca);
561549 ret = 0 ;
550+ *issuer = nullptr ;
562551 goto end;
563552 }
564553 // Note that we must not free r if it was successfully
@@ -569,17 +558,8 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
569558 // Find issuer
570559 if (*issuer != nullptr || X509_check_issued (ca, x) != X509_V_OK)
571560 continue ;
572- *issuer = ca;
573- }
574561
575- // When the while loop ends, it's usually just EOF.
576- err = ERR_peek_last_error ();
577- if (ERR_GET_LIB (err) == ERR_LIB_PEM &&
578- ERR_GET_REASON (err) == PEM_R_NO_START_LINE) {
579- ERR_clear_error ();
580- } else {
581- // some real error
582- ret = 0 ;
562+ *issuer = ca;
583563 }
584564 }
585565
@@ -592,13 +572,88 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
592572 // no need to free `store`
593573 } else {
594574 // Increment issuer reference count
595- CRYPTO_add (&(*issuer)->references , 1 , CRYPTO_LOCK_X509);
575+ *issuer = X509_dup (*issuer);
576+ if (*issuer == nullptr ) {
577+ ret = 0 ;
578+ goto end;
579+ }
596580 }
597581 }
598582
599583 end:
584+ if (ret && x != nullptr ) {
585+ *cert = X509_dup (x);
586+ if (*cert == nullptr )
587+ ret = 0 ;
588+ }
589+ return ret;
590+ }
591+
592+
593+ // Read a file that contains our certificate in "PEM" format,
594+ // possibly followed by a sequence of CA certificates that should be
595+ // sent to the peer in the Certificate message.
596+ //
597+ // Taken from OpenSSL - edited for style.
598+ int SSL_CTX_use_certificate_chain (SSL_CTX* ctx,
599+ BIO* in,
600+ X509** cert,
601+ X509** issuer) {
602+ X509* x = nullptr ;
603+
604+ // Just to ensure that `ERR_peek_last_error` below will return only errors
605+ // that we are interested in
606+ ERR_clear_error ();
607+
608+ x = PEM_read_bio_X509_AUX (in, nullptr , CryptoPemCallback, nullptr );
609+
610+ if (x == nullptr ) {
611+ SSLerr (SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
612+ return 0 ;
613+ }
614+
615+ X509* extra = nullptr ;
616+ int ret = 0 ;
617+ unsigned long err = 0 ;
618+
619+ // Read extra certs
620+ STACK_OF (X509)* extra_certs = sk_X509_new_null ();
621+ if (extra_certs == nullptr ) {
622+ SSLerr (SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_MALLOC_FAILURE);
623+ goto done;
624+ }
625+
626+ while ((extra = PEM_read_bio_X509 (in, nullptr , CryptoPemCallback, nullptr ))) {
627+ if (sk_X509_push (extra_certs, extra))
628+ continue ;
629+
630+ // Failure, free all certs
631+ goto done;
632+ }
633+ extra = nullptr ;
634+
635+ // When the while loop ends, it's usually just EOF.
636+ err = ERR_peek_last_error ();
637+ if (ERR_GET_LIB (err) == ERR_LIB_PEM &&
638+ ERR_GET_REASON (err) == PEM_R_NO_START_LINE) {
639+ ERR_clear_error ();
640+ } else {
641+ // some real error
642+ goto done;
643+ }
644+
645+ ret = SSL_CTX_use_certificate_chain (ctx, x, extra_certs, cert, issuer);
646+ if (!ret)
647+ goto done;
648+
649+ done:
650+ if (extra_certs != nullptr )
651+ sk_X509_pop_free (extra_certs, X509_free);
652+ if (extra != nullptr )
653+ X509_free (extra);
600654 if (x != nullptr )
601- *cert = x;
655+ X509_free (x);
656+
602657 return ret;
603658}
604659
@@ -616,6 +671,16 @@ void SecureContext::SetCert(const FunctionCallbackInfo<Value>& args) {
616671 if (!bio)
617672 return ;
618673
674+ // Free previous certs
675+ if (sc->issuer_ != nullptr ) {
676+ X509_free (sc->issuer_ );
677+ sc->issuer_ = nullptr ;
678+ }
679+ if (sc->cert_ != nullptr ) {
680+ X509_free (sc->cert_ );
681+ sc->cert_ = nullptr ;
682+ }
683+
619684 int rv = SSL_CTX_use_certificate_chain (sc->ctx_ ,
620685 bio,
621686 &sc->cert_ ,
@@ -887,7 +952,7 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
887952 PKCS12* p12 = nullptr ;
888953 EVP_PKEY* pkey = nullptr ;
889954 X509* cert = nullptr ;
890- STACK_OF (X509)* extraCerts = nullptr ;
955+ STACK_OF (X509)* extra_certs = nullptr ;
891956 char * pass = nullptr ;
892957 bool ret = false ;
893958
@@ -912,28 +977,33 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
912977 pass[passlen] = ' \0 ' ;
913978 }
914979
980+ // Free previous certs
981+ if (sc->issuer_ != nullptr ) {
982+ X509_free (sc->issuer_ );
983+ sc->issuer_ = nullptr ;
984+ }
985+ if (sc->cert_ != nullptr ) {
986+ X509_free (sc->cert_ );
987+ sc->cert_ = nullptr ;
988+ }
989+
915990 if (d2i_PKCS12_bio (in, &p12) &&
916- PKCS12_parse (p12, pass, &pkey, &cert, &extraCerts) &&
917- SSL_CTX_use_certificate (sc->ctx_ , cert) &&
991+ PKCS12_parse (p12, pass, &pkey, &cert, &extra_certs) &&
992+ SSL_CTX_use_certificate_chain (sc->ctx_ ,
993+ cert,
994+ extra_certs,
995+ &sc->cert_ ,
996+ &sc->issuer_ ) &&
918997 SSL_CTX_use_PrivateKey (sc->ctx_ , pkey)) {
919- // set extra certs
920- while (X509* x509 = sk_X509_pop (extraCerts)) {
921- if (!sc->ca_store_ ) {
922- sc->ca_store_ = X509_STORE_new ();
923- SSL_CTX_set_cert_store (sc->ctx_ , sc->ca_store_ );
924- }
925-
926- X509_STORE_add_cert (sc->ca_store_ , x509);
927- SSL_CTX_add_client_CA (sc->ctx_ , x509);
928- X509_free (x509);
929- }
998+ ret = true ;
999+ }
9301000
1001+ if (pkey != nullptr )
9311002 EVP_PKEY_free (pkey);
1003+ if (cert != nullptr )
9321004 X509_free (cert);
933- sk_X509_free (extraCerts);
934-
935- ret = true ;
936- }
1005+ if (extra_certs != nullptr )
1006+ sk_X509_free (extra_certs);
9371007
9381008 PKCS12_free (p12);
9391009 BIO_free_all (in);
0 commit comments