Esempio n. 1
0
static isc_boolean_t
checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
#ifdef USE_GETADDRINFO
	struct addrinfo hints, *ai, *cur;
	char namebuf[DNS_NAME_FORMATSIZE + 1];
	char ownerbuf[DNS_NAME_FORMATSIZE];
	int result;
	int level = ISC_LOG_ERROR;
	isc_boolean_t answer = ISC_TRUE;

	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = AI_CANONNAME;
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	dns_name_format(name, namebuf, sizeof(namebuf) - 1);
	/*
	 * Turn off search.
	 */
	if (dns_name_countlabels(name) > 1U)
		strcat(namebuf, ".");
	dns_name_format(owner, ownerbuf, sizeof(ownerbuf));

	result = getaddrinfo(namebuf, NULL, &hints, &ai);
	dns_name_format(name, namebuf, sizeof(namebuf) - 1);
	switch (result) {
	case 0:
		/*
		 * Work around broken getaddrinfo() implementations that
		 * fail to set ai_canonname on first entry.
		 */
		cur = ai;
		while (cur != NULL && cur->ai_canonname == NULL &&
		       cur->ai_next != NULL)
			cur = cur->ai_next;
		if (cur != NULL && cur->ai_canonname != NULL &&
		    strcasecmp(cur->ai_canonname, namebuf) != 0) {
			if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0)
				level = ISC_LOG_WARNING;
			if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) {
				if (!logged(namebuf, ERR_IS_SRVCNAME)) {
					dns_zone_log(zone, level, "%s/SRV '%s'"
						     " (out of zone) is a "
						     "CNAME '%s' (illegal)",
						     ownerbuf, namebuf,
						     cur->ai_canonname);
					add(namebuf, ERR_IS_SRVCNAME);
				}
				if (level == ISC_LOG_ERROR)
					answer = ISC_FALSE;
			}
		}
		freeaddrinfo(ai);
		return (answer);

	case EAI_NONAME:
#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
	case EAI_NODATA:
#endif
		if (!logged(namebuf, ERR_NO_ADDRESSES)) {
			dns_zone_log(zone, ISC_LOG_ERROR,
				     "%s/SRV '%s' (out of zone) "
				     "has no addresses records (A or AAAA)",
				     ownerbuf, namebuf);
			add(namebuf, ERR_NO_ADDRESSES);
		}
		/* XXX950 make fatal for 9.5.0. */
		return (ISC_TRUE);

	default:
		if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
			dns_zone_log(zone, ISC_LOG_WARNING,
				     "getaddrinfo(%s) failed: %s",
				     namebuf, gai_strerror(result));
			add(namebuf, ERR_LOOKUP_FAILURE);
		}
		return (ISC_TRUE);
	}
#else
	return (ISC_TRUE);
