- add always_deny action, use this one for RPZ

- use localzone's memory layout when removing rr from rrset
This commit is contained in:
Ralph Dolmans 2019-08-23 12:15:37 +02:00
parent a16111d471
commit ccb576f95e
8 changed files with 483 additions and 16 deletions

View File

@ -195,6 +195,8 @@ respip_action_cfg(struct respip_set* set, const char* ipstr,
action = respip_always_nxdomain;
else if(strcmp(actnstr, "always_nodata") == 0)
action = respip_always_nodata;
else if(strcmp(actnstr, "always_deny") == 0)
action = respip_always_deny;
else {
log_err("unknown response-ip action %s", actnstr);
return 0;
@ -962,6 +964,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
&& action != respip_always_transparent
&& action != respip_always_nxdomain
&& action != respip_always_nodata
&& action != respip_always_deny
&& (result = respip_data_answer(action,
(data) ? data : raddr->data, qinfo->qtype, rep,
rrset_id, new_repp, tag, tag_datas, tag_datas_size,
@ -1080,9 +1083,11 @@ respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
} else {
qstate->respip_action_info = NULL;
}
if (new_rep == qstate->return_msg->rep &&
if (actinfo.action == respip_always_deny ||
(new_rep == qstate->return_msg->rep &&
(actinfo.action == respip_deny ||
actinfo.action == respip_inform_deny)) {
actinfo.action == respip_deny ||
actinfo.action == respip_inform_deny))) {
/* for deny-variant actions (unless response-ip
* data is applied), mark the query state so
* the response will be dropped for all
@ -1283,7 +1288,7 @@ respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen,
"[%s] ", respip_actinfo->log_name);
}
txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen,
snprintf(txt+txtlen, sizeof(txt)-txtlen,
"%s/%d %s %s@%u", respip, respip_addr->net,
(actionstr) ? actionstr : "inform", srcip, port);
if(actionstr)

View File

@ -394,6 +394,27 @@ rrset_insert_rr(struct regional* region, struct packed_rrset_data* pd,
return 1;
}
/** Delete RR from local-zone RRset, wastes memory as the deleted RRs cannot be
* free'd (regionally alloc'd) */
int
local_rrset_remove_rr(struct packed_rrset_data* pd, size_t index)
{
if(index >= pd->count) {
log_warn("Trying to remove RR with out of bound index");
return 0;
}
if(index - 1 < pd->count) {
/* not removing last element */
size_t nexti = index + 1;
size_t num = pd->count - nexti;
memcpy(pd->rr_len+index, pd->rr_len+nexti, sizeof(*pd->rr_len)*num);
memcpy(pd->rr_ttl+index, pd->rr_ttl+nexti, sizeof(*pd->rr_ttl)*num);
memcpy(pd->rr_data+index, pd->rr_data+nexti, sizeof(*pd->rr_data)*num);
}
pd->count--;
return 1;
}
struct local_data*
local_zone_find_data(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs)
{
@ -1447,7 +1468,9 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
struct comm_reply* repinfo, sldns_buffer* buf, struct regional* temp,
struct local_data* ld, enum localzone_type lz_type)
{
if(lz_type == local_zone_deny || lz_type == local_zone_inform_deny) {
if(lz_type == local_zone_deny ||
lz_type == local_zone_always_deny ||
lz_type == local_zone_inform_deny) {
/** no reply at all, signal caller by clearing buffer. */
sldns_buffer_clear(buf);
sldns_buffer_flip(buf);
@ -1655,6 +1678,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
&& lzt != local_zone_always_transparent
&& lzt != local_zone_always_nxdomain
&& lzt != local_zone_always_nodata
&& lzt != local_zone_always_deny
&& local_data_answer(z, env, qinfo, edns, repinfo, buf, temp, labs,
&ld, lzt, tag, tag_datas, tag_datas_size, tagname, num_tags)) {
lock_rw_unlock(&z->lock);
@ -1685,6 +1709,7 @@ const char* local_zone_type2str(enum localzone_type t)
case local_zone_always_refuse: return "always_refuse";
case local_zone_always_nxdomain: return "always_nxdomain";
case local_zone_always_nodata: return "always_nodata";
case local_zone_always_deny: return "always_deny";
case local_zone_noview: return "noview";
case local_zone_invalid: return "invalid";
}
@ -1719,6 +1744,8 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
*t = local_zone_always_nxdomain;
else if(strcmp(type, "always_nodata") == 0)
*t = local_zone_always_nodata;
else if(strcmp(type, "always_deny") == 0)
*t = local_zone_always_deny;
else if(strcmp(type, "noview") == 0)
*t = local_zone_noview;
else if(strcmp(type, "nodefault") == 0)

View File

@ -94,6 +94,8 @@ enum localzone_type {
local_zone_always_nxdomain,
/** answer with noerror/nodata, even when there is local data */
local_zone_always_nodata,
/** drop query, even when there is local data */
local_zone_always_deny,
/** answer not from the view, but global or no-answer */
local_zone_noview,
/** Invalid type, cannot be used to generate answer */
@ -513,6 +515,15 @@ int rrstr_get_rr_content(const char* str, uint8_t** nm, uint16_t* type,
int rrset_insert_rr(struct regional* region, struct packed_rrset_data* pd,
uint8_t* rdata, size_t rdata_len, time_t ttl, const char* rrstr);
/**
* Remove RR from rrset that is created using localzone's rrset_insert_rr.
* @param pd: the RRset containing the RR to remove
* @param index: index of RR to remove
* @return: 1 on success; 0 otherwise.
*/
int
local_rrset_remove_rr(struct packed_rrset_data* pd, size_t index);
/**
* Valid response ip actions for the IP-response-driven-action feature;
* defined here instead of in the respip module to enable sharing of enum
@ -543,6 +554,8 @@ enum respip_action {
respip_always_nxdomain = local_zone_always_nxdomain,
/** answer with nodata response */
respip_always_nodata = local_zone_always_nodata,
/** answer with nodata response */
respip_always_deny = local_zone_always_deny,
/* The rest of the values are only possible as
* access-control-tag-action */

View File

@ -197,7 +197,7 @@ rpz_action_to_localzone_type(enum rpz_action a)
switch(a) {
case RPZ_NXDOMAIN_ACTION: return local_zone_always_nxdomain;
case RPZ_NODATA_ACTION: return local_zone_always_nodata;
case RPZ_DROP_ACTION: return local_zone_deny;
case RPZ_DROP_ACTION: return local_zone_always_deny;
case RPZ_PASSTHRU_ACTION: return local_zone_always_transparent;
case RPZ_LOCAL_DATA_ACTION:
case RPZ_CNAME_OVERRIDE_ACTION:
@ -215,7 +215,7 @@ rpz_action_to_respip_action(enum rpz_action a)
switch(a) {
case RPZ_NXDOMAIN_ACTION: return respip_always_nxdomain;
case RPZ_NODATA_ACTION: return respip_always_nodata;
case RPZ_DROP_ACTION: return respip_deny;
case RPZ_DROP_ACTION: return respip_always_deny;
case RPZ_PASSTHRU_ACTION: return respip_always_transparent;
case RPZ_LOCAL_DATA_ACTION:
case RPZ_CNAME_OVERRIDE_ACTION:
@ -233,7 +233,7 @@ localzone_type_to_rpz_action(enum localzone_type lzt)
switch(lzt) {
case local_zone_always_nxdomain: return RPZ_NXDOMAIN_ACTION;
case local_zone_always_nodata: return RPZ_NODATA_ACTION;
case local_zone_deny: return RPZ_DROP_ACTION;
case local_zone_always_deny: return RPZ_DROP_ACTION;
case local_zone_always_transparent: return RPZ_PASSTHRU_ACTION;
case local_zone_redirect: return RPZ_LOCAL_DATA_ACTION;
case local_zone_invalid:
@ -248,7 +248,7 @@ respip_action_to_rpz_action(enum respip_action a)
switch(a) {
case respip_always_nxdomain: return RPZ_NXDOMAIN_ACTION;
case respip_always_nodata: return RPZ_NODATA_ACTION;
case respip_deny: return RPZ_DROP_ACTION;
case respip_always_deny: return RPZ_DROP_ACTION;
case respip_always_transparent: return RPZ_PASSTHRU_ACTION;
case respip_redirect: return RPZ_LOCAL_DATA_ACTION;
case respip_invalid:
@ -689,11 +689,8 @@ rpz_data_delete_rr(struct local_zone* z, uint8_t* policydname,
}
if(d->count > 1) {
struct packed_rrset_data* new;
new = packed_rrset_remove_rr(d, index, z->region);
if(!new)
if(!local_rrset_remove_rr(d, index))
return 0;
p->rrset->entry.data = new;
}
}
}
@ -731,11 +728,8 @@ rpz_rrset_delete_rr(struct resp_addr* raddr, uint16_t rr_type, uint8_t* rdata,
return 1;
}
if(d->count > 1) {
struct packed_rrset_data* new;
new = packed_rrset_remove_rr(d, index, region);
if(!new)
if(!local_rrset_remove_rr(d, index))
return 0;
raddr->data->entry.data = new;
}
}
return 0;

View File

@ -44,6 +44,7 @@
#include "services/localzone.h"
#include "util/locks.h"
#include "util/log.h"
#include "util/config_file.h"
#include "services/authzone.h"
#include "sldns/sbuffer.h"

378
testdata/rpz_ixfr.rpl vendored Normal file
View File

@ -0,0 +1,378 @@
; config options
server:
module-config: "respip validator iterator"
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
rpz:
name: "rpz.example.com."
master: 10.20.30.40
zonefile:
TEMPFILE_NAME rpz.example.com
TEMPFILE_CONTENTS rpz.example.com
rpz.example.com. 3600 IN SOA ns.rpz.example.com. hostmaster.rpz.example.com. 1 3600 900 86400 3600
rpz.example.com. 3600 IN NS ns.rpz.example.net.
a.rpz.example.com. IN CNAME *.
c.rpz.example.com. IN TXT "hello from initial RPZ"
c.rpz.example.com. IN TXT "another hello from initial RPZ"
c.rpz.example.com. IN TXT "yet another hello from initial RPZ"
d.rpz.example.com. IN CNAME .
32.1.123.0.10.rpz-ip.rpz.example.com. CNAME *.
32.3.123.0.10.rpz-ip.rpz.example.com. A 10.66.0.3
32.3.123.0.10.rpz-ip.rpz.example.com. A 10.66.0.4
32.4.123.0.10.rpz-ip.rpz.example.com. CNAME .
TEMPFILE_END
stub-zone:
name: "."
stub-addr: 10.20.30.40
CONFIG_END
SCENARIO_BEGIN Test RPZ QNAME trigger, loaded using IXFR
RANGE_BEGIN 0 100
ADDRESS 10.20.30.40
ENTRY_BEGIN
MATCH opcode qname qtype
ADJUST copy_id
REPLY QR NOERROR AA
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS ns.
SECTION ADDITIONAL
ns. IN NS 10.20.30.40
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
ADJUST copy_id
REPLY QR NOERROR AA
SECTION QUESTION
b. IN TXT
SECTION ANSWER
b. TXT "hello from upstream"
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
ADJUST copy_id
REPLY QR NOERROR AA
SECTION QUESTION
d. IN TXT
SECTION ANSWER
d. TXT "hello from upstream"
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
ADJUST copy_id
REPLY QR NOERROR AA
SECTION QUESTION
a.rpz-ip. IN A
SECTION ANSWER
a.rpz-ip. IN A 10.0.123.1
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
ADJUST copy_id
REPLY QR NOERROR AA
SECTION QUESTION
c.rpz-ip. IN A
SECTION ANSWER
c.rpz-ip. IN A 10.0.123.3
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
ADJUST copy_id
REPLY QR NOERROR AA
SECTION QUESTION
d.rpz-ip. IN A
SECTION ANSWER
d.rpz-ip. IN A 10.0.123.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
rpz.example.com. IN SOA
SECTION ANSWER
rpz.example.com. IN SOA ns.rpz.example.com. hostmaster.rpz.example.com. 2 3600 900 86400 3600
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
rpz.example.com. IN IXFR
SECTION ANSWER
rpz.example.com. IN SOA ns.rpz.example.com. hostmaster.rpz.example.com. 2 3600 900 86400 3600
rpz.example.com. IN SOA ns.rpz.example.com. hostmaster.rpz.example.com. 1 3600 900 86400 3600
a.rpz.example.com. IN CNAME *.
c.rpz.example.com. IN TXT "hello from initial RPZ"
c.rpz.example.com. IN TXT "another hello from initial RPZ"
d.rpz.example.com. IN CNAME .
32.1.123.0.10.rpz-ip.rpz.example.com. CNAME *.
32.3.123.0.10.rpz-ip.rpz.example.com. A 10.66.0.3
32.3.123.0.10.rpz-ip.rpz.example.com. A 10.66.0.4
32.4.123.0.10.rpz-ip.rpz.example.com. CNAME .
rpz.example.com. IN SOA ns.rpz.example.com. hostmaster.rpz.example.com. 2 3600 900 86400 3600
b.rpz.example.com. TXT "hello from RPZ"
c.rpz.example.com. TXT "hello from RPZ"
a.rpz.example.com. CNAME .
32.1.123.0.10.rpz-ip.rpz.example.com. CNAME .
32.3.123.0.10.rpz-ip.rpz.example.com. A 10.66.0.5
32.3.123.0.10.rpz-ip.rpz.example.com. A 10.66.0.6
rpz.example.com. IN SOA ns.rpz.example.com. hostmaster.rpz.example.com. 2 3600 900 86400 3600
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
b. IN TXT
ENTRY_END
STEP 2 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
b. IN TXT
SECTION ANSWER
b. IN TXT "hello from upstream"
ENTRY_END
STEP 3 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
a. IN TXT
ENTRY_END
STEP 4 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
a. IN TXT
SECTION ANSWER
ENTRY_END
STEP 5 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
a.rpz-ip. IN A
ENTRY_END
STEP 6 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
a.rpz-ip. IN A
SECTION ANSWER
ENTRY_END
STEP 7 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
c. IN TXT
ENTRY_END
STEP 8 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
c. IN TXT
SECTION ANSWER
c. IN TXT "yet another hello from initial RPZ"
c. IN TXT "another hello from initial RPZ"
c. IN TXT "hello from initial RPZ"
ENTRY_END
STEP 9 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
c.rpz-ip. IN A
ENTRY_END
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
c.rpz-ip. IN A
SECTION ANSWER
c.rpz-ip. IN A 10.66.0.4
c.rpz-ip. IN A 10.66.0.3
ENTRY_END
STEP 11 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d. IN TXT
ENTRY_END
STEP 12 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NXDOMAIN
SECTION QUESTION
d. IN TXT
ENTRY_END
STEP 13 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.rpz-ip. IN A
ENTRY_END
STEP 15 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NXDOMAIN
SECTION QUESTION
d.rpz-ip. IN A
ENTRY_END
STEP 16 TIME_PASSES ELAPSE 1
STEP 30 TIME_PASSES ELAPSE 3600
STEP 40 TRAFFIC
STEP 50 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
b. IN TXT
ENTRY_END
STEP 51 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
b. IN TXT
SECTION ANSWER
b. IN TXT "hello from RPZ"
ENTRY_END
STEP 52 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
a. IN TXT
ENTRY_END
STEP 53 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NXDOMAIN
SECTION QUESTION
a. IN TXT
SECTION ANSWER
ENTRY_END
STEP 54 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
a.rpz-ip. IN A
ENTRY_END
STEP 55 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NXDOMAIN
SECTION QUESTION
a.rpz-ip. IN A
SECTION ANSWER
ENTRY_END
STEP 56 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
c. IN TXT
ENTRY_END
STEP 57 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
c. IN TXT
SECTION ANSWER
c. IN TXT "hello from RPZ"
c. IN TXT "yet another hello from initial RPZ"
ENTRY_END
STEP 58 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
c.rpz-ip. IN A
ENTRY_END
STEP 59 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
c.rpz-ip. IN A
SECTION ANSWER
c.rpz-ip. IN A 10.66.0.6
c.rpz-ip. IN A 10.66.0.5
ENTRY_END
STEP 60 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d. IN TXT
ENTRY_END
STEP 61 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
d. IN TXT
SECTION ANSWER
d. IN TXT "hello from upstream"
ENTRY_END
STEP 62 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.rpz-ip. IN A
ENTRY_END
STEP 63 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
d.rpz-ip. IN A
SECTION ANSWER
d.rpz-ip. IN A 10.0.123.4
ENTRY_END
SCENARIO_END

View File

@ -64,6 +64,16 @@ $ORIGIN rpz6.example.com.
e TXT "should be override by cname"
TEMPFILE_END
rpz:
name: "rpz7.example.com."
rpz-action-override: drop
zonefile:
TEMPFILE_NAME rpz7.example.com
TEMPFILE_CONTENTS rpz7.example.com
$ORIGIN rpz7.example.com.
f TXT "should be override by drop policy"
TEMPFILE_END
stub-zone:
name: "d."
stub-addr: 10.20.30.40
@ -175,4 +185,13 @@ e. IN CNAME d.
d. IN TXT "answer from upstream ns"
ENTRY_END
; check drop override, would be localdata without override
STEP 60 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
f. IN TXT
ENTRY_END
; no answer is checked at exit of testbound.
SCENARIO_END

View File

@ -64,6 +64,16 @@ $ORIGIN rpz6.example.com.
32.6.113.0.203.rpz-ip A 192.0.2.6
TEMPFILE_END
rpz:
name: "rpz7.example.com."
rpz-action-override: drop
zonefile:
TEMPFILE_NAME rpz7.example.com
TEMPFILE_CONTENTS rpz7.example.com
$ORIGIN rpz7.example.com.
32.7.113.0.203.rpz-ip A 192.0.2.7
TEMPFILE_END
stub-zone:
name: "."
stub-addr: 10.20.30.40
@ -146,6 +156,16 @@ SECTION ANSWER
e. IN A 203.0.113.6
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
f. IN A
SECTION ANSWER
f. IN A 203.0.113.7
ENTRY_END
RANGE_END
STEP 1 QUERY
@ -232,4 +252,14 @@ e. IN CNAME ns.
ns. IN A 10.20.30.40
ENTRY_END
STEP 11 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
f. IN A
ENTRY_END
; no answer is checked at exit of testbound.
STEP 12 TIME_PASSES ELAPSE 10
SCENARIO_END