xref: /freebsd/contrib/unbound/services/rpz.c (revision 50caa0ea0c16499c40e785b5aa37053b180b2830)
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 			free(dname);
725 			lock_rw_unlock(&lz->lock);
726 			return;
727 		}
728 		lock_rw_wrlock(&z->lock);
729 		local_zone_enter_rr(z, dname, dnamelen, dnamelabs, rrtype,
730 				    rrclass, ttl, rdata, rdata_len, rrstr);
731 		lock_rw_unlock(&z->lock);
732 		free(rrstr);
733 	}
734 	if(!newzone) {
735 		free(dname);
736 	}
737 	lock_rw_unlock(&lz->lock);
738 }
739 
740 static void
rpz_log_dname(char const * msg,uint8_t * dname,size_t dname_len)741 rpz_log_dname(char const* msg, uint8_t* dname, size_t dname_len)
742 {
743 	char buf[LDNS_MAX_DOMAINLEN];
744 	(void)dname_len;
745 	dname_str(dname, buf);
746 	verbose(VERB_ALGO, "rpz: %s: <%s>", msg, buf);
747 }
748 
749 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)750 rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
751 	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
752 	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
753 {
754 	if(a == RPZ_INVALID_ACTION) {
755 		verbose(VERB_ALGO, "rpz: skipping invalid action");
756 		free(dname);
757 		return;
758 	}
759 
760 	rpz_insert_local_zones_trigger(r->local_zones, dname, dnamelen, a, rrtype,
761 				       rrclass, ttl, rdata, rdata_len, rr, rr_len);
762 }
763 
764 static int
rpz_strip_nsdname_suffix(uint8_t * dname,size_t maxdnamelen,uint8_t ** stripdname,size_t * stripdnamelen)765 rpz_strip_nsdname_suffix(uint8_t* dname, size_t maxdnamelen,
766 	uint8_t** stripdname, size_t* stripdnamelen)
767 {
768 	uint8_t* tldstart = get_tld_label(dname, maxdnamelen);
769 	uint8_t swap;
770 	if(tldstart == NULL) {
771 		if(dname == NULL) {
772 			*stripdname = NULL;
773 			*stripdnamelen = 0;
774 			return 0;
775 		}
776 		*stripdname = memdup(dname, maxdnamelen);
777 		if(!*stripdname) {
778 			*stripdnamelen = 0;
779 			log_err("malloc failure for rpz strip suffix");
780 			return 0;
781 		}
782 		*stripdnamelen = maxdnamelen;
783 		return 1;
784 	}
785 	/* shorten the domain name briefly,
786 	 * then we allocate a new name with the correct length */
787 	swap = *tldstart;
788 	*tldstart = 0;
789 	(void)dname_count_size_labels(dname, stripdnamelen);
790 	*stripdname = memdup(dname, *stripdnamelen);
791 	*tldstart = swap;
792 	if(!*stripdname) {
793 		*stripdnamelen = 0;
794 		log_err("malloc failure for rpz strip suffix");
795 		return 0;
796 	}
797 	return 1;
798 }
799 
800 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)801 rpz_insert_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
802 	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
803 	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
804 {
805 	uint8_t* dname_stripped = NULL;
806 	size_t dnamelen_stripped = 0;
807 
808 	rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
809 		&dnamelen_stripped);
810 	if(a == RPZ_INVALID_ACTION) {
811 		verbose(VERB_ALGO, "rpz: skipping invalid action");
812 		free(dname_stripped);
813 		return;
814 	}
815 
816 	/* dname_stripped is consumed or freed by the insert routine */
817 	rpz_insert_local_zones_trigger(r->nsdname_zones, dname_stripped,
818 		dnamelen_stripped, a, rrtype, rrclass, ttl, rdata, rdata_len,
819 		rr, rr_len);
820 }
821 
822 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)823 rpz_insert_ipaddr_based_trigger(struct respip_set* set, struct sockaddr_storage* addr,
824 	socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype,
825 	uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len,
826 	uint8_t* rr, size_t rr_len)
827 {
828 	struct resp_addr* node;
829 	char* rrstr;
830 	enum respip_action respa = rpz_action_to_respip_action(a);
831 
832 	lock_rw_wrlock(&set->lock);
833 	rrstr = sldns_wire2str_rr(rr, rr_len);
834 	if(rrstr == NULL) {
835 		log_err("malloc error while inserting rpz ipaddr based trigger");
836 		lock_rw_unlock(&set->lock);
837 		return 0;
838 	}
839 
840 	node = respip_sockaddr_find_or_create(set, addr, addrlen, net, 1, rrstr);
841 	if(node == NULL) {
842 		lock_rw_unlock(&set->lock);
843 		free(rrstr);
844 		return 0;
845 	}
846 
847 	lock_rw_wrlock(&node->lock);
848 	lock_rw_unlock(&set->lock);
849 
850 	node->action = respa;
851 
852 	if(a == RPZ_LOCAL_DATA_ACTION) {
853 		respip_enter_rr(set->region, node, rrtype,
854 				rrclass, ttl, rdata, rdata_len, rrstr, "");
855 	}
856 
857 	lock_rw_unlock(&node->lock);
858 	free(rrstr);
859 	return 1;
860 }
861 
862 static inline struct clientip_synthesized_rr*
rpz_clientip_ensure_entry(struct clientip_synthesized_rrset * set,struct sockaddr_storage * addr,socklen_t addrlen,int net)863 rpz_clientip_ensure_entry(struct clientip_synthesized_rrset* set,
864 	struct sockaddr_storage* addr, socklen_t addrlen, int net)
865 {
866 	int insert_ok;
867 	struct clientip_synthesized_rr* node =
868 		(struct clientip_synthesized_rr*)addr_tree_find(&set->entries,
869 								addr, addrlen, net);
870 
871 	if(node != NULL) { return node; }
872 
873 	/* node does not yet exist => allocate one */
874 	node = regional_alloc_zero(set->region, sizeof(*node));
875 	if(node == NULL) {
876 		log_err("out of memory");
877 		return NULL;
878 	}
879 
880 	lock_rw_init(&node->lock);
881 	node->action = RPZ_INVALID_ACTION;
882 	insert_ok = addr_tree_insert(&set->entries, &node->node,
883 				     addr, addrlen, net);
884 	if (!insert_ok) {
885 		log_warn("rpz: unexpected: unable to insert clientip address node");
886 		/* we can not free the just allocated node.
887 		 * theoretically a memleak */
888 		return NULL;
889 	}
890 
891 	return node;
892 }
893 
894 static void
rpz_report_rrset_error(const char * msg,uint8_t * rr,size_t rr_len)895 rpz_report_rrset_error(const char* msg, uint8_t* rr, size_t rr_len) {
896 	char* rrstr = sldns_wire2str_rr(rr, rr_len);
897 	if(rrstr == NULL) {
898 		log_err("malloc error while inserting rpz clientip based record");
899 		return;
900 	}
901 	log_err("rpz: unexpected: unable to insert %s: %s", msg, rrstr);
902 	free(rrstr);
903 }
904 
905 /* from localzone.c; difference is we don't have a dname */
906 static struct local_rrset*
rpz_clientip_new_rrset(struct regional * region,struct clientip_synthesized_rr * raddr,uint16_t rrtype,uint16_t rrclass)907 rpz_clientip_new_rrset(struct regional* region,
908 	struct clientip_synthesized_rr* raddr, uint16_t rrtype, uint16_t rrclass)
909 {
910 	struct packed_rrset_data* pd;
911 	struct local_rrset* rrset = (struct local_rrset*)
912 		regional_alloc_zero(region, sizeof(*rrset));
913 	if(rrset == NULL) {
914 		log_err("out of memory");
915 		return NULL;
916 	}
917 	rrset->next = raddr->data;
918 	raddr->data = rrset;
919 	rrset->rrset = (struct ub_packed_rrset_key*)
920 		regional_alloc_zero(region, sizeof(*rrset->rrset));
921 	if(rrset->rrset == NULL) {
922 		log_err("out of memory");
923 		return NULL;
924 	}
925 	rrset->rrset->entry.key = rrset->rrset;
926 	pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd));
927 	if(pd == NULL) {
928 		log_err("out of memory");
929 		return NULL;
930 	}
931 	pd->trust = rrset_trust_prim_noglue;
932 	pd->security = sec_status_insecure;
933 	rrset->rrset->entry.data = pd;
934 	rrset->rrset->rk.type = htons(rrtype);
935 	rrset->rrset->rk.rrset_class = htons(rrclass);
936 	rrset->rrset->rk.dname = regional_alloc_zero(region, 1);
937 	if(rrset->rrset->rk.dname == NULL) {
938 		log_err("out of memory");
939 		return NULL;
940 	}
941 	rrset->rrset->rk.dname_len = 1;
942 	return rrset;
943 }
944 
945 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)946 rpz_clientip_enter_rr(struct regional* region, struct clientip_synthesized_rr* raddr,
947 	uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata,
948 	size_t rdata_len)
949 {
950 	struct local_rrset* rrset;
951 	if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data != NULL) {
952 		log_err("CNAME response-ip data can not co-exist with other "
953 			"client-ip data");
954 		return 0;
955 	}
956 
957 	rrset = rpz_clientip_new_rrset(region, raddr, rrtype, rrclass);
958 	if(raddr->data == NULL) {
959 		return 0;
960 	}
961 
962 	return rrset_insert_rr(region, rrset->rrset->entry.data, rdata, rdata_len, ttl, "");
963 }
964 
965 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)966 rpz_clientip_insert_trigger_rr(struct clientip_synthesized_rrset* set, struct sockaddr_storage* addr,
967 	socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype,
968 	uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len,
969 	uint8_t* rr, size_t rr_len)
970 {
971 	struct clientip_synthesized_rr* node;
972 
973 	lock_rw_wrlock(&set->lock);
974 
975 	node = rpz_clientip_ensure_entry(set, addr, addrlen, net);
976 	if(node == NULL) {
977 		lock_rw_unlock(&set->lock);
978 		rpz_report_rrset_error("client ip address", rr, rr_len);
979 		return 0;
980 	}
981 
982 	lock_rw_wrlock(&node->lock);
983 	lock_rw_unlock(&set->lock);
984 
985 	node->action = a;
986 	if(a == RPZ_LOCAL_DATA_ACTION) {
987 		if(!rpz_clientip_enter_rr(set->region, node, rrtype,
988 			rrclass, ttl, rdata, rdata_len)) {
989 			verbose(VERB_ALGO, "rpz: unable to insert clientip rr");
990 			lock_rw_unlock(&node->lock);
991 			return 0;
992 		}
993 
994 	}
995 
996 	lock_rw_unlock(&node->lock);
997 
998 	return 1;
999 }
1000 
1001 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)1002 rpz_insert_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1003 	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
1004 	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
1005 {
1006 	struct sockaddr_storage addr;
1007 	socklen_t addrlen;
1008 	int net, af;
1009 
1010 	if(a == RPZ_INVALID_ACTION) {
1011 		return 0;
1012 	}
1013 
1014 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
1015 		verbose(VERB_ALGO, "rpz: unable to parse client ip");
1016 		return 0;
1017 	}
1018 
1019 	return rpz_clientip_insert_trigger_rr(r->client_set, &addr, addrlen, net,
1020 			a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
1021 }
1022 
1023 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)1024 rpz_insert_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1025 	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
1026 	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
1027 {
1028 	struct sockaddr_storage addr;
1029 	socklen_t addrlen;
1030 	int net, af;
1031 
1032 	if(a == RPZ_INVALID_ACTION) {
1033 		return 0;
1034 	}
1035 
1036 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
1037 		verbose(VERB_ALGO, "rpz: unable to parse ns ip");
1038 		return 0;
1039 	}
1040 
1041 	return rpz_clientip_insert_trigger_rr(r->ns_set, &addr, addrlen, net,
1042 			a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
1043 }
1044 
1045 /** Insert RR into RPZ's respip_set */
1046 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)1047 rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1048 	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
1049 	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
1050 {
1051 	struct sockaddr_storage addr;
1052 	socklen_t addrlen;
1053 	int net, af;
1054 
1055 	if(a == RPZ_INVALID_ACTION) {
1056 		return 0;
1057 	}
1058 
1059 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
1060 		verbose(VERB_ALGO, "rpz: unable to parse response ip");
1061 		return 0;
1062 	}
1063 
1064 	if(a == RPZ_INVALID_ACTION ||
1065 		rpz_action_to_respip_action(a) == respip_invalid) {
1066 		char str[LDNS_MAX_DOMAINLEN];
1067 		dname_str(dname, str);
1068 		verbose(VERB_ALGO, "rpz: respip trigger, %s skipping unsupported action: %s",
1069 			str, rpz_action_to_string(a));
1070 		return 0;
1071 	}
1072 
1073 	return rpz_insert_ipaddr_based_trigger(r->respip_set, &addr, addrlen, net,
1074 			a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
1075 }
1076 
1077 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)1078 rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
1079 	size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
1080 	uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len)
1081 {
1082 	size_t policydnamelen;
1083 	/* name is free'd in local_zone delete */
1084 	enum rpz_trigger t;
1085 	enum rpz_action a;
1086 	uint8_t* policydname;
1087 
1088 	if(rpz_type_ignored(rr_type)) {
1089 		/* this rpz action is not valid, eg. this is the SOA or NS RR */
1090 		return 1;
1091 	}
1092 	if(!dname_subdomain_c(dname, azname)) {
1093 		char* dname_str = sldns_wire2str_dname(dname, dnamelen);
1094 		char* azname_str = sldns_wire2str_dname(azname, aznamelen);
1095 		if(dname_str && azname_str) {
1096 			log_err("rpz: name of record (%s) to insert into RPZ is not a "
1097 				"subdomain of the configured name of the RPZ zone (%s)",
1098 				dname_str, azname_str);
1099 		} else {
1100 			log_err("rpz: name of record to insert into RPZ is not a "
1101 				"subdomain of the configured name of the RPZ zone");
1102 		}
1103 		free(dname_str);
1104 		free(azname_str);
1105 		return 0;
1106 	}
1107 
1108 	log_assert(dnamelen >= aznamelen);
1109 	if(!(policydname = calloc(1, (dnamelen-aznamelen)+1))) {
1110 		log_err("malloc error while inserting RPZ RR");
1111 		return 0;
1112 	}
1113 
1114 	a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
1115 	if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
1116 		policydname, (dnamelen-aznamelen)+1))) {
1117 		free(policydname);
1118 		return 0;
1119 	}
1120 	t = rpz_dname_to_trigger(policydname, policydnamelen);
1121 	if(t == RPZ_INVALID_TRIGGER) {
1122 		free(policydname);
1123 		verbose(VERB_ALGO, "rpz: skipping invalid trigger");
1124 		return 1;
1125 	}
1126 	if(t == RPZ_QNAME_TRIGGER) {
1127 		/* policydname will be consumed, no free */
1128 		rpz_insert_qname_trigger(r, policydname, policydnamelen,
1129 			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1130 			rr_len);
1131 	} else if(t == RPZ_RESPONSE_IP_TRIGGER) {
1132 		rpz_insert_response_ip_trigger(r, policydname, policydnamelen,
1133 			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1134 			rr_len);
1135 		free(policydname);
1136 	} else if(t == RPZ_CLIENT_IP_TRIGGER) {
1137 		rpz_insert_clientip_trigger(r, policydname, policydnamelen,
1138 			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1139 			rr_len);
1140 		free(policydname);
1141 	} else if(t == RPZ_NSIP_TRIGGER) {
1142 		rpz_insert_nsip_trigger(r, policydname, policydnamelen,
1143 			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1144 			rr_len);
1145 		free(policydname);
1146 	} else if(t == RPZ_NSDNAME_TRIGGER) {
1147 		rpz_insert_nsdname_trigger(r, policydname, policydnamelen,
1148 			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1149 			rr_len);
1150 		free(policydname);
1151 	} else {
1152 		free(policydname);
1153 		verbose(VERB_ALGO, "rpz: skipping unsupported trigger: %s",
1154 			rpz_trigger_to_string(t));
1155 	}
1156 	return 1;
1157 }
1158 
1159 /**
1160  * Find RPZ local-zone by qname.
1161  * @param zones: local-zone tree
1162  * @param qname: qname
1163  * @param qname_len: length of qname
1164  * @param qclass: qclass
1165  * @param only_exact: if 1 only exact (non wildcard) matches are returned
1166  * @param wr: get write lock for local-zone if 1, read lock if 0
1167  * @param zones_keep_lock: if set do not release the r->local_zones lock, this
1168  * 	  makes the caller of this function responsible for releasing the lock.
1169  * @return: NULL or local-zone holding rd or wr lock
1170  */
1171 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)1172 rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint16_t qclass,
1173 	int only_exact, int wr, int zones_keep_lock)
1174 {
1175 	uint8_t* ce;
1176 	size_t ce_len;
1177 	int ce_labs;
1178 	uint8_t wc[LDNS_MAX_DOMAINLEN+1];
1179 	int exact;
1180 	struct local_zone* z = NULL;
1181 
1182 	if(wr) {
1183 		lock_rw_wrlock(&zones->lock);
1184 	} else {
1185 		lock_rw_rdlock(&zones->lock);
1186 	}
1187 	z = local_zones_find_le(zones, qname, qname_len,
1188 		dname_count_labels(qname),
1189 		LDNS_RR_CLASS_IN, &exact);
1190 	if(!z || (only_exact && !exact)) {
1191 		if(!zones_keep_lock) {
1192 			lock_rw_unlock(&zones->lock);
1193 		}
1194 		return NULL;
1195 	}
1196 	if(wr) {
1197 		lock_rw_wrlock(&z->lock);
1198 	} else {
1199 		lock_rw_rdlock(&z->lock);
1200 	}
1201 	if(!zones_keep_lock) {
1202 		lock_rw_unlock(&zones->lock);
1203 	}
1204 
1205 	if(exact)
1206 		return z;
1207 
1208 	/* No exact match found, lookup wildcard. closest encloser must
1209 	 * be the shared parent between the qname and the best local
1210 	 * zone match, append '*' to that and do another lookup. */
1211 
1212 	ce = dname_get_shared_topdomain(z->name, qname);
1213 	if(!ce /* should not happen */) {
1214 		lock_rw_unlock(&z->lock);
1215 		if(zones_keep_lock) {
1216 			lock_rw_unlock(&zones->lock);
1217 		}
1218 		return NULL;
1219 	}
1220 	ce_labs = dname_count_size_labels(ce, &ce_len);
1221 	if(ce_len+2 > sizeof(wc)) {
1222 		lock_rw_unlock(&z->lock);
1223 		if(zones_keep_lock) {
1224 			lock_rw_unlock(&zones->lock);
1225 		}
1226 		return NULL;
1227 	}
1228 	wc[0] = 1; /* length of wildcard label */
1229 	wc[1] = (uint8_t)'*'; /* wildcard label */
1230 	memmove(wc+2, ce, ce_len);
1231 	lock_rw_unlock(&z->lock);
1232 
1233 	if(!zones_keep_lock) {
1234 		if(wr) {
1235 			lock_rw_wrlock(&zones->lock);
1236 		} else {
1237 			lock_rw_rdlock(&zones->lock);
1238 		}
1239 	}
1240 	z = local_zones_find_le(zones, wc,
1241 		ce_len+2, ce_labs+1, qclass, &exact);
1242 	if(!z || !exact) {
1243 		lock_rw_unlock(&zones->lock);
1244 		return NULL;
1245 	}
1246 	if(wr) {
1247 		lock_rw_wrlock(&z->lock);
1248 	} else {
1249 		lock_rw_rdlock(&z->lock);
1250 	}
1251 	if(!zones_keep_lock) {
1252 		lock_rw_unlock(&zones->lock);
1253 	}
1254 	return z;
1255 }
1256 
1257 /** Find entry for RR type in the list of rrsets for the clientip. */
1258 static struct local_rrset*
rpz_find_synthesized_rrset(uint16_t qtype,struct clientip_synthesized_rr * data,int alias_ok)1259 rpz_find_synthesized_rrset(uint16_t qtype,
1260 	struct clientip_synthesized_rr* data, int alias_ok)
1261 {
1262 	struct local_rrset* cursor = data->data, *cname = NULL;
1263 	while( cursor != NULL) {
1264 		struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
1265 		if(htons(qtype) == packed_rrset->type) {
1266 			return cursor;
1267 		}
1268 		if(ntohs(packed_rrset->type) == LDNS_RR_TYPE_CNAME && alias_ok)
1269 			cname = cursor;
1270 		cursor = cursor->next;
1271 	}
1272 	if(alias_ok)
1273 		return cname;
1274 	return NULL;
1275 }
1276 
1277 /**
1278  * Remove RR from RPZ's local-data
1279  * @param z: local-zone for RPZ, holding write lock
1280  * @param policydname: dname of RR to remove
1281  * @param policydnamelen: length of policydname
1282  * @param rr_type: RR type of RR to remove
1283  * @param rdata: rdata of RR to remove
1284  * @param rdatalen: length of rdata
1285  * @return: 1 if zone must be removed after RR deletion
1286  */
1287 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)1288 rpz_data_delete_rr(struct local_zone* z, uint8_t* policydname,
1289 	size_t policydnamelen, uint16_t rr_type, uint8_t* rdata,
1290 	size_t rdatalen)
1291 {
1292 	struct local_data* ld;
1293 	struct packed_rrset_data* d;
1294 	size_t index;
1295 	ld = local_zone_find_data(z, policydname, policydnamelen,
1296 		dname_count_labels(policydname));
1297 	if(ld) {
1298 		struct local_rrset* prev=NULL, *p=ld->rrsets;
1299 		while(p && ntohs(p->rrset->rk.type) != rr_type) {
1300 			prev = p;
1301 			p = p->next;
1302 		}
1303 		if(!p)
1304 			return 0;
1305 		d = (struct packed_rrset_data*)p->rrset->entry.data;
1306 		if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
1307 			if(d->count == 1) {
1308 				/* no memory recycling for zone deletions ... */
1309 				if(prev) prev->next = p->next;
1310 				else ld->rrsets = p->next;
1311 			}
1312 			if(d->count > 1) {
1313 				if(!local_rrset_remove_rr(d, index))
1314 					return 0;
1315 			}
1316 		}
1317 	}
1318 	if(ld && ld->rrsets)
1319 		return 0;
1320 	return 1;
1321 }
1322 
1323 /**
1324  * Remove RR from RPZ's respip set
1325  * @param raddr: respip node
1326  * @param rr_type: RR type of RR to remove
1327  * @param rdata: rdata of RR to remove
1328  * @param rdatalen: length of rdata
1329  * @return: 1 if zone must be removed after RR deletion
1330  */
1331 static int
rpz_rrset_delete_rr(struct resp_addr * raddr,uint16_t rr_type,uint8_t * rdata,size_t rdatalen)1332 rpz_rrset_delete_rr(struct resp_addr* raddr, uint16_t rr_type, uint8_t* rdata,
1333 	size_t rdatalen)
1334 {
1335 	size_t index;
1336 	struct packed_rrset_data* d;
1337 	if(!raddr->data)
1338 		return 1;
1339 	d = raddr->data->entry.data;
1340 	if(ntohs(raddr->data->rk.type) != rr_type) {
1341 		return 0;
1342 	}
1343 	if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
1344 		if(d->count == 1) {
1345 			/* regional alloc'd */
1346 			raddr->data->entry.data = NULL;
1347 			raddr->data = NULL;
1348 			return 1;
1349 		}
1350 		if(d->count > 1) {
1351 			if(!local_rrset_remove_rr(d, index))
1352 				return 0;
1353 		}
1354 	}
1355 	return 0;
1356 
1357 }
1358 
1359 /** Remove RR from rpz localzones structure */
1360 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)1361 rpz_remove_local_zones_trigger(struct local_zones* zones, uint8_t* dname,
1362 	size_t dnamelen, enum rpz_action a, uint16_t rr_type,
1363 	uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen)
1364 {
1365 	struct local_zone* z;
1366 	int delete_zone = 1;
1367 	z = rpz_find_zone(zones, dname, dnamelen, rr_class,
1368 		1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/);
1369 	if(!z) {
1370 		verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1371 			"RPZ domain not found");
1372 		return;
1373 	}
1374 	if(a == RPZ_LOCAL_DATA_ACTION)
1375 		delete_zone = rpz_data_delete_rr(z, dname,
1376 			dnamelen, rr_type, rdatawl, rdatalen);
1377 	else if(a != localzone_type_to_rpz_action(z->type)) {
1378 		lock_rw_unlock(&z->lock);
1379 		lock_rw_unlock(&zones->lock);
1380 		return;
1381 	}
1382 	lock_rw_unlock(&z->lock);
1383 	if(delete_zone) {
1384 		local_zones_del_zone(zones, z);
1385 	}
1386 	lock_rw_unlock(&zones->lock);
1387 }
1388 
1389 /** Remove RR from RPZ's local-zone */
1390 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)1391 rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1392 	enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
1393 	uint8_t* rdatawl, size_t rdatalen)
1394 {
1395 	rpz_remove_local_zones_trigger(r->local_zones, dname, dnamelen,
1396 		a, rr_type, rr_class, rdatawl, rdatalen);
1397 }
1398 
1399 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)1400 rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1401 	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1402 {
1403 	struct resp_addr* node;
1404 	struct sockaddr_storage addr;
1405 	socklen_t addrlen;
1406 	int net, af;
1407 	int delete_respip = 1;
1408 
1409 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1410 		return;
1411 
1412 	lock_rw_wrlock(&r->respip_set->lock);
1413 	if(!(node = (struct resp_addr*)addr_tree_find(
1414 		&r->respip_set->ip_tree, &addr, addrlen, net))) {
1415 		verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1416 			"RPZ domain not found");
1417 		lock_rw_unlock(&r->respip_set->lock);
1418 		return;
1419 	}
1420 
1421 	lock_rw_wrlock(&node->lock);
1422 	if(a == RPZ_LOCAL_DATA_ACTION) {
1423 		/* remove RR, signal whether RR can be removed */
1424 		delete_respip = rpz_rrset_delete_rr(node, rr_type, rdatawl,
1425 			rdatalen);
1426 	}
1427 	lock_rw_unlock(&node->lock);
1428 	if(delete_respip)
1429 		respip_sockaddr_delete(r->respip_set, node);
1430 	lock_rw_unlock(&r->respip_set->lock);
1431 }
1432 
1433 /** find and remove type from list of local_rrset entries*/
1434 static void
del_local_rrset_from_list(struct local_rrset ** list_head,uint16_t dtype)1435 del_local_rrset_from_list(struct local_rrset** list_head, uint16_t dtype)
1436 {
1437 	struct local_rrset* prev=NULL, *p=*list_head;
1438 	while(p && ntohs(p->rrset->rk.type) != dtype) {
1439 		prev = p;
1440 		p = p->next;
1441 	}
1442 	if(!p)
1443 		return; /* rrset type not found */
1444 	/* unlink it */
1445 	if(prev) prev->next = p->next;
1446 	else *list_head = p->next;
1447 	/* no memory recycling for zone deletions ... */
1448 }
1449 
1450 /** Delete client-ip trigger RR from its RRset and perhaps also the rrset
1451  * from the linked list. Returns if the local data is empty and the node can
1452  * be deleted too, or not. */
rpz_remove_clientip_rr(struct clientip_synthesized_rr * node,uint16_t rr_type,uint8_t * rdatawl,size_t rdatalen)1453 static int rpz_remove_clientip_rr(struct clientip_synthesized_rr* node,
1454 	uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1455 {
1456 	struct local_rrset* rrset;
1457 	struct packed_rrset_data* d;
1458 	size_t index;
1459 	rrset = rpz_find_synthesized_rrset(rr_type, node, 0);
1460 	if(rrset == NULL)
1461 		return 0; /* type not found, ignore */
1462 	d = (struct packed_rrset_data*)rrset->rrset->entry.data;
1463 	if(!packed_rrset_find_rr(d, rdatawl, rdatalen, &index))
1464 		return 0; /* RR not found, ignore */
1465 	if(d->count == 1) {
1466 		/* regional alloc'd */
1467 		/* delete the type entry from the list */
1468 		del_local_rrset_from_list(&node->data, rr_type);
1469 		/* if the list is empty, the node can be removed too */
1470 		if(node->data == NULL)
1471 			return 1;
1472 	} else if (d->count > 1) {
1473 		if(!local_rrset_remove_rr(d, index))
1474 			return 0;
1475 	}
1476 	return 0;
1477 }
1478 
1479 /** remove trigger RR from clientip_syntheized set tree. */
1480 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)1481 rpz_clientip_remove_trigger_rr(struct clientip_synthesized_rrset* set,
1482 	struct sockaddr_storage* addr, socklen_t addrlen, int net,
1483 	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1484 {
1485 	struct clientip_synthesized_rr* node;
1486 	int delete_node = 1;
1487 
1488 	lock_rw_wrlock(&set->lock);
1489 	node = (struct clientip_synthesized_rr*)addr_tree_find(&set->entries,
1490 		addr, addrlen, net);
1491 	if(node == NULL) {
1492 		/* netblock not found */
1493 		verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1494 			"RPZ address, netblock not found");
1495 		lock_rw_unlock(&set->lock);
1496 		return;
1497 	}
1498 	lock_rw_wrlock(&node->lock);
1499 	if(a == RPZ_LOCAL_DATA_ACTION) {
1500 		/* remove RR, signal whether entry can be removed */
1501 		delete_node = rpz_remove_clientip_rr(node, rr_type, rdatawl,
1502 			rdatalen);
1503 	} else if(a != node->action) {
1504 		/* ignore the RR with different action specification */
1505 		delete_node = 0;
1506 	}
1507 	if(delete_node) {
1508 		rbtree_delete(&set->entries, node->node.node.key);
1509 	}
1510 	lock_rw_unlock(&set->lock);
1511 	lock_rw_unlock(&node->lock);
1512 	if(delete_node) {
1513 		lock_rw_destroy(&node->lock);
1514 	}
1515 }
1516 
1517 /** Remove clientip trigger RR from RPZ. */
1518 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)1519 rpz_remove_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1520 	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1521 {
1522 	struct sockaddr_storage addr;
1523 	socklen_t addrlen;
1524 	int net, af;
1525 	if(a == RPZ_INVALID_ACTION)
1526 		return;
1527 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1528 		return;
1529 	rpz_clientip_remove_trigger_rr(r->client_set, &addr, addrlen, net,
1530 		a, rr_type, rdatawl, rdatalen);
1531 }
1532 
1533 /** Remove nsip trigger RR from RPZ. */
1534 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)1535 rpz_remove_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1536 	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1537 {
1538 	struct sockaddr_storage addr;
1539 	socklen_t addrlen;
1540 	int net, af;
1541 	if(a == RPZ_INVALID_ACTION)
1542 		return;
1543 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1544 		return;
1545 	rpz_clientip_remove_trigger_rr(r->ns_set, &addr, addrlen, net,
1546 		a, rr_type, rdatawl, rdatalen);
1547 }
1548 
1549 /** Remove nsdname trigger RR from RPZ. */
1550 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)1551 rpz_remove_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1552 	enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
1553 	uint8_t* rdatawl, size_t rdatalen)
1554 {
1555 	uint8_t* dname_stripped = NULL;
1556 	size_t dnamelen_stripped = 0;
1557 	if(a == RPZ_INVALID_ACTION)
1558 		return;
1559 	if(!rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
1560 		&dnamelen_stripped))
1561 		return;
1562 	rpz_remove_local_zones_trigger(r->nsdname_zones, dname_stripped,
1563 		dnamelen_stripped, a, rr_type, rr_class, rdatawl, rdatalen);
1564 	free(dname_stripped);
1565 }
1566 
1567 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)1568 rpz_remove_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
1569 	size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl,
1570 	size_t rdatalen)
1571 {
1572 	size_t policydnamelen;
1573 	enum rpz_trigger t;
1574 	enum rpz_action a;
1575 	uint8_t* policydname;
1576 
1577 	if(rpz_type_ignored(rr_type)) {
1578 		/* this rpz action is not valid, eg. this is the SOA or NS RR */
1579 		return;
1580 	}
1581 	if(!dname_subdomain_c(dname, azname)) {
1582 		/* not subdomain of the RPZ zone. */
1583 		return;
1584 	}
1585 
1586 	if(!(policydname = calloc(1, LDNS_MAX_DOMAINLEN + 1)))
1587 		return;
1588 
1589 	a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
1590 	if(a == RPZ_INVALID_ACTION) {
1591 		free(policydname);
1592 		return;
1593 	}
1594 	if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
1595 		policydname, LDNS_MAX_DOMAINLEN + 1))) {
1596 		free(policydname);
1597 		return;
1598 	}
1599 	t = rpz_dname_to_trigger(policydname, policydnamelen);
1600 	if(t == RPZ_INVALID_TRIGGER) {
1601 		/* skipping invalid trigger */
1602 		free(policydname);
1603 		return;
1604 	}
1605 	if(t == RPZ_QNAME_TRIGGER) {
1606 		rpz_remove_qname_trigger(r, policydname, policydnamelen, a,
1607 			rr_type, rr_class, rdatawl, rdatalen);
1608 	} else if(t == RPZ_RESPONSE_IP_TRIGGER) {
1609 		rpz_remove_response_ip_trigger(r, policydname, policydnamelen,
1610 			a, rr_type, rdatawl, rdatalen);
1611 	} else if(t == RPZ_CLIENT_IP_TRIGGER) {
1612 		rpz_remove_clientip_trigger(r, policydname, policydnamelen, a,
1613 			rr_type, rdatawl, rdatalen);
1614 	} else if(t == RPZ_NSIP_TRIGGER) {
1615 		rpz_remove_nsip_trigger(r, policydname, policydnamelen, a,
1616 			rr_type, rdatawl, rdatalen);
1617 	} else if(t == RPZ_NSDNAME_TRIGGER) {
1618 		rpz_remove_nsdname_trigger(r, policydname, policydnamelen, a,
1619 			rr_type, rr_class, rdatawl, rdatalen);
1620 	}
1621 	/* else it was an unsupported trigger, also skipped. */
1622 	free(policydname);
1623 }
1624 
1625 /** print log information for an applied RPZ policy. Based on local-zone's
1626  * lz_inform_print().
1627  * The repinfo contains the reply address. If it is NULL, the module
1628  * state is used to report the first IP address (if any).
1629  * The dname is used, for the applied rpz, if NULL, addrnode is used.
1630  */
1631 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)1632 log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode,
1633 	enum rpz_action a, struct query_info* qinfo,
1634 	struct comm_reply* repinfo, struct module_qstate* ms, char* log_name)
1635 {
1636 	char ip[128], txt[512], portstr[32];
1637 	char dnamestr[LDNS_MAX_DOMAINLEN];
1638 	uint16_t port = 0;
1639 	if(dname) {
1640 		dname_str(dname, dnamestr);
1641 	} else if(addrnode) {
1642 		char addrbuf[128];
1643 		addr_to_str(&addrnode->addr, addrnode->addrlen, addrbuf, sizeof(addrbuf));
1644 		snprintf(dnamestr, sizeof(dnamestr), "%s/%d", addrbuf, addrnode->net);
1645 	} else {
1646 		dnamestr[0]=0;
1647 	}
1648 	if(repinfo) {
1649 		addr_to_str(&repinfo->client_addr, repinfo->client_addrlen, ip, sizeof(ip));
1650 		port = ntohs(((struct sockaddr_in*)&repinfo->client_addr)->sin_port);
1651 	} else if(ms && ms->mesh_info && ms->mesh_info->reply_list) {
1652 		addr_to_str(&ms->mesh_info->reply_list->query_reply.client_addr,
1653 			ms->mesh_info->reply_list->query_reply.client_addrlen,
1654 			ip, sizeof(ip));
1655 		port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.client_addr)->sin_port);
1656 	} else {
1657 		ip[0]=0;
1658 		port = 0;
1659 	}
1660 	snprintf(portstr, sizeof(portstr), "@%u", (unsigned)port);
1661 	snprintf(txt, sizeof(txt), "rpz: applied %s%s%s%s%s%s %s %s%s",
1662 		(log_name?"[":""), (log_name?log_name:""), (log_name?"] ":""),
1663 		(strcmp(trigger,"qname")==0?"":trigger),
1664 		(strcmp(trigger,"qname")==0?"":" "),
1665 		dnamestr, rpz_action_to_string(a),
1666 		(ip[0]?ip:""), (ip[0]?portstr:""));
1667 	log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
1668 }
1669 
1670 static struct clientip_synthesized_rr*
rpz_ipbased_trigger_lookup(struct clientip_synthesized_rrset * set,struct sockaddr_storage * addr,socklen_t addrlen,char * triggername)1671 rpz_ipbased_trigger_lookup(struct clientip_synthesized_rrset* set,
1672 	struct sockaddr_storage* addr, socklen_t addrlen, char* triggername)
1673 {
1674 	struct clientip_synthesized_rr* raddr = NULL;
1675 	enum rpz_action action = RPZ_INVALID_ACTION;
1676 
1677 	lock_rw_rdlock(&set->lock);
1678 
1679 	raddr = (struct clientip_synthesized_rr*)addr_tree_lookup(&set->entries,
1680 			addr, addrlen);
1681 	if(raddr != NULL) {
1682 		lock_rw_rdlock(&raddr->lock);
1683 		action = raddr->action;
1684 		if(verbosity >= VERB_ALGO) {
1685 			char ip[256], net[256];
1686 			addr_to_str(addr, addrlen, ip, sizeof(ip));
1687 			addr_to_str(&raddr->node.addr, raddr->node.addrlen,
1688 				net, sizeof(net));
1689 			verbose(VERB_ALGO, "rpz: trigger %s %s/%d on %s action=%s",
1690 				triggername, net, raddr->node.net, ip, rpz_action_to_string(action));
1691 		}
1692 	}
1693 	lock_rw_unlock(&set->lock);
1694 
1695 	return raddr;
1696 }
1697 
1698 static inline
1699 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)1700 rpz_resolve_client_action_and_zone(struct auth_zones* az, struct query_info* qinfo,
1701 	struct comm_reply* repinfo, uint8_t* taglist, size_t taglen,
1702 	struct ub_server_stats* stats,
1703 	/* output parameters */
1704 	struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out)
1705 {
1706 	struct clientip_synthesized_rr* node = NULL;
1707 	struct auth_zone* a = NULL;
1708 	struct rpz* r = NULL;
1709 	struct local_zone* z = NULL;
1710 
1711 	lock_rw_rdlock(&az->rpz_lock);
1712 
1713 	for(a = az->rpz_first; a; a = a->rpz_az_next) {
1714 		lock_rw_rdlock(&a->lock);
1715 		r = a->rpz;
1716 		if(r->disabled) {
1717 			lock_rw_unlock(&a->lock);
1718 			continue;
1719 		}
1720 		if(r->taglist && !taglist_intersect(r->taglist,
1721 					r->taglistlen, taglist, taglen)) {
1722 			lock_rw_unlock(&a->lock);
1723 			continue;
1724 		}
1725 		z = rpz_find_zone(r->local_zones, qinfo->qname, qinfo->qname_len,
1726 			qinfo->qclass, 0, 0, 0);
1727 		node = rpz_ipbased_trigger_lookup(r->client_set,
1728 			&repinfo->client_addr, repinfo->client_addrlen,
1729 			"clientip");
1730 		if((z || node) && r->action_override == RPZ_DISABLED_ACTION) {
1731 			if(r->log)
1732 				log_rpz_apply((node?"clientip":"qname"),
1733 					(z?z->name:NULL),
1734 					(node?&node->node:NULL),
1735 					r->action_override,
1736 					qinfo, repinfo, NULL, r->log_name);
1737 			stats->rpz_action[r->action_override]++;
1738 			if(z != NULL) {
1739 				lock_rw_unlock(&z->lock);
1740 				z = NULL;
1741 			}
1742 			if(node != NULL) {
1743 				lock_rw_unlock(&node->lock);
1744 				node = NULL;
1745 			}
1746 		}
1747 		if(z || node) {
1748 			break;
1749 		}
1750 		/* not found in this auth_zone */
1751 		lock_rw_unlock(&a->lock);
1752 	}
1753 
1754 	lock_rw_unlock(&az->rpz_lock);
1755 
1756 	*r_out = r;
1757 	*a_out = a;
1758 	*z_out = z;
1759 
1760 	return node;
1761 }
1762 
1763 static inline int
rpz_is_udp_query(struct comm_reply * repinfo)1764 rpz_is_udp_query(struct comm_reply* repinfo) {
1765 	return repinfo != NULL
1766 			? (repinfo->c != NULL
1767 				? repinfo->c->type == comm_udp
1768 				: 0)
1769 			: 0;
1770 }
1771 
1772 /** encode answer consisting of 1 rrset */
1773 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)1774 rpz_local_encode(struct module_env* env, struct query_info* qinfo,
1775 	struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
1776 	struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec,
1777 	int rcode, struct ub_packed_rrset_key* soa_rrset)
1778 {
1779 	struct reply_info rep;
1780 	uint16_t udpsize;
1781 	struct ub_packed_rrset_key* rrsetlist[3];
1782 
1783 	memset(&rep, 0, sizeof(rep));
1784 	rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode);
1785 	rep.qdcount = 1;
1786 	rep.rrset_count = ansec;
1787 	rep.rrsets = rrsetlist;
1788 	if(ansec > 0) {
1789 		rep.an_numrrsets = 1;
1790 		rep.rrsets[0] = rrset;
1791 		rep.ttl = ((struct packed_rrset_data*)rrset->entry.data)->rr_ttl[0];
1792 	}
1793 	if(soa_rrset != NULL) {
1794 		rep.ar_numrrsets = 1;
1795 		rep.rrsets[rep.rrset_count] = soa_rrset;
1796 		rep.rrset_count ++;
1797 		if(rep.ttl < ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0]) {
1798 			rep.ttl = ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0];
1799 		}
1800 	}
1801 
1802 	udpsize = edns->udp_size;
1803 	edns->edns_version = EDNS_ADVERTISED_VERSION;
1804 	edns->udp_size = EDNS_ADVERTISED_SIZE;
1805 	edns->ext_rcode = 0;
1806 	edns->bits &= EDNS_DO;
1807 	if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns,
1808 		repinfo, temp, env->now_tv) ||
1809 	  !reply_info_answer_encode(qinfo, &rep,
1810 		*(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2),
1811 		buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) {
1812 		error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
1813 			*(uint16_t*)sldns_buffer_begin(buf),
1814 			sldns_buffer_read_u16_at(buf, 2), edns);
1815 	}
1816 
1817 	return 1;
1818 }
1819 
1820 /** allocate SOA record ubrrsetkey in region */
1821 static struct ub_packed_rrset_key*
make_soa_ubrrset(struct auth_zone * auth_zone,struct auth_rrset * soa,struct regional * temp)1822 make_soa_ubrrset(struct auth_zone* auth_zone, struct auth_rrset* soa,
1823 	struct regional* temp)
1824 {
1825 	struct ub_packed_rrset_key csoa;
1826 	if(!soa)
1827 		return NULL;
1828 	memset(&csoa, 0, sizeof(csoa));
1829 	csoa.entry.key = &csoa;
1830 	csoa.rk.rrset_class = htons(LDNS_RR_CLASS_IN);
1831 	csoa.rk.type = htons(LDNS_RR_TYPE_SOA);
1832 	csoa.rk.flags |= PACKED_RRSET_FIXEDTTL
1833 		| PACKED_RRSET_RPZ;
1834 	csoa.rk.dname = auth_zone->name;
1835 	csoa.rk.dname_len = auth_zone->namelen;
1836 	csoa.entry.hash = rrset_key_hash(&csoa.rk);
1837 	csoa.entry.data = soa->data;
1838 	return respip_copy_rrset(&csoa, temp);
1839 }
1840 
1841 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)1842 rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr,
1843 	struct module_env* env, struct query_info* qinfo,
1844 	struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
1845 	struct regional* temp, struct auth_zone* auth_zone)
1846 {
1847 	struct local_rrset* rrset;
1848 	enum rpz_action action = RPZ_INVALID_ACTION;
1849 	struct ub_packed_rrset_key* rp = NULL;
1850 	struct ub_packed_rrset_key* rsoa = NULL;
1851 	int rcode = LDNS_RCODE_NOERROR|BIT_AA;
1852 	int rrset_count = 1;
1853 
1854 	/* prepare synthesized answer for client */
1855 	action = raddr->action;
1856 	if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL ) {
1857 		verbose(VERB_ALGO, "rpz: bug: local-data action but no local data");
1858 		return;
1859 	}
1860 
1861 	/* check query type / rr type */
1862 	rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr, 1);
1863 	if(rrset == NULL) {
1864 		verbose(VERB_ALGO, "rpz: unable to find local-data for query");
1865 		rrset_count = 0;
1866 		goto nodata;
1867 	}
1868 
1869 	rp = respip_copy_rrset(rrset->rrset, temp);
1870 	if(!rp) {
1871 		verbose(VERB_ALGO, "rpz: local data action: out of memory");
1872 		return;
1873 	}
1874 
1875 	rp->rk.flags |= PACKED_RRSET_FIXEDTTL | PACKED_RRSET_RPZ;
1876 	rp->rk.dname = qinfo->qname;
1877 	rp->rk.dname_len = qinfo->qname_len;
1878 	rp->entry.hash = rrset_key_hash(&rp->rk);
1879 nodata:
1880 	if(auth_zone) {
1881 		struct auth_rrset* soa = NULL;
1882 		soa = auth_zone_get_soa_rrset(auth_zone);
1883 		if(soa) {
1884 			rsoa = make_soa_ubrrset(auth_zone, soa, temp);
1885 			if(!rsoa) {
1886 				verbose(VERB_ALGO, "rpz: local data action soa: out of memory");
1887 				return;
1888 			}
1889 		}
1890 	}
1891 
1892 	rpz_local_encode(env, qinfo, edns, repinfo, buf, temp, rp,
1893 		rrset_count, rcode, rsoa);
1894 }
1895 
1896 /** Apply the cname override action, during worker request callback.
1897  * false on failure. */
1898 static int
rpz_apply_cname_override_action(struct rpz * r,struct query_info * qinfo,struct regional * temp)1899 rpz_apply_cname_override_action(struct rpz* r,
1900 	struct query_info* qinfo, struct regional* temp)
1901 {
1902 	if(!r)
1903 		return 0;
1904 	qinfo->local_alias = regional_alloc_zero(temp,
1905 		sizeof(struct local_rrset));
1906 	if(qinfo->local_alias == NULL)
1907 		return 0; /* out of memory */
1908 	qinfo->local_alias->rrset = respip_copy_rrset(r->cname_override, temp);
1909 	if(qinfo->local_alias->rrset == NULL) {
1910 		qinfo->local_alias = NULL;
1911 		return 0; /* out of memory */
1912 	}
1913 	qinfo->local_alias->rrset->rk.dname = qinfo->qname;
1914 	qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
1915 	return 1;
1916 }
1917 
1918 /** add additional section SOA record to the reply.
1919  * Since this gets fed into the normal iterator answer creation, it
1920  * gets minimal-responses applied to it, that can remove the additional SOA
1921  * again. */
1922 static int
rpz_add_soa(struct reply_info * rep,struct module_qstate * ms,struct auth_zone * az)1923 rpz_add_soa(struct reply_info* rep, struct module_qstate* ms,
1924 	struct auth_zone* az)
1925 {
1926 	struct auth_rrset* soa = NULL;
1927 	struct ub_packed_rrset_key* rsoa = NULL;
1928 	struct ub_packed_rrset_key** prevrrsets;
1929 	if(!az) return 1;
1930 	soa = auth_zone_get_soa_rrset(az);
1931 	if(!soa) return 1;
1932 	if(!rep) return 0;
1933 	rsoa = make_soa_ubrrset(az, soa, ms->region);
1934 	if(!rsoa) return 0;
1935 	prevrrsets = rep->rrsets;
1936 	rep->rrsets = regional_alloc_zero(ms->region,
1937 		sizeof(*rep->rrsets)*(rep->rrset_count+1));
1938 	if(!rep->rrsets)
1939 		return 0;
1940 	if(prevrrsets && rep->rrset_count > 0)
1941 		memcpy(rep->rrsets, prevrrsets, rep->rrset_count*sizeof(*rep->rrsets));
1942 	rep->rrset_count++;
1943 	rep->ar_numrrsets++;
1944 	rep->rrsets[rep->rrset_count-1] = rsoa;
1945 	return 1;
1946 }
1947 
1948 static inline struct dns_msg*
rpz_dns_msg_new(struct regional * region)1949 rpz_dns_msg_new(struct regional* region)
1950 {
1951 	struct dns_msg* msg =
1952 			(struct dns_msg*)regional_alloc(region,
1953 							sizeof(struct dns_msg));
1954 	if(msg == NULL) { return NULL; }
1955 	memset(msg, 0, sizeof(struct dns_msg));
1956 
1957 	return msg;
1958 }
1959 
1960 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)1961 rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
1962 	struct query_info* qinfo, struct auth_zone* az)
1963 {
1964 	struct dns_msg* msg = rpz_dns_msg_new(ms->region);
1965 	if(msg == NULL) { return msg; }
1966 	msg->qinfo = *qinfo;
1967 	msg->rep = construct_reply_info_base(ms->region,
1968 					     LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
1969 					     1, /* qd */
1970 					     0, /* ttl */
1971 					     0, /* prettl */
1972 					     0, /* expttl */
1973 					     0, /* norecttl */
1974 					     0, /* an */
1975 					     0, /* ns */
1976 					     0, /* ar */
1977 					     0, /* total */
1978 					     sec_status_insecure,
1979 					     LDNS_EDE_NONE);
1980 	if(msg->rep)
1981 		msg->rep->authoritative = 1;
1982 	if(!rpz_add_soa(msg->rep, ms, az))
1983 		return NULL;
1984 	return msg;
1985 }
1986 
1987 static inline struct dns_msg*
rpz_synthesize_nxdomain(struct rpz * r,struct module_qstate * ms,struct query_info * qinfo,struct auth_zone * az)1988 rpz_synthesize_nxdomain(struct rpz* r, struct module_qstate* ms,
1989 	struct query_info* qinfo, struct auth_zone* az)
1990 {
1991 	struct dns_msg* msg = rpz_dns_msg_new(ms->region);
1992 	uint16_t flags;
1993 	if(msg == NULL) { return msg; }
1994 	msg->qinfo = *qinfo;
1995 	flags = LDNS_RCODE_NXDOMAIN | BIT_QR | BIT_AA | BIT_RA;
1996 	if(r->signal_nxdomain_ra)
1997 		flags &= ~BIT_RA;
1998 	msg->rep = construct_reply_info_base(ms->region,
1999 					     flags,
2000 					     1, /* qd */
2001 					     0, /* ttl */
2002 					     0, /* prettl */
2003 					     0, /* expttl */
2004 					     0, /* norecttl */
2005 					     0, /* an */
2006 					     0, /* ns */
2007 					     0, /* ar */
2008 					     0, /* total */
2009 					     sec_status_insecure,
2010 					     LDNS_EDE_NONE);
2011 	if(msg->rep)
2012 		msg->rep->authoritative = 1;
2013 	if(!rpz_add_soa(msg->rep, ms, az))
2014 		return NULL;
2015 	return msg;
2016 }
2017 
2018 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)2019 rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
2020 	struct query_info* qi, struct local_rrset* rrset, struct auth_zone* az)
2021 {
2022 	struct dns_msg* msg = NULL;
2023 	struct reply_info* new_reply_info;
2024 	struct ub_packed_rrset_key* rp;
2025 
2026 
2027 	msg = rpz_dns_msg_new(ms->region);
2028 	if(msg == NULL) { return NULL; }
2029 
2030 	msg->qinfo = *qi;
2031         new_reply_info = construct_reply_info_base(ms->region,
2032                                                    LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
2033                                                    1, /* qd */
2034                                                    0, /* ttl */
2035                                                    0, /* prettl */
2036                                                    0, /* expttl */
2037                                                    0, /* norecttl */
2038                                                    1, /* an */
2039                                                    0, /* ns */
2040                                                    0, /* ar */
2041                                                    1, /* total */
2042                                                    sec_status_insecure,
2043                                                    LDNS_EDE_NONE);
2044 	if(new_reply_info == NULL) {
2045 		log_err("out of memory");
2046 		return NULL;
2047 	}
2048 	new_reply_info->authoritative = 1;
2049 	rp = respip_copy_rrset(rrset->rrset, ms->region);
2050 	if(rp == NULL) {
2051 		log_err("out of memory");
2052 		return NULL;
2053 	}
2054 	rp->rk.dname = qi->qname;
2055 	rp->rk.dname_len = qi->qname_len;
2056 	/* this rrset is from the rpz data, or synthesized.
2057 	 * It is not actually from the network, so we flag it with this
2058 	 * flags as a fake RRset. If later the cache is used to look up
2059 	 * rrsets, then the fake ones are not returned (if you look without
2060 	 * the flag). For like CNAME lookups from the iterator or A, AAAA
2061 	 * lookups for nameserver targets, it would use the without flag
2062 	 * actual data. So that the actual network data and fake data
2063 	 * are kept track of separately. */
2064 	rp->rk.flags |= PACKED_RRSET_RPZ;
2065 	new_reply_info->rrsets[0] = rp;
2066 	msg->rep = new_reply_info;
2067 	if(!rpz_add_soa(msg->rep, ms, az))
2068 		return NULL;
2069 	return msg;
2070 }
2071 
2072 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)2073 rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms,
2074 	struct query_info* qi, struct clientip_synthesized_rr* data,
2075 	struct auth_zone* az)
2076 {
2077 	struct local_rrset* rrset;
2078 
2079 	rrset = rpz_find_synthesized_rrset(qi->qtype, data, 1);
2080 	if(rrset == NULL) {
2081 		verbose(VERB_ALGO, "rpz: nsip: no matching local data found");
2082 		return NULL;
2083 	}
2084 
2085 	return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
2086 }
2087 
2088 /* copy'n'paste from localzone.c */
2089 static struct local_rrset*
local_data_find_type(struct local_data * data,uint16_t type,int alias_ok)2090 local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
2091 {
2092 	struct local_rrset* p, *cname = NULL;
2093 	type = htons(type);
2094 	for(p = data->rrsets; p; p = p->next) {
2095 		if(p->rrset->rk.type == type)
2096 			return p;
2097 		if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
2098 			cname = p;
2099 	}
2100 	if(alias_ok)
2101 		return cname;
2102 	return NULL;
2103 }
2104 
2105 /* based on localzone.c:local_data_answer() */
2106 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)2107 rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
2108 	struct query_info* qi, struct local_zone* z,
2109 	struct matched_delegation_point const* match, struct auth_zone* az)
2110 {
2111 	struct local_data key;
2112 	struct local_data* ld;
2113 	struct local_rrset* rrset;
2114 
2115 	if(match->dname == NULL) { return NULL; }
2116 
2117 	key.node.key = &key;
2118 	key.name = match->dname;
2119 	key.namelen = match->dname_len;
2120 	key.namelabs = dname_count_labels(match->dname);
2121 
2122 	rpz_log_dname("nsdname local data", key.name, key.namelen);
2123 
2124 	ld = (struct local_data*)rbtree_search(&z->data, &key.node);
2125 	if(ld == NULL && dname_is_wild(z->name)) {
2126 		key.name = z->name;
2127 		key.namelen = z->namelen;
2128 		key.namelabs = z->namelabs;
2129 		ld = (struct local_data*)rbtree_search(&z->data, &key.node);
2130 		/* rpz_synthesize_localdata_from_rrset is going to make
2131 		 * the rrset source name equal to the query name. So no need
2132 		 * to make the wildcard rrset here. */
2133 	}
2134 	if(ld == NULL) {
2135 		verbose(VERB_ALGO, "rpz: nsdname: qname not found");
2136 		return NULL;
2137 	}
2138 
2139 	rrset = local_data_find_type(ld, qi->qtype, 1);
2140 	if(rrset == NULL) {
2141 		verbose(VERB_ALGO, "rpz: nsdname: no matching local data found");
2142 		return NULL;
2143 	}
2144 
2145 	return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
2146 }
2147 
2148 /* like local_data_answer for qname triggers after a cname */
2149 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)2150 rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms,
2151 	struct query_info* qinfo, struct local_zone* z, struct auth_zone* az)
2152 {
2153 	struct local_data key;
2154 	struct local_data* ld;
2155 	struct local_rrset* rrset;
2156 	key.node.key = &key;
2157 	key.name = qinfo->qname;
2158 	key.namelen = qinfo->qname_len;
2159 	key.namelabs = dname_count_labels(qinfo->qname);
2160 	ld = (struct local_data*)rbtree_search(&z->data, &key.node);
2161 	if(ld == NULL && dname_is_wild(z->name)) {
2162 		key.name = z->name;
2163 		key.namelen = z->namelen;
2164 		key.namelabs = z->namelabs;
2165 		ld = (struct local_data*)rbtree_search(&z->data, &key.node);
2166 		/* rpz_synthesize_localdata_from_rrset is going to make
2167 		 * the rrset source name equal to the query name. So no need
2168 		 * to make the wildcard rrset here. */
2169 	}
2170 	if(ld == NULL) {
2171 		verbose(VERB_ALGO, "rpz: qname: name not found");
2172 		return NULL;
2173 	}
2174 	rrset = local_data_find_type(ld, qinfo->qtype, 1);
2175 	if(rrset == NULL) {
2176 		verbose(VERB_ALGO, "rpz: qname: type not found");
2177 		return NULL;
2178 	}
2179 	return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az);
2180 }
2181 
2182 /** Synthesize a CNAME message for RPZ action override */
2183 static struct dns_msg*
rpz_synthesize_cname_override_msg(struct rpz * r,struct module_qstate * ms,struct query_info * qinfo)2184 rpz_synthesize_cname_override_msg(struct rpz* r, struct module_qstate* ms,
2185 	struct query_info* qinfo)
2186 {
2187 	struct dns_msg* msg = NULL;
2188 	struct reply_info* new_reply_info;
2189 	struct ub_packed_rrset_key* rp;
2190 
2191 	msg = rpz_dns_msg_new(ms->region);
2192 	if(msg == NULL) { return NULL; }
2193 
2194 	msg->qinfo = *qinfo;
2195         new_reply_info = construct_reply_info_base(ms->region,
2196                                                    LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
2197                                                    1, /* qd */
2198                                                    0, /* ttl */
2199                                                    0, /* prettl */
2200                                                    0, /* expttl */
2201                                                    0, /* norecttl */
2202                                                    1, /* an */
2203                                                    0, /* ns */
2204                                                    0, /* ar */
2205                                                    1, /* total */
2206                                                    sec_status_insecure,
2207                                                    LDNS_EDE_NONE);
2208 	if(new_reply_info == NULL) {
2209 		log_err("out of memory");
2210 		return NULL;
2211 	}
2212 	new_reply_info->authoritative = 1;
2213 
2214 	rp = respip_copy_rrset(r->cname_override, ms->region);
2215 	if(rp == NULL) {
2216 		log_err("out of memory");
2217 		return NULL;
2218 	}
2219 	rp->rk.dname = qinfo->qname;
2220 	rp->rk.dname_len = qinfo->qname_len;
2221 	/* this rrset is from the rpz data, or synthesized.
2222 	 * It is not actually from the network, so we flag it with this
2223 	 * flags as a fake RRset. If later the cache is used to look up
2224 	 * rrsets, then the fake ones are not returned (if you look without
2225 	 * the flag). For like CNAME lookups from the iterator or A, AAAA
2226 	 * lookups for nameserver targets, it would use the without flag
2227 	 * actual data. So that the actual network data and fake data
2228 	 * are kept track of separately. */
2229 	rp->rk.flags |= PACKED_RRSET_RPZ;
2230 	new_reply_info->rrsets[0] = rp;
2231 
2232 	msg->rep = new_reply_info;
2233 	return msg;
2234 }
2235 
2236 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)2237 rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
2238 	struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo,
2239 	struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
2240 	struct comm_reply* repinfo, struct ub_server_stats* stats)
2241 {
2242 	struct local_data* ld = NULL;
2243 	int ret = 0;
2244 	if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
2245 		if(!rpz_apply_cname_override_action(r, qinfo, temp))
2246 			return 0;
2247 		if(r->log) {
2248 			log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION,
2249 				      qinfo, repinfo, NULL, r->log_name);
2250 		}
2251 		stats->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
2252 		return 0;
2253 	}
2254 
2255 	if(lzt == local_zone_redirect && local_data_answer(z, env, qinfo,
2256 		edns, repinfo, buf, temp, dname_count_labels(qinfo->qname),
2257 		&ld, lzt, -1, NULL, 0, NULL, 0)) {
2258 		if(r->log) {
2259 			log_rpz_apply("qname", z->name, NULL,
2260 				localzone_type_to_rpz_action(lzt), qinfo,
2261 				repinfo, NULL, r->log_name);
2262 		}
2263 		stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
2264 		return !qinfo->local_alias;
2265 	}
2266 
2267 	ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp,
2268 		0 /* no local data used */, lzt);
2269 	if(r->signal_nxdomain_ra && LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
2270 		== LDNS_RCODE_NXDOMAIN)
2271 		LDNS_RA_CLR(sldns_buffer_begin(buf));
2272 	if(r->log) {
2273 		log_rpz_apply("qname", z->name, NULL, localzone_type_to_rpz_action(lzt),
2274 			      qinfo, repinfo, NULL, r->log_name);
2275 	}
2276 	stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
2277 	return ret;
2278 }
2279 
2280 static struct clientip_synthesized_rr*
rpz_delegation_point_ipbased_trigger_lookup(struct rpz * rpz,struct iter_qstate * is)2281 rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate* is)
2282 {
2283 	struct delegpt_addr* cursor;
2284 	struct clientip_synthesized_rr* action = NULL;
2285 	if(is->dp == NULL) { return NULL; }
2286 	for(cursor = is->dp->target_list;
2287 	    cursor != NULL;
2288 	    cursor = cursor->next_target) {
2289 		if(cursor->bogus) { continue; }
2290 		action = rpz_ipbased_trigger_lookup(rpz->ns_set, &cursor->addr,
2291 						    cursor->addrlen, "nsip");
2292 		if(action != NULL) { return action; }
2293 	}
2294 	return NULL;
2295 }
2296 
2297 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)2298 rpz_apply_nsip_trigger(struct module_qstate* ms, struct query_info* qchase,
2299 	struct rpz* r, struct clientip_synthesized_rr* raddr,
2300 	struct auth_zone* az)
2301 {
2302 	enum rpz_action action = raddr->action;
2303 	struct dns_msg* ret = NULL;
2304 
2305 	if(r->action_override != RPZ_NO_OVERRIDE_ACTION) {
2306 		verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)",
2307 			rpz_action_to_string(r->action_override), rpz_action_to_string(action));
2308 		action = r->action_override;
2309 	}
2310 
2311 	if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) {
2312 		verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data");
2313 		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2314 		ms->rpz_applied = 1;
2315 		goto done;
2316 	}
2317 
2318 	switch(action) {
2319 	case RPZ_NXDOMAIN_ACTION:
2320 		ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
2321 		ms->rpz_applied = 1;
2322 		break;
2323 	case RPZ_NODATA_ACTION:
2324 		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2325 		ms->rpz_applied = 1;
2326 		break;
2327 	case RPZ_TCP_ONLY_ACTION:
2328 		/* basically a passthru here but the tcp-only will be
2329 		 * honored before the query gets sent. */
2330 		ms->tcp_required = 1;
2331 		ret = NULL;
2332 		break;
2333 	case RPZ_DROP_ACTION:
2334 		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2335 		ms->rpz_applied = 1;
2336 		ms->is_drop = 1;
2337 		break;
2338 	case RPZ_LOCAL_DATA_ACTION:
2339 		ret = rpz_synthesize_nsip_localdata(r, ms, qchase, raddr, az);
2340 		if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
2341 		ms->rpz_applied = 1;
2342 		break;
2343 	case RPZ_PASSTHRU_ACTION:
2344 		ret = NULL;
2345 		ms->rpz_passthru = 1;
2346 		break;
2347 	case RPZ_CNAME_OVERRIDE_ACTION:
2348 		ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
2349 		ms->rpz_applied = 1;
2350 		break;
2351 	default:
2352 		verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
2353 			rpz_action_to_string(action));
2354 		ret = NULL;
2355 	}
2356 
2357 done:
2358 	if(r->log)
2359 		log_rpz_apply("nsip", NULL, &raddr->node,
2360 			action, &ms->qinfo, NULL, ms, r->log_name);
2361 	if(ms->env->worker)
2362 		ms->env->worker->stats.rpz_action[action]++;
2363 	lock_rw_unlock(&raddr->lock);
2364 	return ret;
2365 }
2366 
2367 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)2368 rpz_apply_nsdname_trigger(struct module_qstate* ms, struct query_info* qchase,
2369 	struct rpz* r, struct local_zone* z,
2370 	struct matched_delegation_point const* match, struct auth_zone* az)
2371 {
2372 	struct dns_msg* ret = NULL;
2373 	enum rpz_action action = localzone_type_to_rpz_action(z->type);
2374 
2375 	if(r->action_override != RPZ_NO_OVERRIDE_ACTION) {
2376 		verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)",
2377 			rpz_action_to_string(r->action_override), rpz_action_to_string(action));
2378 		action = r->action_override;
2379 	}
2380 
2381 	switch(action) {
2382 	case RPZ_NXDOMAIN_ACTION:
2383 		ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
2384 		ms->rpz_applied = 1;
2385 		break;
2386 	case RPZ_NODATA_ACTION:
2387 		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2388 		ms->rpz_applied = 1;
2389 		break;
2390 	case RPZ_TCP_ONLY_ACTION:
2391 		/* basically a passthru here but the tcp-only will be
2392 		 * honored before the query gets sent. */
2393 		ms->tcp_required = 1;
2394 		ret = NULL;
2395 		break;
2396 	case RPZ_DROP_ACTION:
2397 		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2398 		ms->rpz_applied = 1;
2399 		ms->is_drop = 1;
2400 		break;
2401 	case RPZ_LOCAL_DATA_ACTION:
2402 		ret = rpz_synthesize_nsdname_localdata(r, ms, qchase, z, match, az);
2403 		if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
2404 		ms->rpz_applied = 1;
2405 		break;
2406 	case RPZ_PASSTHRU_ACTION:
2407 		ret = NULL;
2408 		ms->rpz_passthru = 1;
2409 		break;
2410 	case RPZ_CNAME_OVERRIDE_ACTION:
2411 		ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
2412 		ms->rpz_applied = 1;
2413 		break;
2414 	default:
2415 		verbose(VERB_ALGO, "rpz: nsdname: bug: unhandled or invalid action: '%s'",
2416 			rpz_action_to_string(action));
2417 		ret = NULL;
2418 	}
2419 
2420 	if(r->log)
2421 		log_rpz_apply("nsdname", match->dname, NULL,
2422 			action, &ms->qinfo, NULL, ms, r->log_name);
2423 	if(ms->env->worker)
2424 		ms->env->worker->stats.rpz_action[action]++;
2425 	lock_rw_unlock(&z->lock);
2426 	return ret;
2427 }
2428 
2429 static struct local_zone*
rpz_delegation_point_zone_lookup(struct delegpt * dp,struct local_zones * zones,uint16_t qclass,struct matched_delegation_point * match)2430 rpz_delegation_point_zone_lookup(struct delegpt* dp, struct local_zones* zones,
2431 	uint16_t qclass,
2432 	/* output parameter */
2433 	struct matched_delegation_point* match)
2434 {
2435 	struct delegpt_ns* nameserver;
2436 	struct local_zone* z = NULL;
2437 
2438 	/* the rpz specs match the nameserver names (NS records), not the
2439 	 * name of the delegation point itself, to the nsdname triggers */
2440 	for(nameserver = dp->nslist;
2441 	    nameserver != NULL;
2442 	    nameserver = nameserver->next) {
2443 		z = rpz_find_zone(zones, nameserver->name, nameserver->namelen,
2444 				  qclass, 0, 0, 0);
2445 		if(z != NULL) {
2446 			match->dname = nameserver->name;
2447 			match->dname_len = nameserver->namelen;
2448 			if(verbosity >= VERB_ALGO) {
2449 				char nm[LDNS_MAX_DOMAINLEN];
2450 				char zn[LDNS_MAX_DOMAINLEN];
2451 				dname_str(match->dname, nm);
2452 				dname_str(z->name, zn);
2453 				if(strcmp(nm, zn) != 0)
2454 					verbose(VERB_ALGO, "rpz: trigger nsdname %s on %s action=%s",
2455 						zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type)));
2456 				else
2457 					verbose(VERB_ALGO, "rpz: trigger nsdname %s action=%s",
2458 						nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type)));
2459 			}
2460 			break;
2461 		}
2462 	}
2463 
2464 	return z;
2465 }
2466 
2467 struct dns_msg*
rpz_callback_from_iterator_module(struct module_qstate * ms,struct iter_qstate * is)2468 rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate* is)
2469 {
2470 	struct auth_zones* az;
2471 	struct auth_zone* a;
2472 	struct dns_msg* ret = NULL;
2473 	struct clientip_synthesized_rr* raddr = NULL;
2474 	struct rpz* r = NULL;
2475 	struct local_zone* z = NULL;
2476 	struct matched_delegation_point match = {0};
2477 
2478 	if(ms->rpz_passthru) {
2479 		verbose(VERB_ALGO, "query is rpz_passthru, no further processing");
2480 		return NULL;
2481 	}
2482 
2483 	if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
2484 
2485 	az = ms->env->auth_zones;
2486 	lock_rw_rdlock(&az->rpz_lock);
2487 
2488 	verbose(VERB_ALGO, "rpz: iterator module callback: have_rpz=%d", az->rpz_first != NULL);
2489 
2490 	/* precedence of RPZ works, loosely, like this:
2491 	 * CNAMEs in order of the CNAME chain. rpzs in the order they are
2492 	 * configured. In an RPZ: first client-IP addr, then QNAME, then
2493 	 * response IP, then NSDNAME, then NSIP. Longest match first. Smallest
2494 	 * one from a set. */
2495 	/* we use the precedence rules for the topics and triggers that
2496 	 * are pertinent at this stage of the resolve processing */
2497 	for(a = az->rpz_first; a != NULL; a = a->rpz_az_next) {
2498 		lock_rw_rdlock(&a->lock);
2499 		r = a->rpz;
2500 		if(r->disabled) {
2501 			lock_rw_unlock(&a->lock);
2502 			continue;
2503 		}
2504 		if(r->taglist && (!ms->client_info ||
2505 			!taglist_intersect(r->taglist, r->taglistlen,
2506 				ms->client_info->taglist,
2507 				ms->client_info->taglen))) {
2508 			lock_rw_unlock(&a->lock);
2509 			continue;
2510 		}
2511 
2512 		/* the nsdname has precedence over the nsip triggers */
2513 		z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
2514 						     is->qchase.qclass, &match);
2515 		if(z != NULL) {
2516 			break;
2517 		}
2518 
2519 		raddr = rpz_delegation_point_ipbased_trigger_lookup(r, is);
2520 		if(raddr != NULL) {
2521 			break;
2522 		}
2523 		lock_rw_unlock(&a->lock);
2524 	}
2525 
2526 	lock_rw_unlock(&az->rpz_lock);
2527 
2528 	if(raddr == NULL && z == NULL)
2529 		return NULL;
2530 
2531 	if(raddr != NULL) {
2532 		if(z) {
2533 			lock_rw_unlock(&z->lock);
2534 		}
2535 		ret = rpz_apply_nsip_trigger(ms, &is->qchase, r, raddr, a);
2536 	} else {
2537 		ret = rpz_apply_nsdname_trigger(ms, &is->qchase, r, z, &match, a);
2538 	}
2539 	lock_rw_unlock(&a->lock);
2540 	return ret;
2541 }
2542 
rpz_callback_from_iterator_cname(struct module_qstate * ms,struct iter_qstate * is)2543 struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
2544 	struct iter_qstate* is)
2545 {
2546 	struct auth_zones* az;
2547 	struct auth_zone* a = NULL;
2548 	struct rpz* r = NULL;
2549 	struct local_zone* z = NULL;
2550 	enum localzone_type lzt;
2551 	struct dns_msg* ret = NULL;
2552 
2553 	if(ms->rpz_passthru) {
2554 		verbose(VERB_ALGO, "query is rpz_passthru, no further processing");
2555 		return NULL;
2556 	}
2557 
2558 	if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
2559 	az = ms->env->auth_zones;
2560 
2561 	lock_rw_rdlock(&az->rpz_lock);
2562 
2563 	for(a = az->rpz_first; a; a = a->rpz_az_next) {
2564 		lock_rw_rdlock(&a->lock);
2565 		r = a->rpz;
2566 		if(r->disabled) {
2567 			lock_rw_unlock(&a->lock);
2568 			continue;
2569 		}
2570 		if(r->taglist && (!ms->client_info ||
2571 			!taglist_intersect(r->taglist, r->taglistlen,
2572 				ms->client_info->taglist,
2573 				ms->client_info->taglen))) {
2574 			lock_rw_unlock(&a->lock);
2575 			continue;
2576 		}
2577 		z = rpz_find_zone(r->local_zones, is->qchase.qname,
2578 			is->qchase.qname_len, is->qchase.qclass, 0, 0, 0);
2579 		if(z && r->action_override == RPZ_DISABLED_ACTION) {
2580 			if(r->log)
2581 				log_rpz_apply("qname", z->name, NULL,
2582 					r->action_override,
2583 					&ms->qinfo, NULL, ms, r->log_name);
2584 			if(ms->env->worker)
2585 				ms->env->worker->stats.rpz_action[r->action_override]++;
2586 			lock_rw_unlock(&z->lock);
2587 			z = NULL;
2588 		}
2589 		if(z) {
2590 			break;
2591 		}
2592 		/* not found in this auth_zone */
2593 		lock_rw_unlock(&a->lock);
2594 	}
2595 	lock_rw_unlock(&az->rpz_lock);
2596 
2597 	if(z == NULL)
2598 		return NULL;
2599 	if(r->action_override == RPZ_NO_OVERRIDE_ACTION) {
2600 		lzt = z->type;
2601 	} else {
2602 		lzt = rpz_action_to_localzone_type(r->action_override);
2603 	}
2604 
2605 	if(verbosity >= VERB_ALGO) {
2606 		char nm[LDNS_MAX_DOMAINLEN], zn[LDNS_MAX_DOMAINLEN];
2607 		dname_str(is->qchase.qname, nm);
2608 		dname_str(z->name, zn);
2609 		if(strcmp(zn, nm) != 0)
2610 			verbose(VERB_ALGO, "rpz: qname trigger %s on %s, with action=%s",
2611 				zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2612 		else
2613 			verbose(VERB_ALGO, "rpz: qname trigger %s, with action=%s",
2614 				nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2615 	}
2616 	switch(localzone_type_to_rpz_action(lzt)) {
2617 	case RPZ_NXDOMAIN_ACTION:
2618 		ret = rpz_synthesize_nxdomain(r, ms, &is->qchase, a);
2619 		ms->rpz_applied = 1;
2620 		break;
2621 	case RPZ_NODATA_ACTION:
2622 		ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
2623 		ms->rpz_applied = 1;
2624 		break;
2625 	case RPZ_TCP_ONLY_ACTION:
2626 		/* basically a passthru here but the tcp-only will be
2627 		 * honored before the query gets sent. */
2628 		ms->tcp_required = 1;
2629 		ret = NULL;
2630 		break;
2631 	case RPZ_DROP_ACTION:
2632 		ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
2633 		ms->rpz_applied = 1;
2634 		ms->is_drop = 1;
2635 		break;
2636 	case RPZ_LOCAL_DATA_ACTION:
2637 		ret = rpz_synthesize_qname_localdata_msg(r, ms, &is->qchase, z, a);
2638 		if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); }
2639 		ms->rpz_applied = 1;
2640 		break;
2641 	case RPZ_PASSTHRU_ACTION:
2642 		ret = NULL;
2643 		ms->rpz_passthru = 1;
2644 		break;
2645 	default:
2646 		verbose(VERB_ALGO, "rpz: qname trigger: bug: unhandled or invalid action: '%s'",
2647 			rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2648 		ret = NULL;
2649 	}
2650 	if(r->log)
2651 		log_rpz_apply("qname", (z?z->name:NULL), NULL,
2652 			localzone_type_to_rpz_action(lzt),
2653 			&is->qchase, NULL, ms, r->log_name);
2654 	lock_rw_unlock(&z->lock);
2655 	lock_rw_unlock(&a->lock);
2656 	return ret;
2657 }
2658 
2659 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)2660 rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
2661 	struct query_info* qinfo, struct edns_data* edns, struct comm_reply* repinfo,
2662 	uint8_t* taglist, size_t taglen, struct ub_server_stats* stats,
2663 	sldns_buffer* buf, struct regional* temp,
2664 	/* output parameters */
2665 	struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out,
2666 	int* passthru)
2667 {
2668 	int ret = 0;
2669 	enum rpz_action client_action;
2670 	struct clientip_synthesized_rr* node = rpz_resolve_client_action_and_zone(
2671 		az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out);
2672 
2673 	client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action);
2674 	if(node != NULL && *r_out &&
2675 		(*r_out)->action_override != RPZ_NO_OVERRIDE_ACTION) {
2676 		client_action = (*r_out)->action_override;
2677 	}
2678 	if(client_action == RPZ_PASSTHRU_ACTION) {
2679 		if(*r_out && (*r_out)->log)
2680 			log_rpz_apply(
2681 				(node?"clientip":"qname"),
2682 				((*z_out)?(*z_out)->name:NULL),
2683 				(node?&node->node:NULL),
2684 				client_action, qinfo, repinfo, NULL,
2685 				(*r_out)->log_name);
2686 		*passthru = 1;
2687 		ret = 0;
2688 		goto done;
2689 	}
2690 	if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
2691 			      client_action != RPZ_PASSTHRU_ACTION)) {
2692 		if(client_action == RPZ_PASSTHRU_ACTION
2693 			|| client_action == RPZ_INVALID_ACTION
2694 			|| (client_action == RPZ_TCP_ONLY_ACTION
2695 				&& !rpz_is_udp_query(repinfo))) {
2696 			ret = 0;
2697 			goto done;
2698 		}
2699 		stats->rpz_action[client_action]++;
2700 		if(client_action == RPZ_LOCAL_DATA_ACTION) {
2701 			rpz_apply_clientip_localdata_action(node, env, qinfo,
2702 				edns, repinfo, buf, temp, *a_out);
2703 			ret = 1;
2704 		} else if(client_action == RPZ_CNAME_OVERRIDE_ACTION) {
2705 			if(!rpz_apply_cname_override_action(*r_out, qinfo,
2706 				temp)) {
2707 				ret = 0;
2708 				goto done;
2709 			}
2710 			ret = 0;
2711 		} else {
2712 			local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns,
2713 				repinfo, buf, temp, 0 /* no local data used */,
2714 				rpz_action_to_localzone_type(client_action));
2715 			if(*r_out && (*r_out)->signal_nxdomain_ra &&
2716 				LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
2717 				== LDNS_RCODE_NXDOMAIN)
2718 				LDNS_RA_CLR(sldns_buffer_begin(buf));
2719 			ret = 1;
2720 		}
2721 		if(*r_out && (*r_out)->log)
2722 			log_rpz_apply(
2723 				(node?"clientip":"qname"),
2724 				((*z_out)?(*z_out)->name:NULL),
2725 				(node?&node->node:NULL),
2726 				client_action, qinfo, repinfo, NULL,
2727 				(*r_out)->log_name);
2728 		goto done;
2729 	}
2730 	ret = -1;
2731 done:
2732 	if(node != NULL) {
2733 		lock_rw_unlock(&node->lock);
2734 	}
2735 	return ret;
2736 }
2737 
2738 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)2739 rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
2740 	struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
2741 	struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist,
2742 	size_t taglen, struct ub_server_stats* stats, int* passthru)
2743 {
2744 	struct rpz* r = NULL;
2745 	struct auth_zone* a = NULL;
2746 	struct local_zone* z = NULL;
2747 	int ret;
2748 	enum localzone_type lzt;
2749 
2750 	int clientip_trigger = rpz_apply_maybe_clientip_trigger(az, env, qinfo,
2751 		edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r,
2752 		passthru);
2753 	if(clientip_trigger >= 0) {
2754 		if(a) {
2755 			lock_rw_unlock(&a->lock);
2756 		}
2757 		if(z) {
2758 			lock_rw_unlock(&z->lock);
2759 		}
2760 		return clientip_trigger;
2761 	}
2762 
2763 	if(z == NULL) {
2764 		if(a) {
2765 			lock_rw_unlock(&a->lock);
2766 		}
2767 		return 0;
2768 	}
2769 
2770 	log_assert(r);
2771 
2772 	if(r->action_override == RPZ_NO_OVERRIDE_ACTION) {
2773 		lzt = z->type;
2774 	} else {
2775 		lzt = rpz_action_to_localzone_type(r->action_override);
2776 	}
2777 	if(r->action_override == RPZ_PASSTHRU_ACTION ||
2778 		lzt == local_zone_always_transparent /* RPZ_PASSTHRU_ACTION */) {
2779 		*passthru = 1;
2780 	}
2781 
2782 	if(verbosity >= VERB_ALGO) {
2783 		char nm[LDNS_MAX_DOMAINLEN], zn[LDNS_MAX_DOMAINLEN];
2784 		dname_str(qinfo->qname, nm);
2785 		dname_str(z->name, zn);
2786 		if(strcmp(zn, nm) != 0)
2787 			verbose(VERB_ALGO, "rpz: qname trigger %s on %s with action=%s",
2788 				zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2789 		else
2790 			verbose(VERB_ALGO, "rpz: qname trigger %s with action=%s",
2791 				nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2792 	}
2793 
2794 	ret = rpz_synthesize_qname_localdata(env, r, z, lzt, qinfo, edns, buf, temp,
2795 					     repinfo, stats);
2796 
2797 	lock_rw_unlock(&z->lock);
2798 	lock_rw_unlock(&a->lock);
2799 
2800 	return ret;
2801 }
2802 
rpz_enable(struct rpz * r)2803 void rpz_enable(struct rpz* r)
2804 {
2805     if(!r)
2806         return;
2807     r->disabled = 0;
2808 }
2809 
rpz_disable(struct rpz * r)2810 void rpz_disable(struct rpz* r)
2811 {
2812     if(!r)
2813         return;
2814     r->disabled = 1;
2815 }
2816 
2817 /** Get memory usage for clientip_synthesized_rrset. Ignores memory usage
2818  * of locks. */
2819 static size_t
rpz_clientip_synthesized_set_get_mem(struct clientip_synthesized_rrset * set)2820 rpz_clientip_synthesized_set_get_mem(struct clientip_synthesized_rrset* set)
2821 {
2822 	size_t m = sizeof(*set);
2823 	lock_rw_rdlock(&set->lock);
2824 	m += regional_get_mem(set->region);
2825 	lock_rw_unlock(&set->lock);
2826 	return m;
2827 }
2828 
rpz_get_mem(struct rpz * r)2829 size_t rpz_get_mem(struct rpz* r)
2830 {
2831 	size_t m = sizeof(*r);
2832 	if(r->taglist)
2833 		m += r->taglistlen;
2834 	if(r->log_name)
2835 		m += strlen(r->log_name) + 1;
2836 	m += regional_get_mem(r->region);
2837 	m += local_zones_get_mem(r->local_zones);
2838 	m += local_zones_get_mem(r->nsdname_zones);
2839 	m += respip_set_get_mem(r->respip_set);
2840 	m += rpz_clientip_synthesized_set_get_mem(r->client_set);
2841 	m += rpz_clientip_synthesized_set_get_mem(r->ns_set);
2842 	return m;
2843 }
2844