Skip to content

Commit 0f745bf

Browse files
sam-githubdanbev
authored andcommitted
tls: return correct version from getCipher()
OpenSSL 1.0.0 returned incorrect version information. OpenSSL 1.1.0 fixed this, but returning the correct information broke our tests, so was considered semver-major. Because of this, the version was hard-coded to the OpenSSL 1.0.0 (incorrect) string in 5fe81c8. This is ancient history, start returning the correct cipher version. PR-URL: #26625 Reviewed-By: Daniel Bevenius <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Richard Lau <[email protected]> Reviewed-By: Colin Ihrig <[email protected]>
1 parent 1ceb6d8 commit 0f745bf

7 files changed

+54
-32
lines changed

doc/api/tls.md

+12-5
Original file line numberDiff line numberDiff line change
@@ -717,18 +717,25 @@ socket has been destroyed, `null` will be returned.
717717
### tlsSocket.getCipher()
718718
<!-- YAML
719719
added: v0.11.4
720+
changes:
721+
- version: REPLACEME
722+
pr-url: https://github.com/nodejs/node/pull/26625
723+
description: Return the minimum cipher version, instead of a fixed string
724+
(`'TLSv1/SSLv3'`).
720725
-->
721726

722727
* Returns: {Object}
728+
* `name` {string} The name of the cipher suite.
729+
* `version` {string} The minimum TLS protocol version supported by this cipher
730+
suite.
723731

724-
Returns an object representing the cipher name. The `version` key is a legacy
725-
field which always contains the value `'TLSv1/SSLv3'`.
732+
Returns an object containing information on the negotiated cipher suite.
726733

727734
For example: `{ name: 'AES256-SHA', version: 'TLSv1/SSLv3' }`.
728735

