diff options
author | Daniel Salzman <daniel.salzman@nic.cz> | 2023-03-12 18:44:19 +0100 |
---|---|---|
committer | Daniel Salzman <daniel.salzman@nic.cz> | 2023-03-21 09:45:15 +0100 |
commit | 6d07b557cffd29a5874d34c5da2e435d82c17d8b (patch) | |
tree | 578e74e14e40bb44b00262ca09e9eeaa7feb4ed3 /src | |
parent | quic: simplify ALPN handling (diff) | |
download | knot-6d07b557cffd29a5874d34c5da2e435d82c17d8b.tar.xz knot-6d07b557cffd29a5874d34c5da2e435d82c17d8b.zip |
quic: move acl/cert_pin() to libknot/knot_quic_conn_pin()
Diffstat (limited to 'src')
-rw-r--r-- | src/knot/conf/tools.c | 10 | ||||
-rw-r--r-- | src/knot/include/module.h | 2 | ||||
-rw-r--r-- | src/knot/nameserver/process_query.c | 15 | ||||
-rw-r--r-- | src/knot/server/handler.c | 4 | ||||
-rw-r--r-- | src/knot/server/handler.h | 8 | ||||
-rw-r--r-- | src/knot/server/server.c | 2 | ||||
-rw-r--r-- | src/knot/updates/acl.c | 75 | ||||
-rw-r--r-- | src/knot/updates/acl.h | 31 | ||||
-rw-r--r-- | src/libknot/quic/quic.c | 44 | ||||
-rw-r--r-- | src/libknot/quic/quic.h | 14 |
10 files changed, 110 insertions, 95 deletions
diff --git a/src/knot/conf/tools.c b/src/knot/conf/tools.c index afd8cdf6d..f79a75aa9 100644 --- a/src/knot/conf/tools.c +++ b/src/knot/conf/tools.c @@ -38,8 +38,10 @@ #include "knot/conf/module.h" #include "knot/conf/schema.h" #include "knot/common/log.h" -#include "knot/updates/acl.h" #include "libknot/errcode.h" +#ifdef ENABLE_QUIC +#include "libknot/quic/quic.h" +#endif // ENABLE_QUIC #include "libknot/yparser/yptrafo.h" #include "libknot/xdp.h" #include "contrib/files.h" @@ -321,13 +323,15 @@ int check_xdp_listen( int check_cert_pin( knotd_conf_check_args_t *args) { - if (args->data_len != sizeof(uint16_t) + CERT_PIN_LEN) { +#ifdef ENABLE_QUIC + if (args->data_len != sizeof(uint16_t) + KNOT_QUIC_PIN_LEN) { (void)snprintf(check_str, sizeof(check_str), "invalid certificate pin, expected base64-encoded " - "%u bytes", CERT_PIN_LEN); + "%u bytes", KNOT_QUIC_PIN_LEN); args->err_str = check_str; return KNOT_EINVAL; } +#endif // ENABLE_QUIC return KNOT_EOK; } diff --git a/src/knot/include/module.h b/src/knot/include/module.h index b6d406dea..1af997201 100644 --- a/src/knot/include/module.h +++ b/src/knot/include/module.h @@ -410,7 +410,7 @@ typedef struct { unsigned thread_id; /*!< Current thread id. */ void *server; /*!< Server object private item. */ const struct knot_xdp_msg *xdp_msg; /*!< Possible XDP message context. */ - struct gnutls_session_int *session; /*!< QUIC session. */ + struct knot_xquic_conn *quic_conn; /*!< QUIC connection context. */ uint32_t measured_rtt; /*!< Measured RTT in usecs: QUIC or TCP-XDP. */ } knotd_qdata_params_t; diff --git a/src/knot/nameserver/process_query.c b/src/knot/nameserver/process_query.c index 5de641ca4..9fcb1bac6 100644 --- a/src/knot/nameserver/process_query.c +++ b/src/knot/nameserver/process_query.c @@ -30,6 +30,9 @@ #include "knot/nameserver/notify.h" #include "knot/server/server.h" #include "libknot/libknot.h" +#ifdef ENABLE_QUIC +#include "libknot/quic/quic.h" +#endif // ENABLE_QUIC #include "contrib/base64.h" #include "contrib/macros.h" #include "contrib/mempattern.h" @@ -706,22 +709,26 @@ bool process_query_acl_check(conf_t *conf, acl_action_t action, const yp_name_t *item = (action == ACL_ACTION_NOTIFY) ? C_MASTER : C_NOTIFY; conf_val_t rmts = conf_zone_get(conf, item, zone_name); allowed = rmt_allowed(conf, &rmts, query_source, &tsig, - qdata->params->session); + qdata->params->quic_conn); automatic = allowed; } if (!allowed) { conf_val_t acl = conf_zone_get(conf, C_ACL, zone_name); allowed = acl_allowed(conf, &acl, action, query_source, &tsig, - zone_name, query, qdata->params->session); + zone_name, query, qdata->params->quic_conn); } int pin_size = 0; - uint8_t bin_pin[CERT_PIN_LEN], pin[2 * CERT_PIN_LEN]; +#ifdef ENABLE_QUIC + uint8_t bin_pin[KNOT_QUIC_PIN_LEN], pin[2 * KNOT_QUIC_PIN_LEN]; size_t bin_pin_size = sizeof(bin_pin); - cert_pin(qdata->params->session, bin_pin, &bin_pin_size, false); + knot_quic_conn_pin(qdata->params->quic_conn, bin_pin, &bin_pin_size, false); if (bin_pin_size > 0) { pin_size = knot_base64_encode(bin_pin, bin_pin_size, pin, sizeof(pin)); } +#else + uint8_t pin[1]; +#endif // ENABLE_QUIC log_zone_debug(zone_name, "ACL, %s, action %s, remote %s%s%s%s%.*s%s", diff --git a/src/knot/server/handler.c b/src/knot/server/handler.c index d57290b2c..394dc26ff 100644 --- a/src/knot/server/handler.c +++ b/src/knot/server/handler.c @@ -108,10 +108,10 @@ void handle_quic_streams(knot_xquic_conn_t *conn, knotd_qdata_params_t *params, if (msg) { #ifdef ENABLE_XDP params_xdp_update(params, KNOTD_QUERY_PROTO_QUIC, msg, - knot_xquic_conn_rtt(conn), conn->tls_session); + knot_xquic_conn_rtt(conn), conn); #endif // ENABLE_XDP } else { - params_update(params, knot_xquic_conn_rtt(conn), conn->tls_session); + params_update(params, knot_xquic_conn_rtt(conn), conn); } handle_quic_stream(conn, stream_id, stream->inbuf_fin, layer, params, ans_buf, sizeof(ans_buf)); diff --git a/src/knot/server/handler.h b/src/knot/server/handler.h index 7d4121339..784435d98 100644 --- a/src/knot/server/handler.h +++ b/src/knot/server/handler.h @@ -52,10 +52,10 @@ inline static knotd_qdata_params_t params_init(knotd_query_proto_t proto, } inline static void params_update(knotd_qdata_params_t *params, uint32_t rtt, - struct gnutls_session_int *session) + struct knot_xquic_conn *conn) { params->measured_rtt = rtt; - params->session = session; + params->quic_conn = conn; } #ifdef ENABLE_XDP @@ -75,14 +75,14 @@ inline static void params_xdp_update(knotd_qdata_params_t *params, knotd_query_proto_t proto, struct knot_xdp_msg *msg, uint32_t rtt, - struct gnutls_session_int *session) + struct knot_xquic_conn *conn) { params->proto = proto; params->remote = (struct sockaddr_storage *)&msg->ip_from; params->local = (struct sockaddr_storage *)&msg->ip_to; params->xdp_msg = msg; params->measured_rtt = rtt; - params->session = session; + params->quic_conn = conn; } #endif // ENABLE_XDP diff --git a/src/knot/server/server.c b/src/knot/server/server.c index ede542a7a..b215ecfb9 100644 --- a/src/knot/server/server.c +++ b/src/knot/server/server.c @@ -545,7 +545,7 @@ static int init_creds(server_t *server, conf_t *conf) } int pin_size = 0; - uint8_t bin_pin[CERT_PIN_LEN], pin[2 * CERT_PIN_LEN]; + uint8_t bin_pin[KNOT_QUIC_PIN_LEN], pin[2 * KNOT_QUIC_PIN_LEN]; size_t bin_pin_size = sizeof(bin_pin); gnutls_x509_crt_t cert; if (knot_xquic_creds_cert(server->quic_creds, &cert) == KNOT_EOK && diff --git a/src/knot/updates/acl.c b/src/knot/updates/acl.c index da904411b..3ec6d4fbe 100644 --- a/src/knot/updates/acl.c +++ b/src/knot/updates/acl.c @@ -14,56 +14,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -#include <gnutls/x509.h> - #include "knot/updates/acl.h" -#include "contrib/wire_ctx.h" - -void cert_pin(gnutls_session_t session, uint8_t *out, size_t *out_len, bool local) -{ - if (session == NULL) { - goto error; - } - - const gnutls_datum_t *data; - if (local) { - data = gnutls_certificate_get_ours(session); - } else { - unsigned count = 0; - data = gnutls_certificate_get_peers(session, &count); - if (count == 0) { - goto error; - } - } - - gnutls_x509_crt_t cert; - int ret = gnutls_x509_crt_init(&cert); - if (ret != GNUTLS_E_SUCCESS) { - goto error; - } - - ret = gnutls_x509_crt_import(cert, &data[0], GNUTLS_X509_FMT_DER); - if (ret != GNUTLS_E_SUCCESS) { - gnutls_x509_crt_deinit(cert); - goto error; - } - - ret = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, out, out_len); - if (ret != GNUTLS_E_SUCCESS) { - gnutls_x509_crt_deinit(cert); - goto error; - } - gnutls_x509_crt_deinit(cert); - - return; -error: - if (out_len != NULL) { - *out_len = 0; - } -} +#include "contrib/wire_ctx.h" +#ifdef ENABLE_QUIC +#include "libknot/quic/quic.h" +#endif // ENABLE_QUIC -bool cert_pin_check(const uint8_t *session_pin, size_t session_pin_size, conf_val_t *pins) +static bool cert_pin_check(const uint8_t *session_pin, size_t session_pin_size, + conf_val_t *pins) { if (pins->code == KNOT_ENOENT) { // No certificate pin authentication required. return true; @@ -295,15 +254,20 @@ static bool check_addr_key(conf_t *conf, conf_val_t *addr_val, conf_val_t *key_v bool acl_allowed(conf_t *conf, conf_val_t *acl, acl_action_t action, const struct sockaddr_storage *addr, knot_tsig_key_t *tsig, const knot_dname_t *zone_name, knot_pkt_t *query, - gnutls_session_t session) + struct knot_xquic_conn *conn) { if (acl == NULL || addr == NULL || tsig == NULL) { return false; } - uint8_t session_pin[CERT_PIN_LEN]; +#ifdef ENABLE_QUIC + uint8_t session_pin[KNOT_QUIC_PIN_LEN]; size_t session_pin_size = sizeof(session_pin); - cert_pin(session, session_pin, &session_pin_size, false); + knot_quic_conn_pin(conn, session_pin, &session_pin_size, false); +#else + uint8_t session_pin[1]; + size_t session_pin_size = 0; +#endif // ENABLE_QUIC while (acl->code == KNOT_EOK) { conf_val_t rmt_val = conf_id_get(conf, C_ACL, C_RMT, acl); @@ -388,15 +352,20 @@ next_acl: } bool rmt_allowed(conf_t *conf, conf_val_t *rmts, const struct sockaddr_storage *addr, - knot_tsig_key_t *tsig, gnutls_session_t session) + knot_tsig_key_t *tsig, struct knot_xquic_conn *conn) { if (!conf->cache.srv_auto_acl) { return false; } - uint8_t session_pin[CERT_PIN_LEN]; +#ifdef ENABLE_QUIC + uint8_t session_pin[KNOT_QUIC_PIN_LEN]; size_t session_pin_size = sizeof(session_pin); - cert_pin(session, session_pin, &session_pin_size, false); + knot_quic_conn_pin(conn, session_pin, &session_pin_size, false); +#else + uint8_t session_pin[1]; + size_t session_pin_size = 0; +#endif // ENABLE_QUIC conf_mix_iter_t iter; conf_mix_iter_init(conf, rmts, &iter); diff --git a/src/knot/updates/acl.h b/src/knot/updates/acl.h index d0d9b5110..88fc289ed 100644 --- a/src/knot/updates/acl.h +++ b/src/knot/updates/acl.h @@ -18,13 +18,10 @@ #include <stdbool.h> #include <sys/socket.h> -#include <gnutls/gnutls.h> #include "libknot/tsig.h" #include "knot/conf/conf.h" -#define CERT_PIN_LEN 32 - /*! \brief ACL actions. */ typedef enum { ACL_ACTION_QUERY = 0, @@ -49,26 +46,6 @@ typedef enum { } acl_update_owner_match_t; /*! - * \brief Gets local or remote certificate pin. - * - * \param session QUIC session. - * \param session_pin Output certificate pin. - * \param session_pin_size Input size of the storage / output size of the stored pin. - */ -void cert_pin(gnutls_session_t session, uint8_t *out, size_t *out_len, bool local); - -/*! - * \brief Checks if remote certificate pin matches the given list. - * - * \param session_pin QUIC session certificate pin. - * \param session_pin_size QUIC session certificate pin size. - * \param pins Configured certificate pins. - * - * \retval True if match. - */ -bool cert_pin_check(const uint8_t *session_pin, size_t session_pin_size, conf_val_t *pins); - -/*! * \brief Checks if the address and/or tsig key matches given ACL list. * * If a proper ACL rule is found and tsig.name is not empty, tsig.secret is filled. @@ -80,14 +57,14 @@ bool cert_pin_check(const uint8_t *session_pin, size_t session_pin_size, conf_va * \param tsig TSIG parameters. * \param zone_name Zone name. * \param query Update query. - * \param session Possible QUIC session. + * \param conn Possible QUIC connection. * * \retval True if authenticated. */ bool acl_allowed(conf_t *conf, conf_val_t *acl, acl_action_t action, const struct sockaddr_storage *addr, knot_tsig_key_t *tsig, const knot_dname_t *zone_name, knot_pkt_t *query, - gnutls_session_t session); + struct knot_xquic_conn *conn); /*! * \brief Checks if the address and/or tsig key matches a remote from the list. @@ -101,9 +78,9 @@ bool acl_allowed(conf_t *conf, conf_val_t *acl, acl_action_t action, * \param rmts Pointer to REMOTE config multivalued identifier. * \param addr IP address. * \param tsig TSIG parameters. - * \param session Possible QUIC session. + * \param conn Possible QUIC connection. * * \retval True if authenticated. */ bool rmt_allowed(conf_t *conf, conf_val_t *rmts, const struct sockaddr_storage *addr, - knot_tsig_key_t *tsig, gnutls_session_t session); + knot_tsig_key_t *tsig, struct knot_xquic_conn *conn); diff --git a/src/libknot/quic/quic.c b/src/libknot/quic/quic.c index 0d16bb247..460b05b7d 100644 --- a/src/libknot/quic/quic.c +++ b/src/libknot/quic/quic.c @@ -21,6 +21,7 @@ #include <ngtcp2/ngtcp2.h> #include <ngtcp2/ngtcp2_crypto.h> #include <ngtcp2/ngtcp2_crypto_gnutls.h> +#include <stdbool.h> #include <stdio.h> #include <string.h> #include <time.h> @@ -380,6 +381,49 @@ uint32_t knot_xquic_conn_rtt(knot_xquic_conn_t *conn) return stat.smoothed_rtt / 1000; // nanosec --> usec } +_public_ +void knot_quic_conn_pin(knot_xquic_conn_t *conn, uint8_t *pin, size_t *pin_size, bool local) +{ + if (conn == NULL) { + goto error; + } + + const gnutls_datum_t *data; + if (local) { + data = gnutls_certificate_get_ours(conn->tls_session); + } else { + unsigned count = 0; + data = gnutls_certificate_get_peers(conn->tls_session, &count); + if (count == 0) { + goto error; + } + } + + gnutls_x509_crt_t cert; + int ret = gnutls_x509_crt_init(&cert); + if (ret != GNUTLS_E_SUCCESS) { + goto error; + } + + ret = gnutls_x509_crt_import(cert, &data[0], GNUTLS_X509_FMT_DER); + if (ret != GNUTLS_E_SUCCESS) { + gnutls_x509_crt_deinit(cert); + goto error; + } + + ret = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, pin, pin_size); + if (ret != GNUTLS_E_SUCCESS) { + gnutls_x509_crt_deinit(cert); + goto error; + } + + gnutls_x509_crt_deinit(cert); +error: + if (pin_size != NULL) { + *pin_size = 0; + } +} + static void knot_quic_rand_cb(uint8_t *dest, size_t destlen, const ngtcp2_rand_ctx *rand_ctx) { (void)rand_ctx; diff --git a/src/libknot/quic/quic.h b/src/libknot/quic/quic.h index aafcf21db..9da4f8099 100644 --- a/src/libknot/quic/quic.h +++ b/src/libknot/quic/quic.h @@ -30,6 +30,8 @@ #include "libknot/quic/quic_conn.h" +#define KNOT_QUIC_PIN_LEN 32 + struct gnutls_x509_crt_int; struct knot_quic_creds; struct knot_quic_session; @@ -118,6 +120,18 @@ bool xquic_conn_timeout(knot_xquic_conn_t *conn, uint64_t *now); uint32_t knot_xquic_conn_rtt(knot_xquic_conn_t *conn); /*! + * \brief Gets local or remote certificate pin. + * + * \note Zero output pin_size value means no certificate available or error. + * + * \param conn QUIC connection. + * \param pin Output certificate pin. + * \param pin_size Input size of the storage / output size of the stored pin. + * \param local Local or remote certificate indication. + */ +void knot_quic_conn_pin(knot_xquic_conn_t *conn, uint8_t *pin, size_t *pin_size, bool local); + +/*! * \brief Create new outgoing QUIC connection. * * \param table QUIC connections table to be added to. |