xref: /minix3/external/bsd/bind/dist/lib/dns/acl.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: acl.c,v 1.7 2014/12/10 04:37:58 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004-2009, 2011, 2013, 2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2002  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id: acl.c,v 1.55 2011/06/17 23:47:49 tbox Exp  */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek /*! \file */
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <config.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
27*00b67f09SDavid van Moolenbroek #include <isc/once.h>
28*00b67f09SDavid van Moolenbroek #include <isc/string.h>
29*00b67f09SDavid van Moolenbroek #include <isc/util.h>
30*00b67f09SDavid van Moolenbroek 
31*00b67f09SDavid van Moolenbroek #include <dns/acl.h>
32*00b67f09SDavid van Moolenbroek #include <dns/iptable.h>
33*00b67f09SDavid van Moolenbroek 
34*00b67f09SDavid van Moolenbroek 
35*00b67f09SDavid van Moolenbroek /*
36*00b67f09SDavid van Moolenbroek  * Create a new ACL, including an IP table and an array with room
37*00b67f09SDavid van Moolenbroek  * for 'n' ACL elements.  The elements are uninitialized and the
38*00b67f09SDavid van Moolenbroek  * length is 0.
39*00b67f09SDavid van Moolenbroek  */
40*00b67f09SDavid van Moolenbroek isc_result_t
dns_acl_create(isc_mem_t * mctx,int n,dns_acl_t ** target)41*00b67f09SDavid van Moolenbroek dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
42*00b67f09SDavid van Moolenbroek 	isc_result_t result;
43*00b67f09SDavid van Moolenbroek 	dns_acl_t *acl;
44*00b67f09SDavid van Moolenbroek 
45*00b67f09SDavid van Moolenbroek 	/*
46*00b67f09SDavid van Moolenbroek 	 * Work around silly limitation of isc_mem_get().
47*00b67f09SDavid van Moolenbroek 	 */
48*00b67f09SDavid van Moolenbroek 	if (n == 0)
49*00b67f09SDavid van Moolenbroek 		n = 1;
50*00b67f09SDavid van Moolenbroek 
51*00b67f09SDavid van Moolenbroek 	acl = isc_mem_get(mctx, sizeof(*acl));
52*00b67f09SDavid van Moolenbroek 	if (acl == NULL)
53*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
54*00b67f09SDavid van Moolenbroek 
55*00b67f09SDavid van Moolenbroek 	acl->mctx = NULL;
56*00b67f09SDavid van Moolenbroek 	isc_mem_attach(mctx, &acl->mctx);
57*00b67f09SDavid van Moolenbroek 
58*00b67f09SDavid van Moolenbroek 	acl->name = NULL;
59*00b67f09SDavid van Moolenbroek 
60*00b67f09SDavid van Moolenbroek 	result = isc_refcount_init(&acl->refcount, 1);
61*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
62*00b67f09SDavid van Moolenbroek 		isc_mem_put(mctx, acl, sizeof(*acl));
63*00b67f09SDavid van Moolenbroek 		return (result);
64*00b67f09SDavid van Moolenbroek 	}
65*00b67f09SDavid van Moolenbroek 
66*00b67f09SDavid van Moolenbroek 	result = dns_iptable_create(mctx, &acl->iptable);
67*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
68*00b67f09SDavid van Moolenbroek 		isc_mem_put(mctx, acl, sizeof(*acl));
69*00b67f09SDavid van Moolenbroek 		return (result);
70*00b67f09SDavid van Moolenbroek 	}
71*00b67f09SDavid van Moolenbroek 
72*00b67f09SDavid van Moolenbroek 	acl->elements = NULL;
73*00b67f09SDavid van Moolenbroek 	acl->alloc = 0;
74*00b67f09SDavid van Moolenbroek 	acl->length = 0;
75*00b67f09SDavid van Moolenbroek 	acl->has_negatives = ISC_FALSE;
76*00b67f09SDavid van Moolenbroek 
77*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(acl, nextincache);
78*00b67f09SDavid van Moolenbroek 	/*
79*00b67f09SDavid van Moolenbroek 	 * Must set magic early because we use dns_acl_detach() to clean up.
80*00b67f09SDavid van Moolenbroek 	 */
81*00b67f09SDavid van Moolenbroek 	acl->magic = DNS_ACL_MAGIC;
82*00b67f09SDavid van Moolenbroek 
83*00b67f09SDavid van Moolenbroek 	acl->elements = isc_mem_get(mctx, n * sizeof(dns_aclelement_t));
84*00b67f09SDavid van Moolenbroek 	if (acl->elements == NULL) {
85*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
86*00b67f09SDavid van Moolenbroek 		goto cleanup;
87*00b67f09SDavid van Moolenbroek 	}
88*00b67f09SDavid van Moolenbroek 	acl->alloc = n;
89*00b67f09SDavid van Moolenbroek 	memset(acl->elements, 0, n * sizeof(dns_aclelement_t));
90*00b67f09SDavid van Moolenbroek 	*target = acl;
91*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
92*00b67f09SDavid van Moolenbroek 
93*00b67f09SDavid van Moolenbroek  cleanup:
94*00b67f09SDavid van Moolenbroek 	dns_acl_detach(&acl);
95*00b67f09SDavid van Moolenbroek 	return (result);
96*00b67f09SDavid van Moolenbroek }
97*00b67f09SDavid van Moolenbroek 
98*00b67f09SDavid van Moolenbroek /*
99*00b67f09SDavid van Moolenbroek  * Create a new ACL and initialize it with the value "any" or "none",
100*00b67f09SDavid van Moolenbroek  * depending on the value of the "neg" parameter.
101*00b67f09SDavid van Moolenbroek  * "any" is a positive iptable entry with bit length 0.
102*00b67f09SDavid van Moolenbroek  * "none" is the same as "!any".
103*00b67f09SDavid van Moolenbroek  */
104*00b67f09SDavid van Moolenbroek static isc_result_t
dns_acl_anyornone(isc_mem_t * mctx,isc_boolean_t neg,dns_acl_t ** target)105*00b67f09SDavid van Moolenbroek dns_acl_anyornone(isc_mem_t *mctx, isc_boolean_t neg, dns_acl_t **target) {
106*00b67f09SDavid van Moolenbroek 	isc_result_t result;
107*00b67f09SDavid van Moolenbroek 	dns_acl_t *acl = NULL;
108*00b67f09SDavid van Moolenbroek 
109*00b67f09SDavid van Moolenbroek 	result = dns_acl_create(mctx, 0, &acl);
110*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
111*00b67f09SDavid van Moolenbroek 		return (result);
112*00b67f09SDavid van Moolenbroek 
113*00b67f09SDavid van Moolenbroek 	result = dns_iptable_addprefix(acl->iptable, NULL, 0, ISC_TF(!neg));
114*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
115*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&acl);
116*00b67f09SDavid van Moolenbroek 		return (result);
117*00b67f09SDavid van Moolenbroek 	}
118*00b67f09SDavid van Moolenbroek 
119*00b67f09SDavid van Moolenbroek 	*target = acl;
120*00b67f09SDavid van Moolenbroek 	return (result);
121*00b67f09SDavid van Moolenbroek }
122*00b67f09SDavid van Moolenbroek 
123*00b67f09SDavid van Moolenbroek /*
124*00b67f09SDavid van Moolenbroek  * Create a new ACL that matches everything.
125*00b67f09SDavid van Moolenbroek  */
126*00b67f09SDavid van Moolenbroek isc_result_t
dns_acl_any(isc_mem_t * mctx,dns_acl_t ** target)127*00b67f09SDavid van Moolenbroek dns_acl_any(isc_mem_t *mctx, dns_acl_t **target) {
128*00b67f09SDavid van Moolenbroek 	return (dns_acl_anyornone(mctx, ISC_FALSE, target));
129*00b67f09SDavid van Moolenbroek }
130*00b67f09SDavid van Moolenbroek 
131*00b67f09SDavid van Moolenbroek /*
132*00b67f09SDavid van Moolenbroek  * Create a new ACL that matches nothing.
133*00b67f09SDavid van Moolenbroek  */
134*00b67f09SDavid van Moolenbroek isc_result_t
dns_acl_none(isc_mem_t * mctx,dns_acl_t ** target)135*00b67f09SDavid van Moolenbroek dns_acl_none(isc_mem_t *mctx, dns_acl_t **target) {
136*00b67f09SDavid van Moolenbroek 	return (dns_acl_anyornone(mctx, ISC_TRUE, target));
137*00b67f09SDavid van Moolenbroek }
138*00b67f09SDavid van Moolenbroek 
139*00b67f09SDavid van Moolenbroek /*
140*00b67f09SDavid van Moolenbroek  * If pos is ISC_TRUE, test whether acl is set to "{ any; }"
141*00b67f09SDavid van Moolenbroek  * If pos is ISC_FALSE, test whether acl is set to "{ none; }"
142*00b67f09SDavid van Moolenbroek  */
143*00b67f09SDavid van Moolenbroek static isc_boolean_t
dns_acl_isanyornone(dns_acl_t * acl,isc_boolean_t pos)144*00b67f09SDavid van Moolenbroek dns_acl_isanyornone(dns_acl_t *acl, isc_boolean_t pos)
145*00b67f09SDavid van Moolenbroek {
146*00b67f09SDavid van Moolenbroek 	/* Should never happen but let's be safe */
147*00b67f09SDavid van Moolenbroek 	if (acl == NULL ||
148*00b67f09SDavid van Moolenbroek 	    acl->iptable == NULL ||
149*00b67f09SDavid van Moolenbroek 	    acl->iptable->radix == NULL ||
150*00b67f09SDavid van Moolenbroek 	    acl->iptable->radix->head == NULL ||
151*00b67f09SDavid van Moolenbroek 	    acl->iptable->radix->head->prefix == NULL)
152*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
153*00b67f09SDavid van Moolenbroek 
154*00b67f09SDavid van Moolenbroek 	if (acl->length != 0 || acl->node_count != 1)
155*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
156*00b67f09SDavid van Moolenbroek 
157*00b67f09SDavid van Moolenbroek 	if (acl->iptable->radix->head->prefix->bitlen == 0 &&
158*00b67f09SDavid van Moolenbroek 	    acl->iptable->radix->head->data[0] != NULL &&
159*00b67f09SDavid van Moolenbroek 	    acl->iptable->radix->head->data[0] ==
160*00b67f09SDavid van Moolenbroek 		    acl->iptable->radix->head->data[1] &&
161*00b67f09SDavid van Moolenbroek 	    *(isc_boolean_t *) (acl->iptable->radix->head->data[0]) == pos)
162*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
163*00b67f09SDavid van Moolenbroek 
164*00b67f09SDavid van Moolenbroek 	return (ISC_FALSE); /* All others */
165*00b67f09SDavid van Moolenbroek }
166*00b67f09SDavid van Moolenbroek 
167*00b67f09SDavid van Moolenbroek /*
168*00b67f09SDavid van Moolenbroek  * Test whether acl is set to "{ any; }"
169*00b67f09SDavid van Moolenbroek  */
170*00b67f09SDavid van Moolenbroek isc_boolean_t
dns_acl_isany(dns_acl_t * acl)171*00b67f09SDavid van Moolenbroek dns_acl_isany(dns_acl_t *acl)
172*00b67f09SDavid van Moolenbroek {
173*00b67f09SDavid van Moolenbroek 	return (dns_acl_isanyornone(acl, ISC_TRUE));
174*00b67f09SDavid van Moolenbroek }
175*00b67f09SDavid van Moolenbroek 
176*00b67f09SDavid van Moolenbroek /*
177*00b67f09SDavid van Moolenbroek  * Test whether acl is set to "{ none; }"
178*00b67f09SDavid van Moolenbroek  */
179*00b67f09SDavid van Moolenbroek isc_boolean_t
dns_acl_isnone(dns_acl_t * acl)180*00b67f09SDavid van Moolenbroek dns_acl_isnone(dns_acl_t *acl)
181*00b67f09SDavid van Moolenbroek {
182*00b67f09SDavid van Moolenbroek 	return (dns_acl_isanyornone(acl, ISC_FALSE));
183*00b67f09SDavid van Moolenbroek }
184*00b67f09SDavid van Moolenbroek 
185*00b67f09SDavid van Moolenbroek /*
186*00b67f09SDavid van Moolenbroek  * Determine whether a given address or signer matches a given ACL.
187*00b67f09SDavid van Moolenbroek  * For a match with a positive ACL element or iptable radix entry,
188*00b67f09SDavid van Moolenbroek  * return with a positive value in match; for a match with a negated ACL
189*00b67f09SDavid van Moolenbroek  * element or radix entry, return with a negative value in match.
190*00b67f09SDavid van Moolenbroek  */
191*00b67f09SDavid van Moolenbroek isc_result_t
dns_acl_match(const isc_netaddr_t * reqaddr,const dns_name_t * reqsigner,const dns_acl_t * acl,const dns_aclenv_t * env,int * match,const dns_aclelement_t ** matchelt)192*00b67f09SDavid van Moolenbroek dns_acl_match(const isc_netaddr_t *reqaddr,
193*00b67f09SDavid van Moolenbroek 	      const dns_name_t *reqsigner,
194*00b67f09SDavid van Moolenbroek 	      const dns_acl_t *acl,
195*00b67f09SDavid van Moolenbroek 	      const dns_aclenv_t *env,
196*00b67f09SDavid van Moolenbroek 	      int *match,
197*00b67f09SDavid van Moolenbroek 	      const dns_aclelement_t **matchelt)
198*00b67f09SDavid van Moolenbroek {
199*00b67f09SDavid van Moolenbroek 	isc_uint16_t bitlen, family;
200*00b67f09SDavid van Moolenbroek 	isc_prefix_t pfx;
201*00b67f09SDavid van Moolenbroek 	isc_radix_node_t *node = NULL;
202*00b67f09SDavid van Moolenbroek 	const isc_netaddr_t *addr;
203*00b67f09SDavid van Moolenbroek 	isc_netaddr_t v4addr;
204*00b67f09SDavid van Moolenbroek 	isc_result_t result;
205*00b67f09SDavid van Moolenbroek 	int match_num = -1;
206*00b67f09SDavid van Moolenbroek 	unsigned int i;
207*00b67f09SDavid van Moolenbroek 
208*00b67f09SDavid van Moolenbroek 	REQUIRE(reqaddr != NULL);
209*00b67f09SDavid van Moolenbroek 	REQUIRE(matchelt == NULL || *matchelt == NULL);
210*00b67f09SDavid van Moolenbroek 
211*00b67f09SDavid van Moolenbroek 	if (env == NULL || env->match_mapped == ISC_FALSE ||
212*00b67f09SDavid van Moolenbroek 	    reqaddr->family != AF_INET6 ||
213*00b67f09SDavid van Moolenbroek 	    !IN6_IS_ADDR_V4MAPPED(&reqaddr->type.in6))
214*00b67f09SDavid van Moolenbroek 		addr = reqaddr;
215*00b67f09SDavid van Moolenbroek 	else {
216*00b67f09SDavid van Moolenbroek 		isc_netaddr_fromv4mapped(&v4addr, reqaddr);
217*00b67f09SDavid van Moolenbroek 		addr = &v4addr;
218*00b67f09SDavid van Moolenbroek 	}
219*00b67f09SDavid van Moolenbroek 
220*00b67f09SDavid van Moolenbroek 	/* Always match with host addresses. */
221*00b67f09SDavid van Moolenbroek 	family = addr->family;
222*00b67f09SDavid van Moolenbroek 	bitlen = family == AF_INET6 ? 128 : 32;
223*00b67f09SDavid van Moolenbroek 	NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
224*00b67f09SDavid van Moolenbroek 
225*00b67f09SDavid van Moolenbroek 	/* Assume no match. */
226*00b67f09SDavid van Moolenbroek 	*match = 0;
227*00b67f09SDavid van Moolenbroek 
228*00b67f09SDavid van Moolenbroek 	/* Search radix. */
229*00b67f09SDavid van Moolenbroek 	result = isc_radix_search(acl->iptable->radix, &node, &pfx);
230*00b67f09SDavid van Moolenbroek 
231*00b67f09SDavid van Moolenbroek 	/* Found a match. */
232*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS && node != NULL) {
233*00b67f09SDavid van Moolenbroek 		match_num = node->node_num[ISC_IS6(family)];
234*00b67f09SDavid van Moolenbroek 		if (*(isc_boolean_t *) node->data[ISC_IS6(family)] == ISC_TRUE)
235*00b67f09SDavid van Moolenbroek 			*match = match_num;
236*00b67f09SDavid van Moolenbroek 		else
237*00b67f09SDavid van Moolenbroek 			*match = -match_num;
238*00b67f09SDavid van Moolenbroek 	}
239*00b67f09SDavid van Moolenbroek 
240*00b67f09SDavid van Moolenbroek 	/* Now search non-radix elements for a match with a lower node_num. */
241*00b67f09SDavid van Moolenbroek 	for (i = 0; i < acl->length; i++) {
242*00b67f09SDavid van Moolenbroek 		dns_aclelement_t *e = &acl->elements[i];
243*00b67f09SDavid van Moolenbroek 
244*00b67f09SDavid van Moolenbroek 		/* Already found a better match? */
245*00b67f09SDavid van Moolenbroek 		if (match_num != -1 && match_num < e->node_num) {
246*00b67f09SDavid van Moolenbroek 			isc_refcount_destroy(&pfx.refcount);
247*00b67f09SDavid van Moolenbroek 			return (ISC_R_SUCCESS);
248*00b67f09SDavid van Moolenbroek 		}
249*00b67f09SDavid van Moolenbroek 
250*00b67f09SDavid van Moolenbroek 		if (dns_aclelement_match(reqaddr, reqsigner,
251*00b67f09SDavid van Moolenbroek 					 e, env, matchelt)) {
252*00b67f09SDavid van Moolenbroek 			if (match_num == -1 || e->node_num < match_num) {
253*00b67f09SDavid van Moolenbroek 				if (e->negative == ISC_TRUE)
254*00b67f09SDavid van Moolenbroek 					*match = -e->node_num;
255*00b67f09SDavid van Moolenbroek 				else
256*00b67f09SDavid van Moolenbroek 					*match = e->node_num;
257*00b67f09SDavid van Moolenbroek 			}
258*00b67f09SDavid van Moolenbroek 			isc_refcount_destroy(&pfx.refcount);
259*00b67f09SDavid van Moolenbroek 			return (ISC_R_SUCCESS);
260*00b67f09SDavid van Moolenbroek 		}
261*00b67f09SDavid van Moolenbroek 	}
262*00b67f09SDavid van Moolenbroek 
263*00b67f09SDavid van Moolenbroek 	isc_refcount_destroy(&pfx.refcount);
264*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
265*00b67f09SDavid van Moolenbroek }
266*00b67f09SDavid van Moolenbroek 
267*00b67f09SDavid van Moolenbroek /*
268*00b67f09SDavid van Moolenbroek  * Merge the contents of one ACL into another.  Call dns_iptable_merge()
269*00b67f09SDavid van Moolenbroek  * for the IP tables, then concatenate the element arrays.
270*00b67f09SDavid van Moolenbroek  *
271*00b67f09SDavid van Moolenbroek  * If pos is set to false, then the nested ACL is to be negated.  This
272*00b67f09SDavid van Moolenbroek  * means reverse the sense of each *positive* element or IP table node,
273*00b67f09SDavid van Moolenbroek  * but leave negatives alone, so as to prevent a double-negative causing
274*00b67f09SDavid van Moolenbroek  * an unexpected positive match in the parent ACL.
275*00b67f09SDavid van Moolenbroek  */
276*00b67f09SDavid van Moolenbroek isc_result_t
dns_acl_merge(dns_acl_t * dest,dns_acl_t * source,isc_boolean_t pos)277*00b67f09SDavid van Moolenbroek dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
278*00b67f09SDavid van Moolenbroek {
279*00b67f09SDavid van Moolenbroek 	isc_result_t result;
280*00b67f09SDavid van Moolenbroek 	unsigned int newalloc, nelem, i;
281*00b67f09SDavid van Moolenbroek 	int max_node = 0, nodes;
282*00b67f09SDavid van Moolenbroek 
283*00b67f09SDavid van Moolenbroek 	/* Resize the element array if needed. */
284*00b67f09SDavid van Moolenbroek 	if (dest->length + source->length > dest->alloc) {
285*00b67f09SDavid van Moolenbroek 		void *newmem;
286*00b67f09SDavid van Moolenbroek 
287*00b67f09SDavid van Moolenbroek 		newalloc = dest->alloc + source->alloc;
288*00b67f09SDavid van Moolenbroek 		if (newalloc < 4)
289*00b67f09SDavid van Moolenbroek 			newalloc = 4;
290*00b67f09SDavid van Moolenbroek 
291*00b67f09SDavid van Moolenbroek 		newmem = isc_mem_get(dest->mctx,
292*00b67f09SDavid van Moolenbroek 				     newalloc * sizeof(dns_aclelement_t));
293*00b67f09SDavid van Moolenbroek 		if (newmem == NULL)
294*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOMEMORY);
295*00b67f09SDavid van Moolenbroek 
296*00b67f09SDavid van Moolenbroek 		/* Zero. */
297*00b67f09SDavid van Moolenbroek 		memset(newmem, 0, newalloc * sizeof(dns_aclelement_t));
298*00b67f09SDavid van Moolenbroek 
299*00b67f09SDavid van Moolenbroek 		/* Copy in the original elements */
300*00b67f09SDavid van Moolenbroek 		memmove(newmem, dest->elements,
301*00b67f09SDavid van Moolenbroek 			dest->length * sizeof(dns_aclelement_t));
302*00b67f09SDavid van Moolenbroek 
303*00b67f09SDavid van Moolenbroek 		/* Release the memory for the old elements array */
304*00b67f09SDavid van Moolenbroek 		isc_mem_put(dest->mctx, dest->elements,
305*00b67f09SDavid van Moolenbroek 			    dest->alloc * sizeof(dns_aclelement_t));
306*00b67f09SDavid van Moolenbroek 		dest->elements = newmem;
307*00b67f09SDavid van Moolenbroek 		dest->alloc = newalloc;
308*00b67f09SDavid van Moolenbroek 	}
309*00b67f09SDavid van Moolenbroek 
310*00b67f09SDavid van Moolenbroek 	/*
311*00b67f09SDavid van Moolenbroek 	 * Now copy in the new elements, increasing their node_num
312*00b67f09SDavid van Moolenbroek 	 * values so as to keep the new ACL consistent.  If we're
313*00b67f09SDavid van Moolenbroek 	 * negating, then negate positive elements, but keep negative
314*00b67f09SDavid van Moolenbroek 	 * elements the same for security reasons.
315*00b67f09SDavid van Moolenbroek 	 */
316*00b67f09SDavid van Moolenbroek 	nelem = dest->length;
317*00b67f09SDavid van Moolenbroek 	dest->length += source->length;
318*00b67f09SDavid van Moolenbroek 	for (i = 0; i < source->length; i++) {
319*00b67f09SDavid van Moolenbroek 		if (source->elements[i].node_num > max_node)
320*00b67f09SDavid van Moolenbroek 			max_node = source->elements[i].node_num;
321*00b67f09SDavid van Moolenbroek 
322*00b67f09SDavid van Moolenbroek 		/* Copy type. */
323*00b67f09SDavid van Moolenbroek 		dest->elements[nelem + i].type = source->elements[i].type;
324*00b67f09SDavid van Moolenbroek 
325*00b67f09SDavid van Moolenbroek 		/* Adjust node numbering. */
326*00b67f09SDavid van Moolenbroek 		dest->elements[nelem + i].node_num =
327*00b67f09SDavid van Moolenbroek 			source->elements[i].node_num + dest->node_count;
328*00b67f09SDavid van Moolenbroek 
329*00b67f09SDavid van Moolenbroek 		/* Duplicate nested acl. */
330*00b67f09SDavid van Moolenbroek 		if (source->elements[i].type == dns_aclelementtype_nestedacl &&
331*00b67f09SDavid van Moolenbroek 		   source->elements[i].nestedacl != NULL)
332*00b67f09SDavid van Moolenbroek 			dns_acl_attach(source->elements[i].nestedacl,
333*00b67f09SDavid van Moolenbroek 				       &dest->elements[nelem + i].nestedacl);
334*00b67f09SDavid van Moolenbroek 
335*00b67f09SDavid van Moolenbroek 		/* Duplicate key name. */
336*00b67f09SDavid van Moolenbroek 		if (source->elements[i].type == dns_aclelementtype_keyname) {
337*00b67f09SDavid van Moolenbroek 			dns_name_init(&dest->elements[nelem+i].keyname, NULL);
338*00b67f09SDavid van Moolenbroek 			result = dns_name_dup(&source->elements[i].keyname,
339*00b67f09SDavid van Moolenbroek 					      dest->mctx,
340*00b67f09SDavid van Moolenbroek 					      &dest->elements[nelem+i].keyname);
341*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
342*00b67f09SDavid van Moolenbroek 				return result;
343*00b67f09SDavid van Moolenbroek 		}
344*00b67f09SDavid van Moolenbroek 
345*00b67f09SDavid van Moolenbroek #ifdef HAVE_GEOIP
346*00b67f09SDavid van Moolenbroek 		/* Duplicate GeoIP data */
347*00b67f09SDavid van Moolenbroek 		if (source->elements[i].type == dns_aclelementtype_geoip) {
348*00b67f09SDavid van Moolenbroek 			dest->elements[nelem + i].geoip_elem =
349*00b67f09SDavid van Moolenbroek 				source->elements[i].geoip_elem;
350*00b67f09SDavid van Moolenbroek 		}
351*00b67f09SDavid van Moolenbroek #endif
352*00b67f09SDavid van Moolenbroek 
353*00b67f09SDavid van Moolenbroek 		/* reverse sense of positives if this is a negative acl */
354*00b67f09SDavid van Moolenbroek 		if (!pos && source->elements[i].negative == ISC_FALSE) {
355*00b67f09SDavid van Moolenbroek 			dest->elements[nelem + i].negative = ISC_TRUE;
356*00b67f09SDavid van Moolenbroek 		} else {
357*00b67f09SDavid van Moolenbroek 			dest->elements[nelem + i].negative =
358*00b67f09SDavid van Moolenbroek 				source->elements[i].negative;
359*00b67f09SDavid van Moolenbroek 		}
360*00b67f09SDavid van Moolenbroek 	}
361*00b67f09SDavid van Moolenbroek 
362*00b67f09SDavid van Moolenbroek 	/*
363*00b67f09SDavid van Moolenbroek 	 * Merge the iptables.  Make sure the destination ACL's
364*00b67f09SDavid van Moolenbroek 	 * node_count value is set correctly afterward.
365*00b67f09SDavid van Moolenbroek 	 */
366*00b67f09SDavid van Moolenbroek 	nodes = max_node + dest->node_count;
367*00b67f09SDavid van Moolenbroek 	result = dns_iptable_merge(dest->iptable, source->iptable, pos);
368*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
369*00b67f09SDavid van Moolenbroek 		return (result);
370*00b67f09SDavid van Moolenbroek 	if (nodes > dest->node_count)
371*00b67f09SDavid van Moolenbroek 		dest->node_count = nodes;
372*00b67f09SDavid van Moolenbroek 
373*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
374*00b67f09SDavid van Moolenbroek }
375*00b67f09SDavid van Moolenbroek 
376*00b67f09SDavid van Moolenbroek /*
377*00b67f09SDavid van Moolenbroek  * Like dns_acl_match, but matches against the single ACL element 'e'
378*00b67f09SDavid van Moolenbroek  * rather than a complete ACL, and returns ISC_TRUE iff it matched.
379*00b67f09SDavid van Moolenbroek  *
380*00b67f09SDavid van Moolenbroek  * To determine whether the match was positive or negative, the
381*00b67f09SDavid van Moolenbroek  * caller should examine e->negative.  Since the element 'e' may be
382*00b67f09SDavid van Moolenbroek  * a reference to a named ACL or a nested ACL, a matching element
383*00b67f09SDavid van Moolenbroek  * returned through 'matchelt' is not necessarily 'e' itself.
384*00b67f09SDavid van Moolenbroek  */
385*00b67f09SDavid van Moolenbroek isc_boolean_t
dns_aclelement_match(const isc_netaddr_t * reqaddr,const dns_name_t * reqsigner,const dns_aclelement_t * e,const dns_aclenv_t * env,const dns_aclelement_t ** matchelt)386*00b67f09SDavid van Moolenbroek dns_aclelement_match(const isc_netaddr_t *reqaddr,
387*00b67f09SDavid van Moolenbroek 		     const dns_name_t *reqsigner,
388*00b67f09SDavid van Moolenbroek 		     const dns_aclelement_t *e,
389*00b67f09SDavid van Moolenbroek 		     const dns_aclenv_t *env,
390*00b67f09SDavid van Moolenbroek 		     const dns_aclelement_t **matchelt)
391*00b67f09SDavid van Moolenbroek {
392*00b67f09SDavid van Moolenbroek 	dns_acl_t *inner = NULL;
393*00b67f09SDavid van Moolenbroek 	int indirectmatch;
394*00b67f09SDavid van Moolenbroek 	isc_result_t result;
395*00b67f09SDavid van Moolenbroek 
396*00b67f09SDavid van Moolenbroek 	switch (e->type) {
397*00b67f09SDavid van Moolenbroek 	case dns_aclelementtype_keyname:
398*00b67f09SDavid van Moolenbroek 		if (reqsigner != NULL &&
399*00b67f09SDavid van Moolenbroek 		    dns_name_equal(reqsigner, &e->keyname)) {
400*00b67f09SDavid van Moolenbroek 			if (matchelt != NULL)
401*00b67f09SDavid van Moolenbroek 				*matchelt = e;
402*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
403*00b67f09SDavid van Moolenbroek 		} else
404*00b67f09SDavid van Moolenbroek 			return (ISC_FALSE);
405*00b67f09SDavid van Moolenbroek 
406*00b67f09SDavid van Moolenbroek 	case dns_aclelementtype_nestedacl:
407*00b67f09SDavid van Moolenbroek 		inner = e->nestedacl;
408*00b67f09SDavid van Moolenbroek 		break;
409*00b67f09SDavid van Moolenbroek 
410*00b67f09SDavid van Moolenbroek 	case dns_aclelementtype_localhost:
411*00b67f09SDavid van Moolenbroek 		if (env == NULL || env->localhost == NULL)
412*00b67f09SDavid van Moolenbroek 			return (ISC_FALSE);
413*00b67f09SDavid van Moolenbroek 		inner = env->localhost;
414*00b67f09SDavid van Moolenbroek 		break;
415*00b67f09SDavid van Moolenbroek 
416*00b67f09SDavid van Moolenbroek 	case dns_aclelementtype_localnets:
417*00b67f09SDavid van Moolenbroek 		if (env == NULL || env->localnets == NULL)
418*00b67f09SDavid van Moolenbroek 			return (ISC_FALSE);
419*00b67f09SDavid van Moolenbroek 		inner = env->localnets;
420*00b67f09SDavid van Moolenbroek 		break;
421*00b67f09SDavid van Moolenbroek 
422*00b67f09SDavid van Moolenbroek #ifdef HAVE_GEOIP
423*00b67f09SDavid van Moolenbroek 	case dns_aclelementtype_geoip:
424*00b67f09SDavid van Moolenbroek 		if (env == NULL || env->geoip == NULL)
425*00b67f09SDavid van Moolenbroek 			return (ISC_FALSE);
426*00b67f09SDavid van Moolenbroek 		return (dns_geoip_match(reqaddr, env->geoip, &e->geoip_elem));
427*00b67f09SDavid van Moolenbroek #endif
428*00b67f09SDavid van Moolenbroek 	default:
429*00b67f09SDavid van Moolenbroek 		/* Should be impossible. */
430*00b67f09SDavid van Moolenbroek 		INSIST(0);
431*00b67f09SDavid van Moolenbroek 	}
432*00b67f09SDavid van Moolenbroek 
433*00b67f09SDavid van Moolenbroek 	result = dns_acl_match(reqaddr, reqsigner, inner, env,
434*00b67f09SDavid van Moolenbroek 			       &indirectmatch, matchelt);
435*00b67f09SDavid van Moolenbroek 	INSIST(result == ISC_R_SUCCESS);
436*00b67f09SDavid van Moolenbroek 
437*00b67f09SDavid van Moolenbroek 	/*
438*00b67f09SDavid van Moolenbroek 	 * Treat negative matches in indirect ACLs as "no match".
439*00b67f09SDavid van Moolenbroek 	 * That way, a negated indirect ACL will never become a
440*00b67f09SDavid van Moolenbroek 	 * surprise positive match through double negation.
441*00b67f09SDavid van Moolenbroek 	 * XXXDCL this should be documented.
442*00b67f09SDavid van Moolenbroek 	 */
443*00b67f09SDavid van Moolenbroek 
444*00b67f09SDavid van Moolenbroek 	if (indirectmatch > 0) {
445*00b67f09SDavid van Moolenbroek 		if (matchelt != NULL)
446*00b67f09SDavid van Moolenbroek 			*matchelt = e;
447*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
448*00b67f09SDavid van Moolenbroek 	}
449*00b67f09SDavid van Moolenbroek 
450*00b67f09SDavid van Moolenbroek 	/*
451*00b67f09SDavid van Moolenbroek 	 * A negative indirect match may have set *matchelt, but we don't
452*00b67f09SDavid van Moolenbroek 	 * want it set when we return.
453*00b67f09SDavid van Moolenbroek 	 */
454*00b67f09SDavid van Moolenbroek 
455*00b67f09SDavid van Moolenbroek 	if (matchelt != NULL)
456*00b67f09SDavid van Moolenbroek 		*matchelt = NULL;
457*00b67f09SDavid van Moolenbroek 
458*00b67f09SDavid van Moolenbroek 	return (ISC_FALSE);
459*00b67f09SDavid van Moolenbroek }
460*00b67f09SDavid van Moolenbroek 
461*00b67f09SDavid van Moolenbroek void
dns_acl_attach(dns_acl_t * source,dns_acl_t ** target)462*00b67f09SDavid van Moolenbroek dns_acl_attach(dns_acl_t *source, dns_acl_t **target) {
463*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_ACL_VALID(source));
464*00b67f09SDavid van Moolenbroek 
465*00b67f09SDavid van Moolenbroek 	isc_refcount_increment(&source->refcount, NULL);
466*00b67f09SDavid van Moolenbroek 	*target = source;
467*00b67f09SDavid van Moolenbroek }
468*00b67f09SDavid van Moolenbroek 
469*00b67f09SDavid van Moolenbroek static void
destroy(dns_acl_t * dacl)470*00b67f09SDavid van Moolenbroek destroy(dns_acl_t *dacl) {
471*00b67f09SDavid van Moolenbroek 	unsigned int i;
472*00b67f09SDavid van Moolenbroek 
473*00b67f09SDavid van Moolenbroek 	INSIST(!ISC_LINK_LINKED(dacl, nextincache));
474*00b67f09SDavid van Moolenbroek 
475*00b67f09SDavid van Moolenbroek 	for (i = 0; i < dacl->length; i++) {
476*00b67f09SDavid van Moolenbroek 		dns_aclelement_t *de = &dacl->elements[i];
477*00b67f09SDavid van Moolenbroek 		if (de->type == dns_aclelementtype_keyname) {
478*00b67f09SDavid van Moolenbroek 			dns_name_free(&de->keyname, dacl->mctx);
479*00b67f09SDavid van Moolenbroek 		} else if (de->type == dns_aclelementtype_nestedacl) {
480*00b67f09SDavid van Moolenbroek 			dns_acl_detach(&de->nestedacl);
481*00b67f09SDavid van Moolenbroek 		}
482*00b67f09SDavid van Moolenbroek 	}
483*00b67f09SDavid van Moolenbroek 	if (dacl->elements != NULL)
484*00b67f09SDavid van Moolenbroek 		isc_mem_put(dacl->mctx, dacl->elements,
485*00b67f09SDavid van Moolenbroek 			    dacl->alloc * sizeof(dns_aclelement_t));
486*00b67f09SDavid van Moolenbroek 	if (dacl->name != NULL)
487*00b67f09SDavid van Moolenbroek 		isc_mem_free(dacl->mctx, dacl->name);
488*00b67f09SDavid van Moolenbroek 	if (dacl->iptable != NULL)
489*00b67f09SDavid van Moolenbroek 		dns_iptable_detach(&dacl->iptable);
490*00b67f09SDavid van Moolenbroek 	isc_refcount_destroy(&dacl->refcount);
491*00b67f09SDavid van Moolenbroek 	dacl->magic = 0;
492*00b67f09SDavid van Moolenbroek 	isc_mem_putanddetach(&dacl->mctx, dacl, sizeof(*dacl));
493*00b67f09SDavid van Moolenbroek }
494*00b67f09SDavid van Moolenbroek 
495*00b67f09SDavid van Moolenbroek void
dns_acl_detach(dns_acl_t ** aclp)496*00b67f09SDavid van Moolenbroek dns_acl_detach(dns_acl_t **aclp) {
497*00b67f09SDavid van Moolenbroek 	dns_acl_t *acl = *aclp;
498*00b67f09SDavid van Moolenbroek 	unsigned int refs;
499*00b67f09SDavid van Moolenbroek 
500*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_ACL_VALID(acl));
501*00b67f09SDavid van Moolenbroek 
502*00b67f09SDavid van Moolenbroek 	isc_refcount_decrement(&acl->refcount, &refs);
503*00b67f09SDavid van Moolenbroek 	if (refs == 0)
504*00b67f09SDavid van Moolenbroek 		destroy(acl);
505*00b67f09SDavid van Moolenbroek 	*aclp = NULL;
506*00b67f09SDavid van Moolenbroek }
507*00b67f09SDavid van Moolenbroek 
508*00b67f09SDavid van Moolenbroek 
509*00b67f09SDavid van Moolenbroek static isc_once_t	insecure_prefix_once = ISC_ONCE_INIT;
510*00b67f09SDavid van Moolenbroek static isc_mutex_t	insecure_prefix_lock;
511*00b67f09SDavid van Moolenbroek static isc_boolean_t	insecure_prefix_found;
512*00b67f09SDavid van Moolenbroek 
513*00b67f09SDavid van Moolenbroek static void
initialize_action(void)514*00b67f09SDavid van Moolenbroek initialize_action(void) {
515*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_mutex_init(&insecure_prefix_lock) == ISC_R_SUCCESS);
516*00b67f09SDavid van Moolenbroek }
517*00b67f09SDavid van Moolenbroek 
518*00b67f09SDavid van Moolenbroek /*
519*00b67f09SDavid van Moolenbroek  * Called via isc_radix_walk() to find IP table nodes that are
520*00b67f09SDavid van Moolenbroek  * insecure.
521*00b67f09SDavid van Moolenbroek  */
522*00b67f09SDavid van Moolenbroek static void
is_insecure(isc_prefix_t * prefix,void ** data)523*00b67f09SDavid van Moolenbroek is_insecure(isc_prefix_t *prefix, void **data) {
524*00b67f09SDavid van Moolenbroek 	isc_boolean_t secure;
525*00b67f09SDavid van Moolenbroek 	int bitlen, family;
526*00b67f09SDavid van Moolenbroek 
527*00b67f09SDavid van Moolenbroek 	bitlen = prefix->bitlen;
528*00b67f09SDavid van Moolenbroek 	family = prefix->family;
529*00b67f09SDavid van Moolenbroek 
530*00b67f09SDavid van Moolenbroek 	/* Negated entries are always secure. */
531*00b67f09SDavid van Moolenbroek 	secure = * (isc_boolean_t *)data[ISC_IS6(family)];
532*00b67f09SDavid van Moolenbroek 	if (!secure) {
533*00b67f09SDavid van Moolenbroek 		return;
534*00b67f09SDavid van Moolenbroek 	}
535*00b67f09SDavid van Moolenbroek 
536*00b67f09SDavid van Moolenbroek 	/* If loopback prefix found, return */
537*00b67f09SDavid van Moolenbroek 	switch (family) {
538*00b67f09SDavid van Moolenbroek 	case AF_INET:
539*00b67f09SDavid van Moolenbroek 		if (bitlen == 32 &&
540*00b67f09SDavid van Moolenbroek 		    htonl(prefix->add.sin.s_addr) == INADDR_LOOPBACK)
541*00b67f09SDavid van Moolenbroek 			return;
542*00b67f09SDavid van Moolenbroek 		break;
543*00b67f09SDavid van Moolenbroek 	case AF_INET6:
544*00b67f09SDavid van Moolenbroek 		if (bitlen == 128 && IN6_IS_ADDR_LOOPBACK(&prefix->add.sin6))
545*00b67f09SDavid van Moolenbroek 			return;
546*00b67f09SDavid van Moolenbroek 		break;
547*00b67f09SDavid van Moolenbroek 	default:
548*00b67f09SDavid van Moolenbroek 		break;
549*00b67f09SDavid van Moolenbroek 	}
550*00b67f09SDavid van Moolenbroek 
551*00b67f09SDavid van Moolenbroek 	/* Non-negated, non-loopback */
552*00b67f09SDavid van Moolenbroek 	insecure_prefix_found = ISC_TRUE;	/* LOCKED */
553*00b67f09SDavid van Moolenbroek 	return;
554*00b67f09SDavid van Moolenbroek }
555*00b67f09SDavid van Moolenbroek 
556*00b67f09SDavid van Moolenbroek /*
557*00b67f09SDavid van Moolenbroek  * Return ISC_TRUE iff the acl 'a' is considered insecure, that is,
558*00b67f09SDavid van Moolenbroek  * if it contains IP addresses other than those of the local host.
559*00b67f09SDavid van Moolenbroek  * This is intended for applications such as printing warning
560*00b67f09SDavid van Moolenbroek  * messages for suspect ACLs; it is not intended for making access
561*00b67f09SDavid van Moolenbroek  * control decisions.  We make no guarantee that an ACL for which
562*00b67f09SDavid van Moolenbroek  * this function returns ISC_FALSE is safe.
563*00b67f09SDavid van Moolenbroek  */
564*00b67f09SDavid van Moolenbroek isc_boolean_t
dns_acl_isinsecure(const dns_acl_t * a)565*00b67f09SDavid van Moolenbroek dns_acl_isinsecure(const dns_acl_t *a) {
566*00b67f09SDavid van Moolenbroek 	unsigned int i;
567*00b67f09SDavid van Moolenbroek 	isc_boolean_t insecure;
568*00b67f09SDavid van Moolenbroek 
569*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_once_do(&insecure_prefix_once,
570*00b67f09SDavid van Moolenbroek 				  initialize_action) == ISC_R_SUCCESS);
571*00b67f09SDavid van Moolenbroek 
572*00b67f09SDavid van Moolenbroek 	/*
573*00b67f09SDavid van Moolenbroek 	 * Walk radix tree to find out if there are any non-negated,
574*00b67f09SDavid van Moolenbroek 	 * non-loopback prefixes.
575*00b67f09SDavid van Moolenbroek 	 */
576*00b67f09SDavid van Moolenbroek 	LOCK(&insecure_prefix_lock);
577*00b67f09SDavid van Moolenbroek 	insecure_prefix_found = ISC_FALSE;
578*00b67f09SDavid van Moolenbroek 	isc_radix_process(a->iptable->radix, is_insecure);
579*00b67f09SDavid van Moolenbroek 	insecure = insecure_prefix_found;
580*00b67f09SDavid van Moolenbroek 	UNLOCK(&insecure_prefix_lock);
581*00b67f09SDavid van Moolenbroek 	if (insecure)
582*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
583*00b67f09SDavid van Moolenbroek 
584*00b67f09SDavid van Moolenbroek 	/* Now check non-radix elements */
585*00b67f09SDavid van Moolenbroek 	for (i = 0; i < a->length; i++) {
586*00b67f09SDavid van Moolenbroek 		dns_aclelement_t *e = &a->elements[i];
587*00b67f09SDavid van Moolenbroek 
588*00b67f09SDavid van Moolenbroek 		/* A negated match can never be insecure. */
589*00b67f09SDavid van Moolenbroek 		if (e->negative)
590*00b67f09SDavid van Moolenbroek 			continue;
591*00b67f09SDavid van Moolenbroek 
592*00b67f09SDavid van Moolenbroek 		switch (e->type) {
593*00b67f09SDavid van Moolenbroek 		case dns_aclelementtype_keyname:
594*00b67f09SDavid van Moolenbroek 		case dns_aclelementtype_localhost:
595*00b67f09SDavid van Moolenbroek 			continue;
596*00b67f09SDavid van Moolenbroek 
597*00b67f09SDavid van Moolenbroek 		case dns_aclelementtype_nestedacl:
598*00b67f09SDavid van Moolenbroek 			if (dns_acl_isinsecure(e->nestedacl))
599*00b67f09SDavid van Moolenbroek 				return (ISC_TRUE);
600*00b67f09SDavid van Moolenbroek 			continue;
601*00b67f09SDavid van Moolenbroek 
602*00b67f09SDavid van Moolenbroek 		case dns_aclelementtype_localnets:
603*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
604*00b67f09SDavid van Moolenbroek 
605*00b67f09SDavid van Moolenbroek 		default:
606*00b67f09SDavid van Moolenbroek 			INSIST(0);
607*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
608*00b67f09SDavid van Moolenbroek 		}
609*00b67f09SDavid van Moolenbroek 	}
610*00b67f09SDavid van Moolenbroek 
611*00b67f09SDavid van Moolenbroek 	/* No insecure elements were found. */
612*00b67f09SDavid van Moolenbroek 	return (ISC_FALSE);
613*00b67f09SDavid van Moolenbroek }
614*00b67f09SDavid van Moolenbroek 
615*00b67f09SDavid van Moolenbroek /*
616*00b67f09SDavid van Moolenbroek  * Initialize ACL environment, setting up localhost and localnets ACLs
617*00b67f09SDavid van Moolenbroek  */
618*00b67f09SDavid van Moolenbroek isc_result_t
dns_aclenv_init(isc_mem_t * mctx,dns_aclenv_t * env)619*00b67f09SDavid van Moolenbroek dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) {
620*00b67f09SDavid van Moolenbroek 	isc_result_t result;
621*00b67f09SDavid van Moolenbroek 
622*00b67f09SDavid van Moolenbroek 	env->localhost = NULL;
623*00b67f09SDavid van Moolenbroek 	env->localnets = NULL;
624*00b67f09SDavid van Moolenbroek 	result = dns_acl_create(mctx, 0, &env->localhost);
625*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
626*00b67f09SDavid van Moolenbroek 		goto cleanup_nothing;
627*00b67f09SDavid van Moolenbroek 	result = dns_acl_create(mctx, 0, &env->localnets);
628*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
629*00b67f09SDavid van Moolenbroek 		goto cleanup_localhost;
630*00b67f09SDavid van Moolenbroek 	env->match_mapped = ISC_FALSE;
631*00b67f09SDavid van Moolenbroek #ifdef HAVE_GEOIP
632*00b67f09SDavid van Moolenbroek 	env->geoip = NULL;
633*00b67f09SDavid van Moolenbroek #endif
634*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
635*00b67f09SDavid van Moolenbroek 
636*00b67f09SDavid van Moolenbroek  cleanup_localhost:
637*00b67f09SDavid van Moolenbroek 	dns_acl_detach(&env->localhost);
638*00b67f09SDavid van Moolenbroek  cleanup_nothing:
639*00b67f09SDavid van Moolenbroek 	return (result);
640*00b67f09SDavid van Moolenbroek }
641*00b67f09SDavid van Moolenbroek 
642*00b67f09SDavid van Moolenbroek void
dns_aclenv_copy(dns_aclenv_t * t,dns_aclenv_t * s)643*00b67f09SDavid van Moolenbroek dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s) {
644*00b67f09SDavid van Moolenbroek 	dns_acl_detach(&t->localhost);
645*00b67f09SDavid van Moolenbroek 	dns_acl_attach(s->localhost, &t->localhost);
646*00b67f09SDavid van Moolenbroek 	dns_acl_detach(&t->localnets);
647*00b67f09SDavid van Moolenbroek 	dns_acl_attach(s->localnets, &t->localnets);
648*00b67f09SDavid van Moolenbroek 	t->match_mapped = s->match_mapped;
649*00b67f09SDavid van Moolenbroek }
650*00b67f09SDavid van Moolenbroek 
651*00b67f09SDavid van Moolenbroek void
dns_aclenv_destroy(dns_aclenv_t * env)652*00b67f09SDavid van Moolenbroek dns_aclenv_destroy(dns_aclenv_t *env) {
653*00b67f09SDavid van Moolenbroek 	dns_acl_detach(&env->localhost);
654*00b67f09SDavid van Moolenbroek 	dns_acl_detach(&env->localnets);
655*00b67f09SDavid van Moolenbroek }
656