Ejemplo n.º 1
0
static inline isc_boolean_t
checknames_ptr(ARGS_CHECKNAMES) {
	isc_region_t region;
	dns_name_t name;

	REQUIRE(rdata->type == dns_rdatatype_ptr);

	if (rdata->rdclass != dns_rdataclass_in)
	    return (ISC_TRUE);

	if (dns_name_isdnssd(owner))
		return (ISC_TRUE);

	if (dns_name_issubdomain(owner, &in_addr_arpa) ||
	    dns_name_issubdomain(owner, &ip6_arpa) ||
	    dns_name_issubdomain(owner, &ip6_int)) {
		dns_rdata_toregion(rdata, &region);
		dns_name_init(&name, NULL);
		dns_name_fromregion(&name, &region);
		if (!dns_name_ishostname(&name, ISC_FALSE)) {
			if (bad != NULL)
				dns_name_clone(&name, bad);
			return (ISC_FALSE);
		}
	}
	return (ISC_TRUE);
}
Ejemplo n.º 2
0
/*%
 * Configure an apex NS with an out-of-zone NS names for a static-stub zone.
 * For example, for the zone named "example.com", something like the following
 * RRs will be added to the zone DB:
 * example.com. NS ns.example.net.
 */
static isc_result_t
configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone,
				 dns_rdatalist_t *rdatalist, const char *zname)
{
	const cfg_listelt_t *element;
	isc_mem_t *mctx = dns_zone_getmctx(zone);
	dns_rdata_t *rdata;
	isc_region_t sregion, region;
	isc_result_t result = ISC_R_SUCCESS;

	for (element = cfg_list_first(zconfig);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		const cfg_obj_t *obj;
		const char *str;
		dns_fixedname_t fixed_name;
		dns_name_t *nsname;
		isc_buffer_t b;

		obj = cfg_listelt_value(element);
		str = cfg_obj_asstring(obj);

		dns_fixedname_init(&fixed_name);
		nsname = dns_fixedname_name(&fixed_name);

		isc_buffer_init(&b, str, strlen(str));
		isc_buffer_add(&b, strlen(str));
		result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL);
		if (result != ISC_R_SUCCESS) {
			cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
					    "server-name '%s' is not a valid "
					    "name", str);
			return (result);
		}
		if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) {
			cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
				    "server-name '%s' must not be a "
				    "subdomain of zone name '%s'",
				    str, zname);
			return (ISC_R_FAILURE);
		}

		dns_name_toregion(nsname, &sregion);
		rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
		if (rdata == NULL)
			return (ISC_R_NOMEMORY);
		region.length = sregion.length;
		region.base = (unsigned char *)(rdata + 1);
		memcpy(region.base, sregion.base, region.length);
		dns_rdata_init(rdata);
		dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
				     dns_rdatatype_ns, &region);
		ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
	}

	return (result);
}
Ejemplo n.º 3
0
void
dns_badcache_flushtree(dns_badcache_t *bc, dns_name_t *name) {
	dns_bcentry_t *bad, *prev, *next;
	unsigned int i;
	int n;
	isc_time_t now;
	isc_result_t result;

	REQUIRE(VALID_BADCACHE(bc));
	REQUIRE(name != NULL);

	LOCK(&bc->lock);

	result = isc_time_now(&now);
	if (result != ISC_R_SUCCESS)
		isc_time_settoepoch(&now);

	for (i = 0; bc->count > 0 && i < bc->size; i++) {
		prev = NULL;
		for (bad = bc->table[i]; bad != NULL; bad = next) {
			next = bad->next;
			n = isc_time_compare(&bad->expire, &now);
			if (n < 0 || dns_name_issubdomain(&bad->name, name)) {
				if (prev == NULL)
					bc->table[i] = bad->next;
				else
					prev->next = bad->next;

				isc_mem_put(bc->mctx, bad, sizeof(*bad) +
					    bad->name.length);
				bc->count--;
			} else
				prev = bad;
		}
	}

	UNLOCK(&bc->lock);
}
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);
}
Ejemplo n.º 5
0
/**
 * Convert LDAP DN to absolute DNS names.
 *
 * @param[in]  dn     LDAP DN with one or two idnsName components at the
 *                    beginning.
 * @param[out] target Absolute DNS name derived from the first two idnsNames.
 * @param[out] origin Absolute DNS name derived from the last idnsName
 *                    component of DN, i.e. zone. Can be NULL.
 * @param[out] iszone ISC_TRUE if DN points to zone object, ISC_FALSE otherwise.
 *
 * @code
 * Examples:
 * dn = "idnsName=foo.bar, idnsName=example.org., cn=dns, dc=example, dc=org"
 * target = "foo.bar.example.org."
 * origin = "example.org."
 *
 * dn = "idnsname=89, idnsname=4.34.10.in-addr.arpa, cn=dns, dc=example, dc=org"
 * target = "89.4.34.10.in-addr.arpa."
 * origin = "4.34.10.in-addr.arpa."
 *
 * dn = "idnsname=third.test., idnsname=test., cn=dns, dc=example, dc=org"
 * target = "third.test."
 * origin = "test."
 * @endcode
 */
