Exemplo n.º 1
0
isc_result_t
dns_acl_match(isc_netaddr_t *reqaddr,
	      dns_name_t *reqsigner,
	      dns_acl_t *acl,
	      dns_aclenv_t *env,
	      int *match,
	      dns_aclelement_t **matchelt)
{
	unsigned int i;

	REQUIRE(reqaddr != NULL);
	REQUIRE(matchelt == NULL || *matchelt == NULL);
	
	for (i = 0; i < acl->length; i++) {
		dns_aclelement_t *e = &acl->elements[i];

		if (dns_aclelement_match(reqaddr, reqsigner,
					 e, env, matchelt)) {
			*match = e->negative ? -((int)i+1) : ((int)i+1);
			return (ISC_R_SUCCESS);
		}
	}
	/* No match. */
	*match = 0;
	return (ISC_R_SUCCESS);
}
Exemplo n.º 2
0
int
ns_sortlist_addrorder1(const isc_netaddr_t *addr, const void *arg) {
	const dns_aclelement_t *matchelt = (const dns_aclelement_t *) arg;
	if (dns_aclelement_match(addr, NULL, matchelt,
				 &ns_g_server->aclenv,
				 NULL)) {
		return (0);
	} else {
		return (INT_MAX);
	}
}
Exemplo n.º 3
0
ns_sortlisttype_t
ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr,
		  const void **argp)
{
	unsigned int i;

	if (acl == NULL)
		goto dont_sort;

	for (i = 0; i < acl->length; i++) {
		/*
		 * 'e' refers to the current 'top level statement'
		 * in the sortlist (see ARM).
		 */
		dns_aclelement_t *e = &acl->elements[i];
		dns_aclelement_t *try_elt;
		dns_aclelement_t *order_elt = NULL;
		const dns_aclelement_t *matched_elt = NULL;

		if (e->type == dns_aclelementtype_nestedacl) {
			dns_acl_t *inner = e->nestedacl;

			if (inner->length == 0)
				try_elt = e;
			else if (inner->length > 2)
				goto dont_sort;
			else if (inner->elements[0].negative)
				goto dont_sort;
			else {
				try_elt = &inner->elements[0];
				if (inner->length == 2)
					order_elt = &inner->elements[1];
			}
		} else {
			/*
			 * BIND 8 allows bare elements at the top level
			 * as an undocumented feature.
			 */
			try_elt = e;
		}

		if (dns_aclelement_match(clientaddr, NULL, try_elt,
					 &ns_g_server->aclenv,
					 &matched_elt)) {
			if (order_elt != NULL) {
				if (order_elt->type ==
				    dns_aclelementtype_nestedacl) {
					*argp = order_elt->nestedacl;
					return (NS_SORTLISTTYPE_2ELEMENT);
				} else if (order_elt->type ==
					   dns_aclelementtype_localhost &&
					   ns_g_server->aclenv.localhost != NULL) {
					*argp = ns_g_server->aclenv.localhost;
					return (NS_SORTLISTTYPE_2ELEMENT);
				} else if (order_elt->type ==
					   dns_aclelementtype_localnets &&
					   ns_g_server->aclenv.localnets != NULL) {
					*argp = ns_g_server->aclenv.localnets;
					return (NS_SORTLISTTYPE_2ELEMENT);
				} else {
					/*
					 * BIND 8 allows a bare IP prefix as
					 * the 2nd element of a 2-element
					 * sortlist statement.
					 */
					*argp = order_elt;
					return (NS_SORTLISTTYPE_1ELEMENT);
				}
			} else {
				INSIST(matched_elt != NULL);
				*argp = matched_elt;
				return (NS_SORTLISTTYPE_1ELEMENT);
			}
		}
	}

	/* No match; don't sort. */
 dont_sort:
	*argp = NULL;
	return (NS_SORTLISTTYPE_NONE);
}
Exemplo n.º 4
0
/*
 * 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.
 */
isc_result_t
dns_acl_match(const isc_netaddr_t *reqaddr,
	      const dns_name_t *reqsigner,
	      const dns_acl_t *acl,
	      const dns_aclenv_t *env,
	      int *match,
	      const dns_aclelement_t **matchelt)
{
	isc_uint16_t bitlen, family;
	isc_prefix_t pfx;
	isc_radix_node_t *node = NULL;
	const isc_netaddr_t *addr;
	isc_netaddr_t v4addr;
	isc_result_t result;
	int match_num = -1;
	unsigned int i;

	REQUIRE(reqaddr != NULL);
	REQUIRE(matchelt == NULL || *matchelt == NULL);

	if (env == NULL || env->match_mapped == ISC_FALSE ||
	    reqaddr->family != AF_INET6 ||
	    !IN6_IS_ADDR_V4MAPPED(&reqaddr->type.in6))
		addr = reqaddr;
	else {
		isc_netaddr_fromv4mapped(&v4addr, reqaddr);
		addr = &v4addr;
	}

	/* Always match with host addresses. */
	family = addr->family;
	bitlen = family == AF_INET6 ? 128 : 32;
	NETADDR_TO_PREFIX_T(addr, pfx, bitlen);

	/* Assume no match. */
	*match = 0;

	/* Search radix. */
	result = isc_radix_search(acl->iptable->radix, &node, &pfx);

	/* Found a match. */
	if (result == ISC_R_SUCCESS && node != NULL) {
		match_num = node->node_num[ISC_IS6(family)];
		if (*(isc_boolean_t *) node->data[ISC_IS6(family)] == ISC_TRUE)
			*match = match_num;
		else
			*match = -match_num;
	}

	/* Now search non-radix elements for a match with a lower node_num. */
	for (i = 0; i < acl->length; i++) {
		dns_aclelement_t *e = &acl->elements[i];

		/* Already found a better match? */
		if (match_num != -1 && match_num < e->node_num) {
			isc_refcount_destroy(&pfx.refcount);
			return (ISC_R_SUCCESS);
		}

		if (dns_aclelement_match(reqaddr, reqsigner,
					 e, env, matchelt)) {
			if (match_num == -1 || e->node_num < match_num) {
				if (e->negative == ISC_TRUE)
					*match = -e->node_num;
				else
					*match = e->node_num;
			}
			isc_refcount_destroy(&pfx.refcount);
			return (ISC_R_SUCCESS);
		}
	}

	isc_refcount_destroy(&pfx.refcount);
	return (ISC_R_SUCCESS);
}