]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
requestor: return better error code if peer cert key check fails
authorDaniel Salzman <daniel.salzman@nic.cz>
Fri, 14 Apr 2023 14:02:50 +0000 (16:02 +0200)
committerDaniel Salzman <daniel.salzman@nic.cz>
Tue, 23 May 2023 08:42:01 +0000 (10:42 +0200)
src/knot/query/quic-requestor.c
src/knot/query/quic-requestor.h
src/knot/query/requestor.c
src/libknot/errcode.h
src/libknot/error.c
src/libknot/quic/quic.c

index 7e93fdb306f1b1880b276270c09ec942a50062d7..690347e8433db1d7867d398d3b4c4c5e2ea17550 100644 (file)
@@ -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)
index 05b293cf8116c9bbba7ceffb39ecc64f6cced6ff..604947115b09df1223ab682521f9aa8e296a0b67 100644 (file)
 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);
 
index 1d370e4c326f003882940a5acd40bfc64a058c49..18e1f5633cb507ec94412d5c5e6bf69df3b5d279 100644 (file)
@@ -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);
index 648ca660606121f4b5f216af6ae6d754b0421259..a82da352f672a9245a87675eaaaae14d2c99a9ad 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     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,
 
index 352acd32bfff787b95936886d114acaed8607b1d..b6a6d22c7c18c70b05de566ca584597686d04b26 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     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" },
 
index 52898182bad235622f6233a298a05a0e75d9bcaa..4c9f163728de366c18c2cff8a551c507886fae27 100644 (file)
@@ -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;