Beispiel #1
0
void
dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
		 const dns_name_t *prefix, isc_uint16_t offset)
{
	dns_name_t tname;
	unsigned int start;
	unsigned int n;
	unsigned int count;
	unsigned int hash;
	dns_compressnode_t *node;
	unsigned int length;
	unsigned int tlength;
	isc_uint16_t toffset;

	REQUIRE(VALID_CCTX(cctx));
	REQUIRE(dns_name_isabsolute(name));

	dns_name_init(&tname, NULL);

	n = dns_name_countlabels(name);
	count = dns_name_countlabels(prefix);
	if (dns_name_isabsolute(prefix))
		count--;
	start = 0;
	length = name_length(name);
	while (count > 0) {
		if (offset >= 0x4000)
			break;
		dns_name_getlabelsequence(name, start, n, &tname);
		hash = dns_name_hash(&tname, ISC_FALSE) %
		       DNS_COMPRESS_TABLESIZE;
		tlength = name_length(&tname);
		toffset = (isc_uint16_t)(offset + (length - tlength));
		/*
		 * Create a new node and add it.
		 */
		if (cctx->count < DNS_COMPRESS_INITIALNODES)
			node = &cctx->initialnodes[cctx->count];
		else {
			node = isc_mem_get(cctx->mctx,
					   sizeof(dns_compressnode_t));
			if (node == NULL)
				return;
		}
		node->count = cctx->count++;
		node->offset = toffset;
		dns_name_toregion(&tname, &node->r);
		node->labels = (isc_uint8_t)dns_name_countlabels(&tname);
		node->next = cctx->table[hash];
		cctx->table[hash] = node;
		start++;
		n--;
		count--;
	}
}
Beispiel #2
0
isc_result_t
dst_key_getfilename(dns_name_t *name, dns_keytag_t id,
		    unsigned int alg, int type, const char *directory,
		    isc_mem_t *mctx, isc_buffer_t *buf)
{
	isc_result_t result;

	REQUIRE(dst_initialized == ISC_TRUE);
	REQUIRE(dns_name_isabsolute(name));
	REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
	REQUIRE(mctx != NULL);
	REQUIRE(buf != NULL);

	CHECKALG(alg);

	result = buildfilename(name, id, alg, type, directory, buf);
	if (result == ISC_R_SUCCESS) {
		if (isc_buffer_availablelength(buf) > 0)
			isc_buffer_putuint8(buf, 0);
		else
			result = ISC_R_NOSPACE;
	}

	return (result);
}
Beispiel #3
0
isc_result_t
dst_key_buildinternal(dns_name_t *name, unsigned int alg,
		      unsigned int bits, unsigned int flags,
		      unsigned int protocol, dns_rdataclass_t rdclass,
		      void *data, isc_mem_t *mctx, dst_key_t **keyp)
{
	dst_key_t *key;
	isc_result_t result;

	REQUIRE(dst_initialized == ISC_TRUE);
	REQUIRE(dns_name_isabsolute(name));
	REQUIRE(mctx != NULL);
	REQUIRE(keyp != NULL && *keyp == NULL);
	REQUIRE(data != NULL);

	CHECKALG(alg);

	key = get_key_struct(name, alg, flags, protocol, bits, rdclass,
			     0, mctx);
	if (key == NULL)
		return (ISC_R_NOMEMORY);

	key->keydata.generic = data;

	result = computeid(key);
	if (result != ISC_R_SUCCESS) {
		dst_key_free(&key);
		return (result);
	}

	*keyp = key;
	return (ISC_R_SUCCESS);
}
isc_result_t
dns_keytable_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name,
			      dns_name_t *foundname)
{
	isc_result_t result;
	void *data;

	/*
	 * Search for the deepest match in 'keytable'.
	 */

	REQUIRE(VALID_KEYTABLE(keytable));
	REQUIRE(dns_name_isabsolute(name));
	REQUIRE(foundname != NULL);

	RWLOCK(&keytable->rwlock, isc_rwlocktype_read);

	data = NULL;
	result = dns_rbt_findname(keytable->table, name, 0, foundname, &data);

	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
		result = ISC_R_SUCCESS;

	RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);

	return (result);
}
Beispiel #5
0
isc_result_t
dns_db_create(isc_mem_t *mctx, const char *db_type, dns_name_t *origin,
	      dns_dbtype_t type, dns_rdataclass_t rdclass,
	      unsigned int argc, char *argv[], dns_db_t **dbp)
{
	dns_dbimplementation_t *impinfo;

	RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);

	/*
	 * Create a new database using implementation 'db_type'.
	 */

	REQUIRE(dbp != NULL && *dbp == NULL);
	REQUIRE(dns_name_isabsolute(origin));

	RWLOCK(&implock, isc_rwlocktype_read);
	impinfo = impfind(db_type);
	if (impinfo != NULL) {
		isc_result_t result;
		result = ((impinfo->create)(mctx, origin, type,
					    rdclass, argc, argv,
					    impinfo->driverarg, dbp));
		RWUNLOCK(&implock, isc_rwlocktype_read);
		return (result);
	}

	RWUNLOCK(&implock, isc_rwlocktype_read);

	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DB, ISC_LOG_ERROR,
		      "unsupported database type '%s'", db_type);

	return (ISC_R_NOTFOUND);
}
isc_result_t
dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
			    isc_boolean_t *wantdnssecp)
{
	isc_result_t result;
	void *data;

	/*
	 * Is 'name' at or beneath a trusted key?
	 */

	REQUIRE(VALID_KEYTABLE(keytable));
	REQUIRE(dns_name_isabsolute(name));
	REQUIRE(wantdnssecp != NULL);

	RWLOCK(&keytable->rwlock, isc_rwlocktype_read);

	data = NULL;
	result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);

	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
		INSIST(data != NULL);
		*wantdnssecp = ISC_TRUE;
		result = ISC_R_SUCCESS;
	} else if (result == ISC_R_NOTFOUND) {
		*wantdnssecp = ISC_FALSE;
		result = ISC_R_SUCCESS;
	}

	RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);

	return (result);
}
Beispiel #7
0
static inline void
name_to_gbuffer(dns_name_t *name, isc_buffer_t *buffer,
		gss_buffer_desc *gbuffer)
{
	dns_name_t tname, *namep;
	isc_region_t r;
	isc_result_t result;

	if (!dns_name_isabsolute(name))
		namep = name;
	else
	{
		unsigned int labels;
		dns_name_init(&tname, NULL);
		labels = dns_name_countlabels(name);
		dns_name_getlabelsequence(name, 0, labels - 1, &tname);
		namep = &tname;
	}

	result = dns_name_toprincipal(namep, buffer);
	RUNTIME_CHECK(result == ISC_R_SUCCESS);
	isc_buffer_putuint8(buffer, 0);
	isc_buffer_usedregion(buffer, &r);
	REGION_TO_GBUFFER(r, *gbuffer);
}
isc_result_t
dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
			 dns_secalg_t algorithm, dns_keytag_t tag,
			 dns_keynode_t **keynodep)
{
	isc_result_t result;
	dns_keynode_t *knode;
	void *data;

	/*
	 * Search for a key named 'name', matching 'algorithm' and 'tag' in
	 * 'keytable'.
	 */

	REQUIRE(VALID_KEYTABLE(keytable));
	REQUIRE(dns_name_isabsolute(name));
	REQUIRE(keynodep != NULL && *keynodep == NULL);

	RWLOCK(&keytable->rwlock, isc_rwlocktype_read);

	/*
	 * Note we don't want the DNS_R_PARTIALMATCH from dns_rbt_findname()
	 * as that indicates that 'name' was not found.
	 *
	 * DNS_R_PARTIALMATCH indicates that the name was found but we
	 * didn't get a match on algorithm and key id arguments.
	 */
	knode = NULL;
	data = NULL;
	result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);

	if (result == ISC_R_SUCCESS) {
		INSIST(data != NULL);
		for (knode = data; knode != NULL; knode = knode->next) {
			if (knode->key == NULL) {
				knode = NULL;
				break;
			}
			if (algorithm == dst_key_alg(knode->key)
			    && tag == dst_key_id(knode->key))
				break;
		}
		if (knode != NULL) {
			LOCK(&keytable->lock);
			keytable->active_nodes++;
			UNLOCK(&keytable->lock);
			dns_keynode_attach(knode, keynodep);
		} else
			result = DNS_R_PARTIALMATCH;
	} else if (result == DNS_R_PARTIALMATCH)
		result = ISC_R_NOTFOUND;

	RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);

	return (result);
}
Beispiel #9
0
/*
 * Find the longest match of name in the table.
 * If match is found return ISC_TRUE. prefix, suffix and offset are updated.
 * If no match is found return ISC_FALSE.
 */
