acl.c revision 6db55b4ff9b099bc8d6621f6e13ec1f087d35e04
/*
* Copyright (C) 1999-2002, 2004-2009, 2011, 2013, 2014, 2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*! \file */
#include <config.h>
/*
* Create a new ACL, including an IP table and an array with room
* for 'n' ACL elements. The elements are uninitialized and the
* length is 0.
*/
/*
* Work around silly limitation of isc_mem_get().
*/
if (n == 0)
n = 1;
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS) {
return (result);
}
if (result != ISC_R_SUCCESS) {
return (result);
}
/*
* Must set magic early because we use dns_acl_detach() to clean up.
*/
goto cleanup;
}
return (ISC_R_SUCCESS);
return (result);
}
/*
* Create a new ACL and initialize it with the value "any" or "none",
* depending on the value of the "neg" parameter.
* "any" is a positive iptable entry with bit length 0.
* "none" is the same as "!any".
*/
static isc_result_t
if (result != ISC_R_SUCCESS)
return (result);
if (result != ISC_R_SUCCESS) {
return (result);
}
return (result);
}
/*
* Create a new ACL that matches everything.
*/
}
/*
* Create a new ACL that matches nothing.
*/
}
/*
* If pos is ISC_TRUE, test whether acl is set to "{ any; }"
* If pos is ISC_FALSE, test whether acl is set to "{ none; }"
*/
static isc_boolean_t
{
/* Should never happen but let's be safe */
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_TRUE);
return (ISC_FALSE); /* All others */
}
/*
* Test whether acl is set to "{ any; }"
*/
{
}
/*
* Test whether acl is set to "{ none; }"
*/
{
}
/*
* Determine whether a given address or signer matches a given ACL.
* For a match with a positive ACL element or iptable radix entry,
* return with a positive value in match; for a match with a negated ACL
* element or radix entry, return with a negative value in match.
*/
const dns_name_t *reqsigner,
const dns_aclenv_t *env,
int *match,
const dns_aclelement_t **matchelt)
{
}
const dns_name_t *reqsigner,
const isc_netaddr_t *ecs,
const dns_aclenv_t *env,
int *match,
const dns_aclelement_t **matchelt)
{
int match_num = -1;
unsigned int i;
{
}
/* Always match with host addresses. */
/* Assume no match. */
*match = 0;
/* Search radix. */
/* Found a match. */
else
}
/*
* If ecs is not NULL, we search the radix tree again to
* see if we find a better match on an ECS node
*/
{
}
if (match_num == -1 ||
{
else
}
}
}
/* Now search non-radix elements for a match with a lower node_num. */
/* Already found a better match? */
break;
}
{
if (e->negative)
else
}
break;
}
}
return (ISC_R_SUCCESS);
}
/*
* Merge the contents of one ACL into another. Call dns_iptable_merge()
* for the IP tables, then concatenate the element arrays.
*
* If pos is set to false, then the nested ACL is to be negated. This
* means reverse the sense of each *positive* element or IP table node,
* but leave negatives alone, so as to prevent a double-negative causing
* an unexpected positive match in the parent ACL.
*/
{
/* Resize the element array if needed. */
void *newmem;
if (newalloc < 4)
newalloc = 4;
newalloc * sizeof(dns_aclelement_t));
return (ISC_R_NOMEMORY);
/* Zero. */
/* Copy in the original elements */
/* Release the memory for the old elements array */
}
/*
* Now copy in the new elements, increasing their node_num
* values so as to keep the new ACL consistent. If we're
* negating, then negate positive elements, but keep negative
* elements the same for security reasons.
*/
/* Copy type. */
/* Adjust node numbering. */
/* Duplicate nested acl. */
/* Duplicate key name. */
if (result != ISC_R_SUCCESS)
return result;
}
#ifdef HAVE_GEOIP
/* Duplicate GeoIP data */
}
#endif
/* reverse sense of positives if this is a negative acl */
} else {
}
}
/*
* Merge the iptables. Make sure the destination ACL's
* node_count value is set correctly afterward.
*/
if (result != ISC_R_SUCCESS)
return (result);
return (ISC_R_SUCCESS);
}
/*
* Like dns_acl_match, but matches against the single ACL element 'e'
* rather than a complete ACL, and returns ISC_TRUE iff it matched.
*
* To determine whether the match was positive or negative, the
* caller should examine e->negative. Since the element 'e' may be
* a reference to a named ACL or a nested ACL, a matching element
* returned through 'matchelt' is not necessarily 'e' itself.
*/
const dns_name_t *reqsigner,
const dns_aclelement_t *e,
const dns_aclenv_t *env,
const dns_aclelement_t **matchelt)
{
}
const dns_name_t *reqsigner,
const isc_netaddr_t *ecs,
const dns_aclelement_t *e,
const dns_aclenv_t *env,
const dns_aclelement_t **matchelt)
{
int indirectmatch;
#ifdef HAVE_GEOIP
#endif
switch (e->type) {
*matchelt = e;
return (ISC_TRUE);
} else
return (ISC_FALSE);
break;
return (ISC_FALSE);
break;
return (ISC_FALSE);
break;
#ifdef HAVE_GEOIP
case dns_aclelementtype_geoip:
return (ISC_FALSE);
&e->geoip_elem));
#endif
default:
/* Should be impossible. */
INSIST(0);
}
/*
* Treat negative matches in indirect ACLs as "no match".
* That way, a negated indirect ACL will never become a
* surprise positive match through double negation.
* XXXDCL this should be documented.
*/
if (indirectmatch > 0) {
*matchelt = e;
return (ISC_TRUE);
}
/*
* A negative indirect match may have set *matchelt, but we don't
* want it set when we return.
*/
return (ISC_FALSE);
}
void
}
static void
unsigned int i;
}
}
}
void
unsigned int refs;
if (refs == 0)
}
static isc_mutex_t insecure_prefix_lock;
static isc_boolean_t insecure_prefix_found;
static void
initialize_action(void) {
}
/*
* Called via isc_radix_process() to find IP table nodes that are
* insecure.
*/
static void
/*
* If all nonexistent or negative then this node is secure.
*/
return;
/*
* If a loopback address found and there is the other family
* doesn't exist or is negative, return.
*/
if (bitlen == 32 &&
return;
if (bitlen == 128 &&
return;
/* Non-negated, non-loopback */
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.
*/
dns_acl_isinsecure(const dns_acl_t *a) {
unsigned int i;
/*
* Walk radix tree to find out if there are any non-negated,
* non-loopback prefixes.
*/
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) {
continue;
if (dns_acl_isinsecure(e->nestedacl))
return (ISC_TRUE);
continue;
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
*/
if (result != ISC_R_SUCCESS)
goto cleanup_nothing;
if (result != ISC_R_SUCCESS)
goto cleanup_localhost;
#ifdef HAVE_GEOIP
#endif
return (ISC_R_SUCCESS);
return (result);
}
void
dns_acl_detach(&t->localhost);
dns_acl_detach(&t->localnets);
t->match_mapped = s->match_mapped;
#ifdef HAVE_GEOIP
t->geoip_use_ecs = s->geoip_use_ecs;
#endif
}
void
}