aclconf.c revision 501941f0b6cce74c2ff75b10aff3f230d5d37e4c
/*
* Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id$ */
#include <config.h>
#include <isccfg/namedconf.h>
#include <dns/fixedname.h>
#ifdef HAVE_GEOIP
#include <stdlib.h>
#include <math.h>
#endif /* HAVE_GEOIP */
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS)
goto cleanup;
return (ISC_R_SUCCESS);
return (result);
}
void
}
void
unsigned int refs;
if (refs == 0) {
{
}
}
}
/*
* Find the definition of the named acl whose name is "name".
*/
static isc_result_t
const cfg_listelt_t *elt;
if (result != ISC_R_SUCCESS)
return (result);
}
return (ISC_R_SUCCESS);
}
}
return (ISC_R_NOTFOUND);
}
static isc_result_t
{
/* Look for an already-converted version. */
{
"acl loop detected: %s", aclname);
return (ISC_R_FAILURE);
}
return (ISC_R_SUCCESS);
}
}
/* Not yet converted. Convert now. */
if (result != ISC_R_SUCCESS) {
"undefined ACL '%s'", aclname);
return (result);
}
/*
* Add a loop detection element.
*/
nest_level, &dacl);
if (result != ISC_R_SUCCESS)
return (result);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
}
static isc_result_t
{
unsigned int keylen;
dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS) {
"key name '%s' is not a valid domain name",
txtname);
return (result);
}
}
/*
* Recursively pre-parse an ACL definition to find the total number
* of non-IP-prefix elements (localhost, localnets, key) in all nested
* ACLs, so that the parent will have enough space allocated for the
* elements table after all the nested ACLs have been merged in to the
* parent.
*/
static int
{
const cfg_listelt_t *elt;
int n = 0;
if (has_negative != NULL)
/* might be a negated element, in which case get the value. */
if (cfg_obj_istuple(ce)) {
if (! cfg_obj_isvoid(negated)) {
if (has_negative != NULL)
*has_negative = ISC_TRUE;
}
}
n++;
} else if (cfg_obj_islist(ce)) {
if (negative)
n++;
#ifdef HAVE_GEOIP
} else if (cfg_obj_istuple(ce) &&
{
n++;
#endif /* HAVE_GEOIP */
} else if (cfg_obj_isstring(ce)) {
n++;
if (result == ISC_R_SUCCESS)
NULL) + 1;
}
}
}
return n;
}
#ifdef HAVE_GEOIP
static dns_geoip_subtype_t
{
return (subtype);
switch (subtype) {
case dns_geoip_countrycode:
return (dns_geoip_city_countrycode);
return (dns_geoip_region_countrycode);
return (dns_geoip_country_code);
"invalid GeoIP DB specified for "
"country search: ignored");
return (subtype);
case dns_geoip_countrycode3:
return (dns_geoip_city_countrycode3);
return (dns_geoip_country_code3);
"invalid GeoIP DB specified for "
"country search: ignored");
return (subtype);
case dns_geoip_countryname:
return (dns_geoip_city_countryname);
return (dns_geoip_country_name);
"invalid GeoIP DB specified for "
"country search: ignored");
return (subtype);
case dns_geoip_region:
return (dns_geoip_city_region);
return (dns_geoip_region_code);
"invalid GeoIP DB specified for "
"region search: ignored");
return (subtype);
case dns_geoip_regionname:
return (dns_geoip_city_region);
return (dns_geoip_region_name);
"invalid GeoIP DB specified for "
"region search: ignored");
return (subtype);
/*
* Log a warning if the wrong database was specified
* on an unambiguous query
*/
case dns_geoip_city_name:
case dns_geoip_city_metrocode:
case dns_geoip_city_areacode:
"invalid GeoIP DB specified for "
"a 'city'-only search type: ignoring");
return (subtype);
case dns_geoip_isp_name:
"invalid GeoIP DB specified for "
"an 'isp' search: ignoring");
return (subtype);
case dns_geoip_org_name:
"invalid GeoIP DB specified for "
"an 'org' search: ignoring");
return (subtype);
case dns_geoip_as_asnum:
"invalid GeoIP DB specified for "
"an 'asnum' search: ignoring");
return (subtype);
case dns_geoip_domain_name:
"invalid GeoIP DB specified for "
"a 'domain' search: ignoring");
return (subtype);
case dns_geoip_netspeed_id:
"invalid GeoIP DB specified for "
"a 'netspeed' search: ignoring");
return (subtype);
default:
INSIST(0);
}
}
static isc_boolean_t
return (ISC_TRUE);
case dns_geoip_countrycode:
case dns_geoip_countrycode3:
case dns_geoip_countryname:
return (ISC_TRUE);
case dns_geoip_region:
case dns_geoip_regionname:
return (ISC_TRUE);
case dns_geoip_country_code:
case dns_geoip_country_code3:
case dns_geoip_country_name:
return (ISC_TRUE);
case dns_geoip_region_code:
case dns_geoip_region_name:
return (ISC_TRUE);
case dns_geoip_city_region:
case dns_geoip_city_name:
case dns_geoip_city_metrocode:
case dns_geoip_city_areacode:
return (ISC_TRUE);
case dns_geoip_isp_name:
return (ISC_TRUE);
case dns_geoip_org_name:
return (ISC_TRUE);
case dns_geoip_as_asnum:
return (ISC_TRUE);
case dns_geoip_domain_name:
return (ISC_TRUE);
case dns_geoip_netspeed_id:
return (ISC_TRUE);
}
return (ISC_FALSE);
}
static isc_result_t
{
if (!cfg_obj_isvoid(ge))
/* Two-letter country code */
/* Three-letter country code */
/* Country name */
/* Two-letter region code */
/* Region name */
/* City name */
/* Two-letter continent code */
} else
INSIST(0);
"no GeoIP database installed which can answer "
"queries of type '%s'", stype);
return (ISC_R_FAILURE);
}
return (ISC_R_SUCCESS);
}
#endif
unsigned int nest_level,
{
const cfg_listelt_t *elt;
int new_nest_level = 0;
if (nest_level != 0)
/*
* If target already points to an ACL, then we're being
* called recursively to configure a nested ACL. The
* nested ACL's contents should just be absorbed into its
* parent ACL.
*/
} else {
/*
* Need to allocate a new ACL structure. Count the items
* in the ACL definition that will require space in the
* elements table. (Note that if nest_level is nonzero,
* *everything* goes in the elements table.)
*/
int nelem;
if (nest_level == 0)
else
if (result != ISC_R_SUCCESS)
return (result);
}
if (cfg_obj_istuple(ce)) {
/* Might be a negated element */
if (! cfg_obj_isvoid(negated)) {
}
}
/*
* If nest_level is nonzero, then every element is
* to be stored as a separate, nested ACL rather than
* merged into the main iptable.
*/
if (nest_level != 0) {
if (result != ISC_R_SUCCESS)
goto cleanup;
}
if (cfg_obj_isnetprefix(ce)) {
/* Network prefix */
unsigned int bitlen;
/*
* If nesting ACLs (nest_level != 0), we negate
* the nestedacl element, not the iptable entry.
*/
if (result != ISC_R_SUCCESS)
goto cleanup;
if (nest_level > 0) {
} else
continue;
} else if (cfg_obj_islist(ce)) {
/*
* If we're nesting ACLs, put the nested
* ACL onto the elements list; otherwise
* merge it into *this* ACL. We nest ACLs
* in two cases: 1) sortlist, 2) if the
* nested ACL contains negated members.
*/
&inneracl);
if (result != ISC_R_SUCCESS)
goto cleanup;
/* Fall through. */
} else {
continue;
}
/* Key name. */
if (result != ISC_R_SUCCESS)
goto cleanup;
#ifdef HAVE_GEOIP
} else if (cfg_obj_istuple(ce) &&
{
if (result != ISC_R_SUCCESS)
goto cleanup;
#endif /* HAVE_GEOIP */
} else if (cfg_obj_isstring(ce)) {
/* ACL name. */
/* Iptable entry with zero bit length. */
if (result != ISC_R_SUCCESS)
goto cleanup;
if (nest_level != 0) {
} else
continue;
/* none == !any */
/*
* We don't unconditional set
* dacl->has_negatives and
* de->negative to true so we can handle
* "!none;".
*/
if (result != ISC_R_SUCCESS)
goto cleanup;
if (!neg)
if (nest_level != 0) {
} else
continue;
} else {
&inneracl);
if (result != ISC_R_SUCCESS)
goto cleanup;
goto nested_acl;
}
} else {
"address match list contains "
"unsupported element type");
goto cleanup;
}
/*
* This should only be reached for localhost, localnets
* and keyname elements, and nested ACLs if nest_level is
* nonzero (i.e., in sortlists).
*/
dacl->node_count++;
de++;
}
return (result);
}