isc_boolean_t
dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name,
			dns_name_t *prefix, isc_uint16_t *offset)
{
	dns_name_t tname, nname;
	dns_compressnode_t *node = NULL;
	unsigned int labels, hash, n;

	REQUIRE(VALID_CCTX(cctx));
	REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
	REQUIRE(offset != NULL);

	if (cctx->count == 0)
		return (ISC_FALSE);

	labels = dns_name_countlabels(name);
	INSIST(labels > 0);

	dns_name_init(&tname, NULL);
	dns_name_init(&nname, NULL);

	for (n = 0; n < labels - 1; n++) {
		dns_name_getlabelsequence(name, n, labels - n, &tname);
		hash = dns_name_hash(&tname, ISC_FALSE) %
		       DNS_COMPRESS_TABLESIZE;
		for (node = cctx->table[hash]; node != NULL; node = node->next)
		{
			NODENAME(node, &nname);
			if ((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0) {
				if (dns_name_caseequal(&nname, &tname))
					break;
			} else {
				if (dns_name_equal(&nname, &tname))
					break;
			}
		}
		if (node != NULL)
			break;
	}

	/*
	 * If node == NULL, we found no match at all.
	 */
	if (node == NULL)
		return (ISC_FALSE);

	if (n == 0)
		dns_name_reset(prefix);
	else
		dns_name_getlabelsequence(name, 0, n, prefix);

	*offset = node->offset;
	return (ISC_TRUE);
}
Beispiel #10
0
isc_result_t
dst_key_generate2(dns_name_t *name, unsigned int alg,
		  unsigned int bits, unsigned int param,
		  unsigned int flags, unsigned int protocol,
		  dns_rdataclass_t rdclass,
		  isc_mem_t *mctx, dst_key_t **keyp,
		  void (*callback)(int))
{
	dst_key_t *key;
	isc_result_t ret;

	REQUIRE(dst_initialized == ISC_TRUE);
	REQUIRE(dns_name_isabsolute(name));
	REQUIRE(mctx != NULL);
	REQUIRE(keyp != NULL && *keyp == NULL);

	CHECKALG(alg);

	key = get_key_struct(name, alg, flags, protocol, bits,
			     rdclass, 0, mctx);
	if (key == NULL)
		return (ISC_R_NOMEMORY);

	if (bits == 0) { /*%< NULL KEY */
		key->key_flags |= DNS_KEYTYPE_NOKEY;
		*keyp = key;
		return (ISC_R_SUCCESS);
	}

	if (key->func->generate == NULL) {
		dst_key_free(&key);
		return (DST_R_UNSUPPORTEDALG);
	}

	ret = key->func->generate(key, param, callback);
	if (ret != ISC_R_SUCCESS) {
		dst_key_free(&key);
		return (ret);
	}

	ret = computeid(key);
	if (ret != ISC_R_SUCCESS) {
		dst_key_free(&key);
		return (ret);
	}

	*keyp = key;
	return (ISC_R_SUCCESS);
}
Beispiel #11
0
isc_result_t
dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
		 unsigned int alg, int type, const char *directory,
		 isc_mem_t *mctx, dst_key_t **keyp)
{
	isc_result_t result;
	char filename[ISC_DIR_NAMEMAX];
	isc_buffer_t buf;
	dst_key_t *key;

	REQUIRE(dst_initialized == ISC_TRUE);
	REQUIRE(dns_name_isabsolute(name));
	REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
	REQUIRE(mctx != NULL);
	REQUIRE(keyp != NULL && *keyp == NULL);

	CHECKALG(alg);

	key = NULL;

	isc_buffer_init(&buf, filename, ISC_DIR_NAMEMAX);
	result = dst_key_getfilename(name, id, alg, type, NULL, mctx, &buf);
	if (result != ISC_R_SUCCESS)
		goto out;

	result = dst_key_fromnamedfile(filename, directory, type, mctx, &key);
	if (result != ISC_R_SUCCESS)
		goto out;

	result = computeid(key);
	if (result != ISC_R_SUCCESS)
		goto out;

	if (!dns_name_equal(name, key->key_name) || id != key->key_id ||
	    alg != key->key_alg) {
		result = DST_R_INVALIDPRIVATEKEY;
		goto out;
	}

	*keyp = key;
	result = ISC_R_SUCCESS;

 out:
	if ((key != NULL) && (result != ISC_R_SUCCESS))
		dst_key_free(&key);

	return (result);
}
Beispiel #12
0
isc_result_t
dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
		 unsigned int alg, int type, const char *directory,
		 isc_mem_t *mctx, dst_key_t **keyp)
{
	char filename[ISC_DIR_NAMEMAX];
	isc_buffer_t b;
	dst_key_t *key;
	isc_result_t result;

	REQUIRE(dst_initialized == ISC_TRUE);
	REQUIRE(dns_name_isabsolute(name));
	REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
	REQUIRE(mctx != NULL);
	REQUIRE(keyp != NULL && *keyp == NULL);

	CHECKALG(alg);

	isc_buffer_init(&b, filename, sizeof(filename));
	result = buildfilename(name, id, alg, type, directory, &b);
	if (result != ISC_R_SUCCESS)
		return (result);

	key = NULL;
	result = dst_key_fromnamedfile(filename, type, mctx, &key);
	if (result != ISC_R_SUCCESS)
		return (result);

	result = computeid(key);
	if (result != ISC_R_SUCCESS) {
		dst_key_free(&key);
		return (result);
	}

	if (!dns_name_equal(name, key->key_name) ||
	    id != key->key_id ||
	    alg != key->key_alg)
	{
		dst_key_free(&key);
		return (DST_R_INVALIDPRIVATEKEY);
	}
	key->key_id = id;

	*keyp = key;
	return (ISC_R_SUCCESS);
}
Beispiel #13
0
void
ns_lwsearchctx_init(ns_lwsearchctx_t *sctx, ns_lwsearchlist_t *list,
		    dns_name_t *name, unsigned int ndots)
{
	INSIST(sctx != NULL);
	sctx->relname = name;
	sctx->searchname = NULL;
	sctx->doneexact = ISC_FALSE;
	sctx->exactfirst = ISC_FALSE;
	sctx->ndots = ndots;
	if (dns_name_isabsolute(name) || list == NULL) {
		sctx->list = NULL;
		return;
	}
	sctx->list = list;
	sctx->searchname = ISC_LIST_HEAD(sctx->list->names);
	if (dns_name_countlabels(name) > ndots)
		sctx->exactfirst = ISC_TRUE;
}
Beispiel #14
0
isc_result_t
dst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags,
		  unsigned int protocol, dns_rdataclass_t rdclass,
		  const char *engine, const char *label, const char *pin,
		  isc_mem_t *mctx, dst_key_t **keyp)
{
	dst_key_t *key;
	isc_result_t result;

	REQUIRE(dst_initialized == ISC_TRUE);
	REQUIRE(dns_name_isabsolute(name));
	REQUIRE(mctx != NULL);
	REQUIRE(keyp != NULL && *keyp == NULL);
	REQUIRE(label != NULL);

	CHECKALG(alg);

	key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
	if (key == NULL)
		return (ISC_R_NOMEMORY);

	if (key->func->fromlabel == NULL) {
		dst_key_free(&key);
		return (DST_R_UNSUPPORTEDALG);
	}

	result = key->func->fromlabel(key, engine, label, pin);
	if (result != ISC_R_SUCCESS) {
		dst_key_free(&key);
		return (result);
	}

	result = computeid(key);
	if (result != ISC_R_SUCCESS) {
		dst_key_free(&key);
		return (result);
	}

	*keyp = key;
	return (ISC_R_SUCCESS);
}
Beispiel #15
0
isc_result_t
ns_lwsearchctx_current(ns_lwsearchctx_t *sctx, dns_name_t *absname) {
	dns_name_t *tname;
	isc_boolean_t useexact = ISC_FALSE;

	REQUIRE(sctx != NULL);

	if (sctx->list == NULL ||
	    sctx->searchname == NULL ||
	    (sctx->exactfirst && !sctx->doneexact))
		useexact = ISC_TRUE;

	if (useexact) {
		if (dns_name_isabsolute(sctx->relname))
			tname = NULL;
		else
			tname = dns_rootname;
	} else
		tname = sctx->searchname;

	return (dns_name_concatenate(sctx->relname, tname, absname, NULL));
}
Beispiel #16
0
static isc_result_t
frombuffer(dns_name_t *name, unsigned int alg, unsigned int flags,
	   unsigned int protocol, dns_rdataclass_t rdclass,
	   isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
{
	dst_key_t *key;
	isc_result_t ret;

	REQUIRE(dns_name_isabsolute(name));
	REQUIRE(source != NULL);
	REQUIRE(mctx != NULL);
	REQUIRE(keyp != NULL && *keyp == NULL);

	key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
	if (key == NULL)
		return (ISC_R_NOMEMORY);

	if (isc_buffer_remaininglength(source) > 0) {
		ret = algorithm_status(alg);
		if (ret != ISC_R_SUCCESS) {
			dst_key_free(&key);
			return (ret);
		}
		if (key->func->fromdns == NULL) {
			dst_key_free(&key);
			return (DST_R_UNSUPPORTEDALG);
		}

		ret = key->func->fromdns(key, source);
		if (ret != ISC_R_SUCCESS) {
			dst_key_free(&key);
			return (ret);
		}
	}

	*keyp = key;
	return (ISC_R_SUCCESS);
}
Beispiel #17
0
static int
t9_walkchain(dns_rbtnodechain_t *chain, dns_rbt_t *rbt) {
	int		cnt;
	int		order;
	unsigned int	nlabels;
	int		nprobs;
	isc_result_t	dns_result;

	dns_fixedname_t	name;
	dns_fixedname_t	origin;
	dns_fixedname_t	fullname1;
	dns_fixedname_t	fullname2;

	cnt = 0;
	nprobs = 0;

	do {

		if (cnt == 0) {
			dns_fixedname_init(&name);
			dns_fixedname_init(&origin);
			dns_result = dns_rbtnodechain_first(chain, rbt,
						dns_fixedname_name(&name),
						dns_fixedname_name(&origin));
			if (dns_result != DNS_R_NEWORIGIN) {
				t_info("dns_rbtnodechain_first returned %s, "
				       "expecting DNS_R_NEWORIGIN\n",
				       dns_result_totext(dns_result));
				++nprobs;
				break;
			}
			t_info("first name:\t<%s>\n", fixedname_totext(&name));
			t_info("first origin:\t<%s>\n",
			       fixedname_totext(&origin));
		} else {
			dns_fixedname_init(&fullname1);
			dns_result = dns_name_concatenate(
			       dns_fixedname_name(&name),
			       dns_name_isabsolute(dns_fixedname_name(&name)) ?
					    NULL : dns_fixedname_name(&origin),
			       dns_fixedname_name(&fullname1), NULL);
			if (dns_result != ISC_R_SUCCESS) {
				t_info("dns_name_concatenate failed %s\n",
				       dns_result_totext(dns_result));
				++nprobs;
				break;
			}

			/*
			 * Expecting origin not to get touched if next
			 * doesn't return NEWORIGIN.
			 */
			dns_fixedname_init(&name);
			dns_result = dns_rbtnodechain_next(chain,
						  dns_fixedname_name(&name),
						  dns_fixedname_name(&origin));
			if ((dns_result != ISC_R_SUCCESS) &&
			    (dns_result != DNS_R_NEWORIGIN)) {
				if (dns_result != ISC_R_NOMORE) {
					t_info("dns_rbtnodechain_next "
					       "failed %s\n",
					       dns_result_totext(dns_result));
					++nprobs;
				}
				break;
			}

			t_info("next name:\t<%s>\n", fixedname_totext(&name));
			t_info("next origin:\t<%s>\n",
			       fixedname_totext(&origin));

			dns_fixedname_init(&fullname2);
			dns_result = dns_name_concatenate(
			       dns_fixedname_name(&name),
			       dns_name_isabsolute(dns_fixedname_name(&name)) ?
					    NULL : dns_fixedname_name(&origin),
			       dns_fixedname_name(&fullname2), NULL);
			if (dns_result != ISC_R_SUCCESS) {
				t_info("dns_name_concatenate failed %s\n",
				       dns_result_totext(dns_result));
				++nprobs;
				break;
			}

			t_info("comparing\t<%s>\n",
			       fixedname_totext(&fullname1));
			t_info("\twith\t<%s>\n", fixedname_totext(&fullname2));

			(void)dns_name_fullcompare(
						dns_fixedname_name(&fullname1),
						dns_fixedname_name(&fullname2),
						&order, &nlabels);

			if (order >= 0) {
			    t_info("unexpected order %s %s %s\n",
			       dnsname_totext(dns_fixedname_name(&fullname1)),
			       order == -1 ? "<" : (order == 0 ? "==" : ">"),
			       dnsname_totext(dns_fixedname_name(&fullname2)));
				++nprobs;
			}
		}

		++cnt;
	} while (1);

	return (nprobs);
}
isc_boolean_t
dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
			dns_name_t *name, isc_netaddr_t *tcpaddr,
			dns_rdatatype_t type,
			const dst_key_t *key)
{
	dns_ssurule_t *rule;
	unsigned int i;
	dns_fixedname_t fixed;
	dns_name_t *wildcard;
	dns_name_t *tcpself;
	dns_name_t *stfself;
	isc_result_t result;

	REQUIRE(VALID_SSUTABLE(table));
	REQUIRE(signer == NULL || dns_name_isabsolute(signer));
	REQUIRE(dns_name_isabsolute(name));

	if (signer == NULL && tcpaddr == NULL)
		return (ISC_FALSE);

	for (rule = ISC_LIST_HEAD(table->rules);
	     rule != NULL;
	     rule = ISC_LIST_NEXT(rule, link))
	{
		switch (rule->matchtype) {
		case DNS_SSUMATCHTYPE_NAME:
		case DNS_SSUMATCHTYPE_SUBDOMAIN:
		case DNS_SSUMATCHTYPE_WILDCARD:
		case DNS_SSUMATCHTYPE_SELF:
		case DNS_SSUMATCHTYPE_SELFSUB:
		case DNS_SSUMATCHTYPE_SELFWILD:
			if (signer == NULL)
				continue;
			if (dns_name_iswildcard(rule->identity)) {
				if (!dns_name_matcheswildcard(signer,
							      rule->identity))
					continue;
			} else {
				if (!dns_name_equal(signer, rule->identity))
					continue;
			}
			break;
		case DNS_SSUMATCHTYPE_SELFKRB5:
		case DNS_SSUMATCHTYPE_SELFMS:
		case DNS_SSUMATCHTYPE_SUBDOMAINKRB5:
		case DNS_SSUMATCHTYPE_SUBDOMAINMS:
			if (signer == NULL)
				continue;
			break;
		case DNS_SSUMATCHTYPE_TCPSELF:
		case DNS_SSUMATCHTYPE_6TO4SELF:
			if (tcpaddr == NULL)
				continue;
			break;
		}

		switch (rule->matchtype) {
		case DNS_SSUMATCHTYPE_NAME:
			if (!dns_name_equal(name, rule->name))
				continue;
			break;
		case DNS_SSUMATCHTYPE_SUBDOMAIN:
			if (!dns_name_issubdomain(name, rule->name))
				continue;
			break;
		case DNS_SSUMATCHTYPE_WILDCARD:
			if (!dns_name_matcheswildcard(name, rule->name))
				continue;
			break;
		case DNS_SSUMATCHTYPE_SELF:
			if (!dns_name_equal(signer, name))
				continue;
			break;
		case DNS_SSUMATCHTYPE_SELFSUB:
			if (!dns_name_issubdomain(name, signer))
				continue;
			break;
		case DNS_SSUMATCHTYPE_SELFWILD:
			dns_fixedname_init(&fixed);
			wildcard = dns_fixedname_name(&fixed);
			result = dns_name_concatenate(dns_wildcardname, signer,
						      wildcard, NULL);
			if (result != ISC_R_SUCCESS)
				continue;
			if (!dns_name_matcheswildcard(name, wildcard))
				continue;
			break;
		case DNS_SSUMATCHTYPE_SELFKRB5:
			if (!dst_gssapi_identitymatchesrealmkrb5(signer, name,
							       rule->identity))
				continue;
			break;
		case DNS_SSUMATCHTYPE_SELFMS:
			if (!dst_gssapi_identitymatchesrealmms(signer, name,
							       rule->identity))
				continue;
			break;
		case DNS_SSUMATCHTYPE_SUBDOMAINKRB5:
			if (!dns_name_issubdomain(name, rule->name))
				continue;
			if (!dst_gssapi_identitymatchesrealmkrb5(signer, NULL,
							       rule->identity))
				continue;
			break;
		case DNS_SSUMATCHTYPE_SUBDOMAINMS:
			if (!dns_name_issubdomain(name, rule->name))
				continue;
			if (!dst_gssapi_identitymatchesrealmms(signer, NULL,
							       rule->identity))
				continue;
			break;
		case DNS_SSUMATCHTYPE_TCPSELF:
			dns_fixedname_init(&fixed);
			tcpself = dns_fixedname_name(&fixed);
			reverse_from_address(tcpself, tcpaddr);
			if (dns_name_iswildcard(rule->identity)) {
				if (!dns_name_matcheswildcard(tcpself,
							      rule->identity))
					continue;
			} else {
				if (!dns_name_equal(tcpself, rule->identity))
					continue;
			}
			if (!dns_name_equal(tcpself, name))
				continue;
			break;
		case DNS_SSUMATCHTYPE_6TO4SELF:
			dns_fixedname_init(&fixed);
			stfself = dns_fixedname_name(&fixed);
			stf_from_address(stfself, tcpaddr);
			if (dns_name_iswildcard(rule->identity)) {
				if (!dns_name_matcheswildcard(stfself,
							      rule->identity))
					continue;
			} else {
				if (!dns_name_equal(stfself, rule->identity))
					continue;
			}
			if (!dns_name_equal(stfself, name))
				continue;
			break;
		case DNS_SSUMATCHTYPE_EXTERNAL:
			if (!dns_ssu_external_match(rule->identity, signer,
						    name, tcpaddr, type, key,
						    table->mctx))
				continue;
			break;
		case DNS_SSUMATCHTYPE_DLZ:
			if (!dns_dlz_ssumatch(table->dlzdatabase, signer,
					      name, tcpaddr, type, key))
				continue;
			break;
		}

		if (rule->ntypes == 0) {
			/*
			 * If this is a DLZ rule, then the DLZ ssu
			 * checks will have already checked
			 * the type.
			 */
			if (rule->matchtype != DNS_SSUMATCHTYPE_DLZ &&
			    !isusertype(type))
				continue;
		} else {
			for (i = 0; i < rule->ntypes; i++) {
				if (rule->types[i] == dns_rdatatype_any ||
				    rule->types[i] == type)
					break;
			}
			if (i == rule->ntypes)
				continue;
		}
		return (rule->grant);
	}

	return (ISC_FALSE);
}
isc_result_t
dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant,
		     dns_name_t *identity, unsigned int matchtype,
		     dns_name_t *name, unsigned int ntypes,
		     dns_rdatatype_t *types)
{
	dns_ssurule_t *rule;
	isc_mem_t *mctx;
	isc_result_t result;

	REQUIRE(VALID_SSUTABLE(table));
	REQUIRE(dns_name_isabsolute(identity));
	REQUIRE(dns_name_isabsolute(name));
	REQUIRE(matchtype <= DNS_SSUMATCHTYPE_MAX);
	if (matchtype == DNS_SSUMATCHTYPE_WILDCARD)
		REQUIRE(dns_name_iswildcard(name));
	if (ntypes > 0)
		REQUIRE(types != NULL);

	mctx = table->mctx;
	rule = isc_mem_get(mctx, sizeof(dns_ssurule_t));
	if (rule == NULL)
		return (ISC_R_NOMEMORY);

	rule->identity = NULL;
	rule->name = NULL;
	rule->types = NULL;

	rule->grant = grant;

	rule->identity = isc_mem_get(mctx, sizeof(dns_name_t));
	if (rule->identity == NULL) {
		result = ISC_R_NOMEMORY;
		goto failure;
	}
	dns_name_init(rule->identity, NULL);
	result = dns_name_dup(identity, mctx, rule->identity);
	if (result != ISC_R_SUCCESS)
		goto failure;

	rule->name = isc_mem_get(mctx, sizeof(dns_name_t));
	if (rule->name == NULL) {
		result = ISC_R_NOMEMORY;
		goto failure;
	}
	dns_name_init(rule->name, NULL);
	result = dns_name_dup(name, mctx, rule->name);
	if (result != ISC_R_SUCCESS)
		goto failure;

	rule->matchtype = matchtype;

	rule->ntypes = ntypes;
	if (ntypes > 0) {
		rule->types = isc_mem_get(mctx,
					  ntypes * sizeof(dns_rdatatype_t));
		if (rule->types == NULL) {
			result = ISC_R_NOMEMORY;
			goto failure;
		}
		memmove(rule->types, types, ntypes * sizeof(dns_rdatatype_t));
	} else
		rule->types = NULL;

	rule->magic = SSURULEMAGIC;
	ISC_LIST_INITANDAPPEND(table->rules, rule, link);

	return (ISC_R_SUCCESS);

 failure:
	if (rule->identity != NULL) {
		if (dns_name_dynamic(rule->identity))
			dns_name_free(rule->identity, mctx);
		isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
	}
	if (rule->name != NULL) {
		if (dns_name_dynamic(rule->name))
			dns_name_free(rule->name, mctx);
		isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
	}
	if (rule->types != NULL)
		isc_mem_put(mctx, rule->types,
			    ntypes * sizeof(dns_rdatatype_t));
	isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));

	return (result);
}
Beispiel #20
0
/*
 * Find the longest match of name in the table.
 * If match is found return ISC_TRUE. prefix, suffix and offset are updated.
 * If no match is found return ISC_FALSE.
 */
isc_boolean_t
dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name,
			dns_name_t *prefix, isc_uint16_t *offset)
{
	dns_name_t tname;
	dns_compressnode_t *node = NULL;
	unsigned int labels, i, n;
	unsigned int numlabels;
	unsigned char *p;

	REQUIRE(VALID_CCTX(cctx));
	REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
	REQUIRE(offset != NULL);

	if (ISC_UNLIKELY((cctx->allowed & DNS_COMPRESS_ENABLED) == 0))
		return (ISC_FALSE);

	if (cctx->count == 0)
		return (ISC_FALSE);

	labels = dns_name_countlabels(name);
	INSIST(labels > 0);

	dns_name_init(&tname, NULL);

	numlabels = labels > 3U ? 3U : labels;
	p = name->ndata;

	for (n = 0; n < numlabels - 1; n++) {
		unsigned char ch, llen;
		unsigned int firstoffset, length;

		firstoffset = (unsigned int)(p - name->ndata);
		length = name->length - firstoffset;

		/*
		 * We calculate the table index using the first
		 * character in the first label of the suffix name.
		 */
		ch = p[1];
		i = tableindex[ch];
		if (ISC_LIKELY((cctx->allowed &
				DNS_COMPRESS_CASESENSITIVE) != 0))
		{
			for (node = cctx->table[i];
			     node != NULL;
			     node = node->next)
			{
				if (ISC_UNLIKELY(node->name.length != length))
					continue;

				if (ISC_LIKELY(memcmp(node->name.ndata,
						      p, length) == 0))
					goto found;
			}
		} else {
			for (node = cctx->table[i];
			     node != NULL;
			     node = node->next)
			{
				unsigned int l, count;
				unsigned char c;
				unsigned char *label1, *label2;

				if (ISC_UNLIKELY(node->name.length != length))
					continue;

				l = labels - n;
				if (ISC_UNLIKELY(node->name.labels != l))
					continue;

				label1 = node->name.ndata;
				label2 = p;
				while (ISC_LIKELY(l-- > 0)) {
					count = *label1++;
					if (count != *label2++)
						goto cont1;

					/* no bitstring support */
					INSIST(count <= 63);

					/* Loop unrolled for performance */
					while (ISC_LIKELY(count > 3)) {
						c = maptolower[label1[0]];
						if (c != maptolower[label2[0]])
							goto cont1;
						c = maptolower[label1[1]];
						if (c != maptolower[label2[1]])
							goto cont1;
						c = maptolower[label1[2]];
						if (c != maptolower[label2[2]])
							goto cont1;
						c = maptolower[label1[3]];
						if (c != maptolower[label2[3]])
							goto cont1;
						count -= 4;
						label1 += 4;
						label2 += 4;
					}
					while (ISC_LIKELY(count-- > 0)) {
						c = maptolower[*label1++];
						if (c != maptolower[*label2++])
							goto cont1;
					}
				}
				break;
 cont1:
				continue;
			}
		}

		if (node != NULL)
			break;

		llen = *p;
		p += llen + 1;
	}

 found:
	/*
	 * If node == NULL, we found no match at all.
	 */
	if (node == NULL)
		return (ISC_FALSE);

	if (n == 0)
		dns_name_reset(prefix);
	else
		dns_name_getlabelsequence(name, 0, n, prefix);

	*offset = (node->offset & 0x7fff);
	return (ISC_TRUE);
}
Beispiel #21
0
void
dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
		 const dns_name_t *prefix, isc_uint16_t offset)
{
	dns_name_t tname, xname;
	unsigned int start;
	unsigned int n;
	unsigned int count;
	unsigned int i;
	dns_compressnode_t *node;
	unsigned int length;
	unsigned int tlength;
	isc_uint16_t toffset;
	unsigned char *tmp;
	isc_region_t r;

	REQUIRE(VALID_CCTX(cctx));
	REQUIRE(dns_name_isabsolute(name));

	if (ISC_UNLIKELY((cctx->allowed & DNS_COMPRESS_ENABLED) == 0))
		return;

	if (offset >= 0x4000)
		return;
	dns_name_init(&tname, NULL);
	dns_name_init(&xname, NULL);

	n = dns_name_countlabels(name);
	count = dns_name_countlabels(prefix);
	if (dns_name_isabsolute(prefix))
		count--;
	if (count == 0)
		return;
	start = 0;
	dns_name_toregion(name, &r);
	length = r.length;
	tmp = isc_mem_get(cctx->mctx, length);
	if (tmp == NULL)
		return;
	/*
	 * Copy name data to 'tmp' and make 'r' use 'tmp'.
	 */
	memmove(tmp, r.base, r.length);
	r.base = tmp;
	dns_name_fromregion(&xname, &r);

	if (count > 2U)
		count = 2U;

	while (count > 0) {
		unsigned char ch;

		dns_name_getlabelsequence(&xname, start, n, &tname);
		/*
		 * We calculate the table index using the first
		 * character in the first label of tname.
		 */
		ch = tname.ndata[1];
		i = tableindex[ch];
		tlength = name_length(&tname);
		toffset = (isc_uint16_t)(offset + (length - tlength));
		if (toffset >= 0x4000)
			break;
		/*
		 * Create a new node and add it.
		 */
		if (cctx->count < DNS_COMPRESS_INITIALNODES)
			node = &cctx->initialnodes[cctx->count];
		else {
			node = isc_mem_get(cctx->mctx,
					   sizeof(dns_compressnode_t));
			if (node == NULL)
				break;
		}
		node->count = cctx->count++;
		/*
		 * 'node->r.base' becomes 'tmp' when start == 0.
		 * Record this by setting 0x8000 so it can be freed later.
		 */
		if (start == 0)
			toffset |= 0x8000;
		node->offset = toffset;
		dns_name_toregion(&tname, &node->r);
		dns_name_init(&node->name, NULL);
		node->name.length = node->r.length;
		node->name.ndata = node->r.base;
		node->name.labels = tname.labels;
		node->name.attributes = DNS_NAMEATTR_ABSOLUTE;
		node->next = cctx->table[i];
		cctx->table[i] = node;
		start++;
		n--;
		count--;
	}

	if (start == 0)
		isc_mem_put(cctx->mctx, tmp, length);
}
int
main(int argc, char *argv[]) {
	char s[1000];
	isc_result_t result;
	dns_fixedname_t wname, wname2, oname, compname, downname;
	isc_buffer_t source;
	isc_region_t r;
	dns_name_t *name, *origin, *comp, *down;
	isc_boolean_t downcase = ISC_FALSE;
	size_t len;
	isc_boolean_t quiet = ISC_FALSE;
	isc_boolean_t concatenate = ISC_FALSE;
	isc_boolean_t got_name = ISC_FALSE;
	isc_boolean_t check_absolute = ISC_FALSE;
	isc_boolean_t check_wildcard = ISC_FALSE;
	isc_boolean_t test_downcase = ISC_FALSE;
	isc_boolean_t inplace = ISC_FALSE;
	isc_boolean_t want_split = ISC_FALSE;
	unsigned int labels, split_label = 0;
	dns_fixedname_t fprefix, fsuffix;
	dns_name_t *prefix, *suffix;
	int ch;

	while ((ch = isc_commandline_parse(argc, argv, "acdiqs:w")) != -1) {
		switch (ch) {
		case 'a':
			check_absolute = ISC_TRUE;
			break;
		case 'c':
			concatenate = ISC_TRUE;
			break;
		case 'd':
			test_downcase = ISC_TRUE;
			break;
		case 'i':
			inplace = ISC_TRUE;
			break;
		case 'q':
			quiet = ISC_TRUE;
			break;
		case 's':
			want_split = ISC_TRUE;
			split_label = atoi(isc_commandline_argument);
			break;
		case 'w':
			check_wildcard = ISC_TRUE;
			break;
		}
	}

	argc -= isc_commandline_index;
	argv += isc_commandline_index;

	if (argc > 0) {
		if (strcasecmp("none", argv[0]) == 0)
			origin = NULL;
		else {
			len = strlen(argv[0]);
			isc_buffer_init(&source, argv[0], len);
			isc_buffer_add(&source, len);
			dns_fixedname_init(&oname);
			origin = &oname.name;
			result = dns_name_fromtext(origin, &source,
						   dns_rootname, ISC_FALSE,
						   NULL);
			if (result != 0) {
				fprintf(stderr,
					"dns_name_fromtext() failed: %d\n",
					result);
				exit(1);
			}
		}
	} else if (concatenate)
		origin = NULL;
	else
		origin = dns_rootname;

	if (argc >= 1) {
		if (strcasecmp("none", argv[1]) == 0)
			comp = NULL;
		else {
			len = strlen(argv[1]);
			isc_buffer_init(&source, argv[1], len);
			isc_buffer_add(&source, len);
			dns_fixedname_init(&compname);
			comp = &compname.name;
			result = dns_name_fromtext(comp, &source,
						   origin, ISC_FALSE, NULL);
			if (result != 0) {
				fprintf(stderr,
					"dns_name_fromtext() failed: %d\n",
					result);
				exit(1);
			}
		}
	} else
		comp = NULL;

	dns_fixedname_init(&wname);
	name = dns_fixedname_name(&wname);
	dns_fixedname_init(&wname2);
	while (fgets(s, sizeof(s), stdin) != NULL) {
		len = strlen(s);
		if (len > 0U && s[len - 1] == '\n') {
			s[len - 1] = '\0';
			len--;
		}
		isc_buffer_init(&source, s, len);
		isc_buffer_add(&source, len);

		if (len > 0U)
			result = dns_name_fromtext(name, &source, origin,
						   downcase, NULL);
		else {
			if (name == dns_fixedname_name(&wname))
				dns_fixedname_init(&wname);
			else
				dns_fixedname_init(&wname2);
			result = ISC_R_SUCCESS;
		}

		if (result != ISC_R_SUCCESS) {
			printf("%s\n", dns_result_totext(result));
			if (name == dns_fixedname_name(&wname))
				dns_fixedname_init(&wname);
			else
				dns_fixedname_init(&wname2);
			continue;
		}

		if (check_absolute && dns_name_countlabels(name) > 0) {
			if (dns_name_isabsolute(name))
				printf("absolute\n");
			else
				printf("relative\n");
		}
		if (check_wildcard && dns_name_countlabels(name) > 0) {
			if (dns_name_iswildcard(name))
				printf("wildcard\n");
			else
				printf("not wildcard\n");
		}
		dns_name_toregion(name, &r);
		if (!quiet) {
			print_wirename(&r);
			printf("%u labels, %u bytes.\n",
			       dns_name_countlabels(name), r.length);
		}

		if (concatenate) {
			if (got_name) {
				printf("Concatenating.\n");
				result = dns_name_concatenate(&wname.name,
							      &wname2.name,
							      &wname2.name,
							      NULL);
				name = &wname2.name;
				if (result == ISC_R_SUCCESS) {
					if (check_absolute &&
					    dns_name_countlabels(name) > 0) {
						if (dns_name_isabsolute(name))
							printf("absolute\n");
						else
							printf("relative\n");
					}
					if (check_wildcard &&
					    dns_name_countlabels(name) > 0) {
						if (dns_name_iswildcard(name))
							printf("wildcard\n");
						else
							printf("not "
							       "wildcard\n");
					}
					dns_name_toregion(name, &r);
					if (!quiet) {
						print_wirename(&r);
						printf("%u labels, "
						       "%u bytes.\n",
						   dns_name_countlabels(name),
						       r.length);
					}
				} else
					printf("%s\n",
					       dns_result_totext(result));
				got_name = ISC_FALSE;
			} else
				got_name = ISC_TRUE;
		}
		isc_buffer_init(&source, s, sizeof(s));
		if (dns_name_countlabels(name) > 0)
			result = dns_name_totext(name, ISC_FALSE, &source);
		else
			result = ISC_R_SUCCESS;
		if (result == ISC_R_SUCCESS) {
			isc_buffer_usedregion(&source, &r);
			if (r.length > 0)
				printf("%.*s\n", (int)r.length, r.base);
			else
				printf("<empty text name>\n");
			if (!quiet) {
				printf("%u bytes.\n", source.used);
			}
		} else
			printf("%s\n", dns_result_totext(result));

		if (test_downcase) {
			if (inplace) {
				down = name;
			} else {
				dns_fixedname_init(&downname);
				down = dns_fixedname_name(&downname);
			}
			result = dns_name_downcase(name, down, NULL);
			INSIST(result == ISC_R_SUCCESS);
			if (!quiet) {
				dns_name_toregion(down, &r);
				print_wirename(&r);
				printf("%u labels, %u bytes.\n",
				       dns_name_countlabels(down),
				       r.length);
			}
			isc_buffer_init(&source, s, sizeof(s));
			print_name(down);
		}

		if (comp != NULL && dns_name_countlabels(name) > 0) {
			int order;
			unsigned int nlabels;
			dns_namereln_t namereln;

			namereln = dns_name_fullcompare(name, comp, &order,
							&nlabels);
			if (!quiet) {
				if (order < 0)
					printf("<");
				else if (order > 0)
					printf(">");
				else
					printf("=");
				switch (namereln) {
				case dns_namereln_contains:
					printf(", contains");
					break;
				case dns_namereln_subdomain:
					printf(", subdomain");
					break;
				case dns_namereln_commonancestor:
					printf(", common ancestor");
					break;
				default:
					break;
				}
				if (namereln != dns_namereln_none &&
				    namereln != dns_namereln_equal)
					printf(", nlabels = %u", nlabels);
				printf("\n");
			}
			printf("dns_name_equal() returns %s\n",
			       dns_name_equal(name, comp) ? "TRUE" : "FALSE");
		}

		labels = dns_name_countlabels(name);
		if (want_split && split_label < labels) {
			dns_fixedname_init(&fprefix);
			prefix = dns_fixedname_name(&fprefix);
			dns_fixedname_init(&fsuffix);
			suffix = dns_fixedname_name(&fsuffix);
			printf("splitting at label %u: ", split_label);
			dns_name_split(name, split_label, prefix, suffix);
			printf("\n    prefix = ");
			print_name(prefix);
			printf("    suffix = ");
			print_name(suffix);
		}

		if (concatenate) {
			if (got_name)
				name = &wname2.name;
			else
				name = &wname.name;
		}
	}

	return (0);
}