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