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 54 /** string for RPZ action enum */ 55 const char* 56 rpz_action_to_string(enum rpz_action a) 57 { 58 switch(a) { 59 case RPZ_NXDOMAIN_ACTION: return "nxdomain"; 60 case RPZ_NODATA_ACTION: return "nodata"; 61 case RPZ_PASSTHRU_ACTION: return "passthru"; 62 case RPZ_DROP_ACTION: return "drop"; 63 case RPZ_TCP_ONLY_ACTION: return "tcp_only"; 64 case RPZ_INVALID_ACTION: return "invalid"; 65 case RPZ_LOCAL_DATA_ACTION: return "local_data"; 66 case RPZ_DISABLED_ACTION: return "disabled"; 67 case RPZ_CNAME_OVERRIDE_ACTION: return "cname_override"; 68 case RPZ_NO_OVERRIDE_ACTION: return "no_override"; 69 } 70 return "unknown"; 71 } 72 73 /** RPZ action enum for config string */ 74 static enum rpz_action 75 rpz_config_to_action(char* a) 76 { 77 if(strcmp(a, "nxdomain") == 0) 78 return RPZ_NXDOMAIN_ACTION; 79 else if(strcmp(a, "nodata") == 0) 80 return RPZ_NODATA_ACTION; 81 else if(strcmp(a, "passthru") == 0) 82 return RPZ_PASSTHRU_ACTION; 83 else if(strcmp(a, "drop") == 0) 84 return RPZ_DROP_ACTION; 85 else if(strcmp(a, "tcp_only") == 0) 86 return RPZ_TCP_ONLY_ACTION; 87 else if(strcmp(a, "cname") == 0) 88 return RPZ_CNAME_OVERRIDE_ACTION; 89 else if(strcmp(a, "disabled") == 0) 90 return RPZ_DISABLED_ACTION; 91 return RPZ_INVALID_ACTION; 92 } 93 94 /** string for RPZ trigger enum */ 95 static const char* 96 rpz_trigger_to_string(enum rpz_trigger r) 97 { 98 switch(r) { 99 case RPZ_QNAME_TRIGGER: return "qname"; 100 case RPZ_CLIENT_IP_TRIGGER: return "client_ip"; 101 case RPZ_RESPONSE_IP_TRIGGER: return "response_ip"; 102 case RPZ_NSDNAME_TRIGGER: return "nsdname"; 103 case RPZ_NSIP_TRIGGER: return "nsip"; 104 case RPZ_INVALID_TRIGGER: return "invalid"; 105 } 106 return "unknown"; 107 } 108 109 /** 110 * Get the label that is just before the root label. 111 * @param dname: dname to work on 112 * @param maxdnamelen: maximum length of the dname 113 * @return: pointer to TLD label, NULL if not found or invalid dname 114 */ 115 static uint8_t* 116 get_tld_label(uint8_t* dname, size_t maxdnamelen) 117 { 118 uint8_t* prevlab = dname; 119 size_t dnamelen = 0; 120 121 /* one byte needed for label length */ 122 if(dnamelen+1 > maxdnamelen) 123 return NULL; 124 125 /* only root label */ 126 if(*dname == 0) 127 return NULL; 128 129 while(*dname) { 130 dnamelen += ((size_t)*dname)+1; 131 if(dnamelen+1 > maxdnamelen) 132 return NULL; 133 dname = dname+((size_t)*dname)+1; 134 if(*dname != 0) 135 prevlab = dname; 136 } 137 return prevlab; 138 } 139 140 /** 141 * Classify RPZ action for RR type/rdata 142 * @param rr_type: the RR type 143 * @param rdatawl: RDATA with 2 bytes length 144 * @param rdatalen: the length of rdatawl (including its 2 bytes length) 145 * @return: the RPZ action 146 */ 147 static enum rpz_action 148 rpz_rr_to_action(uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen) 149 { 150 char* endptr; 151 uint8_t* rdata; 152 int rdatalabs; 153 uint8_t* tldlab = NULL; 154 155 switch(rr_type) { 156 case LDNS_RR_TYPE_SOA: 157 case LDNS_RR_TYPE_NS: 158 case LDNS_RR_TYPE_DNAME: 159 /* all DNSSEC-related RRs must be ignored */ 160 case LDNS_RR_TYPE_DNSKEY: 161 case LDNS_RR_TYPE_DS: 162 case LDNS_RR_TYPE_RRSIG: 163 case LDNS_RR_TYPE_NSEC: 164 case LDNS_RR_TYPE_NSEC3: 165 case LDNS_RR_TYPE_NSEC3PARAM: 166 return RPZ_INVALID_ACTION; 167 case LDNS_RR_TYPE_CNAME: 168 break; 169 default: 170 return RPZ_LOCAL_DATA_ACTION; 171 } 172 173 /* use CNAME target to determine RPZ action */ 174 log_assert(rr_type == LDNS_RR_TYPE_CNAME); 175 if(rdatalen < 3) 176 return RPZ_INVALID_ACTION; 177 178 rdata = rdatawl + 2; /* 2 bytes of rdata length */ 179 if(dname_valid(rdata, rdatalen-2) != rdatalen-2) 180 return RPZ_INVALID_ACTION; 181 182 rdatalabs = dname_count_labels(rdata); 183 if(rdatalabs == 1) 184 return RPZ_NXDOMAIN_ACTION; 185 else if(rdatalabs == 2) { 186 if(dname_subdomain_c(rdata, (uint8_t*)&"\001*\000")) 187 return RPZ_NODATA_ACTION; 188 else if(dname_subdomain_c(rdata, 189 (uint8_t*)&"\014rpz-passthru\000")) 190 return RPZ_PASSTHRU_ACTION; 191 else if(dname_subdomain_c(rdata, (uint8_t*)&"\010rpz-drop\000")) 192 return RPZ_DROP_ACTION; 193 else if(dname_subdomain_c(rdata, 194 (uint8_t*)&"\014rpz-tcp-only\000")) 195 return RPZ_TCP_ONLY_ACTION; 196 } 197 198 /* all other TLDs starting with "rpz-" are invalid */ 199 tldlab = get_tld_label(rdata, rdatalen-2); 200 if(tldlab && dname_lab_startswith(tldlab, "rpz-", &endptr)) 201 return RPZ_INVALID_ACTION; 202 203 /* no special label found */ 204 return RPZ_LOCAL_DATA_ACTION; 205 } 206 207 static enum localzone_type 208 rpz_action_to_localzone_type(enum rpz_action a) 209 { 210 switch(a) { 211 case RPZ_NXDOMAIN_ACTION: return local_zone_always_nxdomain; 212 case RPZ_NODATA_ACTION: return local_zone_always_nodata; 213 case RPZ_DROP_ACTION: return local_zone_always_deny; 214 case RPZ_PASSTHRU_ACTION: return local_zone_always_transparent; 215 case RPZ_LOCAL_DATA_ACTION: /* fallthrough */ 216 case RPZ_CNAME_OVERRIDE_ACTION: return local_zone_redirect; 217 case RPZ_INVALID_ACTION: /* fallthrough */ 218 case RPZ_TCP_ONLY_ACTION: /* fallthrough */ 219 default: return local_zone_invalid; 220 } 221 } 222 223 enum respip_action 224 rpz_action_to_respip_action(enum rpz_action a) 225 { 226 switch(a) { 227 case RPZ_NXDOMAIN_ACTION: return respip_always_nxdomain; 228 case RPZ_NODATA_ACTION: return respip_always_nodata; 229 case RPZ_DROP_ACTION: return respip_always_deny; 230 case RPZ_PASSTHRU_ACTION: return respip_always_transparent; 231 case RPZ_LOCAL_DATA_ACTION: /* fallthrough */ 232 case RPZ_CNAME_OVERRIDE_ACTION: return respip_redirect; 233 case RPZ_INVALID_ACTION: /* fallthrough */ 234 case RPZ_TCP_ONLY_ACTION: /* fallthrough */ 235 default: return respip_invalid; 236 } 237 } 238 239 static enum rpz_action 240 localzone_type_to_rpz_action(enum localzone_type lzt) 241 { 242 switch(lzt) { 243 case local_zone_always_nxdomain: return RPZ_NXDOMAIN_ACTION; 244 case local_zone_always_nodata: return RPZ_NODATA_ACTION; 245 case local_zone_always_deny: return RPZ_DROP_ACTION; 246 case local_zone_always_transparent: return RPZ_PASSTHRU_ACTION; 247 case local_zone_redirect: return RPZ_LOCAL_DATA_ACTION; 248 case local_zone_invalid: 249 default: 250 return RPZ_INVALID_ACTION; 251 } 252 } 253 254 enum rpz_action 255 respip_action_to_rpz_action(enum respip_action a) 256 { 257 switch(a) { 258 case respip_always_nxdomain: return RPZ_NXDOMAIN_ACTION; 259 case respip_always_nodata: return RPZ_NODATA_ACTION; 260 case respip_always_deny: return RPZ_DROP_ACTION; 261 case respip_always_transparent: return RPZ_PASSTHRU_ACTION; 262 case respip_redirect: return RPZ_LOCAL_DATA_ACTION; 263 case respip_invalid: 264 default: 265 return RPZ_INVALID_ACTION; 266 } 267 } 268 269 /** 270 * Get RPZ trigger for dname 271 * @param dname: dname containing RPZ trigger 272 * @param dname_len: length of the dname 273 * @return: RPZ trigger enum 274 */ 275 static enum rpz_trigger 276 rpz_dname_to_trigger(uint8_t* dname, size_t dname_len) 277 { 278 uint8_t* tldlab; 279 char* endptr; 280 281 if(dname_valid(dname, dname_len) != dname_len) 282 return RPZ_INVALID_TRIGGER; 283 284 tldlab = get_tld_label(dname, dname_len); 285 if(!tldlab || !dname_lab_startswith(tldlab, "rpz-", &endptr)) 286 return RPZ_QNAME_TRIGGER; 287 288 if(dname_subdomain_c(tldlab, 289 (uint8_t*)&"\015rpz-client-ip\000")) 290 return RPZ_CLIENT_IP_TRIGGER; 291 else if(dname_subdomain_c(tldlab, (uint8_t*)&"\006rpz-ip\000")) 292 return RPZ_RESPONSE_IP_TRIGGER; 293 else if(dname_subdomain_c(tldlab, (uint8_t*)&"\013rpz-nsdname\000")) 294 return RPZ_NSDNAME_TRIGGER; 295 else if(dname_subdomain_c(tldlab, (uint8_t*)&"\010rpz-nsip\000")) 296 return RPZ_NSIP_TRIGGER; 297 298 return RPZ_QNAME_TRIGGER; 299 } 300 301 void rpz_delete(struct rpz* r) 302 { 303 if(!r) 304 return; 305 local_zones_delete(r->local_zones); 306 respip_set_delete(r->respip_set); 307 regional_destroy(r->region); 308 free(r->taglist); 309 free(r->log_name); 310 free(r); 311 } 312 313 int 314 rpz_clear(struct rpz* r) 315 { 316 /* must hold write lock on auth_zone */ 317 local_zones_delete(r->local_zones); 318 respip_set_delete(r->respip_set); 319 if(!(r->local_zones = local_zones_create())){ 320 return 0; 321 } 322 if(!(r->respip_set = respip_set_create())) { 323 return 0; 324 } 325 return 1; 326 } 327 328 void 329 rpz_finish_config(struct rpz* r) 330 { 331 lock_rw_wrlock(&r->respip_set->lock); 332 addr_tree_init_parents(&r->respip_set->ip_tree); 333 lock_rw_unlock(&r->respip_set->lock); 334 } 335 336 /** new rrset containing CNAME override, does not yet contain a dname */ 337 static struct ub_packed_rrset_key* 338 new_cname_override(struct regional* region, uint8_t* ct, size_t ctlen) 339 { 340 struct ub_packed_rrset_key* rrset; 341 struct packed_rrset_data* pd; 342 uint16_t rdlength = htons(ctlen); 343 rrset = (struct ub_packed_rrset_key*)regional_alloc_zero(region, 344 sizeof(*rrset)); 345 if(!rrset) { 346 log_err("out of memory"); 347 return NULL; 348 } 349 rrset->entry.key = rrset; 350 pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd)); 351 if(!pd) { 352 log_err("out of memory"); 353 return NULL; 354 } 355 pd->trust = rrset_trust_prim_noglue; 356 pd->security = sec_status_insecure; 357 358 pd->count = 1; 359 pd->rr_len = regional_alloc_zero(region, sizeof(*pd->rr_len)); 360 pd->rr_ttl = regional_alloc_zero(region, sizeof(*pd->rr_ttl)); 361 pd->rr_data = regional_alloc_zero(region, sizeof(*pd->rr_data)); 362 if(!pd->rr_len || !pd->rr_ttl || !pd->rr_data) { 363 log_err("out of memory"); 364 return NULL; 365 } 366 pd->rr_len[0] = ctlen+2; 367 pd->rr_ttl[0] = 3600; 368 pd->rr_data[0] = regional_alloc_zero(region, 2 /* rdlength */ + ctlen); 369 if(!pd->rr_data[0]) { 370 log_err("out of memory"); 371 return NULL; 372 } 373 memmove(pd->rr_data[0], &rdlength, 2); 374 memmove(pd->rr_data[0]+2, ct, ctlen); 375 376 rrset->entry.data = pd; 377 rrset->rk.type = htons(LDNS_RR_TYPE_CNAME); 378 rrset->rk.rrset_class = htons(LDNS_RR_CLASS_IN); 379 return rrset; 380 } 381 382 struct rpz* 383 rpz_create(struct config_auth* p) 384 { 385 struct rpz* r = calloc(1, sizeof(*r)); 386 if(!r) 387 goto err; 388 389 r->region = regional_create_custom(sizeof(struct regional)); 390 if(!r->region) { 391 goto err; 392 } 393 394 if(!(r->local_zones = local_zones_create())){ 395 goto err; 396 } 397 if(!(r->respip_set = respip_set_create())) { 398 goto err; 399 } 400 r->taglistlen = p->rpz_taglistlen; 401 r->taglist = memdup(p->rpz_taglist, r->taglistlen); 402 if(p->rpz_action_override) { 403 r->action_override = rpz_config_to_action(p->rpz_action_override); 404 } 405 else 406 r->action_override = RPZ_NO_OVERRIDE_ACTION; 407 408 if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) { 409 uint8_t nm[LDNS_MAX_DOMAINLEN+1]; 410 size_t nmlen = sizeof(nm); 411 412 if(!p->rpz_cname) { 413 log_err("RPZ override with cname action found, but no " 414 "rpz-cname-override configured"); 415 goto err; 416 } 417 418 if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) { 419 log_err("cannot parse RPZ cname override: %s", 420 p->rpz_cname); 421 goto err; 422 } 423 r->cname_override = new_cname_override(r->region, nm, nmlen); 424 if(!r->cname_override) { 425 goto err; 426 } 427 } 428 r->log = p->rpz_log; 429 if(p->rpz_log_name) { 430 if(!(r->log_name = strdup(p->rpz_log_name))) { 431 log_err("malloc failure on RPZ log_name strdup"); 432 goto err; 433 } 434 } 435 return r; 436 err: 437 if(r) { 438 if(r->local_zones) 439 local_zones_delete(r->local_zones); 440 if(r->respip_set) 441 respip_set_delete(r->respip_set); 442 if(r->taglist) 443 free(r->taglist); 444 if(r->region) 445 regional_destroy(r->region); 446 free(r); 447 } 448 return NULL; 449 } 450 451 /** 452 * Remove RPZ zone name from dname 453 * Copy dname to newdname, without the originlen number of trailing bytes 454 */ 455 static size_t 456 strip_dname_origin(uint8_t* dname, size_t dnamelen, size_t originlen, 457 uint8_t* newdname, size_t maxnewdnamelen) 458 { 459 size_t newdnamelen; 460 if(dnamelen < originlen) 461 return 0; 462 newdnamelen = dnamelen - originlen; 463 if(newdnamelen+1 > maxnewdnamelen) 464 return 0; 465 memmove(newdname, dname, newdnamelen); 466 newdname[newdnamelen] = 0; 467 return newdnamelen + 1; /* + 1 for root label */ 468 } 469 470 /** Insert RR into RPZ's local-zone */ 471 static void 472 rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, 473 enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, 474 uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) 475 { 476 struct local_zone* z; 477 enum localzone_type tp = local_zone_always_transparent; 478 int dnamelabs = dname_count_labels(dname); 479 char* rrstr; 480 int newzone = 0; 481 482 if(a == RPZ_TCP_ONLY_ACTION || a == RPZ_INVALID_ACTION) { 483 char str[255+1]; 484 if(rrtype == LDNS_RR_TYPE_SOA || rrtype == LDNS_RR_TYPE_NS || 485 rrtype == LDNS_RR_TYPE_DNAME || 486 rrtype == LDNS_RR_TYPE_DNSKEY || 487 rrtype == LDNS_RR_TYPE_RRSIG || 488 rrtype == LDNS_RR_TYPE_NSEC || 489 rrtype == LDNS_RR_TYPE_NSEC3PARAM || 490 rrtype == LDNS_RR_TYPE_NSEC3 || 491 rrtype == LDNS_RR_TYPE_DS) { 492 free(dname); 493 return; /* no need to log these types as unsupported */ 494 } 495 dname_str(dname, str); 496 verbose(VERB_ALGO, "RPZ: qname trigger, %s skipping unsupported action: %s", 497 str, rpz_action_to_string(a)); 498 free(dname); 499 return; 500 } 501 502 lock_rw_wrlock(&r->local_zones->lock); 503 /* exact match */ 504 z = local_zones_find(r->local_zones, dname, dnamelen, dnamelabs, 505 LDNS_RR_CLASS_IN); 506 if(z && a != RPZ_LOCAL_DATA_ACTION) { 507 rrstr = sldns_wire2str_rr(rr, rr_len); 508 if(!rrstr) { 509 log_err("malloc error while inserting RPZ qname " 510 "trigger"); 511 free(dname); 512 lock_rw_unlock(&r->local_zones->lock); 513 return; 514 } 515 verbose(VERB_ALGO, "RPZ: skipping duplicate record: '%s'", 516 rrstr); 517 free(rrstr); 518 free(dname); 519 lock_rw_unlock(&r->local_zones->lock); 520 return; 521 } 522 if(!z) { 523 tp = rpz_action_to_localzone_type(a); 524 if(!(z = local_zones_add_zone(r->local_zones, dname, dnamelen, 525 dnamelabs, rrclass, tp))) { 526 log_warn("RPZ create failed"); 527 lock_rw_unlock(&r->local_zones->lock); 528 /* dname will be free'd in failed local_zone_create() */ 529 return; 530 } 531 newzone = 1; 532 } 533 if(a == RPZ_LOCAL_DATA_ACTION) { 534 rrstr = sldns_wire2str_rr(rr, rr_len); 535 if(!rrstr) { 536 log_err("malloc error while inserting RPZ qname " 537 "trigger"); 538 free(dname); 539 lock_rw_unlock(&r->local_zones->lock); 540 return; 541 } 542 lock_rw_wrlock(&z->lock); 543 local_zone_enter_rr(z, dname, dnamelen, dnamelabs, 544 rrtype, rrclass, ttl, rdata, rdata_len, rrstr); 545 lock_rw_unlock(&z->lock); 546 free(rrstr); 547 } 548 if(!newzone) 549 free(dname); 550 lock_rw_unlock(&r->local_zones->lock); 551 return; 552 } 553 554 /** Insert RR into RPZ's respip_set */ 555 static int 556 rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, 557 enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, 558 uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) 559 { 560 struct resp_addr* node; 561 struct sockaddr_storage addr; 562 socklen_t addrlen; 563 int net, af; 564 char* rrstr; 565 enum respip_action respa = rpz_action_to_respip_action(a); 566 567 if(a == RPZ_TCP_ONLY_ACTION || a == RPZ_INVALID_ACTION || 568 respa == respip_invalid) { 569 char str[255+1]; 570 dname_str(dname, str); 571 verbose(VERB_ALGO, "RPZ: respip trigger, %s skipping unsupported action: %s", 572 str, rpz_action_to_string(a)); 573 return 0; 574 } 575 576 if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) 577 return 0; 578 579 lock_rw_wrlock(&r->respip_set->lock); 580 rrstr = sldns_wire2str_rr(rr, rr_len); 581 if(!rrstr) { 582 log_err("malloc error while inserting RPZ respip trigger"); 583 lock_rw_unlock(&r->respip_set->lock); 584 return 0; 585 } 586 if(!(node=respip_sockaddr_find_or_create(r->respip_set, &addr, addrlen, 587 net, 1, rrstr))) { 588 lock_rw_unlock(&r->respip_set->lock); 589 free(rrstr); 590 return 0; 591 } 592 593 lock_rw_wrlock(&node->lock); 594 lock_rw_unlock(&r->respip_set->lock); 595 node->action = respa; 596 597 if(a == RPZ_LOCAL_DATA_ACTION) { 598 respip_enter_rr(r->respip_set->region, node, rrtype, 599 rrclass, ttl, rdata, rdata_len, rrstr, ""); 600 } 601 lock_rw_unlock(&node->lock); 602 free(rrstr); 603 return 1; 604 } 605 606 int 607 rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname, 608 size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl, 609 uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len) 610 { 611 size_t policydnamelen; 612 /* name is free'd in local_zone delete */ 613 enum rpz_trigger t; 614 enum rpz_action a; 615 uint8_t* policydname; 616 617 if(!dname_subdomain_c(dname, azname)) { 618 char* dname_str = sldns_wire2str_dname(dname, dnamelen); 619 char* azname_str = sldns_wire2str_dname(azname, aznamelen); 620 if(dname_str && azname_str) { 621 log_err("RPZ: name of record (%s) to insert into RPZ is not a " 622 "subdomain of the configured name of the RPZ zone (%s)", 623 dname_str, azname_str); 624 } else { 625 log_err("RPZ: name of record to insert into RPZ is not a " 626 "subdomain of the configured name of the RPZ zone"); 627 } 628 free(dname_str); 629 free(azname_str); 630 return 0; 631 } 632 633 log_assert(dnamelen >= aznamelen); 634 if(!(policydname = calloc(1, (dnamelen-aznamelen)+1))) { 635 log_err("malloc error while inserting RPZ RR"); 636 return 0; 637 } 638 639 a = rpz_rr_to_action(rr_type, rdatawl, rdatalen); 640 if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen, 641 policydname, (dnamelen-aznamelen)+1))) { 642 free(policydname); 643 return 0; 644 } 645 t = rpz_dname_to_trigger(policydname, policydnamelen); 646 if(t == RPZ_INVALID_TRIGGER) { 647 free(policydname); 648 verbose(VERB_ALGO, "RPZ: skipping invalid trigger"); 649 return 1; 650 } 651 if(t == RPZ_QNAME_TRIGGER) { 652 rpz_insert_qname_trigger(r, policydname, policydnamelen, 653 a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr, 654 rr_len); 655 } 656 else if(t == RPZ_RESPONSE_IP_TRIGGER) { 657 rpz_insert_response_ip_trigger(r, policydname, policydnamelen, 658 a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr, 659 rr_len); 660 free(policydname); 661 } 662 else { 663 free(policydname); 664 verbose(VERB_ALGO, "RPZ: skipping unsupported trigger: %s", 665 rpz_trigger_to_string(t)); 666 } 667 return 1; 668 } 669 670 /** 671 * Find RPZ local-zone by qname. 672 * @param r: rpz containing local-zone tree 673 * @param qname: qname 674 * @param qname_len: length of qname 675 * @param qclass: qclass 676 * @param only_exact: if 1 only excact (non wildcard) matches are returned 677 * @param wr: get write lock for local-zone if 1, read lock if 0 678 * @param zones_keep_lock: if set do not release the r->local_zones lock, this 679 * makes the caller of this function responsible for releasing the lock. 680 * @return: NULL or local-zone holding rd or wr lock 681 */ 682 static struct local_zone* 683 rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass, 684 int only_exact, int wr, int zones_keep_lock) 685 { 686 uint8_t* ce; 687 size_t ce_len; 688 int ce_labs; 689 uint8_t wc[LDNS_MAX_DOMAINLEN+1]; 690 int exact; 691 struct local_zone* z = NULL; 692 if(wr) { 693 lock_rw_wrlock(&r->local_zones->lock); 694 } else { 695 lock_rw_rdlock(&r->local_zones->lock); 696 } 697 z = local_zones_find_le(r->local_zones, qname, qname_len, 698 dname_count_labels(qname), 699 LDNS_RR_CLASS_IN, &exact); 700 if(!z || (only_exact && !exact)) { 701 lock_rw_unlock(&r->local_zones->lock); 702 return NULL; 703 } 704 if(wr) { 705 lock_rw_wrlock(&z->lock); 706 } else { 707 lock_rw_rdlock(&z->lock); 708 } 709 if(!zones_keep_lock) { 710 lock_rw_unlock(&r->local_zones->lock); 711 } 712 713 if(exact) 714 return z; 715 716 /* No exact match found, lookup wildcard. closest encloser must 717 * be the shared parent between the qname and the best local 718 * zone match, append '*' to that and do another lookup. */ 719 720 ce = dname_get_shared_topdomain(z->name, qname); 721 if(!ce /* should not happen */) { 722 lock_rw_unlock(&z->lock); 723 if(zones_keep_lock) { 724 lock_rw_unlock(&r->local_zones->lock); 725 } 726 return NULL; 727 } 728 ce_labs = dname_count_size_labels(ce, &ce_len); 729 if(ce_len+2 > sizeof(wc)) { 730 lock_rw_unlock(&z->lock); 731 if(zones_keep_lock) { 732 lock_rw_unlock(&r->local_zones->lock); 733 } 734 return NULL; 735 } 736 wc[0] = 1; /* length of wildcard label */ 737 wc[1] = (uint8_t)'*'; /* wildcard label */ 738 memmove(wc+2, ce, ce_len); 739 lock_rw_unlock(&z->lock); 740 741 if(!zones_keep_lock) { 742 if(wr) { 743 lock_rw_wrlock(&r->local_zones->lock); 744 } else { 745 lock_rw_rdlock(&r->local_zones->lock); 746 } 747 } 748 z = local_zones_find_le(r->local_zones, wc, 749 ce_len+2, ce_labs+1, qclass, &exact); 750 if(!z || !exact) { 751 lock_rw_unlock(&r->local_zones->lock); 752 return NULL; 753 } 754 if(wr) { 755 lock_rw_wrlock(&z->lock); 756 } else { 757 lock_rw_rdlock(&z->lock); 758 } 759 if(!zones_keep_lock) { 760 lock_rw_unlock(&r->local_zones->lock); 761 } 762 return z; 763 } 764 765 /** 766 * Remove RR from RPZ's local-data 767 * @param z: local-zone for RPZ, holding write lock 768 * @param policydname: dname of RR to remove 769 * @param policydnamelen: lenth of policydname 770 * @param rr_type: RR type of RR to remove 771 * @param rdata: rdata of RR to remove 772 * @param rdatalen: length of rdata 773 * @return: 1 if zone must be removed after RR deletion 774 */ 775 static int 776 rpz_data_delete_rr(struct local_zone* z, uint8_t* policydname, 777 size_t policydnamelen, uint16_t rr_type, uint8_t* rdata, 778 size_t rdatalen) 779 { 780 struct local_data* ld; 781 struct packed_rrset_data* d; 782 size_t index; 783 ld = local_zone_find_data(z, policydname, policydnamelen, 784 dname_count_labels(policydname)); 785 if(ld) { 786 struct local_rrset* prev=NULL, *p=ld->rrsets; 787 while(p && ntohs(p->rrset->rk.type) != rr_type) { 788 prev = p; 789 p = p->next; 790 } 791 if(!p) 792 return 0; 793 d = (struct packed_rrset_data*)p->rrset->entry.data; 794 if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) { 795 if(d->count == 1) { 796 /* no memory recycling for zone deletions ... */ 797 if(prev) prev->next = p->next; 798 else ld->rrsets = p->next; 799 } 800 if(d->count > 1) { 801 if(!local_rrset_remove_rr(d, index)) 802 return 0; 803 } 804 } 805 } 806 if(ld && ld->rrsets) 807 return 0; 808 return 1; 809 } 810 811 /** 812 * Remove RR from RPZ's respip set 813 * @param raddr: respip node 814 * @param rr_type: RR type of RR to remove 815 * @param rdata: rdata of RR to remove 816 * @param rdatalen: length of rdata 817 * @return: 1 if zone must be removed after RR deletion 818 */ 819 static int 820 rpz_rrset_delete_rr(struct resp_addr* raddr, uint16_t rr_type, uint8_t* rdata, 821 size_t rdatalen) 822 { 823 size_t index; 824 struct packed_rrset_data* d; 825 if(!raddr->data) 826 return 1; 827 d = raddr->data->entry.data; 828 if(ntohs(raddr->data->rk.type) != rr_type) { 829 return 0; 830 } 831 if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) { 832 if(d->count == 1) { 833 /* regional alloc'd */ 834 raddr->data->entry.data = NULL; 835 raddr->data = NULL; 836 return 1; 837 } 838 if(d->count > 1) { 839 if(!local_rrset_remove_rr(d, index)) 840 return 0; 841 } 842 } 843 return 0; 844 845 } 846 847 /** Remove RR from RPZ's local-zone */ 848 static void 849 rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, 850 enum rpz_action a, uint16_t rr_type, uint16_t rr_class, 851 uint8_t* rdatawl, size_t rdatalen) 852 { 853 struct local_zone* z; 854 int delete_zone = 1; 855 z = rpz_find_zone(r, dname, dnamelen, rr_class, 856 1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/); 857 if(!z) { 858 verbose(VERB_ALGO, "RPZ: cannot remove RR from IXFR, " 859 "RPZ domain not found"); 860 return; 861 } 862 if(a == RPZ_LOCAL_DATA_ACTION) 863 delete_zone = rpz_data_delete_rr(z, dname, 864 dnamelen, rr_type, rdatawl, rdatalen); 865 else if(a != localzone_type_to_rpz_action(z->type)) { 866 lock_rw_unlock(&z->lock); 867 lock_rw_unlock(&r->local_zones->lock); 868 return; 869 } 870 lock_rw_unlock(&z->lock); 871 if(delete_zone) { 872 local_zones_del_zone(r->local_zones, z); 873 } 874 lock_rw_unlock(&r->local_zones->lock); 875 return; 876 } 877 878 static void 879 rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, 880 enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen) 881 { 882 struct resp_addr* node; 883 struct sockaddr_storage addr; 884 socklen_t addrlen; 885 int net, af; 886 int delete_respip = 1; 887 888 if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) 889 return; 890 891 lock_rw_wrlock(&r->respip_set->lock); 892 if(!(node = (struct resp_addr*)addr_tree_find( 893 &r->respip_set->ip_tree, &addr, addrlen, net))) { 894 verbose(VERB_ALGO, "RPZ: cannot remove RR from IXFR, " 895 "RPZ domain not found"); 896 lock_rw_unlock(&r->respip_set->lock); 897 return; 898 } 899 900 lock_rw_wrlock(&node->lock); 901 if(a == RPZ_LOCAL_DATA_ACTION) { 902 /* remove RR, signal whether RR can be removed */ 903 delete_respip = rpz_rrset_delete_rr(node, rr_type, rdatawl, 904 rdatalen); 905 } 906 lock_rw_unlock(&node->lock); 907 if(delete_respip) 908 respip_sockaddr_delete(r->respip_set, node); 909 lock_rw_unlock(&r->respip_set->lock); 910 } 911 912 void 913 rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname, size_t dnamelen, 914 uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen) 915 { 916 size_t policydnamelen; 917 enum rpz_trigger t; 918 enum rpz_action a; 919 uint8_t* policydname; 920 921 if(!(policydname = calloc(1, LDNS_MAX_DOMAINLEN + 1))) 922 return; 923 924 a = rpz_rr_to_action(rr_type, rdatawl, rdatalen); 925 if(a == RPZ_INVALID_ACTION) { 926 free(policydname); 927 return; 928 } 929 if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen, 930 policydname, LDNS_MAX_DOMAINLEN + 1))) { 931 free(policydname); 932 return; 933 } 934 t = rpz_dname_to_trigger(policydname, policydnamelen); 935 if(t == RPZ_QNAME_TRIGGER) { 936 rpz_remove_qname_trigger(r, policydname, policydnamelen, a, 937 rr_type, rr_class, rdatawl, rdatalen); 938 } else if(t == RPZ_RESPONSE_IP_TRIGGER) { 939 rpz_remove_response_ip_trigger(r, policydname, policydnamelen, 940 a, rr_type, rdatawl, rdatalen); 941 } 942 free(policydname); 943 } 944 945 /** print log information for an applied RPZ policy. Based on local-zone's 946 * lz_inform_print(). 947 */ 948 static void 949 log_rpz_apply(uint8_t* dname, enum rpz_action a, struct query_info* qinfo, 950 struct comm_reply* repinfo, char* log_name) 951 { 952 char ip[128], txt[512]; 953 char dnamestr[LDNS_MAX_DOMAINLEN+1]; 954 uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port); 955 dname_str(dname, dnamestr); 956 addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip)); 957 if(log_name) 958 snprintf(txt, sizeof(txt), "RPZ applied [%s] %s %s %s@%u", 959 log_name, dnamestr, rpz_action_to_string(a), ip, 960 (unsigned)port); 961 else 962 snprintf(txt, sizeof(txt), "RPZ applied %s %s %s@%u", 963 dnamestr, rpz_action_to_string(a), ip, (unsigned)port); 964 log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass); 965 } 966 967 int 968 rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env, 969 struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf, 970 struct regional* temp, struct comm_reply* repinfo, 971 uint8_t* taglist, size_t taglen, struct ub_server_stats* stats) 972 { 973 struct rpz* r = NULL; 974 struct auth_zone* a; 975 int ret; 976 enum localzone_type lzt; 977 struct local_zone* z = NULL; 978 struct local_data* ld = NULL; 979 lock_rw_rdlock(&az->rpz_lock); 980 for(a = az->rpz_first; a; a = a->rpz_az_next) { 981 lock_rw_rdlock(&a->lock); 982 r = a->rpz; 983 if(!r->disabled && (!r->taglist || taglist_intersect(r->taglist, 984 r->taglistlen, taglist, taglen))) { 985 z = rpz_find_zone(r, qinfo->qname, qinfo->qname_len, 986 qinfo->qclass, 0, 0, 0); 987 if(z && r->action_override == RPZ_DISABLED_ACTION) { 988 if(r->log) 989 log_rpz_apply(z->name, 990 r->action_override, 991 qinfo, repinfo, r->log_name); 992 /* TODO only register stats when stats_extended? 993 * */ 994 stats->rpz_action[r->action_override]++; 995 lock_rw_unlock(&z->lock); 996 z = NULL; 997 } 998 if(z) 999 break; 1000 } 1001 lock_rw_unlock(&a->lock); /* not found in this auth_zone */ 1002 } 1003 lock_rw_unlock(&az->rpz_lock); 1004 if(!z) 1005 return 0; /* not holding auth_zone.lock anymore */ 1006 1007 log_assert(r); 1008 if(r->action_override == RPZ_NO_OVERRIDE_ACTION) 1009 lzt = z->type; 1010 else 1011 lzt = rpz_action_to_localzone_type(r->action_override); 1012 1013 if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) { 1014 qinfo->local_alias = 1015 regional_alloc_zero(temp, sizeof(struct local_rrset)); 1016 if(!qinfo->local_alias) { 1017 lock_rw_unlock(&z->lock); 1018 lock_rw_unlock(&a->lock); 1019 return 0; /* out of memory */ 1020 } 1021 qinfo->local_alias->rrset = 1022 regional_alloc_init(temp, r->cname_override, 1023 sizeof(*r->cname_override)); 1024 if(!qinfo->local_alias->rrset) { 1025 lock_rw_unlock(&z->lock); 1026 lock_rw_unlock(&a->lock); 1027 return 0; /* out of memory */ 1028 } 1029 qinfo->local_alias->rrset->rk.dname = qinfo->qname; 1030 qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len; 1031 if(r->log) 1032 log_rpz_apply(z->name, RPZ_CNAME_OVERRIDE_ACTION, 1033 qinfo, repinfo, r->log_name); 1034 stats->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++; 1035 lock_rw_unlock(&z->lock); 1036 lock_rw_unlock(&a->lock); 1037 return 0; 1038 } 1039 1040 if(lzt == local_zone_redirect && local_data_answer(z, env, qinfo, 1041 edns, repinfo, buf, temp, dname_count_labels(qinfo->qname), 1042 &ld, lzt, -1, NULL, 0, NULL, 0)) { 1043 if(r->log) 1044 log_rpz_apply(z->name, 1045 localzone_type_to_rpz_action(lzt), qinfo, 1046 repinfo, r->log_name); 1047 stats->rpz_action[localzone_type_to_rpz_action(lzt)]++; 1048 lock_rw_unlock(&z->lock); 1049 lock_rw_unlock(&a->lock); 1050 return !qinfo->local_alias; 1051 } 1052 1053 ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp, 1054 0 /* no local data used */, lzt); 1055 if(r->log) 1056 log_rpz_apply(z->name, localzone_type_to_rpz_action(lzt), 1057 qinfo, repinfo, r->log_name); 1058 stats->rpz_action[localzone_type_to_rpz_action(lzt)]++; 1059 lock_rw_unlock(&z->lock); 1060 lock_rw_unlock(&a->lock); 1061 1062 return ret; 1063 } 1064 1065 void rpz_enable(struct rpz* r) 1066 { 1067 if(!r) 1068 return; 1069 r->disabled = 0; 1070 } 1071 1072 void rpz_disable(struct rpz* r) 1073 { 1074 if(!r) 1075 return; 1076 r->disabled = 1; 1077 } 1078