- xfr-tsig, check that tsig keys exist at startup and in unbound-checkconf.

This commit is contained in:
W.C.A. Wijngaards 2025-07-31 17:02:55 +02:00
parent 3b88577dd1
commit b1bb4a4592
9 changed files with 85 additions and 14 deletions

View file

@ -961,7 +961,7 @@ authzone.lo authzone.o: $(srcdir)/services/authzone.c config.h $(srcdir)/service
$(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/daemon/stats.h \
$(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/data/msgencode.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/random.h \
$(srcdir)/util/data/msgencode.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/random.h $(srcdir)/util/tsig.h \
$(srcdir)/services/cache/dns.h $(srcdir)/services/outside_network.h \
$(srcdir)/services/listen_dnsport.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h \
$(srcdir)/sldns/parseutil.h $(srcdir)/sldns/keyraw.h $(srcdir)/validator/val_nsec3.h \
@ -1483,7 +1483,7 @@ memstats.lo memstats.o: $(srcdir)/testcode/memstats.c config.h $(srcdir)/util/lo
unbound-checkconf.lo unbound-checkconf.o: $(srcdir)/smallapp/unbound-checkconf.c config.h $(srcdir)/util/log.h \
$(srcdir)/util/config_file.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/tsig.h \
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
$(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/services/localzone.h \

View file

@ -792,7 +792,8 @@ daemon_fork(struct daemon* daemon)
/* read auth zonefiles */
if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1,
&daemon->use_rpz, daemon->env, &daemon->mods))
&daemon->use_rpz, daemon->env, &daemon->mods,
daemon->env->tsig_key_table))
fatal_exit("auth_zones could not be setup");
/* Set-up EDNS strings */

View file

@ -5159,7 +5159,8 @@ fr_construct_from_config(struct fast_reload_thread* fr,
return 0;
}
if(!auth_zones_apply_cfg(ct->auth_zones, newcfg, 1, &ct->use_rpz,
fr->worker->daemon->env, &fr->worker->daemon->mods)) {
fr->worker->daemon->env, &fr->worker->daemon->mods,
fr->worker->daemon->env->tsig_key_table)) {
fr_construct_clear(ct);
return 0;
}

View file

@ -90,7 +90,7 @@ context_finalize(struct ub_ctx* ctx)
if(!local_zones_apply_cfg(ctx->local_zones, cfg))
return UB_INITFAIL;
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz,
ctx->env, &ctx->mods))
ctx->env, &ctx->mods, ctx->env->tsig_key_table))
return UB_INITFAIL;
if(!(ctx->env->fwds = forwards_create()) ||
!forwards_apply_cfg(ctx->env->fwds, cfg))

View file

