Skip to content

Commit fd0de18

Browse files
committed
tls: Test rollback and Update getCACertificates()
1 parent 319841f commit fd0de18

File tree

4 files changed

+72
-94
lines changed

4 files changed

+72
-94
lines changed

lib/tls.js

Lines changed: 47 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -168,38 +168,57 @@ function cacheDefaultCACertificates() {
168168
return defaultCACertificates;
169169
}
170170

171-
const certificateCache = { __proto__: null };
172-
173-
function getCACertificates(options = {}) {
174-
if (typeof options === 'string') {
175-
options = { type: options };
176-
} else if (typeof options !== 'object' || options === null) {
177-
throw new ERR_INVALID_ARG_TYPE('options', ['string', 'object'], options);
178-
}
179-
180-
const {
181-
type = 'default',
182-
format = 'pem',
183-
} = options;
184-
185-
validateString(type, 'type');
186-
validateOneOf(format, 'format', ['pem', 'der', 'x509', 'string', 'buffer']);
187-
188-
let effectiveFormat = format;
189-
if (format === 'string') {
190-
effectiveFormat = 'pem';
191-
} else if (format === 'buffer') {
192-
effectiveFormat = 'der';
193-
}
171+
function getCACertificates(options = undefined) {
172+
if (typeof options === 'string' || options === undefined) {
173+
const type = (typeof options === 'string') ? options : 'default';
174+
175+
validateString(type, 'type');
176+
177+
switch (type) {
178+
case 'default': return cacheDefaultCACertificates();
179+
case 'bundled': return cacheBundledRootCertificates();
180+
case 'system': return cacheSystemCACertificates();
181+
case 'extra': return cacheExtraCACertificates();
182+
default: throw new ERR_INVALID_ARG_VALUE('type', type);
183+
}
184+
} else if (typeof options === 'object' && options !== null) {
185+
const {
186+
type = 'default',
187+
format = 'pem',
188+
} = options;
189+
190+
validateString(type, 'type');
191+
validateOneOf(format, 'format', ['pem', 'der', 'x509', 'string', 'buffer']);
192+
193+
let effectiveFormat = format;
194+
if (format === 'string') {
195+
effectiveFormat = 'pem';
196+
} else if (format === 'buffer') {
197+
effectiveFormat = 'der';
198+
}
194199

195-
if (certificateCache[type]) {
196-
const cachedCerts = certificateCache[type];
200+
let certs;
201+
switch (type) {
202+
case 'default': certs = cacheDefaultCACertificates(); break;
203+
case 'bundled': certs = cacheBundledRootCertificates(); break;
204+
case 'system': certs = cacheSystemCACertificates(); break;
205+
case 'extra': certs = cacheExtraCACertificates(); break;
206+
default: throw new ERR_INVALID_ARG_VALUE('type', type);
207+
}
197208

198209
if (effectiveFormat === 'pem') {
199-
return cachedCerts;
210+
return certs.map((cert) => {
211+
if (typeof cert === 'string') {
212+
return cert;
213+
}
214+
return `-----BEGIN CERTIFICATE-----\n${cert.toString('base64').match(/.{1,64}/g).join('\n')}\n-----END CERTIFICATE-----`;
215+
});
200216
}
201217

202-
const buffers = cachedCerts.map((cert) => {
218+
const buffers = certs.map((cert) => {
219+
if (Buffer.isBuffer(cert)) {
220+
return cert;
221+
}
203222
const base64 = cert.replace(/(?:\s|-----BEGIN CERTIFICATE-----|-----END CERTIFICATE-----)+/g, '');
204223
return Buffer.from(base64, 'base64');
205224
});
@@ -211,37 +230,7 @@ function getCACertificates(options = {}) {
211230
return buffers.map((buf) => new X509Certificate(buf));
212231
}
213232

214-
let certs;
215-
switch (type) {
216-
case 'default': certs = cacheDefaultCACertificates(); break;
217-
case 'bundled': certs = cacheBundledRootCertificates(); break;
218-
case 'system': certs = cacheSystemCACertificates(); break;
219-
case 'extra': certs = cacheExtraCACertificates(); break;
220-
default: throw new ERR_INVALID_ARG_VALUE('type', type);
221-
}
222-
223-
const pemCerts = certs.map((cert) => {
224-
if (typeof cert === 'string') {
225-
return cert;
226-
}
227-
return `-----BEGIN CERTIFICATE-----\n${cert.toString('base64').match(/.{1,64}/g).join('\n')}\n-----END CERTIFICATE-----`;
228-
});
229-
certificateCache[type] = pemCerts;
230-
231-
if (effectiveFormat === 'pem') {
232-
return pemCerts;
233-
}
234-
235-
const derBuffers = pemCerts.map((cert) => {
236-
const base64 = cert.replace(/(?:\s|-----BEGIN CERTIFICATE-----|-----END CERTIFICATE-----)+/g, '');
237-
return Buffer.from(base64, 'base64');
238-
});
239-
240-
if (effectiveFormat === 'der') {
241-
return derBuffers;
242-
}
243-
244-
return derBuffers.map((buf) => new X509Certificate(buf));
233+
throw new ERR_INVALID_ARG_TYPE('options', ['string', 'object'], options);
245234
}
246235

247236
exports.getCACertificates = getCACertificates;
Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
2-
// Test that tls.getCACertificates() returns the bundled certificates correctly.
2+
// This tests that tls.getCACertificates() returns the bundled
3+
// certificates correctly.
34

45
const common = require('../common');
56
if (!common.hasCrypto) common.skip('missing crypto');
@@ -9,15 +10,11 @@ const tls = require('tls');
910
const { assertIsCAArray } = require('../common/tls');
1011

1112
const certs = tls.getCACertificates('bundled');
12-
assert.deepStrictEqual(certs, tls.getCACertificates({ type: 'bundled' }));
1313
assertIsCAArray(certs);
1414

15-
assert.deepStrictEqual(certs, tls.rootCertificates);
15+
// It's the same as tls.rootCertificates - both are
16+
// Mozilla CA stores across platform.
17+
assert.strictEqual(certs, tls.rootCertificates);
1618

17-
assert.deepStrictEqual(certs, tls.getCACertificates({ type: 'bundled', format: 'string' }));
18-
19-
const certs2 = tls.getCACertificates('bundled');
20-
assertIsCAArray(certs2);
21-
22-
assert.deepStrictEqual(certs2, tls.rootCertificates);
23-
assert.strictEqual(certs, tls.getCACertificates({ type: 'bundled', format: 'string' }));
19+
// It's cached on subsequent accesses.
20+
assert.strictEqual(certs, tls.getCACertificates('bundled'));
Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
2-
// Test that tls.getCACertificates() returns the default certificates correctly.
2+
3+
// This tests that tls.getCACertificates() returns the default
4+
// certificates correctly.
35

46
const common = require('../common');
57
if (!common.hasCrypto) common.skip('missing crypto');
@@ -8,16 +10,8 @@ const assert = require('assert');
810
const tls = require('tls');
911
const { assertIsCAArray } = require('../common/tls');
1012

11-
const certs = tls.getCACertificates({ format: 'string' });
13+
const certs = tls.getCACertificates();
1214
assertIsCAArray(certs);
1315

14-
const certs2 = tls.getCACertificates({ type: 'default', format: 'string' });
15-
assert.deepStrictEqual(certs, certs2);
16-
17-
assert.deepStrictEqual(certs, tls.getCACertificates({ type: 'default', format: 'string' }));
18-
19-
const certs3 = tls.getCACertificates('default');
20-
assertIsCAArray(certs3);
21-
22-
assert.deepStrictEqual(certs3, tls.rootCertificates);
23-
assert.strictEqual(certs2, tls.getCACertificates({ type: 'default', format: 'string' }));
16+
// It's cached on subsequent accesses.
17+
assert.strictEqual(certs, tls.getCACertificates('default'));
Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22
// Flags: --use-system-ca
3-
// Test that tls.getCACertificates() returns system certificates correctly.
3+
// This tests that tls.getCACertificates() returns the system
4+
// certificates correctly.
45

56
const common = require('../common');
67
if (!common.hasCrypto) common.skip('missing crypto');
@@ -9,26 +10,23 @@ const assert = require('assert');
910
const tls = require('tls');
1011
const { assertIsCAArray } = require('../common/tls');
1112

12-
const systemCerts = tls.getCACertificates({ type: 'system', format: 'string' });
13-
13+
const systemCerts = tls.getCACertificates('system');
14+
// Usually Windows come with some certificates installed by default.
15+
// This can't be said about other systems, in that case check that
16+
// at least systemCerts is an array (which may be empty).
1417
if (common.isWindows) {
1518
assertIsCAArray(systemCerts);
1619
} else {
1720
assert(Array.isArray(systemCerts));
1821
}
1922

20-
const defaultCerts = tls.getCACertificates({ format: 'string' });
23+
// When --use-system-ca is true, default is a superset of system
24+
// certificates.
25+
const defaultCerts = tls.getCACertificates('default');
2126
assert(defaultCerts.length >= systemCerts.length);
2227
const defaultSet = new Set(defaultCerts);
2328
const systemSet = new Set(systemCerts);
24-
for (const cert of systemSet) {
25-
assert(defaultSet.has(cert));
26-
}
27-
28-
assert.deepStrictEqual(systemCerts, tls.getCACertificates({ type: 'system', format: 'string' }));
29-
30-
const certs = tls.getCACertificates('bundled');
31-
assertIsCAArray(certs);
29+
assert.deepStrictEqual(defaultSet.intersection(systemSet), systemSet);
3230

33-
assert.deepStrictEqual(certs, tls.rootCertificates);
34-
assert.strictEqual(systemCerts, tls.getCACertificates({ type: 'system', format: 'string' }));
31+
// It's cached on subsequent accesses.
32+
assert.strictEqual(systemCerts, tls.getCACertificates('system'));

0 commit comments

Comments
 (0)