#endif
}
Esempio n. 2
0
/*% scan the zone for oversize TTLs */
static isc_result_t
check_ttls(dns_zone_t *zone, dns_ttl_t maxttl) {
	isc_result_t result;
	dns_db_t *db = NULL;
	dns_dbversion_t *version = NULL;
	dns_dbnode_t *node = NULL;
	dns_dbiterator_t *dbiter = NULL;
	dns_rdatasetiter_t *rdsiter = NULL;
	dns_rdataset_t rdataset;
	dns_fixedname_t fname;
	dns_name_t *name;
	dns_fixedname_init(&fname);
	name = dns_fixedname_name(&fname);
	dns_rdataset_init(&rdataset);

	CHECK(dns_zone_getdb(zone, &db));
	INSIST(db != NULL);

	CHECK(dns_db_newversion(db, &version));
	CHECK(dns_db_createiterator(db, 0, &dbiter));

	for (result = dns_dbiterator_first(dbiter);
	     result == ISC_R_SUCCESS;
	     result = dns_dbiterator_next(dbiter)) {
		result = dns_dbiterator_current(dbiter, &node, name);
		if (result == DNS_R_NEWORIGIN)
			result = ISC_R_SUCCESS;
		CHECK(result);

		CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsiter));
		for (result = dns_rdatasetiter_first(rdsiter);
		     result == ISC_R_SUCCESS;
		     result = dns_rdatasetiter_next(rdsiter)) {
			dns_rdatasetiter_current(rdsiter, &rdataset);
			if (rdataset.ttl > maxttl) {
				char nbuf[DNS_NAME_FORMATSIZE];
				char tbuf[255];
				isc_buffer_t b;
				isc_region_t r;

				dns_name_format(name, nbuf, sizeof(nbuf));
				isc_buffer_init(&b, tbuf, sizeof(tbuf) - 1);
				CHECK(dns_rdatatype_totext(rdataset.type, &b));
				isc_buffer_usedregion(&b, &r);
				r.base[r.length] = 0;

				dns_zone_log(zone, ISC_LOG_ERROR,
					     "%s/%s TTL %d exceeds "
					     "maximum TTL %d",
					     nbuf, tbuf, rdataset.ttl, maxttl);
				dns_rdataset_disassociate(&rdataset);
				CHECK(ISC_R_RANGE);
			}
			dns_rdataset_disassociate(&rdataset);
		}
		if (result == ISC_R_NOMORE)
			result = ISC_R_SUCCESS;
		CHECK(result);

		dns_rdatasetiter_destroy(&rdsiter);
		dns_db_detachnode(db, &node);
	}

	if (result == ISC_R_NOMORE)
		result = ISC_R_SUCCESS;

 cleanup:
	if (node != NULL)
		dns_db_detachnode(db, &node);
	if (rdsiter != NULL)
		dns_rdatasetiter_destroy(&rdsiter);
	if (dbiter != NULL)
		dns_dbiterator_destroy(&dbiter);
	if (version != NULL)
		dns_db_closeversion(db, &version, ISC_FALSE);
	if (db != NULL)
		dns_db_detach(&db);

	return (result);
}
Esempio n. 3
0
static isc_boolean_t
checkns(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner,
	dns_rdataset_t *a, dns_rdataset_t *aaaa)
{
#ifdef USE_GETADDRINFO
	dns_rdataset_t *rdataset;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	struct addrinfo hints, *ai, *cur;
	char namebuf[DNS_NAME_FORMATSIZE + 1];
	char ownerbuf[DNS_NAME_FORMATSIZE];
	char addrbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
	isc_boolean_t answer = ISC_TRUE;
	isc_boolean_t match;
	const char *type;
	void *ptr = NULL;
	int result;

	REQUIRE(a == NULL || !dns_rdataset_isassociated(a) ||
		a->type == dns_rdatatype_a);
	REQUIRE(aaaa == NULL || !dns_rdataset_isassociated(aaaa) ||
		aaaa->type == dns_rdatatype_aaaa);
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = AI_CANONNAME;
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	dns_name_format(name, namebuf, sizeof(namebuf) - 1);
	/*
	 * Turn off search.
	 */
	if (dns_name_countlabels(name) > 1U)
		strcat(namebuf, ".");
	dns_name_format(owner, ownerbuf, sizeof(ownerbuf));

	result = getaddrinfo(namebuf, NULL, &hints, &ai);
	dns_name_format(name, namebuf, sizeof(namebuf) - 1);
	switch (result) {
	case 0:
		/*
		 * Work around broken getaddrinfo() implementations that
		 * fail to set ai_canonname on first entry.
		 */
		cur = ai;
		while (cur != NULL && cur->ai_canonname == NULL &&
		       cur->ai_next != NULL)
			cur = cur->ai_next;
		if (cur != NULL && cur->ai_canonname != NULL &&
		    strcasecmp(cur->ai_canonname, namebuf) != 0 &&
		    !logged(namebuf, ERR_IS_CNAME)) {
			dns_zone_log(zone, ISC_LOG_ERROR,
				     "%s/NS '%s' (out of zone) "
				     "is a CNAME '%s' (illegal)",
				     ownerbuf, namebuf,
				     cur->ai_canonname);
			/* XXX950 make fatal for 9.5.0 */
			/* answer = ISC_FALSE; */
			add(namebuf, ERR_IS_CNAME);
		}
		break;
	case EAI_NONAME:
#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
	case EAI_NODATA:
#endif
		if (!logged(namebuf, ERR_NO_ADDRESSES)) {
			dns_zone_log(zone, ISC_LOG_ERROR,
				     "%s/NS '%s' (out of zone) "
				     "has no addresses records (A or AAAA)",
				     ownerbuf, namebuf);
			add(namebuf, ERR_NO_ADDRESSES);
		}
		/* XXX950 make fatal for 9.5.0 */
		return (ISC_TRUE);

	default:
		if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
			dns_zone_log(zone, ISC_LOG_WARNING,
				     "getaddrinfo(%s) failed: %s",
				     namebuf, gai_strerror(result));
			add(namebuf, ERR_LOOKUP_FAILURE);
		}
		return (ISC_TRUE);
	}
	if (a == NULL || aaaa == NULL)
		return (answer);
	/*
	 * Check that all glue records really exist.
	 */
	if (!dns_rdataset_isassociated(a))
		goto checkaaaa;
	result = dns_rdataset_first(a);
	while (result == ISC_R_SUCCESS) {
		dns_rdataset_current(a, &rdata);
		match = ISC_FALSE;
		for (cur = ai; cur != NULL; cur = cur->ai_next) {
			if (cur->ai_family != AF_INET)
				continue;
			ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
			if (memcmp(ptr, rdata.data, rdata.length) == 0) {
				match = ISC_TRUE;
				break;
			}
		}
		if (!match && !logged(namebuf, ERR_EXTRA_A)) {
			dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
				     "extra GLUE A record (%s)",
				     ownerbuf, namebuf,
				     inet_ntop(AF_INET, rdata.data,
					       addrbuf, sizeof(addrbuf)));
			add(namebuf, ERR_EXTRA_A);
			/* XXX950 make fatal for 9.5.0 */
			/* answer = ISC_FALSE; */
		}
		dns_rdata_reset(&rdata);
		result = dns_rdataset_next(a);
	}

 checkaaaa:
	if (!dns_rdataset_isassociated(aaaa))
		goto checkmissing;
	result = dns_rdataset_first(aaaa);
	while (result == ISC_R_SUCCESS) {
		dns_rdataset_current(aaaa, &rdata);
		match = ISC_FALSE;
		for (cur = ai; cur != NULL; cur = cur->ai_next) {
			if (cur->ai_family != AF_INET6)
				continue;
			ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
			if (memcmp(ptr, rdata.data, rdata.length) == 0) {
				match = ISC_TRUE;
				break;
			}
		}
		if (!match && !logged(namebuf, ERR_EXTRA_AAAA)) {
			dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
				     "extra GLUE AAAA record (%s)",
				     ownerbuf, namebuf,
				     inet_ntop(AF_INET6, rdata.data,
					       addrbuf, sizeof(addrbuf)));
			add(namebuf, ERR_EXTRA_AAAA);
			/* XXX950 make fatal for 9.5.0. */
			/* answer = ISC_FALSE; */
		}
		dns_rdata_reset(&rdata);
		result = dns_rdataset_next(aaaa);
	}

 checkmissing:
	/*
	 * Check that all addresses appear in the glue.
	 */
	if (!logged(namebuf, ERR_MISSING_GLUE)) {
		isc_boolean_t missing_glue = ISC_FALSE;
		for (cur = ai; cur != NULL; cur = cur->ai_next) {
			switch (cur->ai_family) {
			case AF_INET:
				rdataset = a;
				ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
				type = "A";
				break;
			case AF_INET6:
				rdataset = aaaa;
				ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
				type = "AAAA";
				break;
			default:
				 continue;
			}
			match = ISC_FALSE;
			if (dns_rdataset_isassociated(rdataset))
				result = dns_rdataset_first(rdataset);
			else
				result = ISC_R_FAILURE;
			while (result == ISC_R_SUCCESS && !match) {
				dns_rdataset_current(rdataset, &rdata);
				if (memcmp(ptr, rdata.data, rdata.length) == 0)
					match = ISC_TRUE;
				dns_rdata_reset(&rdata);
				result = dns_rdataset_next(rdataset);
			}
			if (!match) {
				dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
					     "missing GLUE %s record (%s)",
					     ownerbuf, namebuf, type,
					     inet_ntop(cur->ai_family, ptr,
						       addrbuf, sizeof(addrbuf)));
				/* XXX950 make fatal for 9.5.0. */
				/* answer = ISC_FALSE; */
				missing_glue = ISC_TRUE;
			}
		}
		if (missing_glue)
			add(namebuf, ERR_MISSING_GLUE);
	}
	freeaddrinfo(ai);
	return (answer);
