Skip to content
This repository was archived by the owner on Apr 22, 2023. It is now read-only.

Commit bf5e2f2

Browse files
Trevor Livingstonindutny
authored andcommitted
tls: checkServerIdentity option
Allow overriding `checkServerIdentity` function, when connecting to a TLS server. Reviewed-By: Fedor Indutny <fedor@indutny.com>
1 parent 06526a2 commit bf5e2f2

File tree

3 files changed

+95
-2
lines changed

3 files changed

+95
-2
lines changed

doc/api/tls.markdown

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ automatically set as a listener for the [secureConnection][] event. The
196196
which is not authorized with the list of supplied CAs. This option only
197197
has an effect if `requestCert` is `true`. Default: `false`.
198198

199+
- `checkServerIdentity(servername, cert)`: Provide an override for checking
200+
server's hostname against the certificate. Should return an error if verification
201+
fails. Return `undefined` if passing.
202+
199203
- `NPNProtocols`: An array or `Buffer` of possible NPN protocols. (Protocols
200204
should be ordered by their priority).
201205

lib/_tls_wrap.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -822,10 +822,14 @@ exports.connect = function(/* [port, host], options, cb */) {
822822

823823
var defaults = {
824824
rejectUnauthorized: '0' !== process.env.NODE_TLS_REJECT_UNAUTHORIZED,
825-
ciphers: tls.DEFAULT_CIPHERS
825+
ciphers: tls.DEFAULT_CIPHERS,
826+
checkServerIdentity: tls.checkServerIdentity
826827
};
828+
827829
options = util._extend(defaults, options || {});
828830

831+
assert(typeof options.checkServerIdentity === 'function');
832+
829833
var hostname = options.servername ||
830834
options.host ||
831835
options.socket && options.socket._host,
@@ -912,7 +916,7 @@ exports.connect = function(/* [port, host], options, cb */) {
912916
// Verify that server's identity matches it's certificate's names
913917
if (!verifyError) {
914918
var cert = result.getPeerCertificate();
915-
verifyError = tls.checkServerIdentity(hostname, cert);
919+
verifyError = options.checkServerIdentity(hostname, cert);
916920
}
917921

918922
if (verifyError) {
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
if (!process.versions.openssl) {
23+
console.error('Skipping because node compiled without OpenSSL.');
24+
process.exit(0);
25+
}
26+
27+
var common = require('../common');
28+
var assert = require('assert');
29+
var https = require('https');
30+
var fs = require('fs');
31+
var path = require('path');
32+
33+
var options = {
34+
key: fs.readFileSync(path.join(common.fixturesDir, 'keys/agent3-key.pem')),
35+
cert: fs.readFileSync(path.join(common.fixturesDir, 'keys/agent3-cert.pem'))
36+
};
37+
38+
var reqCount = 0;
39+
40+
var server = https.createServer(options, function (req, res) {
41+
++reqCount;
42+
res.writeHead(200);
43+
res.end();
44+
req.resume();
45+
}).listen(common.PORT, function () {
46+
authorized();
47+
});
48+
49+
function authorized() {
50+
var req = https.request({
51+
port: common.PORT,
52+
rejectUnauthorized: true,
53+
ca: [fs.readFileSync(path.join(common.fixturesDir, 'keys/ca2-cert.pem'))]
54+
}, function (res) {
55+
assert(false);
56+
});
57+
req.on('error', function (err) {
58+
override();
59+
});
60+
req.end();
61+
}
62+
63+
function override() {
64+
var options = {
65+
port: common.PORT,
66+
rejectUnauthorized: true,
67+
ca: [fs.readFileSync(path.join(common.fixturesDir, 'keys/ca2-cert.pem'))],
68+
checkServerIdentity: function (host, cert) {
69+
return false;
70+
}
71+
};
72+
options.agent = new https.Agent(options);
73+
var req = https.request(options, function (res) {
74+
assert(req.socket.authorized);
75+
server.close();
76+
});
77+
req.on('error', function (err) {
78+
throw err;
79+
});
80+
req.end();
81+
}
82+
83+
process.on('exit', function () {
84+
assert.equal(reqCount, 1);
85+
});

0 commit comments

Comments
 (0)