Browse Source

tls: add `getTicketKeys()`/`setTicketKeys()`

Introduce two new APIs for getting/settings the TLS Server Ticket Keys.

Fix: #1465
PR-URL: https://github.com/nodejs/io.js/pull/2227
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
v4.0.0-rc
Fedor Indutny 9 years ago
parent
commit
e11fc67225
  1. 16
      doc/api/tls.markdown
  2. 14
      lib/_tls_wrap.js
  3. 34
      test/parallel/test-tls-ticket.js

16
doc/api/tls.markdown

@ -630,6 +630,21 @@ Returns the bound address, the address family name and port of the
server as reported by the operating system. See [net.Server.address()][] for
more information.
### server.getTicketKeys()
Returns `Buffer` instance holding the keys currently used for
encryption/decryption of the [TLS Session Tickets][]
### server.setTicketKeys(keys)
Updates the keys for encryption/decryption of the [TLS Session Tickets][].
NOTE: the buffer should be 48 bytes long. See server `ticketKeys` option for
more information oh how it is going to be used.
NOTE: the change is effective only for the future server connections. Existing
or currently pending server connections will use previous keys.
### server.addContext(hostname, context)
Add secure context that will be used if client request's SNI hostname is
@ -835,3 +850,4 @@ The numeric representation of the local port.
[asn1.js]: http://npmjs.org/package/asn1.js
[OCSP request]: http://en.wikipedia.org/wiki/OCSP_stapling
[TLS recommendations]: https://wiki.mozilla.org/Security/Server_Side_TLS
[TLS Session Tickets]: https://www.ietf.org/rfc/rfc5077.txt

14
lib/_tls_wrap.js

@ -812,13 +812,23 @@ exports.createServer = function(options, listener) {
Server.prototype._getServerData = function() {
return {
ticketKeys: this._sharedCreds.context.getTicketKeys().toString('hex')
ticketKeys: this.getTicketKeys().toString('hex')
};
};
Server.prototype._setServerData = function(data) {
this._sharedCreds.context.setTicketKeys(new Buffer(data.ticketKeys, 'hex'));
this.setTicketKeys(new Buffer(data.ticketKeys, 'hex'));
};
Server.prototype.getTicketKeys = function getTicketKeys(keys) {
return this._sharedCreds.context.getTicketKeys(keys);
};
Server.prototype.setTicketKeys = function setTicketKeys(keys) {
this._sharedCreds.context.setTicketKeys(keys);
};

34
test/parallel/test-tls-ticket.js

@ -20,6 +20,9 @@ var serverCount = 0;
function createServer() {
var id = serverCount++;
var counter = 0;
var previousKey = null;
var server = tls.createServer({
key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'),
cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem'),
@ -27,14 +30,29 @@ function createServer() {
}, function(c) {
serverLog.push(id);
c.end();
counter++;
// Rotate ticket keys
if (counter === 1) {
previousKey = server.getTicketKeys();
server.setTicketKeys(crypto.randomBytes(48));
} else if (counter === 2) {
server.setTicketKeys(previousKey);
} else if (counter === 3) {
// Use keys from counter=2
} else {
throw new Error('UNREACHABLE');
}
});
return server;
}
var servers = [ createServer(), createServer(),
createServer(), createServer(),
createServer(), createServer() ];
var naturalServers = [ createServer(), createServer(), createServer() ];
// 3x servers
var servers = naturalServers.concat(naturalServers).concat(naturalServers);
// Create one TCP server and balance sockets to multiple TLS server instances
var shared = net.createServer(function(c) {
@ -54,7 +72,7 @@ function start(callback) {
session: sess,
rejectUnauthorized: false
}, function() {
sess = s.getSession() || sess;
sess = sess || s.getSession();
ticketLog.push(s.getTLSTicket().toString('hex'));
});
s.on('close', function() {
@ -70,8 +88,14 @@ function start(callback) {
process.on('exit', function() {
assert.equal(ticketLog.length, serverLog.length);
for (var i = 0; i < serverLog.length - 1; i++) {
for (var i = 0; i < naturalServers.length - 1; i++) {
assert.notEqual(serverLog[i], serverLog[i + 1]);
assert.equal(ticketLog[i], ticketLog[i + 1]);
// 2nd connection should have different ticket
assert.notEqual(ticketLog[i], ticketLog[i + naturalServers.length]);
// 3rd connection should have the same ticket
assert.equal(ticketLog[i], ticketLog[i + naturalServers.length * 2]);
}
});

Loading…
Cancel
Save