From 9b8fcff43575592ace3d391ee47184f98ed755df Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Fri, 22 Nov 2013 18:33:50 +0400 Subject: tls: reset NPN callbacks after SNI SNI callback selects a new SSL_CTX for the connection, which doesn't have NPN callbacks set up. --- src/node_crypto.cc | 34 ++++++++++++++++++------------- src/node_crypto.h | 2 ++ test/simple/test-tls-npn-server-client.js | 10 ++++++++- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/node_crypto.cc b/src/node_crypto.cc index e3ece0854..3e77918ab 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -1189,6 +1189,7 @@ int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) { p->sniContext_ = Persistent::New(ret); SecureContext *sc = ObjectWrap::Unwrap( Local::Cast(ret)); + p->InitNPN(sc, true); SSL_set_SSL_CTX(s, sc->ctx_); } else { return SSL_TLSEXT_ERR_NOACK; @@ -1223,20 +1224,7 @@ Handle Connection::New(const Arguments& args) { if (is_server) SSL_set_info_callback(p->ssl_, SSLInfoCallback); -#ifdef OPENSSL_NPN_NEGOTIATED - if (is_server) { - // Server should advertise NPN protocols - SSL_CTX_set_next_protos_advertised_cb(sc->ctx_, - AdvertiseNextProtoCallback_, - NULL); - } else { - // Client should select protocol from advertised - // If server supports NPN - SSL_CTX_set_next_proto_select_cb(sc->ctx_, - SelectNextProtoCallback_, - NULL); - } -#endif + p->InitNPN(sc, is_server); #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB if (is_server) { @@ -1980,6 +1968,24 @@ Handle Connection::Close(const Arguments& args) { return True(); } + +void Connection::InitNPN(SecureContext* sc, bool is_server) { +#ifdef OPENSSL_NPN_NEGOTIATED + if (is_server) { + // Server should advertise NPN protocols + SSL_CTX_set_next_protos_advertised_cb(sc->ctx_, + AdvertiseNextProtoCallback_, + NULL); + } else { + // Client should select protocol from advertised + // If server supports NPN + SSL_CTX_set_next_proto_select_cb(sc->ctx_, + SelectNextProtoCallback_, + NULL); + } +#endif +} + #ifdef OPENSSL_NPN_NEGOTIATED Handle Connection::GetNegotiatedProto(const Arguments& args) { HandleScope scope; diff --git a/src/node_crypto.h b/src/node_crypto.h index f1f6334b2..01a052855 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -190,6 +190,8 @@ class Connection : ObjectWrap { static v8::Handle Start(const v8::Arguments& args); static v8::Handle Close(const v8::Arguments& args); + static void InitNPN(SecureContext* sc, bool is_server); + #ifdef OPENSSL_NPN_NEGOTIATED // NPN static v8::Handle GetNegotiatedProto(const v8::Arguments& args); diff --git a/test/simple/test-tls-npn-server-client.js b/test/simple/test-tls-npn-server-client.js index d9e8f9180..ef89bd235 100644 --- a/test/simple/test-tls-npn-server-client.js +++ b/test/simple/test-tls-npn-server-client.js @@ -28,7 +28,8 @@ if (!process.features.tls_npn) { var common = require('../common'), assert = require('assert'), fs = require('fs'), - tls = require('tls'); + tls = require('tls'), + crypto = require('crypto'); function filenamePEM(n) { return require('path').join(common.fixturesDir, 'keys', n + '.pem'); @@ -42,6 +43,13 @@ var serverOptions = { key: loadPEM('agent2-key'), cert: loadPEM('agent2-cert'), crl: loadPEM('ca2-crl'), + SNICallback: function() { + return crypto.createCredentials({ + key: loadPEM('agent2-key'), + cert: loadPEM('agent2-cert'), + crl: loadPEM('ca2-crl'), + }).context; + }, NPNProtocols: ['a', 'b', 'c'] }; -- cgit v1.2.1