Skip to content

Commit ff9ee44

Browse files
fix: certificate verify callback should not raise (#93)
1 parent 018e77e commit ff9ee44

2 files changed

Lines changed: 45 additions & 15 deletions

File tree

lsquic/context/context.nim

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -247,21 +247,32 @@ proc alpnSelectProtoCB(
247247

248248
proc verifyCertificate(
249249
ssl: ptr SSL, out_alert: ptr uint8
250-
): enum_ssl_verify_result_t {.cdecl.} =
251-
let sslCtx = SSL_get_SSL_CTX(ssl)
252-
253-
let quicCtx = cast[QuicContext](SSL_CTX_get_ex_data(sslCtx, SSL_CTX_ID))
254-
if quicCtx.isNil:
255-
raiseAssert "could not obtain context"
256-
257-
let derCertificates = getFullCertChain(ssl)
258-
259-
let serverName = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)
260-
doAssert quicCtx.tlsConfig.certVerifier.isSome, "no custom validator set"
261-
if quicCtx.tlsConfig.certVerifier.get().verify($serverName, derCertificates):
262-
return ssl_verify_ok
263-
else:
264-
out_alert[] = SSL_AD_CERTIFICATE_UNKNOWN
250+
): enum_ssl_verify_result_t {.cdecl, raises: [].} =
251+
try:
252+
let sslCtx = SSL_get_SSL_CTX(ssl)
253+
if sslCtx.isNil:
254+
if not out_alert.isNil:
255+
out_alert[] = SSL_AD_INTERNAL_ERROR
256+
return ssl_verify_invalid
257+
258+
let quicCtx = cast[QuicContext](SSL_CTX_get_ex_data(sslCtx, SSL_CTX_ID))
259+
if quicCtx.isNil or quicCtx.tlsConfig.certVerifier.isNone:
260+
if not out_alert.isNil:
261+
out_alert[] = SSL_AD_INTERNAL_ERROR
262+
return ssl_verify_invalid
263+
264+
let derCertificates = getFullCertChain(ssl)
265+
let serverName = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)
266+
if quicCtx.tlsConfig.certVerifier.get().verify($serverName, derCertificates):
267+
return ssl_verify_ok
268+
269+
if not out_alert.isNil:
270+
out_alert[] = SSL_AD_CERTIFICATE_UNKNOWN
271+
return ssl_verify_invalid
272+
except Exception as exc:
273+
warn "certificate verifier raised", errorMsg = exc.msg
274+
if not out_alert.isNil:
275+
out_alert[] = SSL_AD_CERTIFICATE_UNKNOWN
265276
return ssl_verify_invalid
266277

267278
proc setupSSLContext*(quicCtx: QuicContext) =

tests/test_verifier.nim

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ proc rejectingCertificateCb(
3333
discard derCertificates
3434
false
3535

36+
proc raisingCertificateCb(
37+
serverName: string, derCertificates: seq[seq[byte]]
38+
): bool {.gcsafe.} =
39+
discard serverName
40+
discard derCertificates
41+
raise newException(ValueError, "verifier failed")
42+
3643
proc makeRejectingCertificateCb(
3744
recorder: RejectVerifierRecorder
3845
): certificateVerifierCB =
@@ -92,6 +99,18 @@ suite "certificate verifier":
9299
expect DialError:
93100
discard await client.dial(listener.localAddress())
94101

102+
asyncTest "raising client verifier rejects handshake":
103+
let client =
104+
makeClientWithVerifier(CustomCertificateVerifier.init(raisingCertificateCb))
105+
let server =
106+
makeServerWithVerifier(CustomCertificateVerifier.init(acceptingCertificateCb))
107+
let listener = server.listen(initTAddress("127.0.0.1:0"))
108+
defer:
109+
await allFutures(client.stop(), listener.stop())
110+
111+
expect DialError:
112+
discard await client.dial(listener.localAddress())
113+
95114
asyncTest "alpn mismatch rejects handshake":
96115
let client = makeClientWithVerifier(
97116
CustomCertificateVerifier.init(acceptingCertificateCb), singleAlpn("client-proto")

0 commit comments

Comments
 (0)