1 /* 2 * daemon/acl_list.h - client access control storage for the server. 3 * 4 * Copyright (c) 2007, 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 helps the server keep out queries from outside sources, that 40 * should not be answered. 41 */ 42 #include "config.h" 43 #include "daemon/acl_list.h" 44 #include "util/regional.h" 45 #include "util/log.h" 46 #include "util/config_file.h" 47 #include "util/net_help.h" 48 #include "services/localzone.h" 49 #include "sldns/str2wire.h" 50 51 struct acl_list* 52 acl_list_create(void) 53 { 54 struct acl_list* acl = (struct acl_list*)calloc(1, 55 sizeof(struct acl_list)); 56 if(!acl) 57 return NULL; 58 acl->region = regional_create(); 59 if(!acl->region) { 60 acl_list_delete(acl); 61 return NULL; 62 } 63 return acl; 64 } 65 66 void 67 acl_list_delete(struct acl_list* acl) 68 { 69 if(!acl) 70 return; 71 regional_destroy(acl->region); 72 free(acl); 73 } 74 75 /** insert new address into acl_list structure */ 76 static struct acl_addr* 77 acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr, 78 socklen_t addrlen, int net, enum acl_access control, 79 int complain_duplicates) 80 { 81 struct acl_addr* node = regional_alloc_zero(acl->region, 82 sizeof(struct acl_addr)); 83 if(!node) 84 return NULL; 85 node->control = control; 86 if(!addr_tree_insert(&acl->tree, &node->node, addr, addrlen, net)) { 87 if(complain_duplicates) 88 verbose(VERB_QUERY, "duplicate acl address ignored."); 89 } 90 return node; 91 } 92 93 /** apply acl_list string */ 94 static int 95 acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2, 96 int complain_duplicates) 97 { 98 struct sockaddr_storage addr; 99 int net; 100 socklen_t addrlen; 101 enum acl_access control; 102 if(strcmp(s2, "allow") == 0) 103 control = acl_allow; 104 else if(strcmp(s2, "deny") == 0) 105 control = acl_deny; 106 else if(strcmp(s2, "refuse") == 0) 107 control = acl_refuse; 108 else if(strcmp(s2, "deny_non_local") == 0) 109 control = acl_deny_non_local; 110 else if(strcmp(s2, "refuse_non_local") == 0) 111 control = acl_refuse_non_local; 112 else if(strcmp(s2, "allow_snoop") == 0) 113 control = acl_allow_snoop; 114 else { 115 log_err("access control type %s unknown", str); 116 return 0; 117 } 118 if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { 119 log_err("cannot parse access control: %s %s", str, s2); 120 return 0; 121 } 122 if(!acl_list_insert(acl, &addr, addrlen, net, control, 123 complain_duplicates)) { 124 log_err("out of memory"); 125 return 0; 126 } 127 return 1; 128 } 129 130 /** find or create node (NULL on parse or error) */ 131 static struct acl_addr* 132 acl_find_or_create(struct acl_list* acl, const char* str) 133 { 134 struct acl_addr* node; 135 struct sockaddr_storage addr; 136 int net; 137 socklen_t addrlen; 138 if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { 139 log_err("cannot parse netblock: %s", str); 140 return NULL; 141 } 142 /* find or create node */ 143 if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, &addr, 144 addrlen, net))) { 145 /* create node, type 'allow' since otherwise tags are 146 * pointless, can override with specific access-control: cfg */ 147 if(!(node=(struct acl_addr*)acl_list_insert(acl, &addr, 148 addrlen, net, acl_allow, 1))) { 149 log_err("out of memory"); 150 return NULL; 151 } 152 } 153 return node; 154 } 155 156 /** apply acl_tag string */ 157 static int 158 acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap, 159 size_t bitmaplen) 160 { 161 struct acl_addr* node; 162 if(!(node=acl_find_or_create(acl, str))) 163 return 0; 164 node->taglen = bitmaplen; 165 node->taglist = regional_alloc_init(acl->region, bitmap, bitmaplen); 166 if(!node->taglist) { 167 log_err("out of memory"); 168 return 0; 169 } 170 return 1; 171 } 172 173 /** apply acl_view string */ 174 static int 175 acl_list_view_cfg(struct acl_list* acl, const char* str, const char* str2, 176 struct views* vs) 177 { 178 struct acl_addr* node; 179 if(!(node=acl_find_or_create(acl, str))) 180 return 0; 181 node->view = views_find_view(vs, str2, 0 /* get read lock*/); 182 if(!node->view) { 183 log_err("no view with name: %s", str2); 184 return 0; 185 } 186 lock_rw_unlock(&node->view->lock); 187 return 1; 188 } 189 190 /** apply acl_tag_action string */ 191 static int 192 acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg, 193 const char* str, const char* tag, const char* action) 194 { 195 struct acl_addr* node; 196 int tagid; 197 enum localzone_type t; 198 if(!(node=acl_find_or_create(acl, str))) 199 return 0; 200 /* allocate array if not yet */ 201 if(!node->tag_actions) { 202 node->tag_actions = (uint8_t*)regional_alloc_zero(acl->region, 203 sizeof(*node->tag_actions)*cfg->num_tags); 204 if(!node->tag_actions) { 205 log_err("out of memory"); 206 return 0; 207 } 208 node->tag_actions_size = (size_t)cfg->num_tags; 209 } 210 /* parse tag */ 211 if((tagid=find_tag_id(cfg, tag)) == -1) { 212 log_err("cannot parse tag (define-tag it): %s %s", str, tag); 213 return 0; 214 } 215 if((size_t)tagid >= node->tag_actions_size) { 216 log_err("tagid too large for array %s %s", str, tag); 217 return 0; 218 } 219 if(!local_zone_str2type(action, &t)) { 220 log_err("cannot parse access control action type: %s %s %s", 221 str, tag, action); 222 return 0; 223 } 224 node->tag_actions[tagid] = (uint8_t)t; 225 return 1; 226 } 227 228 /** check wire data parse */ 229 static int 230 check_data(const char* data, const struct config_strlist* head) 231 { 232 char buf[65536]; 233 uint8_t rr[LDNS_RR_BUF_SIZE]; 234 size_t len = sizeof(rr); 235 int res; 236 /* '.' is sufficient for validation, and it makes the call to 237 * sldns_wirerr_get_type() simpler below. */ 238 snprintf(buf, sizeof(buf), "%s %s", ".", data); 239 res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, NULL, 0, 240 NULL, 0); 241 242 /* Reject it if we would end up having CNAME and other data (including 243 * another CNAME) for the same tag. */ 244 if(res == 0 && head) { 245 const char* err_data = NULL; 246 247 if(sldns_wirerr_get_type(rr, len, 1) == LDNS_RR_TYPE_CNAME) { 248 /* adding CNAME while other data already exists. */ 249 err_data = data; 250 } else { 251 snprintf(buf, sizeof(buf), "%s %s", ".", head->str); 252 len = sizeof(rr); 253 res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, 254 NULL, 0, NULL, 0); 255 if(res != 0) { 256 /* This should be impossible here as head->str 257 * has been validated, but we check it just in 258 * case. */ 259 return 0; 260 } 261 if(sldns_wirerr_get_type(rr, len, 1) == 262 LDNS_RR_TYPE_CNAME) /* already have CNAME */ 263 err_data = head->str; 264 } 265 if(err_data) { 266 log_err("redirect tag data '%s' must not coexist with " 267 "other data.", err_data); 268 return 0; 269 } 270 } 271 if(res == 0) 272 return 1; 273 log_err("rr data [char %d] parse error %s", 274 (int)LDNS_WIREPARSE_OFFSET(res)-13, 275 sldns_get_errorstr_parse(res)); 276 return 0; 277 } 278 279 /** apply acl_tag_data string */ 280 static int 281 acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg, 282 const char* str, const char* tag, const char* data) 283 { 284 struct acl_addr* node; 285 int tagid; 286 char* dupdata; 287 if(!(node=acl_find_or_create(acl, str))) 288 return 0; 289 /* allocate array if not yet */ 290 if(!node->tag_datas) { 291 node->tag_datas = (struct config_strlist**)regional_alloc_zero( 292 acl->region, sizeof(*node->tag_datas)*cfg->num_tags); 293 if(!node->tag_datas) { 294 log_err("out of memory"); 295 return 0; 296 } 297 node->tag_datas_size = (size_t)cfg->num_tags; 298 } 299 /* parse tag */ 300 if((tagid=find_tag_id(cfg, tag)) == -1) { 301 log_err("cannot parse tag (define-tag it): %s %s", str, tag); 302 return 0; 303 } 304 if((size_t)tagid >= node->tag_datas_size) { 305 log_err("tagid too large for array %s %s", str, tag); 306 return 0; 307 } 308 309 /* check data? */ 310 if(!check_data(data, node->tag_datas[tagid])) { 311 log_err("cannot parse access-control-tag data: %s %s '%s'", 312 str, tag, data); 313 return 0; 314 } 315 316 dupdata = regional_strdup(acl->region, data); 317 if(!dupdata) { 318 log_err("out of memory"); 319 return 0; 320 } 321 if(!cfg_region_strlist_insert(acl->region, 322 &(node->tag_datas[tagid]), dupdata)) { 323 log_err("out of memory"); 324 return 0; 325 } 326 return 1; 327 } 328 329 /** read acl_list config */ 330 static int 331 read_acl_list(struct acl_list* acl, struct config_file* cfg) 332 { 333 struct config_str2list* p; 334 for(p = cfg->acls; p; p = p->next) { 335 log_assert(p->str && p->str2); 336 if(!acl_list_str_cfg(acl, p->str, p->str2, 1)) 337 return 0; 338 } 339 return 1; 340 } 341 342 /** read acl tags config */ 343 static int 344 read_acl_tags(struct acl_list* acl, struct config_file* cfg) 345 { 346 struct config_strbytelist* np, *p = cfg->acl_tags; 347 cfg->acl_tags = NULL; 348 while(p) { 349 log_assert(p->str && p->str2); 350 if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len)) { 351 config_del_strbytelist(p); 352 return 0; 353 } 354 /* free the items as we go to free up memory */ 355 np = p->next; 356 free(p->str); 357 free(p->str2); 358 free(p); 359 p = np; 360 } 361 return 1; 362 } 363 364 /** read acl view config */ 365 static int 366 read_acl_view(struct acl_list* acl, struct config_file* cfg, struct views* v) 367 { 368 struct config_str2list* np, *p = cfg->acl_view; 369 cfg->acl_view = NULL; 370 while(p) { 371 log_assert(p->str && p->str2); 372 if(!acl_list_view_cfg(acl, p->str, p->str2, v)) { 373 return 0; 374 } 375 /* free the items as we go to free up memory */ 376 np = p->next; 377 free(p->str); 378 free(p->str2); 379 free(p); 380 p = np; 381 } 382 return 1; 383 } 384 385 /** read acl tag actions config */ 386 static int 387 read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg) 388 { 389 struct config_str3list* p, *np; 390 p = cfg->acl_tag_actions; 391 cfg->acl_tag_actions = NULL; 392 while(p) { 393 log_assert(p->str && p->str2 && p->str3); 394 if(!acl_list_tag_action_cfg(acl, cfg, p->str, p->str2, 395 p->str3)) { 396 config_deltrplstrlist(p); 397 return 0; 398 } 399 /* free the items as we go to free up memory */ 400 np = p->next; 401 free(p->str); 402 free(p->str2); 403 free(p->str3); 404 free(p); 405 p = np; 406 } 407 return 1; 408 } 409 410 /** read acl tag datas config */ 411 static int 412 read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg) 413 { 414 struct config_str3list* p, *np; 415 p = cfg->acl_tag_datas; 416 cfg->acl_tag_datas = NULL; 417 while(p) { 418 log_assert(p->str && p->str2 && p->str3); 419 if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3)) { 420 config_deltrplstrlist(p); 421 return 0; 422 } 423 /* free the items as we go to free up memory */ 424 np = p->next; 425 free(p->str); 426 free(p->str2); 427 free(p->str3); 428 free(p); 429 p = np; 430 } 431 return 1; 432 } 433 434 int 435 acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg, 436 struct views* v) 437 { 438 regional_free_all(acl->region); 439 addr_tree_init(&acl->tree); 440 if(!read_acl_list(acl, cfg)) 441 return 0; 442 if(!read_acl_view(acl, cfg, v)) 443 return 0; 444 if(!read_acl_tags(acl, cfg)) 445 return 0; 446 if(!read_acl_tag_actions(acl, cfg)) 447 return 0; 448 if(!read_acl_tag_datas(acl, cfg)) 449 return 0; 450 /* insert defaults, with '0' to ignore them if they are duplicates */ 451 if(!acl_list_str_cfg(acl, "0.0.0.0/0", "refuse", 0)) 452 return 0; 453 if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0)) 454 return 0; 455 if(cfg->do_ip6) { 456 if(!acl_list_str_cfg(acl, "::0/0", "refuse", 0)) 457 return 0; 458 if(!acl_list_str_cfg(acl, "::1", "allow", 0)) 459 return 0; 460 if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0)) 461 return 0; 462 } 463 addr_tree_init_parents(&acl->tree); 464 return 1; 465 } 466 467 enum acl_access 468 acl_get_control(struct acl_addr* acl) 469 { 470 if(acl) return acl->control; 471 return acl_deny; 472 } 473 474 struct acl_addr* 475 acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr, 476 socklen_t addrlen) 477 { 478 return (struct acl_addr*)addr_tree_lookup(&acl->tree, 479 addr, addrlen); 480 } 481 482 size_t 483 acl_list_get_mem(struct acl_list* acl) 484 { 485 if(!acl) return 0; 486 return sizeof(*acl) + regional_get_mem(acl->region); 487 } 488