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