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