mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
e9cd4766e3
Refs: https://github.com/nodejs/node/issues/53382 Refs: https://github.com/nodejs/node/pull/53384 Same change as in 53384 where OpenSSL32 returns a slightly different error but for a different test. Signed-off-by: Michael Dawson <midawson@redhat.com> PR-URL: https://github.com/nodejs/node/pull/54610 Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
364 lines
8.0 KiB
JavaScript
364 lines
8.0 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
const fixtures = require('../common/fixtures');
|
|
|
|
const {
|
|
assert, connect, keys, tls
|
|
} = require(fixtures.path('tls-connect'));
|
|
|
|
// Use ec10 and agent10, they are the only identities with intermediate CAs.
|
|
const client = keys.ec10;
|
|
const server = keys.agent10;
|
|
|
|
// The certificates aren't for "localhost", so override the identity check.
|
|
function checkServerIdentity(hostname, cert) {
|
|
assert.strictEqual(hostname, 'localhost');
|
|
assert.strictEqual(cert.subject.CN, 'agent10.example.com');
|
|
}
|
|
|
|
// Split out the single end-entity cert and the subordinate CA for later use.
|
|
split(client.cert, client);
|
|
split(server.cert, server);
|
|
|
|
function split(file, into) {
|
|
const certs = /([^]*END CERTIFICATE-----\r?\n)(-----BEGIN[^]*)/.exec(file);
|
|
assert.strictEqual(certs.length, 3);
|
|
into.single = certs[1];
|
|
into.subca = certs[2];
|
|
}
|
|
|
|
// Typical setup, nothing special, complete cert chains sent to peer.
|
|
connect({
|
|
client: {
|
|
key: client.key,
|
|
cert: client.cert,
|
|
ca: server.ca,
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert,
|
|
ca: client.ca,
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.ifError(err);
|
|
return cleanup();
|
|
});
|
|
|
|
// As above, but without requesting client's cert.
|
|
connect({
|
|
client: {
|
|
ca: server.ca,
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert,
|
|
ca: client.ca,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.ifError(err);
|
|
return cleanup();
|
|
});
|
|
|
|
// Request cert from TLS1.2 client that doesn't have one.
|
|
connect({
|
|
client: {
|
|
maxVersion: 'TLSv1.2',
|
|
ca: server.ca,
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert,
|
|
ca: client.ca,
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.strictEqual(pair.server.err.code,
|
|
'ERR_SSL_PEER_DID_NOT_RETURN_A_CERTIFICATE');
|
|
const expectedErr = common.hasOpenSSL(3, 2) ?
|
|
'ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE' : 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE';
|
|
assert.strictEqual(pair.client.err.code,
|
|
expectedErr);
|
|
return cleanup();
|
|
});
|
|
|
|
// Request cert from TLS1.3 client that doesn't have one.
|
|
if (tls.DEFAULT_MAX_VERSION === 'TLSv1.3') connect({
|
|
client: {
|
|
ca: server.ca,
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert,
|
|
ca: client.ca,
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.strictEqual(pair.server.err.code,
|
|
'ERR_SSL_PEER_DID_NOT_RETURN_A_CERTIFICATE');
|
|
|
|
// TLS1.3 client completes handshake before server, and its only after the
|
|
// server handshakes, requests certs, gets back a zero-length list of certs,
|
|
// and sends a fatal Alert to the client that the client discovers there has
|
|
// been a fatal error.
|
|
pair.client.conn.once('error', common.mustCall((err) => {
|
|
assert.strictEqual(err.code, 'ERR_SSL_TLSV13_ALERT_CERTIFICATE_REQUIRED');
|
|
cleanup();
|
|
}));
|
|
});
|
|
|
|
// Typical configuration error, incomplete cert chains sent, we have to know the
|
|
// peer's subordinate CAs in order to verify the peer.
|
|
connect({
|
|
client: {
|
|
key: client.key,
|
|
cert: client.single,
|
|
ca: [server.ca, server.subca],
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.single,
|
|
ca: [client.ca, client.subca],
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.ifError(err);
|
|
return cleanup();
|
|
});
|
|
|
|
// Like above, but provide root CA and subordinate CA as multi-PEM.
|
|
connect({
|
|
client: {
|
|
key: client.key,
|
|
cert: client.single,
|
|
ca: server.ca + '\n' + server.subca,
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.single,
|
|
ca: client.ca + '\n' + client.subca,
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.ifError(err);
|
|
return cleanup();
|
|
});
|
|
|
|
// Like above, but provide multi-PEM in an array.
|
|
connect({
|
|
client: {
|
|
key: client.key,
|
|
cert: client.single,
|
|
ca: [server.ca + '\n' + server.subca],
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.single,
|
|
ca: [client.ca + '\n' + client.subca],
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.ifError(err);
|
|
return cleanup();
|
|
});
|
|
|
|
// Fail to complete server's chain
|
|
connect({
|
|
client: {
|
|
ca: server.ca,
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.single,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.strictEqual(err.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE');
|
|
return cleanup();
|
|
});
|
|
|
|
// Fail to complete client's chain.
|
|
connect({
|
|
client: {
|
|
key: client.key,
|
|
cert: client.single,
|
|
ca: server.ca,
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert,
|
|
ca: client.ca,
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.ifError(pair.client.error);
|
|
assert.ifError(pair.server.error);
|
|
assert.strictEqual(err.code, 'ECONNRESET');
|
|
return cleanup();
|
|
});
|
|
|
|
// Fail to find CA for server.
|
|
connect({
|
|
client: {
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.strictEqual(err.code, 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY');
|
|
return cleanup();
|
|
});
|
|
|
|
// Server sent their CA, but CA cannot be trusted if it is not locally known.
|
|
connect({
|
|
client: {
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert + '\n' + server.ca,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.strictEqual(err.code, 'SELF_SIGNED_CERT_IN_CHAIN');
|
|
return cleanup();
|
|
});
|
|
|
|
// Server sent their CA, wrongly, but its OK since we know the CA locally.
|
|
connect({
|
|
client: {
|
|
checkServerIdentity,
|
|
ca: server.ca,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert + '\n' + server.ca,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.ifError(err);
|
|
return cleanup();
|
|
});
|
|
|
|
// Fail to complete client's chain.
|
|
connect({
|
|
client: {
|
|
key: client.key,
|
|
cert: client.single,
|
|
ca: server.ca,
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert,
|
|
ca: client.ca,
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.strictEqual(err.code, 'ECONNRESET');
|
|
return cleanup();
|
|
});
|
|
|
|
// Fail to find CA for client.
|
|
connect({
|
|
client: {
|
|
key: client.key,
|
|
cert: client.cert,
|
|
ca: server.ca,
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert,
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.strictEqual(err.code, 'ECONNRESET');
|
|
return cleanup();
|
|
});
|
|
|
|
// Confirm support for "BEGIN TRUSTED CERTIFICATE".
|
|
connect({
|
|
client: {
|
|
key: client.key,
|
|
cert: client.cert,
|
|
ca: server.ca.replace(/CERTIFICATE/g, 'TRUSTED CERTIFICATE'),
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert,
|
|
ca: client.ca,
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.ifError(err);
|
|
return cleanup();
|
|
});
|
|
|
|
// Confirm support for "BEGIN TRUSTED CERTIFICATE".
|
|
connect({
|
|
client: {
|
|
key: client.key,
|
|
cert: client.cert,
|
|
ca: server.ca,
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert,
|
|
ca: client.ca.replace(/CERTIFICATE/g, 'TRUSTED CERTIFICATE'),
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.ifError(err);
|
|
return cleanup();
|
|
});
|
|
|
|
// Confirm support for "BEGIN X509 CERTIFICATE".
|
|
connect({
|
|
client: {
|
|
key: client.key,
|
|
cert: client.cert,
|
|
ca: server.ca.replace(/CERTIFICATE/g, 'X509 CERTIFICATE'),
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert,
|
|
ca: client.ca,
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.ifError(err);
|
|
return cleanup();
|
|
});
|
|
|
|
// Confirm support for "BEGIN X509 CERTIFICATE".
|
|
connect({
|
|
client: {
|
|
key: client.key,
|
|
cert: client.cert,
|
|
ca: server.ca,
|
|
checkServerIdentity,
|
|
},
|
|
server: {
|
|
key: server.key,
|
|
cert: server.cert,
|
|
ca: client.ca.replace(/CERTIFICATE/g, 'X509 CERTIFICATE'),
|
|
requestCert: true,
|
|
},
|
|
}, function(err, pair, cleanup) {
|
|
assert.ifError(err);
|
|
return cleanup();
|
|
});
|