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("cannot parse RPZ 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 if(p->rpz_log_name) {
546 if(!(r->log_name = strdup(p->rpz_log_name))) {
547 log_err("malloc failure on RPZ log_name strdup");
548 goto err;
549 }
550 }
551 return r;
552 err:
553 if(r) {
554 if(r->local_zones)
555 local_zones_delete(r->local_zones);
556 if(r->nsdname_zones)
557 local_zones_delete(r->nsdname_zones);
558 if(r->respip_set)
559 respip_set_delete(r->respip_set);
560 if(r->client_set != NULL)
561 rpz_clientip_synthesized_set_delete(r->client_set);
562 if(r->ns_set != NULL)
563 rpz_clientip_synthesized_set_delete(r->ns_set);
564 if(r->taglist)
565 free(r->taglist);
566 if(r->region)
567 regional_destroy(r->region);
568 free(r);
569 }
570 return NULL;
571 }
572
573 /**
574 * Remove RPZ zone name from dname
575 * Copy dname to newdname, without the originlen number of trailing bytes
576 */
577 static size_t
strip_dname_origin(uint8_t * dname,size_t dnamelen,size_t originlen,uint8_t * newdname,size_t maxnewdnamelen)578 strip_dname_origin(uint8_t* dname, size_t dnamelen, size_t originlen,
579 uint8_t* newdname, size_t maxnewdnamelen)
580 {
581 size_t newdnamelen;
582 if(dnamelen < originlen)
583 return 0;
584 newdnamelen = dnamelen - originlen;
585 if(newdnamelen+1 > maxnewdnamelen)
586 return 0;
587 memmove(newdname, dname, newdnamelen);
588 newdname[newdnamelen] = 0;
589 return newdnamelen + 1; /* + 1 for root label */
590 }
591
592 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)593 rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
594 size_t dnamelen, enum rpz_action a, uint16_t rrtype, uint16_t rrclass,
595 uint32_t ttl, uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
596 {
597 struct local_zone* z;
598 enum localzone_type tp = local_zone_always_transparent;
599 int dnamelabs = dname_count_labels(dname);
600 int newzone = 0;
601
602 if(a == RPZ_INVALID_ACTION) {
603 char str[255+1];
604 if(rrtype == LDNS_RR_TYPE_SOA || rrtype == LDNS_RR_TYPE_NS ||
605 rrtype == LDNS_RR_TYPE_DNAME ||
606 rrtype == LDNS_RR_TYPE_DNSKEY ||
607 rrtype == LDNS_RR_TYPE_RRSIG ||
608 rrtype == LDNS_RR_TYPE_NSEC ||
609 rrtype == LDNS_RR_TYPE_NSEC3PARAM ||
610 rrtype == LDNS_RR_TYPE_NSEC3 ||
611 rrtype == LDNS_RR_TYPE_DS) {
612 free(dname);
613 return; /* no need to log these types as unsupported */
614 }
615 dname_str(dname, str);
616 verbose(VERB_ALGO, "RPZ: qname trigger, %s skipping unsupported action: %s",
617 str, rpz_action_to_string(a));
618 free(dname);
619 return;
620 }
621
622 lock_rw_wrlock(&lz->lock);
623 /* exact match */
624 z = local_zones_find(lz, dname, dnamelen, dnamelabs, LDNS_RR_CLASS_IN);
625 if(z != NULL && a != RPZ_LOCAL_DATA_ACTION) {
626 char* rrstr = sldns_wire2str_rr(rr, rr_len);
627 if(rrstr == NULL) {
628 log_err("malloc error while inserting rpz nsdname trigger");
629 free(dname);
630 lock_rw_unlock(&lz->lock);
631 return;
632 }
633 if(rrstr[0])
634 rrstr[strlen(rrstr)-1]=0; /* remove newline */
635 verbose(VERB_ALGO, "rpz: skipping duplicate record: '%s'", rrstr);
636 free(rrstr);
637 free(dname);
638 lock_rw_unlock(&lz->lock);
639 return;
640 }
641 if(z == NULL) {
642 tp = rpz_action_to_localzone_type(a);
643 z = local_zones_add_zone(lz, dname, dnamelen,
644 dnamelabs, rrclass, tp);
645 if(z == NULL) {
646 log_warn("rpz: create failed");
647 lock_rw_unlock(&lz->lock);
648 /* dname will be free'd in failed local_zone_create() */
649 return;
650 }
651 newzone = 1;
652 }
653 if(a == RPZ_LOCAL_DATA_ACTION) {
654 char* rrstr = sldns_wire2str_rr(rr, rr_len);
655 if(rrstr == NULL) {
656 log_err("malloc error while inserting rpz nsdname trigger");
657 free(dname);
658 lock_rw_unlock(&lz->lock);
659 return;
660 }
661 lock_rw_wrlock(&z->lock);
662 local_zone_enter_rr(z, dname, dnamelen, dnamelabs, rrtype,
663 rrclass, ttl, rdata, rdata_len, rrstr);
664 lock_rw_unlock(&z->lock);
665 free(rrstr);
666 }
667 if(!newzone) {
668 free(dname);
669 }
670 lock_rw_unlock(&lz->lock);
671 }
672
673 static void
rpz_log_dname(char const * msg,uint8_t * dname,size_t dname_len)674 rpz_log_dname(char const* msg, uint8_t* dname, size_t dname_len)
675 {
676 char buf[LDNS_MAX_DOMAINLEN+1];
677 (void)dname_len;
678 dname_str(dname, buf);
679 verbose(VERB_ALGO, "rpz: %s: <%s>", msg, buf);
680 }
681
682 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)683 rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
684 enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
685 uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
686 {
687 if(a == RPZ_INVALID_ACTION) {
688 verbose(VERB_ALGO, "rpz: skipping invalid action");
689 free(dname);
690 return;
691 }
692
693 rpz_insert_local_zones_trigger(r->local_zones, dname, dnamelen, a, rrtype,
694 rrclass, ttl, rdata, rdata_len, rr, rr_len);
695 }
696
697 static int
rpz_strip_nsdname_suffix(uint8_t * dname,size_t maxdnamelen,uint8_t ** stripdname,size_t * stripdnamelen)698 rpz_strip_nsdname_suffix(uint8_t* dname, size_t maxdnamelen,
699 uint8_t** stripdname, size_t* stripdnamelen)
700 {
701 uint8_t* tldstart = get_tld_label(dname, maxdnamelen);
702 uint8_t swap;
703 if(tldstart == NULL) {
704 if(dname == NULL) {
705 *stripdname = NULL;
706 *stripdnamelen = 0;
707 return 0;
708 }
709 *stripdname = memdup(dname, maxdnamelen);
710 if(!*stripdname) {
711 *stripdnamelen = 0;
712 log_err("malloc failure for rpz strip suffix");
713 return 0;
714 }
715 *stripdnamelen = maxdnamelen;
716 return 1;
717 }
718 /* shorten the domain name briefly,
719 * then we allocate a new name with the correct length */
720 swap = *tldstart;
721 *tldstart = 0;
722 (void)dname_count_size_labels(dname, stripdnamelen);
723 *stripdname = memdup(dname, *stripdnamelen);
724 *tldstart = swap;
725 if(!*stripdname) {
726 *stripdnamelen = 0;
727 log_err("malloc failure for rpz strip suffix");
728 return 0;
729 }
730 return 1;
731 }
732
733 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)734 rpz_insert_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
735 enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
736 uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
737 {
738 uint8_t* dname_stripped = NULL;
739 size_t dnamelen_stripped = 0;
740
741 rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
742 &dnamelen_stripped);
743 if(a == RPZ_INVALID_ACTION) {
744 verbose(VERB_ALGO, "rpz: skipping invalid action");
745 free(dname_stripped);
746 return;
747 }
748
749 /* dname_stripped is consumed or freed by the insert routine */
750 rpz_insert_local_zones_trigger(r->nsdname_zones, dname_stripped,
751 dnamelen_stripped, a, rrtype, rrclass, ttl, rdata, rdata_len,
752 rr, rr_len);
753 }
754
755 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)756 rpz_insert_ipaddr_based_trigger(struct respip_set* set, struct sockaddr_storage* addr,
757 socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype,
758 uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len,
759 uint8_t* rr, size_t rr_len)
760 {
761 struct resp_addr* node;
762 char* rrstr;
763 enum respip_action respa = rpz_action_to_respip_action(a);
764
765 lock_rw_wrlock(&set->lock);
766 rrstr = sldns_wire2str_rr(rr, rr_len);
767 if(rrstr == NULL) {
768 log_err("malloc error while inserting rpz ipaddr based trigger");
769 lock_rw_unlock(&set->lock);
770 return 0;
771 }
772
773 node = respip_sockaddr_find_or_create(set, addr, addrlen, net, 1, rrstr);
774 if(node == NULL) {
775 lock_rw_unlock(&set->lock);
776 free(rrstr);
777 return 0;
778 }
779
780 lock_rw_wrlock(&node->lock);
781 lock_rw_unlock(&set->lock);
782
783 node->action = respa;
784
785 if(a == RPZ_LOCAL_DATA_ACTION) {
786 respip_enter_rr(set->region, node, rrtype,
787 rrclass, ttl, rdata, rdata_len, rrstr, "");
788 }
789
790 lock_rw_unlock(&node->lock);
791 free(rrstr);
792 return 1;
793 }
794
795 static inline struct clientip_synthesized_rr*
rpz_clientip_ensure_entry(struct clientip_synthesized_rrset * set,struct sockaddr_storage * addr,socklen_t addrlen,int net)796 rpz_clientip_ensure_entry(struct clientip_synthesized_rrset* set,
797 struct sockaddr_storage* addr, socklen_t addrlen, int net)
798 {
799 int insert_ok;
800 struct clientip_synthesized_rr* node =
801 (struct clientip_synthesized_rr*)addr_tree_find(&set->entries,
802 addr, addrlen, net);
803
804 if(node != NULL) { return node; }
805
806 /* node does not yet exist => allocate one */
807 node = regional_alloc_zero(set->region, sizeof(*node));
808 if(node == NULL) {
809 log_err("out of memory");
810 return NULL;
811 }
812
813 lock_rw_init(&node->lock);
814 node->action = RPZ_INVALID_ACTION;
815 insert_ok = addr_tree_insert(&set->entries, &node->node,
816 addr, addrlen, net);
817 if (!insert_ok) {
818 log_warn("rpz: unexpected: unable to insert clientip address node");
819 /* we can not free the just allocated node.
820 * theoretically a memleak */
821 return NULL;
822 }
823
824 return node;
825 }
826
827 static void
rpz_report_rrset_error(const char * msg,uint8_t * rr,size_t rr_len)828 rpz_report_rrset_error(const char* msg, uint8_t* rr, size_t rr_len) {
829 char* rrstr = sldns_wire2str_rr(rr, rr_len);
830 if(rrstr == NULL) {
831 log_err("malloc error while inserting rpz clientip based record");
832 return;
833 }
834 log_err("rpz: unexpected: unable to insert %s: %s", msg, rrstr);
835 free(rrstr);
836 }
837
838 /* from localzone.c; difference is we don't have a dname */
839 struct local_rrset*
rpz_clientip_new_rrset(struct regional * region,struct clientip_synthesized_rr * raddr,uint16_t rrtype,uint16_t rrclass)840 rpz_clientip_new_rrset(struct regional* region,
841 struct clientip_synthesized_rr* raddr, uint16_t rrtype, uint16_t rrclass)
842 {
843 struct packed_rrset_data* pd;
844 struct local_rrset* rrset = (struct local_rrset*)
845 regional_alloc_zero(region, sizeof(*rrset));
846 if(rrset == NULL) {
847 log_err("out of memory");
848 return NULL;
849 }
850 rrset->next = raddr->data;
851 raddr->data = rrset;
852 rrset->rrset = (struct ub_packed_rrset_key*)
853 regional_alloc_zero(region, sizeof(*rrset->rrset));
854 if(rrset->rrset == NULL) {
855 log_err("out of memory");
856 return NULL;
857 }
858 rrset->rrset->entry.key = rrset->rrset;
859 pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd));
860 if(pd == NULL) {
861 log_err("out of memory");
862 return NULL;
863 }
864 pd->trust = rrset_trust_prim_noglue;
865 pd->security = sec_status_insecure;
866 rrset->rrset->entry.data = pd;
867 rrset->rrset->rk.type = htons(rrtype);
868 rrset->rrset->rk.rrset_class = htons(rrclass);
869 rrset->rrset->rk.dname = regional_alloc_zero(region, 1);
870 if(rrset->rrset->rk.dname == NULL) {
871 log_err("out of memory");
872 return NULL;
873 }
874 rrset->rrset->rk.dname_len = 1;
875 return rrset;
876 }
877
878 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)879 rpz_clientip_enter_rr(struct regional* region, struct clientip_synthesized_rr* raddr,
880 uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata,
881 size_t rdata_len)
882 {
883 struct local_rrset* rrset;
884 if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data != NULL) {
885 log_err("CNAME response-ip data can not co-exist with other "
886 "client-ip data");
887 return 0;
888 }
889
890 rrset = rpz_clientip_new_rrset(region, raddr, rrtype, rrclass);
891 if(raddr->data == NULL) {
892 return 0;
893 }
894
895 return rrset_insert_rr(region, rrset->rrset->entry.data, rdata, rdata_len, ttl, "");
896 }
897
898 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)899 rpz_clientip_insert_trigger_rr(struct clientip_synthesized_rrset* set, struct sockaddr_storage* addr,
900 socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype,
901 uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len,
902 uint8_t* rr, size_t rr_len)
903 {
904 struct clientip_synthesized_rr* node;
905
906 lock_rw_wrlock(&set->lock);
907
908 node = rpz_clientip_ensure_entry(set, addr, addrlen, net);
909 if(node == NULL) {
910 lock_rw_unlock(&set->lock);
911 rpz_report_rrset_error("client ip address", rr, rr_len);
912 return 0;
913 }
914
915 lock_rw_wrlock(&node->lock);
916 lock_rw_unlock(&set->lock);
917
918 node->action = a;
919 if(a == RPZ_LOCAL_DATA_ACTION) {
920 if(!rpz_clientip_enter_rr(set->region, node, rrtype,
921 rrclass, ttl, rdata, rdata_len)) {
922 verbose(VERB_ALGO, "rpz: unable to insert clientip rr");
923 lock_rw_unlock(&node->lock);
924 return 0;
925 }
926
927 }
928
929 lock_rw_unlock(&node->lock);
930
931 return 1;
932 }
933
934 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)935 rpz_insert_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
936 enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
937 uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
938 {
939 struct sockaddr_storage addr;
940 socklen_t addrlen;
941 int net, af;
942
943 if(a == RPZ_INVALID_ACTION) {
944 return 0;
945 }
946
947 if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
948 verbose(VERB_ALGO, "rpz: unable to parse client ip");
949 return 0;
950 }
951
952 return rpz_clientip_insert_trigger_rr(r->client_set, &addr, addrlen, net,
953 a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
954 }
955
956 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)957 rpz_insert_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
958 enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
959 uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
960 {
961 struct sockaddr_storage addr;
962 socklen_t addrlen;
963 int net, af;
964
965 if(a == RPZ_INVALID_ACTION) {
966 return 0;
967 }
968
969 if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
970 verbose(VERB_ALGO, "rpz: unable to parse ns ip");
971 return 0;
972 }
973
974 return rpz_clientip_insert_trigger_rr(r->ns_set, &addr, addrlen, net,
975 a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
976 }
977
978 /** Insert RR into RPZ's respip_set */
979 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)980 rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
981 enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
982 uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
983 {
984 struct sockaddr_storage addr;
985 socklen_t addrlen;
986 int net, af;
987
988 if(a == RPZ_INVALID_ACTION) {
989 return 0;
990 }
991
992 if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
993 verbose(VERB_ALGO, "rpz: unable to parse response ip");
994 return 0;
995 }
996
997 if(a == RPZ_INVALID_ACTION ||
998 rpz_action_to_respip_action(a) == respip_invalid) {
999 char str[255+1];
1000 dname_str(dname, str);
1001 verbose(VERB_ALGO, "RPZ: respip trigger, %s skipping unsupported action: %s",
1002 str, rpz_action_to_string(a));
1003 return 0;
1004 }
1005
1006 return rpz_insert_ipaddr_based_trigger(r->respip_set, &addr, addrlen, net,
1007 a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
1008 }
1009
1010 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)1011 rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
1012 size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
1013 uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len)
1014 {
1015 size_t policydnamelen;
1016 /* name is free'd in local_zone delete */
1017 enum rpz_trigger t;
1018 enum rpz_action a;
1019 uint8_t* policydname;
1020
1021 if(rpz_type_ignored(rr_type)) {
1022 /* this rpz action is not valid, eg. this is the SOA or NS RR */
1023 return 1;
1024 }
1025 if(!dname_subdomain_c(dname, azname)) {
1026 char* dname_str = sldns_wire2str_dname(dname, dnamelen);
1027 char* azname_str = sldns_wire2str_dname(azname, aznamelen);
1028 if(dname_str && azname_str) {
1029 log_err("rpz: name of record (%s) to insert into RPZ is not a "
1030 "subdomain of the configured name of the RPZ zone (%s)",
1031 dname_str, azname_str);
1032 } else {
1033 log_err("rpz: name of record to insert into RPZ is not a "
1034 "subdomain of the configured name of the RPZ zone");
1035 }
1036 free(dname_str);
1037 free(azname_str);
1038 return 0;
1039 }
1040
1041 log_assert(dnamelen >= aznamelen);
1042 if(!(policydname = calloc(1, (dnamelen-aznamelen)+1))) {
1043 log_err("malloc error while inserting RPZ RR");
1044 return 0;
1045 }
1046
1047 a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
1048 if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
1049 policydname, (dnamelen-aznamelen)+1))) {
1050 free(policydname);
1051 return 0;
1052 }
1053 t = rpz_dname_to_trigger(policydname, policydnamelen);
1054 if(t == RPZ_INVALID_TRIGGER) {
1055 free(policydname);
1056 verbose(VERB_ALGO, "rpz: skipping invalid trigger");
1057 return 1;
1058 }
1059 if(t == RPZ_QNAME_TRIGGER) {
1060 /* policydname will be consumed, no free */
1061 rpz_insert_qname_trigger(r, policydname, policydnamelen,
1062 a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1063 rr_len);
1064 } else if(t == RPZ_RESPONSE_IP_TRIGGER) {
1065 rpz_insert_response_ip_trigger(r, policydname, policydnamelen,
1066 a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1067 rr_len);
1068 free(policydname);
1069 } else if(t == RPZ_CLIENT_IP_TRIGGER) {
1070 rpz_insert_clientip_trigger(r, policydname, policydnamelen,
1071 a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1072 rr_len);
1073 free(policydname);
1074 } else if(t == RPZ_NSIP_TRIGGER) {
1075 rpz_insert_nsip_trigger(r, policydname, policydnamelen,
1076 a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1077 rr_len);
1078 free(policydname);
1079 } else if(t == RPZ_NSDNAME_TRIGGER) {
1080 rpz_insert_nsdname_trigger(r, policydname, policydnamelen,
1081 a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1082 rr_len);
1083 free(policydname);
1084 } else {
1085 free(policydname);
1086 verbose(VERB_ALGO, "rpz: skipping unsupported trigger: %s",
1087 rpz_trigger_to_string(t));
1088 }
1089 return 1;
1090 }
1091
1092 /**
1093 * Find RPZ local-zone by qname.
1094 * @param zones: local-zone tree
1095 * @param qname: qname
1096 * @param qname_len: length of qname
1097 * @param qclass: qclass
1098 * @param only_exact: if 1 only exact (non wildcard) matches are returned
1099 * @param wr: get write lock for local-zone if 1, read lock if 0
1100 * @param zones_keep_lock: if set do not release the r->local_zones lock, this
1101 * makes the caller of this function responsible for releasing the lock.
1102 * @return: NULL or local-zone holding rd or wr lock
1103 */
1104 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)1105 rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint16_t qclass,
1106 int only_exact, int wr, int zones_keep_lock)
1107 {
1108 uint8_t* ce;
1109 size_t ce_len;
1110 int ce_labs;
1111 uint8_t wc[LDNS_MAX_DOMAINLEN+1];
1112 int exact;
1113 struct local_zone* z = NULL;
1114
1115 if(wr) {
1116 lock_rw_wrlock(&zones->lock);
1117 } else {
1118 lock_rw_rdlock(&zones->lock);
1119 }
1120 z = local_zones_find_le(zones, qname, qname_len,
1121 dname_count_labels(qname),
1122 LDNS_RR_CLASS_IN, &exact);
1123 if(!z || (only_exact && !exact)) {
1124 if(!zones_keep_lock) {
1125 lock_rw_unlock(&zones->lock);
1126 }
1127 return NULL;
1128 }
1129 if(wr) {
1130 lock_rw_wrlock(&z->lock);
1131 } else {
1132 lock_rw_rdlock(&z->lock);
1133 }
1134 if(!zones_keep_lock) {
1135 lock_rw_unlock(&zones->lock);
1136 }
1137
1138 if(exact)
1139 return z;
1140
1141 /* No exact match found, lookup wildcard. closest encloser must
1142 * be the shared parent between the qname and the best local
1143 * zone match, append '*' to that and do another lookup. */
1144
1145 ce = dname_get_shared_topdomain(z->name, qname);
1146 if(!ce /* should not happen */) {
1147 lock_rw_unlock(&z->lock);
1148 if(zones_keep_lock) {
1149 lock_rw_unlock(&zones->lock);
1150 }
1151 return NULL;
1152 }
1153 ce_labs = dname_count_size_labels(ce, &ce_len);
1154 if(ce_len+2 > sizeof(wc)) {
1155 lock_rw_unlock(&z->lock);
1156 if(zones_keep_lock) {
1157 lock_rw_unlock(&zones->lock);
1158 }
1159 return NULL;
1160 }
1161 wc[0] = 1; /* length of wildcard label */
1162 wc[1] = (uint8_t)'*'; /* wildcard label */
1163 memmove(wc+2, ce, ce_len);
1164 lock_rw_unlock(&z->lock);
1165
1166 if(!zones_keep_lock) {
1167 if(wr) {
1168 lock_rw_wrlock(&zones->lock);
1169 } else {
1170 lock_rw_rdlock(&zones->lock);
1171 }
1172 }
1173 z = local_zones_find_le(zones, wc,
1174 ce_len+2, ce_labs+1, qclass, &exact);
1175 if(!z || !exact) {
1176 lock_rw_unlock(&zones->lock);
1177 return NULL;
1178 }
1179 if(wr) {
1180 lock_rw_wrlock(&z->lock);
1181 } else {
1182 lock_rw_rdlock(&z->lock);
1183 }
1184 if(!zones_keep_lock) {
1185 lock_rw_unlock(&zones->lock);
1186 }
1187 return z;
1188 }
1189
1190 /**
1191 * Remove RR from RPZ's local-data
1192 * @param z: local-zone for RPZ, holding write lock
1193 * @param policydname: dname of RR to remove
1194 * @param policydnamelen: length of policydname
1195 * @param rr_type: RR type of RR to remove
1196 * @param rdata: rdata of RR to remove
1197 * @param rdatalen: length of rdata
1198 * @return: 1 if zone must be removed after RR deletion
1199 */
1200 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)1201 rpz_data_delete_rr(struct local_zone* z, uint8_t* policydname,
1202 size_t policydnamelen, uint16_t rr_type, uint8_t* rdata,
1203 size_t rdatalen)
1204 {
1205 struct local_data* ld;
1206 struct packed_rrset_data* d;
1207 size_t index;
1208 ld = local_zone_find_data(z, policydname, policydnamelen,
1209 dname_count_labels(policydname));
1210 if(ld) {
1211 struct local_rrset* prev=NULL, *p=ld->rrsets;
1212 while(p && ntohs(p->rrset->rk.type) != rr_type) {
1213 prev = p;
1214 p = p->next;
1215 }
1216 if(!p)
1217 return 0;
1218 d = (struct packed_rrset_data*)p->rrset->entry.data;
1219 if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
1220 if(d->count == 1) {
1221 /* no memory recycling for zone deletions ... */
1222 if(prev) prev->next = p->next;
1223 else ld->rrsets = p->next;
1224 }
1225 if(d->count > 1) {
1226 if(!local_rrset_remove_rr(d, index))
1227 return 0;
1228 }
1229 }
1230 }
1231 if(ld && ld->rrsets)
1232 return 0;
1233 return 1;
1234 }
1235
1236 /**
1237 * Remove RR from RPZ's respip set
1238 * @param raddr: respip node
1239 * @param rr_type: RR type of RR to remove
1240 * @param rdata: rdata of RR to remove
1241 * @param rdatalen: length of rdata
1242 * @return: 1 if zone must be removed after RR deletion
1243 */
1244 static int
rpz_rrset_delete_rr(struct resp_addr * raddr,uint16_t rr_type,uint8_t * rdata,size_t rdatalen)1245 rpz_rrset_delete_rr(struct resp_addr* raddr, uint16_t rr_type, uint8_t* rdata,
1246 size_t rdatalen)
1247 {
1248 size_t index;
1249 struct packed_rrset_data* d;
1250 if(!raddr->data)
1251 return 1;
1252 d = raddr->data->entry.data;
1253 if(ntohs(raddr->data->rk.type) != rr_type) {
1254 return 0;
1255 }
1256 if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
1257 if(d->count == 1) {
1258 /* regional alloc'd */
1259 raddr->data->entry.data = NULL;
1260 raddr->data = NULL;
1261 return 1;
1262 }
1263 if(d->count > 1) {
1264 if(!local_rrset_remove_rr(d, index))
1265 return 0;
1266 }
1267 }
1268 return 0;
1269
1270 }
1271
1272 /** Remove RR from RPZ's local-zone */
1273 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)1274 rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1275 enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
1276 uint8_t* rdatawl, size_t rdatalen)
1277 {
1278 struct local_zone* z;
1279 int delete_zone = 1;
1280 z = rpz_find_zone(r->local_zones, dname, dnamelen, rr_class,
1281 1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/);
1282 if(!z) {
1283 verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1284 "RPZ domain not found");
1285 return;
1286 }
1287 if(a == RPZ_LOCAL_DATA_ACTION)
1288 delete_zone = rpz_data_delete_rr(z, dname,
1289 dnamelen, rr_type, rdatawl, rdatalen);
1290 else if(a != localzone_type_to_rpz_action(z->type)) {
1291 lock_rw_unlock(&z->lock);
1292 lock_rw_unlock(&r->local_zones->lock);
1293 return;
1294 }
1295 lock_rw_unlock(&z->lock);
1296 if(delete_zone) {
1297 local_zones_del_zone(r->local_zones, z);
1298 }
1299 lock_rw_unlock(&r->local_zones->lock);
1300 return;
1301 }
1302
1303 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)1304 rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1305 enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1306 {
1307 struct resp_addr* node;
1308 struct sockaddr_storage addr;
1309 socklen_t addrlen;
1310 int net, af;
1311 int delete_respip = 1;
1312
1313 if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1314 return;
1315
1316 lock_rw_wrlock(&r->respip_set->lock);
1317 if(!(node = (struct resp_addr*)addr_tree_find(
1318 &r->respip_set->ip_tree, &addr, addrlen, net))) {
1319 verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1320 "RPZ domain not found");
1321 lock_rw_unlock(&r->respip_set->lock);
1322 return;
1323 }
1324
1325 lock_rw_wrlock(&node->lock);
1326 if(a == RPZ_LOCAL_DATA_ACTION) {
1327 /* remove RR, signal whether RR can be removed */
1328 delete_respip = rpz_rrset_delete_rr(node, rr_type, rdatawl,
1329 rdatalen);
1330 }
1331 lock_rw_unlock(&node->lock);
1332 if(delete_respip)
1333 respip_sockaddr_delete(r->respip_set, node);
1334 lock_rw_unlock(&r->respip_set->lock);
1335 }
1336
1337 void
rpz_remove_rr(struct rpz * r,size_t aznamelen,uint8_t * dname,size_t dnamelen,uint16_t rr_type,uint16_t rr_class,uint8_t * rdatawl,size_t rdatalen)1338 rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname, size_t dnamelen,
1339 uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen)
1340 {
1341 size_t policydnamelen;
1342 enum rpz_trigger t;
1343 enum rpz_action a;
1344 uint8_t* policydname;
1345
1346 if(!(policydname = calloc(1, LDNS_MAX_DOMAINLEN + 1)))
1347 return;
1348
1349 a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
1350 if(a == RPZ_INVALID_ACTION) {
1351 free(policydname);
1352 return;
1353 }
1354 if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
1355 policydname, LDNS_MAX_DOMAINLEN + 1))) {
1356 free(policydname);
1357 return;
1358 }
1359 t = rpz_dname_to_trigger(policydname, policydnamelen);
1360 if(t == RPZ_QNAME_TRIGGER) {
1361 rpz_remove_qname_trigger(r, policydname, policydnamelen, a,
1362 rr_type, rr_class, rdatawl, rdatalen);
1363 } else if(t == RPZ_RESPONSE_IP_TRIGGER) {
1364 rpz_remove_response_ip_trigger(r, policydname, policydnamelen,
1365 a, rr_type, rdatawl, rdatalen);
1366 }
1367 free(policydname);
1368 }
1369
1370 /** print log information for an applied RPZ policy. Based on local-zone's
1371 * lz_inform_print().
1372 * The repinfo contains the reply address. If it is NULL, the module
1373 * state is used to report the first IP address (if any).
1374 * The dname is used, for the applied rpz, if NULL, addrnode is used.
1375 */
1376 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)1377 log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode,
1378 enum rpz_action a, struct query_info* qinfo,
1379 struct comm_reply* repinfo, struct module_qstate* ms, char* log_name)
1380 {
1381 char ip[128], txt[512], portstr[32];
1382 char dnamestr[LDNS_MAX_DOMAINLEN+1];
1383 uint16_t port = 0;
1384 if(dname) {
1385 dname_str(dname, dnamestr);
1386 } else if(addrnode) {
1387 char a[128];
1388 addr_to_str(&addrnode->addr, addrnode->addrlen, a, sizeof(a));
1389 snprintf(dnamestr, sizeof(dnamestr), "%s/%d", a, addrnode->net);
1390 } else {
1391 dnamestr[0]=0;
1392 }
1393 if(repinfo) {
1394 addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
1395 port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
1396 } else if(ms && ms->mesh_info && ms->mesh_info->reply_list) {
1397 addr_to_str(&ms->mesh_info->reply_list->query_reply.addr, ms->mesh_info->reply_list->query_reply.addrlen, ip, sizeof(ip));
1398 port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.addr)->sin_port);
1399 } else {
1400 ip[0]=0;
1401 port = 0;
1402 }
1403 snprintf(portstr, sizeof(portstr), "@%u", (unsigned)port);
1404 snprintf(txt, sizeof(txt), "rpz: applied %s%s%s%s%s%s %s %s%s",
1405 (log_name?"[":""), (log_name?log_name:""), (log_name?"] ":""),
1406 (strcmp(trigger,"qname")==0?"":trigger),
1407 (strcmp(trigger,"qname")==0?"":" "),
1408 dnamestr, rpz_action_to_string(a),
1409 (ip[0]?ip:""), (ip[0]?portstr:""));
1410 log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
1411 }
1412
1413 static struct clientip_synthesized_rr*
rpz_ipbased_trigger_lookup(struct clientip_synthesized_rrset * set,struct sockaddr_storage * addr,socklen_t addrlen,char * triggername)1414 rpz_ipbased_trigger_lookup(struct clientip_synthesized_rrset* set,
1415 struct sockaddr_storage* addr, socklen_t addrlen, char* triggername)
1416 {
1417 struct clientip_synthesized_rr* raddr = NULL;
1418 enum rpz_action action = RPZ_INVALID_ACTION;
1419
1420 lock_rw_rdlock(&set->lock);
1421
1422 raddr = (struct clientip_synthesized_rr*)addr_tree_lookup(&set->entries,
1423 addr, addrlen);
1424 if(raddr != NULL) {
1425 lock_rw_rdlock(&raddr->lock);
1426 action = raddr->action;
1427 if(verbosity >= VERB_ALGO) {
1428 char ip[256], net[256];
1429 addr_to_str(addr, addrlen, ip, sizeof(ip));
1430 addr_to_str(&raddr->node.addr, raddr->node.addrlen,
1431 net, sizeof(net));
1432 verbose(VERB_ALGO, "rpz: trigger %s %s/%d on %s action=%s",
1433 triggername, net, raddr->node.net, ip, rpz_action_to_string(action));
1434 }
1435 }
1436 lock_rw_unlock(&set->lock);
1437
1438 return raddr;
1439 }
1440
1441 static inline
1442 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)1443 rpz_resolve_client_action_and_zone(struct auth_zones* az, struct query_info* qinfo,
1444 struct comm_reply* repinfo, uint8_t* taglist, size_t taglen,
1445 struct ub_server_stats* stats,
1446 /* output parameters */
1447 struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out)
1448 {
1449 struct clientip_synthesized_rr* node = NULL;
1450 struct auth_zone* a = NULL;
1451 struct rpz* r = NULL;
1452 struct local_zone* z = NULL;
1453
1454 lock_rw_rdlock(&az->rpz_lock);
1455
1456 for(a = az->rpz_first; a; a = a->rpz_az_next) {
1457 lock_rw_rdlock(&a->lock);
1458 r = a->rpz;
1459 if(r->disabled) {
1460 lock_rw_unlock(&a->lock);
1461 continue;
1462 }
1463 if(r->taglist && !taglist_intersect(r->taglist,
1464 r->taglistlen, taglist, taglen)) {
1465 lock_rw_unlock(&a->lock);
1466 continue;
1467 }
1468 z = rpz_find_zone(r->local_zones, qinfo->qname, qinfo->qname_len,
1469 qinfo->qclass, 0, 0, 0);
1470 node = rpz_ipbased_trigger_lookup(r->client_set, &repinfo->addr, repinfo->addrlen, "clientip");
1471 if((z || node) && r->action_override == RPZ_DISABLED_ACTION) {
1472 if(r->log)
1473 log_rpz_apply((node?"clientip":"qname"),
1474 (z?z->name:NULL),
1475 (node?&node->node:NULL),
1476 r->action_override,
1477 qinfo, repinfo, NULL, r->log_name);
1478 stats->rpz_action[r->action_override]++;
1479 if(z != NULL) {
1480 lock_rw_unlock(&z->lock);
1481 z = NULL;
1482 }
1483 if(node != NULL) {
1484 lock_rw_unlock(&node->lock);
1485 node = NULL;
1486 }
1487 }
1488 if(z || node) {
1489 break;
1490 }
1491 /* not found in this auth_zone */
1492 lock_rw_unlock(&a->lock);
1493 }
1494
1495 lock_rw_unlock(&az->rpz_lock);
1496
1497 *r_out = r;
1498 *a_out = a;
1499 *z_out = z;
1500
1501 return node;
1502 }
1503
1504 static inline int
rpz_is_udp_query(struct comm_reply * repinfo)1505 rpz_is_udp_query(struct comm_reply* repinfo) {
1506 return repinfo != NULL
1507 ? (repinfo->c != NULL
1508 ? repinfo->c->type == comm_udp
1509 : 0)
1510 : 0;
1511 }
1512
1513 /** encode answer consisting of 1 rrset */
1514 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)1515 rpz_local_encode(struct module_env* env, struct query_info* qinfo,
1516 struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
1517 struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec,
1518 int rcode, struct ub_packed_rrset_key* soa_rrset)
1519 {
1520 struct reply_info rep;
1521 uint16_t udpsize;
1522 struct ub_packed_rrset_key* rrsetlist[3];
1523
1524 memset(&rep, 0, sizeof(rep));
1525 rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode);
1526 rep.qdcount = 1;
1527 rep.rrset_count = ansec;
1528 rep.rrsets = rrsetlist;
1529 if(ansec > 0) {
1530 rep.an_numrrsets = 1;
1531 rep.rrsets[0] = rrset;
1532 rep.ttl = ((struct packed_rrset_data*)rrset->entry.data)->rr_ttl[0];
1533 }
1534 if(soa_rrset != NULL) {
1535 rep.ar_numrrsets = 1;
1536 rep.rrsets[rep.rrset_count] = soa_rrset;
1537 rep.rrset_count ++;
1538 if(rep.ttl < ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0]) {
1539 rep.ttl = ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0];
1540 }
1541 }
1542
1543 udpsize = edns->udp_size;
1544 edns->edns_version = EDNS_ADVERTISED_VERSION;
1545 edns->udp_size = EDNS_ADVERTISED_SIZE;
1546 edns->ext_rcode = 0;
1547 edns->bits &= EDNS_DO;
1548 if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns,
1549 repinfo, temp, env->now_tv) ||
1550 !reply_info_answer_encode(qinfo, &rep,
1551 *(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2),
1552 buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) {
1553 error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
1554 *(uint16_t*)sldns_buffer_begin(buf),
1555 sldns_buffer_read_u16_at(buf, 2), edns);
1556 }
1557
1558 return 1;
1559 }
1560
1561 static struct local_rrset*
rpz_find_synthesized_rrset(int qtype,struct clientip_synthesized_rr * data)1562 rpz_find_synthesized_rrset(int qtype, struct clientip_synthesized_rr* data) {
1563 struct local_rrset* cursor = data->data;
1564 while( cursor != NULL) {
1565 struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
1566 if(htons(qtype) == packed_rrset->type) {
1567 return cursor;
1568 }
1569 cursor = cursor->next;
1570 }
1571 return NULL;
1572 }
1573
1574 /** allocate SOA record ubrrsetkey in region */
1575 static struct ub_packed_rrset_key*
make_soa_ubrrset(struct auth_zone * auth_zone,struct auth_rrset * soa,struct regional * temp)1576 make_soa_ubrrset(struct auth_zone* auth_zone, struct auth_rrset* soa,
1577 struct regional* temp)
1578 {
1579 struct ub_packed_rrset_key csoa;
1580 if(!soa)
1581 return NULL;
1582 memset(&csoa, 0, sizeof(csoa));
1583 csoa.entry.key = &csoa;
1584 csoa.rk.rrset_class = htons(LDNS_RR_CLASS_IN);
1585 csoa.rk.type = htons(LDNS_RR_TYPE_SOA);
1586 csoa.rk.flags |= PACKED_RRSET_FIXEDTTL
1587 | PACKED_RRSET_RPZ;
1588 csoa.rk.dname = auth_zone->name;
1589 csoa.rk.dname_len = auth_zone->namelen;
1590 csoa.entry.hash = rrset_key_hash(&csoa.rk);
1591 csoa.entry.data = soa->data;
1592 return respip_copy_rrset(&csoa, temp);
1593 }
1594
1595 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)1596 rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr,
1597 struct module_env* env, struct query_info* qinfo,
1598 struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
1599 struct regional* temp, struct auth_zone* auth_zone)
1600 {
1601 struct local_rrset* rrset;
1602 enum rpz_action action = RPZ_INVALID_ACTION;
1603 struct ub_packed_rrset_key* rp = NULL;
1604 struct ub_packed_rrset_key* rsoa = NULL;
1605 int rcode = LDNS_RCODE_NOERROR|BIT_AA;
1606 int rrset_count = 1;
1607
1608 /* prepare synthesized answer for client */
1609 action = raddr->action;
1610 if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL ) {
1611 verbose(VERB_ALGO, "rpz: bug: local-data action but no local data");
1612 return;
1613 }
1614
1615 /* check query type / rr type */
1616 rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr);
1617 if(rrset == NULL) {
1618 verbose(VERB_ALGO, "rpz: unable to find local-data for query");
1619 rrset_count = 0;
1620 goto nodata;
1621 }
1622
1623 rp = respip_copy_rrset(rrset->rrset, temp);
1624 if(!rp) {
1625 verbose(VERB_ALGO, "rpz: local data action: out of memory");
1626 return;
1627 }
1628
1629 rp->rk.flags |= PACKED_RRSET_FIXEDTTL | PACKED_RRSET_RPZ;
1630 rp->rk.dname = qinfo->qname;
1631 rp->rk.dname_len = qinfo->qname_len;
1632 rp->entry.hash = rrset_key_hash(&rp->rk);
1633 nodata:
1634 if(auth_zone) {
1635 struct auth_rrset* soa = NULL;
1636 soa = auth_zone_get_soa_rrset(auth_zone);
1637 if(soa) {
1638 rsoa = make_soa_ubrrset(auth_zone, soa, temp);
1639 if(!rsoa) {
1640 verbose(VERB_ALGO, "rpz: local data action soa: out of memory");
1641 return;
1642 }
1643 }
1644 }
1645
1646 rpz_local_encode(env, qinfo, edns, repinfo, buf, temp, rp,
1647 rrset_count, rcode, rsoa);
1648 }
1649
1650 /** add additional section SOA record to the reply.
1651 * Since this gets fed into the normal iterator answer creation, it
1652 * gets minimal-responses applied to it, that can remove the additional SOA
1653 * again. */
1654 static int
rpz_add_soa(struct reply_info * rep,struct module_qstate * ms,struct auth_zone * az)1655 rpz_add_soa(struct reply_info* rep, struct module_qstate* ms,
1656 struct auth_zone* az)
1657 {
1658 struct auth_rrset* soa = NULL;
1659 struct ub_packed_rrset_key* rsoa = NULL;
1660 struct ub_packed_rrset_key** prevrrsets;
1661 if(!az) return 1;
1662 soa = auth_zone_get_soa_rrset(az);
1663 if(!soa) return 1;
1664 if(!rep) return 0;
1665 rsoa = make_soa_ubrrset(az, soa, ms->region);
1666 if(!rsoa) return 0;
1667 prevrrsets = rep->rrsets;
1668 rep->rrsets = regional_alloc_zero(ms->region,
1669 sizeof(*rep->rrsets)*(rep->rrset_count+1));
1670 if(!rep->rrsets)
1671 return 0;
1672 if(prevrrsets && rep->rrset_count > 0)
1673 memcpy(rep->rrsets, prevrrsets, rep->rrset_count*sizeof(*rep->rrsets));
1674 rep->rrset_count++;
1675 rep->ar_numrrsets++;
1676 rep->rrsets[rep->rrset_count-1] = rsoa;
1677 return 1;
1678 }
1679
1680 static inline struct dns_msg*
rpz_dns_msg_new(struct regional * region)1681 rpz_dns_msg_new(struct regional* region)
1682 {
1683 struct dns_msg* msg =
1684 (struct dns_msg*)regional_alloc(region,
1685 sizeof(struct dns_msg));
1686 if(msg == NULL) { return NULL; }
1687 memset(msg, 0, sizeof(struct dns_msg));
1688
1689 return msg;
1690 }
1691
1692 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)1693 rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
1694 struct query_info* qinfo, struct auth_zone* az)
1695 {
1696 struct dns_msg* msg = rpz_dns_msg_new(ms->region);
1697 if(msg == NULL) { return msg; }
1698 msg->qinfo = *qinfo;
1699 msg->rep = construct_reply_info_base(ms->region,
1700 LDNS_RCODE_NOERROR | BIT_RD | BIT_QR | BIT_AA | BIT_RA,
1701 1, /* qd */
1702 0, /* ttl */
1703 0, /* prettl */
1704 0, /* expttl */
1705 0, /* an */
1706 0, /* ns */
1707 0, /* ar */
1708 0, /* total */
1709 sec_status_insecure);
1710 if(msg->rep)
1711 msg->rep->authoritative = 1;
1712 if(!rpz_add_soa(msg->rep, ms, az))
1713 return NULL;
1714 return msg;
1715 }
1716
1717 static inline struct dns_msg*
rpz_synthesize_nxdomain(struct rpz * ATTR_UNUSED (r),struct module_qstate * ms,struct query_info * qinfo,struct auth_zone * az)1718 rpz_synthesize_nxdomain(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
1719 struct query_info* qinfo, struct auth_zone* az)
1720 {
1721 struct dns_msg* msg = rpz_dns_msg_new(ms->region);
1722 if(msg == NULL) { return msg; }
1723 msg->qinfo = *qinfo;
1724 msg->rep = construct_reply_info_base(ms->region,
1725 LDNS_RCODE_NXDOMAIN | BIT_RD | BIT_QR | BIT_AA | BIT_RA,
1726 1, /* qd */
1727 0, /* ttl */
1728 0, /* prettl */
1729 0, /* expttl */
1730 0, /* an */
1731 0, /* ns */
1732 0, /* ar */
1733 0, /* total */
1734 sec_status_insecure);
1735 if(msg->rep)
1736 msg->rep->authoritative = 1;
1737 if(!rpz_add_soa(msg->rep, ms, az))
1738 return NULL;
1739 return msg;
1740 }
1741
1742 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)1743 rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
1744 struct query_info* qi, struct local_rrset* rrset, struct auth_zone* az)
1745 {
1746 struct dns_msg* msg = NULL;
1747 struct reply_info* new_reply_info;
1748 struct ub_packed_rrset_key* rp;
1749
1750
1751 msg = rpz_dns_msg_new(ms->region);
1752 if(msg == NULL) { return NULL; }
1753
1754 new_reply_info = construct_reply_info_base(ms->region,
1755 LDNS_RCODE_NOERROR | BIT_RD | BIT_QR | BIT_AA | BIT_RA,
1756 1, /* qd */
1757 0, /* ttl */
1758 0, /* prettl */
1759 0, /* expttl */
1760 1, /* an */
1761 0, /* ns */
1762 0, /* ar */
1763 1, /* total */
1764 sec_status_insecure);
1765 if(new_reply_info == NULL) {
1766 log_err("out of memory");
1767 return NULL;
1768 }
1769 new_reply_info->authoritative = 1;
1770 rp = respip_copy_rrset(rrset->rrset, ms->region);
1771 if(rp == NULL) {
1772 log_err("out of memory");
1773 return NULL;
1774 }
1775 rp->rk.dname = qi->qname;
1776 rp->rk.dname_len = qi->qname_len;
1777 /* this rrset is from the rpz data, or synthesized.
1778 * It is not actually from the network, so we flag it with this
1779 * flags as a fake RRset. If later the cache is used to look up
1780 * rrsets, then the fake ones are not returned (if you look without
1781 * the flag). For like CNAME lookups from the iterator or A, AAAA
1782 * lookups for nameserver targets, it would use the without flag
1783 * actual data. So that the actual network data and fake data
1784 * are kept track of separately. */
1785 rp->rk.flags |= PACKED_RRSET_RPZ;
1786 new_reply_info->rrsets[0] = rp;
1787 msg->rep = new_reply_info;
1788 if(!rpz_add_soa(msg->rep, ms, az))
1789 return NULL;
1790 return msg;
1791 }
1792
1793 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)1794 rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms,
1795 struct clientip_synthesized_rr* data, struct auth_zone* az)
1796 {
1797 struct query_info* qi = &ms->qinfo;
1798 struct local_rrset* rrset;
1799
1800 rrset = rpz_find_synthesized_rrset(qi->qtype, data);
1801 if(rrset == NULL) {
1802 verbose(VERB_ALGO, "rpz: nsip: no matching local data found");
1803 return NULL;
1804 }
1805
1806 return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
1807 }
1808
1809 /* copy'n'paste from localzone.c */
1810 static struct local_rrset*
local_data_find_type(struct local_data * data,uint16_t type,int alias_ok)1811 local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
1812 {
1813 struct local_rrset* p;
1814 type = htons(type);
1815 for(p = data->rrsets; p; p = p->next) {
1816 if(p->rrset->rk.type == type)
1817 return p;
1818 if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
1819 return p;
1820 }
1821 return NULL;
1822 }
1823
1824 /* based on localzone.c:local_data_answer() */
1825 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)1826 rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
1827 struct local_zone* z, struct matched_delegation_point const* match,
1828 struct auth_zone* az)
1829 {
1830 struct local_data key;
1831 struct local_data* ld;
1832 struct local_rrset* rrset;
1833
1834 if(match->dname == NULL) { return NULL; }
1835
1836 key.node.key = &key;
1837 key.name = match->dname;
1838 key.namelen = match->dname_len;
1839 key.namelabs = dname_count_labels(match->dname);
1840
1841 rpz_log_dname("nsdname local data", key.name, key.namelen);
1842
1843 ld = (struct local_data*)rbtree_search(&z->data, &key.node);
1844 if(ld == NULL) {
1845 verbose(VERB_ALGO, "rpz: nsdname: impossible: qname not found");
1846 return NULL;
1847 }
1848
1849 rrset = local_data_find_type(ld, ms->qinfo.qtype, 1);
1850 if(rrset == NULL) {
1851 verbose(VERB_ALGO, "rpz: nsdname: no matching local data found");
1852 return NULL;
1853 }
1854
1855 return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
1856 }
1857
1858 /* like local_data_answer for qname triggers after a cname */
1859 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)1860 rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms,
1861 struct query_info* qinfo, struct local_zone* z, struct auth_zone* az)
1862 {
1863 struct local_data key;
1864 struct local_data* ld;
1865 struct local_rrset* rrset;
1866 key.node.key = &key;
1867 key.name = qinfo->qname;
1868 key.namelen = qinfo->qname_len;
1869 key.namelabs = dname_count_labels(qinfo->qname);
1870 ld = (struct local_data*)rbtree_search(&z->data, &key.node);
1871 if(ld == NULL) {
1872 verbose(VERB_ALGO, "rpz: qname after cname: name not found");
1873 return NULL;
1874 }
1875 rrset = local_data_find_type(ld, qinfo->qtype, 1);
1876 if(rrset == NULL) {
1877 verbose(VERB_ALGO, "rpz: qname after cname: type not found");
1878 return NULL;
1879 }
1880 return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az);
1881 }
1882
1883 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)1884 rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
1885 struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo,
1886 struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
1887 struct comm_reply* repinfo, struct ub_server_stats* stats)
1888 {
1889 struct local_data* ld = NULL;
1890 int ret = 0;
1891 if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
1892 qinfo->local_alias = regional_alloc_zero(temp, sizeof(struct local_rrset));
1893 if(qinfo->local_alias == NULL) {
1894 return 0; /* out of memory */
1895 }
1896 qinfo->local_alias->rrset = regional_alloc_init(temp, r->cname_override,
1897 sizeof(*r->cname_override));
1898 if(qinfo->local_alias->rrset == NULL) {
1899 return 0; /* out of memory */
1900 }
1901 qinfo->local_alias->rrset->rk.dname = qinfo->qname;
1902 qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
1903 if(r->log) {
1904 log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION,
1905 qinfo, repinfo, NULL, r->log_name);
1906 }
1907 stats->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
1908 return 0;
1909 }
1910
1911 if(lzt == local_zone_redirect && local_data_answer(z, env, qinfo,
1912 edns, repinfo, buf, temp, dname_count_labels(qinfo->qname),
1913 &ld, lzt, -1, NULL, 0, NULL, 0)) {
1914 if(r->log) {
1915 log_rpz_apply("qname", z->name, NULL,
1916 localzone_type_to_rpz_action(lzt), qinfo,
1917 repinfo, NULL, r->log_name);
1918 }
1919 stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
1920 return !qinfo->local_alias;
1921 }
1922
1923 ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp,
1924 0 /* no local data used */, lzt);
1925 if(r->log) {
1926 log_rpz_apply("qname", z->name, NULL, localzone_type_to_rpz_action(lzt),
1927 qinfo, repinfo, NULL, r->log_name);
1928 }
1929 stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
1930 return ret;
1931 }
1932
1933 struct clientip_synthesized_rr*
rpz_delegation_point_ipbased_trigger_lookup(struct rpz * rpz,struct iter_qstate * is)1934 rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate* is)
1935 {
1936 struct delegpt_addr* cursor;
1937 struct clientip_synthesized_rr* action = NULL;
1938 if(is->dp == NULL) { return NULL; }
1939 for(cursor = is->dp->target_list;
1940 cursor != NULL;
1941 cursor = cursor->next_target) {
1942 if(cursor->bogus) { continue; }
1943 action = rpz_ipbased_trigger_lookup(rpz->ns_set, &cursor->addr,
1944 cursor->addrlen, "nsip");
1945 if(action != NULL) { return action; }
1946 }
1947 return NULL;
1948 }
1949
1950 struct dns_msg*
rpz_apply_nsip_trigger(struct module_qstate * ms,struct rpz * r,struct clientip_synthesized_rr * raddr,struct auth_zone * az)1951 rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
1952 struct clientip_synthesized_rr* raddr, struct auth_zone* az)
1953 {
1954 enum rpz_action action = raddr->action;
1955 struct dns_msg* ret = NULL;
1956
1957 if(r->action_override != RPZ_NO_OVERRIDE_ACTION) {
1958 verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)",
1959 rpz_action_to_string(r->action_override), rpz_action_to_string(action));
1960 action = r->action_override;
1961 }
1962
1963 if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) {
1964 verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data");
1965 ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
1966 goto done;
1967 }
1968
1969 switch(action) {
1970 case RPZ_NXDOMAIN_ACTION:
1971 ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
1972 break;
1973 case RPZ_NODATA_ACTION:
1974 ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
1975 break;
1976 case RPZ_TCP_ONLY_ACTION:
1977 /* basically a passthru here but the tcp-only will be
1978 * honored before the query gets sent. */
1979 ms->respip_action_info->action = respip_truncate;
1980 ret = NULL;
1981 break;
1982 case RPZ_DROP_ACTION:
1983 ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
1984 ms->is_drop = 1;
1985 break;
1986 case RPZ_LOCAL_DATA_ACTION:
1987 ret = rpz_synthesize_nsip_localdata(r, ms, raddr, az);
1988 if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
1989 break;
1990 case RPZ_PASSTHRU_ACTION:
1991 ret = NULL;
1992 break;
1993 default:
1994 verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
1995 rpz_action_to_string(action));
1996 ret = NULL;
1997 }
1998
1999 done:
2000 if(r->log)
2001 log_rpz_apply("nsip", NULL, &raddr->node,
2002 action, &ms->qinfo, NULL, ms, r->log_name);
2003 if(ms->env->worker)
2004 ms->env->worker->stats.rpz_action[action]++;
2005 lock_rw_unlock(&raddr->lock);
2006 return ret;
2007 }
2008
2009 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)2010 rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
2011 struct local_zone* z, struct matched_delegation_point const* match,
2012 struct auth_zone* az)
2013 {
2014 struct dns_msg* ret = NULL;
2015 enum rpz_action action = localzone_type_to_rpz_action(z->type);
2016
2017 if(r->action_override != RPZ_NO_OVERRIDE_ACTION) {
2018 verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)",
2019 rpz_action_to_string(r->action_override), rpz_action_to_string(action));
2020 action = r->action_override;
2021 }
2022
2023 switch(action) {
2024 case RPZ_NXDOMAIN_ACTION:
2025 ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
2026 break;
2027 case RPZ_NODATA_ACTION:
2028 ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
2029 break;
2030 case RPZ_TCP_ONLY_ACTION:
2031 /* basically a passthru here but the tcp-only will be
2032 * honored before the query gets sent. */
2033 ms->respip_action_info->action = respip_truncate;
2034 ret = NULL;
2035 break;
2036 case RPZ_DROP_ACTION:
2037 ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
2038 ms->is_drop = 1;
2039 break;
2040 case RPZ_LOCAL_DATA_ACTION:
2041 ret = rpz_synthesize_nsdname_localdata(r, ms, z, match, az);
2042 if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
2043 break;
2044 case RPZ_PASSTHRU_ACTION:
2045 ret = NULL;
2046 break;
2047 default:
2048 verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
2049 rpz_action_to_string(action));
2050 ret = NULL;
2051 }
2052
2053 if(r->log)
2054 log_rpz_apply("nsdname", match->dname, NULL,
2055 action, &ms->qinfo, NULL, ms, r->log_name);
2056 if(ms->env->worker)
2057 ms->env->worker->stats.rpz_action[action]++;
2058 lock_rw_unlock(&z->lock);
2059 return ret;
2060 }
2061
2062 static struct local_zone*
rpz_delegation_point_zone_lookup(struct delegpt * dp,struct local_zones * zones,uint16_t qclass,struct matched_delegation_point * match)2063 rpz_delegation_point_zone_lookup(struct delegpt* dp, struct local_zones* zones,
2064 uint16_t qclass,
2065 /* output parameter */
2066 struct matched_delegation_point* match)
2067 {
2068 struct delegpt_ns* nameserver;
2069 struct local_zone* z = NULL;
2070
2071 /* the rpz specs match the nameserver names (NS records), not the
2072 * name of the delegation point itself, to the nsdname triggers */
2073 for(nameserver = dp->nslist;
2074 nameserver != NULL;
2075 nameserver = nameserver->next) {
2076 z = rpz_find_zone(zones, nameserver->name, nameserver->namelen,
2077 qclass, 0, 0, 0);
2078 if(z != NULL) {
2079 match->dname = nameserver->name;
2080 match->dname_len = nameserver->namelen;
2081 if(verbosity >= VERB_ALGO) {
2082 char nm[255+1], zn[255+1];
2083 dname_str(match->dname, nm);
2084 dname_str(z->name, zn);
2085 if(strcmp(nm, zn) != 0)
2086 verbose(VERB_ALGO, "rpz: trigger nsdname %s on %s action=%s",
2087 zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type)));
2088 else
2089 verbose(VERB_ALGO, "rpz: trigger nsdname %s action=%s",
2090 nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type)));
2091 }
2092 break;
2093 }
2094 }
2095
2096 return z;
2097 }
2098
2099 struct dns_msg*
rpz_callback_from_iterator_module(struct module_qstate * ms,struct iter_qstate * is)2100 rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate* is)
2101 {
2102 struct auth_zones* az;
2103 struct auth_zone* a;
2104 struct clientip_synthesized_rr* raddr = NULL;
2105 struct rpz* r = NULL;
2106 struct local_zone* z = NULL;
2107 struct matched_delegation_point match = {0};
2108
2109 if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
2110
2111 az = ms->env->auth_zones;
2112
2113 verbose(VERB_ALGO, "rpz: iterator module callback: have_rpz=%d", az->rpz_first != NULL);
2114
2115 lock_rw_rdlock(&az->rpz_lock);
2116
2117 /* precedence of RPZ works, loosely, like this:
2118 * CNAMEs in order of the CNAME chain. rpzs in the order they are
2119 * configured. In an RPZ: first client-IP addr, then QNAME, then
2120 * response IP, then NSDNAME, then NSIP. Longest match first. Smallest
2121 * one from a set. */
2122 /* we use the precedence rules for the topics and triggers that
2123 * are pertinent at this stage of the resolve processing */
2124 for(a = az->rpz_first; a != NULL; a = a->rpz_az_next) {
2125 lock_rw_rdlock(&a->lock);
2126 r = a->rpz;
2127 if(r->disabled) {
2128 lock_rw_unlock(&a->lock);
2129 continue;
2130 }
2131
2132 /* the nsdname has precedence over the nsip triggers */
2133 z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
2134 ms->qinfo.qclass, &match);
2135 if(z != NULL) {
2136 lock_rw_unlock(&a->lock);
2137 break;
2138 }
2139
2140 raddr = rpz_delegation_point_ipbased_trigger_lookup(r, is);
2141 if(raddr != NULL) {
2142 lock_rw_unlock(&a->lock);
2143 break;
2144 }
2145 lock_rw_unlock(&a->lock);
2146 }
2147
2148 lock_rw_unlock(&az->rpz_lock);
2149
2150 if(raddr == NULL && z == NULL) { return NULL; }
2151 else if(raddr != NULL) {
2152 if(z) {
2153 lock_rw_unlock(&z->lock);
2154 }
2155 return rpz_apply_nsip_trigger(ms, r, raddr, a);
2156 } else if(z != NULL) {
2157 if(raddr) {
2158 lock_rw_unlock(&raddr->lock);
2159 }
2160 return rpz_apply_nsdname_trigger(ms, r, z, &match, a);
2161 } else { return NULL; }
2162 }
2163
rpz_callback_from_iterator_cname(struct module_qstate * ms,struct iter_qstate * is)2164 struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
2165 struct iter_qstate* is)
2166 {
2167 struct auth_zones* az;
2168 struct auth_zone* a = NULL;
2169 struct rpz* r = NULL;
2170 struct local_zone* z = NULL;
2171 enum localzone_type lzt;
2172 struct dns_msg* ret = NULL;
2173
2174 if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
2175 az = ms->env->auth_zones;
2176
2177 lock_rw_rdlock(&az->rpz_lock);
2178
2179 for(a = az->rpz_first; a; a = a->rpz_az_next) {
2180 lock_rw_rdlock(&a->lock);
2181 r = a->rpz;
2182 if(r->disabled) {
2183 lock_rw_unlock(&a->lock);
2184 continue;
2185 }
2186 z = rpz_find_zone(r->local_zones, is->qchase.qname,
2187 is->qchase.qname_len, is->qchase.qclass, 0, 0, 0);
2188 if(z && r->action_override == RPZ_DISABLED_ACTION) {
2189 if(r->log)
2190 log_rpz_apply("qname", z->name, NULL,
2191 r->action_override,
2192 &ms->qinfo, NULL, ms, r->log_name);
2193 if(ms->env->worker)
2194 ms->env->worker->stats.rpz_action[r->action_override]++;
2195 lock_rw_unlock(&z->lock);
2196 z = NULL;
2197 }
2198 if(z) {
2199 break;
2200 }
2201 /* not found in this auth_zone */
2202 lock_rw_unlock(&a->lock);
2203 }
2204 lock_rw_unlock(&az->rpz_lock);
2205
2206 if(z == NULL)
2207 return NULL;
2208 if(r->action_override == RPZ_NO_OVERRIDE_ACTION) {
2209 lzt = z->type;
2210 } else {
2211 lzt = rpz_action_to_localzone_type(r->action_override);
2212 }
2213
2214 if(verbosity >= VERB_ALGO) {
2215 char nm[255+1], zn[255+1];
2216 dname_str(is->qchase.qname, nm);
2217 dname_str(z->name, zn);
2218 if(strcmp(zn, nm) != 0)
2219 verbose(VERB_ALGO, "rpz: qname trigger after cname %s on %s, with action=%s",
2220 zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2221 else
2222 verbose(VERB_ALGO, "rpz: qname trigger after cname %s, with action=%s",
2223 nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2224 }
2225 switch(localzone_type_to_rpz_action(lzt)) {
2226 case RPZ_NXDOMAIN_ACTION:
2227 ret = rpz_synthesize_nxdomain(r, ms, &is->qchase, a);
2228 break;
2229 case RPZ_NODATA_ACTION:
2230 ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
2231 break;
2232 case RPZ_TCP_ONLY_ACTION:
2233 /* basically a passthru here but the tcp-only will be
2234 * honored before the query gets sent. */
2235 ms->respip_action_info->action = respip_truncate;
2236 ret = NULL;
2237 break;
2238 case RPZ_DROP_ACTION:
2239 ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
2240 ms->is_drop = 1;
2241 break;
2242 case RPZ_LOCAL_DATA_ACTION:
2243 ret = rpz_synthesize_qname_localdata_msg(r, ms, &is->qchase, z, a);
2244 if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); }
2245 break;
2246 case RPZ_PASSTHRU_ACTION:
2247 ret = NULL;
2248 break;
2249 default:
2250 verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'",
2251 rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2252 ret = NULL;
2253 }
2254 lock_rw_unlock(&z->lock);
2255 lock_rw_unlock(&a->lock);
2256 return ret;
2257 }
2258
2259 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)2260 rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
2261 struct query_info* qinfo, struct edns_data* edns, struct comm_reply* repinfo,
2262 uint8_t* taglist, size_t taglen, struct ub_server_stats* stats,
2263 sldns_buffer* buf, struct regional* temp,
2264 /* output parameters */
2265 struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out)
2266 {
2267 int ret = 0;
2268 enum rpz_action client_action;
2269 struct clientip_synthesized_rr* node = rpz_resolve_client_action_and_zone(
2270 az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out);
2271
2272 client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action);
2273
2274 if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
2275 client_action != RPZ_PASSTHRU_ACTION)) {
2276 if(client_action == RPZ_PASSTHRU_ACTION
2277 || client_action == RPZ_INVALID_ACTION
2278 || (client_action == RPZ_TCP_ONLY_ACTION
2279 && !rpz_is_udp_query(repinfo))) {
2280 ret = 0;
2281 goto done;
2282 }
2283 stats->rpz_action[client_action]++;
2284 if(client_action == RPZ_LOCAL_DATA_ACTION) {
2285 rpz_apply_clientip_localdata_action(node, env, qinfo,
2286 edns, repinfo, buf, temp, *a_out);
2287 } else {
2288 if(*r_out && (*r_out)->log)
2289 log_rpz_apply(
2290 (node?"clientip":"qname"),
2291 ((*z_out)?(*z_out)->name:NULL),
2292 (node?&node->node:NULL),
2293 client_action, qinfo, repinfo, NULL,
2294 (*r_out)->log_name);
2295 local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns,
2296 repinfo, buf, temp, 0 /* no local data used */,
2297 rpz_action_to_localzone_type(client_action));
2298 }
2299 ret = 1;
2300 goto done;
2301 }
2302 ret = -1;
2303 done:
2304 if(node != NULL) {
2305 lock_rw_unlock(&node->lock);
2306 }
2307 return ret;
2308 }
2309
2310 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)2311 rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
2312 struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
2313 struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist,
2314 size_t taglen, struct ub_server_stats* stats)
2315 {
2316 struct rpz* r = NULL;
2317 struct auth_zone* a = NULL;
2318 struct local_zone* z = NULL;
2319 int ret;
2320 enum localzone_type lzt;
2321
2322 int clientip_trigger = rpz_apply_maybe_clientip_trigger(az, env, qinfo,
2323 edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r);
2324 if(clientip_trigger >= 0) {
2325 if(a) {
2326 lock_rw_unlock(&a->lock);
2327 }
2328 if(z) {
2329 lock_rw_unlock(&z->lock);
2330 }
2331 return clientip_trigger;
2332 }
2333
2334 if(z == NULL) {
2335 if(a) {
2336 lock_rw_unlock(&a->lock);
2337 }
2338 return 0;
2339 }
2340
2341 log_assert(r);
2342
2343 if(r->action_override == RPZ_NO_OVERRIDE_ACTION) {
2344 lzt = z->type;
2345 } else {
2346 lzt = rpz_action_to_localzone_type(r->action_override);
2347 }
2348
2349 if(verbosity >= VERB_ALGO) {
2350 char nm[255+1], zn[255+1];
2351 dname_str(qinfo->qname, nm);
2352 dname_str(z->name, zn);
2353 if(strcmp(zn, nm) != 0)
2354 verbose(VERB_ALGO, "rpz: qname trigger %s on %s with action=%s",
2355 zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2356 else
2357 verbose(VERB_ALGO, "rpz: qname trigger %s with action=%s",
2358 nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2359 }
2360
2361 ret = rpz_synthesize_qname_localdata(env, r, z, lzt, qinfo, edns, buf, temp,
2362 repinfo, stats);
2363
2364 lock_rw_unlock(&z->lock);
2365 lock_rw_unlock(&a->lock);
2366
2367 return ret;
2368 }
2369
rpz_enable(struct rpz * r)2370 void rpz_enable(struct rpz* r)
2371 {
2372 if(!r)
2373 return;
2374 r->disabled = 0;
2375 }
2376
rpz_disable(struct rpz * r)2377 void rpz_disable(struct rpz* r)
2378 {
2379 if(!r)
2380 return;
2381 r->disabled = 1;
2382 }
2383