diff --git a/CHANGES b/CHANGES index 932f42f79c..cb6c92dcab 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +3445. [bug] Reject zone files with blank owner names immediately + after $ORIGIN directives. [RT #31848] + 3444. [bug] The NOQNAME proof was not being returned from cached insecure responses. [RT #21409] diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h index 18c49ba8a0..90ac111108 100644 --- a/lib/dns/include/dns/result.h +++ b/lib/dns/include/dns/result.h @@ -152,8 +152,9 @@ #define DNS_R_BROKENCHAIN (ISC_RESULTCLASS_DNS + 106) #define DNS_R_EXPIRED (ISC_RESULTCLASS_DNS + 107) #define DNS_R_NOTDYNAMIC (ISC_RESULTCLASS_DNS + 108) +#define DNS_R_UNSAFENAME (ISC_RESULTCLASS_DNS + 109) -#define DNS_R_NRESULTS 109 /*%< Number of results */ +#define DNS_R_NRESULTS 110 /*%< Number of results */ /* * DNS wire format rcodes. diff --git a/lib/dns/master.c b/lib/dns/master.c index 46867dcc5b..e701549acd 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -160,6 +160,7 @@ struct dns_incctx { int glue_in_use; int current_in_use; int origin_in_use; + isc_boolean_t origin_changed; isc_boolean_t drop; unsigned int glue_line; unsigned int current_line; @@ -1406,6 +1407,7 @@ load_text(dns_loadctx_t *lctx) { ictx->origin_in_use = new_in_use; ictx->in_use[ictx->origin_in_use] = ISC_TRUE; ictx->origin = new_name; + ictx->origin_changed = ISC_TRUE; finish_origin = ISC_FALSE; EXPECTEOL; continue; @@ -1578,8 +1580,31 @@ load_text(dns_loadctx_t *lctx) { } else if (result != ISC_R_SUCCESS) goto insist_and_cleanup; } + + if (ictx->origin_changed) { + char cbuf[DNS_NAME_FORMATSIZE]; + char obuf[DNS_NAME_FORMATSIZE]; + dns_name_format(ictx->current, cbuf, + sizeof(cbuf)); + dns_name_format(ictx->origin, obuf, + sizeof(obuf)); + (*callbacks->error)(callbacks, + "%s:%lu: record with inherited " + "owner (%s) immediately after " + "$ORIGIN (%s)", source, line, + cbuf, obuf); + result = DNS_R_UNSAFENAME; + if (MANYERRS(lctx, result)) { + SETRESULT(lctx, result); + read_till_eol = ISC_TRUE; + continue; + } else if (result != ISC_R_SUCCESS) + goto insist_and_cleanup; + } } + ictx->origin_changed = ISC_FALSE; + if (dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion) == ISC_R_SUCCESS) diff --git a/lib/dns/result.c b/lib/dns/result.c index 192ea06b89..31d5ef3642 100644 --- a/lib/dns/result.c +++ b/lib/dns/result.c @@ -160,8 +160,9 @@ static const char *text[DNS_R_NRESULTS] = { "not master", /*%< 105 DNS_R_NOTMASTER */ "broken trust chain", /*%< 106 DNS_R_BROKENCHAIN */ - "expired", /*%< 106 DNS_R_EXPIRED */ - "not dynamic", /*%< 107 DNS_R_NOTDYNAMIC */ + "expired", /*%< 107 DNS_R_EXPIRED */ + "not dynamic", /*%< 108 DNS_R_NOTDYNAMIC */ + "unsafe name", /*%< 109 DNS_R_UNSAFENAME */ }; static const char *rcode_text[DNS_R_NRCODERESULTS] = { diff --git a/lib/dns/tests/master_test.c b/lib/dns/tests/master_test.c index 093e930a68..86a5142869 100644 --- a/lib/dns/tests/master_test.c +++ b/lib/dns/tests/master_test.c @@ -622,6 +622,29 @@ ATF_TC_BODY(dumpraw, tc) { dns_test_end(); } +/* Origin change test */ +ATF_TC(neworigin); +ATF_TC_HEAD(neworigin, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() rejects " + "zones with inherited name following " + "$ORIGIN"); +} +ATF_TC_BODY(neworigin, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_FALSE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + setup_master(); + result = test_master("testdata/master/master17.data", + dns_masterformat_text); + ATF_REQUIRE_EQ(result, DNS_R_UNSAFENAME); + + dns_test_end(); +} + /* * Main */ @@ -643,6 +666,7 @@ ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, dumpraw); ATF_TP_ADD_TC(tp, toobig); ATF_TP_ADD_TC(tp, maxrdata); + ATF_TP_ADD_TC(tp, neworigin); return (atf_no_error()); } diff --git a/lib/dns/tests/testdata/master/master17.data b/lib/dns/tests/testdata/master/master17.data new file mode 100644 index 0000000000..4b2b63d253 --- /dev/null +++ b/lib/dns/tests/testdata/master/master17.data @@ -0,0 +1,14 @@ +$ORIGIN test. +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.test. + in ns ns2.test. + in ns ns3.test. +b in a 1.2.3.4 +$ORIGIN sub.test. + in a 4.3.2.1