Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a7dccd0

Browse filesBrowse files
jimmycannBridgeAR
authored andcommitted
tls: type checking for key, cert and ca options
PR-URL: #14807 Fixes: #12802 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Roman Reiss <me@silverwind.io> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
1 parent 0097794 commit a7dccd0
Copy full SHA for a7dccd0

File tree

Expand file treeCollapse file tree

3 files changed

+336
-10
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

3 files changed

+336
-10
lines changed
Open diff view settings
Collapse file

‎lib/_tls_common.js‎

Copy file name to clipboardExpand all lines: lib/_tls_common.js
+24-10Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
'use strict';
2323

2424
const tls = require('tls');
25+
const errors = require('internal/errors');
2526

2627
const SSL_OP_CIPHER_SERVER_PREFERENCE =
2728
process.binding('constants').crypto.SSL_OP_CIPHER_SERVER_PREFERENCE;
@@ -52,6 +53,14 @@ function SecureContext(secureProtocol, secureOptions, context) {
5253
if (secureOptions) this.context.setOptions(secureOptions);
5354
}
5455

56+
function validateKeyCert(value, type) {
57+
if (typeof value !== 'string' && !ArrayBuffer.isView(value))
58+
throw new errors.TypeError(
59+
'ERR_INVALID_ARG_TYPE', type,
60+
['string', 'Buffer', 'TypedArray', 'DataView']
61+
);
62+
}
63+
5564
exports.SecureContext = SecureContext;
5665

5766

