xref: /freebsd/contrib/unbound/daemon/acl_list.c (revision 8f76bb7d)
1b7579f77SDag-Erling Smørgrav /*
2b7579f77SDag-Erling Smørgrav  * daemon/acl_list.h - client access control storage for the server.
3b7579f77SDag-Erling Smørgrav  *
4b7579f77SDag-Erling Smørgrav  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5b7579f77SDag-Erling Smørgrav  *
6b7579f77SDag-Erling Smørgrav  * This software is open source.
7b7579f77SDag-Erling Smørgrav  *
8b7579f77SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
9b7579f77SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
10b7579f77SDag-Erling Smørgrav  * are met:
11b7579f77SDag-Erling Smørgrav  *
12b7579f77SDag-Erling Smørgrav  * Redistributions of source code must retain the above copyright notice,
13b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer.
14b7579f77SDag-Erling Smørgrav  *
15b7579f77SDag-Erling Smørgrav  * Redistributions in binary form must reproduce the above copyright notice,
16b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer in the documentation
17b7579f77SDag-Erling Smørgrav  * and/or other materials provided with the distribution.
18b7579f77SDag-Erling Smørgrav  *
19b7579f77SDag-Erling Smørgrav  * Neither the name of the NLNET LABS nor the names of its contributors may
20b7579f77SDag-Erling Smørgrav  * be used to endorse or promote products derived from this software without
21b7579f77SDag-Erling Smørgrav  * specific prior written permission.
22b7579f77SDag-Erling Smørgrav  *
23b7579f77SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2417d15b25SDag-Erling Smørgrav  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2517d15b25SDag-Erling Smørgrav  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2617d15b25SDag-Erling Smørgrav  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2717d15b25SDag-Erling Smørgrav  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2817d15b25SDag-Erling Smørgrav  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2917d15b25SDag-Erling Smørgrav  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3017d15b25SDag-Erling Smørgrav  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3117d15b25SDag-Erling Smørgrav  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3217d15b25SDag-Erling Smørgrav  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3317d15b25SDag-Erling Smørgrav  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34b7579f77SDag-Erling Smørgrav  */
35b7579f77SDag-Erling Smørgrav 
36b7579f77SDag-Erling Smørgrav /**
37b7579f77SDag-Erling Smørgrav  * \file
38b7579f77SDag-Erling Smørgrav  *
39b7579f77SDag-Erling Smørgrav  * This file helps the server keep out queries from outside sources, that
40b7579f77SDag-Erling Smørgrav  * should not be answered.
41b7579f77SDag-Erling Smørgrav  */
42b7579f77SDag-Erling Smørgrav #include "config.h"
43b7579f77SDag-Erling Smørgrav #include "daemon/acl_list.h"
44b7579f77SDag-Erling Smørgrav #include "util/regional.h"
45b7579f77SDag-Erling Smørgrav #include "util/log.h"
46b7579f77SDag-Erling Smørgrav #include "util/config_file.h"
47b7579f77SDag-Erling Smørgrav #include "util/net_help.h"
48b5663de9SDag-Erling Smørgrav #include "services/localzone.h"
49865f46b2SCy Schubert #include "services/listen_dnsport.h"
50b5663de9SDag-Erling Smørgrav #include "sldns/str2wire.h"
51b7579f77SDag-Erling Smørgrav 
52b7579f77SDag-Erling Smørgrav struct acl_list*
acl_list_create(void)53b7579f77SDag-Erling Smørgrav acl_list_create(void)
54b7579f77SDag-Erling Smørgrav {
55b7579f77SDag-Erling Smørgrav 	struct acl_list* acl = (struct acl_list*)calloc(1,
56b7579f77SDag-Erling Smørgrav 		sizeof(struct acl_list));
57b7579f77SDag-Erling Smørgrav 	if(!acl)
58b7579f77SDag-Erling Smørgrav 		return NULL;
59b7579f77SDag-Erling Smørgrav 	acl->region = regional_create();
60b7579f77SDag-Erling Smørgrav 	if(!acl->region) {
61b7579f77SDag-Erling Smørgrav 		acl_list_delete(acl);
62b7579f77SDag-Erling Smørgrav 		return NULL;
63b7579f77SDag-Erling Smørgrav 	}
64b7579f77SDag-Erling Smørgrav 	return acl;
65b7579f77SDag-Erling Smørgrav }
66b7579f77SDag-Erling Smørgrav 
67b7579f77SDag-Erling Smørgrav void
acl_list_delete(struct acl_list * acl)68b7579f77SDag-Erling Smørgrav acl_list_delete(struct acl_list* acl)
69b7579f77SDag-Erling Smørgrav {
70b7579f77SDag-Erling Smørgrav 	if(!acl)
71b7579f77SDag-Erling Smørgrav 		return;
72b7579f77SDag-Erling Smørgrav 	regional_destroy(acl->region);
73b7579f77SDag-Erling Smørgrav 	free(acl);
74b7579f77SDag-Erling Smørgrav }
75b7579f77SDag-Erling Smørgrav 
76b7579f77SDag-Erling Smørgrav /** insert new address into acl_list structure */
77b5663de9SDag-Erling Smørgrav static struct acl_addr*
acl_list_insert(struct acl_list * acl,struct sockaddr_storage * addr,socklen_t addrlen,int net,enum acl_access control,int complain_duplicates)78b7579f77SDag-Erling Smørgrav acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
79b7579f77SDag-Erling Smørgrav 	socklen_t addrlen, int net, enum acl_access control,
80b7579f77SDag-Erling Smørgrav 	int complain_duplicates)
81b7579f77SDag-Erling Smørgrav {
82b5663de9SDag-Erling Smørgrav 	struct acl_addr* node = regional_alloc_zero(acl->region,
83b7579f77SDag-Erling Smørgrav 		sizeof(struct acl_addr));
84b7579f77SDag-Erling Smørgrav 	if(!node)
85b5663de9SDag-Erling Smørgrav 		return NULL;
86b7579f77SDag-Erling Smørgrav 	node->control = control;
87b7579f77SDag-Erling Smørgrav 	if(!addr_tree_insert(&acl->tree, &node->node, addr, addrlen, net)) {
88b7579f77SDag-Erling Smørgrav 		if(complain_duplicates)
89b7579f77SDag-Erling Smørgrav 			verbose(VERB_QUERY, "duplicate acl address ignored.");
90b7579f77SDag-Erling Smørgrav 	}
91b5663de9SDag-Erling Smørgrav 	return node;
92b7579f77SDag-Erling Smørgrav }
93b7579f77SDag-Erling Smørgrav 
94865f46b2SCy Schubert /** parse str to acl_access enum */
95865f46b2SCy Schubert static int
parse_acl_access(const char * str,enum acl_access * control)96865f46b2SCy Schubert parse_acl_access(const char* str, enum acl_access* control)
97865f46b2SCy Schubert {
98865f46b2SCy Schubert 	if(strcmp(str, "allow") == 0)
99865f46b2SCy Schubert 		*control = acl_allow;
100865f46b2SCy Schubert 	else if(strcmp(str, "deny") == 0)
101865f46b2SCy Schubert 		*control = acl_deny;
102865f46b2SCy Schubert 	else if(strcmp(str, "refuse") == 0)
103865f46b2SCy Schubert 		*control = acl_refuse;
104865f46b2SCy Schubert 	else if(strcmp(str, "deny_non_local") == 0)
105865f46b2SCy Schubert 		*control = acl_deny_non_local;
106865f46b2SCy Schubert 	else if(strcmp(str, "refuse_non_local") == 0)
107865f46b2SCy Schubert 		*control = acl_refuse_non_local;
108865f46b2SCy Schubert 	else if(strcmp(str, "allow_snoop") == 0)
109865f46b2SCy Schubert 		*control = acl_allow_snoop;
110865f46b2SCy Schubert 	else if(strcmp(str, "allow_setrd") == 0)
111865f46b2SCy Schubert 		*control = acl_allow_setrd;
1128f76bb7dSCy Schubert 	else if (strcmp(str, "allow_cookie") == 0)
1138f76bb7dSCy Schubert 		*control = acl_allow_cookie;
114865f46b2SCy Schubert 	else {
115865f46b2SCy Schubert 		log_err("access control type %s unknown", str);
116865f46b2SCy Schubert 		return 0;
117865f46b2SCy Schubert 	}
118865f46b2SCy Schubert 	return 1;
119865f46b2SCy Schubert }
120865f46b2SCy Schubert 
121b7579f77SDag-Erling Smørgrav /** apply acl_list string */
122b7579f77SDag-Erling Smørgrav static int
acl_list_str_cfg(struct acl_list * acl,const char * str,const char * s2,int complain_duplicates)123b7579f77SDag-Erling Smørgrav acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
124b7579f77SDag-Erling Smørgrav 	int complain_duplicates)
125b7579f77SDag-Erling Smørgrav {
126b7579f77SDag-Erling Smørgrav 	struct sockaddr_storage addr;
127b7579f77SDag-Erling Smørgrav 	int net;
128b7579f77SDag-Erling Smørgrav 	socklen_t addrlen;
129b7579f77SDag-Erling Smørgrav 	enum acl_access control;
130865f46b2SCy Schubert 	if(!parse_acl_access(s2, &control)) {
131b7579f77SDag-Erling Smørgrav 		return 0;
132b7579f77SDag-Erling Smørgrav 	}
133b7579f77SDag-Erling Smørgrav 	if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
134b7579f77SDag-Erling Smørgrav 		log_err("cannot parse access control: %s %s", str, s2);
135b7579f77SDag-Erling Smørgrav 		return 0;
136b7579f77SDag-Erling Smørgrav 	}
137b7579f77SDag-Erling Smørgrav 	if(!acl_list_insert(acl, &addr, addrlen, net, control,
138b7579f77SDag-Erling Smørgrav 		complain_duplicates)) {
139b7579f77SDag-Erling Smørgrav 		log_err("out of memory");
140b7579f77SDag-Erling Smørgrav 		return 0;
141b7579f77SDag-Erling Smørgrav 	}
142b7579f77SDag-Erling Smørgrav 	return 1;
143b7579f77SDag-Erling Smørgrav }
144b7579f77SDag-Erling Smørgrav 
145b5663de9SDag-Erling Smørgrav /** find or create node (NULL on parse or error) */
146b5663de9SDag-Erling Smørgrav static struct acl_addr*
acl_find_or_create_str2addr(struct acl_list * acl,const char * str,int is_interface,int port)147865f46b2SCy Schubert acl_find_or_create_str2addr(struct acl_list* acl, const char* str,
148865f46b2SCy Schubert 	int is_interface, int port)
149b5663de9SDag-Erling Smørgrav {
150b5663de9SDag-Erling Smørgrav 	struct acl_addr* node;
151b5663de9SDag-Erling Smørgrav 	struct sockaddr_storage addr;
152b5663de9SDag-Erling Smørgrav 	socklen_t addrlen;
153865f46b2SCy Schubert 	int net = (str_is_ip6(str)?128:32);
154865f46b2SCy Schubert 	if(is_interface) {
155865f46b2SCy Schubert 		if(!extstrtoaddr(str, &addr, &addrlen, port)) {
156865f46b2SCy Schubert 			log_err("cannot parse interface: %s", str);
157865f46b2SCy Schubert 			return NULL;
158865f46b2SCy Schubert 		}
159865f46b2SCy Schubert 	} else {
160b5663de9SDag-Erling Smørgrav 		if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
161b5663de9SDag-Erling Smørgrav 			log_err("cannot parse netblock: %s", str);
162b5663de9SDag-Erling Smørgrav 			return NULL;
163b5663de9SDag-Erling Smørgrav 		}
164865f46b2SCy Schubert 	}
165b5663de9SDag-Erling Smørgrav 	/* find or create node */
166b5663de9SDag-Erling Smørgrav 	if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, &addr,
167865f46b2SCy Schubert 		addrlen, net)) && !is_interface) {
168b5663de9SDag-Erling Smørgrav 		/* create node, type 'allow' since otherwise tags are
169b5663de9SDag-Erling Smørgrav 		 * pointless, can override with specific access-control: cfg */
170b5663de9SDag-Erling Smørgrav 		if(!(node=(struct acl_addr*)acl_list_insert(acl, &addr,
171b5663de9SDag-Erling Smørgrav 			addrlen, net, acl_allow, 1))) {
172b5663de9SDag-Erling Smørgrav 			log_err("out of memory");
173b5663de9SDag-Erling Smørgrav 			return NULL;
174b5663de9SDag-Erling Smørgrav 		}
175b5663de9SDag-Erling Smørgrav 	}
176b5663de9SDag-Erling Smørgrav 	return node;
177b5663de9SDag-Erling Smørgrav }
178b5663de9SDag-Erling Smørgrav 
179865f46b2SCy Schubert /** find or create node (NULL on error) */
180865f46b2SCy Schubert static struct acl_addr*
acl_find_or_create(struct acl_list * acl,struct sockaddr_storage * addr,socklen_t addrlen,enum acl_access control)181865f46b2SCy Schubert acl_find_or_create(struct acl_list* acl, struct sockaddr_storage* addr,
182865f46b2SCy Schubert 	socklen_t addrlen, enum acl_access control)
183865f46b2SCy Schubert {
184865f46b2SCy Schubert 	struct acl_addr* node;
185865f46b2SCy Schubert 	int net = (addr_is_ip6(addr, addrlen)?128:32);
186865f46b2SCy Schubert 	/* find or create node */
187865f46b2SCy Schubert 	if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, addr,
188865f46b2SCy Schubert 		addrlen, net))) {
189865f46b2SCy Schubert 		/* create node;
190865f46b2SCy Schubert 		 * can override with specific access-control: cfg */
191865f46b2SCy Schubert 		if(!(node=(struct acl_addr*)acl_list_insert(acl, addr,
192865f46b2SCy Schubert 			addrlen, net, control, 1))) {
193865f46b2SCy Schubert 			log_err("out of memory");
194865f46b2SCy Schubert 			return NULL;
195865f46b2SCy Schubert 		}
196865f46b2SCy Schubert 	}
197865f46b2SCy Schubert 	return node;
198865f46b2SCy Schubert }
199865f46b2SCy Schubert 
200865f46b2SCy Schubert /** apply acl_interface string */
201865f46b2SCy Schubert static int
acl_interface_str_cfg(struct acl_list * acl_interface,const char * iface,const char * s2,int port)202865f46b2SCy Schubert acl_interface_str_cfg(struct acl_list* acl_interface, const char* iface,
203865f46b2SCy Schubert 	const char* s2, int port)
204865f46b2SCy Schubert {
205865f46b2SCy Schubert 	struct acl_addr* node;
206865f46b2SCy Schubert 	enum acl_access control;
207865f46b2SCy Schubert 	if(!parse_acl_access(s2, &control)) {
208865f46b2SCy Schubert 		return 0;
209865f46b2SCy Schubert 	}
210865f46b2SCy Schubert 	if(!(node=acl_find_or_create_str2addr(acl_interface, iface, 1, port))) {
211865f46b2SCy Schubert 		log_err("cannot update ACL on non-configured interface: %s %d",
212865f46b2SCy Schubert 			iface, port);
213865f46b2SCy Schubert 		return 0;
214865f46b2SCy Schubert 	}
215865f46b2SCy Schubert 	node->control = control;
216865f46b2SCy Schubert 	return 1;
217865f46b2SCy Schubert }
218865f46b2SCy Schubert 
219865f46b2SCy Schubert struct acl_addr*
acl_interface_insert(struct acl_list * acl_interface,struct sockaddr_storage * addr,socklen_t addrlen,enum acl_access control)220865f46b2SCy Schubert acl_interface_insert(struct acl_list* acl_interface,
221865f46b2SCy Schubert 	struct sockaddr_storage* addr, socklen_t addrlen,
222865f46b2SCy Schubert 	enum acl_access control)
223865f46b2SCy Schubert {
224865f46b2SCy Schubert 	return acl_find_or_create(acl_interface, addr, addrlen, control);
225865f46b2SCy Schubert }
226865f46b2SCy Schubert 
227b5663de9SDag-Erling Smørgrav /** apply acl_tag string */
228b5663de9SDag-Erling Smørgrav static int
acl_list_tags_cfg(struct acl_list * acl,const char * str,uint8_t * bitmap,size_t bitmaplen,int is_interface,int port)229b5663de9SDag-Erling Smørgrav acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap,
230865f46b2SCy Schubert 	size_t bitmaplen, int is_interface, int port)
231b5663de9SDag-Erling Smørgrav {
232b5663de9SDag-Erling Smørgrav 	struct acl_addr* node;
233865f46b2SCy Schubert 	if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
234865f46b2SCy Schubert 		if(is_interface)
235865f46b2SCy Schubert 			log_err("non-configured interface: %s", str);
236b5663de9SDag-Erling Smørgrav 		return 0;
237865f46b2SCy Schubert 	}
238b5663de9SDag-Erling Smørgrav 	node->taglen = bitmaplen;
239b5663de9SDag-Erling Smørgrav 	node->taglist = regional_alloc_init(acl->region, bitmap, bitmaplen);
240b5663de9SDag-Erling Smørgrav 	if(!node->taglist) {
241b5663de9SDag-Erling Smørgrav 		log_err("out of memory");
242b5663de9SDag-Erling Smørgrav 		return 0;
243b5663de9SDag-Erling Smørgrav 	}
244b5663de9SDag-Erling Smørgrav 	return 1;
245b5663de9SDag-Erling Smørgrav }
246b5663de9SDag-Erling Smørgrav 
247bc892140SDag-Erling Smørgrav /** apply acl_view string */
248bc892140SDag-Erling Smørgrav static int
acl_list_view_cfg(struct acl_list * acl,const char * str,const char * str2,struct views * vs,int is_interface,int port)249bc892140SDag-Erling Smørgrav acl_list_view_cfg(struct acl_list* acl, const char* str, const char* str2,
250865f46b2SCy Schubert 	struct views* vs, int is_interface, int port)
251bc892140SDag-Erling Smørgrav {
252bc892140SDag-Erling Smørgrav 	struct acl_addr* node;
253865f46b2SCy Schubert 	if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
254865f46b2SCy Schubert 		if(is_interface)
255865f46b2SCy Schubert 			log_err("non-configured interface: %s", str);
256bc892140SDag-Erling Smørgrav 		return 0;
257865f46b2SCy Schubert 	}
258bc892140SDag-Erling Smørgrav 	node->view = views_find_view(vs, str2, 0 /* get read lock*/);
259bc892140SDag-Erling Smørgrav 	if(!node->view) {
260bc892140SDag-Erling Smørgrav 		log_err("no view with name: %s", str2);
261bc892140SDag-Erling Smørgrav 		return 0;
262bc892140SDag-Erling Smørgrav 	}
263bc892140SDag-Erling Smørgrav 	lock_rw_unlock(&node->view->lock);
264bc892140SDag-Erling Smørgrav 	return 1;
265bc892140SDag-Erling Smørgrav }
266bc892140SDag-Erling Smørgrav 
267b5663de9SDag-Erling Smørgrav /** apply acl_tag_action string */
268b5663de9SDag-Erling Smørgrav static int
acl_list_tag_action_cfg(struct acl_list * acl,struct config_file * cfg,const char * str,const char * tag,const char * action,int is_interface,int port)269b5663de9SDag-Erling Smørgrav acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg,
270865f46b2SCy Schubert 	const char* str, const char* tag, const char* action,
271865f46b2SCy Schubert 	int is_interface, int port)
272b5663de9SDag-Erling Smørgrav {
273b5663de9SDag-Erling Smørgrav 	struct acl_addr* node;
274b5663de9SDag-Erling Smørgrav 	int tagid;
275b5663de9SDag-Erling Smørgrav 	enum localzone_type t;
276865f46b2SCy Schubert 	if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
277865f46b2SCy Schubert 		if(is_interface)
278865f46b2SCy Schubert 			log_err("non-configured interface: %s", str);
279b5663de9SDag-Erling Smørgrav 		return 0;
280865f46b2SCy Schubert 	}
281b5663de9SDag-Erling Smørgrav 	/* allocate array if not yet */
282b5663de9SDag-Erling Smørgrav 	if(!node->tag_actions) {
283b5663de9SDag-Erling Smørgrav 		node->tag_actions = (uint8_t*)regional_alloc_zero(acl->region,
284b5663de9SDag-Erling Smørgrav 			sizeof(*node->tag_actions)*cfg->num_tags);
285b5663de9SDag-Erling Smørgrav 		if(!node->tag_actions) {
286b5663de9SDag-Erling Smørgrav 			log_err("out of memory");
287b5663de9SDag-Erling Smørgrav 			return 0;
288b5663de9SDag-Erling Smørgrav 		}
289b5663de9SDag-Erling Smørgrav 		node->tag_actions_size = (size_t)cfg->num_tags;
290b5663de9SDag-Erling Smørgrav 	}
291b5663de9SDag-Erling Smørgrav 	/* parse tag */
292b5663de9SDag-Erling Smørgrav 	if((tagid=find_tag_id(cfg, tag)) == -1) {
293b5663de9SDag-Erling Smørgrav 		log_err("cannot parse tag (define-tag it): %s %s", str, tag);
294b5663de9SDag-Erling Smørgrav 		return 0;
295b5663de9SDag-Erling Smørgrav 	}
296b5663de9SDag-Erling Smørgrav 	if((size_t)tagid >= node->tag_actions_size) {
297b5663de9SDag-Erling Smørgrav 		log_err("tagid too large for array %s %s", str, tag);
298b5663de9SDag-Erling Smørgrav 		return 0;
299b5663de9SDag-Erling Smørgrav 	}
300b5663de9SDag-Erling Smørgrav 	if(!local_zone_str2type(action, &t)) {
301b5663de9SDag-Erling Smørgrav 		log_err("cannot parse access control action type: %s %s %s",
302b5663de9SDag-Erling Smørgrav 			str, tag, action);
303b5663de9SDag-Erling Smørgrav 		return 0;
304b5663de9SDag-Erling Smørgrav 	}
305b5663de9SDag-Erling Smørgrav 	node->tag_actions[tagid] = (uint8_t)t;
306b5663de9SDag-Erling Smørgrav 	return 1;
307b5663de9SDag-Erling Smørgrav }
308b5663de9SDag-Erling Smørgrav 
309b5663de9SDag-Erling Smørgrav /** check wire data parse */
310b5663de9SDag-Erling Smørgrav static int
check_data(const char * data,const struct config_strlist * head)311bc892140SDag-Erling Smørgrav check_data(const char* data, const struct config_strlist* head)
312b5663de9SDag-Erling Smørgrav {
313b5663de9SDag-Erling Smørgrav 	char buf[65536];
314b5663de9SDag-Erling Smørgrav 	uint8_t rr[LDNS_RR_BUF_SIZE];
315b5663de9SDag-Erling Smørgrav 	size_t len = sizeof(rr);
316b5663de9SDag-Erling Smørgrav 	int res;
317bc892140SDag-Erling Smørgrav 	/* '.' is sufficient for validation, and it makes the call to
318bc892140SDag-Erling Smørgrav 	 * sldns_wirerr_get_type() simpler below. */
319bc892140SDag-Erling Smørgrav 	snprintf(buf, sizeof(buf), "%s %s", ".", data);
320b5663de9SDag-Erling Smørgrav 	res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, NULL, 0,
321b5663de9SDag-Erling Smørgrav 		NULL, 0);
322bc892140SDag-Erling Smørgrav 
323bc892140SDag-Erling Smørgrav 	/* Reject it if we would end up having CNAME and other data (including
324bc892140SDag-Erling Smørgrav 	 * another CNAME) for the same tag. */
325bc892140SDag-Erling Smørgrav 	if(res == 0 && head) {
326bc892140SDag-Erling Smørgrav 		const char* err_data = NULL;
327bc892140SDag-Erling Smørgrav 
328bc892140SDag-Erling Smørgrav 		if(sldns_wirerr_get_type(rr, len, 1) == LDNS_RR_TYPE_CNAME) {
329bc892140SDag-Erling Smørgrav 			/* adding CNAME while other data already exists. */
330bc892140SDag-Erling Smørgrav 			err_data = data;
331bc892140SDag-Erling Smørgrav 		} else {
332bc892140SDag-Erling Smørgrav 			snprintf(buf, sizeof(buf), "%s %s", ".", head->str);
333bc892140SDag-Erling Smørgrav 			len = sizeof(rr);
334bc892140SDag-Erling Smørgrav 			res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600,
335bc892140SDag-Erling Smørgrav 				NULL, 0, NULL, 0);
336bc892140SDag-Erling Smørgrav 			if(res != 0) {
337bc892140SDag-Erling Smørgrav 				/* This should be impossible here as head->str
338bc892140SDag-Erling Smørgrav 				 * has been validated, but we check it just in
339bc892140SDag-Erling Smørgrav 				 * case. */
340bc892140SDag-Erling Smørgrav 				return 0;
341bc892140SDag-Erling Smørgrav 			}
342bc892140SDag-Erling Smørgrav 			if(sldns_wirerr_get_type(rr, len, 1) ==
343bc892140SDag-Erling Smørgrav 				LDNS_RR_TYPE_CNAME) /* already have CNAME */
344bc892140SDag-Erling Smørgrav 				err_data = head->str;
345bc892140SDag-Erling Smørgrav 		}
346bc892140SDag-Erling Smørgrav 		if(err_data) {
347bc892140SDag-Erling Smørgrav 			log_err("redirect tag data '%s' must not coexist with "
348bc892140SDag-Erling Smørgrav 				"other data.", err_data);
349bc892140SDag-Erling Smørgrav 			return 0;
350bc892140SDag-Erling Smørgrav 		}
351bc892140SDag-Erling Smørgrav 	}
352b5663de9SDag-Erling Smørgrav 	if(res == 0)
353b5663de9SDag-Erling Smørgrav 		return 1;
354b5663de9SDag-Erling Smørgrav 	log_err("rr data [char %d] parse error %s",
35525039b37SCy Schubert 		(int)LDNS_WIREPARSE_OFFSET(res)-2,
356b5663de9SDag-Erling Smørgrav 		sldns_get_errorstr_parse(res));
357b5663de9SDag-Erling Smørgrav 	return 0;
358b5663de9SDag-Erling Smørgrav }
359b5663de9SDag-Erling Smørgrav 
360b5663de9SDag-Erling Smørgrav /** apply acl_tag_data string */
361b5663de9SDag-Erling Smørgrav static int
acl_list_tag_data_cfg(struct acl_list * acl,struct config_file * cfg,const char * str,const char * tag,const char * data,int is_interface,int port)362b5663de9SDag-Erling Smørgrav acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg,
363865f46b2SCy Schubert 	const char* str, const char* tag, const char* data,
364865f46b2SCy Schubert 	int is_interface, int port)
365b5663de9SDag-Erling Smørgrav {
366b5663de9SDag-Erling Smørgrav 	struct acl_addr* node;
367b5663de9SDag-Erling Smørgrav 	int tagid;
368b5663de9SDag-Erling Smørgrav 	char* dupdata;
369865f46b2SCy Schubert 	if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
370865f46b2SCy Schubert 		if(is_interface)
371865f46b2SCy Schubert 			log_err("non-configured interface: %s", str);
372b5663de9SDag-Erling Smørgrav 		return 0;
373865f46b2SCy Schubert 	}
374b5663de9SDag-Erling Smørgrav 	/* allocate array if not yet */
375b5663de9SDag-Erling Smørgrav 	if(!node->tag_datas) {
376b5663de9SDag-Erling Smørgrav 		node->tag_datas = (struct config_strlist**)regional_alloc_zero(
377b5663de9SDag-Erling Smørgrav 			acl->region, sizeof(*node->tag_datas)*cfg->num_tags);
378b5663de9SDag-Erling Smørgrav 		if(!node->tag_datas) {
379b5663de9SDag-Erling Smørgrav 			log_err("out of memory");
380b5663de9SDag-Erling Smørgrav 			return 0;
381b5663de9SDag-Erling Smørgrav 		}
382b5663de9SDag-Erling Smørgrav 		node->tag_datas_size = (size_t)cfg->num_tags;
383b5663de9SDag-Erling Smørgrav 	}
384b5663de9SDag-Erling Smørgrav 	/* parse tag */
385b5663de9SDag-Erling Smørgrav 	if((tagid=find_tag_id(cfg, tag)) == -1) {
386b5663de9SDag-Erling Smørgrav 		log_err("cannot parse tag (define-tag it): %s %s", str, tag);
387b5663de9SDag-Erling Smørgrav 		return 0;
388b5663de9SDag-Erling Smørgrav 	}
389b5663de9SDag-Erling Smørgrav 	if((size_t)tagid >= node->tag_datas_size) {
390b5663de9SDag-Erling Smørgrav 		log_err("tagid too large for array %s %s", str, tag);
391b5663de9SDag-Erling Smørgrav 		return 0;
392b5663de9SDag-Erling Smørgrav 	}
393b5663de9SDag-Erling Smørgrav 
394b5663de9SDag-Erling Smørgrav 	/* check data? */
395bc892140SDag-Erling Smørgrav 	if(!check_data(data, node->tag_datas[tagid])) {
396b5663de9SDag-Erling Smørgrav 		log_err("cannot parse access-control-tag data: %s %s '%s'",
397b5663de9SDag-Erling Smørgrav 			str, tag, data);
398b5663de9SDag-Erling Smørgrav 		return 0;
399b5663de9SDag-Erling Smørgrav 	}
400b5663de9SDag-Erling Smørgrav 
401b5663de9SDag-Erling Smørgrav 	dupdata = regional_strdup(acl->region, data);
402b5663de9SDag-Erling Smørgrav 	if(!dupdata) {
403b5663de9SDag-Erling Smørgrav 		log_err("out of memory");
404b5663de9SDag-Erling Smørgrav 		return 0;
405b5663de9SDag-Erling Smørgrav 	}
406b5663de9SDag-Erling Smørgrav 	if(!cfg_region_strlist_insert(acl->region,
407b5663de9SDag-Erling Smørgrav 		&(node->tag_datas[tagid]), dupdata)) {
408b5663de9SDag-Erling Smørgrav 		log_err("out of memory");
409b5663de9SDag-Erling Smørgrav 		return 0;
410b5663de9SDag-Erling Smørgrav 	}
411b5663de9SDag-Erling Smørgrav 	return 1;
412b5663de9SDag-Erling Smørgrav }
413b5663de9SDag-Erling Smørgrav 
414b7579f77SDag-Erling Smørgrav /** read acl_list config */
415b7579f77SDag-Erling Smørgrav static int
read_acl_list(struct acl_list * acl,struct config_str2list * acls)416865f46b2SCy Schubert read_acl_list(struct acl_list* acl, struct config_str2list* acls)
417b7579f77SDag-Erling Smørgrav {
418b7579f77SDag-Erling Smørgrav 	struct config_str2list* p;
419865f46b2SCy Schubert 	for(p = acls; p; p = p->next) {
420b7579f77SDag-Erling Smørgrav 		log_assert(p->str && p->str2);
421b7579f77SDag-Erling Smørgrav 		if(!acl_list_str_cfg(acl, p->str, p->str2, 1))
422b7579f77SDag-Erling Smørgrav 			return 0;
423b7579f77SDag-Erling Smørgrav 	}
424b7579f77SDag-Erling Smørgrav 	return 1;
425b7579f77SDag-Erling Smørgrav }
426b7579f77SDag-Erling Smørgrav 
427865f46b2SCy Schubert /** read acl view config */
428b5663de9SDag-Erling Smørgrav static int
read_acl_view(struct acl_list * acl,struct config_str2list ** acl_view,struct views * v)429865f46b2SCy Schubert read_acl_view(struct acl_list* acl, struct config_str2list** acl_view,
430865f46b2SCy Schubert 	struct views* v)
431b5663de9SDag-Erling Smørgrav {
432865f46b2SCy Schubert 	struct config_str2list* np, *p = *acl_view;
433865f46b2SCy Schubert 	*acl_view = NULL;
434b5663de9SDag-Erling Smørgrav 	while(p) {
435b5663de9SDag-Erling Smørgrav 		log_assert(p->str && p->str2);
436865f46b2SCy Schubert 		if(!acl_list_view_cfg(acl, p->str, p->str2, v, 0, 0)) {
437865f46b2SCy Schubert 			config_deldblstrlist(p);
438b5663de9SDag-Erling Smørgrav 			return 0;
439b5663de9SDag-Erling Smørgrav 		}
440b5663de9SDag-Erling Smørgrav 		/* free the items as we go to free up memory */
441b5663de9SDag-Erling Smørgrav 		np = p->next;
442b5663de9SDag-Erling Smørgrav 		free(p->str);
443b5663de9SDag-Erling Smørgrav 		free(p->str2);
444b5663de9SDag-Erling Smørgrav 		free(p);
445b5663de9SDag-Erling Smørgrav 		p = np;
446b5663de9SDag-Erling Smørgrav 	}
447b5663de9SDag-Erling Smørgrav 	return 1;
448b5663de9SDag-Erling Smørgrav }
449b5663de9SDag-Erling Smørgrav 
450865f46b2SCy Schubert /** read acl tags config */
451bc892140SDag-Erling Smørgrav static int
read_acl_tags(struct acl_list * acl,struct config_strbytelist ** acl_tags)452865f46b2SCy Schubert read_acl_tags(struct acl_list* acl, struct config_strbytelist** acl_tags)
453bc892140SDag-Erling Smørgrav {
454865f46b2SCy Schubert 	struct config_strbytelist* np, *p = *acl_tags;
455865f46b2SCy Schubert 	*acl_tags = NULL;
456bc892140SDag-Erling Smørgrav 	while(p) {
457bc892140SDag-Erling Smørgrav 		log_assert(p->str && p->str2);
458865f46b2SCy Schubert 		if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len, 0, 0)) {
459865f46b2SCy Schubert 			config_del_strbytelist(p);
460bc892140SDag-Erling Smørgrav 			return 0;
461bc892140SDag-Erling Smørgrav 		}
462bc892140SDag-Erling Smørgrav 		/* free the items as we go to free up memory */
463bc892140SDag-Erling Smørgrav 		np = p->next;
464bc892140SDag-Erling Smørgrav 		free(p->str);
465bc892140SDag-Erling Smørgrav 		free(p->str2);
466bc892140SDag-Erling Smørgrav 		free(p);
467bc892140SDag-Erling Smørgrav 		p = np;
468bc892140SDag-Erling Smørgrav 	}
469bc892140SDag-Erling Smørgrav 	return 1;
470bc892140SDag-Erling Smørgrav }
471bc892140SDag-Erling Smørgrav 
472b5663de9SDag-Erling Smørgrav /** read acl tag actions config */
473b5663de9SDag-Erling Smørgrav static int
read_acl_tag_actions(struct acl_list * acl,struct config_file * cfg,struct config_str3list ** acl_tag_actions)474865f46b2SCy Schubert read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg,
475865f46b2SCy Schubert 	struct config_str3list** acl_tag_actions)
476b5663de9SDag-Erling Smørgrav {
477b5663de9SDag-Erling Smørgrav 	struct config_str3list* p, *np;
478865f46b2SCy Schubert 	p = *acl_tag_actions;
479865f46b2SCy Schubert 	*acl_tag_actions = NULL;
480b5663de9SDag-Erling Smørgrav 	while(p) {
481b5663de9SDag-Erling Smørgrav 		log_assert(p->str && p->str2 && p->str3);
482b5663de9SDag-Erling Smørgrav 		if(!acl_list_tag_action_cfg(acl, cfg, p->str, p->str2,
483865f46b2SCy Schubert 			p->str3, 0, 0)) {
484b5663de9SDag-Erling Smørgrav 			config_deltrplstrlist(p);
485b5663de9SDag-Erling Smørgrav 			return 0;
486b5663de9SDag-Erling Smørgrav 		}
487b5663de9SDag-Erling Smørgrav 		/* free the items as we go to free up memory */
488b5663de9SDag-Erling Smørgrav 		np = p->next;
489b5663de9SDag-Erling Smørgrav 		free(p->str);
490b5663de9SDag-Erling Smørgrav 		free(p->str2);
491b5663de9SDag-Erling Smørgrav 		free(p->str3);
492b5663de9SDag-Erling Smørgrav 		free(p);
493b5663de9SDag-Erling Smørgrav 		p = np;
494b5663de9SDag-Erling Smørgrav 	}
495b5663de9SDag-Erling Smørgrav 	return 1;
496b5663de9SDag-Erling Smørgrav }
497b5663de9SDag-Erling Smørgrav 
498b5663de9SDag-Erling Smørgrav /** read acl tag datas config */
499b5663de9SDag-Erling Smørgrav static int
read_acl_tag_datas(struct acl_list * acl,struct config_file * cfg,struct config_str3list ** acl_tag_datas)500865f46b2SCy Schubert read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg,
501865f46b2SCy Schubert 	struct config_str3list** acl_tag_datas)
502b5663de9SDag-Erling Smørgrav {
503b5663de9SDag-Erling Smørgrav 	struct config_str3list* p, *np;
504865f46b2SCy Schubert 	p = *acl_tag_datas;
505865f46b2SCy Schubert 	*acl_tag_datas = NULL;
506b5663de9SDag-Erling Smørgrav 	while(p) {
507b5663de9SDag-Erling Smørgrav 		log_assert(p->str && p->str2 && p->str3);
508865f46b2SCy Schubert 		if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3,
509865f46b2SCy Schubert 			0, 0)) {
510b5663de9SDag-Erling Smørgrav 			config_deltrplstrlist(p);
511b5663de9SDag-Erling Smørgrav 			return 0;
512b5663de9SDag-Erling Smørgrav 		}
513b5663de9SDag-Erling Smørgrav 		/* free the items as we go to free up memory */
514b5663de9SDag-Erling Smørgrav 		np = p->next;
515b5663de9SDag-Erling Smørgrav 		free(p->str);
516b5663de9SDag-Erling Smørgrav 		free(p->str2);
517b5663de9SDag-Erling Smørgrav 		free(p->str3);
518b5663de9SDag-Erling Smørgrav 		free(p);
519b5663de9SDag-Erling Smørgrav 		p = np;
520b5663de9SDag-Erling Smørgrav 	}
521b5663de9SDag-Erling Smørgrav 	return 1;
522b5663de9SDag-Erling Smørgrav }
523b5663de9SDag-Erling Smørgrav 
524b7579f77SDag-Erling Smørgrav int
acl_list_apply_cfg(struct acl_list * acl,struct config_file * cfg,struct views * v)525bc892140SDag-Erling Smørgrav acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
526bc892140SDag-Erling Smørgrav 	struct views* v)
527b7579f77SDag-Erling Smørgrav {
528b7579f77SDag-Erling Smørgrav 	regional_free_all(acl->region);
529b7579f77SDag-Erling Smørgrav 	addr_tree_init(&acl->tree);
530865f46b2SCy Schubert 	if(!read_acl_list(acl, cfg->acls))
531b7579f77SDag-Erling Smørgrav 		return 0;
532865f46b2SCy Schubert 	if(!read_acl_view(acl, &cfg->acl_view, v))
533bc892140SDag-Erling Smørgrav 		return 0;
534865f46b2SCy Schubert 	if(!read_acl_tags(acl, &cfg->acl_tags))
535b5663de9SDag-Erling Smørgrav 		return 0;
536865f46b2SCy Schubert 	if(!read_acl_tag_actions(acl, cfg, &cfg->acl_tag_actions))
537b5663de9SDag-Erling Smørgrav 		return 0;
538865f46b2SCy Schubert 	if(!read_acl_tag_datas(acl, cfg, &cfg->acl_tag_datas))
539b5663de9SDag-Erling Smørgrav 		return 0;
540b7579f77SDag-Erling Smørgrav 	/* insert defaults, with '0' to ignore them if they are duplicates */
541865f46b2SCy Schubert 	/* the 'refuse' defaults for /0 are now done per interface instead */
542b7579f77SDag-Erling Smørgrav 	if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0))
543b7579f77SDag-Erling Smørgrav 		return 0;
544b7579f77SDag-Erling Smørgrav 	if(cfg->do_ip6) {
545b7579f77SDag-Erling Smørgrav 		if(!acl_list_str_cfg(acl, "::1", "allow", 0))
546b7579f77SDag-Erling Smørgrav 			return 0;
547b7579f77SDag-Erling Smørgrav 		if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0))
548b7579f77SDag-Erling Smørgrav 			return 0;
549b7579f77SDag-Erling Smørgrav 	}
550b7579f77SDag-Erling Smørgrav 	addr_tree_init_parents(&acl->tree);
551b7579f77SDag-Erling Smørgrav 	return 1;
552b7579f77SDag-Erling Smørgrav }
553b7579f77SDag-Erling Smørgrav 
554865f46b2SCy Schubert int
acl_interface_compare(const void * k1,const void * k2)555865f46b2SCy Schubert acl_interface_compare(const void* k1, const void* k2)
556865f46b2SCy Schubert {
557865f46b2SCy Schubert 	struct addr_tree_node* n1 = (struct addr_tree_node*)k1;
558865f46b2SCy Schubert 	struct addr_tree_node* n2 = (struct addr_tree_node*)k2;
559865f46b2SCy Schubert 	return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr,
560865f46b2SCy Schubert 		n2->addrlen);
561865f46b2SCy Schubert 	/* We don't care about comparing node->net. All addresses in the
562865f46b2SCy Schubert 	 * acl_interface tree have either 32 (ipv4) or 128 (ipv6). */
563865f46b2SCy Schubert }
564865f46b2SCy Schubert 
565865f46b2SCy Schubert void
acl_interface_init(struct acl_list * acl_interface)566865f46b2SCy Schubert acl_interface_init(struct acl_list* acl_interface)
567865f46b2SCy Schubert {
568865f46b2SCy Schubert 	regional_free_all(acl_interface->region);
569865f46b2SCy Schubert 	/* We want comparison in the tree to include only address and port.
570865f46b2SCy Schubert 	 * We don't care about comparing node->net. All addresses in the
571865f46b2SCy Schubert 	 * acl_interface->tree should have either 32 (ipv4) or 128 (ipv6).
572865f46b2SCy Schubert 	 * Initialise with the appropriate compare function but keep treating
573865f46b2SCy Schubert 	 * it as an addr_tree. */
574865f46b2SCy Schubert 	addr_tree_addrport_init(&acl_interface->tree);
575865f46b2SCy Schubert }
576865f46b2SCy Schubert 
577865f46b2SCy Schubert static int
read_acl_interface_action(struct acl_list * acl_interface,struct config_str2list * acls,int port)578865f46b2SCy Schubert read_acl_interface_action(struct acl_list* acl_interface,
579865f46b2SCy Schubert 	struct config_str2list* acls, int port)
580865f46b2SCy Schubert {
581865f46b2SCy Schubert 	struct config_str2list* p;
582865f46b2SCy Schubert 	for(p = acls; p; p = p->next) {
583865f46b2SCy Schubert 		char** resif = NULL;
584865f46b2SCy Schubert 		int num_resif = 0;
585865f46b2SCy Schubert 		int i;
586865f46b2SCy Schubert 		log_assert(p->str && p->str2);
587865f46b2SCy Schubert 		if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif))
588865f46b2SCy Schubert 			return 0;
589865f46b2SCy Schubert 		for(i = 0; i<num_resif; i++) {
590865f46b2SCy Schubert 			if(!acl_interface_str_cfg(acl_interface, resif[i], p->str2, port)){
591865f46b2SCy Schubert 				config_del_strarray(resif, num_resif);
592865f46b2SCy Schubert 				return 0;
593865f46b2SCy Schubert 			}
594865f46b2SCy Schubert 		}
595865f46b2SCy Schubert 		config_del_strarray(resif, num_resif);
596865f46b2SCy Schubert 	}
597865f46b2SCy Schubert 	return 1;
598865f46b2SCy Schubert }
599865f46b2SCy Schubert 
600865f46b2SCy Schubert /** read acl view config for interface */
601865f46b2SCy Schubert static int
read_acl_interface_view(struct acl_list * acl_interface,struct config_str2list ** acl_view,struct views * v,int port)602865f46b2SCy Schubert read_acl_interface_view(struct acl_list* acl_interface,
603865f46b2SCy Schubert 	struct config_str2list** acl_view,
604865f46b2SCy Schubert 	struct views* v, int port)
605865f46b2SCy Schubert {
606865f46b2SCy Schubert 	struct config_str2list* np, *p = *acl_view;
607865f46b2SCy Schubert 	*acl_view = NULL;
608865f46b2SCy Schubert 	while(p) {
609865f46b2SCy Schubert 		char** resif = NULL;
610865f46b2SCy Schubert 		int num_resif = 0;
611865f46b2SCy Schubert 		int i;
612865f46b2SCy Schubert 		log_assert(p->str && p->str2);
613865f46b2SCy Schubert 		if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) {
614865f46b2SCy Schubert 			config_deldblstrlist(p);
615865f46b2SCy Schubert 			return 0;
616865f46b2SCy Schubert 		}
617865f46b2SCy Schubert 		for(i = 0; i<num_resif; i++) {
618865f46b2SCy Schubert 			if(!acl_list_view_cfg(acl_interface, resif[i], p->str2,
619865f46b2SCy Schubert 				v, 1, port)) {
620865f46b2SCy Schubert 				config_del_strarray(resif, num_resif);
621865f46b2SCy Schubert 				config_deldblstrlist(p);
622865f46b2SCy Schubert 				return 0;
623865f46b2SCy Schubert 			}
624865f46b2SCy Schubert 		}
625865f46b2SCy Schubert 		config_del_strarray(resif, num_resif);
626865f46b2SCy Schubert 		/* free the items as we go to free up memory */
627865f46b2SCy Schubert 		np = p->next;
628865f46b2SCy Schubert 		free(p->str);
629865f46b2SCy Schubert 		free(p->str2);
630865f46b2SCy Schubert 		free(p);
631865f46b2SCy Schubert 		p = np;
632865f46b2SCy Schubert 	}
633865f46b2SCy Schubert 	return 1;
634865f46b2SCy Schubert }
635865f46b2SCy Schubert 
636865f46b2SCy Schubert /** read acl tags config for interface */
637865f46b2SCy Schubert static int
read_acl_interface_tags(struct acl_list * acl_interface,struct config_strbytelist ** acl_tags,int port)638865f46b2SCy Schubert read_acl_interface_tags(struct acl_list* acl_interface,
639865f46b2SCy Schubert 	struct config_strbytelist** acl_tags, int port)
640865f46b2SCy Schubert {
641865f46b2SCy Schubert 	struct config_strbytelist* np, *p = *acl_tags;
642865f46b2SCy Schubert 	*acl_tags = NULL;
643865f46b2SCy Schubert 	while(p) {
644865f46b2SCy Schubert 		char** resif = NULL;
645865f46b2SCy Schubert 		int num_resif = 0;
646865f46b2SCy Schubert 		int i;
647865f46b2SCy Schubert 		log_assert(p->str && p->str2);
648865f46b2SCy Schubert 		if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) {
649865f46b2SCy Schubert 			config_del_strbytelist(p);
650865f46b2SCy Schubert 			return 0;
651865f46b2SCy Schubert 		}
652865f46b2SCy Schubert 		for(i = 0; i<num_resif; i++) {
653865f46b2SCy Schubert 			if(!acl_list_tags_cfg(acl_interface, resif[i], p->str2,
654865f46b2SCy Schubert 				p->str2len, 1, port)) {
655865f46b2SCy Schubert 				config_del_strbytelist(p);
656865f46b2SCy Schubert 				config_del_strarray(resif, num_resif);
657865f46b2SCy Schubert 				return 0;
658865f46b2SCy Schubert 			}
659865f46b2SCy Schubert 		}
660865f46b2SCy Schubert 		config_del_strarray(resif, num_resif);
661865f46b2SCy Schubert 		/* free the items as we go to free up memory */
662865f46b2SCy Schubert 		np = p->next;
663865f46b2SCy Schubert 		free(p->str);
664865f46b2SCy Schubert 		free(p->str2);
665865f46b2SCy Schubert 		free(p);
666865f46b2SCy Schubert 		p = np;
667865f46b2SCy Schubert 	}
668865f46b2SCy Schubert 	return 1;
669865f46b2SCy Schubert }
670865f46b2SCy Schubert 
671865f46b2SCy Schubert /** read acl tag actions config for interface*/
672865f46b2SCy Schubert static int
read_acl_interface_tag_actions(struct acl_list * acl_interface,struct config_file * cfg,struct config_str3list ** acl_tag_actions,int port)673865f46b2SCy Schubert read_acl_interface_tag_actions(struct acl_list* acl_interface,
674865f46b2SCy Schubert 	struct config_file* cfg,
675865f46b2SCy Schubert 	struct config_str3list** acl_tag_actions, int port)
676865f46b2SCy Schubert {
677865f46b2SCy Schubert 	struct config_str3list* p, *np;
678865f46b2SCy Schubert 	p = *acl_tag_actions;
679865f46b2SCy Schubert 	*acl_tag_actions = NULL;
680865f46b2SCy Schubert 	while(p) {
681865f46b2SCy Schubert 		char** resif = NULL;
682865f46b2SCy Schubert 		int num_resif = 0;
683865f46b2SCy Schubert 		int i;
684865f46b2SCy Schubert 		log_assert(p->str && p->str2 && p->str3);
685865f46b2SCy Schubert 		if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) {
686865f46b2SCy Schubert 			config_deltrplstrlist(p);
687865f46b2SCy Schubert 			return 0;
688865f46b2SCy Schubert 		}
689865f46b2SCy Schubert 		for(i = 0; i<num_resif; i++) {
690865f46b2SCy Schubert 			if(!acl_list_tag_action_cfg(acl_interface, cfg,
691865f46b2SCy Schubert 				resif[i], p->str2, p->str3, 1, port)) {
692865f46b2SCy Schubert 				config_deltrplstrlist(p);
693865f46b2SCy Schubert 				config_del_strarray(resif, num_resif);
694865f46b2SCy Schubert 				return 0;
695865f46b2SCy Schubert 			}
696865f46b2SCy Schubert 		}
697865f46b2SCy Schubert 		config_del_strarray(resif, num_resif);
698865f46b2SCy Schubert 		/* free the items as we go to free up memory */
699865f46b2SCy Schubert 		np = p->next;
700865f46b2SCy Schubert 		free(p->str);
701865f46b2SCy Schubert 		free(p->str2);
702865f46b2SCy Schubert 		free(p->str3);
703865f46b2SCy Schubert 		free(p);
704865f46b2SCy Schubert 		p = np;
705865f46b2SCy Schubert 	}
706865f46b2SCy Schubert 	return 1;
707865f46b2SCy Schubert }
708865f46b2SCy Schubert 
709865f46b2SCy Schubert /** read acl tag datas config for interface */
710865f46b2SCy Schubert static int
read_acl_interface_tag_datas(struct acl_list * acl_interface,struct config_file * cfg,struct config_str3list ** acl_tag_datas,int port)711865f46b2SCy Schubert read_acl_interface_tag_datas(struct acl_list* acl_interface,
712865f46b2SCy Schubert 	struct config_file* cfg,
713865f46b2SCy Schubert 	struct config_str3list** acl_tag_datas, int port)
714865f46b2SCy Schubert {
715865f46b2SCy Schubert 	struct config_str3list* p, *np;
716865f46b2SCy Schubert 	p = *acl_tag_datas;
717865f46b2SCy Schubert 	*acl_tag_datas = NULL;
718865f46b2SCy Schubert 	while(p) {
719865f46b2SCy Schubert 		char** resif = NULL;
720865f46b2SCy Schubert 		int num_resif = 0;
721865f46b2SCy Schubert 		int i;
722865f46b2SCy Schubert 		log_assert(p->str && p->str2 && p->str3);
723865f46b2SCy Schubert 		if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) {
724865f46b2SCy Schubert 			config_deltrplstrlist(p);
725865f46b2SCy Schubert 			return 0;
726865f46b2SCy Schubert 		}
727865f46b2SCy Schubert 		for(i = 0; i<num_resif; i++) {
728865f46b2SCy Schubert 			if(!acl_list_tag_data_cfg(acl_interface, cfg,
729865f46b2SCy Schubert 				resif[i], p->str2, p->str3, 1, port)) {
730865f46b2SCy Schubert 				config_deltrplstrlist(p);
731865f46b2SCy Schubert 				config_del_strarray(resif, num_resif);
732865f46b2SCy Schubert 				return 0;
733865f46b2SCy Schubert 			}
734865f46b2SCy Schubert 		}
735865f46b2SCy Schubert 		config_del_strarray(resif, num_resif);
736865f46b2SCy Schubert 		/* free the items as we go to free up memory */
737865f46b2SCy Schubert 		np = p->next;
738865f46b2SCy Schubert 		free(p->str);
739865f46b2SCy Schubert 		free(p->str2);
740865f46b2SCy Schubert 		free(p->str3);
741865f46b2SCy Schubert 		free(p);
742865f46b2SCy Schubert 		p = np;
743865f46b2SCy Schubert 	}
744865f46b2SCy Schubert 	return 1;
745865f46b2SCy Schubert }
746865f46b2SCy Schubert 
747865f46b2SCy Schubert int
acl_interface_apply_cfg(struct acl_list * acl_interface,struct config_file * cfg,struct views * v)748865f46b2SCy Schubert acl_interface_apply_cfg(struct acl_list* acl_interface, struct config_file* cfg,
749865f46b2SCy Schubert 	struct views* v)
750865f46b2SCy Schubert {
751865f46b2SCy Schubert 	if(!read_acl_interface_action(acl_interface, cfg->interface_actions,
752865f46b2SCy Schubert 		cfg->port))
753865f46b2SCy Schubert 		return 0;
754865f46b2SCy Schubert 	if(!read_acl_interface_view(acl_interface, &cfg->interface_view, v,
755865f46b2SCy Schubert 		cfg->port))
756865f46b2SCy Schubert 		return 0;
757865f46b2SCy Schubert 	if(!read_acl_interface_tags(acl_interface, &cfg->interface_tags,
758865f46b2SCy Schubert 		cfg->port))
759865f46b2SCy Schubert 		return 0;
760865f46b2SCy Schubert 	if(!read_acl_interface_tag_actions(acl_interface, cfg,
761865f46b2SCy Schubert 		&cfg->interface_tag_actions, cfg->port))
762865f46b2SCy Schubert 		return 0;
763865f46b2SCy Schubert 	if(!read_acl_interface_tag_datas(acl_interface, cfg,
764865f46b2SCy Schubert 		&cfg->interface_tag_datas, cfg->port))
765865f46b2SCy Schubert 		return 0;
766865f46b2SCy Schubert 	addr_tree_init_parents(&acl_interface->tree);
767865f46b2SCy Schubert 	return 1;
768865f46b2SCy Schubert }
769865f46b2SCy Schubert 
770b7579f77SDag-Erling Smørgrav enum acl_access
acl_get_control(struct acl_addr * acl)771b5663de9SDag-Erling Smørgrav acl_get_control(struct acl_addr* acl)
772b5663de9SDag-Erling Smørgrav {
773b5663de9SDag-Erling Smørgrav 	if(acl) return acl->control;
774b5663de9SDag-Erling Smørgrav 	return acl_deny;
775b5663de9SDag-Erling Smørgrav }
776b5663de9SDag-Erling Smørgrav 
777b5663de9SDag-Erling Smørgrav struct acl_addr*
acl_addr_lookup(struct acl_list * acl,struct sockaddr_storage * addr,socklen_t addrlen)778b5663de9SDag-Erling Smørgrav acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
779b7579f77SDag-Erling Smørgrav         socklen_t addrlen)
780b7579f77SDag-Erling Smørgrav {
781b5663de9SDag-Erling Smørgrav 	return (struct acl_addr*)addr_tree_lookup(&acl->tree,
782b7579f77SDag-Erling Smørgrav 		addr, addrlen);
783b7579f77SDag-Erling Smørgrav }
784b7579f77SDag-Erling Smørgrav 
785b7579f77SDag-Erling Smørgrav size_t
acl_list_get_mem(struct acl_list * acl)786b7579f77SDag-Erling Smørgrav acl_list_get_mem(struct acl_list* acl)
787b7579f77SDag-Erling Smørgrav {
788b7579f77SDag-Erling Smørgrav 	if(!acl) return 0;
789b7579f77SDag-Erling Smørgrav 	return sizeof(*acl) + regional_get_mem(acl->region);
790b7579f77SDag-Erling Smørgrav }
791a39a5a69SCy Schubert 
acl_access_to_str(enum acl_access acl)792a39a5a69SCy Schubert const char* acl_access_to_str(enum acl_access acl)
793a39a5a69SCy Schubert {
794a39a5a69SCy Schubert 	switch(acl) {
795a39a5a69SCy Schubert 	case acl_deny: return "deny";
796a39a5a69SCy Schubert 	case acl_refuse: return "refuse";
797a39a5a69SCy Schubert 	case acl_deny_non_local: return "deny_non_local";
798a39a5a69SCy Schubert 	case acl_refuse_non_local: return "refuse_non_local";
799a39a5a69SCy Schubert 	case acl_allow: return "allow";
800a39a5a69SCy Schubert 	case acl_allow_snoop: return "allow_snoop";
801a39a5a69SCy Schubert 	case acl_allow_setrd: return "allow_setrd";
802a39a5a69SCy Schubert 	default: break;
803a39a5a69SCy Schubert 	}
804a39a5a69SCy Schubert 	return "unknown";
805a39a5a69SCy Schubert }
806a39a5a69SCy Schubert 
807a39a5a69SCy Schubert void
log_acl_action(const char * action,struct sockaddr_storage * addr,socklen_t addrlen,enum acl_access acl,struct acl_addr * acladdr)808a39a5a69SCy Schubert log_acl_action(const char* action, struct sockaddr_storage* addr,
809a39a5a69SCy Schubert 	socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr)
810a39a5a69SCy Schubert {
811a39a5a69SCy Schubert 	char a[128], n[128];
812a39a5a69SCy Schubert 	uint16_t port;
813a39a5a69SCy Schubert 	addr_to_str(addr, addrlen, a, sizeof(a));
814a39a5a69SCy Schubert 	port = ntohs(((struct sockaddr_in*)addr)->sin_port);
815a39a5a69SCy Schubert 	if(acladdr) {
816a39a5a69SCy Schubert 		addr_to_str(&acladdr->node.addr, acladdr->node.addrlen,
817a39a5a69SCy Schubert 			n, sizeof(n));
818a39a5a69SCy Schubert 		verbose(VERB_ALGO, "%s query from %s port %d because of "
819a39a5a69SCy Schubert 			"%s/%d %s", action, a, (int)port, n, acladdr->node.net,
820a39a5a69SCy Schubert 			acl_access_to_str(acl));
821a39a5a69SCy Schubert 	} else {
822a39a5a69SCy Schubert 		verbose(VERB_ALGO, "%s query from %s port %d", action, a,
823a39a5a69SCy Schubert 			(int)port);
824a39a5a69SCy Schubert 	}
825a39a5a69SCy Schubert }
826