isc_result_t
dn_to_dnsname(isc_mem_t *mctx, const char *dn_str, dns_name_t *target,
	      dns_name_t *otarget, isc_boolean_t *iszone)
{
	LDAPDN dn = NULL;
	LDAPRDN rdn = NULL;
	LDAPAVA *attr = NULL;
	int idx;
	int ret;

	DECLARE_BUFFERED_NAME(name);
	DECLARE_BUFFERED_NAME(origin);
	isc_buffer_t name_buf;
	isc_buffer_t origin_buf;
	isc_result_t result;

	REQUIRE(dn_str != NULL);
	REQUIRE(target != NULL);

	INIT_BUFFERED_NAME(name);
	INIT_BUFFERED_NAME(origin);
	isc_buffer_initnull(&name_buf);
	isc_buffer_initnull(&origin_buf);

	/* Example DN: cn=a+sn=b, ou=people */

	ret = ldap_str2dn(dn_str, &dn, LDAP_DN_FORMAT_LDAPV3);
	if (ret != LDAP_SUCCESS || dn == NULL) {
		log_bug("ldap_str2dn failed: %u", ret);
		CLEANUP_WITH(ISC_R_UNEXPECTED);
	}

	/* iterate over DN components: e.g. cn=a+sn=b */
	for (idx = 0; dn[idx] != NULL; idx++) {
		rdn = dn[idx];

		/* "iterate" over RDN components: e.g. cn=a */
		INSIST(rdn[0] != NULL); /* RDN without (attr=value)?! */
		if (rdn[1] != NULL) {
			log_bug("multi-valued RDNs are not supported");
			CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
		}

		/* attribute in current RDN component */
		attr = rdn[0];
		if ((attr->la_flags & LDAP_AVA_STRING) == 0) {
			log_error("non-string attribute detected: position %u",
				  idx);
			CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
		}

		if (strncasecmp("idnsName", attr->la_attr.bv_val,
				attr->la_attr.bv_len) == 0) {
			if (idx == 0) {
				isc_buffer_init(&name_buf,
						attr->la_value.bv_val,
						attr->la_value.bv_len);
				isc_buffer_add(&name_buf,
					       attr->la_value.bv_len);
			} else if (idx == 1) {
				isc_buffer_init(&origin_buf,
						attr->la_value.bv_val,
						attr->la_value.bv_len);
				isc_buffer_add(&origin_buf,
					       attr->la_value.bv_len);
			} else { /* more than two idnsNames?! */
				break;
			}
		} else { /* no match - idx holds position */
			break;
		}
	}

	/* filter out unsupported cases */
	if (idx <= 0) {
		log_error("no idnsName component found in DN");
		CLEANUP_WITH(ISC_R_UNEXPECTEDEND);
	} else if (idx == 1) { /* zone only */
		if (iszone != NULL)
			*iszone = ISC_TRUE;
		CHECK(dns_name_copy(dns_rootname, &origin, NULL));
		CHECK(dns_name_fromtext(&name, &name_buf, dns_rootname, 0, NULL));
	} else if (idx == 2) { /* owner and zone */
		if (iszone != NULL)
			*iszone = ISC_FALSE;
		CHECK(dns_name_fromtext(&origin, &origin_buf, dns_rootname, 0,
					NULL));
		CHECK(dns_name_fromtext(&name, &name_buf, &origin, 0, NULL));
		if (dns_name_issubdomain(&name, &origin) == ISC_FALSE) {
			log_error("out-of-zone data: first idnsName is not a "
				  "subdomain of the other");
			CLEANUP_WITH(DNS_R_BADOWNERNAME);
		} else if (dns_name_equal(&name, &origin) == ISC_TRUE) {
			log_error("attempt to redefine zone apex: first "
				  "idnsName equals to zone name");
			CLEANUP_WITH(DNS_R_BADOWNERNAME);
		}
	} else {
		log_error("unsupported number of idnsName components in DN: "
			  "%u components found", idx);
		CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
	}

cleanup:
	if (result == ISC_R_SUCCESS)
		result = dns_name_dupwithoffsets(&name, mctx, target);
	else
		log_error_r("failed to convert DN '%s' to DNS name", dn_str);

	if (result == ISC_R_SUCCESS && otarget != NULL)
		result = dns_name_dupwithoffsets(&origin, mctx, otarget);

	if (result != ISC_R_SUCCESS) {
		if (dns_name_dynamic(target))
			dns_name_free(target, mctx);
		if (otarget) {
			if (dns_name_dynamic(otarget))
				dns_name_free(otarget, mctx);
		}
	}

	if (dn != NULL)
		ldap_dnfree(dn);

	return result;
}
Ejemplo n.º 6
0
/*%
 * Return ISC_R_SUCCESS if we can determine that the name doesn't exist
 * or we can determine whether there is data or not at the name.
 * If the name does not exist return the wildcard name.
 *
 * Return ISC_R_IGNORE when the NSEC is not the appropriate one.
 */
