-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: move common tls connect setup into fixtures
TLS connection setup boilerplate is common to many TLS tests, factor it into a test fixture so tests are clearer to read and faster to write. Backport-PR-URL: #12468 PR-URL: #10389 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
- Loading branch information
1 parent
4207bce
commit 4575f92
Showing
4 changed files
with
181 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// One shot call to connect a TLS client and server based on options to | ||
// tls.createServer() and tls.connect(), so assertions can be made on both ends | ||
// of the connection. | ||
'use strict'; | ||
|
||
const common = require('../common'); | ||
const fs = require('fs'); | ||
const join = require('path').join; | ||
const tls = require('tls'); | ||
const util = require('util'); | ||
|
||
module.exports = exports = checkCrypto; | ||
|
||
function checkCrypto() { | ||
if (!common.hasCrypto) { | ||
common.skip('missing crypto'); | ||
process.exit(0); | ||
} | ||
return exports; | ||
} | ||
|
||
exports.assert = require('assert'); | ||
exports.debug = util.debuglog('test'); | ||
exports.tls = tls; | ||
|
||
// Pre-load keys from common fixtures for ease of use by tests. | ||
const keys = exports.keys = { | ||
agent1: load('agent1', 'ca1'), | ||
agent2: load('agent2', 'agent2'), | ||
agent3: load('agent3', 'ca2'), | ||
agent4: load('agent4', 'ca2'), | ||
agent5: load('agent5', 'ca2'), | ||
agent6: load('agent6', 'ca1'), | ||
agent7: load('agent7', 'fake-cnnic-root'), | ||
ec: load('ec', 'ec'), | ||
}; | ||
|
||
function load(cert, issuer) { | ||
issuer = issuer || cert; // Assume self-signed if no issuer | ||
const id = { | ||
key: read(cert + '-key.pem'), | ||
cert: read(cert + '-cert.pem'), | ||
ca: read(issuer + '-cert.pem'), | ||
}; | ||
return id; | ||
} | ||
|
||
function read(file) { | ||
return fs.readFileSync(join(common.fixturesDir, 'keys', file), 'binary'); | ||
} | ||
|
||
exports.connect = function connect(options, callback) { | ||
callback = common.mustCall(callback); | ||
|
||
const server = {}; | ||
const client = {}; | ||
const pair = { | ||
server: server, | ||
client: client, | ||
}; | ||
|
||
tls.createServer(options.server, function(conn) { | ||
server.conn = conn; | ||
conn.pipe(conn); | ||
maybeCallback() | ||
}).listen(0, function() { | ||
server.server = this; | ||
|
||
const optClient = util._extend({ | ||
port: this.address().port, | ||
}, options.client); | ||
|
||
tls.connect(optClient) | ||
.on('secureConnect', function() { | ||
client.conn = this; | ||
maybeCallback(); | ||
}) | ||
.on('error', function(err) { | ||
client.err = err; | ||
client.conn = this; | ||
maybeCallback(); | ||
}); | ||
}); | ||
|
||
function maybeCallback() { | ||
if (!callback) | ||
return; | ||
if (server.conn && (client.conn || client.err)) { | ||
const err = pair.client.err || pair.server.err; | ||
callback(err, pair, cleanup); | ||
callback = null; | ||
|
||
function cleanup() { | ||
if (server.server) | ||
server.server.close(); | ||
if (client.conn) | ||
client.conn.end(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,50 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
const fs = require('fs'); | ||
|
||
if (!common.hasCrypto) { | ||
common.skip('missing crypto'); | ||
return; | ||
} | ||
const tls = require('tls'); | ||
|
||
function filenamePEM(n) { | ||
return require('path').join(common.fixturesDir, 'keys', n + '.pem'); | ||
} | ||
// Adding a CA certificate to contextWithCert should not also add it to | ||
// contextWithoutCert. This is tested by trying to connect to a server that | ||
// depends on that CA using contextWithoutCert. | ||
|
||
function loadPEM(n) { | ||
return fs.readFileSync(filenamePEM(n)); | ||
} | ||
const join = require('path').join; | ||
const { | ||
assert, connect, keys, tls | ||
} = require(join(common.fixturesDir, 'tls-connect'))(); | ||
|
||
const caCert = loadPEM('ca1-cert'); | ||
const contextWithoutCert = tls.createSecureContext({}); | ||
const contextWithCert = tls.createSecureContext({}); | ||
// Adding a CA certificate to contextWithCert should not also add it to | ||
// contextWithoutCert. This is tested by trying to connect to a server that | ||
// depends on that CA using contextWithoutCert. | ||
contextWithCert.context.addCACert(caCert); | ||
contextWithCert.context.addCACert(keys.agent1.ca); | ||
|
||
const serverOptions = { | ||
key: loadPEM('agent1-key'), | ||
cert: loadPEM('agent1-cert'), | ||
key: keys.agent1.key, | ||
cert: keys.agent1.cert, | ||
}; | ||
const server = tls.createServer(serverOptions, function() {}); | ||
|
||
const clientOptions = { | ||
port: undefined, | ||
ca: [caCert], | ||
ca: [keys.agent1.ca], | ||
servername: 'agent1', | ||
rejectUnauthorized: true, | ||
}; | ||
|
||
function startTest() { | ||
// This client should fail to connect because it doesn't trust the CA | ||
// This client should fail to connect because it doesn't trust the CA | ||
// certificate. | ||
clientOptions.secureContext = contextWithoutCert; | ||
|
||
connect({ | ||
client: clientOptions, | ||
server: serverOptions, | ||
}, function(err, pair, cleanup) { | ||
assert(err); | ||
assert.strictEqual(err.message, 'unable to verify the first certificate'); | ||
cleanup(); | ||
|
||
// This time it should connect because contextWithCert includes the needed CA | ||
// certificate. | ||
clientOptions.secureContext = contextWithoutCert; | ||
clientOptions.port = server.address().port; | ||
const client = tls.connect(clientOptions, common.fail); | ||
client.on('error', common.mustCall(() => { | ||
client.destroy(); | ||
|
||
// This time it should connect because contextWithCert includes the needed | ||
// CA certificate. | ||
clientOptions.secureContext = contextWithCert; | ||
const client2 = tls.connect(clientOptions, common.mustCall(() => { | ||
client2.destroy(); | ||
server.close(); | ||
})); | ||
client2.on('error', (e) => { | ||
console.log(e); | ||
}); | ||
})); | ||
} | ||
|
||
server.listen(0, startTest); | ||
clientOptions.secureContext = contextWithCert; | ||
connect({ | ||
client: clientOptions, | ||
server: serverOptions, | ||
}, function(err, pair, cleanup) { | ||
assert.ifError(err); | ||
cleanup(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,25 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
|
||
if (!common.hasCrypto) { | ||
common.skip('missing crypto'); | ||
return; | ||
} | ||
const tls = require('tls'); | ||
// Verify connection with explicitly created client SecureContext. | ||
|
||
const fs = require('fs'); | ||
const path = require('path'); | ||
const join = require('path').join; | ||
const { | ||
assert, connect, keys, tls | ||
} = require(join(common.fixturesDir, 'tls-connect'))(); | ||
|
||
const keysDir = path.join(common.fixturesDir, 'keys'); | ||
|
||
const ca = fs.readFileSync(path.join(keysDir, 'ca1-cert.pem')); | ||
const cert = fs.readFileSync(path.join(keysDir, 'agent1-cert.pem')); | ||
const key = fs.readFileSync(path.join(keysDir, 'agent1-key.pem')); | ||
|
||
const server = tls.createServer({ | ||
cert: cert, | ||
key: key | ||
}, function(c) { | ||
c.end(); | ||
}).listen(0, function() { | ||
const secureContext = tls.createSecureContext({ | ||
ca: ca | ||
}); | ||
|
||
const socket = tls.connect({ | ||
secureContext: secureContext, | ||
connect({ | ||
client: { | ||
servername: 'agent1', | ||
port: this.address().port | ||
}, common.mustCall(function() { | ||
server.close(); | ||
socket.end(); | ||
})); | ||
secureContext: tls.createSecureContext({ | ||
ca: keys.agent1.ca, | ||
}), | ||
}, | ||
server: { | ||
cert: keys.agent1.cert, | ||
key: keys.agent1.key, | ||
}, | ||
}, function(err, pair, cleanup) { | ||
assert.ifError(err); | ||
return cleanup(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,39 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
const assert = require('assert'); | ||
|
||
if (!common.hasCrypto) { | ||
common.skip('missing crypto'); | ||
return; | ||
} | ||
const tls = require('tls'); | ||
// Verify that detailed getPeerCertificate() return value has all certs. | ||
|
||
const fs = require('fs'); | ||
const util = require('util'); | ||
const join = require('path').join; | ||
const { | ||
assert, connect, debug, keys | ||
} = require(join(common.fixturesDir, 'tls-connect'))(); | ||
|
||
const options = { | ||
key: fs.readFileSync(join(common.fixturesDir, 'keys', 'agent1-key.pem')), | ||
cert: fs.readFileSync(join(common.fixturesDir, 'keys', 'agent1-cert.pem')), | ||
ca: [ fs.readFileSync(join(common.fixturesDir, 'keys', 'ca1-cert.pem')) ] | ||
}; | ||
connect({ | ||
client: {rejectUnauthorized: false}, | ||
server: keys.agent1, | ||
}, function(err, pair, cleanup) { | ||
assert.ifError(err); | ||
const socket = pair.client.conn; | ||
let peerCert = socket.getPeerCertificate(); | ||
assert.ok(!peerCert.issuerCertificate); | ||
|
||
const server = tls.createServer(options, function(cleartext) { | ||
cleartext.end('World'); | ||
}); | ||
server.listen(0, common.mustCall(function() { | ||
const socket = tls.connect({ | ||
port: this.address().port, | ||
rejectUnauthorized: false | ||
}, common.mustCall(function() { | ||
let peerCert = socket.getPeerCertificate(); | ||
assert.ok(!peerCert.issuerCertificate); | ||
peerCert = socket.getPeerCertificate(true); | ||
debug('peerCert:\n', peerCert); | ||
|
||
// Verify that detailed return value has all certs | ||
peerCert = socket.getPeerCertificate(true); | ||
assert.ok(peerCert.issuerCertificate); | ||
assert.ok(peerCert.issuerCertificate); | ||
assert.strictEqual(peerCert.subject.emailAddress, 'ry@tinyclouds.org'); | ||
assert.strictEqual(peerCert.serialNumber, '9A84ABCFB8A72AC0'); | ||
assert.strictEqual(peerCert.exponent, '0x10001'); | ||
assert.strictEqual( | ||
peerCert.fingerprint, | ||
'8D:06:3A:B3:E5:8B:85:29:72:4F:7D:1B:54:CD:95:19:3C:EF:6F:AA' | ||
); | ||
assert.deepStrictEqual(peerCert.infoAccess['OCSP - URI'], | ||
[ 'http://ocsp.nodejs.org/' ]); | ||
|
||
console.error(util.inspect(peerCert)); | ||
assert.strictEqual(peerCert.subject.emailAddress, 'ry@tinyclouds.org'); | ||
assert.strictEqual(peerCert.serialNumber, '9A84ABCFB8A72AC0'); | ||
assert.strictEqual(peerCert.exponent, '0x10001'); | ||
assert.strictEqual( | ||
peerCert.fingerprint, | ||
'8D:06:3A:B3:E5:8B:85:29:72:4F:7D:1B:54:CD:95:19:3C:EF:6F:AA' | ||
); | ||
assert.deepStrictEqual(peerCert.infoAccess['OCSP - URI'], | ||
[ 'http://ocsp.nodejs.org/' ]); | ||
const issuer = peerCert.issuerCertificate; | ||
assert.strictEqual(issuer.issuerCertificate, issuer); | ||
assert.strictEqual(issuer.serialNumber, '8DF21C01468AF393'); | ||
|
||
const issuer = peerCert.issuerCertificate; | ||
assert.strictEqual(issuer.issuerCertificate, issuer); | ||
assert.strictEqual(issuer.serialNumber, '8DF21C01468AF393'); | ||
server.close(); | ||
})); | ||
socket.end('Hello'); | ||
})); | ||
return cleanup(); | ||
}); |