mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
zonemd, zonemds are checked at start
This commit is contained in:
parent
5d7e001c63
commit
e09873e0c8
7 changed files with 117 additions and 14 deletions
|
|
@ -632,19 +632,19 @@ daemon_fork(struct daemon* daemon)
|
|||
fatal_exit("Could not set up per-view response IP sets");
|
||||
daemon->use_response_ip = !respip_set_is_empty(daemon->respip_set) ||
|
||||
have_view_respip_cfg;
|
||||
|
||||
|
||||
/* setup modules */
|
||||
daemon_setup_modules(daemon);
|
||||
|
||||
/* read auth zonefiles */
|
||||
if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1,
|
||||
&daemon->use_rpz))
|
||||
&daemon->use_rpz, daemon->env, &daemon->mods))
|
||||
fatal_exit("auth_zones could not be setup");
|
||||
|
||||
/* Set-up EDNS tags */
|
||||
if(!edns_tags_apply_cfg(daemon->env->edns_tags, daemon->cfg))
|
||||
fatal_exit("Could not set up EDNS tags");
|
||||
|
||||
/* setup modules */
|
||||
daemon_setup_modules(daemon);
|
||||
|
||||
/* response-ip-xxx options don't work as expected without the respip
|
||||
* module. To avoid run-time operational surprise we reject such
|
||||
* configuration. */
|
||||
|
|
|
|||
|
|
@ -1906,6 +1906,8 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
|||
#endif
|
||||
) {
|
||||
auth_xfer_pickup_initial(worker->env.auth_zones, &worker->env);
|
||||
auth_zones_pickup_zonemd_verify(worker->env.auth_zones,
|
||||
&worker->env);
|
||||
}
|
||||
#ifdef USE_DNSTAP
|
||||
if(worker->daemon->cfg->dnstap
|
||||
|
|
|
|||
|
|
@ -78,7 +78,8 @@ context_finalize(struct ub_ctx* ctx)
|
|||
return UB_NOMEM;
|
||||
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))
|
||||
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz,
|
||||
ctx->env, &ctx->mods))
|
||||
return UB_INITFAIL;
|
||||
if(!edns_tags_apply_cfg(ctx->env->edns_tags, cfg))
|
||||
return UB_INITFAIL;
|
||||
|
|
|
|||
|
|
@ -1745,9 +1745,47 @@ int auth_zone_write_file(struct auth_zone* z, const char* fname)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** offline verify for zonemd, while reading a zone file to immediately
|
||||
* spot bad hashes in zonefile as they are read.
|
||||
* Creates temp buffers, but uses anchors and validation environment
|
||||
* from the module_env. */
|
||||
static void
|
||||
zonemd_offline_verify(struct auth_zone* z, struct module_env* env_for_val,
|
||||
struct module_stack* mods)
|
||||
{
|
||||
struct module_env env;
|
||||
struct mesh_area mesh;
|
||||
time_t now = 0;
|
||||
env = *env_for_val;
|
||||
env.scratch_buffer = sldns_buffer_new(env.cfg->msg_buffer_size);
|
||||
if(!env.scratch_buffer) {
|
||||
log_err("out of memory");
|
||||
goto clean_exit;
|
||||
}
|
||||
env.scratch = regional_create();
|
||||
memset(&mesh, 0, sizeof(mesh));
|
||||
mesh.mods = *mods;
|
||||
env.mesh = &mesh;
|
||||
if(!env.now) {
|
||||
env.now = &now;
|
||||
now = time(NULL);
|
||||
}
|
||||
if(!env.scratch) {
|
||||
log_err("out of memory");
|
||||
goto clean_exit;
|
||||
}
|
||||
auth_zone_verify_zonemd(z, &env, NULL, 1, 0);
|
||||
|
||||
clean_exit:
|
||||
/* clean up and exit */
|
||||
sldns_buffer_free(env.scratch_buffer);
|
||||
regional_destroy(env.scratch);
|
||||
}
|
||||
|
||||
/** read all auth zones from file (if they have) */
|
||||
static int
|
||||
auth_zones_read_zones(struct auth_zones* az, struct config_file* cfg)
|
||||
auth_zones_read_zones(struct auth_zones* az, struct config_file* cfg,
|
||||
struct module_env* env, struct module_stack* mods)
|
||||
{
|
||||
struct auth_zone* z;
|
||||
lock_rw_wrlock(&az->lock);
|
||||
|
|
@ -1758,6 +1796,8 @@ auth_zones_read_zones(struct auth_zones* az, struct config_file* cfg)
|
|||
lock_rw_unlock(&az->lock);
|
||||
return 0;
|
||||
}
|
||||
if(z->zonefile && z->zonefile[0]!=0 && env)
|
||||
zonemd_offline_verify(z, env, mods);
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
lock_rw_unlock(&az->lock);
|
||||
|
|
@ -2103,7 +2143,8 @@ 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)
|
||||
int setup, int* is_rpz, struct module_env* env,
|
||||
struct module_stack* mods)
|
||||
{
|
||||
struct config_auth* p;
|
||||
az_setall_deleted(az);
|
||||
|
|
@ -2119,7 +2160,7 @@ int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
|
|||
}
|
||||
}
|
||||
az_delete_deleted_zones(az);
|
||||
if(!auth_zones_read_zones(az, cfg))
|
||||
if(!auth_zones_read_zones(az, cfg, env, mods))
|
||||
return 0;
|
||||
if(setup) {
|
||||
if(!auth_zones_setup_zones(az))
|
||||
|
|
@ -8044,7 +8085,7 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env)
|
|||
}
|
||||
|
||||
void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
|
||||
char** result)
|
||||
char** result, int offline, int only_online)
|
||||
{
|
||||
char* reason = NULL, *why_bogus = NULL;
|
||||
struct trust_anchor* anchor = NULL;
|
||||
|
|
@ -8061,6 +8102,10 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
|
|||
* otherwise we have the zone DNSKEY for the DNSSEC verification. */
|
||||
anchor = anchors_lookup(env->anchors, z->name, z->namelen, z->dclass);
|
||||
if(anchor && query_dname_compare(z->name, anchor->name) == 0) {
|
||||
if(only_online) {
|
||||
lock_basic_unlock(&anchor->lock);
|
||||
return;
|
||||
}
|
||||
/* equal to trustanchor, no need for online lookups */
|
||||
dnskey = zonemd_get_dnskey_from_anchor(z, env, anchor,
|
||||
&is_insecure, &why_bogus, &keystorage);
|
||||
|
|
@ -8071,6 +8116,8 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
|
|||
} else if(anchor) {
|
||||
lock_basic_unlock(&anchor->lock);
|
||||
/* perform online lookups */
|
||||
if(offline)
|
||||
return;
|
||||
/* setup online lookups, and wait for them */
|
||||
if(zonemd_lookup_dnskey(z, env)) {
|
||||
/* wait for the lookup */
|
||||
|
|
@ -8079,6 +8126,8 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
|
|||
reason = "could not lookup DNSKEY for chain of trust";
|
||||
} else {
|
||||
/* the zone is not under a trust anchor */
|
||||
if(only_online)
|
||||
return;
|
||||
dnskey = NULL;
|
||||
is_insecure = 1;
|
||||
}
|
||||
|
|
@ -8091,3 +8140,37 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
|
|||
auth_zone_verify_zonemd_with_key(z, env, dnskey, is_insecure, result);
|
||||
regional_free_all(env->scratch);
|
||||
}
|
||||
|
||||
void auth_zones_pickup_zonemd_verify(struct auth_zones* az,
|
||||
struct module_env* env)
|
||||
{
|
||||
struct auth_zone key;
|
||||
uint8_t savezname[255+1];
|
||||
size_t savezname_len;
|
||||
struct auth_zone* z;
|
||||
key.node.key = &key;
|
||||
lock_rw_rdlock(&az->lock);
|
||||
RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
|
||||
lock_rw_wrlock(&z->lock);
|
||||
key.dclass = z->dclass;
|
||||
key.namelabs = z->namelabs;
|
||||
if(z->namelen > sizeof(savezname)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
log_err("auth_zones_pickup_zonemd_verify: zone name too long");
|
||||
continue;
|
||||
}
|
||||
savezname_len = z->namelen;
|
||||
memmove(savezname, z->name, z->namelen);
|
||||
lock_rw_unlock(&az->lock);
|
||||
auth_zone_verify_zonemd(z, env, NULL, 0, 1);
|
||||
lock_rw_unlock(&z->lock);
|
||||
lock_rw_rdlock(&az->lock);
|
||||
/* find the zone we had before, it is not deleted,
|
||||
* because we have a flag for that that is processed at
|
||||
* apply_cfg time */
|
||||
key.namelen = savezname_len;
|
||||
key.name = savezname;
|
||||
z = (struct auth_zone*)rbtree_search(&az->ztree, &key);
|
||||
}
|
||||
lock_rw_unlock(&az->lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -479,10 +479,13 @@ struct auth_zones* auth_zones_create(void);
|
|||
* @param cfg: config to apply.
|
||||
* @param setup: if true, also sets up values in the auth zones structure
|
||||
* @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.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
|
||||
int setup, int* is_rpz);
|
||||
int setup, int* is_rpz, struct module_env* env,
|
||||
struct module_stack* mods);
|
||||
|
||||
/** initial pick up of worker timeouts, ties events to worker event loop
|
||||
* @param az: auth zones structure
|
||||
|
|
@ -744,13 +747,27 @@ int auth_zone_generate_zonemd_check(struct auth_zone* z, int scheme,
|
|||
* @param z: auth zone to check. Caller holds lock. wrlock.
|
||||
* @param env: with temp region, buffer and config.
|
||||
* @param result: if not NULL, result string strdupped in here.
|
||||
* @param offline: if true, there is no spawned lookup when online is needed.
|
||||
* Those zones are skipped for ZONEMD checking.
|
||||
* @param only_online: if true, only for ZONEMD that need online lookup
|
||||
* of DNSKEY chain of trust are processed.
|
||||
*/
|
||||
void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
|
||||
char** result);
|
||||
char** result, int offline, int only_online);
|
||||
|
||||
/** mesh callback for zonemd on lookup of dnskey */
|
||||
void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode,
|
||||
struct sldns_buffer* buf, enum sec_status sec, char* why_bogus,
|
||||
int was_ratelimited);
|
||||
|
||||
/**
|
||||
* Check the ZONEMD records that need online DNSSEC chain lookups,
|
||||
* for them spawn the lookup process to get it checked out.
|
||||
* Attaches the lookup process to the worker event base and mesh state.
|
||||
* @param az: auth zones, every zones is checked.
|
||||
* @param env: env of the worker where the task is attached.
|
||||
*/
|
||||
void auth_zones_pickup_zonemd_verify(struct auth_zones* az,
|
||||
struct module_env* env);
|
||||
|
||||
#endif /* SERVICES_AUTHZONE_H */
|
||||
|
|
|
|||
|
|
@ -851,7 +851,7 @@ check_auth(struct config_file* cfg)
|
|||
{
|
||||
int is_rpz = 0;
|
||||
struct auth_zones* az = auth_zones_create();
|
||||
if(!az || !auth_zones_apply_cfg(az, cfg, 0, &is_rpz)) {
|
||||
if(!az || !auth_zones_apply_cfg(az, cfg, 0, &is_rpz, NULL, NULL)) {
|
||||
fatal_exit("Could not setup authority zones");
|
||||
}
|
||||
auth_zones_delete(az);
|
||||
|
|
|
|||
|
|
@ -291,7 +291,7 @@ static void zonemd_verify_test(char* zname, char* zfile, char* tastr,
|
|||
|
||||
/* test */
|
||||
lock_rw_wrlock(&z->lock);
|
||||
auth_zone_verify_zonemd(z, &env, &result);
|
||||
auth_zone_verify_zonemd(z, &env, &result, 1, 0);
|
||||
lock_rw_unlock(&z->lock);
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
printf("auth zone %s: ZONEMD verification %s: %s\n", zname,
|
||||
|
|
|
|||
Loading…
Reference in a new issue