From 80f7f65464bf06482ad1eff3e2cc625d623b6b8d Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Tue, 1 Dec 2015 12:25:14 +0100 Subject: [PATCH] tls: support reading multiple cas from one input Before this commit you had to pass multiple CA certificates as an array of strings. For convenience you can now pass them as a single string. Fixes: https://github.com/nodejs/node/issues/4096 PR-URL: https://github.com/nodejs/node/pull/4099 Reviewed-By: Fedor Indutny Reviewed-By: James M Snell --- src/node_crypto.cc | 41 ++++++-------------- test/parallel/test-tls-two-cas-one-string.js | 35 +++++++++++++++++ 2 files changed, 47 insertions(+), 29 deletions(-) create mode 100644 test/parallel/test-tls-two-cas-one-string.js diff --git a/src/node_crypto.cc b/src/node_crypto.cc index e7df4b4ef86f32..63d767a1f4cd7c 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -453,26 +453,6 @@ static BIO* LoadBIO(Environment* env, Local v) { } -// Takes a string or buffer and loads it into an X509 -// Caller responsible for X509_free-ing the returned object. -static X509* LoadX509(Environment* env, Local v) { - HandleScope scope(env->isolate()); - - BIO *bio = LoadBIO(env, v); - if (!bio) - return nullptr; - - X509 * x509 = PEM_read_bio_X509(bio, nullptr, CryptoPemCallback, nullptr); - if (!x509) { - BIO_free_all(bio); - return nullptr; - } - - BIO_free_all(bio); - return x509; -} - - void SecureContext::SetKey(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -668,16 +648,19 @@ void SecureContext::AddCACert(const FunctionCallbackInfo& args) { newCAStore = true; } - X509* x509 = LoadX509(env, args[0]); - if (!x509) - return; - - X509_STORE_add_cert(sc->ca_store_, x509); - SSL_CTX_add_client_CA(sc->ctx_, x509); - - X509_free(x509); + unsigned cert_count = 0; + if (BIO* bio = LoadBIO(env, args[0])) { + while (X509* x509 = // NOLINT(whitespace/if-one-line) + PEM_read_bio_X509(bio, nullptr, CryptoPemCallback, nullptr)) { + X509_STORE_add_cert(sc->ca_store_, x509); + SSL_CTX_add_client_CA(sc->ctx_, x509); + X509_free(x509); + cert_count += 1; + } + BIO_free_all(bio); + } - if (newCAStore) { + if (cert_count > 0 && newCAStore) { SSL_CTX_set_cert_store(sc->ctx_, sc->ca_store_); } } diff --git a/test/parallel/test-tls-two-cas-one-string.js b/test/parallel/test-tls-two-cas-one-string.js new file mode 100644 index 00000000000000..c3b5d6961c11c4 --- /dev/null +++ b/test/parallel/test-tls-two-cas-one-string.js @@ -0,0 +1,35 @@ +'use strict'; + +const common = require('../common'); +const tls = require('tls'); +const fs = require('fs'); + +const ca1 = + fs.readFileSync(`${common.fixturesDir}/keys/ca1-cert.pem`, `utf8`); +const ca2 = + fs.readFileSync(`${common.fixturesDir}/keys/ca2-cert.pem`, `utf8`); +const cert = + fs.readFileSync(`${common.fixturesDir}/keys/agent3-cert.pem`, `utf8`); +const key = + fs.readFileSync(`${common.fixturesDir}/keys/agent3-key.pem`, `utf8`); + +function test(ca, next) { + const server = tls.createServer({ ca, cert, key }, function(conn) { + this.close(); + conn.end(); + }); + + server.addContext('agent3', { ca, cert, key }); + + const host = common.localhostIPv4; + const port = common.PORT; + server.listen(port, host, function() { + tls.connect({ servername: 'agent3', host, port, ca }); + }); + + server.once('close', next); +} + +const array = [ca1, ca2]; +const string = ca1 + '\n' + ca2; +test(array, () => test(string, () => {}));