rpz: forge responses

This commit is contained in:
mb 2020-11-24 11:25:01 +01:00
parent 354c19f6ac
commit 126e114d6f
3 changed files with 86 additions and 57 deletions

View file

@ -2471,7 +2471,14 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
/* Add the current set of unused targets to our queue. */
delegpt_add_unused_targets(iq->dp);
rpz_iterator_module_callback(qstate, iq);
{ /* apply rpz triggers at query time */
struct dns_msg* forged_response = rpz_iterator_module_callback(qstate, iq);
if(forged_response != NULL) {
iq->response = forged_response;
next_state(iq, FINISHED_STATE);
return 0;
}
}
/* Select the next usable target, filtering out unsuitable targets. */
target = iter_server_selection(ie, qstate->env, iq->dp,
@ -2662,16 +2669,12 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
{
int dnsseclame = 0;
enum response_type type;
//int rpz_filter_result;
iq->num_current_queries--;
if(!inplace_cb_query_response_call(qstate->env, qstate, iq->response))
log_err("unable to call query_response callback");
//rpz_filter_result = rpz_iterator_module_callback(qstate, iq);
//if(rpz_filter_result > 0) { next_state(iq, FINISHED_STATE); }
if(iq->response == NULL) {
/* Don't increment qname when QNAME minimisation is enabled */
if(qstate->env->cfg->qname_minimisation) {

View file

@ -1421,73 +1421,101 @@ nodata:
rpz_local_encode(qinfo, env, edns, repinfo, buf, temp, rp, rrset_count, rcode);
}
static inline void
rpz_patch_nodata(struct reply_info* ri)
static inline struct dns_msg*
rpz_dns_msg_new(struct regional* region)
{
FLAGS_SET_RCODE(ri->flags, LDNS_RCODE_NOERROR);
ri->flags |= BIT_QR | BIT_AA | BIT_RA;
ri->an_numrrsets = 0;
ri->ns_numrrsets = 0;
ri->ar_numrrsets = 0;
ri->authoritative = 0;
ri->rrset_count = 1;
ri->qdcount = 1;
struct dns_msg* msg =
(struct dns_msg*)regional_alloc(region,
sizeof(struct dns_msg));
if(msg == NULL) { return NULL; }
memset(msg, 0, sizeof(struct dns_msg));
return msg;
}
static inline void
rpz_patch_nxdomain(struct reply_info* ri)
static inline struct dns_msg*
rpz_patch_nodata(struct rpz* r, struct module_qstate* ms)
{
FLAGS_SET_RCODE(ri->flags, LDNS_RCODE_NXDOMAIN);
ri->flags |= BIT_QR | BIT_AA | BIT_RA;
ri->an_numrrsets = 0;
ri->ns_numrrsets = 0;
ri->ar_numrrsets = 0;
ri->authoritative = 0;
ri->rrset_count = 1;
ri->qdcount = 1;
struct dns_msg* msg = rpz_dns_msg_new(ms->region);
if(msg == NULL) { return msg; }
msg->qinfo = ms->qinfo;
msg->rep = construct_reply_info_base(ms->region,
LDNS_RCODE_NOERROR|BIT_QR|BIT_AA|BIT_RA,
1, //qd
0, //ttl
0, //prettl
0, //expttl
0, //an
0, //ns
0, //ar
1, //total
sec_status_secure);
return msg;
}
static inline int
rpz_patch_localdata(struct dns_msg* response, struct clientip_synthesized_rr* data,
struct regional* region)
static inline struct dns_msg*
rpz_patch_nxdomain(struct rpz* r, struct module_qstate* ms)
{
struct query_info* qi = &response->qinfo;
struct dns_msg* msg = rpz_dns_msg_new(ms->region);
if(msg == NULL) { return msg; }
msg->qinfo = ms->qinfo;
msg->rep = construct_reply_info_base(ms->region,
LDNS_RCODE_NXDOMAIN|BIT_QR|BIT_AA|BIT_RA,
1, //qd
0, //ttl
0, //prettl
0, //expttl
0, //an
0, //ns
0, //ar
1, //total
sec_status_secure);
return msg;
}
static inline struct dns_msg*
rpz_patch_localdata(struct rpz* r,
struct module_qstate* ms,
struct clientip_synthesized_rr* data)
{
struct dns_msg* msg = NULL;
struct query_info* qi = &msg->qinfo;
struct ub_packed_rrset_key* rp;
struct local_rrset* rrset;
struct reply_info* new_reply_info;
struct reply_info* ri = response->rep;
struct reply_info* ri = msg->rep;
rrset = rpz_find_synthesized_rrset(qi->qtype, data);
if(rrset == NULL) {
verbose(VERB_ALGO, "rpz: nsip: no matching synthesized data found; resorting to nodata");
rpz_patch_nodata(ri);
return 1;
return rpz_patch_nodata(r, ms);
}
new_reply_info = make_new_reply_info(ri, region, 0, 0);
msg = rpz_dns_msg_new(ms->region);
if(msg == NULL) { return NULL; }
// XXX: use ttl etc from rpz zone?
new_reply_info = make_new_reply_info(ri, ms->region, 0, 0);
if(new_reply_info == NULL) {
log_err("out of memory");
rpz_patch_nodata(ri);
return 1;
return NULL;
}
rp = respip_copy_rrset(rrset->rrset, region);
rp = respip_copy_rrset(rrset->rrset, ms->region);
if(rp == NULL) {
log_err("out of memory");
rpz_patch_nodata(ri);
return 1;
return NULL;
}
new_reply_info->rrsets = regional_alloc(region, sizeof(*new_reply_info->rrsets));
new_reply_info->rrsets = regional_alloc(ms->region, sizeof(*new_reply_info->rrsets));
if(new_reply_info->rrsets == NULL) {
log_err("out of memory");
rpz_patch_nodata(ri);
return 1;
return NULL;
}
rp->rk.dname = qi->qname;
rp->rk.dname_len = qi->qname_len;
new_reply_info->rrset_count = 1;
new_reply_info->an_numrrsets = 1;
new_reply_info->rrsets[0] = rp;
response->rep = new_reply_info;
return 1;
msg->rep = new_reply_info;
return msg;
}
struct clientip_synthesized_rr*
@ -1505,7 +1533,7 @@ rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz,
return NULL;
}
int
struct dns_msg*
rpz_iterator_module_callback(struct module_qstate* ms, struct iter_qstate* is)
{
struct auth_zones* az;
@ -1513,7 +1541,7 @@ rpz_iterator_module_callback(struct module_qstate* ms, struct iter_qstate* is)
struct clientip_synthesized_rr* raddr;
enum rpz_action action = RPZ_INVALID_ACTION;
struct rpz* r;
int ret = 0;
struct dns_msg* ret = NULL;
if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
@ -1537,7 +1565,7 @@ rpz_iterator_module_callback(struct module_qstate* ms, struct iter_qstate* is)
lock_rw_unlock(&az->rpz_lock);
if(raddr == NULL) { return 0; }
if(raddr == NULL) { return NULL; }
verbose(VERB_ALGO, "rpz: iterator callback: nsip: apply action=%s",
rpz_action_to_string(raddr->action));
@ -1545,33 +1573,31 @@ rpz_iterator_module_callback(struct module_qstate* ms, struct iter_qstate* is)
action = raddr->action;
if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) {
verbose(VERB_ALGO, "rpz: bug: local-data action but no local data");
ret = -1;
ret = rpz_patch_nodata(r, ms);
goto done;
}
switch(action) {
case RPZ_NXDOMAIN_ACTION:
rpz_patch_nxdomain(is->response->rep);
ret = 1;
ret = rpz_patch_nxdomain(r, ms);
break;
case RPZ_NODATA_ACTION:
rpz_patch_nodata(is->response->rep);
ret = 1;
ret = rpz_patch_nodata(r, ms);
break;
case RPZ_TCP_ONLY_ACTION:
log_err("rpz: nsip: tcp-only trigger unimplemented; resorting to passthru");
ret = 0;
verbose(VERB_ALGO, "rpz: nsip: tcp-only trigger ignored");
ret = NULL;
break;
case RPZ_PASSTHRU_ACTION:
ret = 0;
ret = NULL;
break;
case RPZ_LOCAL_DATA_ACTION:
ret = rpz_patch_localdata(is->response, raddr, ms->region);
ret = rpz_patch_localdata(r, ms, raddr);
break;
default:
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
rpz_action_to_string(action));
ret = 0;
ret = NULL;
}
done:

View file

@ -179,7 +179,7 @@ int rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
uint8_t* taglist, size_t taglen, struct ub_server_stats* stats);
struct iter_qstate;
int rpz_iterator_module_callback(struct module_qstate*, struct iter_qstate*);
struct dns_msg* rpz_iterator_module_callback(struct module_qstate*, struct iter_qstate*);
/**
* Delete RPZ