isc_result_t
dns_nsec_noexistnodata(dns_rdatatype_t type, dns_name_t *name,
		       dns_name_t *nsecname, dns_rdataset_t *nsecset,
		       isc_boolean_t *exists, isc_boolean_t *data,
		       dns_name_t *wild, dns_nseclog_t logit, void *arg)
{
	int order;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	isc_result_t result;
	dns_namereln_t relation;
	unsigned int olabels, nlabels, labels;
	dns_rdata_nsec_t nsec;
	isc_boolean_t atparent;
	isc_boolean_t ns;
	isc_boolean_t soa;

	REQUIRE(exists != NULL);
	REQUIRE(data != NULL);
	REQUIRE(nsecset != NULL &&
		nsecset->type == dns_rdatatype_nsec);

	result = dns_rdataset_first(nsecset);
	if (result != ISC_R_SUCCESS) {
		(*logit)(arg, ISC_LOG_DEBUG(3), "failure processing NSEC set");
		return (result);
	}
	dns_rdataset_current(nsecset, &rdata);

	(*logit)(arg, ISC_LOG_DEBUG(3), "looking for relevant NSEC");
	relation = dns_name_fullcompare(name, nsecname, &order, &olabels);

	if (order < 0) {
		/*
		 * The name is not within the NSEC range.
		 */
		(*logit)(arg, ISC_LOG_DEBUG(3),
			      "NSEC does not cover name, before NSEC");
		return (ISC_R_IGNORE);
	}

	if (order == 0) {
		/*
		 * The names are the same.   If we are validating "."
		 * then atparent should not be set as there is no parent.
		 */
		atparent = (olabels != 1) && dns_rdatatype_atparent(type);
		ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
		soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa);
		if (ns && !soa) {
			if (!atparent) {
				/*
				 * This NSEC record is from somewhere higher in
				 * the DNS, and at the parent of a delegation.
				 * It can not be legitimately used here.
				 */
				(*logit)(arg, ISC_LOG_DEBUG(3),
					      "ignoring parent nsec");
				return (ISC_R_IGNORE);
			}
		} else if (atparent && ns && soa) {
			/*
			 * This NSEC record is from the child.
			 * It can not be legitimately used here.
			 */
			(*logit)(arg, ISC_LOG_DEBUG(3),
				      "ignoring child nsec");
			return (ISC_R_IGNORE);
		}
		if (type == dns_rdatatype_cname || type == dns_rdatatype_nxt ||
		    type == dns_rdatatype_nsec || type == dns_rdatatype_key ||
		    !dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) {
			*exists = ISC_TRUE;
			*data = dns_nsec_typepresent(&rdata, type);
			(*logit)(arg, ISC_LOG_DEBUG(3),
				      "nsec proves name exists (owner) data=%d",
				      *data);
			return (ISC_R_SUCCESS);
		}
		(*logit)(arg, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists");
		return (ISC_R_IGNORE);
	}

	if (relation == dns_namereln_subdomain &&
	    dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
	    !dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
	{
		/*
		 * This NSEC record is from somewhere higher in
		 * the DNS, and at the parent of a delegation.
		 * It can not be legitimately used here.
		 */
		(*logit)(arg, ISC_LOG_DEBUG(3), "ignoring parent nsec");
		return (ISC_R_IGNORE);
	}

	result = dns_rdata_tostruct(&rdata, &nsec, NULL);
	if (result != ISC_R_SUCCESS)
		return (result);
	relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels);
	if (order == 0) {
		dns_rdata_freestruct(&nsec);
		(*logit)(arg, ISC_LOG_DEBUG(3),
			      "ignoring nsec matches next name");
		return (ISC_R_IGNORE);
	}

	if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) {
		/*
		 * The name is not within the NSEC range.
		 */
		dns_rdata_freestruct(&nsec);
		(*logit)(arg, ISC_LOG_DEBUG(3),
			    "ignoring nsec because name is past end of range");
		return (ISC_R_IGNORE);
	}

	if (order > 0 && relation == dns_namereln_subdomain) {
		(*logit)(arg, ISC_LOG_DEBUG(3),
			      "nsec proves name exist (empty)");
		dns_rdata_freestruct(&nsec);
		*exists = ISC_TRUE;
		*data = ISC_FALSE;
		return (ISC_R_SUCCESS);
	}
	if (wild != NULL) {
		dns_name_t common;
		dns_name_init(&common, NULL);
		if (olabels > nlabels) {
			labels = dns_name_countlabels(nsecname);
			dns_name_getlabelsequence(nsecname, labels - olabels,
						  olabels, &common);
		} else {
			labels = dns_name_countlabels(&nsec.next);
			dns_name_getlabelsequence(&nsec.next, labels - nlabels,
						  nlabels, &common);
		}
		result = dns_name_concatenate(dns_wildcardname, &common,
					      wild, NULL);
		if (result != ISC_R_SUCCESS) {
			dns_rdata_freestruct(&nsec);
			(*logit)(arg, ISC_LOG_DEBUG(3),
				    "failure generating wildcard name");
			return (result);
		}
	}
	dns_rdata_freestruct(&nsec);
	(*logit)(arg, ISC_LOG_DEBUG(3), "nsec range ok");
	*exists = ISC_FALSE;
	return (ISC_R_SUCCESS);
}