@@ -71,10 +80,12 @@ exports.createSecureContext = function createSecureContext(options, context) {
7180
// cert's issuer in C++ code.
7281
if (options.ca) {
7382
if (Array.isArray(options.ca)) {
74-
for (i = 0; i < options.ca.length; i++) {
75-
c.context.addCACert(options.ca[i]);
76-
}
83+
options.ca.forEach((ca) => {
84+
validateKeyCert(ca, 'ca');
85+
c.context.addCACert(ca);
86+
});
7787
} else {
88+
validateKeyCert(options.ca, 'ca');
7889
c.context.addCACert(options.ca);
7990
}
8091
} else {
@@ -83,9 +94,12 @@ exports.createSecureContext = function createSecureContext(options, context) {
8394

8495
if (options.cert) {
8596
if (Array.isArray(options.cert)) {
86-
for (i = 0; i < options.cert.length; i++)
87-
c.context.setCert(options.cert[i]);
97+
options.cert.forEach((cert) => {
98+
validateKeyCert(cert, 'cert');
99+
c.context.setCert(cert);
100+
});
88101
} else {
102+
validateKeyCert(options.cert, 'cert');
89103
c.context.setCert(options.cert);
90104
}
91105
}
@@ -96,12 +110,12 @@ exports.createSecureContext = function createSecureContext(options, context) {
96110
// which leads to the crash later on.
97111
if (options.key) {
98112
if (Array.isArray(options.key)) {
99-
for (i = 0; i < options.key.length; i++) {
100-
const key = options.key[i];
101-
const passphrase = key.passphrase || options.passphrase;
102-
c.context.setKey(key.pem || key, passphrase);
103-
}
113+
options.key.forEach((k) => {
114+
validateKeyCert(k.pem || k, 'key');
115+
c.context.setKey(k.pem || k, k.passphrase || options.passphrase);
116+
});
104117
} else {
118+
validateKeyCert(options.key, 'key');
105119
c.context.setKey(options.key, options.passphrase);
106120
}
107121
}
Collapse file
+156Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const fixtures = require('../common/fixtures');
5+
6+
if (!common.hasCrypto)
7+
common.skip('missing crypto');
8+
9+
const assert = require('assert');
10+
const https = require('https');
11+
12+
function toArrayBuffer(buf) {
13+
const ab = new ArrayBuffer(buf.length);
14+
const view = new Uint8Array(ab);
15+
return buf.map((b, i) => view[i] = b);
16+
}
17+
18+
function toDataView(buf) {
19+
const ab = new ArrayBuffer(buf.length);
20+
const view = new DataView(ab);
21+
return buf.map((b, i) => view[i] = b);
22+
}
23+
24+
const keyBuff = fixtures.readKey('agent1-key.pem');
25+
const certBuff = fixtures.readKey('agent1-cert.pem');
26+
const keyBuff2 = fixtures.readKey('ec-key.pem');
27+
const certBuff2 = fixtures.readKey('ec-cert.pem');
28+
const caCert = fixtures.readKey('ca1-cert.pem');
29+
const caCert2 = fixtures.readKey('ca2-cert.pem');
30+
const keyStr = keyBuff.toString();
31+
const certStr = certBuff.toString();
32+
const keyStr2 = keyBuff2.toString();
33+
const certStr2 = certBuff2.toString();
34+
const caCertStr = caCert.toString();
35+
const caCertStr2 = caCert2.toString();
36+
const keyArrBuff = toArrayBuffer(keyBuff);
37+
const certArrBuff = toArrayBuffer(certBuff);
38+
const caArrBuff = toArrayBuffer(caCert);
39+
const keyDataView = toDataView(keyBuff);
40+
const certDataView = toDataView(certBuff);
41+
const caArrDataView = toDataView(caCert);
42+
const invalidKeyRE = /^The "key" argument must be one of type string, Buffer, TypedArray, or DataView$/;
43+
const invalidCertRE = /^The "cert" argument must be one of type string, Buffer, TypedArray, or DataView$/;
44+
45+
// Checks to ensure https.createServer doesn't throw an error
46+
// Format ['key', 'cert']
47+
[
48+
[keyBuff, certBuff],
49+
[false, certBuff],
50+
[keyBuff, false],
51+
[keyStr, certStr],
52+
[false, certStr],
53+
[keyStr, false],
54+
[false, false],
55+
[keyArrBuff, certArrBuff],
56+
[keyArrBuff, false],
57+
[false, certArrBuff],
58+
[keyDataView, certDataView],
59+
[keyDataView, false],
60+
[false, certDataView],
61+
[[keyBuff, keyBuff2], [certBuff, certBuff2]],
62+
[[keyStr, keyStr2], [certStr, certStr2]],
63+
[[keyStr, keyStr2], false],
64+
[false, [certStr, certStr2]],
65+
[[{ pem: keyBuff }], false],
66+
[[{ pem: keyBuff }, { pem: keyBuff }], false]
67+
].map((params) => {
68+
assert.doesNotThrow(() => {
69+
https.createServer({
70+
key: params[0],
71+
cert: params[1]
72+
});
73+
});
74+
});
75+
76+
// Checks to ensure https.createServer predictably throws an error
77+
// Format ['key', 'cert', 'expected message']
78+
[
79+
[true, certBuff, invalidKeyRE],
80+
[keyBuff, true, invalidCertRE],
81+
[true, certStr, invalidKeyRE],
82+
[keyStr, true, invalidCertRE],
83+
[true, certArrBuff, invalidKeyRE],
84+
[keyArrBuff, true, invalidCertRE],
85+
[true, certDataView, invalidKeyRE],
86+
[keyDataView, true, invalidCertRE],
87+
[true, true, invalidCertRE],
88+
[true, false, invalidKeyRE],
89+
[false, true, invalidCertRE],
90+
[true, false, invalidKeyRE],
91+
[{ pem: keyBuff }, false, invalidKeyRE],
92+
[false, { pem: keyBuff }, invalidCertRE],
93+
[1, false, invalidKeyRE],
94+
[false, 1, invalidCertRE],
95+
[[keyBuff, true], [certBuff, certBuff2], invalidKeyRE],
96+
[[true, keyStr2], [certStr, certStr2], invalidKeyRE],
97+
[[keyBuff, keyBuff2], [true, certBuff2], invalidCertRE],
98+
[[keyStr, keyStr2], [certStr, true], invalidCertRE],
99+
[[true, false], [certBuff, certBuff2], invalidKeyRE],
100+
[[keyStr, keyStr2], [true, false], invalidCertRE],
101+
[[keyStr, keyStr2], true, invalidCertRE],
102+
[true, [certBuff, certBuff2], invalidKeyRE]
103+
].map((params) => {
104+
assert.throws(() => {
105+
https.createServer({
106+
key: params[0],
107+
cert: params[1]
108+
});
109+
}, common.expectsError({
110+
code: 'ERR_INVALID_ARG_TYPE',
111+
type: TypeError,
112+
message: params[2]
113+
}));
114+
});
115+
116+
// Checks to ensure https.createServer works with the CA parameter
117+
// Format ['key', 'cert', 'ca']
118+
[
119+
[keyBuff, certBuff, caCert],
120+
[keyBuff, certBuff, [caCert, caCert2]],
121+
[keyBuff, certBuff, caCertStr],
122+
[keyBuff, certBuff, [caCertStr, caCertStr2]],
123+
[keyBuff, certBuff, caArrBuff],
124+
[keyBuff, certBuff, caArrDataView],
125+
[keyBuff, certBuff, false],
126+
].map((params) => {
127+
assert.doesNotThrow(() => {
128+
https.createServer({
129+
key: params[0],
130+
cert: params[1],
131+
ca: params[2]
132+
});
133+
});
134+
});
135+
136+
// Checks to ensure https.createServer throws an error for CA assignment
137+
// Format ['key', 'cert', 'ca']
138+
[
139+
[keyBuff, certBuff, true],
140+
[keyBuff, certBuff, {}],
141+
[keyBuff, certBuff, 1],
142+
[keyBuff, certBuff, true],
143+
[keyBuff, certBuff, [caCert, true]]
144+
].map((params) => {
145+
assert.throws(() => {
146+
https.createServer({
147+
key: params[0],
148+
cert: params[1],
149+
ca: params[2]
150+
});
151+
}, common.expectsError({
152+
code: 'ERR_INVALID_ARG_TYPE',
153+
type: TypeError,
154+
message: /^The "ca" argument must be one of type string, Buffer, TypedArray, or DataView$/
155+
}));
156+
});
Collapse file
+156Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const fixtures = require('../common/fixtures');
5+
6+
if (!common.hasCrypto)
7+
common.skip('missing crypto');
8+
9+
const assert = require('assert');
10+
const tls = require('tls');
11+
12+
function toArrayBuffer(buf) {
13+
const ab = new ArrayBuffer(buf.length);
14+
const view = new Uint8Array(ab);
15+
return buf.map((b, i) => view[i] = b);
16+
}
17+
18+
function toDataView(buf) {
19+
const ab = new ArrayBuffer(buf.length);
20+
const view = new DataView(ab);
21+
return buf.map((b, i) => view[i] = b);
22+
}
23+
24+
const keyBuff = fixtures.readKey('agent1-key.pem');
25+
const certBuff = fixtures.readKey('agent1-cert.pem');
26+
const keyBuff2 = fixtures.readKey('ec-key.pem');
27+
const certBuff2 = fixtures.readKey('ec-cert.pem');
28+
const caCert = fixtures.readKey('ca1-cert.pem');
29+
const caCert2 = fixtures.readKey('ca2-cert.pem');
30+
const keyStr = keyBuff.toString();
31+
const certStr = certBuff.toString();
32+
const keyStr2 = keyBuff2.toString();
33+
const certStr2 = certBuff2.toString();
34+
const caCertStr = caCert.toString();
35+
const caCertStr2 = caCert2.toString();
36+
const keyArrBuff = toArrayBuffer(keyBuff);
37+
const certArrBuff = toArrayBuffer(certBuff);
38+
const caArrBuff = toArrayBuffer(caCert);
39+
const keyDataView = toDataView(keyBuff);
40+
const certDataView = toDataView(certBuff);
41+
const caArrDataView = toDataView(caCert);
42+
const invalidKeyRE = /^The "key" argument must be one of type string, Buffer, TypedArray, or DataView$/;
43+
const invalidCertRE = /^The "cert" argument must be one of type string, Buffer, TypedArray, or DataView$/;
44+
45+
// Checks to ensure tls.createServer doesn't throw an error
46+
// Format ['key', 'cert']
47+
[
48+
[keyBuff, certBuff],
49+
[false, certBuff],
50+
[keyBuff, false],
51+
[keyStr, certStr],
52+
[false, certStr],
53+
[keyStr, false],
54+
[false, false],
55+
[keyArrBuff, certArrBuff],
56+
[keyArrBuff, false],
57+
[false, certArrBuff],
58+
[keyDataView, certDataView],
59+
[keyDataView, false],
60+
[false, certDataView],
61+
[[keyBuff, keyBuff2], [certBuff, certBuff2]],
62+
[[keyStr, keyStr2], [certStr, certStr2]],
63+
[[keyStr, keyStr2], false],
64+
[false, [certStr, certStr2]],
65+
[[{ pem: keyBuff }], false],
66+
[[{ pem: keyBuff }, { pem: keyBuff }], false]
67+
].map((params) => {
68+
assert.doesNotThrow(() => {
69+
tls.createServer({
70+
key: params[0],
71+
cert: params[1]
72+
});
73+
});
74+
});
75+
76+
// Checks to ensure tls.createServer predictably throws an error
77+
// Format ['key', 'cert', 'expected message']
78+
[
79+
[true, certBuff, invalidKeyRE],
80+
[keyBuff, true, invalidCertRE],
81+
[true, certStr, invalidKeyRE],
82+
[keyStr, true, invalidCertRE],
83+
[true, certArrBuff, invalidKeyRE],
84+
[keyArrBuff, true, invalidCertRE],
85+
[true, certDataView, invalidKeyRE],
86+
[keyDataView, true, invalidCertRE],
87+
[true, true, invalidCertRE],
88+
[true, false, invalidKeyRE],
89+
[false, true, invalidCertRE],
90+
[true, false, invalidKeyRE],
91+
[{ pem: keyBuff }, false, invalidKeyRE],
92+
[false, { pem: keyBuff }, invalidCertRE],
93+
[1, false, invalidKeyRE],
94+
[false, 1, invalidCertRE],
95+
[[keyBuff, true], [certBuff, certBuff2], invalidKeyRE],
96+
[[true, keyStr2], [certStr, certStr2], invalidKeyRE],
97+
[[keyBuff, keyBuff2], [true, certBuff2], invalidCertRE],
98+
[[keyStr, keyStr2], [certStr, true], invalidCertRE],
99+
[[true, false], [certBuff, certBuff2], invalidKeyRE],
100+
[[keyStr, keyStr2], [true, false], invalidCertRE],
101+
[[keyStr, keyStr2], true, invalidCertRE],
102+
[true, [certBuff, certBuff2], invalidKeyRE]
103+
].map((params) => {
104+
assert.throws(() => {
105+
tls.createServer({
106+
key: params[0],
107+
cert: params[1]
108+
});
109+
}, common.expectsError({
110+
code: 'ERR_INVALID_ARG_TYPE',
111+
type: TypeError,
112+
message: params[2]
113+
}));
114+
});
115+
116+
// Checks to ensure tls.createServer works with the CA parameter
117+
// Format ['key', 'cert', 'ca']
118+
[
119+
[keyBuff, certBuff, caCert],
120+
[keyBuff, certBuff, [caCert, caCert2]],
121+
[keyBuff, certBuff, caCertStr],
122+
[keyBuff, certBuff, [caCertStr, caCertStr2]],
123+
[keyBuff, certBuff, caArrBuff],
124+
[keyBuff, certBuff, caArrDataView],
125+
[keyBuff, certBuff, false],
126+
].map((params) => {
127+
assert.doesNotThrow(() => {
128+
tls.createServer({
129+
key: params[0],
130+
cert: params[1],
131+
ca: params[2]
132+
});
133+
});
134+
});
135+
136+
// Checks to ensure tls.createServer throws an error for CA assignment
137+
// Format ['key', 'cert', 'ca']
138+
[
139+
[keyBuff, certBuff, true],
140+
[keyBuff, certBuff, {}],
141+
[keyBuff, certBuff, 1],
142+
[keyBuff, certBuff, true],
143+
[keyBuff, certBuff, [caCert, true]]
144+
].map((params) => {
145+
assert.throws(() => {
146+
tls.createServer({
147+
key: params[0],
148+
cert: params[1],
149+
ca: params[2]
150+
});
151+
}, common.expectsError({
152+
code: 'ERR_INVALID_ARG_TYPE',
153+
type: TypeError,
154+
message: /^The "ca" argument must be one of type string, Buffer, TypedArray, or DataView$/
155+
}));
156+
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.