diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-09-12 04:45:08 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-09-12 04:45:08 +0000 |
commit | 3ade2b375d3e928a06a39bb5ce48e59ea054f9c8 (patch) | |
tree | 23c9115f88363ed22bc4afbeb4901994d036f189 /src/utils/knsupdate | |
parent | Releasing progress-linux version 3.3.9-1~progress7.99u1. (diff) | |
download | knot-3ade2b375d3e928a06a39bb5ce48e59ea054f9c8.tar.xz knot-3ade2b375d3e928a06a39bb5ce48e59ea054f9c8.zip |
Merging upstream version 3.4.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/utils/knsupdate')
-rw-r--r-- | src/utils/knsupdate/knsupdate_exec.c | 12 | ||||
-rw-r--r-- | src/utils/knsupdate/knsupdate_params.c | 160 | ||||
-rw-r--r-- | src/utils/knsupdate/knsupdate_params.h | 8 |
3 files changed, 155 insertions, 25 deletions
diff --git a/src/utils/knsupdate/knsupdate_exec.c b/src/utils/knsupdate/knsupdate_exec.c index e201711..d716ffb 100644 --- a/src/utils/knsupdate/knsupdate_exec.c +++ b/src/utils/knsupdate/knsupdate_exec.c @@ -452,15 +452,23 @@ static int pkt_sendrecv(knsupdate_params_t *params) return -1; } + ret = net_init_crypto(&net, ¶ms->tls_params, NULL, ¶ms->quic_params); + if (ret != 0) { + ERR("failed to initialize crypto context (%s)", knot_strerror(ret)); + net_clean(&net); + return -1; + } + ret = net_connect(&net); - DBG("%s: send_msg = %d", __func__, net.sockfd); if (ret != KNOT_EOK) { + ERR("failed to connect (%s)", knot_strerror(ret)); net_clean(&net); return -1; } ret = net_send(&net, params->query->wire, params->query->size); if (ret != KNOT_EOK) { + ERR("failed to send update (%s)", knot_strerror(ret)); net_close(&net); net_clean(&net); return -1; @@ -471,8 +479,8 @@ static int pkt_sendrecv(knsupdate_params_t *params) /* Wait for reception. */ int rb = net_receive(&net, params->answer->wire, params->answer->max_size); - DBG("%s: receive_msg = %d", __func__, rb); if (rb <= 0) { + ERR("failed to receive response (%s)", knot_strerror(rb)); net_close(&net); net_clean(&net); return -1; diff --git a/src/utils/knsupdate/knsupdate_params.c b/src/utils/knsupdate/knsupdate_params.c index f9fa41f..5aaf808 100644 --- a/src/utils/knsupdate/knsupdate_params.c +++ b/src/utils/knsupdate/knsupdate_params.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 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 @@ -26,6 +26,7 @@ #include "utils/common/netio.h" #include "libknot/libknot.h" #include "libknot/tsig.h" +#include "contrib/base64.h" #include "contrib/mempattern.h" #include "contrib/strtonum.h" #include "contrib/ucw/mempool.h" @@ -90,6 +91,8 @@ static int knsupdate_init(knsupdate_params_t *params) init_list(¶ms->update_list); init_list(¶ms->prereq_list); + tls_params_init(¶ms->tls_params); + /* Initialize memory context. */ mm_ctx_mempool(¶ms->mm, MM_DEFAULT_BLKSIZE); @@ -142,6 +145,9 @@ void knsupdate_clean(knsupdate_params_t *params) knot_pkt_free(params->answer); knot_tsig_key_deinit(¶ms->tsig_key); + tls_params_clean(¶ms->tls_params); + quic_params_clean(¶ms->quic_params); + /* Clean up the structure. */ mp_delete(params->mm.ctx); memset(params, 0, sizeof(*params)); @@ -172,9 +178,31 @@ void knsupdate_reset(knsupdate_params_t *params) static void print_help(void) { - printf("Usage: %s [-d] [-v] [-k keyfile | -y [hmac:]name:key]\n" - " [-p port] [-t timeout] [-r retries] [filename]\n", - PROGRAM_NAME); + printf("Usage:\n" + " %s [-T] [options] [filename]\n" + " %s [-S | -Q] [tls_options] [options] [filename]\n" + "\n" + "Options:\n" + " -T, --tcp Use TCP protocol.\n" + " -S, --tls Use TLS protocol.\n" + " -Q, --quic Use QUIC protocol.\n" + " -p, --port <num> Remote port.\n" + " -r, --retry <num> Number of retries over UDP.\n" + " -t, --timeout <num> Update timeout.\n" + " -y, --tsig <str> TSIG key in the form [alg:]name:key.\n" + " -k, --tsigfile <path> Path to a TSIG key file.\n" + " -d, --debug Debug mode output.\n" + " -h, --help Print the program help.\n" + " -V, --version Print the program version.\n" + "\n" + "QUIC/TLS options:\n" + " -H, --hostname <str> Remote hostname validation.\n" + " -P, --pin <base64> Certificate key PIN.\n" + " -A, --ca [<path>] Path to a CA file.\n" + " -E, --certfile <path> Path to a client certificate file.\n" + " -K, --keyfile <path> Path to a client key file.\n" + " -s, --sni <str> Remote SNI.\n", + PROGRAM_NAME, PROGRAM_NAME); } int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]) @@ -188,40 +216,74 @@ int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]) return ret; } - // Long options. + const char *opts_str = "dhvTSQV::p:r:t:y:k:H:P:A::E:K:s:"; struct option opts[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, + { "debug", no_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "tcp", no_argument, NULL, 'T' }, + { "tls", no_argument, NULL, 'S' }, + { "quic", no_argument, NULL, 'Q' }, + { "version", optional_argument, NULL, 'V' }, + { "port", required_argument, NULL, 'p' }, + { "retry", required_argument, NULL, 'r' }, + { "timeout", required_argument, NULL, 't' }, + { "tsig", required_argument, NULL, 'y' }, + { "tsigfile", required_argument, NULL, 'k' }, + { "hostname", required_argument, NULL, 'H' }, + { "pin", required_argument, NULL, 'P' }, + { "ca", optional_argument, NULL, 'A' }, + { "certfile", required_argument, NULL, 'E' }, + { "keyfile", required_argument, NULL, 'K' }, + { "sni", required_argument, NULL, 's' }, { NULL } }; - /* Command line options processing. */ + bool default_port = true; + int opt = 0; - while ((opt = getopt_long(argc, argv, "dhDvVp:t:r:y:k:", opts, NULL)) - != -1) { + while ((opt = getopt_long(argc, argv, opts_str, opts, NULL)) != -1) { switch (opt) { case 'd': - case 'D': /* Extra debugging. */ msg_enable_debug(1); break; case 'h': print_help(); params->stop = true; return KNOT_EOK; - case 'v': + case 'v': // Compatibility with nsupdate. + case 'T': params->protocol = PROTO_TCP; break; + case 'S': + params->protocol = PROTO_TCP; + + params->tls_params.enable = true; + + if (default_port) { + free(params->server->service); + params->server->service = strdup(DEFAULT_DNS_TLS_PORT); + } + break; + case 'Q': + params->protocol = PROTO_UDP; + + params->tls_params.enable = true; + params->quic_params.enable = true; + + if (default_port) { + free(params->server->service); + params->server->service = strdup(DEFAULT_DNS_QUIC_PORT); + } + break; case 'V': - print_version(PROGRAM_NAME); + print_version(PROGRAM_NAME, optarg != NULL); params->stop = true; return KNOT_EOK; case 'p': + assert(optarg); + default_port = false; free(params->server->service); params->server->service = strdup(optarg); - if (!params->server->service) { - ERR("failed to set default port '%s'", optarg); - return KNOT_ENOMEM; - } break; case 'r': ret = str_to_u32(optarg, ¶ms->retries); @@ -241,7 +303,7 @@ int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]) knot_tsig_key_deinit(¶ms->tsig_key); ret = knot_tsig_key_init_str(¶ms->tsig_key, optarg); if (ret != KNOT_EOK) { - ERR("failed to parse key '%s'", optarg); + ERR("failed to parse TSIG key '%s'", optarg); return ret; } break; @@ -249,9 +311,63 @@ int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]) knot_tsig_key_deinit(¶ms->tsig_key); ret = knot_tsig_key_init_file(¶ms->tsig_key, optarg); if (ret != KNOT_EOK) { - ERR("failed to parse keyfile '%s'", optarg); + ERR("failed to parse TSIG keyfile '%s'", optarg); + return ret; + } + break; + case 'H': + assert(optarg); + free(params->tls_params.hostname); + params->tls_params.hostname = strdup(optarg); + break; + case 'P': + assert(optarg); + uint8_t pin[64] = { 0 }; + ret = knot_base64_decode((const uint8_t *)optarg, strlen(optarg), pin, sizeof(pin)); + if (ret < 0) { + ERR("invalid certificate pin %s", optarg); return ret; + } else if (ret != CERT_PIN_LEN) { // Check for 256-bit value. + ERR("invalid SHA256 hash length of certificate pin %s", optarg); + return KNOT_EINVAL; } + + uint8_t *item = malloc(1 + ret); // 1 ~ leading data length. + if (item == NULL) { + return KNOT_ENOMEM; + } + item[0] = ret; + memcpy(&item[1], pin, ret); + + if (ptrlist_add(¶ms->tls_params.pins, item, NULL) == NULL) { + return KNOT_ENOMEM; + } + + break; + case 'A': + if (optarg == NULL) { + params->tls_params.system_ca = true; + break; + } + if (ptrlist_add(¶ms->tls_params.ca_files, strdup(optarg), NULL) == NULL) { + ERR("failed to set CA file '%s'", optarg); + return KNOT_ENOMEM; + } + break; + case 'E': + assert(optarg); + free(params->tls_params.certfile); + params->tls_params.certfile = strdup(optarg); + break; + case 'K': + assert(optarg); + free(params->tls_params.keyfile); + params->tls_params.keyfile = strdup(optarg); + break; + case 's': + assert(optarg); + free(params->tls_params.sni); + params->tls_params.sni = strdup(optarg); break; default: print_help(); @@ -259,8 +375,8 @@ int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]) } } - /* No retries for TCP. */ - if (params->protocol == PROTO_TCP) { + /* Retries only for UDP. */ + if (params->protocol == PROTO_TCP || params->quic_params.enable) { params->retries = 0; } else { /* If wait/tries < 1 s, set 1 second for each try. */ @@ -277,7 +393,7 @@ int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]) ptrlist_add(¶ms->qfiles, argv[optind], ¶ms->mm); } - return ret; + return KNOT_EOK; } int knsupdate_set_ttl(knsupdate_params_t *params, const uint32_t ttl) diff --git a/src/utils/knsupdate/knsupdate_params.h b/src/utils/knsupdate/knsupdate_params.h index 1933244..fbf30e5 100644 --- a/src/utils/knsupdate/knsupdate_params.h +++ b/src/utils/knsupdate/knsupdate_params.h @@ -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 @@ -20,7 +20,9 @@ #include "utils/common/netio.h" #include "utils/common/params.h" +#include "utils/common/quic.h" #include "utils/common/sign.h" +#include "utils/common/tls.h" #include "libknot/libknot.h" #include "libzscanner/scanner.h" #include "contrib/ucw/lists.h" @@ -63,6 +65,10 @@ typedef struct { style_t style; /*!< Memory context. */ knot_mm_t mm; + /*!< TLS params. */ + tls_params_t tls_params; + /*!< QUIC params. */ + quic_params_t quic_params; } knsupdate_params_t; int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]); |