acl.c revision 39bb14491fa6d55c83b0a61dc07bf7864a726323
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley/*
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Copyright (C) 1999-2001 Internet Software Consortium.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley *
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Permission to use, copy, modify, and distribute this software for any
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * purpose with or without fee is hereby granted, provided that the above
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * copyright notice and this permission notice appear in all copies.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley *
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley/* $Id: acl.c,v 1.19 2001/01/17 02:58:28 bwelling Exp $ */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <config.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <isc/mem.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <isc/string.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <isc/util.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <dns/acl.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleyisc_result_t
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleydns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_result_t result;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_acl_t *acl;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /*
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Work around silly limitation of isc_mem_get().
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (n == 0)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley n = 1;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl = isc_mem_get(mctx, sizeof(*acl));
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (acl == NULL)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (ISC_R_NOMEMORY);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->mctx = mctx;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->name = NULL;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->refcount = 1;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->elements = NULL;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->alloc = 0;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->length = 0;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley ISC_LINK_INIT(acl, nextincache);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /*
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Must set magic early because we use dns_acl_detach() to clean up.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->magic = DNS_ACL_MAGIC;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->elements = isc_mem_get(mctx, n * sizeof(dns_aclelement_t));
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence if (acl->elements == NULL) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley result = ISC_R_NOMEMORY;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley goto cleanup;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley }
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->alloc = n;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley memset(acl->elements, 0, n * sizeof(dns_aclelement_t));
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley *target = acl;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (ISC_R_SUCCESS);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley cleanup:
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_acl_detach(&acl);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (result);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence}
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleyisc_result_t
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleydns_acl_appendelement(dns_acl_t *acl, dns_aclelement_t *elt) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (acl->length + 1 > acl->alloc) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /*
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Resize the ACL.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int newalloc;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley void *newmem;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley newalloc = acl->alloc * 2;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (newalloc < 4)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley newalloc = 4;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley newmem = isc_mem_get(acl->mctx,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley newalloc * sizeof(dns_aclelement_t));
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (newmem == NULL)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (ISC_R_NOMEMORY);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley memcpy(newmem, acl->elements,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->length * sizeof(dns_aclelement_t));
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_mem_put(acl->mctx, acl->elements,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->alloc * sizeof(dns_aclelement_t));
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->elements = newmem;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->alloc = newalloc;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley }
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /*
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Append the new element.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->elements[acl->length++] = *elt;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (ISC_R_SUCCESS);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley}
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halleystatic isc_result_t
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halleydns_acl_anyornone(isc_mem_t *mctx, isc_boolean_t neg, dns_acl_t **target) {
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley isc_result_t result;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley dns_acl_t *acl = NULL;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley result = dns_acl_create(mctx, 1, &acl);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (result != ISC_R_SUCCESS)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (result);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley acl->elements[0].negative = neg;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley acl->elements[0].type = dns_aclelementtype_any;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley acl->length = 1;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley *target = acl;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (result);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley}
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleyisc_result_t
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleydns_acl_any(isc_mem_t *mctx, dns_acl_t **target) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (dns_acl_anyornone(mctx, ISC_FALSE, target));
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley}
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleyisc_result_t
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleydns_acl_none(isc_mem_t *mctx, dns_acl_t **target) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (dns_acl_anyornone(mctx, ISC_TRUE, target));
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley}
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleyisc_result_t
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleydns_acl_match(isc_netaddr_t *reqaddr,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_name_t *reqsigner,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_acl_t *acl,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_aclenv_t *env,
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley int *match,
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley dns_aclelement_t **matchelt)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley{
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley int i;
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley REQUIRE(reqaddr != NULL);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley REQUIRE(matchelt == NULL || *matchelt == NULL);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley for (i = 0; i < (int)acl->length; i++) {
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley dns_aclelement_t *e = &acl->elements[i];
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if (dns_aclelement_match(reqaddr, reqsigner,
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley e, env, matchelt)) {
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley *match = e->negative ? -(i+1) : (i+1);
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley return (ISC_R_SUCCESS);
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley }
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley }
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley /* No match. */
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley *match = 0;
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley return (ISC_R_SUCCESS);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley}
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halleyisc_boolean_t
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halleydns_aclelement_match(isc_netaddr_t *reqaddr,
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley dns_name_t *reqsigner,
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley dns_aclelement_t *e,
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley dns_aclenv_t *env,
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence dns_aclelement_t **matchelt)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley{
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley dns_acl_t *inner = NULL;
b5fff54fe9335b20c02d749831fc0eaeda97198fBrian Wellington int indirectmatch;
b5fff54fe9335b20c02d749831fc0eaeda97198fBrian Wellington isc_result_t result;
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley switch (e->type) {
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley case dns_aclelementtype_ipprefix:
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if (isc_netaddr_eqprefix(reqaddr,
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley &e->u.ip_prefix.address,
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley e->u.ip_prefix.prefixlen))
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley goto matched;
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley break;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley case dns_aclelementtype_keyname:
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (reqsigner != NULL &&
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_name_equal(reqsigner, &e->u.keyname))
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley goto matched;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley break;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley case dns_aclelementtype_nestedacl:
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley inner = e->u.nestedacl;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley nested:
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley result = dns_acl_match(reqaddr, reqsigner,
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley inner,
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley env,
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley &indirectmatch, matchelt);
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley INSIST(result == ISC_R_SUCCESS);
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley /*
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * Treat negative matches in indirect ACLs as
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * "no match".
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * That way, a negated indirect ACL will never become
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * a surprise positive match through double negation.
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * XXXDCL this should be documented.
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley */
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley if (indirectmatch > 0)
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley goto matchelt_set;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley /*
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * A negative indirect match may have set *matchelt,
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * but we don't want it set when we return.
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley */
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley if (matchelt != NULL)
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley *matchelt = NULL;
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence break;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley case dns_aclelementtype_any:
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley matched:
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley if (matchelt != NULL)
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley *matchelt = e;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley matchelt_set:
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley return (ISC_TRUE);
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley case dns_aclelementtype_localhost:
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley if (env != NULL && env->localhost != NULL) {
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley inner = env->localhost;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley goto nested;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley } else {
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley break;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley }
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley case dns_aclelementtype_localnets:
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley if (env != NULL && env->localnets != NULL) {
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley inner = env->localnets;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley goto nested;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley } else {
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley break;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley }
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley default:
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley INSIST(0);
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley break;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley }
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (ISC_FALSE);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley}
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleyvoid
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleydns_acl_attach(dns_acl_t *source, dns_acl_t **target) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley REQUIRE(DNS_ACL_VALID(source));
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley INSIST(source->refcount > 0);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley source->refcount++;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley *target = source;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley}
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic void
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleydestroy(dns_acl_t *dacl) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int i;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley for (i = 0; i < dacl->length; i++) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_aclelement_t *de = &dacl->elements[i];
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley switch (de->type) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley case dns_aclelementtype_keyname:
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley dns_name_free(&de->u.keyname, dacl->mctx);
08af8bf5ade4131fe44926ad04fd489e64a620bbBob Halley break;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley case dns_aclelementtype_nestedacl:
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_acl_detach(&de->u.nestedacl);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley break;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley default:
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley break;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley }
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley }
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (dacl->elements != NULL)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_mem_put(dacl->mctx, dacl->elements,
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dacl->alloc * sizeof(dns_aclelement_t));
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (dacl->name != NULL)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_mem_free(dacl->mctx, dacl->name);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dacl->magic = 0;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_mem_put(dacl->mctx, dacl, sizeof(*dacl));
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley}
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleyvoid
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleydns_acl_detach(dns_acl_t **aclp) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dns_acl_t *acl = *aclp;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley REQUIRE(DNS_ACL_VALID(acl));
569d094440399b000e059d4cb3434391c2c4d330Michael Graff INSIST(acl->refcount > 0);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley acl->refcount--;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (acl->refcount == 0)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley destroy(acl);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley *aclp = NULL;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley}
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleyisc_boolean_t
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrencedns_aclelement_equal(dns_aclelement_t *ea, dns_aclelement_t *eb) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (ea->type != eb->type)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (ISC_FALSE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley switch (ea->type) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley case dns_aclelementtype_ipprefix:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (ea->u.ip_prefix.prefixlen !=
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley eb->u.ip_prefix.prefixlen)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_FALSE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (isc_netaddr_equal(&ea->u.ip_prefix.address,
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley &eb->u.ip_prefix.address));
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley case dns_aclelementtype_keyname:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (dns_name_equal(&ea->u.keyname, &eb->u.keyname));
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley case dns_aclelementtype_nestedacl:
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence return (dns_acl_equal(ea->u.nestedacl, eb->u.nestedacl));
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley case dns_aclelementtype_localhost:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley case dns_aclelementtype_localnets:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley case dns_aclelementtype_any:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_TRUE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley default:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley INSIST(0);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_FALSE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley }
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley}
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleyisc_boolean_t
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleydns_acl_equal(dns_acl_t *a, dns_acl_t *b) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley unsigned int i;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (a == b)
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence return (ISC_TRUE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (a->length != b->length)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_FALSE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley for (i = 0; i < a->length; i++) {
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence if (! dns_aclelement_equal(&a->elements[i],
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley &b->elements[i]))
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_FALSE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley }
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_TRUE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley}
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley#ifndef INADDR_LOOPBACK
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley#define INADDR_LOOPBACK (unsigned long)0x7F000001UL
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley#endif
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffstatic isc_boolean_t
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleyis_loopback(dns_aclipprefix_t *p) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley switch (p->address.family) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley case AF_INET:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (p->prefixlen == 32 &&
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley htonl(p->address.type.in.s_addr) == INADDR_LOOPBACK)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_TRUE);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence break;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley case AF_INET6:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (p->prefixlen == 128 &&
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley IN6_IS_ADDR_LOOPBACK(&p->address.type.in6))
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_TRUE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley break;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley default:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley break;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley }
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_FALSE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley}
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleyisc_boolean_t
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleydns_acl_isinsecure(dns_acl_t *a) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley unsigned int i;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley for (i = 0; i < a->length; i++) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dns_aclelement_t *e = &a->elements[i];
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley /* A negated match can never be insecure. */
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff if (e->negative)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley continue;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley switch (e->type) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley case dns_aclelementtype_ipprefix:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley /* The loopback address is considered secure. */
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (! is_loopback(&e->u.ip_prefix))
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence return (ISC_TRUE);
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence continue;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence case dns_aclelementtype_keyname:
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence case dns_aclelementtype_localhost:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley continue;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley case dns_aclelementtype_nestedacl:
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence if (dns_acl_isinsecure(e->u.nestedacl))
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_TRUE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley continue;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley case dns_aclelementtype_localnets:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley case dns_aclelementtype_any:
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_TRUE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence default:
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence INSIST(0);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_TRUE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley }
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley }
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley /* No insecure elements were found. */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (ISC_FALSE);
}
isc_result_t
dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) {
isc_result_t result;
env->localhost = NULL;
env->localnets = NULL;
result = dns_acl_create(mctx, 0, &env->localhost);
if (result != ISC_R_SUCCESS)
goto cleanup_nothing;
result = dns_acl_create(mctx, 0, &env->localnets);
if (result != ISC_R_SUCCESS)
goto cleanup_localhost;
return (ISC_R_SUCCESS);
cleanup_localhost:
dns_acl_detach(&env->localhost);
cleanup_nothing:
return (result);
}
void
dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s) {
dns_acl_detach(&t->localhost);
dns_acl_attach(s->localhost, &t->localhost);
dns_acl_detach(&t->localnets);
dns_acl_attach(s->localnets, &t->localnets);
}
void
dns_aclenv_destroy(dns_aclenv_t *env) {
dns_acl_detach(&env->localhost);
dns_acl_detach(&env->localnets);
}