Skip to content

Commit 225babf

Browse files
committed
feat: added verifyCallback and verifyAllowFail
[ci skip]
1 parent 9f6ae63 commit 225babf

File tree

7 files changed

+45
-4
lines changed

7 files changed

+45
-4
lines changed

src/QUICClient.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { PromiseCancellable } from '@matrixai/async-cancellable';
22
import type { ContextTimed } from '@matrixai/contexts';
3-
import type { ClientCrypto, Host, Hostname, Port } from './types';
3+
import type { ClientCrypto, Host, Hostname, Port, VerifyCallback } from './types';
44
import type { Config } from './native/types';
55
import type QUICConnectionMap from './QUICConnectionMap';
66
import type {
@@ -79,6 +79,7 @@ class QUICClient extends EventTarget {
7979
resolveHostname?: (hostname: Hostname) => Host | PromiseLike<Host>;
8080
reasonToCode?: StreamReasonToCode;
8181
codeToReason?: StreamCodeToReason;
82+
verifyCallback?: VerifyCallback;
8283
logger?: Logger;
8384
},
8485
ctx?: Partial<ContextTimed>,
@@ -96,6 +97,7 @@ class QUICClient extends EventTarget {
9697
resolveHostname = utils.resolveHostname,
9798
reasonToCode,
9899
codeToReason,
100+
verifyCallback,
99101
logger = new Logger(`${this.name}`),
100102
}: {
101103
host: Host | Hostname;
@@ -112,6 +114,7 @@ class QUICClient extends EventTarget {
112114
resolveHostname?: (hostname: Hostname) => Host | PromiseLike<Host>;
113115
reasonToCode?: StreamReasonToCode;
114116
codeToReason?: StreamCodeToReason;
117+
verifyCallback?: VerifyCallback;
115118
logger?: Logger;
116119
},
117120
@context ctx: ContextTimed,
@@ -199,6 +202,7 @@ class QUICClient extends EventTarget {
199202
config: quicConfig,
200203
reasonToCode,
201204
codeToReason,
205+
verifyCallback,
202206
logger: logger.getChild(
203207
`${QUICConnection.name} ${scid.toString().slice(32)}`,
204208
),

src/QUICConnection.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import * as utils from './utils';
2525
import * as errors from './errors';
2626
import { never } from './utils';
2727

28+
// FIXME
29+
type VerifyCallback = (certs: Array<string>) => void;
30+
2831
/**
2932
* Think of this as equivalent to `net.Socket`.
3033
* Errors here are emitted to the connection only.
@@ -199,6 +202,7 @@ class QUICConnection extends EventTarget {
199202
protected shortSent = false;
200203
protected secured = false;
201204
protected count = 0;
205+
protected verifyCallback: VerifyCallback | undefined;
202206

203207
public constructor({
204208
type,
@@ -209,6 +213,7 @@ class QUICConnection extends EventTarget {
209213
socket,
210214
reasonToCode = () => 0,
211215
codeToReason = (type, code) => new Error(`${type} ${code}`),
216+
verifyCallback,
212217
logger,
213218
}:
214219
| {
@@ -220,6 +225,7 @@ class QUICConnection extends EventTarget {
220225
socket: QUICSocket;
221226
reasonToCode?: StreamReasonToCode;
222227
codeToReason?: StreamCodeToReason;
228+
verifyCallback?: VerifyCallback;
223229
logger?: Logger;
224230
}
225231
| {
@@ -231,6 +237,7 @@ class QUICConnection extends EventTarget {
231237
socket: QUICSocket;
232238
reasonToCode?: StreamReasonToCode;
233239
codeToReason?: StreamCodeToReason;
240+
verifyCallback?: VerifyCallback;
234241
logger?: Logger;
235242
}) {
236243
super();
@@ -281,6 +288,7 @@ class QUICConnection extends EventTarget {
281288
this.config = config;
282289
this.reasonToCode = reasonToCode;
283290
this.codeToReason = codeToReason;
291+
this.verifyCallback = verifyCallback;
284292
this._remoteHost = remoteInfo.host;
285293
this._remotePort = remoteInfo.port;
286294
const {
@@ -755,7 +763,7 @@ class QUICConnection extends EventTarget {
755763
// Dispatching certs available event
756764
// this.dispatchEvent(new events.QUICConnectionRemoteCertEvent()); TODO
757765
try {
758-
// if (this.verifyCallback != null) this.verifyCallback(peerCertsPem); TODO
766+
if (this.verifyCallback != null) this.verifyCallback(peerCertsPem);
759767
this.conn.sendAckEliciting();
760768
} catch (e) {
761769
// Force the connection to end.

src/QUICServer.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type {
66
StreamCodeToReason,
77
StreamReasonToCode,
88
QUICConfig,
9-
ServerCrypto,
9+
ServerCrypto, VerifyCallback
1010
} from './types';
1111
import type { Header } from './native/types';
1212
import type QUICConnectionMap from './QUICConnectionMap';
@@ -51,6 +51,7 @@ class QUICServer extends EventTarget {
5151
protected socket: QUICSocket;
5252
protected reasonToCode: StreamReasonToCode | undefined;
5353
protected codeToReason: StreamCodeToReason | undefined;
54+
protected verifyCallback: VerifyCallback | undefined;
5455
protected connectionMap: QUICConnectionMap;
5556

5657
protected handleQUICSocketEvents = (e: events.QUICSocketEvent) => {
@@ -77,6 +78,7 @@ class QUICServer extends EventTarget {
7778
resolveHostname = utils.resolveHostname,
7879
reasonToCode,
7980
codeToReason,
81+
verifyCallback,
8082
logger,
8183
}: {
8284
crypto: {
@@ -98,6 +100,7 @@ class QUICServer extends EventTarget {
98100
resolveHostname?: (hostname: Hostname) => Host | PromiseLike<Host>;
99101
reasonToCode?: StreamReasonToCode;
100102
codeToReason?: StreamCodeToReason;
103+
verifyCallback?: VerifyCallback;
101104
logger?: Logger;
102105
}) {
103106
super();
@@ -124,6 +127,7 @@ class QUICServer extends EventTarget {
124127
this.config = quicConfig;
125128
this.reasonToCode = reasonToCode;
126129
this.codeToReason = codeToReason;
130+
this.verifyCallback = verifyCallback;
127131
}
128132

129133
@ready(new errors.ErrorQUICServerNotRunning())
@@ -336,6 +340,7 @@ class QUICServer extends EventTarget {
336340
config: this.config,
337341
reasonToCode: this.reasonToCode,
338342
codeToReason: this.codeToReason,
343+
verifyCallback: this.verifyCallback,
339344
logger: this.logger.getChild(
340345
`${QUICConnection.name} ${scid.toString().slice(32)}-${clientConnRef}`,
341346
),

src/config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const sigalgs = [
2626
const clientDefault: QUICConfig = {
2727
sigalgs,
2828
verifyPeer: true,
29+
verifyAllowFail: false,
2930
grease: true,
3031
maxIdleTimeout: 0,
3132
maxRecvUdpPayloadSize: quiche.MAX_DATAGRAM_SIZE, // 65527
@@ -45,6 +46,7 @@ const clientDefault: QUICConfig = {
4546
const serverDefault: QUICConfig = {
4647
sigalgs,
4748
verifyPeer: false,
49+
verifyAllowFail: false,
4850
grease: true,
4951
maxIdleTimeout: 0,
5052
maxRecvUdpPayloadSize: quiche.MAX_DATAGRAM_SIZE, // 65527
@@ -148,6 +150,7 @@ function buildQuicheConfig(config: QUICConfig): QuicheConfig {
148150
try {
149151
quicheConfig = quiche.Config.withBoringSslCtx(
150152
config.verifyPeer,
153+
config.verifyAllowFail,
151154
caPEMBuffer,
152155
keyPEMBuffers,
153156
certChainPEMBuffers,

src/native/napi/config.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ impl Config {
5050
#[napi(factory)]
5151
pub fn with_boring_ssl_ctx(
5252
verify_peer: bool,
53+
verify_allow_fail: bool,
5354
ca: Option<Uint8Array>,
5455
key: Option<Vec<Uint8Array>>,
5556
cert: Option<Vec<Uint8Array>>,
@@ -65,7 +66,15 @@ impl Config {
6566
} else {
6667
boring::ssl::SslVerifyMode::NONE
6768
};
68-
ssl_ctx_builder.set_verify(verify_value);
69+
ssl_ctx_builder.set_verify_callback(verify_value, move |pre_verify, _| {
70+
// Override any validation errors, this is needed so we can request certs but validate them
71+
// manually.
72+
if verify_allow_fail {
73+
true
74+
} else {
75+
pre_verify
76+
}
77+
});
6978
// Setup all CA certificates
7079
if let Some(ca) = ca {
7180
let mut x509_store_builder = boring::x509::store::X509StoreBuilder::new()

src/native/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ interface ConfigConstructor {
4545
new (): Config;
4646
withBoringSslCtx(
4747
verifyPeer: boolean,
48+
verifyAllowFail: boolean,
4849
ca?: Uint8Array | undefined | null,
4950
key?: Array<Uint8Array> | undefined | null,
5051
cert?: Array<Uint8Array> | undefined | null,

src/types.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,17 @@ type QUICConfig = {
168168
* Verify the other peer.
169169
* Clients by default set this to true.
170170
* Servers by default set this to false.
171+
* Servers will not request peer certs unless this is true.
172+
* Server certs are always sent
171173
*/
172174
verifyPeer: boolean;
173175

176+
/**
177+
* Will allow unsecure TLS certs, allowing for certs to be requested
178+
* but the verification result is ignored.
179+
*/
180+
verifyAllowFail: boolean;
181+
174182
/**
175183
* Enables the logging of secret keys to a file path.
176184
* Use this with wireshark to decrypt the QUIC packets for debugging.
@@ -299,6 +307,8 @@ type QUICConfig = {
299307
enableEarlyData: boolean;
300308
};
301309

310+
type VerifyCallback = (certs: Array<string>) => void;
311+
302312
export type {
303313
Opaque,
304314
Callback,
@@ -320,4 +330,5 @@ export type {
320330
QUICConfig,
321331
ContextCancellable,
322332
ContextTimed,
333+
VerifyCallback,
323334
};

0 commit comments

Comments
 (0)