From: Oto Šťáva Date: Wed, 3 Jul 2024 11:04:19 +0000 (+0200) Subject: Merge remote-tracking branch 'origin/master-5' into master X-Git-Tag: v6.0.8~7^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=84428783191be37224bf79bffc238b5021aa356d;p=thirdparty%2Fknot-resolver.git Merge remote-tracking branch 'origin/master-5' into master --- 84428783191be37224bf79bffc238b5021aa356d diff --cc NEWS index 0046e7f2f,0b46d3780..01ecf0b2c --- a/NEWS +++ b/NEWS @@@ -1,119 -1,12 +1,128 @@@ +Knot Resolver 6.0.8 (2024-0m-dd) +================================ + +Improvements +------------ +- TLS (DoT, DoH): respect crypto policy overrides in OS (!1526) +- arch package: fix after they renamed a dependency (!1536) +- manager: export metrics to JSON via management HTTP API (!1527) + + * JSON is the new default metrics output format + * the ``prometheus-client`` Python package is now an optional dependency, + required only for Prometheus export to work +- cache: prefetching records + + * predict module: prefetching expiring records moved to prefetch module + * prefetch module: new module to prefetch expiring records +- stats: add separate metrics for IPv6 and IPv4 (!1545) +- remove unused dependency on `libedit` (!1553) ++- add the fresh DNSSEC root key "KSK-2024" already, Key ID 38696 (!1556) + +- manager: policy-loader: new component for separate loading policy rules (!1540) + + The ``policy-loader`` ensures that configured policies are loaded into the rules database + where they are made available to all running kresd workers. This loading is no longer done + by all kresd workers as it was before, so this should significantly improve the resolver's + startup/reload time when loading large sets of policy rules, e.g. large RPZs. + +.. TODO: Change the link below to a versioned one when releasing. + +Incompatible changes +-------------------- +- cache: the ``cache.prediction`` configuration property has been reorganized + into ``cache.prefetch.expiring`` and ``cache.prefetch.prediction``, changing + the default behaviour as well. See the `relevant documentation section + `_ + for more. + +Bugfixes +-------- +- fix startup with `dnssec: false` (!1548) + + +Knot Resolver 6.0.7 (2024-03-27) +================================ + +Improvements +------------ +- manager: clear the cache via management HTTP API (#876, !1491) +- manager: added support for Python 3.12 and removed for 3.7 (!1502) +- manager: use build-time install prefix to execute `kresd` instead of PATH (!1511) +- docs: documentation is now separated into user and developer parts (!1514) +- daemon: ignore UDP requests from ports < 1024 (!1507) +- manager: increase startup timeout for processes (!1518, !1520) +- local-data: increase default DB size to 2G on 64-bit platforms (!1518) + +Bugfixes +-------- +- fix listening by interface name containing dashes (#900, !1500) +- fix kresctl http request timeout (!1505) +- fix RPZ if it contains apex NS record (!1516) +- fix RPZ if SOA is repated, as usual in AXFR output (!1521) +- avoid RPZ overriding the root SOA (!1521) +- fix on 32-bit systems with 64-bit time_t (!1510) +- fix paths to knot-dns libs if exec_prefix != prefix (!1503) +- manager: add missing early check that neither a custom port nor TLS is set for + authoritative server forwarding (#902, !1505) + + +Knot Resolver 6.0.6 (2024-02-13) +================================ + +Security +-------- +- CVE-2023-50868: NSEC3 closest encloser proof can exhaust CPU + + * validator: lower the NSEC3 iteration limit (150 -> 50) + * validator: similarly also limit excessive NSEC3 salt length + * cache: limit the amount of work on SHA1 in NSEC3 aggressive cache + * validator: limit the amount of work on SHA1 in NSEC3 proofs + * validator: refuse to validate answers with more than 8 NSEC3 records + +- CVE-2023-50387 "KeyTrap": DNSSEC verification complexity + could be exploited to exhaust CPU resources and stall DNS resolvers. + Solution boils down mainly to limiting crypto-validations per packet. + + We would like to thank Elias Heftrig, Haya Schulmann, Niklas Vogel and Michael Waidner + from the German National Research Center for Applied Cybersecurity ATHENE + for bringing this vulnerability to our attention. + +Improvements +------------ +- update addresses of B.root-servers.net (!1478) +- tweak the default run_dir on non-Linux (!1481) + +Bugfixes +-------- +- fix potential SERVFAIL deadlocks if net.ipv6 = false (#880) +- fix validation of RRsets around 64 KiB size; needs libknot >= 3.4 (!1497) + + +Knot Resolver 6.0.5 (2024-01-09) +================================ + +6.0.x are "early access" versions, +not generally recommended for production use. + +6.0 contains biggest changes in the history of Knot Resolver releases. +You will have to rewrite your configuration. See documentation, in particular: +https://www.knot-resolver.cz/documentation/latest/upgrading-to-6.html + + + + +5.x branch longterm support +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + - Knot Resolver 5.7.3 (2024-0m-dd) + Knot Resolver 5.7.4 (2024-06-dd) + ================================ + + Improvements + ------------ + - add the fresh DNSSEC root key "KSK-2024" already, Key ID 38696 (!1556) + + + Knot Resolver 5.7.3 (2024-05-30) ================================ Improvements diff --cc daemon/tls.c index daf6a7bed,e821ff964..c77c5c2b3 --- a/daemon/tls.c +++ b/daemon/tls.c @@@ -789,7 -992,7 +789,7 @@@ static int client_verify_pin(const unsi * * \returns GNUTLS_E_SUCCESS if certificate chain is valid, any other value is an error */ - static int client_verify_certchain(gnutls_session_t tls_session, const char *hostname) -static int client_verify_certchain(struct tls_common_ctx *ctx, const char *hostname) ++static int client_verify_certchain(struct pl_tls_sess_data *tls, const char *hostname) { if (kr_fails_assert(hostname)) { kr_log_error(TLSCLIENT, "internal config inconsistency: no hostname set\n"); @@@ -797,22 -1000,24 +797,24 @@@ } unsigned int status; - int ret = gnutls_certificate_verify_peers3(tls_session, hostname, &status); - int ret = gnutls_certificate_verify_peers3(ctx->tls_session, hostname, &status); ++ int ret = gnutls_certificate_verify_peers3(tls->tls_session, hostname, &status); if ((ret == GNUTLS_E_SUCCESS) && (status == 0)) { return GNUTLS_E_SUCCESS; } - const char *addr_str = kr_straddr(session_get_peer(ctx->session)); ++ const char *addr_str = kr_straddr(session2_get_peer(tls->h.session)); if (ret == GNUTLS_E_SUCCESS) { gnutls_datum_t msg; ret = gnutls_certificate_verification_status_print( - status, gnutls_certificate_type_get(tls_session), &msg, 0); - status, gnutls_certificate_type_get(ctx->tls_session), &msg, 0); ++ status, gnutls_certificate_type_get(tls->tls_session), &msg, 0); if (ret == GNUTLS_E_SUCCESS) { - kr_log_error(TLSCLIENT, "failed to verify peer certificate: " - "%s\n", msg.data); + kr_log_error(TLSCLIENT, "failed to verify peer certificate of %s: " + "%s\n", addr_str, msg.data); gnutls_free(msg.data); } else { - kr_log_error(TLSCLIENT, "failed to verify peer certificate: " + kr_log_error(TLSCLIENT, "failed to verify peer certificate of %s: " "unable to print reason: %s (%s)\n", + addr_str, gnutls_strerror(ret), gnutls_strerror_name(ret)); } /* gnutls_certificate_verification_status_print end */ } else { @@@ -852,150 -1058,20 +855,150 @@@ static int client_verify_certificate(gn return GNUTLS_E_CERTIFICATE_ERROR; } - if (ctx->params->pins.len > 0) + if (tls->client_params->pins.len > 0) /* check hash of the certificate but ignore everything else */ - return client_verify_pin(cert_list_size, cert_list, ctx->params); + return client_verify_pin(cert_list_size, cert_list, tls->client_params); else - return client_verify_certchain(tls->tls_session, tls->client_params->hostname); - return client_verify_certchain(&ctx->c, ctx->params->hostname); ++ return client_verify_certchain(tls, tls->client_params->hostname); } -struct tls_client_ctx *tls_client_ctx_new(tls_client_param_t *entry, - struct worker_ctx *worker) +static int tls_pull_timeout_func(gnutls_transport_ptr_t h, unsigned int ms) { - struct tls_client_ctx *ctx = calloc(1, sizeof (struct tls_client_ctx)); - if (!ctx) { - return NULL; + struct pl_tls_sess_data *tls = h; + if (kr_fails_assert(tls)) { + errno = EFAULT; + return -1; + } + + size_t avail = protolayer_queue_count_payload(&tls->unwrap_queue); + VERBOSE_MSG(tls->client_side, "timeout check: available: %zu\n", avail); + if (!avail) { + errno = EAGAIN; + return -1; + } + return avail; +} + +static int pl_tls_sess_data_deinit(struct pl_tls_sess_data *tls) +{ + if (tls->tls_session) { + /* Don't terminate TLS connection, just tear it down */ + gnutls_deinit(tls->tls_session); + tls->tls_session = NULL; } + + if (tls->client_side) { + tls_client_param_unref(tls->client_params); + } else { + tls_credentials_release(tls->server_credentials); + } + wire_buf_deinit(&tls->unwrap_buf); + queue_deinit(tls->unwrap_queue); /* TODO: break contexts? */ + return kr_ok(); +} + +static int pl_tls_sess_server_init(struct session2 *session, + struct pl_tls_sess_data *tls) +{ + if (kr_fails_assert(the_worker && the_engine)) + return kr_error(EINVAL); + + if (!the_network->tls_credentials) { + the_network->tls_credentials = tls_get_ephemeral_credentials(); + if (!the_network->tls_credentials) { + kr_log_error(TLS, "X.509 credentials are missing, and ephemeral credentials failed; no TLS\n"); + return kr_error(EINVAL); + } + kr_log_info(TLS, "Using ephemeral TLS credentials\n"); + tls_credentials_log_pins(the_network->tls_credentials); + } + + time_t now = time(NULL); + if (the_network->tls_credentials->valid_until != GNUTLS_X509_NO_WELL_DEFINED_EXPIRATION) { + if (the_network->tls_credentials->ephemeral_servicename) { + /* ephemeral cert: refresh if due to expire within a week */ + if (now >= the_network->tls_credentials->valid_until - EPHEMERAL_CERT_EXPIRATION_SECONDS_RENEW_BEFORE) { + struct tls_credentials *newcreds = tls_get_ephemeral_credentials(); + if (newcreds) { + tls_credentials_release(the_network->tls_credentials); + the_network->tls_credentials = newcreds; + kr_log_info(TLS, "Renewed expiring ephemeral X.509 cert\n"); + } else { + kr_log_error(TLS, "Failed to renew expiring ephemeral X.509 cert, using existing one\n"); + } + } + } else { + /* non-ephemeral cert: warn once when certificate expires */ + if (now >= the_network->tls_credentials->valid_until) { + kr_log_error(TLS, "X.509 certificate has expired!\n"); + the_network->tls_credentials->valid_until = GNUTLS_X509_NO_WELL_DEFINED_EXPIRATION; + } + } + } + + int flags = GNUTLS_SERVER | GNUTLS_NONBLOCK; +#if GNUTLS_VERSION_NUMBER >= 0x030705 + if (gnutls_check_version("3.7.5")) + flags |= GNUTLS_NO_TICKETS_TLS12; +#endif + int ret = gnutls_init(&tls->tls_session, flags); + if (ret != GNUTLS_E_SUCCESS) { + kr_log_error(TLS, "gnutls_init(): %s (%d)\n", gnutls_strerror_name(ret), ret); + pl_tls_sess_data_deinit(tls); + return ret; + } + + tls->server_credentials = tls_credentials_reserve(the_network->tls_credentials); + ret = gnutls_credentials_set(tls->tls_session, GNUTLS_CRD_CERTIFICATE, + tls->server_credentials->credentials); + if (ret != GNUTLS_E_SUCCESS) { + kr_log_error(TLS, "gnutls_credentials_set(): %s (%d)\n", gnutls_strerror_name(ret), ret); + pl_tls_sess_data_deinit(tls); + return ret; + } + + ret = kres_gnutls_set_priority(tls->tls_session); + if (ret != GNUTLS_E_SUCCESS) { + pl_tls_sess_data_deinit(tls); + return ret; + } + + tls->client_side = false; + wire_buf_init(&tls->unwrap_buf, UNWRAP_BUF_SIZE); + + gnutls_transport_set_pull_function(tls->tls_session, kres_gnutls_pull); + gnutls_transport_set_vec_push_function(tls->tls_session, kres_gnutls_vec_push); + gnutls_transport_set_ptr(tls->tls_session, tls); + + if (the_network->tls_session_ticket_ctx) { + tls_session_ticket_enable(the_network->tls_session_ticket_ctx, + tls->tls_session); + } + + const gnutls_datum_t *alpn = &tls_grp_alpn[session->proto]; + if (alpn->size) { /* ALPN is a non-empty string */ + flags = 0; +#if GNUTLS_VERSION_NUMBER >= 0x030500 + /* Mandatory ALPN means the protocol must match if and + * only if ALPN extension is used by the client. */ + flags |= GNUTLS_ALPN_MANDATORY; +#endif + + ret = gnutls_alpn_set_protocols(tls->tls_session, alpn, 1, flags); + if (ret != GNUTLS_E_SUCCESS) { + kr_log_error(TLS, "gnutls_alpn_set_protocols(): %s (%d)\n", gnutls_strerror_name(ret), ret); + pl_tls_sess_data_deinit(tls); + return ret; + } + } + + return kr_ok(); +} + +static int pl_tls_sess_client_init(struct session2 *session, + struct pl_tls_sess_data *tls, + tls_client_param_t *param) +{ unsigned int flags = GNUTLS_CLIENT | GNUTLS_NONBLOCK #ifdef GNUTLS_ENABLE_FALSE_START | GNUTLS_ENABLE_FALSE_START