@@ -132,6 +132,8 @@ template int SSLWrap<TLSWrap>::SelectNextProtoCallback(
132
132
#endif
133
133
template int SSLWrap<TLSWrap>::TLSExtStatusCallback(SSL* s, void * arg);
134
134
template void SSLWrap<TLSWrap>::DestroySSL();
135
+ template int SSLWrap<TLSWrap>::SSLCertCallback(SSL* s, void * arg);
136
+ template void SSLWrap<TLSWrap>::WaitForCertCb(CertCb cb, void * arg);
135
137
136
138
137
139
static void crypto_threadid_cb (CRYPTO_THREADID* tid) {
@@ -511,7 +513,8 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
511
513
}
512
514
513
515
while ((ca = PEM_read_bio_X509 (in, nullptr , CryptoPemCallback, nullptr ))) {
514
- r = SSL_CTX_add_extra_chain_cert (ctx, ca);
516
+ // NOTE: Increments reference count on `ca`
517
+ r = SSL_CTX_add1_chain_cert (ctx, ca);
515
518
516
519
if (!r) {
517
520
X509_free (ca);
@@ -987,6 +990,7 @@ void SSLWrap<Base>::AddMethods(Environment* env, Handle<FunctionTemplate> t) {
987
990
env->SetProtoMethod (t, " verifyError" , VerifyError);
988
991
env->SetProtoMethod (t, " getCurrentCipher" , GetCurrentCipher);
989
992
env->SetProtoMethod (t, " endParser" , EndParser);
993
+ env->SetProtoMethod (t, " certCbDone" , CertCbDone);
990
994
env->SetProtoMethod (t, " renegotiate" , Renegotiate);
991
995
env->SetProtoMethod (t, " shutdownSSL" , Shutdown);
992
996
env->SetProtoMethod (t, " getTLSTicket" , GetTLSTicket);
@@ -1869,6 +1873,122 @@ int SSLWrap<Base>::TLSExtStatusCallback(SSL* s, void* arg) {
1869
1873
#endif // NODE__HAVE_TLSEXT_STATUS_CB
1870
1874
1871
1875
1876
+ template <class Base >
1877
+ void SSLWrap<Base>::WaitForCertCb(CertCb cb, void * arg) {
1878
+ cert_cb_ = cb;
1879
+ cert_cb_arg_ = arg;
1880
+ }
1881
+
1882
+
1883
+ template <class Base >
1884
+ int SSLWrap<Base>::SSLCertCallback(SSL* s, void * arg) {
1885
+ Base* w = static_cast <Base*>(SSL_get_app_data (s));
1886
+
1887
+ if (!w->is_server ())
1888
+ return 1 ;
1889
+
1890
+ if (!w->is_waiting_cert_cb ())
1891
+ return 1 ;
1892
+
1893
+ if (w->cert_cb_running_ )
1894
+ return -1 ;
1895
+
1896
+ Environment* env = w->env ();
1897
+ HandleScope handle_scope (env->isolate ());
1898
+ Context::Scope context_scope (env->context ());
1899
+ w->cert_cb_running_ = true ;
1900
+
1901
+ Local<Object> info = Object::New (env->isolate ());
1902
+
1903
+ SSL_SESSION* sess = SSL_get_session (s);
1904
+ if (sess != nullptr ) {
1905
+ if (sess->tlsext_hostname == nullptr ) {
1906
+ info->Set (env->servername_string (), String::Empty (env->isolate ()));
1907
+ } else {
1908
+ Local<String> servername = OneByteString (env->isolate (),
1909
+ sess->tlsext_hostname ,
1910
+ strlen (sess->tlsext_hostname ));
1911
+ info->Set (env->servername_string (), servername);
1912
+ }
1913
+ info->Set (env->tls_ticket_string (),
1914
+ Boolean::New (env->isolate (), sess->tlsext_ticklen != 0 ));
1915
+ }
1916
+ bool ocsp = s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp;
1917
+ info->Set (env->ocsp_request_string (), Boolean::New (env->isolate (), ocsp));
1918
+
1919
+ Local<Value> argv[] = { info };
1920
+ w->MakeCallback (env->oncertcb_string (), ARRAY_SIZE (argv), argv);
1921
+
1922
+ if (!w->cert_cb_running_ )
1923
+ return 1 ;
1924
+
1925
+ // Performing async action, wait...
1926
+ return -1 ;
1927
+ }
1928
+
1929
+
1930
+ template <class Base >
1931
+ void SSLWrap<Base>::CertCbDone(const FunctionCallbackInfo<Value>& args) {
1932
+ Base* w = Unwrap<Base>(args.Holder ());
1933
+ Environment* env = w->env ();
1934
+
1935
+ CHECK (w->is_waiting_cert_cb () && w->cert_cb_running_ );
1936
+
1937
+ Local<Object> object = w->object ();
1938
+ Local<Value> ctx = object->Get (env->sni_context_string ());
1939
+ Local<FunctionTemplate> cons = env->secure_context_constructor_template ();
1940
+
1941
+ // Not an object, probably undefined or null
1942
+ if (!ctx->IsObject ())
1943
+ goto fire_cb;
1944
+
1945
+ if (cons->HasInstance (ctx)) {
1946
+ SecureContext* sc = Unwrap<SecureContext>(ctx.As <Object>());
1947
+ w->sni_context_ .Reset ();
1948
+ w->sni_context_ .Reset (env->isolate (), ctx);
1949
+
1950
+ int rv;
1951
+
1952
+ // NOTE: reference count is not increased by this API methods
1953
+ X509* x509 = SSL_CTX_get0_certificate (sc->ctx_ );
1954
+ EVP_PKEY* pkey = SSL_CTX_get0_privatekey (sc->ctx_ );
1955
+ STACK_OF (X509)* chain;
1956
+
1957
+ rv = SSL_CTX_get0_chain_certs (sc->ctx_ , &chain);
1958
+ if (rv)
1959
+ rv = SSL_use_certificate (w->ssl_ , x509);
1960
+ if (rv)
1961
+ rv = SSL_use_PrivateKey (w->ssl_ , pkey);
1962
+ if (rv && chain != nullptr )
1963
+ rv = SSL_set1_chain (w->ssl_ , chain);
1964
+ if (!rv) {
1965
+ unsigned long err = ERR_get_error ();
1966
+ if (!err)
1967
+ return env->ThrowError (" CertCbDone" );
1968
+ return ThrowCryptoError (env, err);
1969
+ }
1970
+ } else {
1971
+ // Failure: incorrect SNI context object
1972
+ Local<Value> err = Exception::TypeError (env->sni_context_err_string ());
1973
+ w->MakeCallback (env->onerror_string (), 1 , &err);
1974
+ return ;
1975
+ }
1976
+
1977
+ fire_cb:
1978
+ CertCb cb;
1979
+ void * arg;
1980
+
1981
+ cb = w->cert_cb_ ;
1982
+ arg = w->cert_cb_arg_ ;
1983
+
1984
+ w->cert_cb_running_ = false ;
1985
+ w->cert_cb_ = nullptr ;
1986
+ w->cert_cb_arg_ = nullptr ;
1987
+
1988
+ cb (arg);
1989
+ }
1990
+
1991
+
1872
1992
template <class Base >
1873
1993
void SSLWrap<Base>::SSLGetter(Local<String> property,
1874
1994
const PropertyCallbackInfo<Value>& info) {
@@ -1975,6 +2095,10 @@ int Connection::HandleSSLError(const char* func,
1975
2095
DEBUG_PRINT (" [%p] SSL: %s want read\n " , ssl_, func);
1976
2096
return 0 ;
1977
2097
2098
+ } else if (err == SSL_ERROR_WANT_X509_LOOKUP) {
2099
+ DEBUG_PRINT (" [%p] SSL: %s want x509 lookup\n " , ssl_, func);
2100
+ return 0 ;
2101
+
1978
2102
} else if (err == SSL_ERROR_ZERO_RETURN) {
1979
2103
HandleScope scope (ssl_env ()->isolate ());
1980
2104
@@ -2140,7 +2264,7 @@ int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) {
2140
2264
2141
2265
// Call the SNI callback and use its return value as context
2142
2266
if (!conn->sniObject_ .IsEmpty ()) {
2143
- conn->sniContext_ .Reset ();
2267
+ conn->sni_context_ .Reset ();
2144
2268
2145
2269
Local<Value> arg = PersistentToLocal (env->isolate (), conn->servername_ );
2146
2270
Local<Value> ret = conn->MakeCallback (env->onselect_string (), 1 , &arg);
@@ -2149,7 +2273,7 @@ int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) {
2149
2273
Local<FunctionTemplate> secure_context_constructor_template =
2150
2274
env->secure_context_constructor_template ();
2151
2275
if (secure_context_constructor_template->HasInstance (ret)) {
2152
- conn->sniContext_ .Reset (env->isolate (), ret);
2276
+ conn->sni_context_ .Reset (env->isolate (), ret);
2153
2277
SecureContext* sc = Unwrap<SecureContext>(ret.As <Object>());
2154
2278
InitNPN (sc);
2155
2279
SSL_set_SSL_CTX (s, sc->ctx_ );
@@ -2188,6 +2312,8 @@ void Connection::New(const FunctionCallbackInfo<Value>& args) {
2188
2312
2189
2313
InitNPN (sc);
2190
2314
2315
+ SSL_set_cert_cb (conn->ssl_ , SSLWrap<Connection>::SSLCertCallback, conn);
2316
+
2191
2317
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
2192
2318
if (is_server) {
2193
2319
SSL_CTX_set_tlsext_servername_callback (sc->ctx_ , SelectSNIContextCallback_);
0 commit comments