Example #1
0
/*%
 * Allocates a key structure and fills in some of the fields.
 */
static dst_key_t *
get_key_struct(dns_name_t *name, unsigned int alg,
	       unsigned int flags, unsigned int protocol,
	       unsigned int bits, dns_rdataclass_t rdclass,
	       isc_mem_t *mctx)
{
	dst_key_t *key;
	isc_result_t result;
	int i;

	key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t));
	if (key == NULL)
		return (NULL);

	memset(key, 0, sizeof(dst_key_t));
	key->magic = KEY_MAGIC;

	result = isc_refcount_init(&key->refs, 1);
	if (result != ISC_R_SUCCESS) {
		isc_mem_put(mctx, key, sizeof(dst_key_t));
		return (NULL);
	}

	key->key_name = isc_mem_get(mctx, sizeof(dns_name_t));
	if (key->key_name == NULL) {
		isc_refcount_destroy(&key->refs);
		isc_mem_put(mctx, key, sizeof(dst_key_t));
		return (NULL);
	}
	dns_name_init(key->key_name, NULL);
	result = dns_name_dup(name, mctx, key->key_name);
	if (result != ISC_R_SUCCESS) {
		isc_refcount_destroy(&key->refs);
		isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
		isc_mem_put(mctx, key, sizeof(dst_key_t));
		return (NULL);
	}
	key->key_alg = alg;
	key->key_flags = flags;
	key->key_proto = protocol;
	key->mctx = mctx;
	key->keydata.generic = NULL;
	key->key_size = bits;
	key->key_class = rdclass;
	key->func = dst_t_func[alg];
	key->fmt_major = 0;
	key->fmt_minor = 0;
	for (i = 0; i < (DST_MAX_TIMES + 1); i++) {
		key->times[i] = 0;
		key->timeset[i] = ISC_FALSE;
	}
	return (key);
}
Example #2
0
static void
destroy(isc_hash_t **hctxp) {
	isc_hash_t *hctx;
	isc_mem_t *mctx;

	REQUIRE(hctxp != NULL && *hctxp != NULL);
	hctx = *hctxp;
	*hctxp = NULL;

	LOCK(&hctx->lock);

	isc_refcount_destroy(&hctx->refcnt);

	mctx = hctx->mctx;
	if (hctx->entropy != NULL)
		isc_entropy_detach(&hctx->entropy);
	if (hctx->rndvector != NULL)
		isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen);

	UNLOCK(&hctx->lock);

	DESTROYLOCK(&hctx->lock);

	memset(hctx, 0, sizeof(isc_hash_t));
	isc_mem_put(mctx, hctx, sizeof(isc_hash_t));
	isc_mem_detach(&mctx);
}
Example #3
0
static void
destroy(isc_hash_t **hctxp) {
	isc_hash_t *hctx;
	isc_mem_t *mctx;
	unsigned char canary0[4], canary1[4];

	REQUIRE(hctxp != NULL && *hctxp != NULL);
	hctx = *hctxp;
	*hctxp = NULL;

	LOCK(&hctx->lock);

	isc_refcount_destroy(&hctx->refcnt);

	mctx = hctx->mctx;
#ifdef BIND9
	if (hctx->entropy != NULL)
		isc_entropy_detach(&hctx->entropy);
#endif
	if (hctx->rndvector != NULL)
		isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen);

	UNLOCK(&hctx->lock);

	DESTROYLOCK(&hctx->lock);

	memcpy(canary0, hctx + 1, sizeof(canary0));
	memset(hctx, 0, sizeof(isc_hash_t));
	memcpy(canary1, hctx + 1, sizeof(canary1));
	INSIST(memcmp(canary0, canary1, sizeof(canary0)) == 0);
	isc_mem_put(mctx, hctx, sizeof(isc_hash_t));
	isc_mem_detach(&mctx);
}
Example #4
0
static void
destroy(dns_acl_t *dacl) {
	unsigned int i;

	INSIST(!ISC_LINK_LINKED(dacl, nextincache));

	for (i = 0; i < dacl->length; i++) {
		dns_aclelement_t *de = &dacl->elements[i];
		if (de->type == dns_aclelementtype_keyname) {
			dns_name_free(&de->keyname, dacl->mctx);
		} else if (de->type == dns_aclelementtype_nestedacl) {
			dns_acl_detach(&de->nestedacl);
		}
	}
	if (dacl->elements != NULL)
		isc_mem_put(dacl->mctx, dacl->elements,
			    dacl->alloc * sizeof(dns_aclelement_t));
	if (dacl->name != NULL)
		isc_mem_free(dacl->mctx, dacl->name);
	if (dacl->iptable != NULL)
		dns_iptable_detach(&dacl->iptable);
	isc_refcount_destroy(&dacl->refcount);
	dacl->magic = 0;
	isc_mem_put(dacl->mctx, dacl, sizeof(*dacl));
}
Example #5
0
void
dst_key_free(dst_key_t **keyp) {
	isc_mem_t *mctx;
	dst_key_t *key;
	unsigned int refs;

	REQUIRE(dst_initialized == ISC_TRUE);
	REQUIRE(keyp != NULL && VALID_KEY(*keyp));

	key = *keyp;
	mctx = key->mctx;

	isc_refcount_decrement(&key->refs, &refs);
	if (refs != 0)
		return;

	isc_refcount_destroy(&key->refs);
	if (key->keydata.generic != NULL) {
		INSIST(key->func->destroy != NULL);
		key->func->destroy(key);
	}
	if (key->engine != NULL)
		isc_mem_free(mctx, key->engine);
	if (key->label != NULL)
		isc_mem_free(mctx, key->label);
	dns_name_free(key->key_name, mctx);
	isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
	if (key->key_tkeytoken) {
		isc_buffer_free(&key->key_tkeytoken);
	}
	memset(key, 0, sizeof(dst_key_t));
	isc_mem_putanddetach(&mctx, key, sizeof(dst_key_t));
	*keyp = NULL;
}
Example #6
0
static void
destroy(dns_acl_t *dacl) {
	unsigned int i;
	for (i = 0; i < dacl->length; i++) {
		dns_aclelement_t *de = &dacl->elements[i];
		switch (de->type) {
		case dns_aclelementtype_keyname:
			dns_name_free(&de->u.keyname, dacl->mctx);
			break;
		case dns_aclelementtype_nestedacl:
			dns_acl_detach(&de->u.nestedacl);
			break;
		default:
			break;
		}
	}
	if (dacl->elements != NULL)
		isc_mem_put(dacl->mctx, dacl->elements,
			    dacl->alloc * sizeof(dns_aclelement_t));
	if (dacl->name != NULL)
		isc_mem_free(dacl->mctx, dacl->name);
	isc_refcount_destroy(&dacl->refcount);
	dacl->magic = 0;
	isc_mem_put(dacl->mctx, dacl, sizeof(*dacl));
}
void
dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) {
	unsigned int refs;
	dns_keynode_t *node = *keynode;
	REQUIRE(VALID_KEYNODE(node));
	isc_refcount_decrement(&node->refcount, &refs);
	if (refs == 0) {
		if (node->key != NULL)
			dst_key_free(&node->key);
		isc_refcount_destroy(&node->refcount);
		isc_mem_put(mctx, node, sizeof(dns_keynode_t));
	}
	*keynode = NULL;
}
Example #8
0
static void
tsigkey_free(dns_tsigkey_t *key) {
	REQUIRE(VALID_TSIG_KEY(key));

	key->magic = 0;
	dns_name_free(&key->name, key->mctx);
	if (algname_is_allocated(key->algorithm)) {
		dns_name_free(key->algorithm, key->mctx);
		isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t));
	}
	if (key->key != NULL)
		dst_key_free(&key->key);
	if (key->creator != NULL) {
		dns_name_free(key->creator, key->mctx);
		isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t));
	}
	isc_refcount_destroy(&key->refs);
	isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t));
}
Example #9
0
void
dns_portlist_detach(dns_portlist_t **portlistp) {
	dns_portlist_t *portlist;
	unsigned int count;

	REQUIRE(portlistp != NULL);
	portlist = *portlistp;
	REQUIRE(DNS_VALID_PORTLIST(portlist));
	*portlistp = NULL;
	isc_refcount_decrement(&portlist->refcount, &count);
	if (count == 0) {
		portlist->magic = 0;
		isc_refcount_destroy(&portlist->refcount);
		if (portlist->list != NULL)
			isc_mem_put(portlist->mctx, portlist->list,
				    portlist->allocated *
				    sizeof(*portlist->list));
		DESTROYLOCK(&portlist->lock);
		isc_mem_putanddetach(&portlist->mctx, portlist,
				     sizeof(*portlist));
	}
}
Example #10
0
void
dns_order_detach(dns_order_t **orderp) {
	dns_order_t *order;
	dns_order_ent_t *ent;
	unsigned int references;

	REQUIRE(orderp != NULL);
	order = *orderp;
	REQUIRE(DNS_ORDER_VALID(order));
	isc_refcount_decrement(&order->references, &references);
	*orderp = NULL;
	if (references != 0)
		return;

	order->magic = 0;
	while ((ent = ISC_LIST_HEAD(order->ents)) != NULL) {
		ISC_LIST_UNLINK(order->ents, ent, link);
		isc_mem_put(order->mctx, ent, sizeof(*ent));
	}
	isc_refcount_destroy(&order->references);
	isc_mem_putanddetach(&order->mctx, order, sizeof(*order));
}
Example #11
0
isc_result_t
dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
		const char *name, dns_view_t **viewp)
{
	dns_view_t *view;
	isc_result_t result;

	/*
	 * Create a view.
	 */

	REQUIRE(name != NULL);
	REQUIRE(viewp != NULL && *viewp == NULL);

	view = isc_mem_get(mctx, sizeof(*view));
	if (view == NULL)
		return (ISC_R_NOMEMORY);

	view->mctx = NULL;
	isc_mem_attach(mctx, &view->mctx);
	view->name = isc_mem_strdup(mctx, name);
	if (view->name == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup_view;
	}
	result = isc_mutex_init(&view->lock);
	if (result != ISC_R_SUCCESS)
		goto cleanup_name;

	view->zonetable = NULL;
	if (isc_bind9) {
		result = dns_zt_create(mctx, rdclass, &view->zonetable);
		if (result != ISC_R_SUCCESS) {
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "dns_zt_create() failed: %s",
					 isc_result_totext(result));
			result = ISC_R_UNEXPECTED;
			goto cleanup_mutex;
		}
	}
	view->secroots_priv = NULL;
	view->fwdtable = NULL;
	result = dns_fwdtable_create(mctx, &view->fwdtable);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "dns_fwdtable_create() failed: %s",
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
		goto cleanup_zt;
	}

	view->acache = NULL;
	view->cache = NULL;
	view->cachedb = NULL;
	ISC_LIST_INIT(view->dlz_searched);
	ISC_LIST_INIT(view->dlz_unsearched);
	view->hints = NULL;
	view->resolver = NULL;
	view->adb = NULL;
	view->requestmgr = NULL;
	view->rdclass = rdclass;
	view->frozen = ISC_FALSE;
	view->task = NULL;
	result = isc_refcount_init(&view->references, 1);
	if (result != ISC_R_SUCCESS)
		goto cleanup_fwdtable;
	view->weakrefs = 0;
	view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
			    DNS_VIEWATTR_REQSHUTDOWN);
	view->statickeys = NULL;
	view->dynamickeys = NULL;
	view->matchclients = NULL;
	view->matchdestinations = NULL;
	view->matchrecursiveonly = ISC_FALSE;
	result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
	if (result != ISC_R_SUCCESS)
		goto cleanup_references;
	view->peers = NULL;
	view->order = NULL;
	view->delonly = NULL;
	view->rootdelonly = ISC_FALSE;
	view->rootexclude = NULL;
	view->adbstats = NULL;
	view->resstats = NULL;
	view->resquerystats = NULL;
	view->cacheshared = ISC_FALSE;
	ISC_LIST_INIT(view->dns64);
	view->dns64cnt = 0;

	/*
	 * Initialize configuration data with default values.
	 */
	view->recursion = ISC_TRUE;
	view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */
	view->additionalfromcache = ISC_TRUE;
	view->additionalfromauth = ISC_TRUE;
	view->enablednssec = ISC_TRUE;
	view->enablevalidation = ISC_TRUE;
	view->acceptexpired = ISC_FALSE;
	view->minimalresponses = ISC_FALSE;
	view->transfer_format = dns_one_answer;
	view->cacheacl = NULL;
	view->cacheonacl = NULL;
	view->queryacl = NULL;
	view->queryonacl = NULL;
	view->recursionacl = NULL;
	view->recursiononacl = NULL;
	view->sortlist = NULL;
	view->transferacl = NULL;
	view->notifyacl = NULL;
	view->updateacl = NULL;
	view->upfwdacl = NULL;
	view->denyansweracl = NULL;
	view->nocasecompress = NULL;
	view->answeracl_exclude = NULL;
	view->denyanswernames = NULL;
	view->answernames_exclude = NULL;
	view->rrl = NULL;
	view->provideixfr = ISC_TRUE;
	view->maxcachettl = 7 * 24 * 3600;
	view->maxncachettl = 3 * 3600;
	view->dstport = 53;
	view->preferred_glue = 0;
	view->flush = ISC_FALSE;
	view->dlv = NULL;
	view->maxudp = 0;
	view->situdp = 0;
	view->maxbits = 0;
	view->v4_aaaa = dns_aaaa_ok;
	view->v6_aaaa = dns_aaaa_ok;
	view->aaaa_acl = NULL;
	view->rpzs = NULL;
	dns_fixedname_init(&view->dlv_fixed);
	view->managed_keys = NULL;
	view->redirect = NULL;
	view->requestnsid = ISC_FALSE;
	view->requestsit = ISC_TRUE;
	view->new_zone_file = NULL;
	view->new_zone_config = NULL;
	view->cfg_destroy = NULL;

	if (isc_bind9) {
		result = dns_order_create(view->mctx, &view->order);
		if (result != ISC_R_SUCCESS)
			goto cleanup_dynkeys;
	}

	result = dns_peerlist_new(view->mctx, &view->peers);
	if (result != ISC_R_SUCCESS)
		goto cleanup_order;

	result = dns_aclenv_init(view->mctx, &view->aclenv);
	if (result != ISC_R_SUCCESS)
		goto cleanup_peerlist;

	ISC_LINK_INIT(view, link);
	ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL,
		       DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown,
		       view, NULL, NULL, NULL);
	ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL,
		       DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown,
		       view, NULL, NULL, NULL);
	ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL,
		       DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown,
		       view, NULL, NULL, NULL);
	view->viewlist = NULL;
	view->magic = DNS_VIEW_MAGIC;

	*viewp = view;

	return (ISC_R_SUCCESS);

 cleanup_peerlist:
	if (view->peers != NULL)
		dns_peerlist_detach(&view->peers);

 cleanup_order:
	if (view->order != NULL)
		dns_order_detach(&view->order);

 cleanup_dynkeys:
	if (view->dynamickeys != NULL)
		dns_tsigkeyring_detach(&view->dynamickeys);

 cleanup_references:
	isc_refcount_destroy(&view->references);

 cleanup_fwdtable:
	if (view->fwdtable != NULL)
		dns_fwdtable_destroy(&view->fwdtable);

 cleanup_zt:
	if (view->zonetable != NULL)
		dns_zt_detach(&view->zonetable);

 cleanup_mutex:
	DESTROYLOCK(&view->lock);

 cleanup_name:
	isc_mem_free(mctx, view->name);

 cleanup_view:
	isc_mem_putanddetach(&view->mctx, view, sizeof(*view));

	return (result);
}
Example #12
0
isc_result_t
dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
			  dst_key_t *dstkey, isc_boolean_t generated,
			  dns_name_t *creator, isc_stdtime_t inception,
			  isc_stdtime_t expire, isc_mem_t *mctx,
			  dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
{
	dns_tsigkey_t *tkey;
	isc_result_t ret;
	unsigned int refs = 0;

	REQUIRE(key == NULL || *key == NULL);
	REQUIRE(name != NULL);
	REQUIRE(algorithm != NULL);
	REQUIRE(mctx != NULL);
	REQUIRE(key != NULL || ring != NULL);

	tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
	if (tkey == NULL)
		return (ISC_R_NOMEMORY);

	dns_name_init(&tkey->name, NULL);
	ret = dns_name_dup(name, mctx, &tkey->name);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_key;
	(void)dns_name_downcase(&tkey->name, &tkey->name, NULL);

	if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACMD5_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
		tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
		tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else {
		if (dstkey != NULL) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
		tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
		if (tkey->algorithm == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_name;
		}
		dns_name_init(tkey->algorithm, NULL);
		ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_algorithm;
		(void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
					NULL);
	}

	if (creator != NULL) {
		tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
		if (tkey->creator == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_algorithm;
		}
		dns_name_init(tkey->creator, NULL);
		ret = dns_name_dup(creator, mctx, tkey->creator);
		if (ret != ISC_R_SUCCESS) {
			isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
			goto cleanup_algorithm;
		}
	} else
		tkey->creator = NULL;

	tkey->key = NULL;
	if (dstkey != NULL)
		dst_key_attach(dstkey, &tkey->key);
	tkey->ring = ring;

	if (key != NULL)
		refs = 1;
	if (ring != NULL)
		refs++;
	ret = isc_refcount_init(&tkey->refs, refs);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_creator;

	tkey->generated = generated;
	tkey->inception = inception;
	tkey->expire = expire;
	tkey->mctx = NULL;
	isc_mem_attach(mctx, &tkey->mctx);
	ISC_LINK_INIT(tkey, link);

	tkey->magic = TSIG_MAGIC;

	if (ring != NULL) {
		ret = keyring_add(ring, name, tkey);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_refs;
	}

	/*
	 * Ignore this if it's a GSS key, since the key size is meaningless.
	 */
	if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
	    !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
	    !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
		char namestr[DNS_NAME_FORMATSIZE];
		dns_name_format(name, namestr, sizeof(namestr));
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
			      DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
			      "the key '%s' is too short to be secure",
			      namestr);
	}

	if (key != NULL)
		*key = tkey;

	return (ISC_R_SUCCESS);

 cleanup_refs:
	tkey->magic = 0;
	while (refs-- > 0)
		isc_refcount_decrement(&tkey->refs, NULL);
	isc_refcount_destroy(&tkey->refs);
 cleanup_creator:
	if (tkey->key != NULL)
		dst_key_free(&tkey->key);
	if (tkey->creator != NULL) {
		dns_name_free(tkey->creator, mctx);
		isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
	}
 cleanup_algorithm:
	if (algname_is_allocated(tkey->algorithm)) {
		if (dns_name_dynamic(tkey->algorithm))
			dns_name_free(tkey->algorithm, mctx);
		isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
	}
 cleanup_name:
	dns_name_free(&tkey->name, mctx);
 cleanup_key:
	isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));

	return (ret);
}
Example #13
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);
}
Example #14
0
isc_result_t
dns_acl_match2(const isc_netaddr_t *reqaddr,
	       const dns_name_t *reqsigner,
	       const isc_netaddr_t *ecs,
	       isc_uint8_t ecslen,
	       isc_uint8_t *scope,
	       const dns_acl_t *acl,
	       const dns_aclenv_t *env,
	       int *match,
	       const dns_aclelement_t **matchelt)
{
	isc_uint16_t bitlen;
	isc_prefix_t pfx;
	isc_radix_node_t *node = NULL;
	const isc_netaddr_t *addr = reqaddr;
	isc_netaddr_t v4addr;
	isc_result_t result;
	int match_num = -1;
	unsigned int i;

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

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

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

	/* 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) {
		int off = ISC_RADIX_OFF(&pfx);
		match_num = node->node_num[off];
		if (*(isc_boolean_t *) node->data[off])
			*match = match_num;
		else
			*match = -match_num;
	}

	isc_refcount_destroy(&pfx.refcount);

	/*
	 * If ecs is not NULL, we search the radix tree again to
	 * see if we find a better match on an ECS node
	 */
	if (ecs != NULL) {
		node = NULL;
		addr = ecs;

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

		NETADDR_TO_PREFIX_T(addr, pfx, ecslen, ISC_TRUE);

		result = isc_radix_search(acl->iptable->radix, &node, &pfx);
		if (result == ISC_R_SUCCESS && node != NULL) {
			int off = ISC_RADIX_OFF(&pfx);
			if (match_num == -1 ||
			    node->node_num[off] < match_num)
			{
				match_num = node->node_num[off];
				if (scope != NULL)
					*scope = node->bit;
				if (*(isc_boolean_t *) node->data[off])
					*match = match_num;
				else
					*match = -match_num;
			}
		}

		isc_refcount_destroy(&pfx.refcount);
	}

	/* 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) {
			break;
		}

		if (dns_aclelement_match2(reqaddr, reqsigner, ecs, ecslen,
					  scope, e, env, matchelt))
		{
			if (match_num == -1 || e->node_num < match_num) {
				if (e->negative)
					*match = -e->node_num;
				else
					*match = e->node_num;
			}
			break;
		}
	}

	return (ISC_R_SUCCESS);
}