}
}
+static void
+badowner(int level, const dns_name_t *name) {
+ /*
+ * bin/tests/system/rpz/tests.sh looks for "invalid rpz".
+ */
+ if (level < DNS_RPZ_DEBUG_QUIET && isc_log_wouldlog(level)) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ isc_log_write(DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RPZ, level,
+ "invalid rpz owner name \"%s\"; "
+ "not within the policy zone",
+ namebuf);
+ }
+}
+
/*
* Convert an IP address from radix tree binary (host byte order) to
* to its canonical response policy domain name without the origin of the
* Get trigger name and data bits for adding or deleting summary NSDNAME
* or QNAME data.
*/
-static void
-name2data(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
+static isc_result_t
+name2data(int log_level, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
const dns_name_t *src_name, dns_name_t *trig_name,
nmdata_t *new_data) {
+ const dns_name_t *suffix = NULL;
dns_name_t tmp_name;
- unsigned int prefix_len, n;
+ unsigned int prefix_len, nlabels;
REQUIRE(rpz != NULL);
REQUIRE(rpz->rpzs != NULL && rpz->num < rpz->rpzs->p.num_zones);
+ if (rpz_type == DNS_RPZ_TYPE_QNAME) {
+ suffix = &rpz->origin;
+ } else {
+ suffix = &rpz->nsdname;
+ }
+
+ /*
+ * A zone transfer can carry records whose owner name lies outside the
+ * zone, and a secondary keeps them when it reloads its own copy of the
+ * zone. We are about to strip 'suffix' off the owner name, so require
+ * that it is really there, the way dns_catz_update_process() does
+ * before splitting a catalog zone entry.
+ */
+ if (!dns_name_issubdomain(src_name, suffix)) {
+ badowner(log_level, src_name);
+ return ISC_R_FAILURE;
+ }
+
+ nlabels = dns_name_countlabels(src_name) - dns_name_countlabels(suffix);
+
/*
* Handle wildcards by putting only the parent into the
* summary database. The database only causes a check of the
* real policy zone where wildcards will be handled.
+ *
+ * The "*" label is one of the labels we are keeping, so there has to
+ * be one to spare; a policy zone whose own origin is a wildcard has
+ * none at its apex.
*/
- if (dns_name_iswildcard(src_name)) {
+ if (nlabels > 0 && dns_name_iswildcard(src_name)) {
prefix_len = 1;
memset(&new_data->set, 0, sizeof(new_data->set));
make_nm_set(&new_data->wild, rpz->num, rpz_type);
}
dns_name_init(&tmp_name);
- n = dns_name_countlabels(src_name);
- n -= prefix_len;
- if (rpz_type == DNS_RPZ_TYPE_QNAME) {
- n -= dns_name_countlabels(&rpz->origin);
- } else {
- n -= dns_name_countlabels(&rpz->nsdname);
- }
- dns_name_getlabelsequence(src_name, prefix_len, n, &tmp_name);
+ dns_name_getlabelsequence(src_name, prefix_len, nlabels - prefix_len,
+ &tmp_name);
(void)dns_name_concatenate(&tmp_name, dns_rootname, trig_name);
+
+ return ISC_R_SUCCESS;
}
/*
static isc_result_t
add_name(dns_rpz_zone_t *rpz, dns_qp_t *qp, dns_rpz_type_t rpz_type,
- const dns_name_t *src_name) {
+ const dns_name_t *src_name, bool fail) {
nmdata_t new_data;
dns_fixedname_t trig_namef;
dns_name_t *trig_name = NULL;
*/
trig_name = dns_fixedname_initname(&trig_namef);
- name2data(rpz, rpz_type, src_name, trig_name, &new_data);
+ result = name2data(DNS_RPZ_ERROR_LEVEL, rpz, rpz_type, src_name,
+ trig_name, &new_data);
+ /*
+ * Log complaints about bad owner names but let the zone load.
+ */
+ if (result != ISC_R_SUCCESS) {
+ return fail ? result : ISC_R_SUCCESS;
+ }
result = add_nm(rpz->rpzs, qp, trig_name, &new_data);
switch (rpz_type) {
case DNS_RPZ_TYPE_QNAME:
case DNS_RPZ_TYPE_NSDNAME:
- result = add_name(rpz, qp, rpz_type, src_name);
+ result = add_name(rpz, qp, rpz_type, src_name, fail);
break;
case DNS_RPZ_TYPE_CLIENT_IP:
case DNS_RPZ_TYPE_IP:
*/
trig_name = dns_fixedname_initname(&trig_namef);
- name2data(rpz, rpz_type, src_name, trig_name, &del_data);
+ /*
+ * Do not worry about invalid rpz owner names. If we are here, then
+ * something relevant was added and so was valid.
+ */
+ result = name2data(DNS_RPZ_DEBUG_QUIET, rpz, rpz_type, src_name,
+ trig_name, &del_data);
+ if (result != ISC_R_SUCCESS) {
+ return;
+ }
result = dns_qp_getname(qp, trig_name, DNS_DBNAMESPACE_NORMAL,
(void **)&data, NULL);