Skip to content

Commit 7f60df5

Browse files
committed
tls: copy client CAs and cert store on CertCb
Copy client CA certs and cert store when asynchronously selecting `SecureContext` during `SNICallback`. We already copy private key, certificate, and certificate chain, but the client CA certs were missing. Fix: #2772
1 parent 53e64bb commit 7f60df5

File tree

4 files changed

+54
-11
lines changed

4 files changed

+54
-11
lines changed

‎src/node_crypto.cc‎

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ template class SSLWrap<TLSWrap>
137137
template void SSLWrap<TLSWrap>::AddMethods(Environment* env,
138138
Local<FunctionTemplate> t);
139139
template void SSLWrap<TLSWrap>::InitNPN(SecureContext* sc);
140+
template void SSLWrap<TLSWrap>::SetSNIContext(SecureContext* sc);
141+
template int SSLWrap<TLSWrap>::SetCACerts(SecureContext* sc);
140142
template SSL_SESSION* SSLWrap<TLSWrap>::GetSessionCallback(
141143
SSL* s,
142144
unsignedchar* key,
@@ -2264,6 +2266,8 @@ void SSLWrap<Base>::CertCbDone(const FunctionCallbackInfo<Value>& args){
22642266
rv = SSL_use_PrivateKey(w->ssl_, pkey);
22652267
if (rv && chain != nullptr)
22662268
rv = SSL_set1_chain(w->ssl_, chain);
2269+
if (rv)
2270+
rv = w->SetCACerts(sc);
22672271
if (!rv){
22682272
unsignedlong err = ERR_get_error();
22692273
if (!err)
@@ -2314,6 +2318,28 @@ void SSLWrap<Base>::DestroySSL(){
23142318
}
23152319

23162320

2321+
template <classBase>
2322+
void SSLWrap<Base>::SetSNIContext(SecureContext* sc){
2323+
InitNPN(sc);
2324+
SSL_set_SSL_CTX(ssl_, sc->ctx_);
2325+
2326+
SetCACerts(sc);
2327+
}
2328+
2329+
2330+
template <classBase>
2331+
int SSLWrap<Base>::SetCACerts(SecureContext* sc){
2332+
int err = SSL_set1_verify_cert_store(ssl_, SSL_CTX_get_cert_store(sc->ctx_));
2333+
if (err != 1)
2334+
return err;
2335+
2336+
STACK_OF(X509_NAME)* list = SSL_dup_CA_list(
2337+
SSL_CTX_get_client_CA_list(sc->ctx_));
2338+
SSL_set_client_CA_list(ssl_, list);
2339+
return1;
2340+
}
2341+
2342+
23172343
voidConnection::OnClientHelloParseEnd(void* arg){
23182344
Connection* conn = static_cast<Connection*>(arg);
23192345

@@ -2627,8 +2653,7 @@ int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg){
26272653
if (secure_context_constructor_template->HasInstance(ret)){
26282654
conn->sni_context_.Reset(env->isolate(), ret);
26292655
SecureContext* sc = Unwrap<SecureContext>(ret.As<Object>());
2630-
InitNPN(sc);
2631-
SSL_set_SSL_CTX(s, sc->ctx_);
2656+
conn->SetSNIContext(sc);
26322657
} else{
26332658
return SSL_TLSEXT_ERR_NOACK;
26342659
}

‎src/node_crypto.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ class SSLWrap{
271271

272272
voidDestroySSL();
273273
voidWaitForCertCb(CertCb cb, void* arg);
274+
voidSetSNIContext(SecureContext* sc);
275+
intSetCACerts(SecureContext* sc);
274276

275277
inline Environment* ssl_env() const{
276278
return env_;

‎src/tls_wrap.cc‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -857,8 +857,7 @@ int TLSWrap::SelectSNIContextCallback(SSL* s, int* ad, void* arg){
857857
p->sni_context_.Reset(env->isolate(), ctx);
858858

859859
SecureContext* sc = Unwrap<SecureContext>(ctx.As<Object>());
860-
InitNPN(sc);
861-
SSL_set_SSL_CTX(s, sc->ctx_);
860+
p->SetSNIContext(sc);
862861
return SSL_TLSEXT_ERR_OK;
863862
}
864863
#endif// SSL_CTRL_SET_TLSEXT_SERVERNAME_CB

‎test/parallel/test-tls-sni-option.js‎

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ function loadPEM(n){
2626
varserverOptions={
2727
key: loadPEM('agent2-key'),
2828
cert: loadPEM('agent2-cert'),
29+
requestCert: true,
30+
rejectUnauthorized: false,
2931
SNICallback: function(servername,callback){
3032
varcontext=SNIContexts[servername];
3133

@@ -46,7 +48,8 @@ var serverOptions ={
4648
varSNIContexts={
4749
'a.example.com': {
4850
key: loadPEM('agent1-key'),
49-
cert: loadPEM('agent1-cert')
51+
cert: loadPEM('agent1-cert'),
52+
ca: [loadPEM('ca2-cert')]
5053
},
5154
'b.example.com': {
5255
key: loadPEM('agent3-key'),
@@ -66,6 +69,13 @@ var clientsOptions = [{
6669
ca: [loadPEM('ca1-cert')],
6770
servername: 'a.example.com',
6871
rejectUnauthorized: false
72+
},{
73+
port: serverPort,
74+
key: loadPEM('agent4-key'),
75+
cert: loadPEM('agent4-cert'),
76+
ca: [loadPEM('ca1-cert')],
77+
servername: 'a.example.com',
78+
rejectUnauthorized: false
6979
},{
7080
port: serverPort,
7181
key: loadPEM('agent2-key'),
@@ -97,7 +107,7 @@ var serverResults = [],
97107
clientError;
98108

99109
varserver=tls.createServer(serverOptions,function(c){
100-
serverResults.push(c.servername);
110+
serverResults.push({sni: c.servername,authorized: c.authorized});
101111
});
102112

103113
server.on('clientError',function(err){
@@ -144,9 +154,16 @@ function startTest(){
144154
}
145155

146156
process.on('exit',function(){
147-
assert.deepEqual(serverResults,['a.example.com','b.example.com',
148-
'c.wrong.com',null]);
149-
assert.deepEqual(clientResults,[true,true,false,false]);
150-
assert.deepEqual(clientErrors,[null,null,null,'socket hang up']);
151-
assert.deepEqual(serverErrors,[null,null,null,'Invalid SNI context']);
157+
assert.deepEqual(serverResults,[
158+
{sni: 'a.example.com',authorized: false},
159+
{sni: 'a.example.com',authorized: true},
160+
{sni: 'b.example.com',authorized: false},
161+
{sni: 'c.wrong.com',authorized: false},
162+
null
163+
]);
164+
assert.deepEqual(clientResults,[true,true,true,false,false]);
165+
assert.deepEqual(clientErrors,[null,null,null,null,'socket hang up']);
166+
assert.deepEqual(serverErrors,[
167+
null,null,null,null,'Invalid SNI context'
168+
]);
152169
});

0 commit comments

Comments
(0)