diff --git a/daemon/remote.c b/daemon/remote.c index 09128e62a..aa05e85e1 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -3225,6 +3225,7 @@ do_auth_zone_reload(RES* ssl, struct worker* worker, char* arg) return; } if(!auth_zone_read_zonefile(z, worker->env.cfg)) { + auth_zone_clear_data(z); lock_rw_unlock(&z->lock); if(xfr) { lock_basic_unlock(&xfr->lock); diff --git a/doc/Changelog b/doc/Changelog index e7d9dba89..9c1f80762 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,10 @@ +16 June 2026: Wouter + - Fix to disallow $INCLUDE for secondary zones. Start up + of server continues if a secondary zone fails to load. + Failed loads clear the zone data, so there is no partial + zone. Thanks to Qifan Zhang, Palo Alto Networks, for + the report. + 15 June 2026: Wouter - Fix to add `max-transfer-size` and `max-transfer-time` that limit auth-zone and rpz transfer amount and time taken. diff --git a/services/authzone.c b/services/authzone.c index 86f698031..b17cc8602 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -1518,6 +1518,11 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen, "exceeded", fname, state->lineno); return 0; } + /* A $INCLUDE is not expected for a secondary zone. */ + if(z->zone_is_slave) { + log_err("%s:%d $INCLUDE not allowed for secondary zone", fname, state->lineno); + return 0; + } /* skip spaces */ while(*incfile == ' ' || *incfile == '\t') incfile++; @@ -1583,6 +1588,16 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen, return 1; } +void auth_zone_clear_data(struct auth_zone* z) +{ + /* clear the data tree */ + traverse_postorder(&z->data, auth_data_del, NULL); + rbtree_init(&z->data, &auth_data_cmp); + /* clear the RPZ policies */ + if(z->rpz) + rpz_clear(z->rpz); +} + int auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg) { @@ -1811,9 +1826,11 @@ auth_zones_read_zones(struct auth_zones* az, struct config_file* cfg, RBTREE_FOR(z, struct auth_zone*, &az->ztree) { lock_rw_wrlock(&z->lock); if(!auth_zone_read_zonefile(z, cfg)) { + /* For both secondary and primary zones, not fatal. + * This keeps the server up. */ + auth_zone_clear_data(z); lock_rw_unlock(&z->lock); - lock_rw_unlock(&az->lock); - return 0; + continue; } if(z->zonefile && z->zonefile[0]!=0 && env) zonemd_offline_verify(z, env, mods); @@ -5111,13 +5128,7 @@ apply_axfr(struct auth_xfer* xfr, struct auth_zone* z, size_t rr_counter = 0; int have_end_soa = 0; - /* clear the data tree */ - traverse_postorder(&z->data, auth_data_del, NULL); - rbtree_init(&z->data, &auth_data_cmp); - /* clear the RPZ policies */ - if(z->rpz) - rpz_clear(z->rpz); - + auth_zone_clear_data(z); xfr->have_zone = 0; xfr->serial = 0; xfr->soa_zone_acquired = 0; @@ -5214,13 +5225,7 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z, return 0; } - /* clear the data tree */ - traverse_postorder(&z->data, auth_data_del, NULL); - rbtree_init(&z->data, &auth_data_cmp); - /* clear the RPZ policies */ - if(z->rpz) - rpz_clear(z->rpz); - + auth_zone_clear_data(z); xfr->have_zone = 0; xfr->serial = 0; xfr->soa_zone_acquired = 0; @@ -5405,6 +5410,7 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env, /* apply data */ if(xfr->task_transfer->master->http) { if(!apply_http(xfr, z, env->scratch_buffer)) { + auth_zone_clear_data(z); lock_rw_unlock(&z->lock); verbose(VERB_ALGO, "http from %s: could not store data", xfr->task_transfer->master->host); @@ -5413,6 +5419,7 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env, } else if(xfr->task_transfer->on_ixfr && !xfr->task_transfer->on_ixfr_is_axfr) { if(!apply_ixfr(xfr, z, env->scratch_buffer)) { + auth_zone_clear_data(z); lock_rw_unlock(&z->lock); verbose(VERB_ALGO, "xfr from %s: could not store IXFR" " data", xfr->task_transfer->master->host); @@ -5421,6 +5428,7 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env, } } else { if(!apply_axfr(xfr, z, env->scratch_buffer)) { + auth_zone_clear_data(z); lock_rw_unlock(&z->lock); verbose(VERB_ALGO, "xfr from %s: could not store AXFR" " data", xfr->task_transfer->master->host); diff --git a/services/authzone.h b/services/authzone.h index b55b711ae..97ab01fcb 100644 --- a/services/authzone.h +++ b/services/authzone.h @@ -854,4 +854,7 @@ void xfr_disown_tasks(struct auth_xfer* xfr, struct worker* worker); /** count number of open and closed parenthesis in a chunkline */ int chunkline_count_parens(struct sldns_buffer* buf, size_t start); +/** Clear data in auth zone */ +void auth_zone_clear_data(struct auth_zone* z); + #endif /* SERVICES_AUTHZONE_H */