https: add client support for TLS keylog events

The keylog event is implemented on TLS sockets, but client HTTPS uses
TLS sockets managed by an agent, so accessing the underlying socket
before the TLS handshake completed was not possible.  Note that server
HTTPS already supports the keylog event because it inherits from the TLS
server.

PR-URL: https://github.com/nodejs/node/pull/30053
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Sam Roberts
2019-10-21 14:27:50 -07:00
committed by Rich Trott
parent 9d09969f4c
commit b0cf62b3a0
4 changed files with 100 additions and 3 deletions

View File

@@ -32,6 +32,7 @@ const {
ERR_INVALID_ARG_TYPE,
},
} = require('internal/errors');
const kOnKeylog = Symbol('onkeylog');
// New Agent code.
// The largest departure from the previous implementation is that
@@ -124,10 +125,29 @@ function Agent(options) {
}
}
});
// Don't emit keylog events unless there is a listener for them.
this.on('newListener', maybeEnableKeylog);
}
Object.setPrototypeOf(Agent.prototype, EventEmitter.prototype);
Object.setPrototypeOf(Agent, EventEmitter);
function maybeEnableKeylog(eventName) {
if (eventName === 'keylog') {
this.removeListener('newListener', maybeEnableKeylog);
// Future sockets will listen on keylog at creation.
const agent = this;
this[kOnKeylog] = function onkeylog(keylog) {
agent.emit('keylog', keylog, this);
};
// Existing sockets will start listening on keylog now.
const sockets = Object.values(this.sockets);
for (let i = 0; i < sockets.length; i++) {
sockets[i].on('keylog', this[kOnKeylog]);
}
}
}
Agent.defaultMaxSockets = Infinity;
Agent.prototype.createConnection = net.createConnection;
@@ -306,6 +326,10 @@ function installListeners(agent, s, options) {
s.removeListener('agentRemove', onRemove);
}
s.on('agentRemove', onRemove);
if (agent[kOnKeylog]) {
s.on('keylog', agent[kOnKeylog]);
}
}
Agent.prototype.removeSocket = function removeSocket(s, options) {