xref: /freebsd/contrib/unbound/services/rpz.c (revision 848ee2a3a8b47c9905fc51fefcf60eb371edbb98)
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 
54 /** string for RPZ action enum */
55 const char*
56 rpz_action_to_string(enum rpz_action a)
57 {
58 	switch(a) {
59 	case RPZ_NXDOMAIN_ACTION:	return "nxdomain";
60 	case RPZ_NODATA_ACTION:		return "nodata";
61 	case RPZ_PASSTHRU_ACTION:	return "passthru";
62 	case RPZ_DROP_ACTION:		return "drop";
63 	case RPZ_TCP_ONLY_ACTION:	return "tcp_only";
64 	case RPZ_INVALID_ACTION:	return "invalid";
65 	case RPZ_LOCAL_DATA_ACTION:	return "local_data";
66 	case RPZ_DISABLED_ACTION:	return "disabled";
67 	case RPZ_CNAME_OVERRIDE_ACTION:	return "cname_override";
68 	case RPZ_NO_OVERRIDE_ACTION:	return "no_override";
69 	}
70 	return "unknown";
71 }
72 
73 /** RPZ action enum for config string */
74 static enum rpz_action
75 rpz_config_to_action(char* a)
76 {
77 	if(strcmp(a, "nxdomain") == 0)
78 		return RPZ_NXDOMAIN_ACTION;
79 	else if(strcmp(a, "nodata") == 0)
80 		return RPZ_NODATA_ACTION;
81 	else if(strcmp(a, "passthru") == 0)
82 		return RPZ_PASSTHRU_ACTION;
83 	else if(strcmp(a, "drop") == 0)
84 		return RPZ_DROP_ACTION;
85 	else if(strcmp(a, "tcp_only") == 0)
86 		return RPZ_TCP_ONLY_ACTION;
87 	else if(strcmp(a, "cname") == 0)
88 		return RPZ_CNAME_OVERRIDE_ACTION;
89 	else if(strcmp(a, "disabled") == 0)
90 		return RPZ_DISABLED_ACTION;
91 	return RPZ_INVALID_ACTION;
92 }
93 
94 /** string for RPZ trigger enum */
95 static const char*
96 rpz_trigger_to_string(enum rpz_trigger r)
97 {
98 	switch(r) {
99 	case RPZ_QNAME_TRIGGER:		return "qname";
100 	case RPZ_CLIENT_IP_TRIGGER:	return "client_ip";
101 	case RPZ_RESPONSE_IP_TRIGGER:	return "response_ip";
102 	case RPZ_NSDNAME_TRIGGER:	return "nsdname";
103 	case RPZ_NSIP_TRIGGER:		return "nsip";
104 	case RPZ_INVALID_TRIGGER:	return "invalid";
105 	}
106 	return "unknown";
107 }
108 
109 /**
110  * Get the label that is just before the root label.
111  * @param dname: dname to work on
112  * @param maxdnamelen: maximum length of the dname
113  * @return: pointer to TLD label, NULL if not found or invalid dname
114  */
115 static uint8_t*
116 get_tld_label(uint8_t* dname, size_t maxdnamelen)
117 {
118 	uint8_t* prevlab = dname;
119 	size_t dnamelen = 0;
120 
121 	/* one byte needed for label length */
122 	if(dnamelen+1 > maxdnamelen)
123 		return NULL;
124 
125 	/* only root label */
126 	if(*dname == 0)
127 		return NULL;
128 
129 	while(*dname) {
130 		dnamelen += ((size_t)*dname)+1;
131 		if(dnamelen+1 > maxdnamelen)
132 			return NULL;
133 		dname = dname+((size_t)*dname)+1;
134 		if(*dname != 0)
135 			prevlab = dname;
136 	}
137 	return prevlab;
138 }
139 
140 /**
141  * Classify RPZ action for RR type/rdata
142  * @param rr_type: the RR type
143  * @param rdatawl: RDATA with 2 bytes length
144  * @param rdatalen: the length of rdatawl (including its 2 bytes length)
145  * @return: the RPZ action
146  */
147 static enum rpz_action
148 rpz_rr_to_action(uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
149 {
150 	char* endptr;
151 	uint8_t* rdata;
152 	int rdatalabs;
153 	uint8_t* tldlab = NULL;
154 
155 	switch(rr_type) {
156 		case LDNS_RR_TYPE_SOA:
157 		case LDNS_RR_TYPE_NS:
158 		case LDNS_RR_TYPE_DNAME:
159 		/* all DNSSEC-related RRs must be ignored */
160 		case LDNS_RR_TYPE_DNSKEY:
161 		case LDNS_RR_TYPE_DS:
162 		case LDNS_RR_TYPE_RRSIG:
163 		case LDNS_RR_TYPE_NSEC:
164 		case LDNS_RR_TYPE_NSEC3:
165 		case LDNS_RR_TYPE_NSEC3PARAM:
166 			return RPZ_INVALID_ACTION;
167 		case LDNS_RR_TYPE_CNAME:
168 			break;
169 		default:
170 			return RPZ_LOCAL_DATA_ACTION;
171 	}
172 
173 	/* use CNAME target to determine RPZ action */
174 	log_assert(rr_type == LDNS_RR_TYPE_CNAME);
175 	if(rdatalen < 3)
176 		return RPZ_INVALID_ACTION;
177 
178 	rdata = rdatawl + 2; /* 2 bytes of rdata length */
179 	if(dname_valid(rdata, rdatalen-2) != rdatalen-2)
180 		return RPZ_INVALID_ACTION;
181 
182 	rdatalabs = dname_count_labels(rdata);
183 	if(rdatalabs == 1)
184 		return RPZ_NXDOMAIN_ACTION;
185 	else if(rdatalabs == 2) {
186 		if(dname_subdomain_c(rdata, (uint8_t*)&"\001*\000"))
187 			return RPZ_NODATA_ACTION;
188 		else if(dname_subdomain_c(rdata,
189 			(uint8_t*)&"\014rpz-passthru\000"))
190 			return RPZ_PASSTHRU_ACTION;
191 		else if(dname_subdomain_c(rdata, (uint8_t*)&"\010rpz-drop\000"))
192 			return RPZ_DROP_ACTION;
193 		else if(dname_subdomain_c(rdata,
194 			(uint8_t*)&"\014rpz-tcp-only\000"))
195 			return RPZ_TCP_ONLY_ACTION;
196 	}
197 
198 	/* all other TLDs starting with "rpz-" are invalid */
199 	tldlab = get_tld_label(rdata, rdatalen-2);
200 	if(tldlab && dname_lab_startswith(tldlab, "rpz-", &endptr))
201 		return RPZ_INVALID_ACTION;
202 
203 	/* no special label found */
204 	return RPZ_LOCAL_DATA_ACTION;
205 }
206 
207 static enum localzone_type
208 rpz_action_to_localzone_type(enum rpz_action a)
209 {
210 	switch(a) {
211 	case RPZ_NXDOMAIN_ACTION:	return local_zone_always_nxdomain;
212 	case RPZ_NODATA_ACTION:		return local_zone_always_nodata;
213 	case RPZ_DROP_ACTION:		return local_zone_always_deny;
214 	case RPZ_PASSTHRU_ACTION:	return local_zone_always_transparent;
215 	case RPZ_LOCAL_DATA_ACTION:	/* fallthrough */
216 	case RPZ_CNAME_OVERRIDE_ACTION: return local_zone_redirect;
217 	case RPZ_INVALID_ACTION: 	/* fallthrough */
218 	case RPZ_TCP_ONLY_ACTION:	/* fallthrough */
219 	default:			return local_zone_invalid;
220 	}
221 }
222 
223 enum respip_action
224 rpz_action_to_respip_action(enum rpz_action a)
225 {
226 	switch(a) {
227 	case RPZ_NXDOMAIN_ACTION:	return respip_always_nxdomain;
228 	case RPZ_NODATA_ACTION:		return respip_always_nodata;
229 	case RPZ_DROP_ACTION:		return respip_always_deny;
230 	case RPZ_PASSTHRU_ACTION:	return respip_always_transparent;
231 	case RPZ_LOCAL_DATA_ACTION:	/* fallthrough */
232 	case RPZ_CNAME_OVERRIDE_ACTION: return respip_redirect;
233 	case RPZ_INVALID_ACTION:	/* fallthrough */
234 	case RPZ_TCP_ONLY_ACTION:	/* fallthrough */
235 	default:			return respip_invalid;
236 	}
237 }
238 
239 static enum rpz_action
240 localzone_type_to_rpz_action(enum localzone_type lzt)
241 {
242 	switch(lzt) {
243 	case local_zone_always_nxdomain:	return RPZ_NXDOMAIN_ACTION;
244 	case local_zone_always_nodata:		return RPZ_NODATA_ACTION;
245 	case local_zone_always_deny:		return RPZ_DROP_ACTION;
246 	case local_zone_always_transparent:	return RPZ_PASSTHRU_ACTION;
247 	case local_zone_redirect:		return RPZ_LOCAL_DATA_ACTION;
248 	case local_zone_invalid:
249 	default:
250 		return RPZ_INVALID_ACTION;
251 	}
252 }
253 
254 enum rpz_action
255 respip_action_to_rpz_action(enum respip_action a)
256 {
257 	switch(a) {
258 	case respip_always_nxdomain:	return RPZ_NXDOMAIN_ACTION;
259 	case respip_always_nodata:	return RPZ_NODATA_ACTION;
260 	case respip_always_deny:	return RPZ_DROP_ACTION;
261 	case respip_always_transparent:	return RPZ_PASSTHRU_ACTION;
262 	case respip_redirect:		return RPZ_LOCAL_DATA_ACTION;
263 	case respip_invalid:
264 	default:
265 		return RPZ_INVALID_ACTION;
266 	}
267 }
268 
269 /**
270  * Get RPZ trigger for dname
271  * @param dname: dname containing RPZ trigger
272  * @param dname_len: length of the dname
273  * @return: RPZ trigger enum
274  */
275 static enum rpz_trigger
276 rpz_dname_to_trigger(uint8_t* dname, size_t dname_len)
277 {
278 	uint8_t* tldlab;
279 	char* endptr;
280 
281 	if(dname_valid(dname, dname_len) != dname_len)
282 		return RPZ_INVALID_TRIGGER;
283 
284 	tldlab = get_tld_label(dname, dname_len);
285 	if(!tldlab || !dname_lab_startswith(tldlab, "rpz-", &endptr))
286 		return RPZ_QNAME_TRIGGER;
287 
288 	if(dname_subdomain_c(tldlab,
289 		(uint8_t*)&"\015rpz-client-ip\000"))
290 		return RPZ_CLIENT_IP_TRIGGER;
291 	else if(dname_subdomain_c(tldlab, (uint8_t*)&"\006rpz-ip\000"))
292 		return RPZ_RESPONSE_IP_TRIGGER;
293 	else if(dname_subdomain_c(tldlab, (uint8_t*)&"\013rpz-nsdname\000"))
294 		return RPZ_NSDNAME_TRIGGER;
295 	else if(dname_subdomain_c(tldlab, (uint8_t*)&"\010rpz-nsip\000"))
296 		return RPZ_NSIP_TRIGGER;
297 
298 	return RPZ_QNAME_TRIGGER;
299 }
300 
301 void rpz_delete(struct rpz* r)
302 {
303 	if(!r)
304 		return;
305 	local_zones_delete(r->local_zones);
306 	respip_set_delete(r->respip_set);
307 	regional_destroy(r->region);
308 	free(r->taglist);
309 	free(r->log_name);
310 	free(r);
311 }
312 
313 int
314 rpz_clear(struct rpz* r)
315 {
316 	/* must hold write lock on auth_zone */
317 	local_zones_delete(r->local_zones);
318 	respip_set_delete(r->respip_set);
319 	if(!(r->local_zones = local_zones_create())){
320 		return 0;
321 	}
322 	if(!(r->respip_set = respip_set_create())) {
323 		return 0;
324 	}
325 	return 1;
326 }
327 
328 void
329 rpz_finish_config(struct rpz* r)
330 {
331 	lock_rw_wrlock(&r->respip_set->lock);
332 	addr_tree_init_parents(&r->respip_set->ip_tree);
333 	lock_rw_unlock(&r->respip_set->lock);
334 }
335 
336 /** new rrset containing CNAME override, does not yet contain a dname */
337 static struct ub_packed_rrset_key*
338 new_cname_override(struct regional* region, uint8_t* ct, size_t ctlen)
339 {
340 	struct ub_packed_rrset_key* rrset;
341 	struct packed_rrset_data* pd;
342 	uint16_t rdlength = htons(ctlen);
343 	rrset = (struct ub_packed_rrset_key*)regional_alloc_zero(region,
344 		sizeof(*rrset));
345 	if(!rrset) {
346 		log_err("out of memory");
347 		return NULL;
348 	}
349 	rrset->entry.key = rrset;
350 	pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd));
351 	if(!pd) {
352 		log_err("out of memory");
353 		return NULL;
354 	}
355 	pd->trust = rrset_trust_prim_noglue;
356 	pd->security = sec_status_insecure;
357 
358 	pd->count = 1;
359 	pd->rr_len = regional_alloc_zero(region, sizeof(*pd->rr_len));
360 	pd->rr_ttl = regional_alloc_zero(region, sizeof(*pd->rr_ttl));
361 	pd->rr_data = regional_alloc_zero(region, sizeof(*pd->rr_data));
362 	if(!pd->rr_len || !pd->rr_ttl || !pd->rr_data) {
363 		log_err("out of memory");
364 		return NULL;
365 	}
366 	pd->rr_len[0] = ctlen+2;
367 	pd->rr_ttl[0] = 3600;
368 	pd->rr_data[0] = regional_alloc_zero(region, 2 /* rdlength */ + ctlen);
369 	if(!pd->rr_data[0]) {
370 		log_err("out of memory");
371 		return NULL;
372 	}
373 	memmove(pd->rr_data[0], &rdlength, 2);
374 	memmove(pd->rr_data[0]+2, ct, ctlen);
375 
376 	rrset->entry.data = pd;
377 	rrset->rk.type = htons(LDNS_RR_TYPE_CNAME);
378 	rrset->rk.rrset_class = htons(LDNS_RR_CLASS_IN);
379 	return rrset;
380 }
381 
382 struct rpz*
383 rpz_create(struct config_auth* p)
384 {
385 	struct rpz* r = calloc(1, sizeof(*r));
386 	if(!r)
387 		goto err;
388 
389 	r->region = regional_create_custom(sizeof(struct regional));
390 	if(!r->region) {
391 		goto err;
392 	}
393 
394 	if(!(r->local_zones = local_zones_create())){
395 		goto err;
396 	}
397 	if(!(r->respip_set = respip_set_create())) {
398 		goto err;
399 	}
400 	r->taglistlen = p->rpz_taglistlen;
401 	r->taglist = memdup(p->rpz_taglist, r->taglistlen);
402 	if(p->rpz_action_override) {
403 		r->action_override = rpz_config_to_action(p->rpz_action_override);
404 	}
405 	else
406 		r->action_override = RPZ_NO_OVERRIDE_ACTION;
407 
408 	if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
409 		uint8_t nm[LDNS_MAX_DOMAINLEN+1];
410 		size_t nmlen = sizeof(nm);
411 
412 		if(!p->rpz_cname) {
413 			log_err("RPZ override with cname action found, but no "
414 				"rpz-cname-override configured");
415 			goto err;
416 		}
417 
418 		if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
419 			log_err("cannot parse RPZ cname override: %s",
420 				p->rpz_cname);
421 			goto err;
422 		}
423 		r->cname_override = new_cname_override(r->region, nm, nmlen);
424 		if(!r->cname_override) {
425 			goto err;
426 		}
427 	}
428 	r->log = p->rpz_log;
429 	if(p->rpz_log_name) {
430 		if(!(r->log_name = strdup(p->rpz_log_name))) {
431 			log_err("malloc failure on RPZ log_name strdup");
432 			goto err;
433 		}
434 	}
435 	return r;
436 err:
437 	if(r) {
438 		if(r->local_zones)
439 			local_zones_delete(r->local_zones);
440 		if(r->respip_set)
441 			respip_set_delete(r->respip_set);
442 		if(r->taglist)
443 			free(r->taglist);
444 		if(r->region)
445 			regional_destroy(r->region);
446 		free(r);
447 	}
448 	return NULL;
449 }
450 
451 /**
452  * Remove RPZ zone name from dname
453  * Copy dname to newdname, without the originlen number of trailing bytes
454  */
455 static size_t
456 strip_dname_origin(uint8_t* dname, size_t dnamelen, size_t originlen,
457 	uint8_t* newdname, size_t maxnewdnamelen)
458 {
459 	size_t newdnamelen;
460 	if(dnamelen < originlen)
461 		return 0;
462 	newdnamelen = dnamelen - originlen;
463 	if(newdnamelen+1 > maxnewdnamelen)
464 		return 0;
465 	memmove(newdname, dname, newdnamelen);
466 	newdname[newdnamelen] = 0;
467 	return newdnamelen + 1;	/* + 1 for root label */
468 }
469 
470 /** Insert RR into RPZ's local-zone */
471 static void
472 rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
473 	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
474 	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
475 {
476 	struct local_zone* z;
477 	enum localzone_type tp = local_zone_always_transparent;
478 	int dnamelabs = dname_count_labels(dname);
479 	char* rrstr;
480 	int newzone = 0;
481 
482 	if(a == RPZ_TCP_ONLY_ACTION || a == RPZ_INVALID_ACTION) {
483 		char str[255+1];
484 		if(rrtype == LDNS_RR_TYPE_SOA || rrtype == LDNS_RR_TYPE_NS ||
485 			rrtype == LDNS_RR_TYPE_DNAME ||
486 			rrtype == LDNS_RR_TYPE_DNSKEY ||
487 			rrtype == LDNS_RR_TYPE_RRSIG ||
488 			rrtype == LDNS_RR_TYPE_NSEC ||
489 			rrtype == LDNS_RR_TYPE_NSEC3PARAM ||
490 			rrtype == LDNS_RR_TYPE_NSEC3 ||
491 			rrtype == LDNS_RR_TYPE_DS) {
492 			free(dname);
493 			return; /* no need to log these types as unsupported */
494 		}
495 		dname_str(dname, str);
496 		verbose(VERB_ALGO, "RPZ: qname trigger, %s skipping unsupported action: %s",
497 			str, rpz_action_to_string(a));
498 		free(dname);
499 		return;
500 	}
501 
502 	lock_rw_wrlock(&r->local_zones->lock);
503 	/* exact match */
504 	z = local_zones_find(r->local_zones, dname, dnamelen, dnamelabs,
505 		LDNS_RR_CLASS_IN);
506 	if(z && a != RPZ_LOCAL_DATA_ACTION) {
507 		rrstr = sldns_wire2str_rr(rr, rr_len);
508 		if(!rrstr) {
509 			log_err("malloc error while inserting RPZ qname "
510 				"trigger");
511 			free(dname);
512 			lock_rw_unlock(&r->local_zones->lock);
513 			return;
514 		}
515 		verbose(VERB_ALGO, "RPZ: skipping duplicate record: '%s'",
516 			rrstr);
517 		free(rrstr);
518 		free(dname);
519 		lock_rw_unlock(&r->local_zones->lock);
520 		return;
521 	}
522 	if(!z) {
523 		tp = rpz_action_to_localzone_type(a);
524 		if(!(z = local_zones_add_zone(r->local_zones, dname, dnamelen,
525 			dnamelabs, rrclass, tp))) {
526 			log_warn("RPZ create failed");
527 			lock_rw_unlock(&r->local_zones->lock);
528 			/* dname will be free'd in failed local_zone_create() */
529 			return;
530 		}
531 		newzone = 1;
532 	}
533 	if(a == RPZ_LOCAL_DATA_ACTION) {
534 		rrstr = sldns_wire2str_rr(rr, rr_len);
535 		if(!rrstr) {
536 			log_err("malloc error while inserting RPZ qname "
537 				"trigger");
538 			free(dname);
539 			lock_rw_unlock(&r->local_zones->lock);
540 			return;
541 		}
542 		lock_rw_wrlock(&z->lock);
543 		local_zone_enter_rr(z, dname, dnamelen, dnamelabs,
544 			rrtype, rrclass, ttl, rdata, rdata_len, rrstr);
545 		lock_rw_unlock(&z->lock);
546 		free(rrstr);
547 	}
548 	if(!newzone)
549 		free(dname);
550 	lock_rw_unlock(&r->local_zones->lock);
551 	return;
552 }
553 
554 /** Insert RR into RPZ's respip_set */
555 static int
556 rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
557 	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
558 	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
559 {
560 	struct resp_addr* node;
561 	struct sockaddr_storage addr;
562 	socklen_t addrlen;
563 	int net, af;
564 	char* rrstr;
565 	enum respip_action respa = rpz_action_to_respip_action(a);
566 
567 	if(a == RPZ_TCP_ONLY_ACTION || a == RPZ_INVALID_ACTION ||
568 		respa == respip_invalid) {
569 		char str[255+1];
570 		dname_str(dname, str);
571 		verbose(VERB_ALGO, "RPZ: respip trigger, %s skipping unsupported action: %s",
572 			str, rpz_action_to_string(a));
573 		return 0;
574 	}
575 
576 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
577 		return 0;
578 
579 	lock_rw_wrlock(&r->respip_set->lock);
580 	rrstr = sldns_wire2str_rr(rr, rr_len);
581 	if(!rrstr) {
582 		log_err("malloc error while inserting RPZ respip trigger");
583 		lock_rw_unlock(&r->respip_set->lock);
584 		return 0;
585 	}
586 	if(!(node=respip_sockaddr_find_or_create(r->respip_set, &addr, addrlen,
587 		net, 1, rrstr))) {
588 		lock_rw_unlock(&r->respip_set->lock);
589 		free(rrstr);
590 		return 0;
591 	}
592 
593 	lock_rw_wrlock(&node->lock);
594 	lock_rw_unlock(&r->respip_set->lock);
595 	node->action = respa;
596 
597 	if(a == RPZ_LOCAL_DATA_ACTION) {
598 		respip_enter_rr(r->respip_set->region, node, rrtype,
599 			rrclass, ttl, rdata, rdata_len, rrstr, "");
600 	}
601 	lock_rw_unlock(&node->lock);
602 	free(rrstr);
603 	return 1;
604 }
605 
606 int
607 rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
608 	size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
609 	uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len)
610 {
611 	size_t policydnamelen;
612 	/* name is free'd in local_zone delete */
613 	enum rpz_trigger t;
614 	enum rpz_action a;
615 	uint8_t* policydname;
616 
617 	if(!dname_subdomain_c(dname, azname)) {
618 		char* dname_str = sldns_wire2str_dname(dname, dnamelen);
619 		char* azname_str = sldns_wire2str_dname(azname, aznamelen);
620 		if(dname_str && azname_str) {
621 			log_err("RPZ: name of record (%s) to insert into RPZ is not a "
622 				"subdomain of the configured name of the RPZ zone (%s)",
623 				dname_str, azname_str);
624 		} else {
625 			log_err("RPZ: name of record to insert into RPZ is not a "
626 				"subdomain of the configured name of the RPZ zone");
627 		}
628 		free(dname_str);
629 		free(azname_str);
630 		return 0;
631 	}
632 
633 	log_assert(dnamelen >= aznamelen);
634 	if(!(policydname = calloc(1, (dnamelen-aznamelen)+1))) {
635 		log_err("malloc error while inserting RPZ RR");
636 		return 0;
637 	}
638 
639 	a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
640 	if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
641 		policydname, (dnamelen-aznamelen)+1))) {
642 		free(policydname);
643 		return 0;
644 	}
645 	t = rpz_dname_to_trigger(policydname, policydnamelen);
646 	if(t == RPZ_INVALID_TRIGGER) {
647 		free(policydname);
648 		verbose(VERB_ALGO, "RPZ: skipping invalid trigger");
649 		return 1;
650 	}
651 	if(t == RPZ_QNAME_TRIGGER) {
652 		rpz_insert_qname_trigger(r, policydname, policydnamelen,
653 			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
654 			rr_len);
655 	}
656 	else if(t == RPZ_RESPONSE_IP_TRIGGER) {
657 		rpz_insert_response_ip_trigger(r, policydname, policydnamelen,
658 			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
659 			rr_len);
660 		free(policydname);
661 	}
662 	else {
663 		free(policydname);
664 		verbose(VERB_ALGO, "RPZ: skipping unsupported trigger: %s",
665 			rpz_trigger_to_string(t));
666 	}
667 	return 1;
668 }
669 
670 /**
671  * Find RPZ local-zone by qname.
672  * @param r: rpz containing local-zone tree
673  * @param qname: qname
674  * @param qname_len: length of qname
675  * @param qclass: qclass
676  * @param only_exact: if 1 only excact (non wildcard) matches are returned
677  * @param wr: get write lock for local-zone if 1, read lock if 0
678  * @param zones_keep_lock: if set do not release the r->local_zones lock, this
679  * 	  makes the caller of this function responsible for releasing the lock.
680  * @return: NULL or local-zone holding rd or wr lock
681  */
682 static struct local_zone*
683 rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass,
684 	int only_exact, int wr, int zones_keep_lock)
685 {
686 	uint8_t* ce;
687 	size_t ce_len;
688 	int ce_labs;
689 	uint8_t wc[LDNS_MAX_DOMAINLEN+1];
690 	int exact;
691 	struct local_zone* z = NULL;
692 	if(wr) {
693 		lock_rw_wrlock(&r->local_zones->lock);
694 	} else {
695 		lock_rw_rdlock(&r->local_zones->lock);
696 	}
697 	z = local_zones_find_le(r->local_zones, qname, qname_len,
698 		dname_count_labels(qname),
699 		LDNS_RR_CLASS_IN, &exact);
700 	if(!z || (only_exact && !exact)) {
701 		lock_rw_unlock(&r->local_zones->lock);
702 		return NULL;
703 	}
704 	if(wr) {
705 		lock_rw_wrlock(&z->lock);
706 	} else {
707 		lock_rw_rdlock(&z->lock);
708 	}
709 	if(!zones_keep_lock) {
710 		lock_rw_unlock(&r->local_zones->lock);
711 	}
712 
713 	if(exact)
714 		return z;
715 
716 	/* No exact match found, lookup wildcard. closest encloser must
717 	 * be the shared parent between the qname and the best local
718 	 * zone match, append '*' to that and do another lookup. */
719 
720 	ce = dname_get_shared_topdomain(z->name, qname);
721 	if(!ce /* should not happen */) {
722 		lock_rw_unlock(&z->lock);
723 		if(zones_keep_lock) {
724 			lock_rw_unlock(&r->local_zones->lock);
725 		}
726 		return NULL;
727 	}
728 	ce_labs = dname_count_size_labels(ce, &ce_len);
729 	if(ce_len+2 > sizeof(wc)) {
730 		lock_rw_unlock(&z->lock);
731 		if(zones_keep_lock) {
732 			lock_rw_unlock(&r->local_zones->lock);
733 		}
734 		return NULL;
735 	}
736 	wc[0] = 1; /* length of wildcard label */
737 	wc[1] = (uint8_t)'*'; /* wildcard label */
738 	memmove(wc+2, ce, ce_len);
739 	lock_rw_unlock(&z->lock);
740 
741 	if(!zones_keep_lock) {
742 		if(wr) {
743 			lock_rw_wrlock(&r->local_zones->lock);
744 		} else {
745 			lock_rw_rdlock(&r->local_zones->lock);
746 		}
747 	}
748 	z = local_zones_find_le(r->local_zones, wc,
749 		ce_len+2, ce_labs+1, qclass, &exact);
750 	if(!z || !exact) {
751 		lock_rw_unlock(&r->local_zones->lock);
752 		return NULL;
753 	}
754 	if(wr) {
755 		lock_rw_wrlock(&z->lock);
756 	} else {
757 		lock_rw_rdlock(&z->lock);
758 	}
759 	if(!zones_keep_lock) {
760 		lock_rw_unlock(&r->local_zones->lock);
761 	}
762 	return z;
763 }
764 
765 /**
766  * Remove RR from RPZ's local-data
767  * @param z: local-zone for RPZ, holding write lock
768  * @param policydname: dname of RR to remove
769  * @param policydnamelen: lenth of policydname
770  * @param rr_type: RR type of RR to remove
771  * @param rdata: rdata of RR to remove
772  * @param rdatalen: length of rdata
773  * @return: 1 if zone must be removed after RR deletion
774  */
775 static int
776 rpz_data_delete_rr(struct local_zone* z, uint8_t* policydname,
777 	size_t policydnamelen, uint16_t rr_type, uint8_t* rdata,
778 	size_t rdatalen)
779 {
780 	struct local_data* ld;
781 	struct packed_rrset_data* d;
782 	size_t index;
783 	ld = local_zone_find_data(z, policydname, policydnamelen,
784 		dname_count_labels(policydname));
785 	if(ld) {
786 		struct local_rrset* prev=NULL, *p=ld->rrsets;
787 		while(p && ntohs(p->rrset->rk.type) != rr_type) {
788 			prev = p;
789 			p = p->next;
790 		}
791 		if(!p)
792 			return 0;
793 		d = (struct packed_rrset_data*)p->rrset->entry.data;
794 		if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
795 			if(d->count == 1) {
796 				/* no memory recycling for zone deletions ... */
797 				if(prev) prev->next = p->next;
798 				else ld->rrsets = p->next;
799 			}
800 			if(d->count > 1) {
801 				if(!local_rrset_remove_rr(d, index))
802 					return 0;
803 			}
804 		}
805 	}
806 	if(ld && ld->rrsets)
807 		return 0;
808 	return 1;
809 }
810 
811 /**
812  * Remove RR from RPZ's respip set
813  * @param raddr: respip node
814  * @param rr_type: RR type of RR to remove
815  * @param rdata: rdata of RR to remove
816  * @param rdatalen: length of rdata
817  * @return: 1 if zone must be removed after RR deletion
818  */
819 static int
820 rpz_rrset_delete_rr(struct resp_addr* raddr, uint16_t rr_type, uint8_t* rdata,
821 	size_t rdatalen)
822 {
823 	size_t index;
824 	struct packed_rrset_data* d;
825 	if(!raddr->data)
826 		return 1;
827 	d = raddr->data->entry.data;
828 	if(ntohs(raddr->data->rk.type) != rr_type) {
829 		return 0;
830 	}
831 	if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
832 		if(d->count == 1) {
833 			/* regional alloc'd */
834 			raddr->data->entry.data = NULL;
835 			raddr->data = NULL;
836 			return 1;
837 		}
838 		if(d->count > 1) {
839 			if(!local_rrset_remove_rr(d, index))
840 				return 0;
841 		}
842 	}
843 	return 0;
844 
845 }
846 
847 /** Remove RR from RPZ's local-zone */
848 static void
849 rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
850 	enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
851 	uint8_t* rdatawl, size_t rdatalen)
852 {
853 	struct local_zone* z;
854 	int delete_zone = 1;
855 	z = rpz_find_zone(r, dname, dnamelen, rr_class,
856 		1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/);
857 	if(!z) {
858 		verbose(VERB_ALGO, "RPZ: cannot remove RR from IXFR, "
859 			"RPZ domain not found");
860 		return;
861 	}
862 	if(a == RPZ_LOCAL_DATA_ACTION)
863 		delete_zone = rpz_data_delete_rr(z, dname,
864 			dnamelen, rr_type, rdatawl, rdatalen);
865 	else if(a != localzone_type_to_rpz_action(z->type)) {
866 		lock_rw_unlock(&z->lock);
867 		lock_rw_unlock(&r->local_zones->lock);
868 		return;
869 	}
870 	lock_rw_unlock(&z->lock);
871 	if(delete_zone) {
872 		local_zones_del_zone(r->local_zones, z);
873 	}
874 	lock_rw_unlock(&r->local_zones->lock);
875 	return;
876 }
877 
878 static void
879 rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
880 	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
881 {
882 	struct resp_addr* node;
883 	struct sockaddr_storage addr;
884 	socklen_t addrlen;
885 	int net, af;
886 	int delete_respip = 1;
887 
888 	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
889 		return;
890 
891 	lock_rw_wrlock(&r->respip_set->lock);
892 	if(!(node = (struct resp_addr*)addr_tree_find(
893 		&r->respip_set->ip_tree, &addr, addrlen, net))) {
894 		verbose(VERB_ALGO, "RPZ: cannot remove RR from IXFR, "
895 			"RPZ domain not found");
896 		lock_rw_unlock(&r->respip_set->lock);
897 		return;
898 	}
899 
900 	lock_rw_wrlock(&node->lock);
901 	if(a == RPZ_LOCAL_DATA_ACTION) {
902 		/* remove RR, signal whether RR can be removed */
903 		delete_respip = rpz_rrset_delete_rr(node, rr_type, rdatawl,
904 			rdatalen);
905 	}
906 	lock_rw_unlock(&node->lock);
907 	if(delete_respip)
908 		respip_sockaddr_delete(r->respip_set, node);
909 	lock_rw_unlock(&r->respip_set->lock);
910 }
911 
912 void
913 rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname, size_t dnamelen,
914 	uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen)
915 {
916 	size_t policydnamelen;
917 	enum rpz_trigger t;
918 	enum rpz_action a;
919 	uint8_t* policydname;
920 
921 	if(!(policydname = calloc(1, LDNS_MAX_DOMAINLEN + 1)))
922 		return;
923 
924 	a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
925 	if(a == RPZ_INVALID_ACTION) {
926 		free(policydname);
927 		return;
928 	}
929 	if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
930 		policydname, LDNS_MAX_DOMAINLEN + 1))) {
931 		free(policydname);
932 		return;
933 	}
934 	t = rpz_dname_to_trigger(policydname, policydnamelen);
935 	if(t == RPZ_QNAME_TRIGGER) {
936 		rpz_remove_qname_trigger(r, policydname, policydnamelen, a,
937 			rr_type, rr_class, rdatawl, rdatalen);
938 	} else if(t == RPZ_RESPONSE_IP_TRIGGER) {
939 		rpz_remove_response_ip_trigger(r, policydname, policydnamelen,
940 			a, rr_type, rdatawl, rdatalen);
941 	}
942 	free(policydname);
943 }
944 
945 /** print log information for an applied RPZ policy. Based on local-zone's
946  * lz_inform_print().
947  */
948 static void
949 log_rpz_apply(uint8_t* dname, enum rpz_action a, struct query_info* qinfo,
950 	struct comm_reply* repinfo, char* log_name)
951 {
952 	char ip[128], txt[512];
953 	char dnamestr[LDNS_MAX_DOMAINLEN+1];
954 	uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
955 	dname_str(dname, dnamestr);
956 	addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
957 	if(log_name)
958 		snprintf(txt, sizeof(txt), "RPZ applied [%s] %s %s %s@%u",
959 			log_name, dnamestr, rpz_action_to_string(a), ip,
960 			(unsigned)port);
961 	else
962 		snprintf(txt, sizeof(txt), "RPZ applied %s %s %s@%u",
963 			dnamestr, rpz_action_to_string(a), ip, (unsigned)port);
964 	log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
965 }
966 
967 int
968 rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
969 	struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
970 	struct regional* temp, struct comm_reply* repinfo,
971 	uint8_t* taglist, size_t taglen, struct ub_server_stats* stats)
972 {
973 	struct rpz* r = NULL;
974 	struct auth_zone* a;
975 	int ret;
976 	enum localzone_type lzt;
977 	struct local_zone* z = NULL;
978 	struct local_data* ld = NULL;
979 	lock_rw_rdlock(&az->rpz_lock);
980 	for(a = az->rpz_first; a; a = a->rpz_az_next) {
981 		lock_rw_rdlock(&a->lock);
982 		r = a->rpz;
983 		if(!r->disabled && (!r->taglist || taglist_intersect(r->taglist,
984 			r->taglistlen, taglist, taglen))) {
985 			z = rpz_find_zone(r, qinfo->qname, qinfo->qname_len,
986 				qinfo->qclass, 0, 0, 0);
987 			if(z && r->action_override == RPZ_DISABLED_ACTION) {
988 				if(r->log)
989 					log_rpz_apply(z->name,
990 						r->action_override,
991 						qinfo, repinfo, r->log_name);
992 				/* TODO only register stats when stats_extended?
993 				 * */
994 				stats->rpz_action[r->action_override]++;
995 				lock_rw_unlock(&z->lock);
996 				z = NULL;
997 			}
998 			if(z)
999 				break;
1000 		}
1001 		lock_rw_unlock(&a->lock); /* not found in this auth_zone */
1002 	}
1003 	lock_rw_unlock(&az->rpz_lock);
1004 	if(!z)
1005 		return 0; /* not holding auth_zone.lock anymore */
1006 
1007 	log_assert(r);
1008 	if(r->action_override == RPZ_NO_OVERRIDE_ACTION)
1009 		lzt = z->type;
1010 	else
1011 		lzt = rpz_action_to_localzone_type(r->action_override);
1012 
1013 	if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
1014 		qinfo->local_alias =
1015 			regional_alloc_zero(temp, sizeof(struct local_rrset));
1016 		if(!qinfo->local_alias) {
1017 			lock_rw_unlock(&z->lock);
1018 			lock_rw_unlock(&a->lock);
1019 			return 0; /* out of memory */
1020 		}
1021 		qinfo->local_alias->rrset =
1022 			regional_alloc_init(temp, r->cname_override,
1023 				sizeof(*r->cname_override));
1024 		if(!qinfo->local_alias->rrset) {
1025 			lock_rw_unlock(&z->lock);
1026 			lock_rw_unlock(&a->lock);
1027 			return 0; /* out of memory */
1028 		}
1029 		qinfo->local_alias->rrset->rk.dname = qinfo->qname;
1030 		qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
1031 		if(r->log)
1032 			log_rpz_apply(z->name, RPZ_CNAME_OVERRIDE_ACTION,
1033 				qinfo, repinfo, r->log_name);
1034 		stats->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
1035 		lock_rw_unlock(&z->lock);
1036 		lock_rw_unlock(&a->lock);
1037 		return 0;
1038 	}
1039 
1040 	if(lzt == local_zone_redirect && local_data_answer(z, env, qinfo,
1041 		edns, repinfo, buf, temp, dname_count_labels(qinfo->qname),
1042 		&ld, lzt, -1, NULL, 0, NULL, 0)) {
1043 		if(r->log)
1044 			log_rpz_apply(z->name,
1045 				localzone_type_to_rpz_action(lzt), qinfo,
1046 				repinfo, r->log_name);
1047 		stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
1048 		lock_rw_unlock(&z->lock);
1049 		lock_rw_unlock(&a->lock);
1050 		return !qinfo->local_alias;
1051 	}
1052 
1053 	ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp,
1054 		0 /* no local data used */, lzt);
1055 	if(r->log)
1056 		log_rpz_apply(z->name, localzone_type_to_rpz_action(lzt),
1057 			qinfo, repinfo, r->log_name);
1058 	stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
1059 	lock_rw_unlock(&z->lock);
1060 	lock_rw_unlock(&a->lock);
1061 
1062 	return ret;
1063 }
1064 
1065 void rpz_enable(struct rpz* r)
1066 {
1067     if(!r)
1068         return;
1069     r->disabled = 0;
1070 }
1071 
1072 void rpz_disable(struct rpz* r)
1073 {
1074     if(!r)
1075         return;
1076     r->disabled = 1;
1077 }
1078