Merge branch 'master' into xfr-tsig

This commit is contained in:
W.C.A. Wijngaards
2025-08-27 16:30:03 +02:00
9 changed files with 180 additions and 12 deletions
+2 -2
View File
@@ -31,12 +31,12 @@ jobs:
clang_analysis: "yes"
- name: OS X
os: macos-latest
install_expat: "no"
install_expat: "yes"
config: "--enable-debug --disable-flto --with-ssl=/opt/homebrew/opt/openssl --with-libexpat=/opt/homebrew/opt/expat"
make_test: "yes"
- name: Clang on OS X
os: macos-latest
install_expat: "no"
install_expat: "yes"
config: "CC=clang --enable-debug --disable-flto --with-ssl=/opt/homebrew/opt/openssl --with-libexpat=/opt/homebrew/opt/expat --disable-static"
make_test: "yes"
clang_analysis: "yes"
+6
View File
@@ -38,11 +38,17 @@
; - `LockPersonality=yes` locks down the personality system call so that the
; kernel execution domain may not be changed from the default.
;
; - With /etc/systemd/network/*.network a setting to make sure the network
; is not considered online too early, can reduce network unreachable
; errors on server start:
; [Link]
; RequiredForOnline=routable
;
[Unit]
Description=Validating, recursive, and caching DNS resolver
Documentation=man:unbound(8)
After=network-online.target
Wants=network-online.target
Before=nss-lookup.target
[Install]
+110 -7
View File
@@ -3221,10 +3221,13 @@ do_auth_zone_reload(RES* ssl, struct worker* worker, char* arg)
(void)ssl_printf(ssl, "error: no SOA in zone after read %s\n", arg);
return;
}
if(xfr->have_zone)
if(xfr->have_zone) {
xfr->lease_time = *worker->env.now;
xfr->soa_zone_acquired = *worker->env.now;
}
lock_basic_unlock(&xfr->lock);
}
z->soa_zone_acquired = *worker->env.now;
auth_zone_verify_zonemd(z, &worker->env, &worker->env.mesh->mods,
&reason, 0, 0);
@@ -3373,7 +3376,7 @@ static void
do_list_auth_zones(RES* ssl, struct auth_zones* az)
{
struct auth_zone* z;
char buf[LDNS_MAX_DOMAINLEN], buf2[256];
char buf[LDNS_MAX_DOMAINLEN], buf2[256], buf3[256];
lock_rw_rdlock(&az->lock);
RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
lock_rw_rdlock(&z->lock);
@@ -3382,18 +3385,41 @@ do_list_auth_zones(RES* ssl, struct auth_zones* az)
snprintf(buf2, sizeof(buf2), "expired");
else {
uint32_t serial = 0;
if(auth_zone_get_serial(z, &serial))
if(auth_zone_get_serial(z, &serial)) {
snprintf(buf2, sizeof(buf2), "serial %u",
(unsigned)serial);
else snprintf(buf2, sizeof(buf2), "no serial");
if(z->soa_zone_acquired != 0) {
#if defined(HAVE_STRFTIME) && defined(HAVE_LOCALTIME_R)
char tmbuf[32];
struct tm tm;
struct tm *tm_p;
tm_p = localtime_r(
&z->soa_zone_acquired, &tm);
if(!strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%dT%H:%M:%S", tm_p))
snprintf(tmbuf, sizeof(tmbuf), "strftime-err-%u", (unsigned)z->soa_zone_acquired);
snprintf(buf3, sizeof(buf3),
"\t since %u %s",
(unsigned)z->soa_zone_acquired,
tmbuf);
#else
snprintf(buf3, sizeof(buf3),
"\t since %u",
(unsigned)z->soa_zone_acquired);
#endif
} else {
buf3[0]=0;
}
} else {
snprintf(buf2, sizeof(buf2), "no serial");
buf3[0]=0;
}
}
if(!ssl_printf(ssl, "%s\t%s\n", buf, buf2)) {
lock_rw_unlock(&z->lock);
if(!ssl_printf(ssl, "%s\t%s%s\n", buf, buf2, buf3)) {
/* failure to print */
lock_rw_unlock(&z->lock);
lock_rw_unlock(&az->lock);
return;
}
lock_rw_unlock(&z->lock);
}
lock_rw_unlock(&az->lock);
}
@@ -3836,6 +3862,30 @@ do_print_cookie_secrets(RES* ssl, struct worker* worker) {
explicit_bzero(secret_hex, sizeof(secret_hex));
}
/** check that there is no argument after a command that takes no arguments. */
static int
cmd_no_args(RES* ssl, char* cmd, char* p)
{
if(p && *p != 0) {
/* cmd contains the command that is called at the start,
* with space or tab after it. */
char* c = cmd;
if(strchr(c, ' ') && strchr(c, '\t')) {
if(strchr(c, ' ') < strchr(c, '\t'))
*strchr(c, ' ')=0;
else *strchr(c, '\t')=0;
} else if(strchr(c, ' ')) {
*strchr(c, ' ')=0;
} else if(strchr(c, '\t')) {
*strchr(c, '\t')=0;
}
(void)ssl_printf(ssl, "error command %s takes no arguments,"
" have '%s'\n", c, p);
return 1;
}
return 0;
}
/** check for name with end-of-string, space or tab after it */
static int
cmdcmp(char* p, const char* cmd, size_t len)
@@ -3851,27 +3901,41 @@ execute_cmd(struct daemon_remote* rc, struct rc_state* s, RES* ssl, char* cmd,
char* p = skipwhite(cmd);
/* compare command */
if(cmdcmp(p, "stop", 4)) {
if(cmd_no_args(ssl, p, skipwhite(p+4)))
return;
do_stop(ssl, worker);
return;
} else if(cmdcmp(p, "reload_keep_cache", 17)) {
if(cmd_no_args(ssl, p, skipwhite(p+17)))
return;
do_reload(ssl, worker, 1);
return;
} else if(cmdcmp(p, "reload", 6)) {
if(cmd_no_args(ssl, p, skipwhite(p+6)))
return;
do_reload(ssl, worker, 0);
return;
} else if(cmdcmp(p, "fast_reload", 11)) {
do_fast_reload(ssl, worker, s, skipwhite(p+11));
return;
} else if(cmdcmp(p, "stats_noreset", 13)) {
if(cmd_no_args(ssl, p, skipwhite(p+13)))
return;
do_stats(ssl, worker, 0);
return;
} else if(cmdcmp(p, "stats", 5)) {
if(cmd_no_args(ssl, p, skipwhite(p+5)))
return;
do_stats(ssl, worker, 1);
return;
} else if(cmdcmp(p, "status", 6)) {
if(cmd_no_args(ssl, p, skipwhite(p+6)))
return;
do_status(ssl, worker);
return;
} else if(cmdcmp(p, "dump_cache", 10)) {
if(cmd_no_args(ssl, p, skipwhite(p+10)))
return;
#ifdef THREADS_DISABLED
if(worker->daemon->num > 1) {
(void)ssl_printf(ssl, "dump_cache/load_cache is not "
@@ -3882,6 +3946,8 @@ execute_cmd(struct daemon_remote* rc, struct rc_state* s, RES* ssl, char* cmd,
(void)dump_cache(ssl, worker);
return;
} else if(cmdcmp(p, "load_cache", 10)) {
if(cmd_no_args(ssl, p, skipwhite(p+10)))
return;
#ifdef THREADS_DISABLED
if(worker->daemon->num > 1) {
/* The warning can't be printed when stdin is sending
@@ -3892,18 +3958,28 @@ execute_cmd(struct daemon_remote* rc, struct rc_state* s, RES* ssl, char* cmd,
if(load_cache(ssl, worker)) send_ok(ssl);
return;
} else if(cmdcmp(p, "list_forwards", 13)) {
if(cmd_no_args(ssl, p, skipwhite(p+13)))
return;
do_list_forwards(ssl, worker);
return;
} else if(cmdcmp(p, "list_stubs", 10)) {
if(cmd_no_args(ssl, p, skipwhite(p+10)))
return;
do_list_stubs(ssl, worker);
return;
} else if(cmdcmp(p, "list_insecure", 13)) {
if(cmd_no_args(ssl, p, skipwhite(p+13)))
return;
do_insecure_list(ssl, worker);
return;
} else if(cmdcmp(p, "list_local_zones", 16)) {
if(cmd_no_args(ssl, p, skipwhite(p+16)))
return;
do_list_local_zones(ssl, worker->daemon->local_zones);
return;
} else if(cmdcmp(p, "list_local_data", 15)) {
if(cmd_no_args(ssl, p, skipwhite(p+15)))
return;
do_list_local_data(ssl, worker, worker->daemon->local_zones);
return;
} else if(cmdcmp(p, "view_list_local_zones", 21)) {
@@ -3919,6 +3995,8 @@ execute_cmd(struct daemon_remote* rc, struct rc_state* s, RES* ssl, char* cmd,
do_ip_ratelimit_list(ssl, worker, p+17);
return;
} else if(cmdcmp(p, "list_auth_zones", 15)) {
if(cmd_no_args(ssl, p, skipwhite(p+15)))
return;
do_list_auth_zones(ssl, worker->env.auth_zones);
return;
} else if(cmdcmp(p, "auth_zone_reload", 16)) {
@@ -3939,11 +4017,15 @@ execute_cmd(struct daemon_remote* rc, struct rc_state* s, RES* ssl, char* cmd,
return;
} else if(cmdcmp(p, "flush_stats", 11)) {
/* must always distribute this cmd */
if(cmd_no_args(ssl, p, skipwhite(p+11)))
return;
if(rc) distribute_cmd(rc, ssl, cmd);
do_flush_stats(ssl, worker);
return;
} else if(cmdcmp(p, "flush_requestlist", 17)) {
/* must always distribute this cmd */
if(cmd_no_args(ssl, p, skipwhite(p+17)))
return;
if(rc) distribute_cmd(rc, ssl, cmd);
do_flush_requestlist(ssl, worker);
return;
@@ -3957,15 +4039,23 @@ execute_cmd(struct daemon_remote* rc, struct rc_state* s, RES* ssl, char* cmd,
* Each line needs to be distributed if THREADS_DISABLED.
*/
} else if(cmdcmp(p, "local_zones_remove", 18)) {
if(cmd_no_args(ssl, p, skipwhite(p+18)))
return;
do_zones_remove(rc, ssl, worker);
return;
} else if(cmdcmp(p, "local_zones", 11)) {
if(cmd_no_args(ssl, p, skipwhite(p+11)))
return;
do_zones_add(rc, ssl, worker);
return;
} else if(cmdcmp(p, "local_datas_remove", 18)) {
if(cmd_no_args(ssl, p, skipwhite(p+18)))
return;
do_datas_remove(rc, ssl, worker);
return;
} else if(cmdcmp(p, "local_datas", 11)) {
if(cmd_no_args(ssl, p, skipwhite(p+11)))
return;
do_datas_add(rc, ssl, worker);
return;
} else if(cmdcmp(p, "view_local_datas_remove", 23)){
@@ -3975,6 +4065,8 @@ execute_cmd(struct daemon_remote* rc, struct rc_state* s, RES* ssl, char* cmd,
do_view_datas_add(rc, ssl, worker, skipwhite(p+16));
return;
} else if(cmdcmp(p, "print_cookie_secrets", 20)) {
if(cmd_no_args(ssl, p, skipwhite(p+20)))
return;
do_print_cookie_secrets(ssl, worker);
return;
}
@@ -4024,10 +4116,16 @@ execute_cmd(struct daemon_remote* rc, struct rc_state* s, RES* ssl, char* cmd,
} else if(cmdcmp(p, "flush", 5)) {
do_flush_name(ssl, worker, skipwhite(p+5));
} else if(cmdcmp(p, "dump_requestlist", 16)) {
if(cmd_no_args(ssl, p, skipwhite(p+16)))
return;
do_dump_requestlist(ssl, worker);
} else if(cmdcmp(p, "dump_infra", 10)) {
if(cmd_no_args(ssl, p, skipwhite(p+10)))
return;
do_dump_infra(ssl, worker);
} else if(cmdcmp(p, "log_reopen", 10)) {
if(cmd_no_args(ssl, p, skipwhite(p+10)))
return;
do_log_reopen(ssl, worker);
} else if(cmdcmp(p, "set_option", 10)) {
do_set_option(ssl, worker, skipwhite(p+10));
@@ -4044,8 +4142,12 @@ execute_cmd(struct daemon_remote* rc, struct rc_state* s, RES* ssl, char* cmd,
} else if(cmdcmp(p, "add_cookie_secret", 17)) {
do_add_cookie_secret(ssl, worker, skipwhite(p+17));
} else if(cmdcmp(p, "drop_cookie_secret", 18)) {
if(cmd_no_args(ssl, p, skipwhite(p+18)))
return;
do_drop_cookie_secret(ssl, worker);
} else if(cmdcmp(p, "activate_cookie_secret", 22)) {
if(cmd_no_args(ssl, p, skipwhite(p+22)))
return;
do_activate_cookie_secret(ssl, worker);
} else {
(void)ssl_printf(ssl, "error unknown command '%s'\n", p);
@@ -7394,6 +7496,7 @@ fr_worker_auth_add(struct worker* worker, struct fast_reload_auth_change* item,
xfr->serial = 0;
}
}
auth_zone_pickup_initial_zone(item->new_z, &worker->env);
lock_rw_unlock(&item->new_z->lock);
lock_rw_unlock(&worker->env.auth_zones->lock);
lock_rw_unlock(&worker->daemon->fast_reload_thread->old_auth_zones->lock);
+18
View File
@@ -1,3 +1,21 @@
26 August 2025: Wouter
- Fix ports workflow to install expat for macos.
22 August 2025: Wouter
- For #1318: Fix compile warnings for DoH compile on windows.
- Fix sha1 enable environment variable in test code on windows.
- Fix #1319: [FR] zone status for Unbound auth-zones.
- Fix that the zone acquired timestamp is set after the
zonefile is read.
21 August 2025: Wouter
- Fix to check for extraneous command arguments for unbound-control,
when the command takes no arguments but there are arguments present.
- Fix #1317: Unbound starts too early. Add
Wants=network-online.target under [Unit] in unbound.service.
- Fix for #1317: Fix contrib/unbound.service comment path for
systemd network configuration.
15 August 2025: Wouter
- unbound-control cache_lookup +t allows tld and root names. And
subnet cache contents are printed.
+22 -1
View File
@@ -5119,6 +5119,7 @@ apply_axfr(struct auth_xfer* xfr, struct auth_zone* z,
xfr->have_zone = 0;
xfr->serial = 0;
xfr->soa_zone_acquired = 0;
/* insert all RRs in to the zone */
/* insert the SOA only once, skip the last one */
@@ -5220,6 +5221,7 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z,
xfr->have_zone = 0;
xfr->serial = 0;
xfr->soa_zone_acquired = 0;
chunk = xfr->task_transfer->chunks_first;
chunk_pos = 0;
@@ -5430,6 +5432,8 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env,
" (or malformed RR)", xfr->task_transfer->master->host);
return 0;
}
z->soa_zone_acquired = *env->now;
xfr->soa_zone_acquired = *env->now;
/* release xfr lock while verifying zonemd because it may have
* to spawn lookups in the state machines */
@@ -7150,13 +7154,23 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
comm_timer_set(xfr->task_nextprobe->timer, &tv);
}
void auth_zone_pickup_initial_zone(struct auth_zone* z, struct module_env* env)
{
/* Set the time, because we now have timestamp in env,
* (not earlier during startup and apply_cfg), and this
* notes the start time when the data was acquired. */
z->soa_zone_acquired = *env->now;
}
void auth_xfer_pickup_initial_zone(struct auth_xfer* x, struct module_env* env)
{
/* set lease_time, because we now have timestamp in env,
* (not earlier during startup and apply_cfg), and this
* notes the start time when the data was acquired */
if(x->have_zone)
if(x->have_zone) {
x->lease_time = *env->now;
x->soa_zone_acquired = *env->now;
}
if(x->task_nextprobe && x->task_nextprobe->worker == NULL) {
xfr_set_timeout(x, env, 0, 1);
}
@@ -7167,7 +7181,13 @@ void
auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env)
{
struct auth_xfer* x;
struct auth_zone* z;
lock_rw_wrlock(&az->lock);
RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
lock_rw_wrlock(&z->lock);
auth_zone_pickup_initial_zone(z, env);
lock_rw_unlock(&z->lock);
}
RBTREE_FOR(x, struct auth_xfer*, &az->xtree) {
lock_basic_lock(&x->lock);
auth_xfer_pickup_initial_zone(x, env);
@@ -7252,6 +7272,7 @@ auth_xfer_new(struct auth_zone* z)
lock_protect(&xfr->lock, &xfr->notify_serial, sizeof(xfr->notify_serial));
lock_protect(&xfr->lock, &xfr->zone_expired, sizeof(xfr->zone_expired));
lock_protect(&xfr->lock, &xfr->have_zone, sizeof(xfr->have_zone));
lock_protect(&xfr->lock, &xfr->soa_zone_acquired, sizeof(xfr->soa_zone_acquired));
lock_protect(&xfr->lock, &xfr->serial, sizeof(xfr->serial));
lock_protect(&xfr->lock, &xfr->retry, sizeof(xfr->retry));
lock_protect(&xfr->lock, &xfr->refresh, sizeof(xfr->refresh));
+12
View File
@@ -120,6 +120,8 @@ struct auth_zone {
char* zonefile;
/** fallback to the internet on failure or ttl-expiry of auth zone */
int fallback_enabled;
/** the time when zone was transferred from upstream */
time_t soa_zone_acquired;
/** the zone has expired (enabled by the xfer worker), fallback
* happens if that option is enabled. */
int zone_expired;
@@ -263,6 +265,8 @@ struct auth_xfer {
int zone_expired;
/** do we have a zone (if 0, no zone data at all) */
int have_zone;
/** the time when zone was transferred from upstream */
time_t soa_zone_acquired;
/** current serial (from SOA), if we have no zone, 0 */
uint32_t serial;
@@ -818,6 +822,14 @@ size_t auth_zones_get_mem(struct auth_zones* zones);
void auth_xfer_pickup_initial_zone(struct auth_xfer* x,
struct module_env* env);
/**
* Initial pick up of the auth zone, it sets the acquired time.
* @param z: the zone, write locked by caller.
* @param env: environment of the worker, with current time.
*/
void auth_zone_pickup_initial_zone(struct auth_zone* z,
struct module_env* env);
/**
* Delete auth xfer structure
* @param xfr: delete this xfer and its tasks.
+4
View File
@@ -297,7 +297,11 @@ setup_config(FILE* in, int* lineno, int* pass_argc, char* pass_argv[])
/* Allow the use of SHA1 signatures for the test,
* in case that OpenSSL disallows use of RSASHA1
* with rh-allow-sha1-signatures disabled. */
#ifndef UB_ON_WINDOWS
setenv("OPENSSL_ENABLE_SHA1_SIGNATURES", "1", 0);
#else
_putenv("OPENSSL_ENABLE_SHA1_SIGNATURES=1");
#endif
}
fputs(line, cfg);
}
+4
View File
@@ -638,7 +638,11 @@ verify_test(void)
/* Allow the use of SHA1 signatures for the test,
* in case that OpenSSL disallows use of RSASHA1
* with rh-allow-sha1-signatures disabled. */
#ifndef UB_ON_WINDOWS
setenv("OPENSSL_ENABLE_SHA1_SIGNATURES", "1", 0);
#else
_putenv("OPENSSL_ENABLE_SHA1_SIGNATURES=1");
#endif
}
#endif
+2 -2
View File
@@ -5194,7 +5194,7 @@ ssize_t http2_recv_cb(nghttp2_session* ATTR_UNUSED(session), uint8_t* buf,
}
#endif /* HAVE_SSL */
ret = recv(h2_session->c->fd, buf, len, MSG_DONTWAIT);
ret = recv(h2_session->c->fd, (void*)buf, len, MSG_DONTWAIT);
if(ret == 0) {
return NGHTTP2_ERR_EOF;
} else if(ret < 0) {
@@ -5522,7 +5522,7 @@ ssize_t http2_send_cb(nghttp2_session* ATTR_UNUSED(session), const uint8_t* buf,
}
#endif /* HAVE_SSL */
ret = send(h2_session->c->fd, buf, len, 0);
ret = send(h2_session->c->fd, (void*)buf, len, 0);
if(ret == 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
} else if(ret < 0) {