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_tag_action string */ 174 static int 175 acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg, 176 const char* str, const char* tag, const char* action) 177 { 178 struct acl_addr* node; 179 int tagid; 180 enum localzone_type t; 181 if(!(node=acl_find_or_create(acl, str))) 182 return 0; 183 /* allocate array if not yet */ 184 if(!node->tag_actions) { 185 node->tag_actions = (uint8_t*)regional_alloc_zero(acl->region, 186 sizeof(*node->tag_actions)*cfg->num_tags); 187 if(!node->tag_actions) { 188 log_err("out of memory"); 189 return 0; 190 } 191 node->tag_actions_size = (size_t)cfg->num_tags; 192 } 193 /* parse tag */ 194 if((tagid=find_tag_id(cfg, tag)) == -1) { 195 log_err("cannot parse tag (define-tag it): %s %s", str, tag); 196 return 0; 197 } 198 if((size_t)tagid >= node->tag_actions_size) { 199 log_err("tagid too large for array %s %s", str, tag); 200 return 0; 201 } 202 if(!local_zone_str2type(action, &t)) { 203 log_err("cannot parse access control action type: %s %s %s", 204 str, tag, action); 205 return 0; 206 } 207 node->tag_actions[tagid] = (uint8_t)t; 208 return 1; 209 } 210 211 /** check wire data parse */ 212 static int 213 check_data(const char* data) 214 { 215 char buf[65536]; 216 uint8_t rr[LDNS_RR_BUF_SIZE]; 217 size_t len = sizeof(rr); 218 int res; 219 snprintf(buf, sizeof(buf), "%s %s", "example.com.", data); 220 res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, NULL, 0, 221 NULL, 0); 222 if(res == 0) 223 return 1; 224 log_err("rr data [char %d] parse error %s", 225 (int)LDNS_WIREPARSE_OFFSET(res)-13, 226 sldns_get_errorstr_parse(res)); 227 return 0; 228 } 229 230 /** apply acl_tag_data string */ 231 static int 232 acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg, 233 const char* str, const char* tag, const char* data) 234 { 235 struct acl_addr* node; 236 int tagid; 237 char* dupdata; 238 if(!(node=acl_find_or_create(acl, str))) 239 return 0; 240 /* allocate array if not yet */ 241 if(!node->tag_datas) { 242 node->tag_datas = (struct config_strlist**)regional_alloc_zero( 243 acl->region, sizeof(*node->tag_datas)*cfg->num_tags); 244 if(!node->tag_datas) { 245 log_err("out of memory"); 246 return 0; 247 } 248 node->tag_datas_size = (size_t)cfg->num_tags; 249 } 250 /* parse tag */ 251 if((tagid=find_tag_id(cfg, tag)) == -1) { 252 log_err("cannot parse tag (define-tag it): %s %s", str, tag); 253 return 0; 254 } 255 if((size_t)tagid >= node->tag_datas_size) { 256 log_err("tagid too large for array %s %s", str, tag); 257 return 0; 258 } 259 260 /* check data? */ 261 if(!check_data(data)) { 262 log_err("cannot parse access-control-tag data: %s %s '%s'", 263 str, tag, data); 264 return 0; 265 } 266 267 dupdata = regional_strdup(acl->region, data); 268 if(!dupdata) { 269 log_err("out of memory"); 270 return 0; 271 } 272 if(!cfg_region_strlist_insert(acl->region, 273 &(node->tag_datas[tagid]), dupdata)) { 274 log_err("out of memory"); 275 return 0; 276 } 277 return 1; 278 } 279 280 /** read acl_list config */ 281 static int 282 read_acl_list(struct acl_list* acl, struct config_file* cfg) 283 { 284 struct config_str2list* p; 285 for(p = cfg->acls; p; p = p->next) { 286 log_assert(p->str && p->str2); 287 if(!acl_list_str_cfg(acl, p->str, p->str2, 1)) 288 return 0; 289 } 290 return 1; 291 } 292 293 /** read acl tags config */ 294 static int 295 read_acl_tags(struct acl_list* acl, struct config_file* cfg) 296 { 297 struct config_strbytelist* np, *p = cfg->acl_tags; 298 cfg->acl_tags = NULL; 299 while(p) { 300 log_assert(p->str && p->str2); 301 if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len)) { 302 config_del_strbytelist(p); 303 return 0; 304 } 305 /* free the items as we go to free up memory */ 306 np = p->next; 307 free(p->str); 308 free(p->str2); 309 free(p); 310 p = np; 311 } 312 return 1; 313 } 314 315 /** read acl tag actions config */ 316 static int 317 read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg) 318 { 319 struct config_str3list* p, *np; 320 p = cfg->acl_tag_actions; 321 cfg->acl_tag_actions = NULL; 322 while(p) { 323 log_assert(p->str && p->str2 && p->str3); 324 if(!acl_list_tag_action_cfg(acl, cfg, p->str, p->str2, 325 p->str3)) { 326 config_deltrplstrlist(p); 327 return 0; 328 } 329 /* free the items as we go to free up memory */ 330 np = p->next; 331 free(p->str); 332 free(p->str2); 333 free(p->str3); 334 free(p); 335 p = np; 336 } 337 return 1; 338 } 339 340 /** read acl tag datas config */ 341 static int 342 read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg) 343 { 344 struct config_str3list* p, *np; 345 p = cfg->acl_tag_datas; 346 cfg->acl_tag_datas = NULL; 347 while(p) { 348 log_assert(p->str && p->str2 && p->str3); 349 if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3)) { 350 config_deltrplstrlist(p); 351 return 0; 352 } 353 /* free the items as we go to free up memory */ 354 np = p->next; 355 free(p->str); 356 free(p->str2); 357 free(p->str3); 358 free(p); 359 p = np; 360 } 361 return 1; 362 } 363 364 int 365 acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg) 366 { 367 regional_free_all(acl->region); 368 addr_tree_init(&acl->tree); 369 if(!read_acl_list(acl, cfg)) 370 return 0; 371 if(!read_acl_tags(acl, cfg)) 372 return 0; 373 if(!read_acl_tag_actions(acl, cfg)) 374 return 0; 375 if(!read_acl_tag_datas(acl, cfg)) 376 return 0; 377 /* insert defaults, with '0' to ignore them if they are duplicates */ 378 if(!acl_list_str_cfg(acl, "0.0.0.0/0", "refuse", 0)) 379 return 0; 380 if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0)) 381 return 0; 382 if(cfg->do_ip6) { 383 if(!acl_list_str_cfg(acl, "::0/0", "refuse", 0)) 384 return 0; 385 if(!acl_list_str_cfg(acl, "::1", "allow", 0)) 386 return 0; 387 if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0)) 388 return 0; 389 } 390 addr_tree_init_parents(&acl->tree); 391 return 1; 392 } 393 394 enum acl_access 395 acl_get_control(struct acl_addr* acl) 396 { 397 if(acl) return acl->control; 398 return acl_deny; 399 } 400 401 struct acl_addr* 402 acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr, 403 socklen_t addrlen) 404 { 405 return (struct acl_addr*)addr_tree_lookup(&acl->tree, 406 addr, addrlen); 407 } 408 409 size_t 410 acl_list_get_mem(struct acl_list* acl) 411 { 412 if(!acl) return 0; 413 return sizeof(*acl) + regional_get_mem(acl->region); 414 } 415