Skip to content

Commit

Permalink
tls: add getProtocol() to TLS sockets
Browse files Browse the repository at this point in the history
This commit adds a new method for TLS sockets that returns the
negotiated protocol version.

PR-URL: #4995
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
mscdex authored and rvagg committed Feb 9, 2016
1 parent b4db318 commit c3f8aab
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 0 deletions.
18 changes: 18 additions & 0 deletions doc/api/tls.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,24 @@ Example:
If the peer does not provide a certificate, it returns `null` or an empty
object.

### tlsSocket.getProtocol()

Returns a string containing the negotiated SSL/TLS protocol version of the
current connection. `'unknown'` will be returned for connected sockets that have
not completed the handshaking process. `null` will be returned for server
sockets or disconnected client sockets.

Examples:
```
'SSLv3'
'TLSv1'
'TLSv1.1'
'TLSv1.2'
'unknown'
```

See https://www.openssl.org/docs/manmaster/ssl/SSL_get_version.html for more
information.

### tlsSocket.getSession()

Expand Down
7 changes: 7 additions & 0 deletions lib/_tls_wrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,13 @@ TLSSocket.prototype.getEphemeralKeyInfo = function() {
return null;
};

TLSSocket.prototype.getProtocol = function() {
if (this._handle)
return this._handle.getProtocol();

return null;
};

// TODO: support anonymous (nocert) and PSK


Expand Down
10 changes: 10 additions & 0 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,7 @@ void SSLWrap<Base>::AddMethods(Environment* env, Local<FunctionTemplate> t) {
env->SetProtoMethod(t, "setOCSPResponse", SetOCSPResponse);
env->SetProtoMethod(t, "requestOCSP", RequestOCSP);
env->SetProtoMethod(t, "getEphemeralKeyInfo", GetEphemeralKeyInfo);
env->SetProtoMethod(t, "getProtocol", GetProtocol);

#ifdef SSL_set_max_send_fragment
env->SetProtoMethod(t, "setMaxSendFragment", SetMaxSendFragment);
Expand Down Expand Up @@ -1965,6 +1966,15 @@ void SSLWrap<Base>::GetCurrentCipher(const FunctionCallbackInfo<Value>& args) {
}


template <class Base>
void SSLWrap<Base>::GetProtocol(const FunctionCallbackInfo<Value>& args) {
Base* w = Unwrap<Base>(args.Holder());

const char* tls_version = SSL_get_version(w->ssl_);
args.GetReturnValue().Set(OneByteString(args.GetIsolate(), tls_version));
}


#ifdef OPENSSL_NPN_NEGOTIATED
template <class Base>
int SSLWrap<Base>::AdvertiseNextProtoCallback(SSL* s,
Expand Down
1 change: 1 addition & 0 deletions src/node_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ class SSLWrap {
static void RequestOCSP(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetEphemeralKeyInfo(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetProtocol(const v8::FunctionCallbackInfo<v8::Value>& args);

#ifdef SSL_set_max_send_fragment
static void SetMaxSendFragment(
Expand Down
43 changes: 43 additions & 0 deletions test/parallel/test-tls-getprotocol.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';
const common = require('../common');
const assert = require('assert');

if (!common.hasCrypto) {
console.log('1..0 # Skipped: missing crypto');
return;
}

const tls = require('tls');
const fs = require('fs');

const clientConfigs = [
{ secureProtocol: 'TLSv1_method', version: 'TLSv1' },
{ secureProtocol: 'TLSv1_1_method', version: 'TLSv1.1' },
{ secureProtocol: 'TLSv1_2_method', version: 'TLSv1.2' }
];

const serverConfig = {
key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'),
cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem')
};

const server = tls.createServer(serverConfig, common.mustCall(function() {

}, clientConfigs.length)).listen(common.PORT, common.localhostIPv4, function() {
let connected = 0;
clientConfigs.forEach(function(v) {
tls.connect({
host: common.localhostIPv4,
port: common.PORT,
rejectUnauthorized: false,
secureProtocol: v.secureProtocol
}, common.mustCall(function() {
assert.strictEqual(this.getProtocol(), v.version);
this.on('end', common.mustCall(function() {
assert.strictEqual(this.getProtocol(), null);
})).end();
if (++connected === clientConfigs.length)
server.close();
}));
});
});

0 comments on commit c3f8aab

Please sign in to comment.