From: W.C.A. Wijngaards Date: Tue, 15 Feb 2022 15:20:12 +0000 (+0100) Subject: - Fix #628: A rpz-passthru action is not ending RPZ zone processing. X-Git-Tag: release-1.16.0rc1~51 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2b90181d3a47db7b19d0f2b8de0881f3e235aeb8;p=thirdparty%2Funbound.git - Fix #628: A rpz-passthru action is not ending RPZ zone processing. --- diff --git a/daemon/worker.c b/daemon/worker.c index aee308d7d..863cd7a35 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -553,7 +553,7 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo, return 1; if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo, - alias_rrset, 0, worker->scratchpad, az)) + alias_rrset, 0, worker->scratchpad, az, NULL)) return 0; /* xxx_deny actions mean dropping the reply, unless the original reply @@ -742,7 +742,8 @@ bail_out: /** Reply to client and perform prefetch to keep cache up to date. */ static void reply_and_prefetch(struct worker* worker, struct query_info* qinfo, - uint16_t flags, struct comm_reply* repinfo, time_t leeway, int noreply) + uint16_t flags, struct comm_reply* repinfo, time_t leeway, int noreply, + int rpz_passthru) { /* first send answer to client to keep its latency * as small as a cachereply */ @@ -761,7 +762,7 @@ reply_and_prefetch(struct worker* worker, struct query_info* qinfo, * the cache and go to the network for the data). */ /* this (potentially) runs the mesh for the new query */ mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway + - PREFETCH_EXPIRY_ADD); + PREFETCH_EXPIRY_ADD, rpz_passthru); } /** @@ -1073,6 +1074,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, int need_drop = 0; int is_expired_answer = 0; int is_secure_answer = 0; + int rpz_passthru = 0; /* We might have to chase a CNAME chain internally, in which case * we'll have up to two replies and combine them to build a complete * answer. These variables control this case. */ @@ -1338,7 +1340,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error, if(worker->env.auth_zones && rpz_callback_from_worker_request(worker->env.auth_zones, &worker->env, &qinfo, &edns, c->buffer, worker->scratchpad, - repinfo, acladdr->taglist, acladdr->taglen, &worker->stats)) { + repinfo, acladdr->taglist, acladdr->taglen, &worker->stats, + &rpz_passthru)) { regional_free_all(worker->scratchpad); if(sldns_buffer_limit(c->buffer) == 0) { comm_point_drop_reply(repinfo); @@ -1464,7 +1467,8 @@ lookup_cache: reply_and_prefetch(worker, lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2), repinfo, leeway, - (partial_rep || need_drop)); + (partial_rep || need_drop), + rpz_passthru); if(!partial_rep) { rc = 0; regional_free_all(worker->scratchpad); @@ -1527,7 +1531,8 @@ lookup_cache: /* grab a work request structure for this new request */ mesh_new_client(worker->env.mesh, &qinfo, cinfo, sldns_buffer_read_u16_at(c->buffer, 2), - &edns, repinfo, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer)); + &edns, repinfo, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), + rpz_passthru); regional_free_all(worker->scratchpad); worker_mem_report(worker, NULL); return 0; diff --git a/doc/Changelog b/doc/Changelog index 3690dd653..7dea5002e 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +15 February 2022: Wouter + - Fix #628: A rpz-passthru action is not ending RPZ zone processing. + 11 February 2022: Wouter - Fix #624: Unable to stop Unbound in Windows console (does not respond to CTRL+C command). diff --git a/libunbound/libworker.c b/libunbound/libworker.c index ab28dd54f..11bf5f9db 100644 --- a/libunbound/libworker.c +++ b/libunbound/libworker.c @@ -650,7 +650,7 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q) } /* process new query */ if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, - w->back->udp_buff, qid, libworker_fg_done_cb, q)) { + w->back->udp_buff, qid, libworker_fg_done_cb, q, 0)) { free(qinfo.qname); return UB_NOMEM; } @@ -730,7 +730,7 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q, if(async_id) *async_id = q->querynum; if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, - w->back->udp_buff, qid, libworker_event_done_cb, q)) { + w->back->udp_buff, qid, libworker_event_done_cb, q, 0)) { free(qinfo.qname); return UB_NOMEM; } @@ -867,7 +867,7 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len) q->w = w; /* process new query */ if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, - w->back->udp_buff, qid, libworker_bg_done_cb, q)) { + w->back->udp_buff, qid, libworker_bg_done_cb, q, 0)) { add_bg_result(w, q, NULL, UB_NOMEM, NULL, 0); } free(qinfo.qname); diff --git a/respip/respip.c b/respip/respip.c index 3d1b3feaf..569943e9e 100644 --- a/respip/respip.c +++ b/respip/respip.c @@ -833,8 +833,11 @@ static int respip_use_rpz(struct resp_addr* raddr, struct rpz* r, enum respip_action* action, struct ub_packed_rrset_key** data, int* rpz_log, char** log_name, - int* rpz_cname_override, struct regional* region, int* is_rpz) + int* rpz_cname_override, struct regional* region, int* is_rpz, + int* rpz_passthru) { + if(rpz_passthru && *rpz_passthru) + return 0; if(r->action_override == RPZ_DISABLED_ACTION) { *is_rpz = 0; return 1; @@ -848,6 +851,9 @@ respip_use_rpz(struct resp_addr* raddr, struct rpz* r, *data = r->cname_override; *rpz_cname_override = 1; } + if(*action == respip_always_transparent /* RPZ_PASSTHRU_ACTION */ + && rpz_passthru) + *rpz_passthru = 1; *rpz_log = r->log; if(r->log_name) if(!(*log_name = regional_strdup(region, r->log_name))) @@ -861,7 +867,7 @@ respip_rewrite_reply(const struct query_info* qinfo, const struct respip_client_info* cinfo, const struct reply_info* rep, struct reply_info** new_repp, struct respip_action_info* actinfo, struct ub_packed_rrset_key** alias_rrset, int search_only, - struct regional* region, struct auth_zones* az) + struct regional* region, struct auth_zones* az, int* rpz_passthru) { const uint8_t* ctaglist; size_t ctaglen; @@ -934,7 +940,7 @@ respip_rewrite_reply(const struct query_info* qinfo, ipset->tagname, ipset->num_tags); } lock_rw_rdlock(&az->rpz_lock); - for(a = az->rpz_first; a && !raddr; a = a->rpz_az_next) { + for(a = az->rpz_first; a && !raddr && !(rpz_passthru && *rpz_passthru); a = a->rpz_az_next) { lock_rw_rdlock(&a->lock); r = a->rpz; if(!r->taglist || taglist_intersect(r->taglist, @@ -943,7 +949,7 @@ respip_rewrite_reply(const struct query_info* qinfo, r->respip_set, &rrset_id, &rr_id))) { if(!respip_use_rpz(raddr, r, &action, &data, &rpz_log, &log_name, &rpz_cname_override, - region, &rpz_used)) { + region, &rpz_used, rpz_passthru)) { log_err("out of memory"); lock_rw_unlock(&raddr->lock); lock_rw_unlock(&a->lock); @@ -1094,7 +1100,8 @@ respip_operate(struct module_qstate* qstate, enum module_ev event, int id, if(!respip_rewrite_reply(&qstate->qinfo, qstate->client_info, qstate->return_msg->rep, &new_rep, &actinfo, &alias_rrset, 0, - qstate->region, qstate->env->auth_zones)) { + qstate->region, qstate->env->auth_zones, + &qstate->rpz_passthru)) { goto servfail; } if(actinfo.action != respip_none) { @@ -1169,7 +1176,7 @@ respip_merge_cname(struct reply_info* base_rep, /* see if the target reply would be subject to a response-ip action. */ if(!respip_rewrite_reply(qinfo, cinfo, tgt_rep, &tmp_rep, &actinfo, - &alias_rrset, 1, region, az)) + &alias_rrset, 1, region, az, NULL)) return 0; if(actinfo.action != respip_none) { log_info("CNAME target of redirect response-ip action would " diff --git a/respip/respip.h b/respip/respip.h index 3dfb4e9f0..988a72263 100644 --- a/respip/respip.h +++ b/respip/respip.h @@ -176,6 +176,8 @@ int respip_merge_cname(struct reply_info* base_rep, * will be set (or intact) accordingly but the modified reply won't be built. * @param az: auth zones containing RPZ information. * @param region: allocator to build *new_repp. + * @param rpz_passthru: keeps track of query state can have passthru that + * stops further rpz processing. Or NULL for cached answer processing. * @return 1 on success, 0 on error. */ int respip_rewrite_reply(const struct query_info* qinfo, @@ -183,7 +185,8 @@ int respip_rewrite_reply(const struct query_info* qinfo, const struct reply_info *rep, struct reply_info** new_repp, struct respip_action_info* actinfo, struct ub_packed_rrset_key** alias_rrset, - int search_only, struct regional* region, struct auth_zones* az); + int search_only, struct regional* region, struct auth_zones* az, + int* rpz_passthru); /** * Get the response-ip function block. diff --git a/services/authzone.c b/services/authzone.c index e83af533d..66d118b02 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -5370,7 +5370,7 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env) * called straight away */ lock_basic_unlock(&xfr->lock); if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, - &auth_xfer_transfer_lookup_callback, xfr)) { + &auth_xfer_transfer_lookup_callback, xfr, 0)) { lock_basic_lock(&xfr->lock); log_err("out of memory lookup up master %s", master->host); return 0; @@ -6561,7 +6561,7 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env) * called straight away */ lock_basic_unlock(&xfr->lock); if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, - &auth_xfer_probe_lookup_callback, xfr)) { + &auth_xfer_probe_lookup_callback, xfr, 0)) { lock_basic_lock(&xfr->lock); log_err("out of memory lookup up master %s", master->host); return 0; @@ -8340,7 +8340,7 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env) /* the callback can be called straight away */ lock_rw_unlock(&z->lock); if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, - &auth_zonemd_dnskey_lookup_callback, z)) { + &auth_zonemd_dnskey_lookup_callback, z, 0)) { lock_rw_wrlock(&z->lock); log_err("out of memory lookup of %s for zonemd", (fetch_ds?"DS":"DNSKEY")); diff --git a/services/mesh.c b/services/mesh.c index cdcfedda2..4b022d47f 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -458,7 +458,8 @@ mesh_serve_expired_init(struct mesh_state* mstate, int timeout) void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, struct respip_client_info* cinfo, uint16_t qflags, - struct edns_data* edns, struct comm_reply* rep, uint16_t qid) + struct edns_data* edns, struct comm_reply* rep, uint16_t qid, + int rpz_passthru) { struct mesh_state* s = NULL; int unique = unique_mesh_state(edns->opt_list_in, mesh->env); @@ -513,6 +514,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, } if(unique) mesh_state_make_unique(s); + s->s.rpz_passthru = rpz_passthru; /* copy the edns options we got from the front */ if(edns->opt_list_in) { s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in, @@ -606,7 +608,7 @@ servfail_mem: int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, uint16_t qflags, struct edns_data* edns, sldns_buffer* buf, - uint16_t qid, mesh_cb_func_type cb, void* cb_arg) + uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru) { struct mesh_state* s = NULL; int unique = unique_mesh_state(edns->opt_list_in, mesh->env); @@ -632,6 +634,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, } if(unique) mesh_state_make_unique(s); + s->s.rpz_passthru = rpz_passthru; if(edns->opt_list_in) { s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in, s->s.region); @@ -686,7 +689,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, * 0 (false), in which case the new state is only made runnable so it * will not be run recursively on top of the current state. */ static void mesh_schedule_prefetch(struct mesh_area* mesh, - struct query_info* qinfo, uint16_t qflags, time_t leeway, int run) + struct query_info* qinfo, uint16_t qflags, time_t leeway, int run, + int rpz_passthru) { struct mesh_state* s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0); @@ -741,6 +745,7 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh, s->list_select = mesh_jostle_list; } } + s->s.rpz_passthru = rpz_passthru; if(!run) { #ifdef UNBOUND_DEBUG @@ -757,9 +762,9 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh, } void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo, - uint16_t qflags, time_t leeway) + uint16_t qflags, time_t leeway, int rpz_passthru) { - mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1); + mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1, rpz_passthru); } void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e, @@ -1693,6 +1698,7 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate, if(mstate->s.curmod == 0) { struct query_info* qinfo = NULL; uint16_t qflags; + int rpz_p = 0; mesh_query_done(mstate); mesh_walk_supers(mesh, mstate); @@ -1701,13 +1707,15 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate, * from an external DNS server, we'll need to schedule * a prefetch after removing the current state, so * we need to make a copy of the query info here. */ - if(mstate->s.need_refetch) + if(mstate->s.need_refetch) { mesh_copy_qinfo(mstate, &qinfo, &qflags); + rpz_p = mstate->s.rpz_passthru; + } mesh_state_delete(&mstate->s); if(qinfo) { mesh_schedule_prefetch(mesh, qinfo, qflags, - 0, 1); + 0, 1, rpz_p); } return 0; } @@ -1917,7 +1925,7 @@ apply_respip_action(struct module_qstate* qstate, return 1; if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, actinfo, - alias_rrset, 0, qstate->region, az)) + alias_rrset, 0, qstate->region, az, NULL)) return 0; /* xxx_deny actions mean dropping the reply, unless the original reply diff --git a/services/mesh.h b/services/mesh.h index d0a4b5fb3..526e679fe 100644 --- a/services/mesh.h +++ b/services/mesh.h @@ -296,10 +296,13 @@ void mesh_delete(struct mesh_area* mesh); * @param edns: edns data from client query. * @param rep: where to reply to. * @param qid: query id to reply with. + * @param rpz_passthru: if true, the rpz passthru was previously found and + * further rpz processing is stopped. */ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, struct respip_client_info* cinfo, uint16_t qflags, - struct edns_data* edns, struct comm_reply* rep, uint16_t qid); + struct edns_data* edns, struct comm_reply* rep, uint16_t qid, + int rpz_passthru); /** * New query with callback. Create new query state if needed, and @@ -314,11 +317,13 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, * @param qid: query id to reply with. * @param cb: callback function. * @param cb_arg: callback user arg. + * @param rpz_passthru: if true, the rpz passthru was previously found and + * further rpz processing is stopped. * @return 0 on error. */ int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, uint16_t qflags, struct edns_data* edns, struct sldns_buffer* buf, - uint16_t qid, mesh_cb_func_type cb, void* cb_arg); + uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru); /** * New prefetch message. Create new query state if needed. @@ -328,9 +333,11 @@ int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, * @param qinfo: query from client. * @param qflags: flags from client query. * @param leeway: TTL leeway what to expire earlier for this update. + * @param rpz_passthru: if true, the rpz passthru was previously found and + * further rpz processing is stopped. */ void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo, - uint16_t qflags, time_t leeway); + uint16_t qflags, time_t leeway, int rpz_passthru); /** * Handle new event from the wire. A serviced query has returned. diff --git a/services/rpz.c b/services/rpz.c index 322e9d139..2d8b06922 100644 --- a/services/rpz.c +++ b/services/rpz.c @@ -1997,6 +1997,7 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r, break; case RPZ_PASSTHRU_ACTION: ret = NULL; + ms->rpz_passthru = 1; break; default: verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'", @@ -2051,6 +2052,7 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r, break; case RPZ_PASSTHRU_ACTION: ret = NULL; + ms->rpz_passthru = 1; break; default: verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'", @@ -2114,6 +2116,11 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate* struct local_zone* z = NULL; struct matched_delegation_point match = {0}; + if(ms->rpz_passthru) { + verbose(VERB_ALGO, "query is rpz_passthru, no futher processing"); + return NULL; + } + if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; } az = ms->env->auth_zones; @@ -2179,6 +2186,11 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms, enum localzone_type lzt; struct dns_msg* ret = NULL; + if(ms->rpz_passthru) { + verbose(VERB_ALGO, "query is rpz_passthru, no futher processing"); + return NULL; + } + if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; } az = ms->env->auth_zones; @@ -2253,6 +2265,7 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms, break; case RPZ_PASSTHRU_ACTION: ret = NULL; + ms->rpz_passthru = 1; break; default: verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'", @@ -2270,7 +2283,8 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env, uint8_t* taglist, size_t taglen, struct ub_server_stats* stats, sldns_buffer* buf, struct regional* temp, /* output parameters */ - struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out) + struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out, + int* passthru) { int ret = 0; enum rpz_action client_action; @@ -2278,7 +2292,9 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env, az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out); client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action); - + if(client_action == RPZ_PASSTHRU_ACTION) { + *passthru = 1; + } if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION && client_action != RPZ_PASSTHRU_ACTION)) { if(client_action == RPZ_PASSTHRU_ACTION @@ -2323,7 +2339,7 @@ int rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env, struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf, struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist, - size_t taglen, struct ub_server_stats* stats) + size_t taglen, struct ub_server_stats* stats, int* passthru) { struct rpz* r = NULL; struct auth_zone* a = NULL; @@ -2332,7 +2348,8 @@ rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env, enum localzone_type lzt; int clientip_trigger = rpz_apply_maybe_clientip_trigger(az, env, qinfo, - edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r); + edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r, + passthru); if(clientip_trigger >= 0) { if(a) { lock_rw_unlock(&a->lock); @@ -2357,6 +2374,9 @@ rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env, } else { lzt = rpz_action_to_localzone_type(r->action_override); } + if(r->action_override == RPZ_PASSTHRU_ACTION) { + *passthru = 1; + } if(verbosity >= VERB_ALGO) { char nm[255+1], zn[255+1]; diff --git a/services/rpz.h b/services/rpz.h index c29d30dff..53781197a 100644 --- a/services/rpz.h +++ b/services/rpz.h @@ -176,12 +176,14 @@ void rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname, * @param taglist: taglist to lookup. * @param taglen: length of taglist. * @param stats: worker stats struct + * @param passthru: returns if the query can passthru further rpz processing. * @return: 1 if client answer is ready, 0 to continue resolving */ int rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env, struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf, struct regional* temp, struct comm_reply* repinfo, - uint8_t* taglist, size_t taglen, struct ub_server_stats* stats); + uint8_t* taglist, size_t taglen, struct ub_server_stats* stats, + int* passthru); /** * Callback to process when the iterator module is about to send queries. diff --git a/testdata/rpz_passthru.rpl b/testdata/rpz_passthru.rpl new file mode 100644 index 000000000..cc7a6af89 --- /dev/null +++ b/testdata/rpz_passthru.rpl @@ -0,0 +1,111 @@ +; config options +server: + module-config: "respip validator iterator" + target-fetch-policy: "0 0 0 0 0" + qname-minimisation: no + access-control: 192.0.0.0/8 allow + +rpz: + name: "rpz.example.com." + rpz-log: yes + rpz-log-name: "rpz.example.com" + rpz-action-override: passthru + zonefile: +TEMPFILE_NAME rpz.example.com +TEMPFILE_CONTENTS rpz.example.com +$ORIGIN example.com. +rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( + 1379078166 28800 7200 604800 7200 ) + 3600 IN NS ns1.rpz.example.com. + 3600 IN NS ns2.rpz.example.com. +$ORIGIN rpz.example.com. +c.a TXT "local data 1st zone" +d.a A 127.0.0.1 +TEMPFILE_END + +rpz: + name: "rpz2.example.com." + rpz-log: yes + rpz-log-name: "rpz2.example.com" + rpz-action-override: nxdomain + zonefile: +TEMPFILE_NAME rpz2.example.com +TEMPFILE_CONTENTS rpz2.example.com +$ORIGIN example.com. +rpz2 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( + 1379078166 28800 7200 604800 7200 ) + 3600 IN NS ns1.rpz.example.com. + 3600 IN NS ns2.rpz.example.com. +$ORIGIN rpz2.example.com. +c.a TXT "local data 2nd zone" +24.0.5.0.192.rpz-client-ip A 127.0.0.1 +24.0.5.0.192.rpz-client-ip TXT "clientip 2nd zone" +24.0.3.2.1.rpz-ip A 127.0.0.2 +TEMPFILE_END + +stub-zone: + name: "a." + stub-addr: 10.20.30.40 +CONFIG_END + +SCENARIO_BEGIN Test RPZ passthru ends processing for later triggers. + +; a. +RANGE_BEGIN 0 1000 + ADDRESS 10.20.30.40 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +c.a. IN TXT +SECTION ANSWER +c.a. IN TXT "answer from upstream ns" +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +d.a. IN A +SECTION ANSWER +d.a. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 10 QUERY ADDRESS 192.0.5.1 +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +c.a. IN TXT +ENTRY_END + +STEP 11 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +c.a. IN TXT +SECTION ANSWER +c.a. IN TXT "answer from upstream ns" +ENTRY_END + +STEP 20 QUERY ADDRESS 192.0.2.1 +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +d.a. IN A +ENTRY_END + +STEP 21 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +d.a. IN A +SECTION ANSWER +d.a. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/rpz_qname.rpl b/testdata/rpz_qname.rpl index ede697233..aae55b573 100644 --- a/testdata/rpz_qname.rpl +++ b/testdata/rpz_qname.rpl @@ -6,6 +6,8 @@ server: rpz: name: "rpz.example.com." + rpz-log: yes + rpz-log-name: "rpz.example.com" zonefile: TEMPFILE_NAME rpz.example.com TEMPFILE_CONTENTS rpz.example.com @@ -20,10 +22,13 @@ a CNAME *. ; duplicate CNAME here on purpose *.a TXT "wildcard local data" b.a CNAME *. c.a CNAME rpz-passthru. +c.g CNAME rpz-passthru. TEMPFILE_END rpz: name: "rpz2.example.com." + rpz-log: yes + rpz-log-name: "rpz2.example.com" zonefile: TEMPFILE_NAME rpz2.example.com TEMPFILE_CONTENTS rpz2.example.com @@ -39,6 +44,7 @@ e CNAME *.a.example. *.e CNAME *.b.example. drop CNAME rpz-drop. tcp CNAME rpz-tcp-only. +c.g CNAME . TEMPFILE_END stub-zone: @@ -50,6 +56,9 @@ stub-zone: stub-zone: name: "tcp." stub-addr: 10.20.30.60 +stub-zone: + name: "g." + stub-addr: 10.20.30.40 CONFIG_END SCENARIO_BEGIN Test all support RPZ action for QNAME trigger @@ -89,6 +98,16 @@ SECTION ANSWER x.b.a. IN TXT "answer from upstream ns" ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +c.g. IN TXT +SECTION ANSWER +c.g. IN TXT "answer from upstream ns" +ENTRY_END + RANGE_END ; example. @@ -396,5 +415,23 @@ f.example. IN CNAME d. d. IN TXT "local data 2nd zone" ENTRY_END +; check if passthru ends processing +STEP 110 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +c.g. IN TXT +ENTRY_END + +STEP 111 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +c.g. IN TXT +SECTION ANSWER +c.g. IN TXT "answer from upstream ns" +ENTRY_END + ; no answer is checked at exit of testbound. SCENARIO_END diff --git a/util/module.h b/util/module.h index 7a5480033..1ae7477cb 100644 --- a/util/module.h +++ b/util/module.h @@ -667,6 +667,8 @@ struct module_qstate { /** Extended result of response-ip action processing, mainly * for logging purposes. */ struct respip_action_info* respip_action_info; + /** if the query is rpz passthru, no further rpz processing for it */ + int rpz_passthru; /** whether the reply should be dropped */ int is_drop; diff --git a/validator/autotrust.c b/validator/autotrust.c index 55e82c176..ec656a1bd 100644 --- a/validator/autotrust.c +++ b/validator/autotrust.c @@ -2397,7 +2397,7 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp) qinfo.qclass); if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, - &probe_answer_cb, env)) { + &probe_answer_cb, env, 0)) { log_err("out of memory making 5011 probe"); } }