feat: add disabledCipherSuites option to setSSLConfig (#25818)
This commit is contained in:
parent
f6a27973d1
commit
22cb3cd18b
3 changed files with 85 additions and 4 deletions
|
@ -574,11 +574,20 @@ Returns `String` - The user agent for this session.
|
|||
#### `ses.setSSLConfig(config)`
|
||||
|
||||
* `config` Object
|
||||
* `minVersion` String - Can be `tls1`, `tls1.1`, `tls1.2` or `tls1.3`. The
|
||||
* `minVersion` String (optional) - Can be `tls1`, `tls1.1`, `tls1.2` or `tls1.3`. The
|
||||
minimum SSL version to allow when connecting to remote servers. Defaults to
|
||||
`tls1`.
|
||||
* `maxVersion` String - Can be `tls1.2` or `tls1.3`. The maximum SSL version
|
||||
* `maxVersion` String (optional) - Can be `tls1.2` or `tls1.3`. The maximum SSL version
|
||||
to allow when connecting to remote servers. Defaults to `tls1.3`.
|
||||
* `disabledCipherSuites` Integer[] (optional) - List of cipher suites which
|
||||
should be explicitly prevented from being used in addition to those
|
||||
disabled by the net built-in policy.
|
||||
Supported literal forms: 0xAABB, where AA is `cipher_suite[0]` and BB is
|
||||
`cipher_suite[1]`, as defined in RFC 2246, Section 7.4.1.2. Unrecognized but
|
||||
parsable cipher suites in this form will not return an error.
|
||||
Ex: To disable TLS_RSA_WITH_RC4_128_MD5, specify 0x0004, while to
|
||||
disable TLS_ECDH_ECDSA_WITH_RC4_128_SHA, specify 0xC002.
|
||||
Note that TLSv1.3 ciphers cannot be disabled using this mechanism.
|
||||
|
||||
Sets the SSL configuration for the session. All subsequent network requests
|
||||
will use the new configuration. Existing network connections (such as WebSocket
|
||||
|
|
|
@ -202,6 +202,19 @@ bool SSLProtocolVersionFromString(const std::string& version_str,
|
|||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
struct Converter<uint16_t> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
uint16_t* out) {
|
||||
auto maybe = val->IntegerValue(isolate->GetCurrentContext());
|
||||
if (maybe.IsNothing())
|
||||
return false;
|
||||
*out = maybe.FromJust();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<network::mojom::SSLConfigPtr> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
|
@ -224,8 +237,14 @@ struct Converter<network::mojom::SSLConfigPtr> {
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO(nornagon): also support client_cert_pooling_policy and
|
||||
// disabled_cipher_suites. Maybe other SSLConfig properties too?
|
||||
if (options.Has("disabledCipherSuites") &&
|
||||
!options.Get("disabledCipherSuites", &(*out)->disabled_cipher_suites)) {
|
||||
return false;
|
||||
}
|
||||
std::sort((*out)->disabled_cipher_suites.begin(),
|
||||
(*out)->disabled_cipher_suites.end());
|
||||
|
||||
// TODO(nornagon): also support other SSLConfig properties?
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@ import * as send from 'send';
|
|||
import * as auth from 'basic-auth';
|
||||
import { closeAllWindows } from './window-helpers';
|
||||
import { emittedOnce } from './events-helpers';
|
||||
import { defer } from './spec-helpers';
|
||||
import { AddressInfo } from 'net';
|
||||
|
||||
/* The whole session API doesn't use standard callbacks */
|
||||
|
@ -985,4 +986,56 @@ describe('session module', () => {
|
|||
expect(session1).to.equal(session2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ses.setSSLConfig()', () => {
|
||||
it('can disable cipher suites', async () => {
|
||||
const ses = session.fromPartition('' + Math.random());
|
||||
const fixturesPath = path.resolve(__dirname, '..', 'spec', 'fixtures');
|
||||
const certPath = path.join(fixturesPath, 'certificates');
|
||||
const server = https.createServer({
|
||||
key: fs.readFileSync(path.join(certPath, 'server.key')),
|
||||
cert: fs.readFileSync(path.join(certPath, 'server.pem')),
|
||||
ca: [
|
||||
fs.readFileSync(path.join(certPath, 'rootCA.pem')),
|
||||
fs.readFileSync(path.join(certPath, 'intermediateCA.pem'))
|
||||
],
|
||||
minVersion: 'TLSv1.2',
|
||||
maxVersion: 'TLSv1.2',
|
||||
ciphers: 'AES128-GCM-SHA256'
|
||||
}, (req, res) => {
|
||||
res.end('hi');
|
||||
});
|
||||
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
|
||||
defer(() => server.close());
|
||||
const { port } = server.address() as AddressInfo;
|
||||
|
||||
function request () {
|
||||
return new Promise((resolve, reject) => {
|
||||
const r = net.request({
|
||||
url: `https://127.0.0.1:${port}`,
|
||||
session: ses
|
||||
});
|
||||
r.on('response', (res) => {
|
||||
let data = '';
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk.toString('utf8');
|
||||
});
|
||||
res.on('end', () => {
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
r.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
r.end();
|
||||
});
|
||||
}
|
||||
|
||||
await expect(request()).to.be.rejectedWith(/ERR_CERT_AUTHORITY_INVALID/);
|
||||
ses.setSSLConfig({
|
||||
disabledCipherSuites: [0x009C]
|
||||
});
|
||||
await expect(request()).to.be.rejectedWith(/ERR_SSL_VERSION_OR_CIPHER_MISMATCH/);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue