acl.c revision e80f661db8ec9596eb977d6fc537484aa3662e22
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson/*
2f99b54e8ec8e908ea894bc808d1c18a5f51a850Automatic Updater * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 1999-2002 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * Permission to use, copy, modify, and/or distribute this software for any
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * purpose with or without fee is hereby granted, provided that the above
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PERFORMANCE OF THIS SOFTWARE.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
e80f661db8ec9596eb977d6fc537484aa3662e22Evan Hunt/* $Id: acl.c,v 1.47 2008/09/12 04:54:39 each Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*! \file */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#include <config.h>
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#include <isc/mem.h>
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews#include <isc/once.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/string.h>
364a82f7c25b62967678027043425201a5e5171aBob Halley#include <isc/util.h>
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#include <dns/acl.h>
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt#include <dns/iptable.h>
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Create a new ACL, including an IP table and an array with room
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * for 'n' ACL elements. The elements are uninitialized and the
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * length is 0.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafssonisc_result_t
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc_result_t result;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson dns_acl_t *acl;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Work around silly limitation of isc_mem_get().
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson if (n == 0)
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson n = 1;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson acl = isc_mem_get(mctx, sizeof(*acl));
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson if (acl == NULL)
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson return (ISC_R_NOMEMORY);
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson acl->mctx = mctx;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson acl->name = NULL;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews result = isc_refcount_init(&acl->refcount, 1);
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews if (result != ISC_R_SUCCESS) {
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews isc_mem_put(mctx, acl, sizeof(*acl));
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews return (result);
18d0b5e54be891a1aa938c165b6d439859121ec8Mark Andrews }
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews result = dns_iptable_create(mctx, &acl->iptable);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt if (result != ISC_R_SUCCESS) {
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_mem_put(mctx, acl, sizeof(*acl));
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt return (result);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson acl->elements = NULL;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson acl->alloc = 0;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson acl->length = 0;
114c14f8adfc249cf2e5cdcb9007af46fed257e3Mark Andrews acl->has_negatives = ISC_FALSE;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson ISC_LINK_INIT(acl, nextincache);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Must set magic early because we use dns_acl_detach() to clean up.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence acl->magic = DNS_ACL_MAGIC;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson acl->elements = isc_mem_get(mctx, n * sizeof(dns_aclelement_t));
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson if (acl->elements == NULL) {
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson result = ISC_R_NOMEMORY;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson goto cleanup;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson }
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson acl->alloc = n;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson memset(acl->elements, 0, n * sizeof(dns_aclelement_t));
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson *target = acl;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson return (ISC_R_SUCCESS);
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson cleanup:
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson dns_acl_detach(&acl);
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson return (result);
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson}
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Create a new ACL and initialize it with the value "any" or "none",
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * depending on the value of the "neg" parameter.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * "any" is a positive iptable entry with bit length 0.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * "none" is the same as "!any".
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafssonstatic isc_result_t
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_acl_anyornone(isc_mem_t *mctx, isc_boolean_t neg, dns_acl_t **target) {
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc_result_t result;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson dns_acl_t *acl = NULL;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt result = dns_acl_create(mctx, 0, &acl);
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson if (result != ISC_R_SUCCESS)
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson return (result);
1aba9fe67899522364a9dbc3ee5a14da081f0314Evan Hunt
1aba9fe67899522364a9dbc3ee5a14da081f0314Evan Hunt result = dns_iptable_addprefix(acl->iptable, NULL, 0, ISC_TF(!neg));
1aba9fe67899522364a9dbc3ee5a14da081f0314Evan Hunt if (result != ISC_R_SUCCESS) {
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater dns_acl_detach(&acl);
1aba9fe67899522364a9dbc3ee5a14da081f0314Evan Hunt return (result);
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater }
1aba9fe67899522364a9dbc3ee5a14da081f0314Evan Hunt
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson *target = acl;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson return (result);
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson}
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Create a new ACL that matches everything.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafssonisc_result_t
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafssondns_acl_any(isc_mem_t *mctx, dns_acl_t **target) {
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson return (dns_acl_anyornone(mctx, ISC_FALSE, target));
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson}
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Create a new ACL that matches nothing.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafssonisc_result_t
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafssondns_acl_none(isc_mem_t *mctx, dns_acl_t **target) {
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson return (dns_acl_anyornone(mctx, ISC_TRUE, target));
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson}
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * If pos is ISC_TRUE, test whether acl is set to "{ any; }"
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * If pos is ISC_FALSE, test whether acl is set to "{ none; }"
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Huntstatic isc_boolean_t
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Huntdns_acl_isanyornone(dns_acl_t *acl, isc_boolean_t pos)
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt{
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Should never happen but let's be safe */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (acl == NULL ||
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews acl->iptable == NULL ||
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews acl->iptable->radix == NULL ||
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews acl->iptable->radix->head == NULL ||
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews acl->iptable->radix->head->prefix == NULL)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_FALSE);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
e80f661db8ec9596eb977d6fc537484aa3662e22Evan Hunt if (acl->length != 0 || acl->node_count != 1)
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt return (ISC_FALSE);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt if (acl->iptable->radix->head->prefix->bitlen == 0 &&
e80f661db8ec9596eb977d6fc537484aa3662e22Evan Hunt acl->iptable->radix->head->data[0] != NULL &&
28ad0be64ee756013c0f6a474fc447ee613ee0d1Evan Hunt *(isc_boolean_t *) (acl->iptable->radix->head->data[0]) == pos)
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt return (ISC_TRUE);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt return (ISC_FALSE); /* All others */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt}
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Test whether acl is set to "{ any; }"
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Huntisc_boolean_t
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Huntdns_acl_isany(dns_acl_t *acl)
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt{
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (dns_acl_isanyornone(acl, ISC_TRUE));
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt}
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Test whether acl is set to "{ none; }"
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Huntisc_boolean_t
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Huntdns_acl_isnone(dns_acl_t *acl)
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt{
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (dns_acl_isanyornone(acl, ISC_FALSE));
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt}
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Determine whether a given address or signer matches a given ACL.
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater * For a match with a positive ACL element or iptable radix entry,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * return with a positive value in match; for a match with a negated ACL
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * element or radix entry, return with a negative value in match.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssonisc_result_t
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrewsdns_acl_match(const isc_netaddr_t *reqaddr,
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const dns_name_t *reqsigner,
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const dns_acl_t *acl,
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const dns_aclenv_t *env,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson int *match,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt const dns_aclelement_t **matchelt)
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson{
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt isc_uint16_t bitlen, family;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_prefix_t pfx;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_radix_node_t *node;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews const isc_netaddr_t *addr;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc_netaddr_t v4addr;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_result_t result;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews int match_num = -1;
8bb77cd31b7518fb5d2a6a9d75e16e4abd59df61Andreas Gustafsson unsigned int i;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
d8d0c5b1bc97ac0f07e35a31b58ced80ce613c55David Lawrence REQUIRE(reqaddr != NULL);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson REQUIRE(matchelt == NULL || *matchelt == NULL);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt if (env == NULL || env->match_mapped == ISC_FALSE ||
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt reqaddr->family != AF_INET6 ||
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt !IN6_IS_ADDR_V4MAPPED(&reqaddr->type.in6))
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews addr = reqaddr;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt else {
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt isc_netaddr_fromv4mapped(&v4addr, reqaddr);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt addr = &v4addr;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt }
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt /* Always match with host addresses. */
fc7043d7d1294478c9988c10af9a7fb8fd810338Evan Hunt family = addr->family;
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt bitlen = family == AF_INET6 ? 128 : 32;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt /* Assume no match. */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt *match = 0;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt /* Search radix. */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt result = isc_radix_search(acl->iptable->radix, &node, &pfx);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt /* Found a match. */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt if (result == ISC_R_SUCCESS && node != NULL) {
1fa2ce7eaef0c17d554495220565b681639b2ce5Mark Andrews if (node->bit == 0)
1fa2ce7eaef0c17d554495220565b681639b2ce5Mark Andrews family = AF_INET;
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt match_num = node->node_num[ISC_IS6(family)];
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt if (*(isc_boolean_t *) node->data[ISC_IS6(family)] == ISC_TRUE)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews *match = match_num;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews else
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews *match = -match_num;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Now search non-radix elements for a match with a lower node_num. */
8bb77cd31b7518fb5d2a6a9d75e16e4abd59df61Andreas Gustafsson for (i = 0; i < acl->length; i++) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson dns_aclelement_t *e = &acl->elements[i];
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
114c14f8adfc249cf2e5cdcb9007af46fed257e3Mark Andrews /* Already found a better match? */
aeadcd63196f164b219629a53c0e0925519288f3Evan Hunt if (match_num != -1 && match_num < e->node_num) {
aeadcd63196f164b219629a53c0e0925519288f3Evan Hunt isc_refcount_destroy(&pfx.refcount);
114c14f8adfc249cf2e5cdcb9007af46fed257e3Mark Andrews return (ISC_R_SUCCESS);
aeadcd63196f164b219629a53c0e0925519288f3Evan Hunt }
114c14f8adfc249cf2e5cdcb9007af46fed257e3Mark Andrews
ba7ea2326d98edb4296098749fc9cf44b5157643David Lawrence if (dns_aclelement_match(reqaddr, reqsigner,
ba7ea2326d98edb4296098749fc9cf44b5157643David Lawrence e, env, matchelt)) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (match_num == -1 || e->node_num < match_num) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (e->negative == ISC_TRUE)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews *match = -e->node_num;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews else
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews *match = e->node_num;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
aeadcd63196f164b219629a53c0e0925519288f3Evan Hunt isc_refcount_destroy(&pfx.refcount);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson return (ISC_R_SUCCESS);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
aeadcd63196f164b219629a53c0e0925519288f3Evan Hunt isc_refcount_destroy(&pfx.refcount);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson return (ISC_R_SUCCESS);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson}
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Merge the contents of one ACL into another. Call dns_iptable_merge()
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * for the IP tables, then concatenate the element arrays.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt *
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * If pos is set to false, then the nested ACL is to be negated. This
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * means reverse the sense of each *positive* element or IP table node,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * but leave negatives alone, so as to prevent a double-negative causing
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * an unexpected postive match in the parent ACL.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrewsisc_result_t
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Huntdns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews{
12e0477d4e132c9122312246ed60aaa646f819b2Mark Andrews isc_result_t result;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews unsigned int newalloc, nelem, i;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews int max_node = 0, nodes;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Resize the element array if needed. */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (dest->length + source->length > dest->alloc) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews void *newmem;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews newalloc = dest->alloc + source->alloc;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (newalloc < 4)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews newalloc = 4;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews newmem = isc_mem_get(dest->mctx,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews newalloc * sizeof(dns_aclelement_t));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (newmem == NULL)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_R_NOMEMORY);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Copy in the original elements */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews memcpy(newmem, dest->elements,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dest->length * sizeof(dns_aclelement_t));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Release the memory for the old elements array */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc_mem_put(dest->mctx, dest->elements,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dest->alloc * sizeof(dns_aclelement_t));
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dest->elements = newmem;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dest->alloc = newalloc;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /*
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * Now copy in the new elements, increasing their node_num
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * values so as to keep the new ACL consistent. If we're
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * negating, then negate positive elements, but keep negative
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * elements the same for security reasons.
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews nelem = dest->length;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dest->length += source->length;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews for (i = 0; i < source->length; i++) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (source->elements[i].node_num > max_node)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews max_node = source->elements[i].node_num;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Copy type. */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dest->elements[nelem + i].type = source->elements[i].type;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Adjust node numbering. */
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater dest->elements[nelem + i].node_num =
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews source->elements[i].node_num + dest->node_count;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Duplicate nested acl. */
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt if (source->elements[i].type == dns_aclelementtype_nestedacl &&
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews source->elements[i].nestedacl != NULL)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dns_acl_attach(source->elements[i].nestedacl,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews &dest->elements[nelem + i].nestedacl);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Duplicate key name. */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (source->elements[i].type == dns_aclelementtype_keyname) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dns_name_init(&dest->elements[nelem+i].keyname, NULL);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews result = dns_name_dup(&source->elements[i].keyname,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dest->mctx,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews &dest->elements[nelem+i].keyname);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (result != ISC_R_SUCCESS)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return result;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* reverse sense of positives if this is a negative acl */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (!pos && source->elements[i].negative == ISC_FALSE) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dest->elements[nelem + i].negative = ISC_TRUE;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews } else {
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater dest->elements[nelem + i].negative =
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews source->elements[i].negative;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /*
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * Merge the iptables. Make sure the destination ACL's
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * node_count value is set correctly afterward.
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews nodes = max_node + dest->node_count;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews result = dns_iptable_merge(dest->iptable, source->iptable, pos);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (result != ISC_R_SUCCESS)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (result);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (nodes > dest->node_count)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dest->node_count = nodes;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_R_SUCCESS);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews}
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Like dns_acl_match, but matches against the single ACL element 'e'
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * rather than a complete ACL, and returns ISC_TRUE iff it matched.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt *
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater * To determine whether the match was prositive or negative, the
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * caller should examine e->negative. Since the element 'e' may be
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * a reference to a named ACL or a nested ACL, a matching element
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * returned through 'matchelt' is not necessarily 'e' itself.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafssonisc_boolean_t
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrewsdns_aclelement_match(const isc_netaddr_t *reqaddr,
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const dns_name_t *reqsigner,
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const dns_aclelement_t *e,
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const dns_aclenv_t *env,
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const dns_aclelement_t **matchelt)
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson{
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson dns_acl_t *inner = NULL;
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson int indirectmatch;
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson isc_result_t result;
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews switch (e->type) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews case dns_aclelementtype_keyname:
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson if (reqsigner != NULL &&
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt dns_name_equal(reqsigner, &e->keyname)) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (matchelt != NULL)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews *matchelt = e;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_TRUE);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews } else {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_FALSE);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews case dns_aclelementtype_nestedacl:
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews inner = e->nestedacl;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews break;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews case dns_aclelementtype_localhost:
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (env == NULL || env->localhost == NULL)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_FALSE);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews inner = env->localhost;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews break;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews case dns_aclelementtype_localnets:
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (env == NULL || env->localnets == NULL)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_FALSE);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews inner = env->localnets;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews break;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews default:
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Should be impossible. */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews INSIST(0);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews result = dns_acl_match(reqaddr, reqsigner, inner, env,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews &indirectmatch, matchelt);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews INSIST(result == ISC_R_SUCCESS);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /*
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * Treat negative matches in indirect ACLs as "no match".
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * That way, a negated indirect ACL will never become a
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * surprise positive match through double negation.
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * XXXDCL this should be documented.
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (indirectmatch > 0) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (matchelt != NULL)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews *matchelt = e;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_TRUE);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /*
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * A negative indirect match may have set *matchelt, but we don't
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * want it set when we return.
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews */
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (matchelt != NULL)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews *matchelt = NULL;
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson return (ISC_FALSE);
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater}
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssonvoid
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_acl_attach(dns_acl_t *source, dns_acl_t **target) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson REQUIRE(DNS_ACL_VALID(source));
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson isc_refcount_increment(&source->refcount, NULL);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson *target = source;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson}
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssonstatic void
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedestroy(dns_acl_t *dacl) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson unsigned int i;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson for (i = 0; i < dacl->length; i++) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson dns_aclelement_t *de = &dacl->elements[i];
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt if (de->type == dns_aclelementtype_keyname) {
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt dns_name_free(&de->keyname, dacl->mctx);
12e0477d4e132c9122312246ed60aaa646f819b2Mark Andrews } else if (de->type == dns_aclelementtype_nestedacl) {
12e0477d4e132c9122312246ed60aaa646f819b2Mark Andrews dns_acl_detach(&de->nestedacl);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson if (dacl->elements != NULL)
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson isc_mem_put(dacl->mctx, dacl->elements,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson dacl->alloc * sizeof(dns_aclelement_t));
ea419adc4eca4c3e44f2c282035b5dce6b795fe2Andreas Gustafsson if (dacl->name != NULL)
ea419adc4eca4c3e44f2c282035b5dce6b795fe2Andreas Gustafsson isc_mem_free(dacl->mctx, dacl->name);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (dacl->iptable != NULL)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews dns_iptable_detach(&dacl->iptable);
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson isc_refcount_destroy(&dacl->refcount);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson dacl->magic = 0;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson isc_mem_put(dacl->mctx, dacl, sizeof(*dacl));
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson}
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssonvoid
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_acl_detach(dns_acl_t **aclp) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson dns_acl_t *acl = *aclp;
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson unsigned int refs;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson REQUIRE(DNS_ACL_VALID(acl));
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson isc_refcount_decrement(&acl->refcount, &refs);
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson if (refs == 0)
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson destroy(acl);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson *aclp = NULL;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson}
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrewsstatic isc_once_t insecure_prefix_once = ISC_ONCE_INIT;
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrewsstatic isc_mutex_t insecure_prefix_lock;
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrewsstatic isc_boolean_t insecure_prefix_found;
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrewsstatic void
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrewsinitialize_action(void) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews RUNTIME_CHECK(isc_mutex_init(&insecure_prefix_lock) == ISC_R_SUCCESS);
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews}
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Called via isc_radix_walk() to find IP table nodes that are
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * insecure.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Huntstatic void
262c39b2366bf79062f7f86b218947523dd1cbacEvan Huntis_insecure(isc_prefix_t *prefix, void **data) {
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt isc_boolean_t secure;
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt int bitlen, family;
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt /* Bitlen 0 means "any" or "none", which is always treated as IPv4 */
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt bitlen = prefix->bitlen;
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt family = bitlen ? prefix->family : AF_INET;
140a27777d6fba397720770b101967d5cf73f42bAutomatic Updater
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Negated entries are always secure. */
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt secure = * (isc_boolean_t *)data[ISC_IS6(family)];
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (!secure) {
140a27777d6fba397720770b101967d5cf73f42bAutomatic Updater return;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews }
140a27777d6fba397720770b101967d5cf73f42bAutomatic Updater
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* If loopback prefix found, return */
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt switch (family) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews case AF_INET:
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt if (bitlen == 32 &&
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt htonl(prefix->add.sin.s_addr) == INADDR_LOOPBACK)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson break;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews case AF_INET6:
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt if (bitlen == 128 && IN6_IS_ADDR_LOOPBACK(&prefix->add.sin6))
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson break;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews default:
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson break;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson }
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Non-negated, non-loopback */
262c39b2366bf79062f7f86b218947523dd1cbacEvan Hunt insecure_prefix_found = ISC_TRUE; /* LOCKED */
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson}
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Return ISC_TRUE iff the acl 'a' is considered insecure, that is,
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * if it contains IP addresses other than those of the local host.
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater * This is intended for applications such as printing warning
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * messages for suspect ACLs; it is not intended for making access
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * control decisions. We make no guarantee that an ACL for which
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * this function returns ISC_FALSE is safe.
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafssonisc_boolean_t
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrewsdns_acl_isinsecure(const dns_acl_t *a) {
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson unsigned int i;
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews isc_boolean_t insecure;
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews RUNTIME_CHECK(isc_once_do(&insecure_prefix_once,
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews initialize_action) == ISC_R_SUCCESS);
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /*
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * Walk radix tree to find out if there are any non-negated,
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews * non-loopback prefixes.
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews */
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews LOCK(&insecure_prefix_lock);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews insecure_prefix_found = ISC_FALSE;
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews isc_radix_process(a->iptable->radix, is_insecure);
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews insecure = insecure_prefix_found;
69f3cb5abcb38f105c653c7b3df7cec33b87b292Mark Andrews UNLOCK(&insecure_prefix_lock);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (insecure)
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return(ISC_TRUE);
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews /* Now check non-radix elements */
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson for (i = 0; i < a->length; i++) {
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson dns_aclelement_t *e = &a->elements[i];
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson /* A negated match can never be insecure. */
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson if (e->negative)
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson continue;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson switch (e->type) {
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews case dns_aclelementtype_keyname:
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews case dns_aclelementtype_localhost:
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson continue;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews case dns_aclelementtype_nestedacl:
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews if (dns_acl_isinsecure(e->nestedacl))
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews return (ISC_TRUE);
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews continue;
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews case dns_aclelementtype_localnets:
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson return (ISC_TRUE);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
604419a812b491cd35fb6fad129c3c39da7200a1Mark Andrews default:
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson INSIST(0);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson return (ISC_TRUE);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson }
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson }
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson /* No insecure elements were found. */
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson return (ISC_FALSE);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson}
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt/*
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt * Initialize ACL environment, setting up localhost and localnets ACLs
c7e266b7e5675e12d1ca3cc929f24b3e86d41f8eEvan Hunt */
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafssonisc_result_t
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) {
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson isc_result_t result;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson env->localhost = NULL;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson env->localnets = NULL;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson result = dns_acl_create(mctx, 0, &env->localhost);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson if (result != ISC_R_SUCCESS)
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson goto cleanup_nothing;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson result = dns_acl_create(mctx, 0, &env->localnets);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson if (result != ISC_R_SUCCESS)
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson goto cleanup_localhost;
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington env->match_mapped = ISC_FALSE;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson return (ISC_R_SUCCESS);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson cleanup_localhost:
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson dns_acl_detach(&env->localhost);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson cleanup_nothing:
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson return (result);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson}
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencevoid
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s) {
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson dns_acl_detach(&t->localhost);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson dns_acl_attach(s->localhost, &t->localhost);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson dns_acl_detach(&t->localnets);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson dns_acl_attach(s->localnets, &t->localnets);
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington t->match_mapped = s->match_mapped;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson}
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencevoid
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_aclenv_destroy(dns_aclenv_t *env) {
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson dns_acl_detach(&env->localhost);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson dns_acl_detach(&env->localnets);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson}