From fe8e07ddd98534b067a2a4dc71838a3732cad1eb Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Mon, 7 Jan 2019 14:13:17 -0800 Subject: [PATCH] test: assert on client and server side seperately This gets better coverage of the codes, and is more explicit. It also works around ordering differences in the errors produced by openssl. The approach was tested with 1.1.0 and 1.1.1, as well as TLSv1.2 vs TLSv1.3. OpenSSL 1.1.0 is relevant when node is built against a shared openssl. Backport-PR-URL: https://github.com/nodejs/node/pull/26270 PR-URL: https://github.com/nodejs/node/pull/25381 Reviewed-By: Daniel Bevenius Reviewed-By: Shigeki Ohtsu --- test/parallel/test-tls-min-max-version.js | 137 ++++++++++++++++------ 1 file changed, 100 insertions(+), 37 deletions(-) diff --git a/test/parallel/test-tls-min-max-version.js b/test/parallel/test-tls-min-max-version.js index 94468e47e23f75..521bc5ce9f193e 100644 --- a/test/parallel/test-tls-min-max-version.js +++ b/test/parallel/test-tls-min-max-version.js @@ -8,11 +8,13 @@ const { assert, connect, keys, tls } = require(fixtures.path('tls-connect')); const DEFAULT_MIN_VERSION = tls.DEFAULT_MIN_VERSION; +const DEFAULT_MAX_VERSION = tls.DEFAULT_MAX_VERSION; // For v11.x, the default is fixed and cannot be changed via CLI. assert.strictEqual(DEFAULT_MIN_VERSION, 'TLSv1'); -function test(cmin, cmax, cprot, smin, smax, sprot, expect) { +function test(cmin, cmax, cprot, smin, smax, sprot, proto, cerr, serr) { + assert(proto || cerr || serr, 'test missing any expectations'); connect({ client: { checkServerIdentity: (servername, cert) => { }, @@ -29,23 +31,52 @@ function test(cmin, cmax, cprot, smin, smax, sprot, expect) { secureProtocol: sprot, }, }, common.mustCall((err, pair, cleanup) => { - if (expect && !expect.match(/^TLS/)) { - assert(err.message.match(expect)); + function u(_) { return _ === undefined ? 'U' : _; } + console.log('test:', u(cmin), u(cmax), u(cprot), u(smin), u(smax), u(sprot), + 'expect', u(proto), u(cerr), u(serr)); + if (!proto) { + console.log('client', pair.client.err ? pair.client.err.code : undefined); + console.log('server', pair.server.err ? pair.server.err.code : undefined); + // 11.x doesn't have https://github.com/nodejs/node/pull/24729 + if (cerr === 'ERR_TLS_INVALID_PROTOCOL_METHOD' && + pair.client.err && + pair.client.err.message.includes('methods disabled')) + pair.client.err.code = 'ERR_TLS_INVALID_PROTOCOL_METHOD'; + if (serr === 'ERR_TLS_INVALID_PROTOCOL_METHOD' && + pair.server.err && + pair.server.err.message.includes('methods disabled')) + pair.server.err.code = 'ERR_TLS_INVALID_PROTOCOL_METHOD'; + if (cerr === 'ERR_TLS_INVALID_PROTOCOL_METHOD' && + pair.client.err && + pair.client.err.message.includes('Unknown method')) + pair.client.err.code = 'ERR_TLS_INVALID_PROTOCOL_METHOD'; + if (serr === 'ERR_TLS_INVALID_PROTOCOL_METHOD' && + pair.server.err && + pair.server.err.message.includes('Unknown method')) + pair.server.err.code = 'ERR_TLS_INVALID_PROTOCOL_METHOD'; + if (cerr) { + assert(pair.client.err); + // Accept these codes as aliases, the one reported depends on the + // OpenSSL version. + if (cerr === 'ERR_SSL_UNSUPPORTED_PROTOCOL' && + pair.client.err.code === 'ERR_SSL_VERSION_TOO_LOW') + cerr = 'ERR_SSL_VERSION_TOO_LOW'; + assert.strictEqual(pair.client.err.code, cerr); + } + if (serr) { + assert(pair.server.err); + assert.strictEqual(pair.server.err.code, serr); + } return cleanup(); } - if (expect) { - assert.ifError(pair.server.err); - assert.ifError(pair.client.err); - assert(pair.server.conn); - assert(pair.client.conn); - assert.strictEqual(pair.client.conn.getProtocol(), expect); - assert.strictEqual(pair.server.conn.getProtocol(), expect); - return cleanup(); - } - - assert(pair.server.err); - assert(pair.client.err); + assert.ifError(err); + assert.ifError(pair.server.err); + assert.ifError(pair.client.err); + assert(pair.server.conn); + assert(pair.client.conn); + assert.strictEqual(pair.client.conn.getProtocol(), proto); + assert.strictEqual(pair.server.conn.getProtocol(), proto); return cleanup(); })); } @@ -56,18 +87,28 @@ const U = undefined; test(U, U, U, U, U, U, 'TLSv1.2'); // Insecure or invalid protocols cannot be enabled. -test(U, U, U, U, U, 'SSLv2_method', 'SSLv2 methods disabled'); -test(U, U, U, U, U, 'SSLv3_method', 'SSLv3 methods disabled'); -test(U, U, 'SSLv2_method', U, U, U, 'SSLv2 methods disabled'); -test(U, U, 'SSLv3_method', U, U, U, 'SSLv3 methods disabled'); -test(U, U, 'hokey-pokey', U, U, U, 'Unknown method'); -test(U, U, U, U, U, 'hokey-pokey', 'Unknown method'); +test(U, U, U, U, U, 'SSLv2_method', + U, U, 'ERR_TLS_INVALID_PROTOCOL_METHOD'); +test(U, U, U, U, U, 'SSLv3_method', + U, U, 'ERR_TLS_INVALID_PROTOCOL_METHOD'); +test(U, U, 'SSLv2_method', U, U, U, + U, 'ERR_TLS_INVALID_PROTOCOL_METHOD'); +test(U, U, 'SSLv3_method', U, U, U, + U, 'ERR_TLS_INVALID_PROTOCOL_METHOD'); +test(U, U, 'hokey-pokey', U, U, U, + U, 'ERR_TLS_INVALID_PROTOCOL_METHOD'); +test(U, U, U, U, U, 'hokey-pokey', + U, U, 'ERR_TLS_INVALID_PROTOCOL_METHOD'); // Cannot use secureProtocol and min/max versions simultaneously. -test(U, U, U, U, 'TLSv1.2', 'TLS1_2_method', 'conflicts with secureProtocol'); -test(U, U, U, 'TLSv1.2', U, 'TLS1_2_method', 'conflicts with secureProtocol'); -test(U, 'TLSv1.2', 'TLS1_2_method', U, U, U, 'conflicts with secureProtocol'); -test('TLSv1.2', U, 'TLS1_2_method', U, U, U, 'conflicts with secureProtocol'); +test(U, U, U, U, 'TLSv1.2', 'TLS1_2_method', + U, U, 'ERR_TLS_PROTOCOL_VERSION_CONFLICT'); +test(U, U, U, 'TLSv1.2', U, 'TLS1_2_method', + U, U, 'ERR_TLS_PROTOCOL_VERSION_CONFLICT'); +test(U, 'TLSv1.2', 'TLS1_2_method', U, U, U, + U, 'ERR_TLS_PROTOCOL_VERSION_CONFLICT'); +test('TLSv1.2', U, 'TLS1_2_method', U, U, U, + U, 'ERR_TLS_PROTOCOL_VERSION_CONFLICT'); // TLS_method means "any supported protocol". test(U, U, 'TLSv1_2_method', U, U, 'TLS_method', 'TLSv1.2'); @@ -82,17 +123,23 @@ test(U, U, 'TLS_method', U, U, 'TLSv1_method', 'TLSv1'); test(U, U, 'TLSv1_2_method', U, U, 'SSLv23_method', 'TLSv1.2'); if (DEFAULT_MIN_VERSION === 'TLSv1.2') { - test(U, U, 'TLSv1_1_method', U, U, 'SSLv23_method', null); - test(U, U, 'TLSv1_method', U, U, 'SSLv23_method', null); - test(U, U, 'SSLv23_method', U, U, 'TLSv1_1_method', null); - test(U, U, 'SSLv23_method', U, U, 'TLSv1_method', null); + test(U, U, 'TLSv1_1_method', U, U, 'SSLv23_method', + U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL'); + test(U, U, 'TLSv1_method', U, U, 'SSLv23_method', + U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL'); + test(U, U, 'SSLv23_method', U, U, 'TLSv1_1_method', + U, 'ERR_SSL_UNSUPPORTED_PROTOCOL', 'ERR_SSL_WRONG_VERSION_NUMBER'); + test(U, U, 'SSLv23_method', U, U, 'TLSv1_method', + U, 'ERR_SSL_UNSUPPORTED_PROTOCOL', 'ERR_SSL_WRONG_VERSION_NUMBER'); } if (DEFAULT_MIN_VERSION === 'TLSv1.1') { test(U, U, 'TLSv1_1_method', U, U, 'SSLv23_method', 'TLSv1.1'); - test(U, U, 'TLSv1_method', U, U, 'SSLv23_method', null); + test(U, U, 'TLSv1_method', U, U, 'SSLv23_method', + U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL'); test(U, U, 'SSLv23_method', U, U, 'TLSv1_1_method', 'TLSv1.1'); - test(U, U, 'SSLv23_method', U, U, 'TLSv1_method', null); + test(U, U, 'SSLv23_method', U, U, 'TLSv1_method', + U, 'ERR_SSL_UNSUPPORTED_PROTOCOL', 'ERR_SSL_WRONG_VERSION_NUMBER'); } if (DEFAULT_MIN_VERSION === 'TLSv1') { @@ -110,18 +157,34 @@ test(U, U, 'TLSv1_method', U, U, 'TLSv1_method', 'TLSv1'); // The default default. if (DEFAULT_MIN_VERSION === 'TLSv1.2') { - test(U, U, 'TLSv1_1_method', U, U, U, null); - test(U, U, 'TLSv1_method', U, U, U, null); - test(U, U, U, U, U, 'TLSv1_1_method', null); - test(U, U, U, U, U, 'TLSv1_method', null); + test(U, U, 'TLSv1_1_method', U, U, U, + U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL'); + test(U, U, 'TLSv1_method', U, U, U, + U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL'); + + if (DEFAULT_MAX_VERSION === 'TLSv1.2') { + test(U, U, U, U, U, 'TLSv1_1_method', + U, 'ERR_SSL_UNSUPPORTED_PROTOCOL', 'ERR_SSL_WRONG_VERSION_NUMBER'); + test(U, U, U, U, U, 'TLSv1_method', + U, 'ERR_SSL_UNSUPPORTED_PROTOCOL', 'ERR_SSL_WRONG_VERSION_NUMBER'); + } else { + assert(false, 'unreachable'); + } } // The default with --tls-v1.1. if (DEFAULT_MIN_VERSION === 'TLSv1.1') { test(U, U, 'TLSv1_1_method', U, U, U, 'TLSv1.1'); - test(U, U, 'TLSv1_method', U, U, U, null); + test(U, U, 'TLSv1_method', U, U, U, + U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL'); test(U, U, U, U, U, 'TLSv1_1_method', 'TLSv1.1'); - test(U, U, U, U, U, 'TLSv1_method', null); + + if (DEFAULT_MAX_VERSION === 'TLSv1.2') { + test(U, U, U, U, U, 'TLSv1_method', + U, 'ERR_SSL_UNSUPPORTED_PROTOCOL', 'ERR_SSL_WRONG_VERSION_NUMBER'); + } else { + assert(false, 'unreachable'); + } } // The default with --tls-v1.0.