729-
See `SSL_CIPHER_get_name()` in
730-
<https://www.openssl.org/docs/man1.1.0/ssl/SSL_CIPHER_get_name.html> for more
731-
information.
736+
See
737+
[OpenSSL](https://www.openssl.org/docs/man1.1.1/man3/SSL_CIPHER_get_name.html)
738+
for more information.
732739

733740
### tlsSocket.getEphemeralKeyInfo()
734741
<!-- YAML

lib/_tls_wrap.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -737,18 +737,18 @@ function makeSocketMethodProxy(name) {
737737
}
738738

739739
[
740-
'getFinished', 'getPeerFinished', 'getSession', 'isSessionReused',
741-
'getEphemeralKeyInfo', 'getProtocol', 'getTLSTicket'
740+
'getCipher',
741+
'getEphemeralKeyInfo',
742+
'getFinished',
743+
'getPeerFinished',
744+
'getProtocol',
745+
'getSession',
746+
'getTLSTicket',
747+
'isSessionReused',
742748
].forEach((method) => {
743749
TLSSocket.prototype[method] = makeSocketMethodProxy(method);
744750
});
745751

746-
TLSSocket.prototype.getCipher = function(err) {
747-
if (this._handle)
748-
return this._handle.getCurrentCipher();
749-
return null;
750-
};
751-
752752
// TODO: support anonymous (nocert) and PSK
753753

754754

src/node_crypto.cc

+4-3
Original file line numberDiff line numberDiff line change
@@ -1464,7 +1464,7 @@ void SSLWrap<Base>::AddMethods(Environment* env, Local<FunctionTemplate> t) {
14641464
env->SetProtoMethod(t, "loadSession", LoadSession);
14651465
env->SetProtoMethodNoSideEffect(t, "isSessionReused", IsSessionReused);
14661466
env->SetProtoMethodNoSideEffect(t, "verifyError", VerifyError);
1467-
env->SetProtoMethodNoSideEffect(t, "getCurrentCipher", GetCurrentCipher);
1467+
env->SetProtoMethodNoSideEffect(t, "getCipher", GetCipher);
14681468
env->SetProtoMethod(t, "endParser", EndParser);
14691469
env->SetProtoMethod(t, "certCbDone", CertCbDone);
14701470
env->SetProtoMethod(t, "renegotiate", Renegotiate);
@@ -2357,7 +2357,7 @@ void SSLWrap<Base>::VerifyError(const FunctionCallbackInfo<Value>& args) {
23572357

23582358

23592359
template <class Base>
2360-
void SSLWrap<Base>::GetCurrentCipher(const FunctionCallbackInfo<Value>& args) {
2360+
void SSLWrap<Base>::GetCipher(const FunctionCallbackInfo<Value>& args) {
23612361
Base* w;
23622362
ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
23632363
Environment* env = w->ssl_env();
@@ -2371,8 +2371,9 @@ void SSLWrap<Base>::GetCurrentCipher(const FunctionCallbackInfo<Value>& args) {
23712371
const char* cipher_name = SSL_CIPHER_get_name(c);
23722372
info->Set(context, env->name_string(),
23732373
OneByteString(args.GetIsolate(), cipher_name)).FromJust();
2374+
const char* cipher_version = SSL_CIPHER_get_version(c);
23742375
info->Set(context, env->version_string(),
2375-
OneByteString(args.GetIsolate(), "TLSv1/SSLv3")).FromJust();
2376+
OneByteString(args.GetIsolate(), cipher_version)).FromJust();
23762377
args.GetReturnValue().Set(info);
23772378
}
23782379

src/node_crypto.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ class SSLWrap {
281281
static void LoadSession(const v8::FunctionCallbackInfo<v8::Value>& args);
282282
static void IsSessionReused(const v8::FunctionCallbackInfo<v8::Value>& args);
283283
static void VerifyError(const v8::FunctionCallbackInfo<v8::Value>& args);
284-
static void GetCurrentCipher(const v8::FunctionCallbackInfo<v8::Value>& args);
284+
static void GetCipher(const v8::FunctionCallbackInfo<v8::Value>& args);
285285
static void EndParser(const v8::FunctionCallbackInfo<v8::Value>& args);
286286
static void CertCbDone(const v8::FunctionCallbackInfo<v8::Value>& args);
287287
static void Renegotiate(const v8::FunctionCallbackInfo<v8::Value>& args);

test/parallel/test-tls-getcipher.js

+25-11
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,42 @@ const tls = require('tls');
3030
// Import fixtures directly from its module
3131
const fixtures = require('../common/fixtures');
3232

33-
const cipher_list = ['AES128-SHA256', 'AES256-SHA256'];
34-
const cipher_version_pattern = /TLS|SSL/;
3533
const options = {
3634
key: fixtures.readKey('agent2-key.pem'),
3735
cert: fixtures.readKey('agent2-cert.pem'),
38-
ciphers: cipher_list.join(':'),
3936
honorCipherOrder: true
4037
};
4138

42-
const server = tls.createServer(options, common.mustCall());
39+
let clients = 0;
40+
const server = tls.createServer(options, common.mustCall(() => {
41+
if (--clients === 0)
42+
server.close();
43+
}, 2));
4344

4445
server.listen(0, '127.0.0.1', common.mustCall(function() {
45-
const client = tls.connect({
46+
clients++;
47+
tls.connect({
4648
host: '127.0.0.1',
4749
port: this.address().port,
48-
ciphers: cipher_list.join(':'),
50+
ciphers: 'AES128-SHA256',
4951
rejectUnauthorized: false
5052
}, common.mustCall(function() {
51-
const cipher = client.getCipher();
52-
assert.strictEqual(cipher.name, cipher_list[0]);
53-
assert(cipher_version_pattern.test(cipher.version));
54-
client.end();
55-
server.close();
53+
const cipher = this.getCipher();
54+
assert.strictEqual(cipher.name, 'AES128-SHA256');
55+
assert.strictEqual(cipher.version, 'TLSv1.2');
56+
this.end();
57+
}));
58+
59+
clients++;
60+
tls.connect({
61+
host: '127.0.0.1',
62+
port: this.address().port,
63+
cipher: 'ECDHE-RSA-AES128-GCM-SHA256',
64+
rejectUnauthorized: false
65+
}, common.mustCall(function() {
66+
const cipher = this.getCipher();
67+
assert.strictEqual(cipher.name, 'ECDHE-RSA-AES128-GCM-SHA256');
68+
assert.strictEqual(cipher.version, 'TLSv1.2');
69+
this.end();
5670
}));
5771
}));

test/parallel/test-tls-multi-key.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ function test(options) {
157157
}, common.mustCall(function() {
158158
assert.deepStrictEqual(ecdsa.getCipher(), {
159159
name: 'ECDHE-ECDSA-AES256-GCM-SHA384',
160-
version: 'TLSv1/SSLv3'
160+
version: 'TLSv1.2'
161161
});
162162
assert.strictEqual(ecdsa.getPeerCertificate().subject.CN, eccCN);
163163
// XXX(sam) certs don't currently include EC key info, so depend on
@@ -177,7 +177,7 @@ function test(options) {
177177
}, common.mustCall(function() {
178178
assert.deepStrictEqual(rsa.getCipher(), {
179179
name: 'ECDHE-RSA-AES256-GCM-SHA384',
180-
version: 'TLSv1/SSLv3'
180+
version: 'TLSv1.2'
181181
});
182182
assert.strictEqual(rsa.getPeerCertificate().subject.CN, rsaCN);
183183
assert(rsa.getPeerCertificate().exponent, 'cert for an RSA key');

test/parallel/test-tls-multi-pfx.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ const server = tls.createServer(options, function(conn) {
4242
process.on('exit', function() {
4343
assert.deepStrictEqual(ciphers, [{
4444
name: 'ECDHE-ECDSA-AES256-GCM-SHA384',
45-
version: 'TLSv1/SSLv3'
45+
version: 'TLSv1.2'
4646
}, {
4747
name: 'ECDHE-RSA-AES256-GCM-SHA384',
48-
version: 'TLSv1/SSLv3'
48+
version: 'TLSv1.2'
4949
}]);
5050
});

0 commit comments

Comments
 (0)