2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-02 07:35:26 +00:00

3964. [func] nsupdate now performs check-names processing.

[RT #36266]
This commit is contained in:
Mark Andrews
2014-10-02 09:35:43 +10:00
parent 7c1468ed50
commit ed1c845c1d
7 changed files with 109 additions and 1 deletions

View File

@@ -1,3 +1,6 @@
3964. [func] nsupdate now performs check-names processing.
[RT #36266]
3963. [test] Added NXRRSET test cases to the "dlzexternal" 3963. [test] Added NXRRSET test cases to the "dlzexternal"
system test. [RT #37344] system test. [RT #37344]

2
README
View File

@@ -97,6 +97,8 @@ BIND 9.11.0
- dig can now set yet-to-be-defined EDNS flags on requests (+ednsflags). - dig can now set yet-to-be-defined EDNS flags on requests (+ednsflags).
- serial-query-rate no longer covers NOTIFY messages. These are - serial-query-rate no longer covers NOTIFY messages. These are
separately controlled by notify-rate and startup-notify-rate. separately controlled by notify-rate and startup-notify-rate.
- nsupdate now performs check-names processing by default on records
to be added. This can be disabled with "check-names no".
This release addresses the security flaw described in This release addresses the security flaw described in
CVE-2014-3214 and CVE-2014-3859. CVE-2014-3214 and CVE-2014-3859.

View File

@@ -182,6 +182,7 @@ static dns_rdataclass_t zoneclass = dns_rdataclass_none;
static dns_message_t *answer = NULL; static dns_message_t *answer = NULL;
static isc_uint32_t default_ttl = 0; static isc_uint32_t default_ttl = 0;
static isc_boolean_t default_ttl_set = ISC_FALSE; static isc_boolean_t default_ttl_set = ISC_FALSE;
static isc_boolean_t checknames = ISC_TRUE;
typedef struct nsu_requestinfo { typedef struct nsu_requestinfo {
dns_message_t *msg; dns_message_t *msg;
@@ -1827,6 +1828,33 @@ update_addordelete(char *cmdline, isc_boolean_t isdelete) {
} }
} }
if (!isdelete && checknames) {
dns_fixedname_t fixed;
dns_name_t *bad;
if (!dns_rdata_checkowner(name, rdata->rdclass, rdata->type,
ISC_TRUE))
{
char namebuf[DNS_NAME_FORMATSIZE];
dns_name_format(name, namebuf, sizeof(namebuf));
fprintf(stderr, "check-names failed: bad owner '%s'\n",
namebuf);
goto failure;
}
dns_fixedname_init(&fixed);
bad = dns_fixedname_name(&fixed);
if (!dns_rdata_checknames(rdata, name, bad)) {
char namebuf[DNS_NAME_FORMATSIZE];
dns_name_format(bad, namebuf, sizeof(namebuf));
fprintf(stderr, "check-names failed: bad name '%s'\n",
namebuf);
goto failure;
}
}
doneparsing: doneparsing:
result = dns_message_gettemprdatalist(updatemsg, &rdatalist); result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
@@ -1878,6 +1906,31 @@ evaluate_update(char *cmdline) {
return (update_addordelete(cmdline, isdelete)); return (update_addordelete(cmdline, isdelete));
} }
static isc_uint16_t
evaluate_checknames(char *cmdline) {
char *word;
ddebug("evaluate_checknames()");
word = nsu_strsep(&cmdline, " \t\r\n");
if (word == NULL || *word == 0) {
fprintf(stderr, "could not read check-names directive\n");
return (STATUS_SYNTAX);
}
if (strcasecmp(word, "yes") == 0 ||
strcasecmp(word, "true") == 0 ||
strcasecmp(word, "on") == 0) {
checknames = ISC_TRUE;
} else if (strcasecmp(word, "no") == 0 ||
strcasecmp(word, "false") == 0 ||
strcasecmp(word, "off") == 0) {
checknames = ISC_FALSE;
} else {
fprintf(stderr, "incorrect check-names directive: %s\n", word);
return (STATUS_SYNTAX);
}
return (STATUS_MORE);
}
static void static void
setzone(dns_name_t *zonename) { setzone(dns_name_t *zonename) {
isc_result_t result; isc_result_t result;
@@ -2012,6 +2065,9 @@ do_next_command(char *cmdline) {
} }
if (strcasecmp(word, "realm") == 0) if (strcasecmp(word, "realm") == 0)
return (evaluate_realm(cmdline)); return (evaluate_realm(cmdline));
if (strcasecmp(word, "check-names") == 0 ||
strcasecmp(word, "checknames") == 0)
return (evaluate_checknames(cmdline));
if (strcasecmp(word, "gsstsig") == 0) { if (strcasecmp(word, "gsstsig") == 0) {
#ifdef GSSAPI #ifdef GSSAPI
usegsstsig = ISC_TRUE; usegsstsig = ISC_TRUE;
@@ -2045,6 +2101,7 @@ do_next_command(char *cmdline) {
"oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n" "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n"
"zone name (set the zone to be updated)\n" "zone name (set the zone to be updated)\n"
"class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n" "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
"check-names { on | off } (enable / disable check-names)\n"
"[prereq] nxdomain name (does this name not exist)\n" "[prereq] nxdomain name (does this name not exist)\n"
"[prereq] yxdomain name (does this name exist)\n" "[prereq] yxdomain name (does this name exist)\n"
"[prereq] nxrrset .... (does this RRset exist)\n" "[prereq] nxrrset .... (does this RRset exist)\n"

View File

@@ -455,6 +455,22 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>
<command>check-names</command>
<arg choice="req"><optional>yes_or_no</optional></arg>
</term>
<listitem>
<para>
Turn on or off check-names processing on records to
be added. Check-names has no effect on prerequisites
or records to be deleted. By default check-names
processing is on. If check-names processing fails
the record will not be added to the UPDATE message.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<command><optional>prereq</optional> nxdomain</command> <command><optional>prereq</optional> nxdomain</command>

View File

@@ -89,6 +89,7 @@ echo "I: check that updates to 'check-names fail;' are rejected ($n)"
ret=0 ret=0
not=1 not=1
$NSUPDATE -d <<END> nsupdate.out.test$n 2>&1 || not=0 $NSUPDATE -d <<END> nsupdate.out.test$n 2>&1 || not=0
check-names off
server 10.53.0.1 5300 server 10.53.0.1 5300
update add xxx_xxx.fail.update. 600 A 10.10.10.1 update add xxx_xxx.fail.update. 600 A 10.10.10.1
send send
@@ -104,6 +105,7 @@ n=`expr $n + 1`
echo "I: check that updates to 'check-names warn;' succeed and are logged ($n)" echo "I: check that updates to 'check-names warn;' succeed and are logged ($n)"
ret=0 ret=0
$NSUPDATE -d <<END> nsupdate.out.test$n 2>&1|| ret=1 $NSUPDATE -d <<END> nsupdate.out.test$n 2>&1|| ret=1
check-names off
server 10.53.0.1 5300 server 10.53.0.1 5300
update add xxx_xxx.warn.update. 600 A 10.10.10.1 update add xxx_xxx.warn.update. 600 A 10.10.10.1
send send
@@ -119,6 +121,7 @@ echo "I: check that updates to 'check-names ignore;' succeed and are not logged
ret=0 ret=0
not=1 not=1
$NSUPDATE -d <<END> nsupdate.out.test$n 2>&1 || ret=1 $NSUPDATE -d <<END> nsupdate.out.test$n 2>&1 || ret=1
check-names off
server 10.53.0.1 5300 server 10.53.0.1 5300
update add xxx_xxx.ignore.update. 600 A 10.10.10.1 update add xxx_xxx.ignore.update. 600 A 10.10.10.1
send send
@@ -135,6 +138,7 @@ echo "I: check that updates to 'check-names master ignore;' succeed and are not
ret=0 ret=0
not=1 not=1
$NSUPDATE -d <<END> nsupdate.out.test$n 2>&1 || ret=1 $NSUPDATE -d <<END> nsupdate.out.test$n 2>&1 || ret=1
check-names off
server 10.53.0.4 5300 server 10.53.0.4 5300
update add xxx_xxx.master-ignore.update. 600 A 10.10.10.1 update add xxx_xxx.master-ignore.update. 600 A 10.10.10.1
send send

View File

@@ -629,5 +629,32 @@ test ${lines:-0} -eq 64 || ret=1
[ $ret = 0 ] || { echo I:failed; status=1; } [ $ret = 0 ] || { echo I:failed; status=1; }
fi fi
n=`expr $n + 1`
echo "I:check check-names processing ($n)"
ret=0
$NSUPDATE << EOF > nsupdate.out1-$n 2>&1
update add # 0 in a 1.2.3.4
EOF
grep "bad owner" nsupdate.out1-$n > /dev/null || ret=1
$NSUPDATE << EOF > nsupdate.out2-$n 2>&1
check-names off
update add # 0 in a 1.2.3.4
EOF
grep "bad owner" nsupdate.out2-$n > /dev/null && ret=1
$NSUPDATE << EOF > nsupdate.out3-$n 2>&1
update add . 0 in mx 0 #
EOF
grep "bad name" nsupdate.out3-$n > /dev/null || ret=1
$NSUPDATE << EOF > nsupdate.out4-$n 2>&1
check-names off
update add . 0 in mx 0 #
EOF
grep "bad name" nsupdate.out4-$n > /dev/null && ret=1
[ $ret = 0 ] || { echo I:failed; status=1; }
echo "I:exit status: $status" echo "I:exit status: $status"
exit $status exit $status

View File

@@ -1833,7 +1833,6 @@ load_text(dns_loadctx_t *lctx) {
goto insist_and_cleanup; goto insist_and_cleanup;
} }
if (type == dns_rdatatype_rrsig || if (type == dns_rdatatype_rrsig ||
type == dns_rdatatype_sig) type == dns_rdatatype_sig)
covers = dns_rdata_covers(&rdata[rdcount]); covers = dns_rdata_covers(&rdata[rdcount]);