@@ -131,6 +131,8 @@ template int SSLWrap<TLSWrap>::SelectNextProtoCallback(
131
131
void * arg);
132
132
#endif
133
133
template int SSLWrap<TLSWrap>::TLSExtStatusCallback(SSL* s, void * arg);
134
+ template int SSLWrap<TLSWrap>::SSLCertCallback(SSL* s, void * arg);
135
+ template void SSLWrap<TLSWrap>::WaitForCertCb(CertCb cb, void * arg);
134
136
135
137
136
138
static void crypto_threadid_cb (CRYPTO_THREADID* tid) {
@@ -509,7 +511,8 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
509
511
}
510
512
511
513
while ((ca = PEM_read_bio_X509 (in, nullptr , CryptoPemCallback, nullptr ))) {
512
- r = SSL_CTX_add_extra_chain_cert (ctx, ca);
514
+ // NOTE: Increments reference count on `ca`
515
+ r = SSL_CTX_add1_chain_cert (ctx, ca);
513
516
514
517
if (!r) {
515
518
X509_free (ca);
@@ -978,6 +981,7 @@ void SSLWrap<Base>::AddMethods(Environment* env, Handle<FunctionTemplate> t) {
978
981
env->SetProtoMethod (t, " verifyError" , VerifyError);
979
982
env->SetProtoMethod (t, " getCurrentCipher" , GetCurrentCipher);
980
983
env->SetProtoMethod (t, " endParser" , EndParser);
984
+ env->SetProtoMethod (t, " certCbDone" , CertCbDone);
981
985
env->SetProtoMethod (t, " renegotiate" , Renegotiate);
982
986
env->SetProtoMethod (t, " shutdownSSL" , Shutdown);
983
987
env->SetProtoMethod (t, " getTLSTicket" , GetTLSTicket);
@@ -1860,6 +1864,122 @@ int SSLWrap<Base>::TLSExtStatusCallback(SSL* s, void* arg) {
1860
1864
#endif // NODE__HAVE_TLSEXT_STATUS_CB
1861
1865
1862
1866
1867
+ template <class Base >
1868
+ void SSLWrap<Base>::WaitForCertCb(CertCb cb, void * arg) {
1869
+ cert_cb_ = cb;
1870
+ cert_cb_arg_ = arg;
1871
+ }
1872
+
1873
+
1874
+ template <class Base >
1875
+ int SSLWrap<Base>::SSLCertCallback(SSL* s, void * arg) {
1876
+ Base* w = static_cast <Base*>(SSL_get_app_data (s));
1877
+
1878
+ if (!w->is_server ())
1879
+ return 1 ;
1880
+
1881
+ if (!w->is_waiting_cert_cb ())
1882
+ return 1 ;
1883
+
1884
+ if (w->cert_cb_running_ )
1885
+ return -1 ;
1886
+
1887
+ Environment* env = w->env ();
1888
+ HandleScope handle_scope (env->isolate ());
1889
+ Context::Scope context_scope (env->context ());
1890
+ w->cert_cb_running_ = true ;
1891
+
1892
+ Local<Object> info = Object::New (env->isolate ());
1893
+
1894
+ SSL_SESSION* sess = SSL_get_session (s);
1895
+ if (sess != nullptr ) {
1896
+ if (sess->tlsext_hostname == nullptr ) {
1897
+ info->Set (env->servername_string (), String::Empty (env->isolate ()));
1898
+ } else {
1899
+ Local<String> servername = OneByteString (env->isolate (),
1900
+ sess->tlsext_hostname ,
1901
+ strlen (sess->tlsext_hostname ));
1902
+ info->Set (env->servername_string (), servername);
1903
+ }
1904
+ info->Set (env->tls_ticket_string (),
1905
+ Boolean::New (env->isolate (), sess->tlsext_ticklen != 0 ));
1906
+ }
1907
+ bool ocsp = s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp;
1908
+ info->Set (env->ocsp_request_string (), Boolean::New (env->isolate (), ocsp));
1909
+
1910
+ Local<Value> argv[] = { info };
1911
+ w->MakeCallback (env->oncertcb_string (), ARRAY_SIZE (argv), argv);
1912
+
1913
+ if (!w->cert_cb_running_ )
1914
+ return 1 ;
1915
+
1916
+ // Performing async action, wait...
1917
+ return -1 ;
1918
+ }
1919
+
1920
+
1921
+ template <class Base >
1922
+ void SSLWrap<Base>::CertCbDone(const FunctionCallbackInfo<Value>& args) {
1923
+ Base* w = Unwrap<Base>(args.Holder ());
1924
+ Environment* env = w->env ();
1925
+
1926
+ CHECK (w->is_waiting_cert_cb () && w->cert_cb_running_ );
1927
+
1928
+ Local<Object> object = w->object ();
1929
+ Local<Value> ctx = object->Get (env->sni_context_string ());
1930
+ Local<FunctionTemplate> cons = env->secure_context_constructor_template ();
1931
+
1932
+ // Not an object, probably undefined or null
1933
+ if (!ctx->IsObject ())
1934
+ goto fire_cb;
1935
+
1936
+ if (cons->HasInstance (ctx)) {
1937
+ SecureContext* sc = Unwrap<SecureContext>(ctx.As <Object>());
1938
+ w->sni_context_ .Reset ();
1939
+ w->sni_context_ .Reset (env->isolate (), ctx);
1940
+
1941
+ int rv;
1942
+
1943
+ // NOTE: reference count is not increased by this API methods
1944
+ X509* x509 = SSL_CTX_get0_certificate (sc->ctx_ );
1945
+ EVP_PKEY* pkey = SSL_CTX_get0_privatekey (sc->ctx_ );
1946
+ STACK_OF (X509)* chain;
1947
+
1948
+ rv = SSL_CTX_get0_chain_certs (sc->ctx_ , &chain);
1949
+ if (rv)
1950
+ rv = SSL_use_certificate (w->ssl_ , x509);
1951
+ if (rv)
1952
+ rv = SSL_use_PrivateKey (w->ssl_ , pkey);
1953
+ if (rv && chain != nullptr )
1954
+ rv = SSL_set1_chain (w->ssl_ , chain);
1955
+ if (!rv) {
1956
+ unsigned long err = ERR_get_error ();
1957
+ if (!err)
1958
+ return env->ThrowError (" CertCbDone" );
1959
+ return ThrowCryptoError (env, err);
1960
+ }
1961
+ } else {
1962
+ // Failure: incorrect SNI context object
1963
+ Local<Value> err = Exception::TypeError (env->sni_context_err_string ());
1964
+ w->MakeCallback (env->onerror_string (), 1 , &err);
1965
+ return ;
1966
+ }
1967
+
1968
+ fire_cb:
1969
+ CertCb cb;
1970
+ void * arg;
1971
+
1972
+ cb = w->cert_cb_ ;
1973
+ arg = w->cert_cb_arg_ ;
1974
+
1975
+ w->cert_cb_running_ = false ;
1976
+ w->cert_cb_ = nullptr ;
1977
+ w->cert_cb_arg_ = nullptr ;
1978
+
1979
+ cb (arg);
1980
+ }
1981
+
1982
+
1863
1983
template <class Base >
1864
1984
void SSLWrap<Base>::SSLGetter(Local<String> property,
1865
1985
const PropertyCallbackInfo<Value>& info) {
@@ -1955,6 +2075,10 @@ int Connection::HandleSSLError(const char* func,
1955
2075
DEBUG_PRINT (" [%p] SSL: %s want read\n " , ssl_, func);
1956
2076
return 0 ;
1957
2077
2078
+ } else if (err == SSL_ERROR_WANT_X509_LOOKUP) {
2079
+ DEBUG_PRINT (" [%p] SSL: %s want x509 lookup\n " , ssl_, func);
2080
+ return 0 ;
2081
+
1958
2082
} else if (err == SSL_ERROR_ZERO_RETURN) {
1959
2083
HandleScope scope (ssl_env ()->isolate ());
1960
2084
@@ -2120,7 +2244,7 @@ int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) {
2120
2244
2121
2245
// Call the SNI callback and use its return value as context
2122
2246
if (!conn->sniObject_ .IsEmpty ()) {
2123
- conn->sniContext_ .Reset ();
2247
+ conn->sni_context_ .Reset ();
2124
2248
2125
2249
Local<Value> arg = PersistentToLocal (env->isolate (), conn->servername_ );
2126
2250
Local<Value> ret = conn->MakeCallback (env->onselect_string (), 1 , &arg);
@@ -2129,7 +2253,7 @@ int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) {
2129
2253
Local<FunctionTemplate> secure_context_constructor_template =
2130
2254
env->secure_context_constructor_template ();
2131
2255
if (secure_context_constructor_template->HasInstance (ret)) {
2132
- conn->sniContext_ .Reset (env->isolate (), ret);
2256
+ conn->sni_context_ .Reset (env->isolate (), ret);
2133
2257
SecureContext* sc = Unwrap<SecureContext>(ret.As <Object>());
2134
2258
InitNPN (sc);
2135
2259
SSL_set_SSL_CTX (s, sc->ctx_ );
@@ -2168,6 +2292,8 @@ void Connection::New(const FunctionCallbackInfo<Value>& args) {
2168
2292
2169
2293
InitNPN (sc);
2170
2294
2295
+ SSL_set_cert_cb (conn->ssl_ , SSLWrap<Connection>::SSLCertCallback, conn);
2296
+
2171
2297
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
2172
2298
if (is_server) {
2173
2299
SSL_CTX_set_tlsext_servername_callback (sc->ctx_ , SelectSNIContextCallback_);
0 commit comments