#else
	return (ISC_TRUE);
#endif
}
Esempio n. 4
0
isc_result_t
acl_configure_zone_ssutable(const char *policy_str, dns_zone_t *zone)
{
	isc_result_t result = ISC_R_SUCCESS;
	cfg_parser_t *parser = NULL;
	const cfg_listelt_t *el;
	cfg_obj_t *policy = NULL;
	dns_ssutable_t *table = NULL;
	ld_string_t *new_policy_str = NULL;
	isc_mem_t *mctx;

	REQUIRE(zone != NULL);

	mctx = dns_zone_getmctx(zone);

	if (policy_str == NULL)
		goto cleanup;

	CHECK(bracket_str(mctx, policy_str, &new_policy_str));

	CHECK(cfg_parser_create(mctx, dns_lctx, &parser));
	result = cfg_parse_strbuf(parser, str_buf(new_policy_str), &cfg_type_update_policy, &policy);

	if (result != ISC_R_SUCCESS) {
		dns_zone_log(zone, ISC_LOG_ERROR,
			     "failed to parse policy string");
		goto cleanup;
	}

	CHECK(dns_ssutable_create(mctx, &table));

	for (el = cfg_list_first(policy); el != NULL; el = cfg_list_next(el)) {
		const cfg_obj_t *stmt;
		isc_boolean_t grant;
		unsigned int match_type;
		dns_fixedname_t fname, fident;
		dns_rdatatype_t *types;
		unsigned int n;

		types = NULL;

		stmt = cfg_listelt_value(el);
		CHECK(get_mode(stmt, &grant));
		CHECK(get_match_type(stmt, &match_type));

		CHECK(get_fixed_name(stmt, "identity", &fident));

		/* Use zone name for 'zonesub' match type */
		result = get_fixed_name(stmt, "name", &fname);
		if (result == ISC_R_NOTFOUND &&
		    match_type == DNS_SSUMATCHTYPE_SUBDOMAIN) {
			dns_fixedname_init(&fname);
			CHECK(dns_name_copy(dns_zone_getorigin(zone),
					    dns_fixedname_name(&fname),
					    &fname.buffer));
		}
		else if (result != ISC_R_SUCCESS)
			goto cleanup;

		CHECK(get_types(mctx, stmt, &types, &n));

		if (match_type == DNS_SSUMATCHTYPE_WILDCARD &&
		    !dns_name_iswildcard(dns_fixedname_name(&fname))) {
			char name[DNS_NAME_FORMATSIZE];
			dns_name_format(dns_fixedname_name(&fname), name,
					DNS_NAME_FORMATSIZE);
			dns_zone_log(zone, ISC_LOG_ERROR,
				     "invalid update policy: "
				     "name '%s' is expected to be a wildcard",
				     name);
			CLEANUP_WITH(DNS_R_BADNAME);
		}

		result = dns_ssutable_addrule(table, grant,
					      dns_fixedname_name(&fident),
					      match_type,
					      dns_fixedname_name(&fname),
					      n, types);

		SAFE_MEM_PUT(mctx, types, n * sizeof(dns_rdatatype_t));
		if (result != ISC_R_SUCCESS)
			goto cleanup;

	}

 cleanup:
	if (result == ISC_R_SUCCESS)
		dns_zone_setssutable(zone, table);

	str_destroy(&new_policy_str);
	if (policy != NULL)
		cfg_obj_destroy(parser, &policy);
	if (parser != NULL)
		cfg_parser_destroy(&parser);
	if (table != NULL)
		dns_ssutable_detach(&table);

	return result;
}