From d273f50ec2ad98288d496077c9e6989f46f526b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=A1k?= <jan.hak@nic.cz> Date: Mon, 2 May 2022 13:31:47 +0200 Subject: [PATCH] utils: small change of common API for TLS in kdig and knsupdate Move ALPN and settings in context initialization --- src/utils/common/https.c | 13 ++++---- src/utils/common/https.h | 4 ++- src/utils/common/netio.c | 29 ++++++++++++------ src/utils/common/tls.c | 64 ++++++++++++++++++++++++---------------- src/utils/common/tls.h | 11 ++++--- 5 files changed, 75 insertions(+), 46 deletions(-) diff --git a/src/utils/common/https.c b/src/utils/common/https.c index bc7912bfea..e432b0524f 100644 --- a/src/utils/common/https.c +++ b/src/utils/common/https.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 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 @@ -76,14 +76,15 @@ void https_params_clean(https_params_t *params) static const char default_path[] = "/dns-query"; static const char default_query[] = "?dns="; -static const gnutls_datum_t https_protocols[] = { - { (unsigned char *)"h2", 2 } -}; - static const nghttp2_settings_entry settings[] = { { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, HTTPS_MAX_STREAMS } }; +const gnutls_datum_t doh_alpn = { + .data = (unsigned char *)"h2", + .size = 2 +}; + static bool https_status_is_redirect(unsigned long status) { switch (status) { @@ -326,7 +327,7 @@ int https_ctx_connect(https_ctx_t *ctx, int sockfd, const char *remote, } // Create TLS connection - int ret = tls_ctx_connect(ctx->tls, sockfd, remote, fastopen, addr, https_protocols); + int ret = tls_ctx_connect(ctx->tls, sockfd, remote, fastopen, addr); if (ret != KNOT_EOK) { return ret; } diff --git a/src/utils/common/https.h b/src/utils/common/https.h index 1ab42642ab..6c54baee15 100644 --- a/src/utils/common/https.h +++ b/src/utils/common/https.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 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 @@ -46,6 +46,8 @@ void https_params_clean(https_params_t *params); #include "utils/common/tls.h" +extern const gnutls_datum_t doh_alpn; + /*! \brief Structure that stores data source for DATA frames. */ typedef struct { const uint8_t *buf; diff --git a/src/utils/common/netio.c b/src/utils/common/netio.c index bd7ec1aea1..233b5d8d02 100644 --- a/src/utils/common/netio.c +++ b/src/utils/common/netio.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 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 @@ -218,22 +218,33 @@ int net_init(const srv_info_t *local, // Prepare for TLS. if (tls_params != NULL && tls_params->enable) { - int ret = tls_ctx_init(&net->tls, tls_params, net->wait); - if (ret != KNOT_EOK) { - net_clean(net); - return ret; - } - + int ret = 0; #ifdef LIBNGHTTP2 // Prepare for HTTPS. if (https_params != NULL && https_params->enable) { + ret = tls_ctx_init(&net->tls, tls_params, + GNUTLS_NONBLOCK, net->wait, + &doh_alpn, 1, NULL); + if (ret != KNOT_EOK) { + net_clean(net); + return ret; + } ret = https_ctx_init(&net->https, &net->tls, https_params); if (ret != KNOT_EOK) { net_clean(net); return ret; } - } + } else #endif //LIBNGHTTP2 + { + ret = tls_ctx_init(&net->tls, tls_params, + GNUTLS_NONBLOCK, net->wait, + &dot_alpn, 1, NULL); + if (ret != KNOT_EOK) { + net_clean(net); + return ret; + } + } } return KNOT_EOK; @@ -392,7 +403,7 @@ int net_connect(net_t *net) #endif //LIBNGHTTP2 // Establish TLS connection. ret = tls_ctx_connect(&net->tls, sockfd, net->tls.params->sni, fastopen, - (struct sockaddr_storage *)net->srv->ai_addr, &dot_alpn); + (struct sockaddr_storage *)net->srv->ai_addr); #ifdef LIBNGHTTP2 } #endif //LIBNGHTTP2 diff --git a/src/utils/common/tls.c b/src/utils/common/tls.c index 5cbbb420ea..b792b0df4a 100644 --- a/src/utils/common/tls.c +++ b/src/utils/common/tls.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 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 @@ -421,7 +421,10 @@ static int verify_certificate(gnutls_session_t session) return GNUTLS_E_SUCCESS; } -int tls_ctx_init(tls_ctx_t *ctx, const tls_params_t *params, int wait) +int tls_ctx_init(tls_ctx_t *ctx, const tls_params_t *params, + unsigned int flags, int wait, const gnutls_datum_t *alpn, + size_t alpn_size, const char *priority) + { if (ctx == NULL || params == NULL || !params->enable) { return KNOT_EINVAL; @@ -465,7 +468,7 @@ int tls_ctx_init(tls_ctx_t *ctx, const tls_params_t *params, int wait) } } - gnutls_certificate_set_verify_function(ctx->credentials, verify_certificate); + // gnutls_certificate_set_verify_function(ctx->credentials, verify_certificate); // Setup client keypair if specified. Both key and cert files must be provided. if (params->keyfile != NULL && params->certfile != NULL) { @@ -494,34 +497,48 @@ int tls_ctx_init(tls_ctx_t *ctx, const tls_params_t *params, int wait) return KNOT_ERROR; } - return KNOT_EOK; -} - -int tls_ctx_connect(tls_ctx_t *ctx, int sockfd, const char *remote, bool fastopen, - struct sockaddr_storage *addr, const gnutls_datum_t *protocol) -{ - if (ctx == NULL) { - return KNOT_EINVAL; + ret = gnutls_init(&ctx->session, GNUTLS_CLIENT | flags); + if (ret != GNUTLS_E_SUCCESS) { + return KNOT_ENOMEM; } - int ret = gnutls_init(&ctx->session, GNUTLS_CLIENT | GNUTLS_NONBLOCK); - if (ret != GNUTLS_E_SUCCESS) { - return KNOT_NET_ECONNECT; + if (alpn != NULL) { + ret = gnutls_alpn_set_protocols(ctx->session, alpn, alpn_size, 0); + if (ret != GNUTLS_E_SUCCESS) { + gnutls_deinit(ctx->session); + return KNOT_NET_ECONNECT; + } } - ret = gnutls_set_default_priority(ctx->session); + if (priority != NULL) { + ret = gnutls_priority_set_direct(ctx->session, priority, NULL); + } else { + ret = gnutls_set_default_priority(ctx->session); + } if (ret != GNUTLS_E_SUCCESS) { gnutls_deinit(ctx->session); - return KNOT_NET_ECONNECT; + return KNOT_EINVAL; } ret = gnutls_credentials_set(ctx->session, GNUTLS_CRD_CERTIFICATE, ctx->credentials); if (ret != GNUTLS_E_SUCCESS) { gnutls_deinit(ctx->session); - return KNOT_NET_ECONNECT; + return KNOT_ERROR; + } + + return KNOT_EOK; +} + +int tls_ctx_connect(tls_ctx_t *ctx, int sockfd, const char *remote, bool fastopen, + struct sockaddr_storage *addr) +{ + if (ctx == NULL) { + return KNOT_EINVAL; } + int ret = 0; + // TODO mayble also move to `tls_ctx_init` if (remote != NULL) { ret = gnutls_server_name_set(ctx->session, GNUTLS_NAME_DNS, remote, strlen(remote)); @@ -547,14 +564,6 @@ int tls_ctx_connect(tls_ctx_t *ctx, int sockfd, const char *remote, bool fastope gnutls_handshake_set_timeout(ctx->session, 1000 * ctx->wait); - if (protocol != NULL) { - ret = gnutls_alpn_set_protocols(ctx->session, protocol, 1, 0); - if (ret != GNUTLS_E_SUCCESS) { - gnutls_deinit(ctx->session); - return KNOT_NET_ECONNECT; - } - } - // Initialize poll descriptor structure. struct pollfd pfd = { .fd = sockfd, @@ -688,7 +697,6 @@ void tls_ctx_close(tls_ctx_t *ctx) } gnutls_bye(ctx->session, GNUTLS_SHUT_RDWR); - gnutls_deinit(ctx->session); } void tls_ctx_deinit(tls_ctx_t *ctx) @@ -701,6 +709,10 @@ void tls_ctx_deinit(tls_ctx_t *ctx) gnutls_certificate_free_credentials(ctx->credentials); ctx->credentials = NULL; } + if (ctx->session != NULL) { + gnutls_deinit(ctx->session); + ctx->session = NULL; + } } void print_tls(const tls_ctx_t *ctx) diff --git a/src/utils/common/tls.h b/src/utils/common/tls.h index c6014f4988..ddf3d4f5e1 100644 --- a/src/utils/common/tls.h +++ b/src/utils/common/tls.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 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 @@ -65,9 +65,12 @@ void tls_params_init(tls_params_t *params); int tls_params_copy(tls_params_t *dst, const tls_params_t *src); void tls_params_clean(tls_params_t *params); -int tls_ctx_init(tls_ctx_t *ctx, const tls_params_t *params, int wait); -int tls_ctx_connect(tls_ctx_t *ctx, int sockfd, const char *remote, bool fastopen, - struct sockaddr_storage *addr, const gnutls_datum_t *protocol); +int tls_ctx_init(tls_ctx_t *ctx, const tls_params_t *params, + unsigned int flags, int wait, const gnutls_datum_t *alpn, + size_t alpn_size, const char *priority); +int tls_ctx_connect(tls_ctx_t *ctx, int sockfd, const char *remote, + bool fastopen, struct sockaddr_storage *addr); + int tls_ctx_send(tls_ctx_t *ctx, const uint8_t *buf, const size_t buf_len); int tls_ctx_receive(tls_ctx_t *ctx, uint8_t *buf, const size_t buf_len); void tls_ctx_close(tls_ctx_t *ctx); -- GitLab