]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- xfr-tsig, check that tsig keys exist at startup and in unbound-checkconf. xfr-tsig
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Thu, 31 Jul 2025 15:02:55 +0000 (17:02 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Thu, 31 Jul 2025 15:02:55 +0000 (17:02 +0200)
Makefile.in
daemon/daemon.c
daemon/remote.c
libunbound/context.c
services/authzone.c
services/authzone.h
smallapp/unbound-checkconf.c
util/tsig.c
util/tsig.h

index 417e8c4ef534a0ae4cfeeed68e47c65942838f05..60c15f4603a72a932f8affe15ce90b9ece9cbad5 100644 (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 \
index 92d0d031b73d35ee0bf5feedba6e418fc70b7751..11d81d048761a92cb58f87476ce93ea8acdc5b84 100644 (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 */
index 22475c4682475cccaf2a9bab8068476bc9f0b743..386854061608315e38feb84d95426e42ca9c69cd 100644 (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;
        }
index 38b5dbf0015954dfc52fb49a5e60bbdfbf1ba388..02c279bc516b27192381aabf9acc3d44b20f61e4 100644 (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))
index e59d384f241c4eec7720930f6b31561131914eb1..c014c5643c283d0d5b266aeb8627fc09f7c6b0ca 100644 (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");
index 00e6343f21521635159b621334d8b2a0fc1a4e60..7ca0a99635cfefb2e2bf29fb95e668088f138a92 100644 (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);
index 2ca69e9e69c79717f3a8080eb74d6e304473b2f3..66f53bd4dbbf1f150be19cec5d6e45daf5cf3aea 100644 (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 */
index 23075c53660e54e40a7b8ea76aace796e85b2e12..187c6a3cae2d075c701c5ac7619476f53a692db2 100644 (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)
index 06a63f5bbaa372c468351b942879e2fe2e443a8e..448637a2db5bdbba18f24de90ffc061572de53c3 100644 (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