From: Daniel Salzman Date: Fri, 14 Apr 2023 14:02:50 +0000 (+0200) Subject: requestor: return better error code if peer cert key check fails X-Git-Tag: v3.4.dev~138^2~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dbd7cdd654d758ea456902318db8f8a604b3dcdf;p=thirdparty%2Fknot-dns.git requestor: return better error code if peer cert key check fails --- diff --git a/src/knot/query/quic-requestor.c b/src/knot/query/quic-requestor.c index 7e93fdb306..690347e843 100644 --- a/src/knot/query/quic-requestor.c +++ b/src/knot/query/quic-requestor.c @@ -46,13 +46,13 @@ static int quic_exchange(knot_quic_conn_t *conn, knot_quic_reply_t *r, int timeo r->in_payload->iov_len = ret; knot_quic_conn_t *hconn = NULL; - (void)knot_quic_handle(conn->quic_table, r, timeout_ms * 1000L, &hconn); + ret = knot_quic_handle(conn->quic_table, r, timeout_ms * 1000L, &hconn); if (hconn == NULL) { return KNOT_EOK; } else if (hconn != conn) { return KNOT_ESEMCHECK; } else { - return KNOT_EOK; + return ret; } } @@ -81,18 +81,19 @@ void qr_free_reply(struct knot_quic_reply *r) (void)r; } -struct knot_quic_reply *knot_qreq_connect(int fd, - struct sockaddr_storage *remote, - struct sockaddr_storage *local, - const struct knot_quic_creds *local_creds, - const uint8_t *peer_pin, - uint8_t peer_pin_len, - int timeout_ms) +int knot_qreq_connect(struct knot_quic_reply **out, + int fd, + struct sockaddr_storage *remote, + struct sockaddr_storage *local, + const struct knot_quic_creds *local_creds, + const uint8_t *peer_pin, + uint8_t peer_pin_len, + int timeout_ms) { - knot_quic_reply_t *r = calloc(1, sizeof(*r) + 2 * sizeof(struct iovec) + - 2 * QUIC_BUF_SIZE); + struct knot_quic_reply *r = calloc(1, sizeof(*r) + 2 * sizeof(struct iovec) + + 2 * QUIC_BUF_SIZE); if (r == NULL) { - return NULL; + return KNOT_ENOMEM; } r->ip_rem = remote; @@ -110,7 +111,7 @@ struct knot_quic_reply *knot_qreq_connect(int fd, peer_pin, peer_pin_len); if (creds == NULL) { free(r); - return NULL; + return KNOT_ENOMEM; } // NOTE the limits on conns and buffers do not do anything since we do not sweep @@ -119,7 +120,7 @@ struct knot_quic_reply *knot_qreq_connect(int fd, if (table == NULL) { knot_quic_free_creds(creds); free(r); - return NULL; + return KNOT_ENOMEM; } knot_quic_conn_t *conn = NULL; @@ -128,21 +129,23 @@ struct knot_quic_reply *knot_qreq_connect(int fd, r->in_ctx = conn; if (ret != KNOT_EOK) { knot_qreq_close(r); - return NULL; + return ret; } struct timespec t_start = time_now(), t_cur; while (!conn->handshake_done) { t_cur = time_now(); if (time_diff_ms(&t_start, &t_cur) > timeout_ms || - quic_exchange(conn, r, timeout_ms) != KNOT_EOK) { + (ret = quic_exchange(conn, r, timeout_ms)) != KNOT_EOK) { knot_qreq_close(r); - return NULL; + return ret; } } r->in_ctx = conn; - return r; + *out = r; + + return KNOT_EOK; } int knot_qreq_send(struct knot_quic_reply *r, const struct iovec *data) diff --git a/src/knot/query/quic-requestor.h b/src/knot/query/quic-requestor.h index 05b293cf81..604947115b 100644 --- a/src/knot/query/quic-requestor.h +++ b/src/knot/query/quic-requestor.h @@ -21,13 +21,14 @@ struct knot_quic_creds; struct knot_quic_reply; -struct knot_quic_reply *knot_qreq_connect(int fd, - struct sockaddr_storage *remote, - struct sockaddr_storage *local, - const struct knot_quic_creds *local_creds, - const uint8_t *peer_pin, - uint8_t peer_pin_len, - int timeout_ms); +int knot_qreq_connect(struct knot_quic_reply **out, + int fd, + struct sockaddr_storage *remote, + struct sockaddr_storage *local, + const struct knot_quic_creds *local_creds, + const uint8_t *peer_pin, + uint8_t peer_pin_len, + int timeout_ms); int knot_qreq_send(struct knot_quic_reply *r, const struct iovec *data); diff --git a/src/knot/query/requestor.c b/src/knot/query/requestor.c index 1d370e4c32..18e1f5633c 100644 --- a/src/knot/query/requestor.c +++ b/src/knot/query/requestor.c @@ -89,13 +89,14 @@ static int request_ensure_connected(knot_request_t *request, bool *reused_fd, in &local_len); } #ifdef ENABLE_QUIC - request->quic_ctx = knot_qreq_connect(request->fd, &request->remote, - &request->source, request->creds, - request->pin, request->pin_len, - timeout_ms); - if (request->quic_ctx == NULL) { + int ret = knot_qreq_connect(&request->quic_ctx, + request->fd, &request->remote, + &request->source, request->creds, + request->pin, request->pin_len, + timeout_ms); + if (ret != KNOT_EOK) { close(request->fd); - return KNOT_ECONN; + return ret; } #else assert(0); diff --git a/src/libknot/errcode.h b/src/libknot/errcode.h index 648ca66060..a82da352f6 100644 --- a/src/libknot/errcode.h +++ b/src/libknot/errcode.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -105,6 +105,7 @@ enum knot_error { KNOT_EEMPTYZONE, KNOT_ENODB, KNOT_EUNREACH, + KNOT_EBADCERTKEY, KNOT_GENERAL_ERROR = -900, diff --git a/src/libknot/error.c b/src/libknot/error.c index 352acd32bf..b6a6d22c7c 100644 --- a/src/libknot/error.c +++ b/src/libknot/error.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -104,6 +104,7 @@ static const struct error errors[] = { { KNOT_EEMPTYZONE, "zone is empty" }, { KNOT_ENODB, "database does not exist" }, { KNOT_EUNREACH, "remote known to be unreachable" }, + { KNOT_EBADCERTKEY, "unknown certificate key" }, { KNOT_GENERAL_ERROR, "unknown general error" }, diff --git a/src/libknot/quic/quic.c b/src/libknot/quic/quic.c index 52898182ba..4c9f163728 100644 --- a/src/libknot/quic/quic.c +++ b/src/libknot/quic/quic.c @@ -939,9 +939,13 @@ int knot_quic_handle(knot_quic_table_t *table, knot_quic_reply_t *reply, knot_quic_table_rem(conn, table); ret = KNOT_EOK; goto finish; - } else if(ngtcp2_err_is_fatal(ret)) { // connection doomed + } else if (ngtcp2_err_is_fatal(ret)) { // connection doomed + if (ret == NGTCP2_ERR_CALLBACK_FAILURE) { + ret = KNOT_EBADCERTKEY; + } else { + ret = KNOT_ECONN; + } knot_quic_table_rem(conn, table); - ret = KNOT_ECONN; goto finish; } else if (ret != NGTCP2_NO_ERROR) { // non-fatal error, discard packet ret = KNOT_EOK;