test: cover tls multi-identity option mixtures

Prove that cert and key options do not have to be ordered, and that the
pfx option can be used at the same time as the cert/key option
(which was claimed to be impossible by some pre-existing documentation).

PR-URL: https://github.com/nodejs/node/pull/24374
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
This commit is contained in:
Sam Roberts 2016-11-28 11:55:29 -08:00
parent ec6b7939eb
commit a745b1bdd0

View File

@ -21,6 +21,9 @@
'use strict'; 'use strict';
const common = require('../common'); const common = require('../common');
// Test multi-identity ('key')/multi-algorithm scenarios.
if (!common.hasCrypto) if (!common.hasCrypto)
common.skip('missing crypto'); common.skip('missing crypto');
@ -28,45 +31,158 @@ const fixtures = require('../common/fixtures');
const assert = require('assert'); const assert = require('assert');
const tls = require('tls'); const tls = require('tls');
const options = { // Key is ordered as ec, rsa, cert is ordered as rsa, ec.
test({
key: [ key: [
fixtures.readKey('ec-key.pem'), fixtures.readKey('ec10-key.pem'),
fixtures.readKey('agent1-key.pem'), fixtures.readKey('agent1-key.pem'),
], ],
cert: [ cert: [
fixtures.readKey('agent1-cert.pem'), fixtures.readKey('agent1-cert.pem'),
fixtures.readKey('ec10-cert.pem'),
],
eccCN: 'agent10.example.com',
client: { ca: [
fixtures.readKey('ca5-cert.pem'),
fixtures.readKey('ca1-cert.pem'),
] },
});
// Key and cert are ordered as ec, rsa.
test({
key: [
fixtures.readKey('ec10-key.pem'),
fixtures.readKey('agent1-key.pem'),
],
cert: [
fixtures.readKey('agent1-cert.pem'),
fixtures.readKey('ec10-cert.pem'),
],
eccCN: 'agent10.example.com',
client: { ca: [
fixtures.readKey('ca5-cert.pem'),
fixtures.readKey('ca1-cert.pem'),
] },
});
// Key, cert, and pfx options can be used simultaneously.
test({
key: [
fixtures.readKey('ec-key.pem'),
],
cert: [
fixtures.readKey('ec-cert.pem'), fixtures.readKey('ec-cert.pem'),
] ],
}; pfx: fixtures.readKey('agent1.pfx'),
passphrase: 'sample',
client: { ca: [
fixtures.readKey('ec-cert.pem'),
fixtures.readKey('ca1-cert.pem'),
] },
});
const ciphers = []; // Key and cert with mixed algorithms, and cert chains with intermediate CAs
test({
key: [
fixtures.readKey('ec10-key.pem'),
fixtures.readKey('agent10-key.pem'),
],
cert: [
fixtures.readKey('agent10-cert.pem'),
fixtures.readKey('ec10-cert.pem'),
],
rsaCN: 'agent10.example.com',
eccCN: 'agent10.example.com',
client: { ca: [
fixtures.readKey('ca2-cert.pem'),
fixtures.readKey('ca5-cert.pem'),
] },
});
const server = tls.createServer(options, function(conn) { // Key and cert with mixed algorithms, and cert chains with intermediate CAs,
conn.end('ok'); // using PFX for EC.
}).listen(0, function() { test({
const ecdsa = tls.connect(this.address().port, { key: [
ciphers: 'ECDHE-ECDSA-AES256-GCM-SHA384', fixtures.readKey('agent10-key.pem'),
rejectUnauthorized: false ],
}, function() { cert: [
ciphers.push(ecdsa.getCipher()); fixtures.readKey('agent10-cert.pem'),
],
pfx: fixtures.readKey('ec10.pfx'),
passphrase: 'sample',
rsaCN: 'agent10.example.com',
eccCN: 'agent10.example.com',
client: { ca: [
fixtures.readKey('ca2-cert.pem'),
fixtures.readKey('ca5-cert.pem'),
] },
});
// Key and cert with mixed algorithms, and cert chains with intermediate CAs,
// using PFX for RSA.
test({
key: [
fixtures.readKey('ec10-key.pem'),
],
cert: [
fixtures.readKey('ec10-cert.pem'),
],
pfx: fixtures.readKey('agent10.pfx'),
passphrase: 'sample',
rsaCN: 'agent10.example.com',
eccCN: 'agent10.example.com',
client: { ca: [
fixtures.readKey('ca2-cert.pem'),
fixtures.readKey('ca5-cert.pem'),
] },
});
function test(options) {
const rsaCN = options.rsaCN || 'agent1';
const eccCN = options.eccCN || 'agent2';
const clientTrustRoots = options.client.ca;
delete options.rsaCN;
delete options.eccCN;
delete options.client;
const server = tls.createServer(options, function(conn) {
conn.end('ok');
}).listen(0, common.mustCall(connectWithEcdsa));
function connectWithEcdsa() {
const ecdsa = tls.connect(this.address().port, {
ciphers: 'ECDHE-ECDSA-AES256-GCM-SHA384',
rejectUnauthorized: true,
ca: clientTrustRoots,
checkServerIdentity: (_, c) => assert.strictEqual(c.subject.CN, eccCN),
}, common.mustCall(function() {
assert.deepStrictEqual(ecdsa.getCipher(), {
name: 'ECDHE-ECDSA-AES256-GCM-SHA384',
version: 'TLSv1/SSLv3'
});
assert.strictEqual(ecdsa.getPeerCertificate().subject.CN, eccCN);
// XXX(sam) certs don't currently include EC key info, so depend on
// absence of RSA key info to indicate key is EC.
assert(!ecdsa.getPeerCertificate().exponent, 'not cert for an RSA key');
ecdsa.end();
connectWithRsa();
}));
}
function connectWithRsa() {
const rsa = tls.connect(server.address().port, { const rsa = tls.connect(server.address().port, {
ciphers: 'ECDHE-RSA-AES256-GCM-SHA384', ciphers: 'ECDHE-RSA-AES256-GCM-SHA384',
rejectUnauthorized: false rejectUnauthorized: true,
}, function() { ca: clientTrustRoots,
ciphers.push(rsa.getCipher()); checkServerIdentity: (_, c) => assert.strictEqual(c.subject.CN, rsaCN),
ecdsa.end(); }, common.mustCall(function() {
assert.deepStrictEqual(rsa.getCipher(), {
name: 'ECDHE-RSA-AES256-GCM-SHA384',
version: 'TLSv1/SSLv3'
});
assert.strictEqual(rsa.getPeerCertificate().subject.CN, rsaCN);
assert(rsa.getPeerCertificate().exponent, 'cert for an RSA key');
rsa.end(); rsa.end();
server.close(); server.close();
}); }));
}); }
}); }
process.on('exit', function() {
assert.deepStrictEqual(ciphers, [{
name: 'ECDHE-ECDSA-AES256-GCM-SHA384',
version: 'TLSv1/SSLv3'
}, {
name: 'ECDHE-RSA-AES256-GCM-SHA384',
version: 'TLSv1/SSLv3'
}]);
});