acl.c revision b0bf1ad5b0b1d29b4cdf5de9789405aec5e0844c
8804fd9936acd703073c4a75072852c38738a990Brian Wellington/*
1b5a34533410ff4eaff0e5b5b110221a97e29cfcAutomatic Updater * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 1999-2002 Internet Software Consortium.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * Permission to use, copy, modify, and/or distribute this software for any
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * purpose with or without fee is hereby granted, provided that the above
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * copyright notice and this permission notice appear in all copies.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *
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.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater/* $Id: acl.c,v 1.49 2008/09/26 21:12:02 each Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*! \file */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington#include <config.h>
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington#include <isc/mem.h>
8804fd9936acd703073c4a75072852c38738a990Brian Wellington#include <isc/once.h>
8804fd9936acd703073c4a75072852c38738a990Brian Wellington#include <isc/string.h>
8804fd9936acd703073c4a75072852c38738a990Brian Wellington#include <isc/util.h>
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington#include <dns/acl.h>
8804fd9936acd703073c4a75072852c38738a990Brian Wellington#include <dns/iptable.h>
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington/*
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * Create a new ACL, including an IP table and an array with room
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * for 'n' ACL elements. The elements are uninitialized and the
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * length is 0.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonisc_result_t
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtondns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_result_t result;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dns_acl_t *acl;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /*
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * Work around silly limitation of isc_mem_get().
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (n == 0)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington n = 1;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl = isc_mem_get(mctx, sizeof(*acl));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (acl == NULL)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_R_NOMEMORY);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->mctx = mctx;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->name = NULL;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington result = isc_refcount_init(&acl->refcount, 1);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (result != ISC_R_SUCCESS) {
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington isc_mem_put(mctx, acl, sizeof(*acl));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (result);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington result = dns_iptable_create(mctx, &acl->iptable);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (result != ISC_R_SUCCESS) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_mem_put(mctx, acl, sizeof(*acl));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (result);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->elements = NULL;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->alloc = 0;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->length = 0;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->has_negatives = ISC_FALSE;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington ISC_LINK_INIT(acl, nextincache);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /*
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * Must set magic early because we use dns_acl_detach() to clean up.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->magic = DNS_ACL_MAGIC;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->elements = isc_mem_get(mctx, n * sizeof(dns_aclelement_t));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (acl->elements == NULL) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington result = ISC_R_NOMEMORY;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington goto cleanup;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->alloc = n;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington memset(acl->elements, 0, n * sizeof(dns_aclelement_t));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *target = acl;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_R_SUCCESS);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington cleanup:
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dns_acl_detach(&acl);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (result);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington}
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington/*
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * Create a new ACL and initialize it with the value "any" or "none",
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * depending on the value of the "neg" parameter.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * "any" is a positive iptable entry with bit length 0.
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington * "none" is the same as "!any".
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington */
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonstatic isc_result_t
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtondns_acl_anyornone(isc_mem_t *mctx, isc_boolean_t neg, dns_acl_t **target) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_result_t result;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dns_acl_t *acl = NULL;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington result = dns_acl_create(mctx, 0, &acl);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (result != ISC_R_SUCCESS)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (result);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington result = dns_iptable_addprefix(acl->iptable, NULL, 0, ISC_TF(!neg));
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington if (result != ISC_R_SUCCESS) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dns_acl_detach(&acl);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (result);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *target = acl;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (result);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington}
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington/*
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * Create a new ACL that matches everything.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonisc_result_t
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtondns_acl_any(isc_mem_t *mctx, dns_acl_t **target) {
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington return (dns_acl_anyornone(mctx, ISC_FALSE, target));
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington}
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington/*
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington * Create a new ACL that matches nothing.
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington */
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellingtonisc_result_t
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellingtondns_acl_none(isc_mem_t *mctx, dns_acl_t **target) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (dns_acl_anyornone(mctx, ISC_TRUE, target));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington}
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington/*
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington * If pos is ISC_TRUE, test whether acl is set to "{ any; }"
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington * If pos is ISC_FALSE, test whether acl is set to "{ none; }"
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington */
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellingtonstatic isc_boolean_t
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellingtondns_acl_isanyornone(dns_acl_t *acl, isc_boolean_t pos)
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington{
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington /* Should never happen but let's be safe */
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington if (acl == NULL ||
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington acl->iptable == NULL ||
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->iptable->radix == NULL ||
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->iptable->radix->head == NULL ||
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington acl->iptable->radix->head->prefix == NULL)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_FALSE);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (acl->length != 0 || acl->node_count != 1)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_FALSE);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (acl->iptable->radix->head->prefix->bitlen == 0 &&
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->iptable->radix->head->data[0] != NULL &&
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->iptable->radix->head->data[0] ==
8804fd9936acd703073c4a75072852c38738a990Brian Wellington acl->iptable->radix->head->data[1] &&
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *(isc_boolean_t *) (acl->iptable->radix->head->data[0]) == pos)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_TRUE);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_FALSE); /* All others */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington}
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington/*
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * Test whether acl is set to "{ any; }"
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington */
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellingtonisc_boolean_t
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellingtondns_acl_isany(dns_acl_t *acl)
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington{
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington return (dns_acl_isanyornone(acl, ISC_TRUE));
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington}
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington/*
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington * Test whether acl is set to "{ none; }"
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington */
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellingtonisc_boolean_t
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellingtondns_acl_isnone(dns_acl_t *acl)
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington{
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington return (dns_acl_isanyornone(acl, ISC_FALSE));
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington}
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington/*
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington * Determine whether a given address or signer matches a given ACL.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * For a match with a positive ACL element or iptable radix entry,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * return with a positive value in match; for a match with a negated ACL
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * element or radix entry, return with a negative value in match.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
a56f5ada432128085e4a06815328023ee0c9610dMark Andrewsisc_result_t
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtondns_acl_match(const isc_netaddr_t *reqaddr,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington const dns_name_t *reqsigner,
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews const dns_acl_t *acl,
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉 const dns_aclenv_t *env,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington int *match,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington const dns_aclelement_t **matchelt)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington{
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_uint16_t bitlen, family;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_prefix_t pfx;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_radix_node_t *node;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington const isc_netaddr_t *addr;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_netaddr_t v4addr;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_result_t result;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington int match_num = -1;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington unsigned int i;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington REQUIRE(reqaddr != NULL);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington REQUIRE(matchelt == NULL || *matchelt == NULL);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews if (env == NULL || env->match_mapped == ISC_FALSE ||
8804fd9936acd703073c4a75072852c38738a990Brian Wellington reqaddr->family != AF_INET6 ||
8804fd9936acd703073c4a75072852c38738a990Brian Wellington !IN6_IS_ADDR_V4MAPPED(&reqaddr->type.in6))
8804fd9936acd703073c4a75072852c38738a990Brian Wellington addr = reqaddr;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington else {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_netaddr_fromv4mapped(&v4addr, reqaddr);
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington addr = &v4addr;
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington }
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews /* Always match with host addresses. */
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews family = addr->family;
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews bitlen = family == AF_INET6 ? 128 : 32;
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews /* Assume no match. */
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews *match = 0;
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington /* Search radix. */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington result = isc_radix_search(acl->iptable->radix, &node, &pfx);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /* Found a match. */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (result == ISC_R_SUCCESS && node != NULL) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington match_num = node->node_num[ISC_IS6(family)];
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington if (*(isc_boolean_t *) node->data[ISC_IS6(family)] == ISC_TRUE)
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington *match = match_num;
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington else
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington *match = -match_num;
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington }
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington /* Now search non-radix elements for a match with a lower node_num. */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington for (i = 0; i < acl->length; i++) {
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews dns_aclelement_t *e = &acl->elements[i];
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /* Already found a better match? */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (match_num != -1 && match_num < e->node_num) {
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews isc_refcount_destroy(&pfx.refcount);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_R_SUCCESS);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (dns_aclelement_match(reqaddr, reqsigner,
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington e, env, matchelt)) {
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews if (match_num == -1 || e->node_num < match_num) {
2674e1a455d4f71de09b2b60e7a8304b9a305588Mark Andrews if (e->negative == ISC_TRUE)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *match = -e->node_num;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington else
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *match = e->node_num;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_refcount_destroy(&pfx.refcount);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_R_SUCCESS);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_refcount_destroy(&pfx.refcount);
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington return (ISC_R_SUCCESS);
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington}
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington/*
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington * Merge the contents of one ACL into another. Call dns_iptable_merge()
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington * for the IP tables, then concatenate the element arrays.
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington *
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington * If pos is set to false, then the nested ACL is to be negated. This
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * means reverse the sense of each *positive* element or IP table node,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * but leave negatives alone, so as to prevent a double-negative causing
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * an unexpected postive match in the parent ACL.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonisc_result_t
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtondns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington{
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_result_t result;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington unsigned int newalloc, nelem, i;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington int max_node = 0, nodes;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews /* Resize the element array if needed. */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (dest->length + source->length > dest->alloc) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington void *newmem;
b7cd261f2fca2c7138cdc6ae8ee434e9c0031303Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington newalloc = dest->alloc + source->alloc;
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews if (newalloc < 4)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington newalloc = 4;
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews newmem = isc_mem_get(dest->mctx,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington newalloc * sizeof(dns_aclelement_t));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (newmem == NULL)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_R_NOMEMORY);
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /* Copy in the original elements */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington memcpy(newmem, dest->elements,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dest->length * sizeof(dns_aclelement_t));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /* Release the memory for the old elements array */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_mem_put(dest->mctx, dest->elements,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dest->alloc * sizeof(dns_aclelement_t));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dest->elements = newmem;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dest->alloc = newalloc;
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /*
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * Now copy in the new elements, increasing their node_num
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * values so as to keep the new ACL consistent. If we're
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * negating, then negate positive elements, but keep negative
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * elements the same for security reasons.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉 nelem = dest->length;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dest->length += source->length;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington for (i = 0; i < source->length; i++) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (source->elements[i].node_num > max_node)
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews max_node = source->elements[i].node_num;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews /* Copy type. */
a56f5ada432128085e4a06815328023ee0c9610dMark Andrews dest->elements[nelem + i].type = source->elements[i].type;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /* Adjust node numbering. */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dest->elements[nelem + i].node_num =
8804fd9936acd703073c4a75072852c38738a990Brian Wellington source->elements[i].node_num + dest->node_count;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /* Duplicate nested acl. */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (source->elements[i].type == dns_aclelementtype_nestedacl &&
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington source->elements[i].nestedacl != NULL)
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington dns_acl_attach(source->elements[i].nestedacl,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington &dest->elements[nelem + i].nestedacl);
86c3cd20dd2aff4b1c52ce13d8587abd8d2bd16cBrian Wellington
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington /* Duplicate key name. */
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington if (source->elements[i].type == dns_aclelementtype_keyname) {
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington dns_name_init(&dest->elements[nelem+i].keyname, NULL);
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington result = dns_name_dup(&source->elements[i].keyname,
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington dest->mctx,
42b48d11ca7b296324d7a8a98cdbf0070b0deb1dMark Andrews &dest->elements[nelem+i].keyname);
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington if (result != ISC_R_SUCCESS)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return result;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /* reverse sense of positives if this is a negative acl */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (!pos && source->elements[i].negative == ISC_FALSE) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dest->elements[nelem + i].negative = ISC_TRUE;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington } else {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dest->elements[nelem + i].negative =
8804fd9936acd703073c4a75072852c38738a990Brian Wellington source->elements[i].negative;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /*
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * Merge the iptables. Make sure the destination ACL's
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * node_count value is set correctly afterward.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington nodes = max_node + dest->node_count;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington result = dns_iptable_merge(dest->iptable, source->iptable, pos);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (result != ISC_R_SUCCESS)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (result);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (nodes > dest->node_count)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dest->node_count = nodes;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_R_SUCCESS);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington}
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington/*
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * Like dns_acl_match, but matches against the single ACL element 'e'
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * rather than a complete ACL, and returns ISC_TRUE iff it matched.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * To determine whether the match was prositive or negative, the
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * caller should examine e->negative. Since the element 'e' may be
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * a reference to a named ACL or a nested ACL, a matching element
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * returned through 'matchelt' is not necessarily 'e' itself.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonisc_boolean_t
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtondns_aclelement_match(const isc_netaddr_t *reqaddr,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington const dns_name_t *reqsigner,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington const dns_aclelement_t *e,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington const dns_aclenv_t *env,
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington const dns_aclelement_t **matchelt)
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington{
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington dns_acl_t *inner = NULL;
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington int indirectmatch;
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington isc_result_t result;
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington switch (e->type) {
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington case dns_aclelementtype_keyname:
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (reqsigner != NULL &&
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dns_name_equal(reqsigner, &e->keyname)) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (matchelt != NULL)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *matchelt = e;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_TRUE);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington } else {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_FALSE);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington case dns_aclelementtype_nestedacl:
8804fd9936acd703073c4a75072852c38738a990Brian Wellington inner = e->nestedacl;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington break;
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson
8804fd9936acd703073c4a75072852c38738a990Brian Wellington case dns_aclelementtype_localhost:
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (env == NULL || env->localhost == NULL)
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (ISC_FALSE);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt inner = env->localhost;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington break;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington case dns_aclelementtype_localnets:
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson if (env == NULL || env->localnets == NULL)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington return (ISC_FALSE);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington inner = env->localnets;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington break;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington default:
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /* Should be impossible. */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington INSIST(0);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington result = dns_acl_match(reqaddr, reqsigner, inner, env,
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington &indirectmatch, matchelt);
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington INSIST(result == ISC_R_SUCCESS);
13090db2b1c210b8386793ff0cbbb0b4348c1ecaBrian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /*
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * Treat negative matches in indirect ACLs as "no match".
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * That way, a negated indirect ACL will never become a
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * surprise positive match through double negation.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * XXXDCL this should be documented.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (indirectmatch > 0) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (matchelt != NULL)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *matchelt = e;
b7cd261f2fca2c7138cdc6ae8ee434e9c0031303Brian Wellington return (ISC_TRUE);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington /*
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * A negative indirect match may have set *matchelt, but we don't
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * want it set when we return.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (matchelt != NULL)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *matchelt = NULL;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington return (ISC_FALSE);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington}
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonvoid
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtondns_acl_attach(dns_acl_t *source, dns_acl_t **target) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington REQUIRE(DNS_ACL_VALID(source));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_refcount_increment(&source->refcount, NULL);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *target = source;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington}
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonstatic void
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtondestroy(dns_acl_t *dacl) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington unsigned int i;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington for (i = 0; i < dacl->length; i++) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dns_aclelement_t *de = &dacl->elements[i];
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (de->type == dns_aclelementtype_keyname) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dns_name_free(&de->keyname, dacl->mctx);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington } else if (de->type == dns_aclelementtype_nestedacl) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dns_acl_detach(&de->nestedacl);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington }
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt }
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (dacl->elements != NULL)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_mem_put(dacl->mctx, dacl->elements,
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dacl->alloc * sizeof(dns_aclelement_t));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (dacl->name != NULL)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_mem_free(dacl->mctx, dacl->name);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (dacl->iptable != NULL)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dns_iptable_detach(&dacl->iptable);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_refcount_destroy(&dacl->refcount);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dacl->magic = 0;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_mem_put(dacl->mctx, dacl, sizeof(*dacl));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington}
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonvoid
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtondns_acl_detach(dns_acl_t **aclp) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington dns_acl_t *acl = *aclp;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington unsigned int refs;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington REQUIRE(DNS_ACL_VALID(acl));
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_refcount_decrement(&acl->refcount, &refs);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington if (refs == 0)
8804fd9936acd703073c4a75072852c38738a990Brian Wellington destroy(acl);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington *aclp = NULL;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington}
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonstatic isc_once_t insecure_prefix_once = ISC_ONCE_INIT;
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonstatic isc_mutex_t insecure_prefix_lock;
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonstatic isc_boolean_t insecure_prefix_found;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonstatic void
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtoninitialize_action(void) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington RUNTIME_CHECK(isc_mutex_init(&insecure_prefix_lock) == ISC_R_SUCCESS);
8804fd9936acd703073c4a75072852c38738a990Brian Wellington}
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington/*
e3e3bafa138a20558a2253470effc01702fc6dfdBrian Wellington * Called via isc_radix_walk() to find IP table nodes that are
8804fd9936acd703073c4a75072852c38738a990Brian Wellington * insecure.
8804fd9936acd703073c4a75072852c38738a990Brian Wellington */
8804fd9936acd703073c4a75072852c38738a990Brian Wellingtonstatic void
df925e6c66d45d960fbac0383169763967d2111cEvan Huntis_insecure(isc_prefix_t *prefix, void **data) {
8804fd9936acd703073c4a75072852c38738a990Brian Wellington isc_boolean_t secure;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington int bitlen, family;
8804fd9936acd703073c4a75072852c38738a990Brian Wellington
bitlen = prefix->bitlen;
family = prefix->family;
/* Negated entries are always secure. */
secure = * (isc_boolean_t *)data[ISC_IS6(family)];
if (!secure) {
return;
}
/* If loopback prefix found, return */
switch (family) {
case AF_INET:
if (bitlen == 32 &&
htonl(prefix->add.sin.s_addr) == INADDR_LOOPBACK)
return;
break;
case AF_INET6:
if (bitlen == 128 && IN6_IS_ADDR_LOOPBACK(&prefix->add.sin6))
return;
break;
default:
break;
}
/* Non-negated, non-loopback */
insecure_prefix_found = ISC_TRUE; /* LOCKED */
return;
}
/*
* Return ISC_TRUE iff the acl 'a' is considered insecure, that is,
* if it contains IP addresses other than those of the local host.
* This is intended for applications such as printing warning
* messages for suspect ACLs; it is not intended for making access
* control decisions. We make no guarantee that an ACL for which
* this function returns ISC_FALSE is safe.
*/
isc_boolean_t
dns_acl_isinsecure(const dns_acl_t *a) {
unsigned int i;
isc_boolean_t insecure;
RUNTIME_CHECK(isc_once_do(&insecure_prefix_once,
initialize_action) == ISC_R_SUCCESS);
/*
* Walk radix tree to find out if there are any non-negated,
* non-loopback prefixes.
*/
LOCK(&insecure_prefix_lock);
insecure_prefix_found = ISC_FALSE;
isc_radix_process(a->iptable->radix, is_insecure);
insecure = insecure_prefix_found;
UNLOCK(&insecure_prefix_lock);
if (insecure)
return(ISC_TRUE);
/* Now check non-radix elements */
for (i = 0; i < a->length; i++) {
dns_aclelement_t *e = &a->elements[i];
/* A negated match can never be insecure. */
if (e->negative)
continue;
switch (e->type) {
case dns_aclelementtype_keyname:
case dns_aclelementtype_localhost:
continue;
case dns_aclelementtype_nestedacl:
if (dns_acl_isinsecure(e->nestedacl))
return (ISC_TRUE);
continue;
case dns_aclelementtype_localnets:
return (ISC_TRUE);
default:
INSIST(0);
return (ISC_TRUE);
}
}
/* No insecure elements were found. */
return (ISC_FALSE);
}
/*
* Initialize ACL environment, setting up localhost and localnets ACLs
*/
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;
env->match_mapped = ISC_FALSE;
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);
t->match_mapped = s->match_mapped;
}
void
dns_aclenv_destroy(dns_aclenv_t *env) {
dns_acl_detach(&env->localhost);
dns_acl_detach(&env->localnets);
}