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