Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2020-07-23 22:11:12 +0300
committerJames M Snell <jasnell@gmail.com>2020-07-27 23:33:14 +0300
commit1f94b89309bcd56a2883cd1b0eb2db610251095e (patch)
treef26a6929226f6ff4039c0ea58584821147b26ce4 /lib/internal/quic
parent06664298fa07442b5be6dbc891ea999f6c9e7d28 (diff)
quic: refactor ocsp to use async function rather than event/callback
PR-URL: https://github.com/nodejs/node/pull/34498 Reviewed-By: Anna Henningsen <anna@addaleax.net>
Diffstat (limited to 'lib/internal/quic')
-rw-r--r--lib/internal/quic/core.js117
-rw-r--r--lib/internal/quic/util.js33
2 files changed, 77 insertions, 73 deletions
diff --git a/lib/internal/quic/core.js b/lib/internal/quic/core.js
index 6a227d3d4ae..821b2839fe9 100644
--- a/lib/internal/quic/core.js
+++ b/lib/internal/quic/core.js
@@ -209,11 +209,11 @@ const kAddSession = Symbol('kAddSession');
const kAddStream = Symbol('kAddStream');
const kBind = Symbol('kBind');
const kClose = Symbol('kClose');
-const kCert = Symbol('kCert');
const kClientHello = Symbol('kClientHello');
const kDestroy = Symbol('kDestroy');
const kEndpointBound = Symbol('kEndpointBound');
const kEndpointClose = Symbol('kEndpointClose');
+const kHandleOcsp = Symbol('kHandleOcsp');
const kHandshake = Symbol('kHandshake');
const kHandshakeComplete = Symbol('kHandshakeComplete');
const kHandshakePost = Symbol('kHandshakePost');
@@ -323,52 +323,37 @@ function onSessionClientHello(alpn, servername, ciphers) {
clientHelloCallback.bind(this));
}
-// Used only within the onSessionCert function. Invoked
-// to complete the session cert process.
-function sessionCertCallback(err, context, ocspResponse) {
- if (err) {
- this[owner_symbol].destroy(err);
- return;
- }
- if (context != null && !context.context) {
- this[owner_symbol].destroy(
- new ERR_INVALID_ARG_TYPE(
- 'context',
- 'SecureContext',
- context));
- }
- if (ocspResponse != null) {
- if (typeof ocspResponse === 'string')
- ocspResponse = Buffer.from(ocspResponse);
- if (!isArrayBufferView(ocspResponse)) {
- this[owner_symbol].destroy(
- new ERR_INVALID_ARG_TYPE(
- 'ocspResponse',
- ['string', 'Buffer', 'TypedArray', 'DataView'],
- ocspResponse));
- }
- }
- try {
- this.onCertDone(context ? context.context : undefined, ocspResponse);
- } catch (err) {
- this[owner_symbol].destroy(err);
- }
-}
-
// This callback is only ever invoked for QuicServerSession instances,
// and is used to trigger OCSP request processing when needed. The
// user callback must invoke .onCertDone() in order for the
// TLS handshake to continue.
function onSessionCert(servername) {
- this[owner_symbol][kCert](servername, sessionCertCallback.bind(this));
+ this[owner_symbol][kHandleOcsp](servername)
+ .then(({ context, data }) => {
+ if (context !== undefined && !context?.context)
+ throw new ERR_INVALID_ARG_TYPE('context', 'SecureContext', context);
+ if (data !== undefined) {
+ if (typeof data === 'string')
+ data = Buffer.from(data);
+ if (!isArrayBufferView(data)) {
+ throw new ERR_INVALID_ARG_TYPE(
+ 'data',
+ ['string', 'Buffer', 'TypedArray', 'DataView'],
+ data);
+ }
+ }
+ this.onCertDone(context?.context, data);
+ })
+ .catch((error) => this[owner_symbol].destroy(error));
}
// This callback is only ever invoked for QuicClientSession instances,
// and is used to deliver the OCSP response as provided by the server.
// If the requestOCSP configuration option is false, this will never
// be called.
-function onSessionStatus(response) {
- this[owner_symbol][kCert](response);
+function onSessionStatus(data) {
+ this[owner_symbol][kHandleOcsp](data)
+ .catch((error) => this[owner_symbol].destroy(error));
}
// Called by the C++ internals when the TLS handshake is completed.
@@ -524,12 +509,12 @@ setCallbacks({
onSocketServerBusy,
onSessionReady,
onSessionCert,
+ onSessionStatus,
onSessionClientHello,
onSessionClose,
onSessionHandshake,
onSessionKeylog,
onSessionQlog,
- onSessionStatus,
onSessionTicket,
onSessionVersionNegotiation,
onStreamReady,
@@ -933,6 +918,7 @@ class QuicSocket extends EventEmitter {
listenPending: false,
listenPromise: undefined,
lookup: undefined,
+ ocspHandler: undefined,
server: undefined,
serverSecureContext: undefined,
sessions: new Set(),
@@ -1032,6 +1018,7 @@ class QuicSocket extends EventEmitter {
return {
highWaterMark: state.highWaterMark,
defaultEncoding: state.defaultEncoding,
+ ocspHandler: state.ocspHandler,
};
}
@@ -1224,6 +1211,7 @@ class QuicSocket extends EventEmitter {
lookup = state.lookup,
defaultEncoding,
highWaterMark,
+ ocspHandler,
transportParams,
} = validateQuicSocketListenOptions(options);
@@ -1239,6 +1227,7 @@ class QuicSocket extends EventEmitter {
state.defaultEncoding = defaultEncoding;
state.alpn = alpn;
state.listenPending = true;
+ state.ocspHandler = ocspHandler;
await this[kMaybeBind]();
@@ -1663,6 +1652,7 @@ class QuicSession extends EventEmitter {
handshakeCompletePromiseReject: undefined,
idleTimeout: false,
maxPacketLength: NGTCP2_DEFAULT_MAX_PKTLEN,
+ ocspHandler: undefined,
servername: undefined,
socket: undefined,
silentClose: false,
@@ -1685,6 +1675,7 @@ class QuicSession extends EventEmitter {
servername,
highWaterMark,
defaultEncoding,
+ ocspHandler,
} = options;
super({ captureRejections: true });
this.on('newListener', onNewListener);
@@ -1695,6 +1686,7 @@ class QuicSession extends EventEmitter {
state.alpn = alpn;
state.highWaterMark = highWaterMark;
state.defaultEncoding = defaultEncoding;
+ state.ocspHandler = ocspHandler;
socket[kAddSession](this);
}
@@ -1758,6 +1750,7 @@ class QuicSession extends EventEmitter {
state.state = new QuicSessionSharedState(handle.state);
state.handshakeAckHistogram = new Histogram(handle.ack);
state.handshakeContinuationHistogram = new Histogram(handle.rate);
+ state.state.ocspEnabled = state.ocspHandler !== undefined;
if (handle.qlogStream !== undefined) {
this[kSetQLogStream](handle.qlogStream);
handle.qlogStream = undefined;
@@ -2284,8 +2277,9 @@ class QuicServerSession extends QuicSession {
const {
highWaterMark,
defaultEncoding,
+ ocspHandler,
} = options;
- super(socket, { highWaterMark, defaultEncoding });
+ super(socket, { highWaterMark, defaultEncoding, ocspHandler });
this[kSetHandle](handle);
}
@@ -2301,26 +2295,18 @@ class QuicServerSession extends QuicSession {
callback.bind(this[kHandle]));
}
- // Called only when an OCSPRequest event handler is registered.
- // Allows user code the ability to answer the OCSP query.
- [kCert](servername, callback) {
+ async [kHandleOcsp](servername) {
+ const internalState = this[kInternalState];
const state = this[kInternalServerState];
- const { serverSecureContext } = this.socket;
- let { context } = serverSecureContext;
-
- for (var i = 0; i < state.contexts.length; i++) {
- const elem = state.contexts[i];
- if (elem[0].test(servername)) {
- context = elem[1];
- break;
- }
- }
-
- this.emit(
- 'OCSPRequest',
- servername,
- context,
- callback.bind(this[kHandle]));
+ const { context } = this.socket.serverSecureContext;
+
+ return internalState.ocspHandler?.(
+ 'request',
+ {
+ servername,
+ context,
+ contexts: Array.from(state.contexts)
+ });
}
get allowEarlyData() { return false; }
@@ -2358,10 +2344,10 @@ class QuicClientSession extends QuicSession {
alpn,
dcid,
minDHSize,
+ ocspHandler,
port,
preferredAddressPolicy,
remoteTransportParams,
- requestOCSP,
servername,
sessionTicket,
verifyHostnameIdentity,
@@ -2379,7 +2365,13 @@ class QuicClientSession extends QuicSession {
);
}
- super(socket, { servername, alpn, highWaterMark, defaultEncoding });
+ super(socket, {
+ servername,
+ alpn,
+ highWaterMark,
+ defaultEncoding,
+ ocspHandler
+ });
const state = this[kInternalClientState];
state.handshakeStarted = autoStart;
state.minDHSize = minDHSize;
@@ -2412,7 +2404,7 @@ class QuicClientSession extends QuicSession {
this.alpnProtocol,
(verifyHostnameIdentity ?
QUICCLIENTSESSION_OPTION_VERIFY_HOSTNAME_IDENTITY : 0) |
- (requestOCSP ?
+ (ocspHandler !== undefined ?
QUICCLIENTSESSION_OPTION_REQUEST_OCSP : 0),
qlog,
autoStart);
@@ -2444,8 +2436,9 @@ class QuicClientSession extends QuicSession {
return true;
}
- [kCert](response) {
- this.emit('OCSPResponse', response);
+ async [kHandleOcsp](data) {
+ const internalState = this[kInternalState];
+ return internalState.ocspHandler?.('response', { data });
}
get allowEarlyData() {
diff --git a/lib/internal/quic/util.js b/lib/internal/quic/util.js
index f46a8714e00..3d0ebb0884a 100644
--- a/lib/internal/quic/util.js
+++ b/lib/internal/quic/util.js
@@ -72,7 +72,7 @@ const {
IDX_QUICSESSION_STATE_KEYLOG_ENABLED,
IDX_QUICSESSION_STATE_CLIENT_HELLO_ENABLED,
- IDX_QUICSESSION_STATE_CERT_ENABLED,
+ IDX_QUICSESSION_STATE_OCSP_ENABLED,
IDX_QUICSESSION_STATE_PATH_VALIDATED_ENABLED,
IDX_QUICSESSION_STATE_USE_PREFERRED_ADDRESS_ENABLED,
IDX_QUICSESSION_STATE_HANDSHAKE_CONFIRMED,
@@ -368,10 +368,10 @@ function validateQuicClientSessionOptions(options = {}) {
alpn = '',
dcid: dcid_value,
minDHSize = 1024,
+ ocspHandler,
port = 0,
preferredAddressPolicy = 'ignore',
remoteTransportParams,
- requestOCSP = false,
servername = (isIP(address) ? '' : address),
sessionTicket,
verifyHostnameIdentity = true,
@@ -434,23 +434,29 @@ function validateQuicClientSessionOptions(options = {}) {
if (preferredAddressPolicy !== undefined)
validateString(preferredAddressPolicy, 'options.preferredAddressPolicy');
- validateBoolean(requestOCSP, 'options.requestOCSP');
validateBoolean(verifyHostnameIdentity, 'options.verifyHostnameIdentity');
validateBoolean(qlog, 'options.qlog');
+ if (ocspHandler !== undefined && typeof ocspHandler !== 'function') {
+ throw new ERR_INVALID_ARG_TYPE(
+ 'options.ocspHandler',
+ 'functon',
+ ocspHandler);
+ }
+
return {
autoStart,
address,
alpn,
dcid,
minDHSize,
+ ocspHandler,
port,
preferredAddressPolicy:
preferredAddressPolicy === 'accept' ?
QUIC_PREFERRED_ADDRESS_USE :
QUIC_PREFERRED_ADDRESS_IGNORE,
remoteTransportParams,
- requestOCSP,
servername,
sessionTicket,
verifyHostnameIdentity,
@@ -605,6 +611,7 @@ function validateQuicSocketListenOptions(options = {}) {
alpn = NGHTTP3_ALPN_H3,
defaultEncoding,
highWaterMark,
+ ocspHandler,
requestCert,
rejectUnauthorized,
lookup,
@@ -616,6 +623,12 @@ function validateQuicSocketListenOptions(options = {}) {
validateBoolean(requestCert, 'options.requestCert');
if (lookup !== undefined)
validateLookup(lookup);
+ if (ocspHandler !== undefined && typeof ocspHandler !== 'function') {
+ throw new ERR_INVALID_ARG_TYPE(
+ 'options.ocspHandler',
+ 'functon',
+ ocspHandler);
+ }
const transportParams =
validateTransportParams(
options,
@@ -625,6 +638,7 @@ function validateQuicSocketListenOptions(options = {}) {
return {
alpn,
lookup,
+ ocspHandler,
rejectUnauthorized,
requestCert,
transportParams,
@@ -804,9 +818,6 @@ function toggleListeners(state, event, on) {
case 'pathValidation':
state.pathValidatedEnabled = on;
break;
- case 'OCSPRequest':
- state.certEnabled = on;
- break;
case 'usePreferredAddress':
state.usePreferredAddressEnabled = on;
break;
@@ -915,14 +926,14 @@ class QuicSessionSharedState {
.writeUInt8(on ? 1 : 0, IDX_QUICSESSION_STATE_CLIENT_HELLO_ENABLED);
}
- get certEnabled() {
+ get ocspEnabled() {
return Boolean(this[kHandle]
- .readUInt8(IDX_QUICSESSION_STATE_CERT_ENABLED));
+ .readUInt8(IDX_QUICSESSION_STATE_OCSP_ENABLED));
}
- set certEnabled(on) {
+ set ocspEnabled(on) {
this[kHandle]
- .writeUInt8(on ? 1 : 0, IDX_QUICSESSION_STATE_CERT_ENABLED);
+ .writeUInt8(on ? 1 : 0, IDX_QUICSESSION_STATE_OCSP_ENABLED);
}
get pathValidatedEnabled() {