Skip to content

Commit d4c3ac0

Browse files
committed
tls: Test rollback and Update getCACertificates()
1 parent 651a42d commit d4c3ac0

4 files changed

Lines changed: 72 additions & 94 deletions

File tree

lib/tls.js

Lines changed: 47 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -184,38 +184,57 @@ function cacheDefaultCACertificates() {
184184
return defaultCACertificates;
185185
}
186186

187-
const certificateCache = { __proto__: null };
188-
189-
function getCACertificates(options = {}) {
190-
if (typeof options === 'string') {
191-
options = { type: options };
192-
} else if (typeof options !== 'object' || options === null) {
193-
throw new ERR_INVALID_ARG_TYPE('options', ['string', 'object'], options);
194-
}
195-
196-
const {
197-
type = 'default',
198-
format = 'pem',
199-
} = options;
200-
201-
validateString(type, 'type');
202-
validateOneOf(format, 'format', ['pem', 'der', 'x509', 'string', 'buffer']);
203-
204-
let effectiveFormat = format;
205-
if (format === 'string') {
206-
effectiveFormat = 'pem';
207-
} else if (format === 'buffer') {
208-
effectiveFormat = 'der';
209-
}
187+
function getCACertificates(options = undefined) {
188+
if (typeof options === 'string' || options === undefined) {
189+
const type = (typeof options === 'string') ? options : 'default';
190+
191+
validateString(type, 'type');
192+
193+
switch (type) {
194+
case 'default': return cacheDefaultCACertificates();
195+
case 'bundled': return cacheBundledRootCertificates();
196+
case 'system': return cacheSystemCACertificates();
197+
case 'extra': return cacheExtraCACertificates();
198+
default: throw new ERR_INVALID_ARG_VALUE('type', type);
199+
}
200+
} else if (typeof options === 'object' && options !== null) {
201+
const {
202+
type = 'default',
203+
format = 'pem',
204+
} = options;
205+
206+
validateString(type, 'type');
207+
validateOneOf(format, 'format', ['pem', 'der', 'x509', 'string', 'buffer']);
208+
209+
let effectiveFormat = format;
210+
if (format === 'string') {
211+
effectiveFormat = 'pem';
212+
} else if (format === 'buffer') {
213+
effectiveFormat = 'der';
214+
}
210215

211-
if (certificateCache[type]) {
212-
const cachedCerts = certificateCache[type];
216+
let certs;
217+
switch (type) {
218+
case 'default': certs = cacheDefaultCACertificates(); break;
219+
case 'bundled': certs = cacheBundledRootCertificates(); break;
220+
case 'system': certs = cacheSystemCACertificates(); break;
221+
case 'extra': certs = cacheExtraCACertificates(); break;
222+
default: throw new ERR_INVALID_ARG_VALUE('type', type);
223+
}
213224

214225
if (effectiveFormat === 'pem') {
215-
return cachedCerts;
226+
return certs.map((cert) => {
227+
if (typeof cert === 'string') {
228+
return cert;
229+
}
230+
return `-----BEGIN CERTIFICATE-----\n${cert.toString('base64').match(/.{1,64}/g).join('\n')}\n-----END CERTIFICATE-----`;
231+
});
216232
}
217233

218-
const buffers = cachedCerts.map((cert) => {
234+
const buffers = certs.map((cert) => {
235+
if (Buffer.isBuffer(cert)) {
236+
return cert;
237+
}
219238
const base64 = cert.replace(/(?:\s|-----BEGIN CERTIFICATE-----|-----END CERTIFICATE-----)+/g, '');
220239
return Buffer.from(base64, 'base64');
221240
});
@@ -227,37 +246,7 @@ function getCACertificates(options = {}) {
227246
return buffers.map((buf) => new X509Certificate(buf));
228247
}
229248

230-
let certs;
231-
switch (type) {
232-
case 'default': certs = cacheDefaultCACertificates(); break;
233-
case 'bundled': certs = cacheBundledRootCertificates(); break;
234-
case 'system': certs = cacheSystemCACertificates(); break;
235-
case 'extra': certs = cacheExtraCACertificates(); break;
236-
default: throw new ERR_INVALID_ARG_VALUE('type', type);
237-
}
238-
239-
const pemCerts = certs.map((cert) => {
240-
if (typeof cert === 'string') {
241-
return cert;
242-
}
243-
return `-----BEGIN CERTIFICATE-----\n${cert.toString('base64').match(/.{1,64}/g).join('\n')}\n-----END CERTIFICATE-----`;
244-
});
245-
certificateCache[type] = pemCerts;
246-
247-
if (effectiveFormat === 'pem') {
248-
return pemCerts;
249-
}
250-
251-
const derBuffers = pemCerts.map((cert) => {
252-
const base64 = cert.replace(/(?:\s|-----BEGIN CERTIFICATE-----|-----END CERTIFICATE-----)+/g, '');
253-
return Buffer.from(base64, 'base64');
254-
});
255-
256-
if (effectiveFormat === 'der') {
257-
return derBuffers;
258-
}
259-
260-
return derBuffers.map((buf) => new X509Certificate(buf));
249+
throw new ERR_INVALID_ARG_TYPE('options', ['string', 'object'], options);
261250
}
262251

263252
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)