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