xref: /freebsd/contrib/unbound/services/rpz.c (revision 7a789145f88a6aceacc59029a0cafe7de7aeefea)
1 /*
2  * services/rpz.c - rpz service
3  *
4  * Copyright (c) 2019, NLnet Labs. All rights reserved.
5  *
6  * This software is open source.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * Neither the name of the NLNET LABS nor the names of its contributors may
20  * be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /**
37  * \file
38  *
39  * This file contains functions to enable RPZ service.
40  */
41 
42 #include "config.h"
43 #include "services/rpz.h"
44 #include "util/config_file.h"
45 #include "sldns/wire2str.h"
46 #include "sldns/str2wire.h"
47 #include "util/data/dname.h"
48 #include "util/net_help.h"
49 #include "util/log.h"
50 #include "util/data/dname.h"
51 #include "util/locks.h"
52 #include "util/regional.h"
53 #include "util/data/msgencode.h"
54 #include "services/cache/dns.h"
55 #include "iterator/iterator.h"
56 #include "iterator/iter_delegpt.h"
57 #include "daemon/worker.h"
58 
59 typedef struct resp_addr rpz_aclnode_type;
60 
61 struct matched_delegation_point {
62 	uint8_t* dname;
63 	size_t dname_len;
64 };
65 
66 /** string for RPZ action enum */
67 const char*
rpz_action_to_string(enum rpz_action a)68 rpz_action_to_string(enum rpz_action a)
69 {
70 	switch(a) {
71 	case RPZ_NXDOMAIN_ACTION: return "rpz-nxdomain";
72 	case RPZ_NODATA_ACTION: return "rpz-nodata";
73 	case RPZ_PASSTHRU_ACTION: return "rpz-passthru";
74 	case RPZ_DROP_ACTION: return "rpz-drop";
75 	case RPZ_TCP_ONLY_ACTION: return "rpz-tcp-only";
76 	case RPZ_INVALID_ACTION: return "rpz-invalid";
77 	case RPZ_LOCAL_DATA_ACTION: return "rpz-local-data";
78 	case RPZ_DISABLED_ACTION: return "rpz-disabled";
79 	case RPZ_CNAME_OVERRIDE_ACTION: return "rpz-cname-override";
80 	case RPZ_NO_OVERRIDE_ACTION: return "rpz-no-override";
81 	default: return "rpz-unknown-action";
82 	}
83 }
84 
85 /** RPZ action enum for config string */
86 static enum rpz_action
rpz_config_to_action(char * a)87 rpz_config_to_action(char* a)
88 {
89 	if(strcmp(a, "nxdomain") == 0) return RPZ_NXDOMAIN_ACTION;
90 	else if(strcmp(a, "nodata") == 0) return RPZ_NODATA_ACTION;
91 	else if(strcmp(a, "passthru") == 0) return RPZ_PASSTHRU_ACTION;
92 	else if(strcmp(a, "drop") == 0) return RPZ_DROP_ACTION;
93 	else if(strcmp(a, "tcp_only") == 0) return RPZ_TCP_ONLY_ACTION;
94 	else if(strcmp(a, "cname") == 0) return RPZ_CNAME_OVERRIDE_ACTION;
95 	else if(strcmp(a, "disabled") == 0) return RPZ_DISABLED_ACTION;
96 	else return RPZ_INVALID_ACTION;
97 }
98 
99 /** string for RPZ trigger enum */
100 static const char*
rpz_trigger_to_string(enum rpz_trigger r)101 rpz_trigger_to_string(enum rpz_trigger r)
102 {
103 	switch(r) {
104 	case RPZ_QNAME_TRIGGER: return "rpz-qname";
105 	case RPZ_CLIENT_IP_TRIGGER: return "rpz-client-ip";
106 	case RPZ_RESPONSE_IP_TRIGGER: return "rpz-response-ip";
107 	case RPZ_NSDNAME_TRIGGER: return "rpz-nsdname";
108 	case RPZ_NSIP_TRIGGER: return "rpz-nsip";
109 	case RPZ_INVALID_TRIGGER: return "rpz-invalid";
110 	default: return "rpz-unknown-trigger";
111 	}
112 }
113 
114 /**
115  * Get the label that is just before the root label.
116  * @param dname: dname to work on
117  * @param maxdnamelen: maximum length of the dname
118  * @return: pointer to TLD label, NULL if not found or invalid dname
119  */
120 static uint8_t*
get_tld_label(uint8_t * dname,size_t maxdnamelen)121 get_tld_label(uint8_t* dname, size_t maxdnamelen)
122 {
123 	uint8_t* prevlab = dname;
124 	size_t dnamelen = 0;
125 
126 	/* one byte needed for label length */
127 	if(dnamelen+1 > maxdnamelen)
128 		return NULL;
129 
130 	/* only root label */
131 	if(*dname == 0)
132 		return NULL;
133 
134 	while(*dname) {
135 		dnamelen += ((size_t)*dname)+1;
136 		if(dnamelen+1 > maxdnamelen)
137 			return NULL;
138 		dname = dname+((size_t)*dname)+1;
139 		if(*dname != 0)
140 			prevlab = dname;
141 	}
142 	return prevlab;
143 }
144 
145 /**
146  * The RR types that are to be ignored.
147  * DNSSEC RRs at the apex, and SOA and NS are ignored.
148  */
149 static int
rpz_type_ignored(uint16_t rr_type)150 rpz_type_ignored(uint16_t rr_type)
151 {
152 	switch(rr_type) {
153 		case LDNS_RR_TYPE_SOA:
154 		case LDNS_RR_TYPE_NS:
155 		case LDNS_RR_TYPE_DNAME:
156 		case LDNS_RR_TYPE_ZONEMD:
157 		/* all DNSSEC-related RRs must be ignored */
158 		case LDNS_RR_TYPE_DNSKEY:
159 		case LDNS_RR_TYPE_DS:
160 		case LDNS_RR_TYPE_RRSIG:
161 		case LDNS_RR_TYPE_NSEC:
162 		case LDNS_RR_TYPE_NSEC3:
163 		case LDNS_RR_TYPE_NSEC3PARAM:
164 			return 1;
165 		default:
166 			break;
167 	}
168 	return 0;
169 }
170 
171 /**
172  * Classify RPZ action for RR type/rdata
173  * @param rr_type: the RR type
174  * @param rdatawl: RDATA with 2 bytes length
175  * @param rdatalen: the length of rdatawl (including its 2 bytes length)
176  * @return: the RPZ action
177  */
178 static enum rpz_action
rpz_rr_to_action(uint16_t rr_type,uint8_t * rdatawl,size_t rdatalen)179 rpz_rr_to_action(uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
180 {
181 	char* endptr;
182 	uint8_t* rdata;
183 	int rdatalabs;
184 	uint8_t* tldlab = NULL;
185 
186 	switch(rr_type) {
187 		case LDNS_RR_TYPE_SOA:
188 		case LDNS_RR_TYPE_NS:
189 		case LDNS_RR_TYPE_DNAME:
190 		/* all DNSSEC-related RRs must be ignored */
191 		case LDNS_RR_TYPE_DNSKEY:
192 		case LDNS_RR_TYPE_DS:
193 		case LDNS_RR_TYPE_RRSIG:
194 		case LDNS_RR_TYPE_NSEC:
195 		case LDNS_RR_TYPE_NSEC3:
196 		case LDNS_RR_TYPE_NSEC3PARAM:
197 			return RPZ_INVALID_ACTION;
198 		case LDNS_RR_TYPE_CNAME:
199 			break;
200 		default:
201 			return RPZ_LOCAL_DATA_ACTION;
202 	}
203 
204 	/* use CNAME target to determine RPZ action */
205 	log_assert(rr_type == LDNS_RR_TYPE_CNAME);
206 	if(rdatalen < 3)
207 		return RPZ_INVALID_ACTION;
208 
209 	rdata = rdatawl + 2; /* 2 bytes of rdata length */
210 	if(dname_valid(rdata, rdatalen-2) != rdatalen-2)
211 		return RPZ_INVALID_ACTION;
212 
213 	rdatalabs = dname_count_labels(rdata);
214 	if(rdatalabs == 1)
215 		return RPZ_NXDOMAIN_ACTION;
216 	else if(rdatalabs == 2) {
217 		if(dname_subdomain_c(rdata, (uint8_t*)&"\001*\000"))
218 			return RPZ_NODATA_ACTION;
219 		else if(dname_subdomain_c(rdata,
220 			(uint8_t*)&"\014rpz-passthru\000"))
221 			return RPZ_PASSTHRU_ACTION;
222 		else if(dname_subdomain_c(rdata, (uint8_t*)&"\010rpz-drop\000"))
223 			return RPZ_DROP_ACTION;
224 		else if(dname_subdomain_c(rdata,
225 			(uint8_t*)&"\014rpz-tcp-only\000"))
226 			return RPZ_TCP_ONLY_ACTION;
227 	}
228 
229 	/* all other TLDs starting with "rpz-" are invalid */
230 	tldlab = get_tld_label(rdata, rdatalen-2);
231 	if(tldlab && dname_lab_startswith(tldlab, "rpz-", &endptr))
232 		return RPZ_INVALID_ACTION;
233 
234 	/* no special label found */
235 	return RPZ_LOCAL_DATA_ACTION;
236 }
237 
238 static enum localzone_type
rpz_action_to_localzone_type(enum rpz_action a)239 rpz_action_to_localzone_type(enum rpz_action a)
240 {
241 	switch(a) {
242 	case RPZ_NXDOMAIN_ACTION: return local_zone_always_nxdomain;
243 	case RPZ_NODATA_ACTION: return local_zone_always_nodata;
244 	case RPZ_DROP_ACTION: return local_zone_always_deny;
245 	case RPZ_PASSTHRU_ACTION: return local_zone_always_transparent;
246 	case RPZ_LOCAL_DATA_ACTION:
247 		ATTR_FALLTHROUGH
248 		/* fallthrough */
249 	case RPZ_CNAME_OVERRIDE_ACTION: return local_zone_redirect;
250 	case RPZ_TCP_ONLY_ACTION: return local_zone_truncate;
251 	case RPZ_INVALID_ACTION:
252 		ATTR_FALLTHROUGH
253 		/* fallthrough */
254 	default: return local_zone_invalid;
255 	}
256 }
257 
258 enum respip_action
rpz_action_to_respip_action(enum rpz_action a)259 rpz_action_to_respip_action(enum rpz_action a)
260 {
261 	switch(a) {
262 	case RPZ_NXDOMAIN_ACTION: return respip_always_nxdomain;
263 	case RPZ_NODATA_ACTION: return respip_always_nodata;
264 	case RPZ_DROP_ACTION: return respip_always_deny;
265 	case RPZ_PASSTHRU_ACTION: return respip_always_transparent;
266 	case RPZ_LOCAL_DATA_ACTION:
267 		ATTR_FALLTHROUGH
268 		/* fallthrough */
269 	case RPZ_CNAME_OVERRIDE_ACTION: return respip_redirect;
270 	case RPZ_TCP_ONLY_ACTION: return respip_truncate;
271 	case RPZ_INVALID_ACTION:
272 		ATTR_FALLTHROUGH
273 		/* fallthrough */
274 	default: return respip_invalid;
275 	}
276 }
277 
278 static enum rpz_action
localzone_type_to_rpz_action(enum localzone_type lzt)279 localzone_type_to_rpz_action(enum localzone_type lzt)
280 {
281 	switch(lzt) {
282 	case local_zone_always_nxdomain: return RPZ_NXDOMAIN_ACTION;
283 	case local_zone_always_nodata: return RPZ_NODATA_ACTION;
284 	case local_zone_always_deny: return RPZ_DROP_ACTION;
285 	case local_zone_always_transparent: return RPZ_PASSTHRU_ACTION;
286 	case local_zone_redirect: return RPZ_LOCAL_DATA_ACTION;
287 	case local_zone_truncate: return RPZ_TCP_ONLY_ACTION;
288 	case local_zone_invalid:
289 		ATTR_FALLTHROUGH
290 		/* fallthrough */
291 	default: return RPZ_INVALID_ACTION;
292 	}
293 }
294 
295 enum rpz_action
respip_action_to_rpz_action(enum respip_action a)296 respip_action_to_rpz_action(enum respip_action a)
297 {
298 	switch(a) {
299 	case respip_always_nxdomain: return RPZ_NXDOMAIN_ACTION;
300 	case respip_always_nodata: return RPZ_NODATA_ACTION;
301 	case respip_always_deny: return RPZ_DROP_ACTION;
302 	case respip_always_transparent: return RPZ_PASSTHRU_ACTION;
303 	case respip_redirect: return RPZ_LOCAL_DATA_ACTION;
304 	case respip_truncate: return RPZ_TCP_ONLY_ACTION;
305 	case respip_invalid:
306 		ATTR_FALLTHROUGH
307 		/* fallthrough */
308 	default: return RPZ_INVALID_ACTION;
309 	}
310 }
311 
312 /**
313  * Get RPZ trigger for dname
314  * @param dname: dname containing RPZ trigger
315  * @param dname_len: length of the dname
316  * @return: RPZ trigger enum
317  */
318 static enum rpz_trigger
rpz_dname_to_trigger(uint8_t * dname,size_t dname_len)319 rpz_dname_to_trigger(uint8_t* dname, size_t dname_len)
320 {
321 	uint8_t* tldlab;
322 	char* endptr;
323 
324 	if(dname_valid(dname, dname_len) != dname_len)
325 		return RPZ_INVALID_TRIGGER;
326 
327 	tldlab = get_tld_label(dname, dname_len);
328 	if(!tldlab || !dname_lab_startswith(tldlab, "rpz-", &endptr))
329 		return RPZ_QNAME_TRIGGER;
330 
331 	if(dname_subdomain_c(tldlab,
332 		(uint8_t*)&"\015rpz-client-ip\000"))
333 		return RPZ_CLIENT_IP_TRIGGER;
334 	else if(dname_subdomain_c(tldlab, (uint8_t*)&"\006rpz-ip\000"))
335 		return RPZ_RESPONSE_IP_TRIGGER;
336 	else if(dname_subdomain_c(tldlab, (uint8_t*)&"\013rpz-nsdname\000"))
337 		return RPZ_NSDNAME_TRIGGER;
338 	else if(dname_subdomain_c(tldlab, (uint8_t*)&"\010rpz-nsip\000"))
339 		return RPZ_NSIP_TRIGGER;
340 
341 	return RPZ_QNAME_TRIGGER;
342 }
343 
344 static inline struct clientip_synthesized_rrset*
rpz_clientip_synthesized_set_create(void)345 rpz_clientip_synthesized_set_create(void)
346 {
347 	struct clientip_synthesized_rrset* set = calloc(1, sizeof(*set));
348 	if(set == NULL) {
349 		return NULL;
350 	}
351 	set->region = regional_create();
352 	if(set->region == NULL) {
353 		free(set);
354 		return NULL;
355 	}
356 	addr_tree_init(&set->entries);
357 	lock_rw_init(&set->lock);
358 	return set;
359 }
360 
361 static void
rpz_clientip_synthesized_rr_delete(rbnode_type * n,void * ATTR_UNUSED (arg))362 rpz_clientip_synthesized_rr_delete(rbnode_type* n, void* ATTR_UNUSED(arg))
363 {
364 	struct clientip_synthesized_rr* r = (struct clientip_synthesized_rr*)n->key;
365 	lock_rw_destroy(&r->lock);
366 #ifdef THREADS_DISABLED
367 	(void)r;
368 #endif
369 }
370 
371 static inline void
rpz_clientip_synthesized_set_delete(struct clientip_synthesized_rrset * set)372 rpz_clientip_synthesized_set_delete(struct clientip_synthesized_rrset* set)
373 {
374 	if(set == NULL) {
375 		return;
376 	}
377 	lock_rw_destroy(&set->lock);
378 	traverse_postorder(&set->entries, rpz_clientip_synthesized_rr_delete, NULL);
379 	regional_destroy(set->region);
380 	free(set);
381 }
382 
383 void
rpz_delete(struct rpz * r)384 rpz_delete(struct rpz* r)
385 {
386 	if(!r)
387 		return;
388 	local_zones_delete(r->local_zones);
389 	local_zones_delete(r->nsdname_zones);
390 	respip_set_delete(r->respip_set);
391 	rpz_clientip_synthesized_set_delete(r->client_set);
392 	rpz_clientip_synthesized_set_delete(r->ns_set);
393 	regional_destroy(r->region);
394 	free(r->taglist);
395 	free(r->log_name);
396 	free(r);
397 }
398 
399 int
rpz_clear(struct rpz * r)400 rpz_clear(struct rpz* r)
401 {
402 	/* must hold write lock on auth_zone */
403 	local_zones_delete(r->local_zones);
404 	r->local_zones = NULL;
405 	local_zones_delete(r->nsdname_zones);
406 	r->nsdname_zones = NULL;
407 	respip_set_delete(r->respip_set);
408 	r->respip_set = NULL;
409 	rpz_clientip_synthesized_set_delete(r->client_set);
410 	r->client_set = NULL;
411 	rpz_clientip_synthesized_set_delete(r->ns_set);
412 	r->ns_set = NULL;
413 	if(!(r->local_zones = local_zones_create())){
414 		return 0;
415 	}
416 	r->nsdname_zones = local_zones_create();
417 	if(r->nsdname_zones == NULL) {
418 		return 0;
419 	}
420 	if(!(r->respip_set = respip_set_create())) {
421 		return 0;
422 	}
423 	if(!(r->client_set = rpz_clientip_synthesized_set_create())) {
424 		return 0;
425 	}
426 	if(!(r->ns_set = rpz_clientip_synthesized_set_create())) {
427 		return 0;
428 	}
429 	return 1;
430 }
431 
432 void
rpz_finish_config(struct rpz * r)433 rpz_finish_config(struct rpz* r)
434 {
435 	lock_rw_wrlock(&r->respip_set->lock);
436 	addr_tree_init_parents(&r->respip_set->ip_tree);
437 	lock_rw_unlock(&r->respip_set->lock);
438 
439 	lock_rw_wrlock(&r->client_set->lock);
440 	addr_tree_init_parents(&r->client_set->entries);
441 	lock_rw_unlock(&r->client_set->lock);
442 
443 	lock_rw_wrlock(&r->ns_set->lock);
444 	addr_tree_init_parents(&r->ns_set->entries);
445 	lock_rw_unlock(&r->ns_set->lock);
446 }
447 
448 /** new rrset containing CNAME override, does not yet contain a dname */
449 static struct ub_packed_rrset_key*
new_cname_override(struct regional * region,uint8_t * ct,size_t ctlen)450 new_cname_override(struct regional* region, uint8_t* ct, size_t ctlen)
451 {
452 	struct ub_packed_rrset_key* rrset;
453 	struct packed_rrset_data* pd;
454 	uint16_t rdlength = htons(ctlen);
455 	rrset = (struct ub_packed_rrset_key*)regional_alloc_zero(region,
456 		sizeof(*rrset));
457 	if(!rrset) {
458 		log_err("out of memory");
459 		return NULL;
460 	}
461 	rrset->entry.key = rrset;
462 	pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd));
463 	if(!pd) {
464 		log_err("out of memory");
465 		return NULL;
466 	}
467 	pd->trust = rrset_trust_prim_noglue;
468 	pd->security = sec_status_insecure;
469 
470 	pd->count = 1;
471 	pd->rr_len = regional_alloc_zero(region, sizeof(*pd->rr_len));
472 	pd->rr_ttl = regional_alloc_zero(region, sizeof(*pd->rr_ttl));
473 	pd->rr_data = regional_alloc_zero(region, sizeof(*pd->rr_data));
474 	if(!pd->rr_len || !pd->rr_ttl || !pd->rr_data) {
475 		log_err("out of memory");
476 		return NULL;
477 	}
478 	pd->rr_len[0] = ctlen+2;
479 	pd->rr_ttl[0] = 3600;
480 	pd->rr_data[0] = regional_alloc_zero(region, 2 /* rdlength */ + ctlen);
481 	if(!pd->rr_data[0]) {
482 		log_err("out of memory");
483 		return NULL;
484 	}
485 	memmove(pd->rr_data[0], &rdlength, 2);
486 	memmove(pd->rr_data[0]+2, ct, ctlen);
487 
488 	rrset->entry.data = pd;
489 	rrset->rk.type = htons(LDNS_RR_TYPE_CNAME);
490 	rrset->rk.rrset_class = htons(LDNS_RR_CLASS_IN);
491 	return rrset;
492 }
493 
494 /** delete the cname override */
495 static void
delete_cname_override(struct rpz * r)496 delete_cname_override(struct rpz* r)
497 {
498 	if(r->cname_override) {
499 		/* The cname override is what is allocated in the region. */
500 		regional_free_all(r->region);
501 		r->cname_override = NULL;
502 	}
503 }
504 
505 /** Apply rpz config elements to the rpz structure, false on failure. */
506 static int
rpz_apply_cfg_elements(struct rpz * r,struct config_auth * p)507 rpz_apply_cfg_elements(struct rpz* r, struct config_auth* p)
508 {
509 	if(p->rpz_taglist && p->rpz_taglistlen) {
510 		r->taglistlen = p->rpz_taglistlen;
511 		r->taglist = memdup(p->rpz_taglist, r->taglistlen);
512 		if(!r->taglist) {
513 			log_err("malloc failure on RPZ taglist alloc");
514 			return 0;
515 		}
516 	}
517 
518 	if(p->rpz_action_override) {
519 		r->action_override = rpz_config_to_action(p->rpz_action_override);
520 	}
521 	else
522 		r->action_override = RPZ_NO_OVERRIDE_ACTION;
523 
524 	if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
525 		uint8_t nm[LDNS_MAX_DOMAINLEN+1];
526 		size_t nmlen = sizeof(nm);
527 
528 		if(!p->rpz_cname) {
529 			log_err("rpz: override with cname action found, but no "
530 				"rpz-cname-override configured");
531 			return 0;
532 		}
533 
534 		if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
535 			log_err("rpz: cannot parse cname override: %s",
536 				p->rpz_cname);
537 			return 0;
538 		}
539 		r->cname_override = new_cname_override(r->region, nm, nmlen);
540 		if(!r->cname_override) {
541 			return 0;
542 		}
543 	}
544 	r->log = p->rpz_log;
545 	r->signal_nxdomain_ra = p->rpz_signal_nxdomain_ra;
546 	if(p->rpz_log_name) {
547 		if(!(r->log_name = strdup(p->rpz_log_name))) {
548 			log_err("malloc failure on RPZ log_name strdup");
549 			return 0;
550 		}
551 	}
552 	return 1;
553 }
554 
555 struct rpz*
rpz_create(struct config_auth * p)556 rpz_create(struct config_auth* p)
557 {
558 	struct rpz* r = calloc(1, sizeof(*r));
559 	if(!r)
560 		goto err;
561 
562 	r->region = regional_create_custom(sizeof(struct regional));
563 	if(!r->region) {
564 		goto err;
565 	}
566 
567 	if(!(r->local_zones = local_zones_create())){
568 		goto err;
569 	}
570 
571 	r->nsdname_zones = local_zones_create();
572 	if(r->local_zones == NULL){
573 		goto err;
574 	}
575 
576 	if(!(r->respip_set = respip_set_create())) {
577 		goto err;
578 	}
579 
580 	r->client_set = rpz_clientip_synthesized_set_create();
581 	if(r->client_set == NULL) {
582 		goto err;
583 	}
584 
585 	r->ns_set = rpz_clientip_synthesized_set_create();
586 	if(r->ns_set == NULL) {
587 		goto err;
588 	}
589 
590 	if(!rpz_apply_cfg_elements(r, p))
591 		goto err;
592 	return r;
593 err:
594 	if(r) {
595 		if(r->local_zones)
596 			local_zones_delete(r->local_zones);
597 		if(r->nsdname_zones)
598 			local_zones_delete(r->nsdname_zones);
599 		if(r->respip_set)
600 			respip_set_delete(r->respip_set);
601 		if(r->client_set != NULL)
602 			rpz_clientip_synthesized_set_delete(r->client_set);
603 		if(r->ns_set != NULL)
604 			rpz_clientip_synthesized_set_delete(r->ns_set);
605 		if(r->taglist)
606 			free(r->taglist);
607 		if(r->region)
608 			regional_destroy(r->region);
609 		free(r);
610 	}
611 	return NULL;
612 }
613 
614 int
rpz_config(struct rpz * r,struct config_auth * p)615 rpz_config(struct rpz* r, struct config_auth* p)
616 {
617 	/* If the zonefile changes, it is read later, after which
618 	 * rpz_clear and rpz_finish_config is called. */
619 
620 	/* free taglist, if any */
621 	if(r->taglist) {
622 		free(r->taglist);
623 		r->taglist = NULL;
624 		r->taglistlen = 0;
625 	}
626 
627 	/* free logname, if any */
628 	if(r->log_name) {
629 		free(r->log_name);
630 		r->log_name = NULL;
631 	}
632 
633 	delete_cname_override(r);
634 
635 	if(!rpz_apply_cfg_elements(r, p))
636 		return 0;
637 	return 1;
638 }
639 
640 /**
641  * Remove RPZ zone name from dname
642  * Copy dname to newdname, without the originlen number of trailing bytes
643  */
644 static size_t
strip_dname_origin(uint8_t * dname,size_t dnamelen,size_t originlen,uint8_t * newdname,size_t maxnewdnamelen)645 strip_dname_origin(uint8_t* dname, size_t dnamelen, size_t originlen,
646 	uint8_t* newdname, size_t maxnewdnamelen)
647 {
648 	size_t newdnamelen;
649 	if(dnamelen < originlen)
650 		return 0;
651 	newdnamelen = dnamelen - originlen;
652 	if(newdnamelen+1 > maxnewdnamelen)
653 		return 0;
654 	memmove(newdname, dname, newdnamelen);
655 	newdname[newdnamelen] = 0;
656 	return newdnamelen + 1;	/* + 1 for root label */
657 }
658 
659 static void
rpz_insert_local_zones_trigger(struct local_zones * lz,uint8_t * dname,size_t dnamelen,enum rpz_action a,uint16_t rrtype,uint16_t rrclass,uint32_t ttl,uint8_t * rdata,size_t rdata_len,uint8_t * rr,size_t rr_len)660 rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
661 	size_t dnamelen, enum rpz_action a, uint16_t rrtype, uint16_t rrclass,
662 	uint32_t ttl, uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
663 {
664 	struct local_zone* z;
665 	enum localzone_type tp = local_zone_always_transparent;
666 	int dnamelabs = dname_count_labels(dname);
667 	int newzone = 0;
668 
669 	if(a == RPZ_INVALID_ACTION) {
670 		char str[LDNS_MAX_DOMAINLEN];
671 		if(rrtype == LDNS_RR_TYPE_SOA || rrtype == LDNS_RR_TYPE_NS ||
672 			rrtype == LDNS_RR_TYPE_DNAME ||
673 			rrtype == LDNS_RR_TYPE_DNSKEY ||
674 			rrtype == LDNS_RR_TYPE_RRSIG ||
675 			rrtype == LDNS_RR_TYPE_NSEC ||
676 			rrtype == LDNS_RR_TYPE_NSEC3PARAM ||
677 			rrtype == LDNS_RR_TYPE_NSEC3 ||
678 			rrtype == LDNS_RR_TYPE_DS) {
679 			free(dname);
680 			return; /* no need to log these types as unsupported */
681 		}
682 		dname_str(dname, str);
683 		verbose(VERB_ALGO, "rpz: qname trigger, %s skipping unsupported action: %s",
684 			str, rpz_action_to_string(a));
685 		free(dname);
686 		return;
687 	}
688 
689 	lock_rw_wrlock(&lz->lock);
690 	/* exact match */
691 	z = local_zones_find(lz, dname, dnamelen, dnamelabs, LDNS_RR_CLASS_IN);
692 	if(z != NULL && a != RPZ_LOCAL_DATA_ACTION) {
693 		char* rrstr = sldns_wire2str_rr(rr, rr_len);
694 		if(rrstr == NULL) {
695 			log_err("malloc error while inserting rpz nsdname trigger");
696 			free(dname);
697 			lock_rw_unlock(&lz->lock);
698 			return;
699 		}
700 		if(rrstr[0])
701 			rrstr[strlen(rrstr)-1]=0; /* remove newline */
702 		verbose(VERB_ALGO, "rpz: skipping duplicate record: '%s'", rrstr);
703 		free(rrstr);
704 		free(dname);
705 		lock_rw_unlock(&lz->lock);
706 		return;
707 	}
708 	if(z == NULL) {
709 		tp = rpz_action_to_localzone_type(a);
710 		z = local_zones_add_zone(lz, dname, dnamelen,
711 					 dnamelabs, rrclass, tp);
712 		if(z == NULL) {
713 			log_warn("rpz: create failed");
714 			lock_rw_unlock(&lz->lock);
715 			/* dname will be free'd in failed local_zone_create() */
716 			return;
717 		}
718 		newzone = 1;
719 	}
720 	if(a == RPZ_LOCAL_DATA_ACTION) {
721 		char* rrstr = sldns_wire2str_rr(rr, rr_len);
722 		if(rrstr == NULL) {
723 			log_err("malloc error while inserting rpz nsdname trigger");
724 			if(!newzone)
725 				free(dname);
726 			lock_rw_unlock(&lz->lock);
727 			return;
728 		}
729 		lock_rw_wrlock(&z->lock);
730 		if(!local_zone_enter_rr(z, dname, dnamelen, dnamelabs, rrtype,
731 				    rrclass, ttl, rdata, rdata_len, rrstr)) {
732 			log_err("rpz: could not enter local-data: %s", rrstr);
733 			if(!newzone)
734 				free(dname);
735 			lock_rw_unlock(&z->lock);
736 			lock_rw_unlock(&lz->lock);
737 			free(rrstr);
738 			return;
739 		}
740 		lock_rw_unlock(&z->lock);
741 		free(rrstr);
742 	}
743 	if(!newzone) {
744 		free(dname);
745 	}
746 	lock_rw_unlock(&lz->lock);
747 }
748 
749 static void
rpz_log_dname(char const * msg,uint8_t * dname,size_t dname_len)750 rpz_log_dname(char const* msg, uint8_t* dname, size_t dname_len)
751 {
752 	char buf[LDNS_MAX_DOMAINLEN];
753 	(void)dname_len;
754 	dname_str(dname, buf);
755 	verbose(VERB_ALGO, "rpz: %s: <%s>", msg, buf);
756 }
757 
758 static void
rpz_insert_qname_trigger(struct rpz * r,uint8_t * dname,size_t dnamelen,enum rpz_action a,uint16_t rrtype,uint16_t rrclass,uint32_t ttl,uint8_t * rdata,size_t rdata_len,uint8_t * rr,size_t rr_len)759 rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
760 	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
761 	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
762 {
763 	if(a == RPZ_INVALID_ACTION) {
764 		verbose(VERB_ALGO, "rpz: skipping invalid action");
765 		free(dname);
766 		return;
767 	}
768 
769 	rpz_insert_local_zones_trigger(r->local_zones, dname, dnamelen, a, rrtype,
770 				       rrclass, ttl, rdata, rdata_len, rr, rr_len);
771 }
772 
773 static int
rpz_strip_nsdname_suffix(uint8_t * dname,size_t maxdnamelen,uint8_t ** stripdname,size_t * stripdnamelen)774 rpz_strip_nsdname_suffix(uint8_t* dname, size_t maxdnamelen,
775 	uint8_t** stripdname, size_t* stripdnamelen)
776 {
777 	uint8_t* tldstart = get_tld_label(dname, maxdnamelen);
778 	uint8_t swap;
779 	if(tldstart == NULL) {
780 		if(dname == NULL) {
781 			*stripdname = NULL;
782 			*stripdnamelen = 0;
783 			return 0;
784 		}
785 		*stripdname = memdup(dname, maxdnamelen);
786 		if(!*stripdname) {
787 			*stripdnamelen = 0;
788 			log_err("malloc failure for rpz strip suffix");
789 			return 0;
790 		}
791 		*stripdnamelen = maxdnamelen;
792 		return 1;
793 	}
794 	/* shorten the domain name briefly,
795 	 * then we allocate a new name with the correct length */
796 	swap = *tldstart;
797 	*tldstart = 0;
798 	(void)dname_count_size_labels(dname, stripdnamelen);
799 	*stripdname = memdup(dname, *stripdnamelen);
800 	*tldstart = swap;
801 	if(!*stripdname) {
802 		*stripdnamelen = 0;
803 		log_err("malloc failure for rpz strip suffix");
804 		return 0;
805 	}
806 	return 1;
807 }
808 
809 static void
rpz_insert_nsdname_trigger(struct rpz * r,uint8_t * dname,size_t dnamelen,enum rpz_action a,uint16_t rrtype,uint16_t rrclass,uint32_t ttl,uint8_t * rdata,size_t rdata_len,uint8_t * rr,size_t rr_len)810 rpz_insert_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
811 	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
812 	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
813 {
814 	uint8_t* dname_stripped = NULL;
815 	size_t dnamelen_stripped = 0;
816 
817 	if(!rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
818 		&dnamelen_stripped))
819 		return;
820 	if(a == RPZ_INVALID_ACTION) {
821 		verbose(VERB_ALGO, "rpz: skipping invalid action");
822 		free(dname_stripped);
823 		return;
824 	}
825 
826 	/* dname_stripped is consumed or freed by the insert routine */
827 	rpz_insert_local_zones_trigger(r->nsdname_zones, dname_stripped,
828 		dnamelen_stripped, a, rrtype, rrclass, ttl, rdata, rdata_len,
829 		rr, rr_len);
830 }
831 
832 static int
rpz_insert_ipaddr_based_trigger(struct respip_set * set,struct sockaddr_storage * addr,socklen_t addrlen,int net,enum rpz_action a,uint16_t rrtype,uint16_t rrclass,uint32_t ttl,uint8_t * rdata,size_t rdata_len,uint8_t * rr,size_t rr_len)833 rpz_insert_ipaddr_based_trigger(struct respip_set* set, struct sockaddr_storage* addr,
834 	socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype,
835 	uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len,
836 	uint8_t* rr, size_t rr_len)
837 {
838 	struct resp_addr* node;
839 	char* rrstr;
840 	enum respip_action respa = rpz_action_to_respip_action(a);
841 
842 	lock_rw_wrlock(&set->lock);
843 	rrstr = sldns_wire2str_rr(rr, rr_len);
844 	if(rrstr == NULL) {
845 		log_err("malloc error while inserting rpz ipaddr based trigger");
846 		lock_rw_unlock(&set->lock);
847 		return 0;
848 	}
849 
850 	node = respip_sockaddr_find_or_create(set, addr, addrlen, net, 1, rrstr);
851 	if(node == NULL) {
852 		lock_rw_unlock(&set->lock);
853 		free(rrstr);
854 		return 0;
855 	}
856 
857 	lock_rw_wrlock(&node->lock);
858 	lock_rw_unlock(&set->lock);
859 
860 	node->action = respa;
861 
862 	if(a == RPZ_LOCAL_DATA_ACTION) {
863 		respip_enter_rr(set->region, node, rrtype,
864 				rrclass, ttl, rdata, rdata_len, rrstr, "");
865 	}
866 
867 	lock_rw_unlock(&node->lock);
868 	free(rrstr);
869 	return 1;
870 }
871 
872 static inline struct clientip_synthesized_rr*
rpz_clientip_ensure_entry(struct clientip_synthesized_rrset * set,struct sockaddr_storage * addr,socklen_t addrlen,int net)873 rpz_clientip_ensure_entry(struct clientip_synthesized_rrset* set,
874 	struct sockaddr_storage* addr, socklen_t addrlen, int net)
875 {
876 	int insert_ok;
877 	struct clientip_synthesized_rr* node =
878 		(struct clientip_synthesized_rr*)addr_tree_find(&set->entries,
879 								addr, addrlen, net);
880 
881 	if(node != NULL) { return node; }
882 
883 	/* node does not yet exist => allocate one */
884 	node = regional_alloc_zero(set->region, sizeof(*node));
885 	if(node == NULL) {
886 		log_err("out of memory");
887 		return NULL;
888 	}
889 
890 	lock_rw_init(&node->lock);
891 	node->action = RPZ_INVALID_ACTION;
892 	insert_ok = addr_tree_insert(&set->entries, &node->node,
893 				     addr, addrlen, net);
894 	if (!insert_ok) {
895 		log_warn("rpz: unexpected: unable to insert clientip address node");
896 		/* we can not free the just allocated node.
897 		 * theoretically a memleak */
898 		return NULL;
899 	}
900 
901 	return node;
902 }
903 
904 static void
rpz_report_rrset_error(const char * msg,uint8_t * rr,size_t rr_len)905 rpz_report_rrset_error(const char* msg, uint8_t* rr, size_t rr_len) {
906 	char* rrstr = sldns_wire2str_rr(rr, rr_len);
907 	if(rrstr == NULL) {
908 		log_err("malloc error while inserting rpz clientip based record");
909 		return;
910 	}
911 	log_err("rpz: unexpected: unable to insert %s: %s", msg, rrstr);
912 	free(rrstr);
913 }
914 
915 /* from localzone.c; difference is we don't have a dname */
916 static struct local_rrset*
rpz_clientip_new_rrset(struct regional * region,uint16_t rrtype,uint16_t rrclass)917 rpz_clientip_new_rrset(struct regional* region, uint16_t rrtype,
918 	uint16_t rrclass)
919 {
920 	struct packed_rrset_data* pd;
921 	struct local_rrset* rrset = (struct local_rrset*)
922 		regional_alloc_zero(region, sizeof(*rrset));
923 	if(rrset == NULL) {
924 		log_err("out of memory");
925 		return NULL;
926 	}
927 	rrset->rrset = (struct ub_packed_rrset_key*)
928 		regional_alloc_zero(region, sizeof(*rrset->rrset));
929 	if(rrset->rrset == NULL) {
930 		log_err("out of memory");
931 		return NULL;
932 	}
933 	rrset->rrset->entry.key = rrset->rrset;
934 	pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd));
935 	if(pd == NULL) {
936 		log_err("out of memory");
937 		return NULL;
938 	}
939 	pd->trust = rrset_trust_prim_noglue;
940 	pd->security = sec_status_insecure;
941 	rrset->rrset->entry.data = pd;
942 	rrset->rrset->rk.type = htons(rrtype);
943 	rrset->rrset->rk.rrset_class = htons(rrclass);
944 	rrset->rrset->rk.dname = regional_alloc_zero(region, 1);
945 	if(rrset->rrset->rk.dname == NULL) {
946 		log_err("out of memory");
947 		return NULL;
948 	}
949 	rrset->rrset->rk.dname_len = 1;
950 	return rrset;
951 }
952 
953 static int
rpz_clientip_enter_rr(struct regional * region,struct clientip_synthesized_rr * raddr,uint16_t rrtype,uint16_t rrclass,time_t ttl,uint8_t * rdata,size_t rdata_len)954 rpz_clientip_enter_rr(struct regional* region, struct clientip_synthesized_rr* raddr,
955 	uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata,
956 	size_t rdata_len)
957 {
958 	struct local_rrset* rrset;
959 	if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data != NULL) {
960 		log_err("CNAME response-ip data can not co-exist with other "
961 			"client-ip data");
962 		return 0;
963 	}
964 
965 	rrset = rpz_clientip_new_rrset(region, rrtype, rrclass);
966 	if(rrset == NULL) {
967 		return 0;
968 	}
969 
970 	if(!rrset_insert_rr(region, rrset->rrset->entry.data, rdata, rdata_len, ttl, ""))
971 		return 0;
972 
973 	/* Link in now that the allocations have succeeded. */
974 	rrset->next = raddr->data;
975 	raddr->data = rrset;
976 	return 1;
977 }
978 
979 static int
rpz_clientip_insert_trigger_rr(struct clientip_synthesized_rrset * set,struct sockaddr_storage * addr,socklen_t addrlen,int net,enum rpz_action a,uint16_t rrtype,uint16_t rrclass,uint32_t ttl,uint8_t * rdata,size_t rdata_len,uint8_t * rr,size_t rr_len)980 rpz_clientip_insert_trigger_rr(struct clientip_synthesized_rrset* set, struct sockaddr_storage* addr,
981 	socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype,
982 	uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len,
983 	uint8_t* rr, size_t rr_len)
984 {
985 	struct clientip_synthesized_rr* node;
986 
987 	lock_rw_wrlock(&set->lock);
988 
989 	node = rpz_clientip_ensure_entry(set, addr, addrlen, net);
990 	if(node == NULL) {
991 		lock_rw_unlock(&set->lock);
992 		rpz_report_rrset_error("client ip address", rr, rr_len);
993 		return 0;
994 	}
995 
996 	lock_rw_wrlock(&node->lock);
997 	lock_rw_unlock(&set->lock);
998 
999 	if(a == RPZ_LOCAL_DATA_ACTION) {
1000 		if(!rpz_clientip_enter_rr(set->region, node, rrtype,
1001 			rrclass, ttl, rdata, rdata_len)) {
1002 			verbose(VERB_ALGO, "rpz: unable to insert clientip rr");
1003 			lock_rw_unlock(&node->lock);
1004 			return 0;
1005 		}
1006 
1007 	}
1008 	node->action = a;
1009 
1010 	lock_rw_unlock(&node->lock);
1011 
1012 	return 1;
1013 }
1014 
1015 static int
rpz_insert_clientip_trigger(struct rpz * r,uint8_t * dname,size_t dnamelen,enum rpz_action a,uint16_t rrtype,uint16_t rrclass,uint32_t ttl,uint8_t * rdata,size_t rdata_len,uint8_t * rr,size_t rr_len)1016 rpz_insert_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1017 	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
1018 	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
1019 {
1020 	struct sockaddr_storage addr;
1021 	socklen_t addrlen;
1022 	int net, af;
1023 
1024 	if(a == RPZ_INVALID_ACTION) {
1025 		return 0;
1026 	}
1027 
1028 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
1029 		verbose(VERB_ALGO, "rpz: unable to parse client ip");
1030 		return 0;
1031 	}
1032 
1033 	return rpz_clientip_insert_trigger_rr(r->client_set, &addr, addrlen, net,
1034 			a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
1035 }
1036 
1037 static int
rpz_insert_nsip_trigger(struct rpz * r,uint8_t * dname,size_t dnamelen,enum rpz_action a,uint16_t rrtype,uint16_t rrclass,uint32_t ttl,uint8_t * rdata,size_t rdata_len,uint8_t * rr,size_t rr_len)1038 rpz_insert_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1039 	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
1040 	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
1041 {
1042 	struct sockaddr_storage addr;
1043 	socklen_t addrlen;
1044 	int net, af;
1045 
1046 	if(a == RPZ_INVALID_ACTION) {
1047 		return 0;
1048 	}
1049 
1050 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
1051 		verbose(VERB_ALGO, "rpz: unable to parse ns ip");
1052 		return 0;
1053 	}
1054 
1055 	return rpz_clientip_insert_trigger_rr(r->ns_set, &addr, addrlen, net,
1056 			a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
1057 }
1058 
1059 /** Insert RR into RPZ's respip_set */
1060 static int
rpz_insert_response_ip_trigger(struct rpz * r,uint8_t * dname,size_t dnamelen,enum rpz_action a,uint16_t rrtype,uint16_t rrclass,uint32_t ttl,uint8_t * rdata,size_t rdata_len,uint8_t * rr,size_t rr_len)1061 rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1062 	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
1063 	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
1064 {
1065 	struct sockaddr_storage addr;
1066 	socklen_t addrlen;
1067 	int net, af;
1068 
1069 	if(a == RPZ_INVALID_ACTION) {
1070 		return 0;
1071 	}
1072 
1073 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
1074 		verbose(VERB_ALGO, "rpz: unable to parse response ip");
1075 		return 0;
1076 	}
1077 
1078 	if(a == RPZ_INVALID_ACTION ||
1079 		rpz_action_to_respip_action(a) == respip_invalid) {
1080 		char str[LDNS_MAX_DOMAINLEN];
1081 		dname_str(dname, str);
1082 		verbose(VERB_ALGO, "rpz: respip trigger, %s skipping unsupported action: %s",
1083 			str, rpz_action_to_string(a));
1084 		return 0;
1085 	}
1086 
1087 	return rpz_insert_ipaddr_based_trigger(r->respip_set, &addr, addrlen, net,
1088 			a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
1089 }
1090 
1091 int
rpz_insert_rr(struct rpz * r,uint8_t * azname,size_t aznamelen,uint8_t * dname,size_t dnamelen,uint16_t rr_type,uint16_t rr_class,uint32_t rr_ttl,uint8_t * rdatawl,size_t rdatalen,uint8_t * rr,size_t rr_len)1092 rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
1093 	size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
1094 	uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len)
1095 {
1096 	size_t policydnamelen;
1097 	/* name is free'd in local_zone delete */
1098 	enum rpz_trigger t;
1099 	enum rpz_action a;
1100 	uint8_t* policydname;
1101 
1102 	if(rpz_type_ignored(rr_type)) {
1103 		/* this rpz action is not valid, eg. this is the SOA or NS RR */
1104 		return 1;
1105 	}
1106 	if(!dname_subdomain_c(dname, azname)) {
1107 		char* dname_str = sldns_wire2str_dname(dname, dnamelen);
1108 		char* azname_str = sldns_wire2str_dname(azname, aznamelen);
1109 		if(dname_str && azname_str) {
1110 			log_err("rpz: name of record (%s) to insert into RPZ is not a "
1111 				"subdomain of the configured name of the RPZ zone (%s)",
1112 				dname_str, azname_str);
1113 		} else {
1114 			log_err("rpz: name of record to insert into RPZ is not a "
1115 				"subdomain of the configured name of the RPZ zone");
1116 		}
1117 		free(dname_str);
1118 		free(azname_str);
1119 		return 0;
1120 	}
1121 
1122 	log_assert(dnamelen >= aznamelen);
1123 	if(!(policydname = calloc(1, (dnamelen-aznamelen)+1))) {
1124 		log_err("malloc error while inserting RPZ RR");
1125 		return 0;
1126 	}
1127 
1128 	a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
1129 	if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
1130 		policydname, (dnamelen-aznamelen)+1))) {
1131 		free(policydname);
1132 		return 0;
1133 	}
1134 	t = rpz_dname_to_trigger(policydname, policydnamelen);
1135 	if(t == RPZ_INVALID_TRIGGER) {
1136 		free(policydname);
1137 		verbose(VERB_ALGO, "rpz: skipping invalid trigger");
1138 		return 1;
1139 	}
1140 	if(t == RPZ_QNAME_TRIGGER) {
1141 		/* policydname will be consumed, no free */
1142 		rpz_insert_qname_trigger(r, policydname, policydnamelen,
1143 			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1144 			rr_len);
1145 	} else if(t == RPZ_RESPONSE_IP_TRIGGER) {
1146 		rpz_insert_response_ip_trigger(r, policydname, policydnamelen,
1147 			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1148 			rr_len);
1149 		free(policydname);
1150 	} else if(t == RPZ_CLIENT_IP_TRIGGER) {
1151 		rpz_insert_clientip_trigger(r, policydname, policydnamelen,
1152 			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1153 			rr_len);
1154 		free(policydname);
1155 	} else if(t == RPZ_NSIP_TRIGGER) {
1156 		rpz_insert_nsip_trigger(r, policydname, policydnamelen,
1157 			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1158 			rr_len);
1159 		free(policydname);
1160 	} else if(t == RPZ_NSDNAME_TRIGGER) {
1161 		rpz_insert_nsdname_trigger(r, policydname, policydnamelen,
1162 			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1163 			rr_len);
1164 		free(policydname);
1165 	} else {
1166 		free(policydname);
1167 		verbose(VERB_ALGO, "rpz: skipping unsupported trigger: %s",
1168 			rpz_trigger_to_string(t));
1169 	}
1170 	return 1;
1171 }
1172 
1173 /**
1174  * Find RPZ local-zone by qname.
1175  * @param zones: local-zone tree
1176  * @param qname: qname
1177  * @param qname_len: length of qname
1178  * @param qclass: qclass
1179  * @param only_exact: if 1 only exact (non wildcard) matches are returned
1180  * @param wr: get write lock for local-zone if 1, read lock if 0
1181  * @param zones_keep_lock: if set do not release the r->local_zones lock, this
1182  * 	  makes the caller of this function responsible for releasing the lock.
1183  * @return: NULL or local-zone holding rd or wr lock
1184  */
1185 static struct local_zone*
rpz_find_zone(struct local_zones * zones,uint8_t * qname,size_t qname_len,uint16_t qclass,int only_exact,int wr,int zones_keep_lock)1186 rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint16_t qclass,
1187 	int only_exact, int wr, int zones_keep_lock)
1188 {
1189 	uint8_t* ce;
1190 	size_t ce_len;
1191 	int ce_labs;
1192 	uint8_t wc[LDNS_MAX_DOMAINLEN+1];
1193 	int exact;
1194 	struct local_zone* z = NULL;
1195 
1196 	if(wr) {
1197 		lock_rw_wrlock(&zones->lock);
1198 	} else {
1199 		lock_rw_rdlock(&zones->lock);
1200 	}
1201 	z = local_zones_find_le(zones, qname, qname_len,
1202 		dname_count_labels(qname),
1203 		LDNS_RR_CLASS_IN, &exact);
1204 	if(!z || (only_exact && !exact)) {
1205 		if(!zones_keep_lock) {
1206 			lock_rw_unlock(&zones->lock);
1207 		}
1208 		return NULL;
1209 	}
1210 	if(wr) {
1211 		lock_rw_wrlock(&z->lock);
1212 	} else {
1213 		lock_rw_rdlock(&z->lock);
1214 	}
1215 	if(!zones_keep_lock) {
1216 		lock_rw_unlock(&zones->lock);
1217 	}
1218 
1219 	if(exact)
1220 		return z;
1221 
1222 	/* No exact match found, lookup wildcard. closest encloser must
1223 	 * be the shared parent between the qname and the best local
1224 	 * zone match, append '*' to that and do another lookup. */
1225 
1226 	ce = dname_get_shared_topdomain(z->name, qname);
1227 	if(!ce /* should not happen */) {
1228 		lock_rw_unlock(&z->lock);
1229 		if(zones_keep_lock) {
1230 			lock_rw_unlock(&zones->lock);
1231 		}
1232 		return NULL;
1233 	}
1234 	ce_labs = dname_count_size_labels(ce, &ce_len);
1235 	if(ce_len+2 > sizeof(wc)) {
1236 		lock_rw_unlock(&z->lock);
1237 		if(zones_keep_lock) {
1238 			lock_rw_unlock(&zones->lock);
1239 		}
1240 		return NULL;
1241 	}
1242 	wc[0] = 1; /* length of wildcard label */
1243 	wc[1] = (uint8_t)'*'; /* wildcard label */
1244 	memmove(wc+2, ce, ce_len);
1245 	lock_rw_unlock(&z->lock);
1246 
1247 	if(!zones_keep_lock) {
1248 		if(wr) {
1249 			lock_rw_wrlock(&zones->lock);
1250 		} else {
1251 			lock_rw_rdlock(&zones->lock);
1252 		}
1253 	}
1254 	z = local_zones_find_le(zones, wc,
1255 		ce_len+2, ce_labs+1, qclass, &exact);
1256 	if(!z || !exact) {
1257 		lock_rw_unlock(&zones->lock);
1258 		return NULL;
1259 	}
1260 	if(wr) {
1261 		lock_rw_wrlock(&z->lock);
1262 	} else {
1263 		lock_rw_rdlock(&z->lock);
1264 	}
1265 	if(!zones_keep_lock) {
1266 		lock_rw_unlock(&zones->lock);
1267 	}
1268 	return z;
1269 }
1270 
1271 /** Find entry for RR type in the list of rrsets for the clientip. */
1272 static struct local_rrset*
rpz_find_synthesized_rrset(uint16_t qtype,struct clientip_synthesized_rr * data,int alias_ok)1273 rpz_find_synthesized_rrset(uint16_t qtype,
1274 	struct clientip_synthesized_rr* data, int alias_ok)
1275 {
1276 	struct local_rrset* cursor = data->data, *cname = NULL;
1277 	while( cursor != NULL) {
1278 		struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
1279 		if(htons(qtype) == packed_rrset->type) {
1280 			return cursor;
1281 		}
1282 		if(ntohs(packed_rrset->type) == LDNS_RR_TYPE_CNAME && alias_ok)
1283 			cname = cursor;
1284 		cursor = cursor->next;
1285 	}
1286 	if(alias_ok)
1287 		return cname;
1288 	return NULL;
1289 }
1290 
1291 /**
1292  * Remove RR from RPZ's local-data
1293  * @param z: local-zone for RPZ, holding write lock
1294  * @param policydname: dname of RR to remove
1295  * @param policydnamelen: length of policydname
1296  * @param rr_type: RR type of RR to remove
1297  * @param rdata: rdata of RR to remove
1298  * @param rdatalen: length of rdata
1299  * @return: 1 if zone must be removed after RR deletion
1300  */
1301 static int
rpz_data_delete_rr(struct local_zone * z,uint8_t * policydname,size_t policydnamelen,uint16_t rr_type,uint8_t * rdata,size_t rdatalen)1302 rpz_data_delete_rr(struct local_zone* z, uint8_t* policydname,
1303 	size_t policydnamelen, uint16_t rr_type, uint8_t* rdata,
1304 	size_t rdatalen)
1305 {
1306 	struct local_data* ld;
1307 	struct packed_rrset_data* d;
1308 	size_t index;
1309 	ld = local_zone_find_data(z, policydname, policydnamelen,
1310 		dname_count_labels(policydname));
1311 	if(ld) {
1312 		struct local_rrset* prev=NULL, *p=ld->rrsets;
1313 		while(p && ntohs(p->rrset->rk.type) != rr_type) {
1314 			prev = p;
1315 			p = p->next;
1316 		}
1317 		if(!p)
1318 			return 0;
1319 		d = (struct packed_rrset_data*)p->rrset->entry.data;
1320 		if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
1321 			if(d->count == 1) {
1322 				/* no memory recycling for zone deletions ... */
1323 				if(prev) prev->next = p->next;
1324 				else ld->rrsets = p->next;
1325 			}
1326 			if(d->count > 1) {
1327 				if(!local_rrset_remove_rr(d, index))
1328 					return 0;
1329 			}
1330 		}
1331 	}
1332 	if(ld && ld->rrsets)
1333 		return 0;
1334 	return 1;
1335 }
1336 
1337 /**
1338  * Remove RR from RPZ's respip set
1339  * @param raddr: respip node
1340  * @param rr_type: RR type of RR to remove
1341  * @param rdata: rdata of RR to remove
1342  * @param rdatalen: length of rdata
1343  * @return: 1 if zone must be removed after RR deletion
1344  */
1345 static int
rpz_rrset_delete_rr(struct resp_addr * raddr,uint16_t rr_type,uint8_t * rdata,size_t rdatalen)1346 rpz_rrset_delete_rr(struct resp_addr* raddr, uint16_t rr_type, uint8_t* rdata,
1347 	size_t rdatalen)
1348 {
1349 	size_t index;
1350 	struct packed_rrset_data* d;
1351 	if(!raddr->data)
1352 		return 1;
1353 	d = raddr->data->entry.data;
1354 	if(ntohs(raddr->data->rk.type) != rr_type) {
1355 		return 0;
1356 	}
1357 	if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
1358 		if(d->count == 1) {
1359 			/* regional alloc'd */
1360 			raddr->data->entry.data = NULL;
1361 			raddr->data = NULL;
1362 			return 1;
1363 		}
1364 		if(d->count > 1) {
1365 			if(!local_rrset_remove_rr(d, index))
1366 				return 0;
1367 		}
1368 	}
1369 	return 0;
1370 
1371 }
1372 
1373 /** Remove RR from rpz localzones structure */
1374 static void
rpz_remove_local_zones_trigger(struct local_zones * zones,uint8_t * dname,size_t dnamelen,enum rpz_action a,uint16_t rr_type,uint16_t rr_class,uint8_t * rdatawl,size_t rdatalen)1375 rpz_remove_local_zones_trigger(struct local_zones* zones, uint8_t* dname,
1376 	size_t dnamelen, enum rpz_action a, uint16_t rr_type,
1377 	uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen)
1378 {
1379 	struct local_zone* z;
1380 	int delete_zone = 1;
1381 	z = rpz_find_zone(zones, dname, dnamelen, rr_class,
1382 		1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/);
1383 	if(!z) {
1384 		verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1385 			"RPZ domain not found");
1386 		return;
1387 	}
1388 	if(a == RPZ_LOCAL_DATA_ACTION)
1389 		delete_zone = rpz_data_delete_rr(z, dname,
1390 			dnamelen, rr_type, rdatawl, rdatalen);
1391 	else if(a != localzone_type_to_rpz_action(z->type)) {
1392 		lock_rw_unlock(&z->lock);
1393 		lock_rw_unlock(&zones->lock);
1394 		return;
1395 	}
1396 	lock_rw_unlock(&z->lock);
1397 	if(delete_zone) {
1398 		local_zones_del_zone(zones, z);
1399 	}
1400 	lock_rw_unlock(&zones->lock);
1401 }
1402 
1403 /** Remove RR from RPZ's local-zone */
1404 static void
rpz_remove_qname_trigger(struct rpz * r,uint8_t * dname,size_t dnamelen,enum rpz_action a,uint16_t rr_type,uint16_t rr_class,uint8_t * rdatawl,size_t rdatalen)1405 rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1406 	enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
1407 	uint8_t* rdatawl, size_t rdatalen)
1408 {
1409 	rpz_remove_local_zones_trigger(r->local_zones, dname, dnamelen,
1410 		a, rr_type, rr_class, rdatawl, rdatalen);
1411 }
1412 
1413 static void
rpz_remove_response_ip_trigger(struct rpz * r,uint8_t * dname,size_t dnamelen,enum rpz_action a,uint16_t rr_type,uint8_t * rdatawl,size_t rdatalen)1414 rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1415 	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1416 {
1417 	struct resp_addr* node;
1418 	struct sockaddr_storage addr;
1419 	socklen_t addrlen;
1420 	int net, af;
1421 	int delete_respip = 1;
1422 
1423 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1424 		return;
1425 
1426 	lock_rw_wrlock(&r->respip_set->lock);
1427 	if(!(node = (struct resp_addr*)addr_tree_find(
1428 		&r->respip_set->ip_tree, &addr, addrlen, net))) {
1429 		verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1430 			"RPZ domain not found");
1431 		lock_rw_unlock(&r->respip_set->lock);
1432 		return;
1433 	}
1434 
1435 	lock_rw_wrlock(&node->lock);
1436 	if(a == RPZ_LOCAL_DATA_ACTION) {
1437 		/* remove RR, signal whether RR can be removed */
1438 		delete_respip = rpz_rrset_delete_rr(node, rr_type, rdatawl,
1439 			rdatalen);
1440 	}
1441 	lock_rw_unlock(&node->lock);
1442 	if(delete_respip)
1443 		respip_sockaddr_delete(r->respip_set, node);
1444 	lock_rw_unlock(&r->respip_set->lock);
1445 }
1446 
1447 /** find and remove type from list of local_rrset entries*/
1448 static void
del_local_rrset_from_list(struct local_rrset ** list_head,uint16_t dtype)1449 del_local_rrset_from_list(struct local_rrset** list_head, uint16_t dtype)
1450 {
1451 	struct local_rrset* prev=NULL, *p=*list_head;
1452 	while(p && ntohs(p->rrset->rk.type) != dtype) {
1453 		prev = p;
1454 		p = p->next;
1455 	}
1456 	if(!p)
1457 		return; /* rrset type not found */
1458 	/* unlink it */
1459 	if(prev) prev->next = p->next;
1460 	else *list_head = p->next;
1461 	/* no memory recycling for zone deletions ... */
1462 }
1463 
1464 /** Delete client-ip trigger RR from its RRset and perhaps also the rrset
1465  * from the linked list. Returns if the local data is empty and the node can
1466  * be deleted too, or not. */
rpz_remove_clientip_rr(struct clientip_synthesized_rr * node,uint16_t rr_type,uint8_t * rdatawl,size_t rdatalen)1467 static int rpz_remove_clientip_rr(struct clientip_synthesized_rr* node,
1468 	uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1469 {
1470 	struct local_rrset* rrset;
1471 	struct packed_rrset_data* d;
1472 	size_t index;
1473 	rrset = rpz_find_synthesized_rrset(rr_type, node, 0);
1474 	if(rrset == NULL)
1475 		return 0; /* type not found, ignore */
1476 	d = (struct packed_rrset_data*)rrset->rrset->entry.data;
1477 	if(!packed_rrset_find_rr(d, rdatawl, rdatalen, &index))
1478 		return 0; /* RR not found, ignore */
1479 	if(d->count == 1) {
1480 		/* regional alloc'd */
1481 		/* delete the type entry from the list */
1482 		del_local_rrset_from_list(&node->data, rr_type);
1483 		/* if the list is empty, the node can be removed too */
1484 		if(node->data == NULL)
1485 			return 1;
1486 	} else if (d->count > 1) {
1487 		if(!local_rrset_remove_rr(d, index))
1488 			return 0;
1489 	}
1490 	return 0;
1491 }
1492 
1493 /** remove trigger RR from clientip_syntheized set tree. */
1494 static void
rpz_clientip_remove_trigger_rr(struct clientip_synthesized_rrset * set,struct sockaddr_storage * addr,socklen_t addrlen,int net,enum rpz_action a,uint16_t rr_type,uint8_t * rdatawl,size_t rdatalen)1495 rpz_clientip_remove_trigger_rr(struct clientip_synthesized_rrset* set,
1496 	struct sockaddr_storage* addr, socklen_t addrlen, int net,
1497 	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1498 {
1499 	struct clientip_synthesized_rr* node;
1500 	int delete_node = 1;
1501 
1502 	lock_rw_wrlock(&set->lock);
1503 	node = (struct clientip_synthesized_rr*)addr_tree_find(&set->entries,
1504 		addr, addrlen, net);
1505 	if(node == NULL) {
1506 		/* netblock not found */
1507 		verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1508 			"RPZ address, netblock not found");
1509 		lock_rw_unlock(&set->lock);
1510 		return;
1511 	}
1512 	lock_rw_wrlock(&node->lock);
1513 	if(a == RPZ_LOCAL_DATA_ACTION) {
1514 		/* remove RR, signal whether entry can be removed */
1515 		delete_node = rpz_remove_clientip_rr(node, rr_type, rdatawl,
1516 			rdatalen);
1517 	} else if(a != node->action) {
1518 		/* ignore the RR with different action specification */
1519 		delete_node = 0;
1520 	}
1521 	if(delete_node) {
1522 		rbtree_delete(&set->entries, node->node.node.key);
1523 	}
1524 	lock_rw_unlock(&set->lock);
1525 	lock_rw_unlock(&node->lock);
1526 	if(delete_node) {
1527 		lock_rw_destroy(&node->lock);
1528 	}
1529 }
1530 
1531 /** Remove clientip trigger RR from RPZ. */
1532 static void
rpz_remove_clientip_trigger(struct rpz * r,uint8_t * dname,size_t dnamelen,enum rpz_action a,uint16_t rr_type,uint8_t * rdatawl,size_t rdatalen)1533 rpz_remove_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1534 	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1535 {
1536 	struct sockaddr_storage addr;
1537 	socklen_t addrlen;
1538 	int net, af;
1539 	if(a == RPZ_INVALID_ACTION)
1540 		return;
1541 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1542 		return;
1543 	rpz_clientip_remove_trigger_rr(r->client_set, &addr, addrlen, net,
1544 		a, rr_type, rdatawl, rdatalen);
1545 }
1546 
1547 /** Remove nsip trigger RR from RPZ. */
1548 static void
rpz_remove_nsip_trigger(struct rpz * r,uint8_t * dname,size_t dnamelen,enum rpz_action a,uint16_t rr_type,uint8_t * rdatawl,size_t rdatalen)1549 rpz_remove_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1550 	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1551 {
1552 	struct sockaddr_storage addr;
1553 	socklen_t addrlen;
1554 	int net, af;
1555 	if(a == RPZ_INVALID_ACTION)
1556 		return;
1557 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1558 		return;
1559 	rpz_clientip_remove_trigger_rr(r->ns_set, &addr, addrlen, net,
1560 		a, rr_type, rdatawl, rdatalen);
1561 }
1562 
1563 /** Remove nsdname trigger RR from RPZ. */
1564 static void
rpz_remove_nsdname_trigger(struct rpz * r,uint8_t * dname,size_t dnamelen,enum rpz_action a,uint16_t rr_type,uint16_t rr_class,uint8_t * rdatawl,size_t rdatalen)1565 rpz_remove_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1566 	enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
1567 	uint8_t* rdatawl, size_t rdatalen)
1568 {
1569 	uint8_t* dname_stripped = NULL;
1570 	size_t dnamelen_stripped = 0;
1571 	if(a == RPZ_INVALID_ACTION)
1572 		return;
1573 	if(!rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
1574 		&dnamelen_stripped))
1575 		return;
1576 	rpz_remove_local_zones_trigger(r->nsdname_zones, dname_stripped,
1577 		dnamelen_stripped, a, rr_type, rr_class, rdatawl, rdatalen);
1578 	free(dname_stripped);
1579 }
1580 
1581 void
rpz_remove_rr(struct rpz * r,uint8_t * azname,size_t aznamelen,uint8_t * dname,size_t dnamelen,uint16_t rr_type,uint16_t rr_class,uint8_t * rdatawl,size_t rdatalen)1582 rpz_remove_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
1583 	size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl,
1584 	size_t rdatalen)
1585 {
1586 	size_t policydnamelen;
1587 	enum rpz_trigger t;
1588 	enum rpz_action a;
1589 	uint8_t* policydname;
1590 
1591 	if(rpz_type_ignored(rr_type)) {
1592 		/* this rpz action is not valid, eg. this is the SOA or NS RR */
1593 		return;
1594 	}
1595 	if(!dname_subdomain_c(dname, azname)) {
1596 		/* not subdomain of the RPZ zone. */
1597 		return;
1598 	}
1599 
1600 	if(!(policydname = calloc(1, LDNS_MAX_DOMAINLEN + 1)))
1601 		return;
1602 
1603 	a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
1604 	if(a == RPZ_INVALID_ACTION) {
1605 		free(policydname);
1606 		return;
1607 	}
1608 	if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
1609 		policydname, LDNS_MAX_DOMAINLEN + 1))) {
1610 		free(policydname);
1611 		return;
1612 	}
1613 	t = rpz_dname_to_trigger(policydname, policydnamelen);
1614 	if(t == RPZ_INVALID_TRIGGER) {
1615 		/* skipping invalid trigger */
1616 		free(policydname);
1617 		return;
1618 	}
1619 	if(t == RPZ_QNAME_TRIGGER) {
1620 		rpz_remove_qname_trigger(r, policydname, policydnamelen, a,
1621 			rr_type, rr_class, rdatawl, rdatalen);
1622 	} else if(t == RPZ_RESPONSE_IP_TRIGGER) {
1623 		rpz_remove_response_ip_trigger(r, policydname, policydnamelen,
1624 			a, rr_type, rdatawl, rdatalen);
1625 	} else if(t == RPZ_CLIENT_IP_TRIGGER) {
1626 		rpz_remove_clientip_trigger(r, policydname, policydnamelen, a,
1627 			rr_type, rdatawl, rdatalen);
1628 	} else if(t == RPZ_NSIP_TRIGGER) {
1629 		rpz_remove_nsip_trigger(r, policydname, policydnamelen, a,
1630 			rr_type, rdatawl, rdatalen);
1631 	} else if(t == RPZ_NSDNAME_TRIGGER) {
1632 		rpz_remove_nsdname_trigger(r, policydname, policydnamelen, a,
1633 			rr_type, rr_class, rdatawl, rdatalen);
1634 	}
1635 	/* else it was an unsupported trigger, also skipped. */
1636 	free(policydname);
1637 }
1638 
1639 /** print log information for an applied RPZ policy. Based on local-zone's
1640  * lz_inform_print().
1641  * The repinfo contains the reply address. If it is NULL, the module
1642  * state is used to report the first IP address (if any).
1643  * The dname is used, for the applied rpz, if NULL, addrnode is used.
1644  */
1645 static void
log_rpz_apply(char * trigger,uint8_t * dname,struct addr_tree_node * addrnode,enum rpz_action a,struct query_info * qinfo,struct comm_reply * repinfo,struct module_qstate * ms,char * log_name)1646 log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode,
1647 	enum rpz_action a, struct query_info* qinfo,
1648 	struct comm_reply* repinfo, struct module_qstate* ms, char* log_name)
1649 {
1650 	char ip[128], txt[512], portstr[32];
1651 	char dnamestr[LDNS_MAX_DOMAINLEN];
1652 	uint16_t port = 0;
1653 	if(dname) {
1654 		dname_str(dname, dnamestr);
1655 	} else if(addrnode) {
1656 		char addrbuf[128];
1657 		addr_to_str(&addrnode->addr, addrnode->addrlen, addrbuf, sizeof(addrbuf));
1658 		snprintf(dnamestr, sizeof(dnamestr), "%s/%d", addrbuf, addrnode->net);
1659 	} else {
1660 		dnamestr[0]=0;
1661 	}
1662 	if(repinfo) {
1663 		addr_to_str(&repinfo->client_addr, repinfo->client_addrlen, ip, sizeof(ip));
1664 		port = ntohs(((struct sockaddr_in*)&repinfo->client_addr)->sin_port);
1665 	} else if(ms && ms->mesh_info && ms->mesh_info->reply_list) {
1666 		addr_to_str(&ms->mesh_info->reply_list->query_reply.client_addr,
1667 			ms->mesh_info->reply_list->query_reply.client_addrlen,
1668 			ip, sizeof(ip));
1669 		port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.client_addr)->sin_port);
1670 	} else {
1671 		ip[0]=0;
1672 		port = 0;
1673 	}
1674 	snprintf(portstr, sizeof(portstr), "@%u", (unsigned)port);
1675 	snprintf(txt, sizeof(txt), "rpz: applied %s%s%s%s%s%s %s %s%s",
1676 		(log_name?"[":""), (log_name?log_name:""), (log_name?"] ":""),
1677 		(strcmp(trigger,"qname")==0?"":trigger),
1678 		(strcmp(trigger,"qname")==0?"":" "),
1679 		dnamestr, rpz_action_to_string(a),
1680 		(ip[0]?ip:""), (ip[0]?portstr:""));
1681 	log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
1682 }
1683 
1684 static struct clientip_synthesized_rr*
rpz_ipbased_trigger_lookup(struct clientip_synthesized_rrset * set,struct sockaddr_storage * addr,socklen_t addrlen,char * triggername)1685 rpz_ipbased_trigger_lookup(struct clientip_synthesized_rrset* set,
1686 	struct sockaddr_storage* addr, socklen_t addrlen, char* triggername)
1687 {
1688 	struct clientip_synthesized_rr* raddr = NULL;
1689 	enum rpz_action action = RPZ_INVALID_ACTION;
1690 
1691 	lock_rw_rdlock(&set->lock);
1692 
1693 	raddr = (struct clientip_synthesized_rr*)addr_tree_lookup(&set->entries,
1694 			addr, addrlen);
1695 	if(raddr != NULL) {
1696 		lock_rw_rdlock(&raddr->lock);
1697 		action = raddr->action;
1698 		if(verbosity >= VERB_ALGO) {
1699 			char ip[256], net[256];
1700 			addr_to_str(addr, addrlen, ip, sizeof(ip));
1701 			addr_to_str(&raddr->node.addr, raddr->node.addrlen,
1702 				net, sizeof(net));
1703 			verbose(VERB_ALGO, "rpz: trigger %s %s/%d on %s action=%s",
1704 				triggername, net, raddr->node.net, ip, rpz_action_to_string(action));
1705 		}
1706 	}
1707 	lock_rw_unlock(&set->lock);
1708 
1709 	return raddr;
1710 }
1711 
1712 static inline
1713 struct clientip_synthesized_rr*
rpz_resolve_client_action_and_zone(struct auth_zones * az,struct query_info * qinfo,struct comm_reply * repinfo,uint8_t * taglist,size_t taglen,struct ub_server_stats * stats,struct local_zone ** z_out,struct auth_zone ** a_out,struct rpz ** r_out)1714 rpz_resolve_client_action_and_zone(struct auth_zones* az, struct query_info* qinfo,
1715 	struct comm_reply* repinfo, uint8_t* taglist, size_t taglen,
1716 	struct ub_server_stats* stats,
1717 	/* output parameters */
1718 	struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out)
1719 {
1720 	struct clientip_synthesized_rr* node = NULL;
1721 	struct auth_zone* a = NULL;
1722 	struct rpz* r = NULL;
1723 	struct local_zone* z = NULL;
1724 
1725 	lock_rw_rdlock(&az->rpz_lock);
1726 
1727 	for(a = az->rpz_first; a; a = a->rpz_az_next) {
1728 		lock_rw_rdlock(&a->lock);
1729 		r = a->rpz;
1730 		if(r->disabled) {
1731 			lock_rw_unlock(&a->lock);
1732 			continue;
1733 		}
1734 		if(r->taglist && !taglist_intersect(r->taglist,
1735 					r->taglistlen, taglist, taglen)) {
1736 			lock_rw_unlock(&a->lock);
1737 			continue;
1738 		}
1739 		z = rpz_find_zone(r->local_zones, qinfo->qname, qinfo->qname_len,
1740 			qinfo->qclass, 0, 0, 0);
1741 		node = rpz_ipbased_trigger_lookup(r->client_set,
1742 			&repinfo->client_addr, repinfo->client_addrlen,
1743 			"clientip");
1744 		if((z || node) && r->action_override == RPZ_DISABLED_ACTION) {
1745 			if(r->log)
1746 				log_rpz_apply((node?"clientip":"qname"),
1747 					(z?z->name:NULL),
1748 					(node?&node->node:NULL),
1749 					r->action_override,
1750 					qinfo, repinfo, NULL, r->log_name);
1751 			stats->rpz_action[r->action_override]++;
1752 			if(z != NULL) {
1753 				lock_rw_unlock(&z->lock);
1754 				z = NULL;
1755 			}
1756 			if(node != NULL) {
1757 				lock_rw_unlock(&node->lock);
1758 				node = NULL;
1759 			}
1760 		}
1761 		if(z || node) {
1762 			break;
1763 		}
1764 		/* not found in this auth_zone */
1765 		lock_rw_unlock(&a->lock);
1766 	}
1767 
1768 	lock_rw_unlock(&az->rpz_lock);
1769 
1770 	*r_out = r;
1771 	*a_out = a;
1772 	*z_out = z;
1773 
1774 	return node;
1775 }
1776 
1777 static inline int
rpz_is_udp_query(struct comm_reply * repinfo)1778 rpz_is_udp_query(struct comm_reply* repinfo) {
1779 	return repinfo != NULL
1780 			? (repinfo->c != NULL
1781 				? repinfo->c->type == comm_udp
1782 				: 0)
1783 			: 0;
1784 }
1785 
1786 /** encode answer consisting of 1 rrset */
1787 static int
rpz_local_encode(struct module_env * env,struct query_info * qinfo,struct edns_data * edns,struct comm_reply * repinfo,sldns_buffer * buf,struct regional * temp,struct ub_packed_rrset_key * rrset,int ansec,int rcode,struct ub_packed_rrset_key * soa_rrset)1788 rpz_local_encode(struct module_env* env, struct query_info* qinfo,
1789 	struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
1790 	struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec,
1791 	int rcode, struct ub_packed_rrset_key* soa_rrset)
1792 {
1793 	struct reply_info rep;
1794 	uint16_t udpsize;
1795 	struct ub_packed_rrset_key* rrsetlist[3];
1796 
1797 	memset(&rep, 0, sizeof(rep));
1798 	rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode);
1799 	rep.qdcount = 1;
1800 	rep.rrset_count = ansec;
1801 	rep.rrsets = rrsetlist;
1802 	if(ansec > 0) {
1803 		rep.an_numrrsets = 1;
1804 		rep.rrsets[0] = rrset;
1805 		rep.ttl = ((struct packed_rrset_data*)rrset->entry.data)->rr_ttl[0];
1806 	}
1807 	if(soa_rrset != NULL) {
1808 		rep.ar_numrrsets = 1;
1809 		rep.rrsets[rep.rrset_count] = soa_rrset;
1810 		rep.rrset_count ++;
1811 		if(rep.ttl < ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0]) {
1812 			rep.ttl = ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0];
1813 		}
1814 	}
1815 
1816 	udpsize = edns->udp_size;
1817 	edns->edns_version = EDNS_ADVERTISED_VERSION;
1818 	edns->udp_size = EDNS_ADVERTISED_SIZE;
1819 	edns->ext_rcode = 0;
1820 	edns->bits &= EDNS_DO;
1821 	if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns,
1822 		repinfo, temp, env->now_tv) ||
1823 	  !reply_info_answer_encode(qinfo, &rep,
1824 		*(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2),
1825 		buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) {
1826 		error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
1827 			*(uint16_t*)sldns_buffer_begin(buf),
1828 			sldns_buffer_read_u16_at(buf, 2), edns);
1829 	}
1830 
1831 	return 1;
1832 }
1833 
1834 /** allocate SOA record ubrrsetkey in region */
1835 static struct ub_packed_rrset_key*
make_soa_ubrrset(struct auth_zone * auth_zone,struct auth_rrset * soa,struct regional * temp)1836 make_soa_ubrrset(struct auth_zone* auth_zone, struct auth_rrset* soa,
1837 	struct regional* temp)
1838 {
1839 	struct ub_packed_rrset_key csoa;
1840 	if(!soa)
1841 		return NULL;
1842 	memset(&csoa, 0, sizeof(csoa));
1843 	csoa.entry.key = &csoa;
1844 	csoa.rk.rrset_class = htons(LDNS_RR_CLASS_IN);
1845 	csoa.rk.type = htons(LDNS_RR_TYPE_SOA);
1846 	csoa.rk.flags |= PACKED_RRSET_FIXEDTTL
1847 		| PACKED_RRSET_RPZ;
1848 	csoa.rk.dname = auth_zone->name;
1849 	csoa.rk.dname_len = auth_zone->namelen;
1850 	csoa.entry.hash = rrset_key_hash(&csoa.rk);
1851 	csoa.entry.data = soa->data;
1852 	return respip_copy_rrset(&csoa, temp);
1853 }
1854 
1855 static void
rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr * raddr,struct module_env * env,struct query_info * qinfo,struct edns_data * edns,struct comm_reply * repinfo,sldns_buffer * buf,struct regional * temp,struct auth_zone * auth_zone)1856 rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr,
1857 	struct module_env* env, struct query_info* qinfo,
1858 	struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
1859 	struct regional* temp, struct auth_zone* auth_zone)
1860 {
1861 	struct local_rrset* rrset;
1862 	enum rpz_action action = RPZ_INVALID_ACTION;
1863 	struct ub_packed_rrset_key* rp = NULL;
1864 	struct ub_packed_rrset_key* rsoa = NULL;
1865 	int rcode = LDNS_RCODE_NOERROR|BIT_AA;
1866 	int rrset_count = 1;
1867 
1868 	/* prepare synthesized answer for client */
1869 	action = raddr->action;
1870 	if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL ) {
1871 		verbose(VERB_ALGO, "rpz: bug: local-data action but no local data");
1872 		return;
1873 	}
1874 
1875 	/* check query type / rr type */
1876 	rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr, 1);
1877 	if(rrset == NULL) {
1878 		verbose(VERB_ALGO, "rpz: unable to find local-data for query");
1879 		rrset_count = 0;
1880 		goto nodata;
1881 	}
1882 
1883 	rp = respip_copy_rrset(rrset->rrset, temp);
1884 	if(!rp) {
1885 		verbose(VERB_ALGO, "rpz: local data action: out of memory");
1886 		return;
1887 	}
1888 
1889 	rp->rk.flags |= PACKED_RRSET_FIXEDTTL | PACKED_RRSET_RPZ;
1890 	rp->rk.dname = qinfo->qname;
1891 	rp->rk.dname_len = qinfo->qname_len;
1892 	rp->entry.hash = rrset_key_hash(&rp->rk);
1893 nodata:
1894 	if(auth_zone) {
1895 		struct auth_rrset* soa = NULL;
1896 		soa = auth_zone_get_soa_rrset(auth_zone);
1897 		if(soa) {
1898 			rsoa = make_soa_ubrrset(auth_zone, soa, temp);
1899 			if(!rsoa) {
1900 				verbose(VERB_ALGO, "rpz: local data action soa: out of memory");
1901 				return;
1902 			}
1903 		}
1904 	}
1905 
1906 	rpz_local_encode(env, qinfo, edns, repinfo, buf, temp, rp,
1907 		rrset_count, rcode, rsoa);
1908 }
1909 
1910 /** Apply the cname override action, during worker request callback.
1911  * false on failure. */
1912 static int
rpz_apply_cname_override_action(struct rpz * r,struct query_info * qinfo,struct regional * temp)1913 rpz_apply_cname_override_action(struct rpz* r,
1914 	struct query_info* qinfo, struct regional* temp)
1915 {
1916 	if(!r)
1917 		return 0;
1918 	qinfo->local_alias = regional_alloc_zero(temp,
1919 		sizeof(struct local_rrset));
1920 	if(qinfo->local_alias == NULL)
1921 		return 0; /* out of memory */
1922 	qinfo->local_alias->rrset = respip_copy_rrset(r->cname_override, temp);
1923 	if(qinfo->local_alias->rrset == NULL) {
1924 		qinfo->local_alias = NULL;
1925 		return 0; /* out of memory */
1926 	}
1927 	qinfo->local_alias->rrset->rk.dname = qinfo->qname;
1928 	qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
1929 	return 1;
1930 }
1931 
1932 /** add additional section SOA record to the reply.
1933  * Since this gets fed into the normal iterator answer creation, it
1934  * gets minimal-responses applied to it, that can remove the additional SOA
1935  * again. */
1936 static int
rpz_add_soa(struct reply_info * rep,struct module_qstate * ms,struct auth_zone * az)1937 rpz_add_soa(struct reply_info* rep, struct module_qstate* ms,
1938 	struct auth_zone* az)
1939 {
1940 	struct auth_rrset* soa = NULL;
1941 	struct ub_packed_rrset_key* rsoa = NULL;
1942 	struct ub_packed_rrset_key** prevrrsets;
1943 	if(!az) return 1;
1944 	soa = auth_zone_get_soa_rrset(az);
1945 	if(!soa) return 1;
1946 	if(!rep) return 0;
1947 	rsoa = make_soa_ubrrset(az, soa, ms->region);
1948 	if(!rsoa) return 0;
1949 	prevrrsets = rep->rrsets;
1950 	rep->rrsets = regional_alloc_zero(ms->region,
1951 		sizeof(*rep->rrsets)*(rep->rrset_count+1));
1952 	if(!rep->rrsets)
1953 		return 0;
1954 	if(prevrrsets && rep->rrset_count > 0)
1955 		memcpy(rep->rrsets, prevrrsets, rep->rrset_count*sizeof(*rep->rrsets));
1956 	rep->rrset_count++;
1957 	rep->ar_numrrsets++;
1958 	rep->rrsets[rep->rrset_count-1] = rsoa;
1959 	return 1;
1960 }
1961 
1962 static inline struct dns_msg*
rpz_dns_msg_new(struct regional * region)1963 rpz_dns_msg_new(struct regional* region)
1964 {
1965 	struct dns_msg* msg =
1966 			(struct dns_msg*)regional_alloc(region,
1967 							sizeof(struct dns_msg));
1968 	if(msg == NULL) { return NULL; }
1969 	memset(msg, 0, sizeof(struct dns_msg));
1970 
1971 	return msg;
1972 }
1973 
1974 static inline struct dns_msg*
rpz_synthesize_nodata(struct rpz * ATTR_UNUSED (r),struct module_qstate * ms,struct query_info * qinfo,struct auth_zone * az)1975 rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
1976 	struct query_info* qinfo, struct auth_zone* az)
1977 {
1978 	struct dns_msg* msg = rpz_dns_msg_new(ms->region);
1979 	if(msg == NULL) { return msg; }
1980 	msg->qinfo = *qinfo;
1981 	msg->rep = construct_reply_info_base(ms->region,
1982 					     LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
1983 					     1, /* qd */
1984 					     0, /* ttl */
1985 					     0, /* prettl */
1986 					     0, /* expttl */
1987 					     0, /* norecttl */
1988 					     0, /* an */
1989 					     0, /* ns */
1990 					     0, /* ar */
1991 					     0, /* total */
1992 					     sec_status_insecure,
1993 					     LDNS_EDE_NONE);
1994 	if(!msg->rep)
1995 		return NULL;
1996 	msg->rep->authoritative = 1;
1997 	if(!rpz_add_soa(msg->rep, ms, az))
1998 		return NULL;
1999 	return msg;
2000 }
2001 
2002 static inline struct dns_msg*
rpz_synthesize_nxdomain(struct rpz * r,struct module_qstate * ms,struct query_info * qinfo,struct auth_zone * az)2003 rpz_synthesize_nxdomain(struct rpz* r, struct module_qstate* ms,
2004 	struct query_info* qinfo, struct auth_zone* az)
2005 {
2006 	struct dns_msg* msg = rpz_dns_msg_new(ms->region);
2007 	uint16_t flags;
2008 	if(msg == NULL) { return msg; }
2009 	msg->qinfo = *qinfo;
2010 	flags = LDNS_RCODE_NXDOMAIN | BIT_QR | BIT_AA | BIT_RA;
2011 	if(r->signal_nxdomain_ra)
2012 		flags &= ~BIT_RA;
2013 	msg->rep = construct_reply_info_base(ms->region,
2014 					     flags,
2015 					     1, /* qd */
2016 					     0, /* ttl */
2017 					     0, /* prettl */
2018 					     0, /* expttl */
2019 					     0, /* norecttl */
2020 					     0, /* an */
2021 					     0, /* ns */
2022 					     0, /* ar */
2023 					     0, /* total */
2024 					     sec_status_insecure,
2025 					     LDNS_EDE_NONE);
2026 	if(!msg->rep)
2027 		return NULL;
2028 	msg->rep->authoritative = 1;
2029 	if(!rpz_add_soa(msg->rep, ms, az))
2030 		return NULL;
2031 	return msg;
2032 }
2033 
2034 static inline struct dns_msg*
rpz_synthesize_localdata_from_rrset(struct rpz * ATTR_UNUSED (r),struct module_qstate * ms,struct query_info * qi,struct local_rrset * rrset,struct auth_zone * az)2035 rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
2036 	struct query_info* qi, struct local_rrset* rrset, struct auth_zone* az)
2037 {
2038 	struct dns_msg* msg = NULL;
2039 	struct reply_info* new_reply_info;
2040 	struct ub_packed_rrset_key* rp;
2041 
2042 
2043 	msg = rpz_dns_msg_new(ms->region);
2044 	if(msg == NULL) { return NULL; }
2045 
2046 	msg->qinfo = *qi;
2047         new_reply_info = construct_reply_info_base(ms->region,
2048                                                    LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
2049                                                    1, /* qd */
2050                                                    0, /* ttl */
2051                                                    0, /* prettl */
2052                                                    0, /* expttl */
2053                                                    0, /* norecttl */
2054                                                    1, /* an */
2055                                                    0, /* ns */
2056                                                    0, /* ar */
2057                                                    1, /* total */
2058                                                    sec_status_insecure,
2059                                                    LDNS_EDE_NONE);
2060 	if(new_reply_info == NULL) {
2061 		log_err("out of memory");
2062 		return NULL;
2063 	}
2064 	new_reply_info->authoritative = 1;
2065 	rp = respip_copy_rrset(rrset->rrset, ms->region);
2066 	if(rp == NULL) {
2067 		log_err("out of memory");
2068 		return NULL;
2069 	}
2070 	rp->rk.dname = qi->qname;
2071 	rp->rk.dname_len = qi->qname_len;
2072 	/* this rrset is from the rpz data, or synthesized.
2073 	 * It is not actually from the network, so we flag it with this
2074 	 * flags as a fake RRset. If later the cache is used to look up
2075 	 * rrsets, then the fake ones are not returned (if you look without
2076 	 * the flag). For like CNAME lookups from the iterator or A, AAAA
2077 	 * lookups for nameserver targets, it would use the without flag
2078 	 * actual data. So that the actual network data and fake data
2079 	 * are kept track of separately. */
2080 	rp->rk.flags |= PACKED_RRSET_RPZ;
2081 	new_reply_info->rrsets[0] = rp;
2082 	msg->rep = new_reply_info;
2083 	if(!rpz_add_soa(msg->rep, ms, az))
2084 		return NULL;
2085 	return msg;
2086 }
2087 
2088 static inline struct dns_msg*
rpz_synthesize_nsip_localdata(struct rpz * r,struct module_qstate * ms,struct query_info * qi,struct clientip_synthesized_rr * data,struct auth_zone * az)2089 rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms,
2090 	struct query_info* qi, struct clientip_synthesized_rr* data,
2091 	struct auth_zone* az)
2092 {
2093 	struct local_rrset* rrset;
2094 
2095 	rrset = rpz_find_synthesized_rrset(qi->qtype, data, 1);
2096 	if(rrset == NULL) {
2097 		verbose(VERB_ALGO, "rpz: nsip: no matching local data found");
2098 		return NULL;
2099 	}
2100 
2101 	return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
2102 }
2103 
2104 /* copy'n'paste from localzone.c */
2105 static struct local_rrset*
local_data_find_type(struct local_data * data,uint16_t type,int alias_ok)2106 local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
2107 {
2108 	struct local_rrset* p, *cname = NULL;
2109 	type = htons(type);
2110 	for(p = data->rrsets; p; p = p->next) {
2111 		if(p->rrset->rk.type == type)
2112 			return p;
2113 		if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
2114 			cname = p;
2115 	}
2116 	if(alias_ok)
2117 		return cname;
2118 	return NULL;
2119 }
2120 
2121 /* based on localzone.c:local_data_answer() */
2122 static inline struct dns_msg*
rpz_synthesize_nsdname_localdata(struct rpz * r,struct module_qstate * ms,struct query_info * qi,struct local_zone * z,struct matched_delegation_point const * match,struct auth_zone * az)2123 rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
2124 	struct query_info* qi, struct local_zone* z,
2125 	struct matched_delegation_point const* match, struct auth_zone* az)
2126 {
2127 	struct local_data key;
2128 	struct local_data* ld;
2129 	struct local_rrset* rrset;
2130 
2131 	if(match->dname == NULL) { return NULL; }
2132 
2133 	key.node.key = &key;
2134 	key.name = match->dname;
2135 	key.namelen = match->dname_len;
2136 	key.namelabs = dname_count_labels(match->dname);
2137 
2138 	rpz_log_dname("nsdname local data", key.name, key.namelen);
2139 
2140 	ld = (struct local_data*)rbtree_search(&z->data, &key.node);
2141 	if(ld == NULL && dname_is_wild(z->name)) {
2142 		key.name = z->name;
2143 		key.namelen = z->namelen;
2144 		key.namelabs = z->namelabs;
2145 		ld = (struct local_data*)rbtree_search(&z->data, &key.node);
2146 		/* rpz_synthesize_localdata_from_rrset is going to make
2147 		 * the rrset source name equal to the query name. So no need
2148 		 * to make the wildcard rrset here. */
2149 	}
2150 	if(ld == NULL) {
2151 		verbose(VERB_ALGO, "rpz: nsdname: qname not found");
2152 		return NULL;
2153 	}
2154 
2155 	rrset = local_data_find_type(ld, qi->qtype, 1);
2156 	if(rrset == NULL) {
2157 		verbose(VERB_ALGO, "rpz: nsdname: no matching local data found");
2158 		return NULL;
2159 	}
2160 
2161 	return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
2162 }
2163 
2164 /* like local_data_answer for qname triggers after a cname */
2165 static struct dns_msg*
rpz_synthesize_qname_localdata_msg(struct rpz * r,struct module_qstate * ms,struct query_info * qinfo,struct local_zone * z,struct auth_zone * az)2166 rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms,
2167 	struct query_info* qinfo, struct local_zone* z, struct auth_zone* az)
2168 {
2169 	struct local_data key;
2170 	struct local_data* ld;
2171 	struct local_rrset* rrset;
2172 	key.node.key = &key;
2173 	key.name = qinfo->qname;
2174 	key.namelen = qinfo->qname_len;
2175 	key.namelabs = dname_count_labels(qinfo->qname);
2176 	ld = (struct local_data*)rbtree_search(&z->data, &key.node);
2177 	if(ld == NULL && dname_is_wild(z->name)) {
2178 		key.name = z->name;
2179 		key.namelen = z->namelen;
2180 		key.namelabs = z->namelabs;
2181 		ld = (struct local_data*)rbtree_search(&z->data, &key.node);
2182 		/* rpz_synthesize_localdata_from_rrset is going to make
2183 		 * the rrset source name equal to the query name. So no need
2184 		 * to make the wildcard rrset here. */
2185 	}
2186 	if(ld == NULL) {
2187 		verbose(VERB_ALGO, "rpz: qname: name not found");
2188 		return NULL;
2189 	}
2190 	rrset = local_data_find_type(ld, qinfo->qtype, 1);
2191 	if(rrset == NULL) {
2192 		verbose(VERB_ALGO, "rpz: qname: type not found");
2193 		return NULL;
2194 	}
2195 	return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az);
2196 }
2197 
2198 /** Synthesize a CNAME message for RPZ action override */
2199 static struct dns_msg*
rpz_synthesize_cname_override_msg(struct rpz * r,struct module_qstate * ms,struct query_info * qinfo)2200 rpz_synthesize_cname_override_msg(struct rpz* r, struct module_qstate* ms,
2201 	struct query_info* qinfo)
2202 {
2203 	struct dns_msg* msg = NULL;
2204 	struct reply_info* new_reply_info;
2205 	struct ub_packed_rrset_key* rp;
2206 
2207 	msg = rpz_dns_msg_new(ms->region);
2208 	if(msg == NULL) { return NULL; }
2209 
2210 	msg->qinfo = *qinfo;
2211         new_reply_info = construct_reply_info_base(ms->region,
2212                                                    LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
2213                                                    1, /* qd */
2214                                                    0, /* ttl */
2215                                                    0, /* prettl */
2216                                                    0, /* expttl */
2217                                                    0, /* norecttl */
2218                                                    1, /* an */
2219                                                    0, /* ns */
2220                                                    0, /* ar */
2221                                                    1, /* total */
2222                                                    sec_status_insecure,
2223                                                    LDNS_EDE_NONE);
2224 	if(new_reply_info == NULL) {
2225 		log_err("out of memory");
2226 		return NULL;
2227 	}
2228 	new_reply_info->authoritative = 1;
2229 
2230 	rp = respip_copy_rrset(r->cname_override, ms->region);
2231 	if(rp == NULL) {
2232 		log_err("out of memory");
2233 		return NULL;
2234 	}
2235 	rp->rk.dname = qinfo->qname;
2236 	rp->rk.dname_len = qinfo->qname_len;
2237 	/* this rrset is from the rpz data, or synthesized.
2238 	 * It is not actually from the network, so we flag it with this
2239 	 * flags as a fake RRset. If later the cache is used to look up
2240 	 * rrsets, then the fake ones are not returned (if you look without
2241 	 * the flag). For like CNAME lookups from the iterator or A, AAAA
2242 	 * lookups for nameserver targets, it would use the without flag
2243 	 * actual data. So that the actual network data and fake data
2244 	 * are kept track of separately. */
2245 	rp->rk.flags |= PACKED_RRSET_RPZ;
2246 	new_reply_info->rrsets[0] = rp;
2247 
2248 	msg->rep = new_reply_info;
2249 	return msg;
2250 }
2251 
2252 static int
rpz_synthesize_qname_localdata(struct module_env * env,struct rpz * r,struct local_zone * z,enum localzone_type lzt,struct query_info * qinfo,struct edns_data * edns,sldns_buffer * buf,struct regional * temp,struct comm_reply * repinfo,struct ub_server_stats * stats)2253 rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
2254 	struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo,
2255 	struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
2256 	struct comm_reply* repinfo, struct ub_server_stats* stats)
2257 {
2258 	struct local_data* ld = NULL;
2259 	int ret = 0;
2260 	if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
2261 		if(!rpz_apply_cname_override_action(r, qinfo, temp))
2262 			return 0;
2263 		if(r->log) {
2264 			log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION,
2265 				      qinfo, repinfo, NULL, r->log_name);
2266 		}
2267 		stats->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
2268 		return 0;
2269 	}
2270 
2271 	if(lzt == local_zone_redirect && local_data_answer(z, env, qinfo,
2272 		edns, repinfo, buf, temp, dname_count_labels(qinfo->qname),
2273 		&ld, lzt, -1, NULL, 0, NULL, 0)) {
2274 		if(r->log) {
2275 			log_rpz_apply("qname", z->name, NULL,
2276 				localzone_type_to_rpz_action(lzt), qinfo,
2277 				repinfo, NULL, r->log_name);
2278 		}
2279 		stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
2280 		return !qinfo->local_alias;
2281 	}
2282 
2283 	ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp,
2284 		0 /* no local data used */, lzt);
2285 	if(r->signal_nxdomain_ra && LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
2286 		== LDNS_RCODE_NXDOMAIN)
2287 		LDNS_RA_CLR(sldns_buffer_begin(buf));
2288 	if(r->log) {
2289 		log_rpz_apply("qname", z->name, NULL, localzone_type_to_rpz_action(lzt),
2290 			      qinfo, repinfo, NULL, r->log_name);
2291 	}
2292 	stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
2293 	return ret;
2294 }
2295 
2296 static struct clientip_synthesized_rr*
rpz_delegation_point_ipbased_trigger_lookup(struct rpz * rpz,struct iter_qstate * is)2297 rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate* is)
2298 {
2299 	struct delegpt_addr* cursor;
2300 	struct clientip_synthesized_rr* action = NULL;
2301 	if(is->dp == NULL) { return NULL; }
2302 	for(cursor = is->dp->target_list;
2303 	    cursor != NULL;
2304 	    cursor = cursor->next_target) {
2305 		if(cursor->bogus) { continue; }
2306 		action = rpz_ipbased_trigger_lookup(rpz->ns_set, &cursor->addr,
2307 						    cursor->addrlen, "nsip");
2308 		if(action != NULL) { return action; }
2309 	}
2310 	return NULL;
2311 }
2312 
2313 static struct dns_msg*
rpz_apply_nsip_trigger(struct module_qstate * ms,struct query_info * qchase,struct rpz * r,struct clientip_synthesized_rr * raddr,struct auth_zone * az)2314 rpz_apply_nsip_trigger(struct module_qstate* ms, struct query_info* qchase,
2315 	struct rpz* r, struct clientip_synthesized_rr* raddr,
2316 	struct auth_zone* az)
2317 {
2318 	enum rpz_action action = raddr->action;
2319 	struct dns_msg* ret = NULL;
2320 
2321 	if(r->action_override != RPZ_NO_OVERRIDE_ACTION) {
2322 		verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)",
2323 			rpz_action_to_string(r->action_override), rpz_action_to_string(action));
2324 		action = r->action_override;
2325 	}
2326 
2327 	if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) {
2328 		verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data");
2329 		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2330 		ms->rpz_applied = 1;
2331 		goto done;
2332 	}
2333 
2334 	switch(action) {
2335 	case RPZ_NXDOMAIN_ACTION:
2336 		ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
2337 		ms->rpz_applied = 1;
2338 		break;
2339 	case RPZ_NODATA_ACTION:
2340 		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2341 		ms->rpz_applied = 1;
2342 		break;
2343 	case RPZ_TCP_ONLY_ACTION:
2344 		/* basically a passthru here but the tcp-only will be
2345 		 * honored before the query gets sent. */
2346 		ms->tcp_required = 1;
2347 		ret = NULL;
2348 		break;
2349 	case RPZ_DROP_ACTION:
2350 		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2351 		ms->rpz_applied = 1;
2352 		ms->is_drop = 1;
2353 		break;
2354 	case RPZ_LOCAL_DATA_ACTION:
2355 		ret = rpz_synthesize_nsip_localdata(r, ms, qchase, raddr, az);
2356 		if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
2357 		ms->rpz_applied = 1;
2358 		break;
2359 	case RPZ_PASSTHRU_ACTION:
2360 		ret = NULL;
2361 		ms->rpz_passthru = 1;
2362 		break;
2363 	case RPZ_CNAME_OVERRIDE_ACTION:
2364 		ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
2365 		ms->rpz_applied = 1;
2366 		break;
2367 	default:
2368 		verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
2369 			rpz_action_to_string(action));
2370 		ret = NULL;
2371 	}
2372 
2373 done:
2374 	if(r->log)
2375 		log_rpz_apply("nsip", NULL, &raddr->node,
2376 			action, &ms->qinfo, NULL, ms, r->log_name);
2377 	if(ms->env->worker)
2378 		ms->env->worker->stats.rpz_action[action]++;
2379 	lock_rw_unlock(&raddr->lock);
2380 	return ret;
2381 }
2382 
2383 static struct dns_msg*
rpz_apply_nsdname_trigger(struct module_qstate * ms,struct query_info * qchase,struct rpz * r,struct local_zone * z,struct matched_delegation_point const * match,struct auth_zone * az)2384 rpz_apply_nsdname_trigger(struct module_qstate* ms, struct query_info* qchase,
2385 	struct rpz* r, struct local_zone* z,
2386 	struct matched_delegation_point const* match, struct auth_zone* az)
2387 {
2388 	struct dns_msg* ret = NULL;
2389 	enum rpz_action action = localzone_type_to_rpz_action(z->type);
2390 
2391 	if(r->action_override != RPZ_NO_OVERRIDE_ACTION) {
2392 		verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)",
2393 			rpz_action_to_string(r->action_override), rpz_action_to_string(action));
2394 		action = r->action_override;
2395 	}
2396 
2397 	switch(action) {
2398 	case RPZ_NXDOMAIN_ACTION:
2399 		ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
2400 		ms->rpz_applied = 1;
2401 		break;
2402 	case RPZ_NODATA_ACTION:
2403 		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2404 		ms->rpz_applied = 1;
2405 		break;
2406 	case RPZ_TCP_ONLY_ACTION:
2407 		/* basically a passthru here but the tcp-only will be
2408 		 * honored before the query gets sent. */
2409 		ms->tcp_required = 1;
2410 		ret = NULL;
2411 		break;
2412 	case RPZ_DROP_ACTION:
2413 		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2414 		ms->rpz_applied = 1;
2415 		ms->is_drop = 1;
2416 		break;
2417 	case RPZ_LOCAL_DATA_ACTION:
2418 		ret = rpz_synthesize_nsdname_localdata(r, ms, qchase, z, match, az);
2419 		if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
2420 		ms->rpz_applied = 1;
2421 		break;
2422 	case RPZ_PASSTHRU_ACTION:
2423 		ret = NULL;
2424 		ms->rpz_passthru = 1;
2425 		break;
2426 	case RPZ_CNAME_OVERRIDE_ACTION:
2427 		ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
2428 		ms->rpz_applied = 1;
2429 		break;
2430 	default:
2431 		verbose(VERB_ALGO, "rpz: nsdname: bug: unhandled or invalid action: '%s'",
2432 			rpz_action_to_string(action));
2433 		ret = NULL;
2434 	}
2435 
2436 	if(r->log)
2437 		log_rpz_apply("nsdname", match->dname, NULL,
2438 			action, &ms->qinfo, NULL, ms, r->log_name);
2439 	if(ms->env->worker)
2440 		ms->env->worker->stats.rpz_action[action]++;
2441 	lock_rw_unlock(&z->lock);
2442 	return ret;
2443 }
2444 
2445 static struct local_zone*
rpz_delegation_point_zone_lookup(struct delegpt * dp,struct local_zones * zones,uint16_t qclass,struct matched_delegation_point * match)2446 rpz_delegation_point_zone_lookup(struct delegpt* dp, struct local_zones* zones,
2447 	uint16_t qclass,
2448 	/* output parameter */
2449 	struct matched_delegation_point* match)
2450 {
2451 	struct delegpt_ns* nameserver;
2452 	struct local_zone* z = NULL;
2453 
2454 	/* the rpz specs match the nameserver names (NS records), not the
2455 	 * name of the delegation point itself, to the nsdname triggers */
2456 	for(nameserver = dp->nslist;
2457 	    nameserver != NULL;
2458 	    nameserver = nameserver->next) {
2459 		z = rpz_find_zone(zones, nameserver->name, nameserver->namelen,
2460 				  qclass, 0, 0, 0);
2461 		if(z != NULL) {
2462 			match->dname = nameserver->name;
2463 			match->dname_len = nameserver->namelen;
2464 			if(verbosity >= VERB_ALGO) {
2465 				char nm[LDNS_MAX_DOMAINLEN];
2466 				char zn[LDNS_MAX_DOMAINLEN];
2467 				dname_str(match->dname, nm);
2468 				dname_str(z->name, zn);
2469 				if(strcmp(nm, zn) != 0)
2470 					verbose(VERB_ALGO, "rpz: trigger nsdname %s on %s action=%s",
2471 						zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type)));
2472 				else
2473 					verbose(VERB_ALGO, "rpz: trigger nsdname %s action=%s",
2474 						nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type)));
2475 			}
2476 			break;
2477 		}
2478 	}
2479 
2480 	return z;
2481 }
2482 
2483 struct dns_msg*
rpz_callback_from_iterator_module(struct module_qstate * ms,struct iter_qstate * is)2484 rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate* is)
2485 {
2486 	struct auth_zones* az;
2487 	struct auth_zone* a;
2488 	struct dns_msg* ret = NULL;
2489 	struct clientip_synthesized_rr* raddr = NULL;
2490 	struct rpz* r = NULL;
2491 	struct local_zone* z = NULL;
2492 	struct matched_delegation_point match = {0};
2493 
2494 	if(ms->rpz_passthru) {
2495 		verbose(VERB_ALGO, "query is rpz_passthru, no further processing");
2496 		return NULL;
2497 	}
2498 
2499 	if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
2500 
2501 	az = ms->env->auth_zones;
2502 	lock_rw_rdlock(&az->rpz_lock);
2503 
2504 	verbose(VERB_ALGO, "rpz: iterator module callback: have_rpz=%d", az->rpz_first != NULL);
2505 
2506 	/* precedence of RPZ works, loosely, like this:
2507 	 * CNAMEs in order of the CNAME chain. rpzs in the order they are
2508 	 * configured. In an RPZ: first client-IP addr, then QNAME, then
2509 	 * response IP, then NSDNAME, then NSIP. Longest match first. Smallest
2510 	 * one from a set. */
2511 	/* we use the precedence rules for the topics and triggers that
2512 	 * are pertinent at this stage of the resolve processing */
2513 	for(a = az->rpz_first; a != NULL; a = a->rpz_az_next) {
2514 		lock_rw_rdlock(&a->lock);
2515 		r = a->rpz;
2516 		if(r->disabled) {
2517 			lock_rw_unlock(&a->lock);
2518 			continue;
2519 		}
2520 		if(r->taglist && (!ms->client_info ||
2521 			!taglist_intersect(r->taglist, r->taglistlen,
2522 				ms->client_info->taglist,
2523 				ms->client_info->taglen))) {
2524 			lock_rw_unlock(&a->lock);
2525 			continue;
2526 		}
2527 
2528 		/* the nsdname has precedence over the nsip triggers */
2529 		z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
2530 						     is->qchase.qclass, &match);
2531 		if(z != NULL) {
2532 			break;
2533 		}
2534 
2535 		raddr = rpz_delegation_point_ipbased_trigger_lookup(r, is);
2536 		if(raddr != NULL) {
2537 			break;
2538 		}
2539 		lock_rw_unlock(&a->lock);
2540 	}
2541 
2542 	lock_rw_unlock(&az->rpz_lock);
2543 
2544 	if(raddr == NULL && z == NULL)
2545 		return NULL;
2546 
2547 	if(raddr != NULL) {
2548 		if(z) {
2549 			lock_rw_unlock(&z->lock);
2550 		}
2551 		ret = rpz_apply_nsip_trigger(ms, &is->qchase, r, raddr, a);
2552 	} else {
2553 		ret = rpz_apply_nsdname_trigger(ms, &is->qchase, r, z, &match, a);
2554 	}
2555 	lock_rw_unlock(&a->lock);
2556 	return ret;
2557 }
2558 
rpz_callback_from_iterator_cname(struct module_qstate * ms,struct iter_qstate * is)2559 struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
2560 	struct iter_qstate* is)
2561 {
2562 	struct auth_zones* az;
2563 	struct auth_zone* a = NULL;
2564 	struct rpz* r = NULL;
2565 	struct local_zone* z = NULL;
2566 	enum localzone_type lzt;
2567 	struct dns_msg* ret = NULL;
2568 
2569 	if(ms->rpz_passthru) {
2570 		verbose(VERB_ALGO, "query is rpz_passthru, no further processing");
2571 		return NULL;
2572 	}
2573 
2574 	if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
2575 	az = ms->env->auth_zones;
2576 
2577 	lock_rw_rdlock(&az->rpz_lock);
2578 
2579 	for(a = az->rpz_first; a; a = a->rpz_az_next) {
2580 		lock_rw_rdlock(&a->lock);
2581 		r = a->rpz;
2582 		if(r->disabled) {
2583 			lock_rw_unlock(&a->lock);
2584 			continue;
2585 		}
2586 		if(r->taglist && (!ms->client_info ||
2587 			!taglist_intersect(r->taglist, r->taglistlen,
2588 				ms->client_info->taglist,
2589 				ms->client_info->taglen))) {
2590 			lock_rw_unlock(&a->lock);
2591 			continue;
2592 		}
2593 		z = rpz_find_zone(r->local_zones, is->qchase.qname,
2594 			is->qchase.qname_len, is->qchase.qclass, 0, 0, 0);
2595 		if(z && r->action_override == RPZ_DISABLED_ACTION) {
2596 			if(r->log)
2597 				log_rpz_apply("qname", z->name, NULL,
2598 					r->action_override,
2599 					&ms->qinfo, NULL, ms, r->log_name);
2600 			if(ms->env->worker)
2601 				ms->env->worker->stats.rpz_action[r->action_override]++;
2602 			lock_rw_unlock(&z->lock);
2603 			z = NULL;
2604 		}
2605 		if(z) {
2606 			break;
2607 		}
2608 		/* not found in this auth_zone */
2609 		lock_rw_unlock(&a->lock);
2610 	}
2611 	lock_rw_unlock(&az->rpz_lock);
2612 
2613 	if(z == NULL)
2614 		return NULL;
2615 	if(r->action_override == RPZ_NO_OVERRIDE_ACTION) {
2616 		lzt = z->type;
2617 	} else {
2618 		lzt = rpz_action_to_localzone_type(r->action_override);
2619 	}
2620 
2621 	if(verbosity >= VERB_ALGO) {
2622 		char nm[LDNS_MAX_DOMAINLEN], zn[LDNS_MAX_DOMAINLEN];
2623 		dname_str(is->qchase.qname, nm);
2624 		dname_str(z->name, zn);
2625 		if(strcmp(zn, nm) != 0)
2626 			verbose(VERB_ALGO, "rpz: qname trigger %s on %s, with action=%s",
2627 				zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2628 		else
2629 			verbose(VERB_ALGO, "rpz: qname trigger %s, with action=%s",
2630 				nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2631 	}
2632 	switch(localzone_type_to_rpz_action(lzt)) {
2633 	case RPZ_NXDOMAIN_ACTION:
2634 		ret = rpz_synthesize_nxdomain(r, ms, &is->qchase, a);
2635 		ms->rpz_applied = 1;
2636 		break;
2637 	case RPZ_NODATA_ACTION:
2638 		ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
2639 		ms->rpz_applied = 1;
2640 		break;
2641 	case RPZ_TCP_ONLY_ACTION:
2642 		/* basically a passthru here but the tcp-only will be
2643 		 * honored before the query gets sent. */
2644 		ms->tcp_required = 1;
2645 		ret = NULL;
2646 		break;
2647 	case RPZ_DROP_ACTION:
2648 		ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
2649 		ms->rpz_applied = 1;
2650 		ms->is_drop = 1;
2651 		break;
2652 	case RPZ_LOCAL_DATA_ACTION:
2653 		ret = rpz_synthesize_qname_localdata_msg(r, ms, &is->qchase, z, a);
2654 		if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); }
2655 		ms->rpz_applied = 1;
2656 		break;
2657 	case RPZ_PASSTHRU_ACTION:
2658 		ret = NULL;
2659 		ms->rpz_passthru = 1;
2660 		break;
2661 	default:
2662 		verbose(VERB_ALGO, "rpz: qname trigger: bug: unhandled or invalid action: '%s'",
2663 			rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2664 		ret = NULL;
2665 	}
2666 	if(r->log)
2667 		log_rpz_apply("qname", (z?z->name:NULL), NULL,
2668 			localzone_type_to_rpz_action(lzt),
2669 			&is->qchase, NULL, ms, r->log_name);
2670 	lock_rw_unlock(&z->lock);
2671 	lock_rw_unlock(&a->lock);
2672 	return ret;
2673 }
2674 
2675 static int
rpz_apply_maybe_clientip_trigger(struct auth_zones * az,struct module_env * env,struct query_info * qinfo,struct edns_data * edns,struct comm_reply * repinfo,uint8_t * taglist,size_t taglen,struct ub_server_stats * stats,sldns_buffer * buf,struct regional * temp,struct local_zone ** z_out,struct auth_zone ** a_out,struct rpz ** r_out,int * passthru)2676 rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
2677 	struct query_info* qinfo, struct edns_data* edns, struct comm_reply* repinfo,
2678 	uint8_t* taglist, size_t taglen, struct ub_server_stats* stats,
2679 	sldns_buffer* buf, struct regional* temp,
2680 	/* output parameters */
2681 	struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out,
2682 	int* passthru)
2683 {
2684 	int ret = 0;
2685 	enum rpz_action client_action;
2686 	struct clientip_synthesized_rr* node = rpz_resolve_client_action_and_zone(
2687 		az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out);
2688 
2689 	client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action);
2690 	if(node != NULL && *r_out &&
2691 		(*r_out)->action_override != RPZ_NO_OVERRIDE_ACTION) {
2692 		client_action = (*r_out)->action_override;
2693 	}
2694 	if(client_action == RPZ_PASSTHRU_ACTION) {
2695 		if(*r_out && (*r_out)->log)
2696 			log_rpz_apply(
2697 				(node?"clientip":"qname"),
2698 				((*z_out)?(*z_out)->name:NULL),
2699 				(node?&node->node:NULL),
2700 				client_action, qinfo, repinfo, NULL,
2701 				(*r_out)->log_name);
2702 		*passthru = 1;
2703 		ret = 0;
2704 		goto done;
2705 	}
2706 	if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
2707 			      client_action != RPZ_PASSTHRU_ACTION)) {
2708 		if(client_action == RPZ_PASSTHRU_ACTION
2709 			|| client_action == RPZ_INVALID_ACTION
2710 			|| (client_action == RPZ_TCP_ONLY_ACTION
2711 				&& !rpz_is_udp_query(repinfo))) {
2712 			ret = 0;
2713 			goto done;
2714 		}
2715 		stats->rpz_action[client_action]++;
2716 		if(client_action == RPZ_LOCAL_DATA_ACTION) {
2717 			rpz_apply_clientip_localdata_action(node, env, qinfo,
2718 				edns, repinfo, buf, temp, *a_out);
2719 			ret = 1;
2720 		} else if(client_action == RPZ_CNAME_OVERRIDE_ACTION) {
2721 			if(!rpz_apply_cname_override_action(*r_out, qinfo,
2722 				temp)) {
2723 				ret = 0;
2724 				goto done;
2725 			}
2726 			ret = 0;
2727 		} else {
2728 			local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns,
2729 				repinfo, buf, temp, 0 /* no local data used */,
2730 				rpz_action_to_localzone_type(client_action));
2731 			if(*r_out && (*r_out)->signal_nxdomain_ra &&
2732 				LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
2733 				== LDNS_RCODE_NXDOMAIN)
2734 				LDNS_RA_CLR(sldns_buffer_begin(buf));
2735 			ret = 1;
2736 		}
2737 		if(*r_out && (*r_out)->log)
2738 			log_rpz_apply(
2739 				(node?"clientip":"qname"),
2740 				((*z_out)?(*z_out)->name:NULL),
2741 				(node?&node->node:NULL),
2742 				client_action, qinfo, repinfo, NULL,
2743 				(*r_out)->log_name);
2744 		goto done;
2745 	}
2746 	ret = -1;
2747 done:
2748 	if(node != NULL) {
2749 		lock_rw_unlock(&node->lock);
2750 	}
2751 	return ret;
2752 }
2753 
2754 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,int * passthru)2755 rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
2756 	struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
2757 	struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist,
2758 	size_t taglen, struct ub_server_stats* stats, int* passthru)
2759 {
2760 	struct rpz* r = NULL;
2761 	struct auth_zone* a = NULL;
2762 	struct local_zone* z = NULL;
2763 	int ret;
2764 	enum localzone_type lzt;
2765 
2766 	int clientip_trigger = rpz_apply_maybe_clientip_trigger(az, env, qinfo,
2767 		edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r,
2768 		passthru);
2769 	if(clientip_trigger >= 0) {
2770 		if(a) {
2771 			lock_rw_unlock(&a->lock);
2772 		}
2773 		if(z) {
2774 			lock_rw_unlock(&z->lock);
2775 		}
2776 		return clientip_trigger;
2777 	}
2778 
2779 	if(z == NULL) {
2780 		if(a) {
2781 			lock_rw_unlock(&a->lock);
2782 		}
2783 		return 0;
2784 	}
2785 
2786 	log_assert(r);
2787 
2788 	if(r->action_override == RPZ_NO_OVERRIDE_ACTION) {
2789 		lzt = z->type;
2790 	} else {
2791 		lzt = rpz_action_to_localzone_type(r->action_override);
2792 	}
2793 	if(r->action_override == RPZ_PASSTHRU_ACTION ||
2794 		lzt == local_zone_always_transparent /* RPZ_PASSTHRU_ACTION */) {
2795 		*passthru = 1;
2796 	}
2797 
2798 	if(verbosity >= VERB_ALGO) {
2799 		char nm[LDNS_MAX_DOMAINLEN], zn[LDNS_MAX_DOMAINLEN];
2800 		dname_str(qinfo->qname, nm);
2801 		dname_str(z->name, zn);
2802 		if(strcmp(zn, nm) != 0)
2803 			verbose(VERB_ALGO, "rpz: qname trigger %s on %s with action=%s",
2804 				zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2805 		else
2806 			verbose(VERB_ALGO, "rpz: qname trigger %s with action=%s",
2807 				nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2808 	}
2809 
2810 	ret = rpz_synthesize_qname_localdata(env, r, z, lzt, qinfo, edns, buf, temp,
2811 					     repinfo, stats);
2812 
2813 	lock_rw_unlock(&z->lock);
2814 	lock_rw_unlock(&a->lock);
2815 
2816 	return ret;
2817 }
2818 
rpz_enable(struct rpz * r)2819 void rpz_enable(struct rpz* r)
2820 {
2821     if(!r)
2822         return;
2823     r->disabled = 0;
2824 }
2825 
rpz_disable(struct rpz * r)2826 void rpz_disable(struct rpz* r)
2827 {
2828     if(!r)
2829         return;
2830     r->disabled = 1;
2831 }
2832 
2833 /** Get memory usage for clientip_synthesized_rrset. Ignores memory usage
2834  * of locks. */
2835 static size_t
rpz_clientip_synthesized_set_get_mem(struct clientip_synthesized_rrset * set)2836 rpz_clientip_synthesized_set_get_mem(struct clientip_synthesized_rrset* set)
2837 {
2838 	size_t m = sizeof(*set);
2839 	lock_rw_rdlock(&set->lock);
2840 	m += regional_get_mem(set->region);
2841 	lock_rw_unlock(&set->lock);
2842 	return m;
2843 }
2844 
rpz_get_mem(struct rpz * r)2845 size_t rpz_get_mem(struct rpz* r)
2846 {
2847 	size_t m = sizeof(*r);
2848 	if(r->taglist)
2849 		m += r->taglistlen;
2850 	if(r->log_name)
2851 		m += strlen(r->log_name) + 1;
2852 	m += regional_get_mem(r->region);
2853 	m += local_zones_get_mem(r->local_zones);
2854 	m += local_zones_get_mem(r->nsdname_zones);
2855 	m += respip_set_get_mem(r->respip_set);
2856 	m += rpz_clientip_synthesized_set_get_mem(r->client_set);
2857 	m += rpz_clientip_synthesized_set_get_mem(r->ns_set);
2858 	return m;
2859 }
2860