@ -55,6 +55,7 @@
#include "util/log.h"
#include "util/module.h"
#include "util/random.h"
#include "util/tsig.h"
#include "services/cache/dns.h"
#include "services/outside_network.h"
#include "services/listen_dnsport.h"
@ -2091,7 +2092,8 @@ auth_zones_setup_zones(struct auth_zones* az)
/** set config items and create zones */
static int
auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
auth_zones_cfg(struct auth_zones* az, struct config_auth* c,
struct tsig_key_table* tsig_key_table)
{
struct auth_zone* z;
struct auth_xfer* x = NULL;
@ -2171,12 +2173,14 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
if(x) {
z->zone_is_slave = 1;
/* set options on xfer zone */
if(!xfer_set_masters(&x->task_probe->masters, c, 0)) {
if(!xfer_set_masters(&x->task_probe->masters, c, 0,
tsig_key_table)) {
lock_basic_unlock(&x->lock);
lock_rw_unlock(&z->lock);
return 0;
}
if(!xfer_set_masters(&x->task_transfer->masters, c, 1)) {
if(!xfer_set_masters(&x->task_transfer->masters, c, 1,
tsig_key_table)) {
lock_basic_unlock(&x->lock);
lock_rw_unlock(&z->lock);
return 0;
@ -2244,7 +2248,7 @@ az_delete_deleted_zones(struct auth_zones* az)
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
int setup, int* is_rpz, struct module_env* env,
struct module_stack* mods)
struct module_stack* mods, struct tsig_key_table* tsig_key_table)
{
struct config_auth* p;
az_setall_deleted(az);
@ -2254,7 +2258,7 @@ int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
continue;
}
*is_rpz = (*is_rpz || p->isrpz);
if(!auth_zones_cfg(az, p)) {
if(!auth_zones_cfg(az, p, tsig_key_table)) {
log_err("cannot config auth zone %s", p->name);
return 0;
}
@ -7284,9 +7288,30 @@ parse_url(char* url, char** host, char** file, int* port, int* ssl)
return 1;
}
/** Check the tsig key exists */
static int
check_tsig_key_exists(struct tsig_key_table* tsig_key_table,
const char* optname, char* str, char* str2)
{
struct tsig_key* key;
if(!tsig_key_table)
return 1;
lock_rw_rdlock(&tsig_key_table->lock);
key = tsig_key_table_search_fromstr(tsig_key_table, str2);
lock_rw_unlock(&tsig_key_table->lock);
if(!key) {
log_err("could not find tsig-key for %s: %s %s",
optname, str, str2);
return 0;
}
return 1;
}
int
xfer_set_masters(struct auth_master** list, struct config_auth* c,
int with_http)
int with_http, struct tsig_key_table* tsig_key_table)
{
struct auth_master* m;
struct config_strlist* p;
@ -7322,6 +7347,9 @@ xfer_set_masters(struct auth_master** list, struct config_auth* c,
log_err("malloc failure");
return 0;
}
if(!check_tsig_key_exists(tsig_key_table, "primary-tsig",
p2->str, p2->str2))
return 0;
m->tsig_key_name = strdup(p2->str2);
if(!m->tsig_key_name) {
log_err("malloc failure");
@ -7347,6 +7375,9 @@ xfer_set_masters(struct auth_master** list, struct config_auth* c,
log_err("malloc failure");
return 0;
}
if(!check_tsig_key_exists(tsig_key_table, "allow-notify-tsig",
p2->str, p2->str2))
return 0;
m->tsig_key_name = strdup(p2->str2);
if(!m->tsig_key_name) {
log_err("malloc failure");

View file

@ -55,6 +55,7 @@ struct query_info;
struct dns_msg;
struct edns_data;
struct module_env;
struct tsig_key_table;
struct worker;
struct comm_point;
struct comm_timer;
@ -488,11 +489,13 @@ struct auth_zones* auth_zones_create(void);
* @param is_rpz: set to 1 if at least one RPZ zone is configured.
* @param env: environment for offline verification.
* @param mods: modules in environment.
* @param tsig_key_table: tsig key table to check if tsig keys exist.
* If NULL, no check is performed.
* @return false on failure.
*/
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
int setup, int* is_rpz, struct module_env* env,
struct module_stack* mods);
struct module_stack* mods, struct tsig_key_table* tsig_key_table);
/** initial pick up of worker timeouts, ties events to worker event loop
* @param az: auth zones structure
@ -669,10 +672,12 @@ struct auth_xfer* auth_xfer_create(struct auth_zones* az, struct auth_zone* z);
* @param list: pointer to start of list. The malloced list is returned here.
* @param c: the config items to copy over.
* @param with_http: if true, http urls are also included, before the masters.
* @param tsig_key_table: if nonNULL, used to check that tsig keys exist in
* the key table.
* @return false on failure.
*/
int xfer_set_masters(struct auth_master** list, struct config_auth* c,
int with_http);
int with_http, struct tsig_key_table* tsig_key_table);
/** xfer nextprobe timeout callback, this is part of task_nextprobe */
void auth_xfer_timer(void* arg);

View file

@ -49,6 +49,7 @@
#include "util/module.h"
#include "util/net_help.h"
#include "util/regional.h"
#include "util/tsig.h"
#include "iterator/iterator.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_hints.h"
@ -1003,13 +1004,23 @@ static void
check_auth(struct config_file* cfg)
{
int is_rpz = 0;
struct tsig_key_table* tsig_key_table;
struct auth_zones* az = auth_zones_create();
if(!az || !auth_zones_apply_cfg(az, cfg, 0, &is_rpz, NULL, NULL)) {
/* construct tsig key table for tsig key name checks, and it
* also checks the TSIG key name and algorithm and base64 syntax. */
tsig_key_table = tsig_key_table_create();
if(!tsig_key_table || !tsig_key_table_apply_cfg(tsig_key_table, cfg))
fatal_exit("Could not set up TSIG keys");
if(!az || !auth_zones_apply_cfg(az, cfg, 0, &is_rpz, NULL, NULL,
tsig_key_table)) {
fatal_exit("Could not setup authority zones");
}
if(is_rpz && !strstr(cfg->module_conf, "respip"))
fatal_exit("RPZ requires the respip module");
auth_zones_delete(az);
tsig_key_table_delete(tsig_key_table);
}
/** check config file */

View file

@ -252,6 +252,18 @@ tsig_key_table_search(struct tsig_key_table* key_table, uint8_t* name,
return (struct tsig_key*)node->key;
}
struct tsig_key*
tsig_key_table_search_fromstr(struct tsig_key_table* key_table, char* name)
{
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
size_t len = sizeof(buf);
if(sldns_str2wire_dname_buf(name, buf, &len) != 0) {
log_err("could not parse '%s'", name);
return NULL;
}
return tsig_key_table_search(key_table, buf, len);
}
void tsig_key_delete(struct tsig_key* key)
{
if(!key)

View file

@ -217,6 +217,16 @@ int tsig_key_table_apply_cfg(struct tsig_key_table* key_table,
struct tsig_key* tsig_key_table_search(struct tsig_key_table* key_table,
uint8_t* name, size_t namelen);
/**
* Find key in key table. Caller must hold lock on the table.
* @param key_table: the tsig key table.
* @param name: the name in string format, it is parsed to wireformat.
* @return the found key or NULL if not found or NULL on parse error of the
* key name as a domain name. The item is locked by the key_table lock.
*/
struct tsig_key* tsig_key_table_search_fromstr(
struct tsig_key_table* key_table, char* name);
/**
* Delete TSIG key.
* @param key: to delete