]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
Merge remote-tracking branch 'origin/master-5' into master docs-develop-merg-ecf55w/deployments/4466
authorOto Šťáva <oto.stava@nic.cz>
Wed, 3 Jul 2024 11:04:19 +0000 (13:04 +0200)
committerOto Šťáva <oto.stava@nic.cz>
Wed, 3 Jul 2024 11:04:19 +0000 (13:04 +0200)
1  2 
NEWS
daemon/tls.c
lib/layer/iterate.c

diff --cc NEWS
index 0046e7f2f816375f98b01a54c401e87c633a73a7,0b46d3780247dffb522e6dd75f48f4f495d8f19f..01ecf0b2c411619af54ed4f0ad5f80e393d6078a
--- 1/NEWS
--- 2/NEWS
+++ b/NEWS
- Knot Resolver 5.7.3 (2024-0m-dd)
 +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
 +  <https://www.knot-resolver.cz/documentation/latest/config-cache-predict.html>`_
 +  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.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 daf6a7bed231c1278e601b1263b410104218462a,e821ff964c4dd85b8c26c77d11c2e00777b95f89..c77c5c2b34fd2a49face6138d6d7a147a2cae26b
@@@ -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");
        }
  
        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
Simple merge