diff -Naur node-v5.7.1.orig/lib/_tls_wrap.js node-v5.7.1/lib/_tls_wrap.js --- node-v5.7.1.orig/lib/_tls_wrap.js 2016-03-02 14:20:54.000000000 -0800 +++ node-v5.7.1/lib/_tls_wrap.js 2016-03-09 12:41:27.567542510 -0800 @@ -165,26 +165,31 @@ if (err) return self.destroy(err); - self._handle.endParser(); - }); -} - - -function oncertcb(info) { - var self = this; - var servername = info.servername; - - loadSNI(self, servername, function(err, ctx) { - if (err) - return self.destroy(err); - requestOCSP(self, info, ctx, function(err) { + // Servername came from SSL session + // NOTE: TLS Session ticket doesn't include servername information + // + // Another note, From RFC3546: + // + // If, on the other hand, the older + // session is resumed, then the server MUST ignore extensions appearing + // in the client hello, and send a server hello containing no + // extensions; in this case the extension functionality negotiated + // during the original session initiation is applied to the resumed + // session. + // + // Therefore we should account session loading when dealing with servername + var servername = session && session.servername || hello.servername; + loadSNI(self, servername, function(err, ctx) { if (err) return self.destroy(err); - - if (!self._handle) - return self.destroy(new Error('Socket is closed')); - - self._handle.certCbDone(); + requestOCSP(self, hello, ctx, function(err) { + if (err) + return self.destroy(err); + + if (!self._handle) + return self.destroy(new Error('Socket is closed')); + self._handle.endParser(); + }); }); }); } @@ -407,18 +412,15 @@ ssl.onhandshakestart = () => onhandshakestart.call(this); ssl.onhandshakedone = () => onhandshakedone.call(this); ssl.onclienthello = (hello) => onclienthello.call(this, hello); - ssl.oncertcb = (info) => oncertcb.call(this, info); ssl.onnewsession = (key, session) => onnewsession.call(this, key, session); ssl.lastHandshakeTime = 0; ssl.handshakes = 0; - if (this.server) { - if (this.server.listenerCount('resumeSession') > 0 || - this.server.listenerCount('newSession') > 0) { - ssl.enableSessionCallbacks(); - } - if (this.server.listenerCount('OCSPRequest') > 0) - ssl.enableCertCb(); + if (this.server && + (this.server.listenerCount('resumeSession') > 0 || + this.server.listenerCount('newSession') > 0 || + this.server.listenerCount('OCSPRequest') > 0)) { + ssl.enableSessionCallbacks(); } } else { ssl.onhandshakestart = function() {}; @@ -460,7 +462,7 @@ options.server._contexts.length)) { assert(typeof options.SNICallback === 'function'); this._SNICallback = options.SNICallback; - ssl.enableCertCb(); + ssl.enableHelloParser(); } if (process.features.tls_npn && options.NPNProtocols) @@ -654,13 +656,6 @@ } }; -TLSSocket.prototype.getEphemeralKeyInfo = function() { - if (this._handle) - return this._handle.getEphemeralKeyInfo(); - - return null; -}; - TLSSocket.prototype.getProtocol = function() { if (this._handle) return this._handle.getProtocol(); @@ -1047,17 +1042,6 @@ socket._start(); socket.on('secure', function() { - // Check the size of DHE parameter above minimum requirement - // specified in options. - var ekeyinfo = socket.getEphemeralKeyInfo(); - if (ekeyinfo.type === 'DH' && ekeyinfo.size < options.minDHSize) { - var err = new Error('DH parameter size ' + ekeyinfo.size + - ' is less than ' + options.minDHSize); - socket.emit('error', err); - socket.destroy(); - return; - } - var verifyError = socket._handle.verifyError(); // Verify that server's identity matches it's certificate's names diff -Naur node-v5.7.1.orig/src/env.h node-v5.7.1/src/env.h --- node-v5.7.1.orig/src/env.h 2016-03-02 14:20:54.000000000 -0800 +++ node-v5.7.1/src/env.h 2016-03-09 12:38:59.042899553 -0800 @@ -66,7 +66,6 @@ V(cached_data_rejected_string, "cachedDataRejected") \ V(callback_string, "callback") \ V(change_string, "change") \ - V(oncertcb_string, "oncertcb") \ V(onclose_string, "_onclose") \ V(code_string, "code") \ V(compare_string, "compare") \ diff -Naur node-v5.7.1.orig/src/node_crypto.cc node-v5.7.1/src/node_crypto.cc --- node-v5.7.1.orig/src/node_crypto.cc 2016-03-02 14:20:54.000000000 -0800 +++ node-v5.7.1/src/node_crypto.cc 2016-03-09 12:44:13.609732921 -0800 @@ -164,8 +164,6 @@ #endif template void SSLWrap::DestroySSL(); -template int SSLWrap::SSLCertCallback(SSL* s, void* arg); -template void SSLWrap::WaitForCertCb(CertCb cb, void* arg); #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation template int SSLWrap::SelectALPNCallback( @@ -518,8 +516,7 @@ for (int i = 0; i < sk_X509_num(extra_certs); i++) { X509* ca = sk_X509_value(extra_certs, i); - // NOTE: Increments reference count on `ca` - r = SSL_CTX_add1_chain_cert(ctx, ca); + r = SSL_CTX_add_extra_chain_cert(ctx, ca); if (!r) { ret = 0; @@ -1045,7 +1042,7 @@ void SecureContext::SetFreeListLength(const FunctionCallbackInfo& args) { SecureContext* wrap = Unwrap(args.Holder()); - wrap->ctx_->freelist_max_len = args[0]->Int32Value(); + // wrap->ctx_->freelist_max_len = args[0]->Int32Value(); } @@ -1182,14 +1179,12 @@ env->SetProtoMethod(t, "verifyError", VerifyError); env->SetProtoMethod(t, "getCurrentCipher", GetCurrentCipher); env->SetProtoMethod(t, "endParser", EndParser); - env->SetProtoMethod(t, "certCbDone", CertCbDone); env->SetProtoMethod(t, "renegotiate", Renegotiate); env->SetProtoMethod(t, "shutdownSSL", Shutdown); env->SetProtoMethod(t, "getTLSTicket", GetTLSTicket); env->SetProtoMethod(t, "newSessionDone", NewSessionDone); env->SetProtoMethod(t, "setOCSPResponse", SetOCSPResponse); env->SetProtoMethod(t, "requestOCSP", RequestOCSP); - env->SetProtoMethod(t, "getEphemeralKeyInfo", GetEphemeralKeyInfo); env->SetProtoMethod(t, "getProtocol", GetProtocol); #ifdef SSL_set_max_send_fragment @@ -1805,50 +1800,6 @@ } -template -void SSLWrap::GetEphemeralKeyInfo( - const v8::FunctionCallbackInfo& args) { - Base* w = Unwrap(args.Holder()); - Environment* env = Environment::GetCurrent(args); - - CHECK_NE(w->ssl_, nullptr); - - // tmp key is available on only client - if (w->is_server()) - return args.GetReturnValue().SetNull(); - - Local info = Object::New(env->isolate()); - - EVP_PKEY* key; - - if (SSL_get_server_tmp_key(w->ssl_, &key)) { - switch (EVP_PKEY_id(key)) { - case EVP_PKEY_DH: - info->Set(env->type_string(), - FIXED_ONE_BYTE_STRING(env->isolate(), "DH")); - info->Set(env->size_string(), - Integer::New(env->isolate(), EVP_PKEY_bits(key))); - break; - case EVP_PKEY_EC: - { - EC_KEY* ec = EVP_PKEY_get1_EC_KEY(key); - int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); - EC_KEY_free(ec); - info->Set(env->type_string(), - FIXED_ONE_BYTE_STRING(env->isolate(), "ECDH")); - info->Set(env->name_string(), - OneByteString(args.GetIsolate(), OBJ_nid2sn(nid))); - info->Set(env->size_string(), - Integer::New(env->isolate(), EVP_PKEY_bits(key))); - } - } - EVP_PKEY_free(key); - } - - return args.GetReturnValue().Set(info); -} - - #ifdef SSL_set_max_send_fragment template void SSLWrap::SetMaxSendFragment( @@ -2234,129 +2185,6 @@ template -void SSLWrap::WaitForCertCb(CertCb cb, void* arg) { - cert_cb_ = cb; - cert_cb_arg_ = arg; -} - - -template -int SSLWrap::SSLCertCallback(SSL* s, void* arg) { - Base* w = static_cast(SSL_get_app_data(s)); - - if (!w->is_server()) - return 1; - - if (!w->is_waiting_cert_cb()) - return 1; - - if (w->cert_cb_running_) - return -1; - - Environment* env = w->env(); - HandleScope handle_scope(env->isolate()); - Context::Scope context_scope(env->context()); - w->cert_cb_running_ = true; - - Local info = Object::New(env->isolate()); - - SSL_SESSION* sess = SSL_get_session(s); - if (sess != nullptr) { - if (sess->tlsext_hostname == nullptr) { - info->Set(env->servername_string(), String::Empty(env->isolate())); - } else { - Local servername = OneByteString(env->isolate(), - sess->tlsext_hostname, - strlen(sess->tlsext_hostname)); - info->Set(env->servername_string(), servername); - } - info->Set(env->tls_ticket_string(), - Boolean::New(env->isolate(), sess->tlsext_ticklen != 0)); - } - - bool ocsp = false; -#ifdef NODE__HAVE_TLSEXT_STATUS_CB - ocsp = s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp; -#endif - - info->Set(env->ocsp_request_string(), Boolean::New(env->isolate(), ocsp)); - - Local argv[] = { info }; - w->MakeCallback(env->oncertcb_string(), ARRAY_SIZE(argv), argv); - - if (!w->cert_cb_running_) - return 1; - - // Performing async action, wait... - return -1; -} - - -template -void SSLWrap::CertCbDone(const FunctionCallbackInfo& args) { - Base* w = Unwrap(args.Holder()); - Environment* env = w->env(); - - CHECK(w->is_waiting_cert_cb() && w->cert_cb_running_); - - Local object = w->object(); - Local ctx = object->Get(env->sni_context_string()); - Local cons = env->secure_context_constructor_template(); - - // Not an object, probably undefined or null - if (!ctx->IsObject()) - goto fire_cb; - - if (cons->HasInstance(ctx)) { - SecureContext* sc = Unwrap(ctx.As()); - w->sni_context_.Reset(); - w->sni_context_.Reset(env->isolate(), ctx); - - int rv; - - // NOTE: reference count is not increased by this API methods - X509* x509 = SSL_CTX_get0_certificate(sc->ctx_); - EVP_PKEY* pkey = SSL_CTX_get0_privatekey(sc->ctx_); - STACK_OF(X509)* chain; - - rv = SSL_CTX_get0_chain_certs(sc->ctx_, &chain); - if (rv) - rv = SSL_use_certificate(w->ssl_, x509); - if (rv) - rv = SSL_use_PrivateKey(w->ssl_, pkey); - if (rv && chain != nullptr) - rv = SSL_set1_chain(w->ssl_, chain); - if (rv) - rv = w->SetCACerts(sc); - if (!rv) { - unsigned long err = ERR_get_error(); - if (!err) - return env->ThrowError("CertCbDone"); - return ThrowCryptoError(env, err); - } - } else { - // Failure: incorrect SNI context object - Local err = Exception::TypeError(env->sni_context_err_string()); - w->MakeCallback(env->onerror_string(), 1, &err); - return; - } - - fire_cb: - CertCb cb; - void* arg; - - cb = w->cert_cb_; - arg = w->cert_cb_arg_; - - w->cert_cb_running_ = false; - w->cert_cb_ = nullptr; - w->cert_cb_arg_ = nullptr; - - cb(arg); -} - - -template void SSLWrap::SSLGetter(Local property, const PropertyCallbackInfo& info) { SSL* ssl = Unwrap(info.This())->ssl_; @@ -2387,10 +2215,6 @@ template int SSLWrap::SetCACerts(SecureContext* sc) { - int err = SSL_set1_verify_cert_store(ssl_, SSL_CTX_get_cert_store(sc->ctx_)); - if (err != 1) - return err; - STACK_OF(X509_NAME)* list = SSL_dup_CA_list( SSL_CTX_get_client_CA_list(sc->ctx_)); @@ -2484,10 +2308,6 @@ DEBUG_PRINT("[%p] SSL: %s want read\n", ssl_, func); return 0; - } else if (err == SSL_ERROR_WANT_X509_LOOKUP) { - DEBUG_PRINT("[%p] SSL: %s want x509 lookup\n", ssl_, func); - return 0; - } else if (err == SSL_ERROR_ZERO_RETURN) { HandleScope scope(ssl_env()->isolate()); @@ -2668,7 +2488,7 @@ SSL* ssl = static_cast( X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); - if (SSL_is_server(ssl)) + if (ssl->server) return 1; // Client needs to check if the server cert is listed in the @@ -2695,7 +2515,7 @@ // Call the SNI callback and use its return value as context if (!conn->sniObject_.IsEmpty()) { - conn->sni_context_.Reset(); + conn->sniContext_.Reset(); Local sni_obj = PersistentToLocal(env->isolate(), conn->sniObject_); @@ -2711,7 +2531,7 @@ Local secure_context_constructor_template = env->secure_context_constructor_template(); if (secure_context_constructor_template->HasInstance(ret)) { - conn->sni_context_.Reset(env->isolate(), ret); + conn->sniContext_.Reset(env->isolate(), ret); SecureContext* sc = Unwrap(ret.As()); conn->SetSNIContext(sc); } else { @@ -2749,8 +2569,6 @@ InitNPN(sc); - SSL_set_cert_cb(conn->ssl_, SSLWrap::SSLCertCallback, conn); - #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB if (is_server) { SSL_CTX_set_tlsext_servername_callback(sc->ctx_, SelectSNIContextCallback_); diff -Naur node-v5.7.1.orig/src/node_crypto.h node-v5.7.1/src/node_crypto.h --- node-v5.7.1.orig/src/node_crypto.h 2016-03-02 14:20:54.000000000 -0800 +++ node-v5.7.1/src/node_crypto.h 2016-03-09 12:45:11.683121390 -0800 @@ -177,10 +177,7 @@ kind_(kind), next_sess_(nullptr), session_callbacks_(false), - new_session_wait_(false), - cert_cb_(nullptr), - cert_cb_arg_(nullptr), - cert_cb_running_(false) { + new_session_wait_(false) { ssl_ = SSL_new(sc->ctx_); env_->isolate()->AdjustAmountOfExternalAllocatedMemory(kExternalSize); CHECK_NE(ssl_, nullptr); @@ -193,10 +190,6 @@ next_sess_ = nullptr; } -#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB - sni_context_.Reset(); -#endif - #ifdef NODE__HAVE_TLSEXT_STATUS_CB ocsp_response_.Reset(); #endif // NODE__HAVE_TLSEXT_STATUS_CB @@ -207,11 +200,8 @@ inline bool is_server() const { return kind_ == kServer; } inline bool is_client() const { return kind_ == kClient; } inline bool is_waiting_new_session() const { return new_session_wait_; } - inline bool is_waiting_cert_cb() const { return cert_cb_ != nullptr; } protected: - typedef void (*CertCb)(void* arg); - // Size allocated by OpenSSL: one for SSL structure, one for SSL3_STATE and // some for buffers. // NOTE: Actually it is much more than this @@ -239,15 +229,12 @@ static void VerifyError(const v8::FunctionCallbackInfo& args); static void GetCurrentCipher(const v8::FunctionCallbackInfo& args); static void EndParser(const v8::FunctionCallbackInfo& args); - static void CertCbDone(const v8::FunctionCallbackInfo& args); static void Renegotiate(const v8::FunctionCallbackInfo& args); static void Shutdown(const v8::FunctionCallbackInfo& args); static void GetTLSTicket(const v8::FunctionCallbackInfo& args); static void NewSessionDone(const v8::FunctionCallbackInfo& args); static void SetOCSPResponse(const v8::FunctionCallbackInfo& args); static void RequestOCSP(const v8::FunctionCallbackInfo& args); - static void GetEphemeralKeyInfo( - const v8::FunctionCallbackInfo& args); static void GetProtocol(const v8::FunctionCallbackInfo& args); #ifdef SSL_set_max_send_fragment @@ -281,12 +268,10 @@ unsigned int inlen, void* arg); static int TLSExtStatusCallback(SSL* s, void* arg); - static int SSLCertCallback(SSL* s, void* arg); static void SSLGetter(v8::Local property, const v8::PropertyCallbackInfo& info); void DestroySSL(); - void WaitForCertCb(CertCb cb, void* arg); void SetSNIContext(SecureContext* sc); int SetCACerts(SecureContext* sc); @@ -301,21 +286,12 @@ bool session_callbacks_; bool new_session_wait_; - // SSL_set_cert_cb - CertCb cert_cb_; - void* cert_cb_arg_; - bool cert_cb_running_; - ClientHelloParser hello_parser_; #ifdef NODE__HAVE_TLSEXT_STATUS_CB v8::Persistent ocsp_response_; #endif // NODE__HAVE_TLSEXT_STATUS_CB -#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB - v8::Persistent sni_context_; -#endif - friend class SecureContext; }; @@ -327,6 +303,7 @@ ~Connection() override { #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB sniObject_.Reset(); + sniContext_.Reset(); servername_.Reset(); #endif } @@ -341,6 +318,7 @@ #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB v8::Persistent sniObject_; + v8::Persistent sniContext_; v8::Persistent servername_; #endif diff -Naur node-v5.7.1.orig/src/tls_wrap.cc node-v5.7.1/src/tls_wrap.cc --- node-v5.7.1.orig/src/tls_wrap.cc 2016-03-02 14:20:54.000000000 -0800 +++ node-v5.7.1/src/tls_wrap.cc 2016-03-09 12:38:59.047899589 -0800 @@ -141,8 +141,6 @@ InitNPN(sc_); - SSL_set_cert_cb(ssl_, SSLWrap::SSLCertCallback, this); - if (is_server()) { SSL_set_accept_state(ssl_); } else if (is_client()) { @@ -353,7 +351,6 @@ case SSL_ERROR_NONE: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: - case SSL_ERROR_WANT_X509_LOOKUP: break; case SSL_ERROR_ZERO_RETURN: return scope.Escape(env()->zero_return_string()); @@ -769,6 +766,11 @@ "EnableSessionCallbacks after destroySSL"); } wrap->enable_session_callbacks(); + EnableHelloParser(args); +} + +void TLSWrap::EnableHelloParser(const FunctionCallbackInfo& args) { + TLSWrap* wrap = Unwrap(args.Holder()); NodeBIO::FromBIO(wrap->enc_in_)->set_initial(kMaxHelloLength); wrap->hello_parser_.Start(SSLWrap::OnClientHello, OnClientHelloParseEnd, @@ -793,12 +795,6 @@ } -void TLSWrap::EnableCertCb(const FunctionCallbackInfo& args) { - TLSWrap* wrap = Unwrap(args.Holder()); - wrap->WaitForCertCb(OnClientHelloParseEnd, wrap); -} - - void TLSWrap::OnClientHelloParseEnd(void* arg) { TLSWrap* c = static_cast(arg); c->Cycle(); @@ -896,8 +892,8 @@ env->SetProtoMethod(t, "start", Start); env->SetProtoMethod(t, "setVerifyMode", SetVerifyMode); env->SetProtoMethod(t, "enableSessionCallbacks", EnableSessionCallbacks); + env->SetProtoMethod(t, "enableHelloParser", EnableHelloParser); env->SetProtoMethod(t, "destroySSL", DestroySSL); - env->SetProtoMethod(t, "enableCertCb", EnableCertCb); StreamBase::AddMethods(env, t, StreamBase::kFlagHasWritev); SSLWrap::AddMethods(env, t); diff -Naur node-v5.7.1.orig/src/tls_wrap.h node-v5.7.1/src/tls_wrap.h --- node-v5.7.1.orig/src/tls_wrap.h 2016-03-02 14:20:54.000000000 -0800 +++ node-v5.7.1/src/tls_wrap.h 2016-03-09 12:38:59.047899589 -0800 @@ -132,7 +132,7 @@ static void SetVerifyMode(const v8::FunctionCallbackInfo& args); static void EnableSessionCallbacks( const v8::FunctionCallbackInfo& args); - static void EnableCertCb( + static void EnableHelloParser( const v8::FunctionCallbackInfo& args); static void DestroySSL(const v8::FunctionCallbackInfo& args); @@ -161,6 +161,10 @@ // If true - delivered EOF to the js-land, either after `close_notify`, or // after the `UV_EOF` on socket. bool eof_; + +#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB + v8::Persistent sni_context_; +#endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB }; } // namespace node diff -Naur node-v5.7.1.orig/test/parallel/test-tls-client-getephemeralkeyinfo.js node-v5.7.1/test/parallel/test-tls-client-getephemeralkeyinfo.js --- node-v5.7.1.orig/test/parallel/test-tls-client-getephemeralkeyinfo.js 2016-03-02 14:20:55.000000000 -0800 +++ node-v5.7.1/test/parallel/test-tls-client-getephemeralkeyinfo.js 1969-12-31 16:00:00.000000000 -0800 @@ -1,98 +0,0 @@ -'use strict'; -var common = require('../common'); -var assert = require('assert'); - -if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); - process.exit(); -} -var tls = require('tls'); - -var fs = require('fs'); -var key = fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'); -var cert = fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem'); - -var ntests = 0; -var nsuccess = 0; - -function loadDHParam(n) { - var path = common.fixturesDir; - if (n !== 'error') path += '/keys'; - return fs.readFileSync(path + '/dh' + n + '.pem'); -} - -var cipherlist = { - 'NOT_PFS': 'AES128-SHA256', - 'DH': 'DHE-RSA-AES128-GCM-SHA256', - 'ECDH': 'ECDHE-RSA-AES128-GCM-SHA256' -}; - -function test(size, type, name, next) { - var cipher = type ? cipherlist[type] : cipherlist['NOT_PFS']; - - if (name) tls.DEFAULT_ECDH_CURVE = name; - - var options = { - key: key, - cert: cert, - ciphers: cipher - }; - - if (type === 'DH') options.dhparam = loadDHParam(size); - - var server = tls.createServer(options, function(conn) { - assert.strictEqual(conn.getEphemeralKeyInfo(), null); - conn.end(); - }); - - server.on('close', function(err) { - assert(!err); - if (next) next(); - }); - - server.listen(common.PORT, '127.0.0.1', function() { - var client = tls.connect({ - port: common.PORT, - rejectUnauthorized: false - }, function() { - var ekeyinfo = client.getEphemeralKeyInfo(); - assert.strictEqual(ekeyinfo.type, type); - assert.strictEqual(ekeyinfo.size, size); - assert.strictEqual(ekeyinfo.name, name); - nsuccess++; - server.close(); - }); - }); -} - -function testNOT_PFS() { - test(undefined, undefined, undefined, testDHE1024); - ntests++; -} - -function testDHE1024() { - test(1024, 'DH', undefined, testDHE2048); - ntests++; -} - -function testDHE2048() { - test(2048, 'DH', undefined, testECDHE256); - ntests++; -} - -function testECDHE256() { - test(256, 'ECDH', tls.DEFAULT_ECDH_CURVE, testECDHE512); - ntests++; -} - -function testECDHE512() { - test(521, 'ECDH', 'secp521r1', null); - ntests++; -} - -testNOT_PFS(); - -process.on('exit', function() { - assert.equal(ntests, nsuccess); - assert.equal(ntests, 5); -}); diff -Naur node-v5.7.1.orig/test/parallel/test-tls-cnnic-whitelist.js node-v5.7.1/test/parallel/test-tls-cnnic-whitelist.js --- node-v5.7.1.orig/test/parallel/test-tls-cnnic-whitelist.js 2016-03-02 14:20:55.000000000 -0800 +++ node-v5.7.1/test/parallel/test-tls-cnnic-whitelist.js 2016-03-09 12:38:59.048899596 -0800 @@ -53,7 +53,9 @@ port: common.PORT, rejectUnauthorized: true }, - errorCode: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY' + // LibreSSL returns CERT_UNTRUSTED in this case, OpenSSL UNABLE_TO_GET_ISSUER_CERT_LOCALLY. + errorCode: 'CERT_UNTRUSTED' + // errorCode: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY' } ]; diff -Naur node-v5.7.1.orig/test/parallel/test-tls-sni-server-client.js node-v5.7.1/test/parallel/test-tls-sni-server-client.js --- node-v5.7.1.orig/test/parallel/test-tls-sni-server-client.js 2016-03-02 14:20:55.000000000 -0800 +++ node-v5.7.1/test/parallel/test-tls-sni-server-client.js 2016-03-09 12:39:14.677009247 -0800 @@ -36,11 +36,6 @@ 'asterisk.test.com': { key: loadPEM('agent3-key'), cert: loadPEM('agent3-cert') - }, - 'chain.example.com': { - key: loadPEM('agent6-key'), - // NOTE: Contains ca3 chain cert - cert: loadPEM('agent6-cert') } }; @@ -48,29 +43,32 @@ var clientsOptions = [{ port: serverPort, + key: loadPEM('agent1-key'), + cert: loadPEM('agent1-cert'), ca: [loadPEM('ca1-cert')], servername: 'a.example.com', rejectUnauthorized: false }, { port: serverPort, + key: loadPEM('agent2-key'), + cert: loadPEM('agent2-cert'), ca: [loadPEM('ca2-cert')], servername: 'b.test.com', rejectUnauthorized: false }, { port: serverPort, + key: loadPEM('agent2-key'), + cert: loadPEM('agent2-cert'), ca: [loadPEM('ca2-cert')], servername: 'a.b.test.com', rejectUnauthorized: false }, { port: serverPort, + key: loadPEM('agent3-key'), + cert: loadPEM('agent3-cert'), ca: [loadPEM('ca1-cert')], servername: 'c.wrong.com', rejectUnauthorized: false -}, { - port: serverPort, - ca: [loadPEM('ca1-cert')], - servername: 'chain.example.com', - rejectUnauthorized: false }]; const serverResults = []; @@ -82,7 +80,6 @@ server.addContext('a.example.com', SNIContexts['a.example.com']); server.addContext('*.test.com', SNIContexts['asterisk.test.com']); -server.addContext('chain.example.com', SNIContexts['chain.example.com']); server.listen(serverPort, startTest); @@ -109,9 +106,7 @@ } process.on('exit', function() { - assert.deepEqual(serverResults, [ - 'a.example.com', 'b.test.com', 'a.b.test.com', 'c.wrong.com', - 'chain.example.com' - ]); - assert.deepEqual(clientResults, [true, true, false, false, true]); + assert.deepEqual(serverResults, ['a.example.com', 'b.test.com', + 'a.b.test.com', 'c.wrong.com']); + assert.deepEqual(clientResults, [true, true, false, false]); });