Browse Source

tls: add getProtocol() to TLS sockets

This commit adds a new method for TLS sockets that returns the
negotiated protocol version.

PR-URL: https://github.com/nodejs/node/pull/4995
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
process-exit-stdio-flushing
Brian White 9 years ago
parent
commit
2c357a7e3b
  1. 18
      doc/api/tls.markdown
  2. 7
      lib/_tls_wrap.js
  3. 10
      src/node_crypto.cc
  4. 1
      src/node_crypto.h
  5. 43
      test/parallel/test-tls-getprotocol.js

18
doc/api/tls.markdown

@ -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()

7
lib/_tls_wrap.js

@ -649,6 +649,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

10
src/node_crypto.cc

@ -1192,6 +1192,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);
@ -1954,6 +1955,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,

1
src/node_crypto.h

@ -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(

43
test/parallel/test-tls-getprotocol.js

@ -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();
}));
});
});
Loading…
Cancel
Save