#include "knot/query/layer.h"
#include "knot/query/query.h"
#include "knot/query/requestor.h"
+#include "knot/server/server.h"
static bool match_key_ds(knot_kasp_key_t *key, knot_rdata_t *ds)
{
};
static int try_ds(conf_t *conf, const knot_dname_t *zone_name, const conf_remote_t *parent,
- knot_kasp_key_t *key, knot_kasp_key_t *not_key, size_t timeout, uint32_t *ds_ttl)
+ knot_kasp_key_t *key, knot_kasp_key_t *not_key, server_t *server,
+ size_t timeout, uint32_t *ds_ttl)
{
// TODO: Abstract interface to issue DNS queries. This is almost copy-pasted.
return KNOT_ENOMEM;
}
- knot_request_t *req = knot_request_make(NULL, parent, pkt, 0);
+ knot_request_t *req = knot_request_make(NULL, parent, pkt, server->quic_creds, 0);
if (req == NULL) {
knot_request_free(req, NULL);
knot_requestor_clear(&requestor);
}
static bool parents_have_ds(conf_t *conf, kdnssec_ctx_t *kctx, knot_kasp_key_t *key,
- size_t timeout, uint32_t *max_ds_ttl)
+ server_t *server, size_t timeout, uint32_t *max_ds_ttl)
{
bool success = false;
knot_dynarray_foreach(parent, knot_kasp_parent_t, i, kctx->policy->parents) {
for (size_t j = 0; j < i->addrs; j++) {
uint32_t ds_ttl = 0;
int ret = try_ds(conf, kctx->zone->dname, &i->addr[j], key,
- get_not_key(kctx, key), timeout, &ds_ttl);
+ get_not_key(kctx, key), server, timeout, &ds_ttl);
if (ret == KNOT_EOK) {
*max_ds_ttl = MAX(*max_ds_ttl, ds_ttl);
success = true;
return success;
}
-int knot_parent_ds_query(conf_t *conf, kdnssec_ctx_t *kctx, size_t timeout)
+int knot_parent_ds_query(conf_t *conf, kdnssec_ctx_t *kctx, struct server *server,
+ size_t timeout)
{
uint32_t max_ds_ttl = 0;
knot_time_cmp(key->timing.ready, kctx->now) <= 0 &&
knot_time_cmp(key->timing.active, kctx->now) > 0) {
assert(key->is_ksk);
- if (parents_have_ds(conf, kctx, key, timeout, &max_ds_ttl)) {
+ if (parents_have_ds(conf, kctx, key, server, timeout, &max_ds_ttl)) {
return knot_dnssec_ksk_sbm_confirm(kctx, max_ds_ttl + kctx->policy->ksk_sbm_delay);
} else {
return KNOT_ENOENT;
-/* 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
#include "knot/dnssec/zone-keys.h"
#include "knot/dnssec/context.h"
-int knot_parent_ds_query(conf_t *conf, kdnssec_ctx_t *kctx, size_t timeout);
+struct server;
+
+int knot_parent_ds_query(conf_t *conf, kdnssec_ctx_t *kctx, struct server *server,
+ size_t timeout);
-/* 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
return ret;
}
- ret = knot_parent_ds_query(conf, &ctx, conf->cache.srv_tcp_remote_io_timeout);
+ ret = knot_parent_ds_query(conf, &ctx, zone->server,
+ conf->cache.srv_tcp_remote_io_timeout);
zone->timers.next_ds_check = 0;
switch (ret) {
#include "knot/conf/conf.h"
#include "knot/query/query.h"
#include "knot/query/requestor.h"
+#include "knot/server/server.h"
#include "knot/zone/zone.h"
#include "libknot/errcode.h"
return KNOT_ENOMEM;
}
- knot_request_t *req = knot_request_make(NULL, parent, pkt, 0);
+ knot_request_t *req = knot_request_make(NULL, parent, pkt,
+ zone->server->quic_creds, 0);
if (req == NULL) {
knot_rdataset_clear(&data.del_old_ds.rrs, NULL);
knot_request_free(req, NULL);
#include "knot/conf/conf.h"
#include "knot/query/query.h"
#include "knot/query/requestor.h"
+#include "knot/server/server.h"
#include "knot/zone/zone.h"
#include "libknot/errcode.h"
}
knot_request_flag_t flags = conf->cache.srv_tcp_fastopen ? KNOT_REQUEST_TFO : 0;
- knot_request_t *req = knot_request_make(NULL, slave, pkt, flags);
+ knot_request_t *req = knot_request_make(NULL, slave, pkt,
+ zone->server->quic_creds, flags);
if (req == NULL) {
knot_request_free(req, NULL);
knot_requestor_clear(&requestor);
#include "knot/query/layer.h"
#include "knot/query/query.h"
#include "knot/query/requestor.h"
+#include "knot/server/server.h"
#include "knot/updates/changesets.h"
#include "knot/zone/adjust.h"
#include "knot/zone/digest.h"
}
knot_request_flag_t flags = conf->cache.srv_tcp_fastopen ? KNOT_REQUEST_TFO : 0;
- knot_request_t *req = knot_request_make(NULL, master, pkt, flags);
+ knot_request_t *req = knot_request_make(NULL, master, pkt,
+ zone->server->quic_creds, flags);
if (req == NULL) {
knot_request_free(req, NULL);
knot_requestor_clear(&requestor);
#include "knot/nameserver/process_query.h"
#include "knot/query/capture.h"
#include "knot/query/requestor.h"
+#include "knot/server/server.h"
#include "knot/updates/ddns.h"
#include "knot/zone/digest.h"
#include "knot/zone/zone.h"
zone_schedule_notify(zone, 1);
}
-static int remote_forward(conf_t *conf, knot_request_t *request, conf_remote_t *remote)
+static int remote_forward(conf_t *conf, knot_request_t *request, conf_remote_t *remote,
+ zone_t *zone)
{
/* Copy request (without possible TSIG) and assign new ID. */
knot_pkt_t *query = knot_pkt_new(NULL, request->query->size +
/* Create a request. */
knot_request_flag_t flags = conf->cache.srv_tcp_fastopen ? KNOT_REQUEST_TFO : 0;
- knot_request_t *req = knot_request_make(NULL, remote, query, flags);
+ knot_request_t *req = knot_request_make(NULL, remote, query,
+ zone->server->quic_creds, flags);
if (req == NULL) {
knot_requestor_clear(&re);
knot_pkt_free(query);
for (size_t i = 0; i < addr_count; i++) {
conf_remote_t master = conf_remote(conf, &remote, i);
- ret = remote_forward(conf, request, &master);
+ ret = remote_forward(conf, request, &master, zone);
if (ret == KNOT_EOK) {
break;
}
-/* Copyright (C) 2021 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
const struct sockaddr_storage *dst = &proxy->remote;
const struct sockaddr_storage *src = &proxy->via;
knot_request_t *req = knot_request_make_generic(re.mm, dst, src, qdata->query,
- NULL, NULL, 0, flags);
+ NULL, NULL, NULL, 0, flags);
if (req == NULL) {
knot_requestor_clear(&re);
return state; /* Ignore, not enough memory. */
-/* 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
int ret = KNOT_ESEMCHECK;
if (knot_time_cmp(ctx->event_parent_ds_q, mod->dnssec->now) <= 0) {
pthread_rwlock_rdlock(&ctx->signing_mutex);
- ret = knot_parent_ds_query(conf(), mod->dnssec, 1000);
+ ret = knot_parent_ds_query(conf(), mod->dnssec, qdata->params->server, 1000);
pthread_rwlock_unlock(&ctx->signing_mutex);
if (ret != KNOT_EOK && ret != KNOT_NO_READY_KEY && mod->dnssec->policy->ksk_sbm_check_interval > 0) {
ctx->event_parent_ds_q = mod->dnssec->now + mod->dnssec->policy->ksk_sbm_check_interval;
struct knot_quic_reply *knot_qreq_connect(int fd,
struct sockaddr_storage *remote,
struct sockaddr_storage *local,
- const uint8_t *pin,
- uint8_t pin_len,
+ const struct knot_quic_creds *local_creds,
+ const uint8_t *peer_pin,
+ uint8_t peer_pin_len,
int timeout_ms)
{
knot_quic_reply_t *r = calloc(1, sizeof(*r) + 2 * sizeof(struct iovec) +
r->send_reply = qr_send_reply;
r->free_reply = qr_free_reply;
- struct knot_quic_creds *creds = knot_quic_init_creds(false, NULL, NULL,
- pin, pin_len);
+ struct knot_quic_creds *creds = knot_quic_init_creds_peer(local_creds,
+ peer_pin, peer_pin_len);
if (creds == NULL) {
free(r);
return NULL;
#include "contrib/sockaddr.h"
+struct knot_quic_creds;
struct knot_quic_reply;
struct knot_quic_reply *knot_qreq_connect(int fd,
struct sockaddr_storage *remote,
struct sockaddr_storage *local,
- const uint8_t *pin,
- uint8_t pin_len,
+ const struct knot_quic_creds *local_creds,
+ const uint8_t *peer_pin,
+ uint8_t peer_pin_len,
int timeout_ms);
int knot_qreq_send(struct knot_quic_reply *r, const struct iovec *data);
}
#ifdef ENABLE_QUIC
request->quic_ctx = knot_qreq_connect(request->fd, &request->remote,
- &request->source, request->pin,
- request->pin_len, timeout_ms);
+ &request->source, request->creds,
+ request->pin, request->pin_len,
+ timeout_ms);
if (request->quic_ctx == NULL) {
close(request->fd);
return KNOT_ECONN;
const struct sockaddr_storage *remote,
const struct sockaddr_storage *source,
knot_pkt_t *query,
+ const struct knot_quic_creds *creds,
const knot_tsig_key_t *tsig_key,
const uint8_t *pin,
size_t pin_len,
}
tsig_init(&request->tsig, tsig_key);
+ request->creds = creds;
if (flags & KNOT_REQUEST_QUIC && pin_len > 0) {
request->pin_len = pin_len;
memcpy(request->pin, pin, pin_len);
knot_request_t *knot_request_make(knot_mm_t *mm,
const conf_remote_t *remote,
knot_pkt_t *query,
+ const struct knot_quic_creds *creds,
knot_request_flag_t flags)
{
if (remote->quic) {
}
return knot_request_make_generic(mm, &remote->addr, &remote->via,
- query, &remote->key, remote->pin,
+ query, creds, &remote->key, remote->pin,
remote->pin_len, flags);
}
#include "libknot/mm_ctx.h"
#include "libknot/rrtype/tsig.h"
+struct knot_quic_creds;
struct knot_quic_reply;
typedef enum {
knot_sign_context_t sign; /*!< Required for async. DDNS processing. */
+ const struct knot_quic_creds *creds;
size_t pin_len;
uint8_t pin[];
} knot_request_t;
* \param remote Remote endpoint address.
* \param source Source address (or NULL).
* \param query Query message.
+ * \param creds Local (server) credentials.
* \param tsig_key TSIG key for authentication.
* \param pin Possible remote certificate PIN.
* \param pin_len Length of the remote certificate PIN.
const struct sockaddr_storage *remote,
const struct sockaddr_storage *source,
knot_pkt_t *query,
+ const struct knot_quic_creds *creds,
const knot_tsig_key_t *tsig_key,
const uint8_t *pin,
size_t pin_len,
knot_request_t *knot_request_make(knot_mm_t *mm,
const conf_remote_t *remote,
knot_pkt_t *query,
+ const struct knot_quic_creds *creds,
knot_request_flag_t flags);
/*!
log_debug("QUIC, using self generated key '%s' with "
"one-time certificate", key_file);
}
- server->quic_creds = knot_quic_init_creds(true, cert_file, key_file, NULL, 0);
+ server->quic_creds = knot_quic_init_creds(cert_file, key_file);
free(cert_file);
if (server->quic_creds == NULL) {
log_error("QUIC, failed to initialize server credentials with key '%s'",
gnutls_certificate_credentials_t tls_cert;
gnutls_anti_replay_t tls_anti_replay;
gnutls_datum_t tls_ticket_key;
- uint8_t *peer_pin;
+ bool peer;
uint8_t peer_pin_len;
+ uint8_t peer_pin[];
} knot_quic_creds_t;
typedef struct knot_quic_session {
}
_public_
-struct knot_quic_creds *knot_quic_init_creds(bool server,
- const char *cert_file,
- const char *key_file,
- const uint8_t *peer_pin,
- uint8_t peer_pin_len)
+struct knot_quic_creds *knot_quic_init_creds(const char *cert_file,
+ const char *key_file)
{
knot_quic_creds_t *creds = calloc(1, sizeof(*creds));
if (creds == NULL) {
goto fail;
}
- if (server) {
- ret = gnutls_anti_replay_init(&creds->tls_anti_replay);
- if (ret != GNUTLS_E_SUCCESS) {
- goto fail;
- }
- gnutls_anti_replay_set_add_function(creds->tls_anti_replay, tls_anti_replay_db_add_func);
- gnutls_anti_replay_set_ptr(creds->tls_anti_replay, NULL);
-
- if (cert_file != NULL) {
- ret = gnutls_certificate_set_x509_key_file(creds->tls_cert,
- cert_file, key_file,
- GNUTLS_X509_FMT_PEM);
- } else {
- ret = self_signed_cert(creds->tls_cert, key_file);
- }
- if (ret != GNUTLS_E_SUCCESS) {
- goto fail;
- }
+ ret = gnutls_anti_replay_init(&creds->tls_anti_replay);
+ if (ret != GNUTLS_E_SUCCESS) {
+ goto fail;
+ }
+ gnutls_anti_replay_set_add_function(creds->tls_anti_replay, tls_anti_replay_db_add_func);
+ gnutls_anti_replay_set_ptr(creds->tls_anti_replay, NULL);
- ret = gnutls_session_ticket_key_generate(&creds->tls_ticket_key);
- if (ret != GNUTLS_E_SUCCESS) {
- goto fail;
- }
+ if (cert_file != NULL) {
+ ret = gnutls_certificate_set_x509_key_file(creds->tls_cert,
+ cert_file, key_file,
+ GNUTLS_X509_FMT_PEM);
} else {
- if (peer_pin_len > 0) {
- creds->peer_pin = malloc(peer_pin_len);
- if (creds->peer_pin == NULL || peer_pin == NULL) {
- goto fail;
- }
- memcpy(creds->peer_pin, peer_pin, peer_pin_len);
- creds->peer_pin_len = peer_pin_len;
- }
+ ret = self_signed_cert(creds->tls_cert, key_file);
+ }
+ if (ret != GNUTLS_E_SUCCESS) {
+ goto fail;
}
- return creds;
+ ret = gnutls_session_ticket_key_generate(&creds->tls_ticket_key);
+ if (ret != GNUTLS_E_SUCCESS) {
+ goto fail;
+ }
+ return creds;
fail:
knot_quic_free_creds(creds);
return NULL;
}
+_public_
+struct knot_quic_creds *knot_quic_init_creds_peer(const struct knot_quic_creds *local_creds,
+ const uint8_t *peer_pin,
+ uint8_t peer_pin_len)
+{
+ knot_quic_creds_t *creds = calloc(1, sizeof(*creds) + peer_pin_len);
+ if (creds == NULL) {
+ return NULL;
+ }
+
+ creds->peer = true;
+ creds->tls_cert = local_creds->tls_cert;
+
+ if (peer_pin_len > 0 && peer_pin != NULL) {
+ memcpy(creds->peer_pin, peer_pin, peer_pin_len);
+ creds->peer_pin_len = peer_pin_len;
+ }
+
+ return creds;
+}
+
_public_
int knot_quic_creds_cert(struct knot_quic_creds *creds, struct gnutls_x509_crt_int **cert)
{
return;
}
- gnutls_certificate_free_credentials(creds->tls_cert);
+ if (!creds->peer && creds->tls_cert != NULL) {
+ gnutls_certificate_free_credentials(creds->tls_cert);
+ }
gnutls_anti_replay_deinit(creds->tls_anti_replay);
if (creds->tls_ticket_key.data != NULL) {
tls_session_ticket_key_free(&creds->tls_ticket_key);
}
- free(creds->peer_pin);
free(creds);
}
/*!
* \brief Init server TLS certificate for DoQ.
*
- * \param server Initializing for server-side (client otherwise).
- * \param cert_file X509 certificate PEM file path/name.
+ * \param cert_file X509 certificate PEM file path/name (NULL if auto-generated).
* \param key_file Key PEM file path/name.
+ *
+ * \return Initialized creds.
+ */
+struct knot_quic_creds *knot_quic_init_creds(const char *cert_file,
+ const char *key_file);
+
+/*!
+ * \brief Init peer TLS certificate for DoQ.
+ *
+ * \param local_creds Local credentials if server.
* \param peer_pin Optional peer certificate pin to check.
* \param peer_pin_len Length of the peer pin. Set 0 if not specified.
*
* \return Initialized creds.
*/
-struct knot_quic_creds *knot_quic_init_creds(bool server,
- const char *cert_file,
- const char *key_file,
- const uint8_t *peer_pin,
- uint8_t peer_pin_len);
+struct knot_quic_creds *knot_quic_init_creds_peer(const struct knot_quic_creds *local_creds,
+ const uint8_t *peer_pin,
+ uint8_t peer_pin_len);
/*!
* \brief Gets the certificate from credentials.
_public_
void knot_quic_table_rem(knot_quic_conn_t *conn, knot_quic_table_t *table)
{
+ if (conn->conn == NULL) {
+ return;
+ }
+
if (conn->streams_count == -1) { // kxdpgun special
conn->streams_count = 1;
}
}
if (ctx->quic) {
#ifdef ENABLE_QUIC
- quic_creds = knot_quic_init_creds(false, NULL, NULL, NULL, 0);
+ quic_creds = knot_quic_init_creds_peer(NULL, NULL, 0);
if (quic_creds == NULL) {
ERR2("failed to initialize QUIC context");
return NULL;
knot_request_flag_t flags = TFO ? KNOT_REQUEST_TFO: KNOT_REQUEST_NONE;
return knot_request_make_generic(requestor->mm, dst, src, pkt, NULL,
- NULL, 0, flags);
+ NULL, NULL, 0, flags);
}
static void test_disconnected(knot_requestor_t *requestor,