Skip to content

Commit

Permalink
tls: add getter and setter for session ticket number.
Browse files Browse the repository at this point in the history
  • Loading branch information
mkrawczuk committed Jun 22, 2020
1 parent 8ef86a9 commit 3911595
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 1 deletion.
28 changes: 28 additions & 0 deletions doc/api/tls.md
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,30 @@ Existing or currently pending server connections will use the previous keys.

See [Session Resumption][] for more information.

### `server.getNumTickets()`
<!-- YAML
added: CHANGEME
-->

* Returns: {number} A number of session tickets.

Returns the number of session tickets that are sent to the client after
a full handshake.

See [SSL_CTX_get_num_tickets][] for more information.

### `server.setNumTickets(numTickets)`
<!-- YAML
added: CHANGEME
-->

* `numTickets` {number} A number of session tickets.

Sets the number of session tickets that are sent to the client after
a full handshake.

See [SSL_CTX_set_num_tickets][] for more information.

## Class: `tls.TLSSocket`
<!-- YAML
added: v0.11.4
Expand Down Expand Up @@ -1628,6 +1652,8 @@ changes:
**Default:** none, see `minVersion`.
* `sessionIdContext` {string} Opaque identifier used by servers to ensure
session state is not shared between applications. Unused by clients.
* `numTickets` {number} The number of session tickets that will be sent to the
client after a full handshake. **Default:** `2`.

[`tls.createServer()`][] sets the default value of the `honorCipherOrder` option
to `true`, other APIs that create secure contexts leave it unset.
Expand Down Expand Up @@ -2005,3 +2031,5 @@ where `secureSocket` has the same API as `pair.cleartext`.
[specific attacks affecting larger AES key sizes]: https://www.schneier.com/blog/archives/2009/07/another_new_aes.html
[RFC 4279]: https://tools.ietf.org/html/rfc4279
[RFC 4086]: https://tools.ietf.org/html/rfc4086
[SSL_CTX_get_num_tickets]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_get_num_tickets.html
[SSL_CTX_set_num_tickets]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_num_tickets.html
4 changes: 4 additions & 0 deletions lib/_tls_common.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,10 @@ exports.createSecureContext = function createSecureContext(options) {
options.clientCertEngine);
}

if (options.numTickets) {
c.context.setNumTickets(options.numTickets);
}

return c;
};

Expand Down
14 changes: 13 additions & 1 deletion lib/_tls_wrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -1315,6 +1315,9 @@ Server.prototype.setSecureContext = function(options) {
.slice(0, 32);
}

if (options.numTickets)
this.numTickets = options.numTickets;

this._sharedCreds = tls.createSecureContext({
pfx: this.pfx,
key: this.key,
Expand All @@ -1332,7 +1335,8 @@ Server.prototype.setSecureContext = function(options) {
secureOptions: this.secureOptions,
honorCipherOrder: this.honorCipherOrder,
crl: this.crl,
sessionIdContext: this.sessionIdContext
sessionIdContext: this.sessionIdContext,
numTickets: this.numTickets
});

if (this.sessionTimeout)
Expand Down Expand Up @@ -1366,6 +1370,14 @@ Server.prototype.setTicketKeys = function setTicketKeys(keys) {
this._sharedCreds.context.setTicketKeys(keys);
};

Server.prototype.getNumTickets = function getNumTickets() {
return this._sharedCreds.context.getNumTickets();
};


Server.prototype.setNumTickets = function setNumTickets(numTickets) {
this._sharedCreds.context.setNumTickets(numTickets);
};

Server.prototype.setOptions = deprecate(function(options) {
this.requestCert = options.requestCert === true;
Expand Down
28 changes: 28 additions & 0 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,8 @@ void SecureContext::Initialize(Environment* env, Local<Object> target) {
env->SetProtoMethod(t, "enableTicketKeyCallback", EnableTicketKeyCallback);
env->SetProtoMethodNoSideEffect(t, "getCertificate", GetCertificate<true>);
env->SetProtoMethodNoSideEffect(t, "getIssuer", GetCertificate<false>);
env->SetProtoMethodNoSideEffect(t, "getNumTickets", GetNumTickets);
env->SetProtoMethod(t, "setNumTickets", SetNumTickets);

#define SET_INTEGER_CONSTANTS(name, value) \
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), name), \
Expand Down Expand Up @@ -1558,6 +1560,32 @@ void SecureContext::SetTicketKeys(const FunctionCallbackInfo<Value>& args) {
}


void SecureContext::GetNumTickets(const FunctionCallbackInfo<Value>& args) {
SecureContext* sc;
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());

CHECK_EQ(args.Length(), 0);

uint32_t numTickets = SSL_CTX_get_num_tickets(sc->ctx_.get());
args.GetReturnValue().Set(static_cast<uint32_t>(numTickets));
}


void SecureContext::SetNumTickets(const FunctionCallbackInfo<Value>& args) {
SecureContext* sc;
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());

if (args.Length() != 1 || !args[0]->IsUint32()) {
return THROW_ERR_INVALID_ARG_TYPE(
sc->env(), "Number of tickets must be an unsigned 32-bit integer");
}

uint32_t numTickets = args[0].As<Uint32>()->Value();

CHECK(SSL_CTX_set_num_tickets(sc->ctx_.get(), numTickets));
}


void SecureContext::SetFreeListLength(const FunctionCallbackInfo<Value>& args) {
}

Expand Down
2 changes: 2 additions & 0 deletions src/node_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ class SecureContext final : public BaseObject {
#endif // !OPENSSL_NO_ENGINE
static void GetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetNumTickets(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetNumTickets(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetFreeListLength(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void EnableTicketKeyCallback(
Expand Down
40 changes: 40 additions & 0 deletions test/parallel/test-tls-num-tickets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
const fixtures = require('../common/fixtures');

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

const server = tls.createServer({
key: fixtures.readKey('agent1-key.pem'),
cert: fixtures.readKey('agent1-cert.pem'),
});

const expectedNumTickets = 1;
// 2 is the deafult value set by OpenSSL.
assert.strictEqual(server.getNumTickets(), 2);
// Change the number of sent session tickets.
server.setNumTickets(expectedNumTickets);
// Ensure that it has indeed been changed.
assert.strictEqual(server.getNumTickets(), expectedNumTickets);
// Ensure that an error is thrown when attempting to set the number of tickets
// to a negative number.
assert.throws(
() => server.setNumTickets(-1),
{
code: 'ERR_INVALID_ARG_TYPE',
message: 'Number of tickets must be an unsigned 32-bit integer'
}
);

// Ensure that an error is thrown when attempting to set the number of tickets
// to Mongolian throat singing.
assert.throws(
() => server.setNumTickets('HURRMMMM'),
{
code: 'ERR_INVALID_ARG_TYPE',
message: 'Number of tickets must be an unsigned 32-bit integer'
}
);

0 comments on commit 3911595

Please sign in to comment.