[master] Prevent nsupdate from immediately exiting on invalid user input in interactive mode
4683. [bug] Prevent nsupdate from immediately exiting on invalid user input in interactive mode. [RT #28194]
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -1,3 +1,6 @@
|
||||
4683. [bug] Prevent nsupdate from immediately exiting on invalid
|
||||
user input in interactive mode. [RT #28194]
|
||||
|
||||
4682. [bug] Don't report errors on records below a DNAME.
|
||||
[RT #44880]
|
||||
|
||||
|
||||
@@ -450,8 +450,10 @@ reset_system(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static isc_uint16_t
|
||||
parse_hmac(const dns_name_t **hmac, const char *hmacstr, size_t len) {
|
||||
static isc_boolean_t
|
||||
parse_hmac(const dns_name_t **hmac, const char *hmacstr, size_t len,
|
||||
isc_uint16_t *digestbitsp)
|
||||
{
|
||||
isc_uint16_t digestbits = 0;
|
||||
isc_result_t result;
|
||||
char buf[20];
|
||||
@@ -459,8 +461,10 @@ parse_hmac(const dns_name_t **hmac, const char *hmacstr, size_t len) {
|
||||
REQUIRE(hmac != NULL && *hmac == NULL);
|
||||
REQUIRE(hmacstr != NULL);
|
||||
|
||||
if (len >= sizeof(buf))
|
||||
fatal("unknown key type '%.*s'", (int)(len), hmacstr);
|
||||
if (len >= sizeof(buf)) {
|
||||
error("unknown key type '%.*s'", (int)(len), hmacstr);
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
strncpy(buf, hmacstr, len);
|
||||
buf[len] = 0;
|
||||
@@ -471,9 +475,11 @@ parse_hmac(const dns_name_t **hmac, const char *hmacstr, size_t len) {
|
||||
} else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
|
||||
*hmac = DNS_TSIG_HMACMD5_NAME;
|
||||
result = isc_parse_uint16(&digestbits, &buf[9], 10);
|
||||
if (result != ISC_R_SUCCESS || digestbits > 128)
|
||||
fatal("digest-bits out of range [0..128]");
|
||||
digestbits = (digestbits +7) & ~0x7U;
|
||||
if (result != ISC_R_SUCCESS || digestbits > 128) {
|
||||
error("digest-bits out of range [0..128]");
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
*digestbitsp = (digestbits + 7) & ~0x7U;
|
||||
} else
|
||||
#endif
|
||||
if (strcasecmp(buf, "hmac-sha1") == 0) {
|
||||
@@ -481,44 +487,56 @@ parse_hmac(const dns_name_t **hmac, const char *hmacstr, size_t len) {
|
||||
} else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
|
||||
*hmac = DNS_TSIG_HMACSHA1_NAME;
|
||||
result = isc_parse_uint16(&digestbits, &buf[10], 10);
|
||||
if (result != ISC_R_SUCCESS || digestbits > 160)
|
||||
fatal("digest-bits out of range [0..160]");
|
||||
digestbits = (digestbits +7) & ~0x7U;
|
||||
if (result != ISC_R_SUCCESS || digestbits > 160) {
|
||||
error("digest-bits out of range [0..160]");
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
*digestbitsp = (digestbits + 7) & ~0x7U;
|
||||
} else if (strcasecmp(buf, "hmac-sha224") == 0) {
|
||||
*hmac = DNS_TSIG_HMACSHA224_NAME;
|
||||
} else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
|
||||
*hmac = DNS_TSIG_HMACSHA224_NAME;
|
||||
result = isc_parse_uint16(&digestbits, &buf[12], 10);
|
||||
if (result != ISC_R_SUCCESS || digestbits > 224)
|
||||
fatal("digest-bits out of range [0..224]");
|
||||
digestbits = (digestbits +7) & ~0x7U;
|
||||
if (result != ISC_R_SUCCESS || digestbits > 224) {
|
||||
error("digest-bits out of range [0..224]");
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
*digestbitsp = (digestbits + 7) & ~0x7U;
|
||||
} else if (strcasecmp(buf, "hmac-sha256") == 0) {
|
||||
*hmac = DNS_TSIG_HMACSHA256_NAME;
|
||||
} else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
|
||||
*hmac = DNS_TSIG_HMACSHA256_NAME;
|
||||
result = isc_parse_uint16(&digestbits, &buf[12], 10);
|
||||
if (result != ISC_R_SUCCESS || digestbits > 256)
|
||||
fatal("digest-bits out of range [0..256]");
|
||||
digestbits = (digestbits +7) & ~0x7U;
|
||||
if (result != ISC_R_SUCCESS || digestbits > 256) {
|
||||
error("digest-bits out of range [0..256]");
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
*digestbitsp = (digestbits + 7) & ~0x7U;
|
||||
} else if (strcasecmp(buf, "hmac-sha384") == 0) {
|
||||
*hmac = DNS_TSIG_HMACSHA384_NAME;
|
||||
} else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
|
||||
*hmac = DNS_TSIG_HMACSHA384_NAME;
|
||||
result = isc_parse_uint16(&digestbits, &buf[12], 10);
|
||||
if (result != ISC_R_SUCCESS || digestbits > 384)
|
||||
fatal("digest-bits out of range [0..384]");
|
||||
digestbits = (digestbits +7) & ~0x7U;
|
||||
if (result != ISC_R_SUCCESS || digestbits > 384) {
|
||||
error("digest-bits out of range [0..384]");
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
*digestbitsp = (digestbits + 7) & ~0x7U;
|
||||
} else if (strcasecmp(buf, "hmac-sha512") == 0) {
|
||||
*hmac = DNS_TSIG_HMACSHA512_NAME;
|
||||
} else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
|
||||
*hmac = DNS_TSIG_HMACSHA512_NAME;
|
||||
result = isc_parse_uint16(&digestbits, &buf[12], 10);
|
||||
if (result != ISC_R_SUCCESS || digestbits > 512)
|
||||
fatal("digest-bits out of range [0..512]");
|
||||
digestbits = (digestbits +7) & ~0x7U;
|
||||
} else
|
||||
fatal("unknown key type '%s'", buf);
|
||||
return (digestbits);
|
||||
if (result != ISC_R_SUCCESS || digestbits > 512) {
|
||||
error("digest-bits out of range [0..512]");
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
*digestbitsp = (digestbits + 7) & ~0x7U;
|
||||
} else {
|
||||
error("unknown key type '%s'", buf);
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -564,7 +582,9 @@ setup_keystr(void) {
|
||||
fatal("key option must specify [hmac:]keyname:secret");
|
||||
name = secretstr;
|
||||
secretstr = n + 1;
|
||||
digestbits = parse_hmac(&hmacname, keystr, s - keystr);
|
||||
if (!parse_hmac(&hmacname, keystr, s - keystr, &digestbits)) {
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
#ifndef PK11_MD5_DISABLE
|
||||
hmacname = DNS_TSIG_HMACMD5_NAME;
|
||||
@@ -997,14 +1017,14 @@ static int
|
||||
get_addresses(char *host, in_port_t port,
|
||||
isc_sockaddr_t *sockaddr, int naddrs)
|
||||
{
|
||||
int count;
|
||||
int count = 0;
|
||||
isc_result_t result;
|
||||
|
||||
isc_app_block();
|
||||
result = bind9_getaddresses(host, port, sockaddr, naddrs, &count);
|
||||
isc_app_unblock();
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fatal("couldn't get address for '%s': %s",
|
||||
error("couldn't get address for '%s': %s",
|
||||
host, isc_result_totext(result));
|
||||
return (count);
|
||||
}
|
||||
@@ -1014,7 +1034,7 @@ version(void) {
|
||||
fputs("nsupdate " VERSION "\n", stderr);
|
||||
}
|
||||
|
||||
#define PARSE_ARGS_FMT "dDML:y:ghlovk:p:Pr:R::t:Tu:V"
|
||||
#define PARSE_ARGS_FMT "dDML:y:ghilovk:p:Pr:R::t:Tu:V"
|
||||
|
||||
static void
|
||||
pre_parse_args(int argc, char **argv) {
|
||||
@@ -1038,7 +1058,7 @@ pre_parse_args(int argc, char **argv) {
|
||||
if (isc_commandline_option != '?')
|
||||
fprintf(stderr, "%s: invalid argument -%c\n",
|
||||
argv[0], isc_commandline_option);
|
||||
fprintf(stderr, "usage: nsupdate [-dD] [-L level] [-l]"
|
||||
fprintf(stderr, "usage: nsupdate [-dDi] [-L level] [-l]"
|
||||
"[-g | -o | -y keyname:secret | -k keyfile] "
|
||||
"[-v] [-V] [-P] [-T] [filename]\n");
|
||||
exit(1);
|
||||
@@ -1085,6 +1105,7 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
|
||||
int ch;
|
||||
isc_uint32_t i;
|
||||
isc_result_t result;
|
||||
isc_boolean_t force_interactive = ISC_FALSE;
|
||||
|
||||
debug("parse_args");
|
||||
while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
|
||||
@@ -1098,6 +1119,10 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
|
||||
break;
|
||||
case 'M':
|
||||
break;
|
||||
case 'i':
|
||||
force_interactive = ISC_TRUE;
|
||||
interactive = ISC_TRUE;
|
||||
break;
|
||||
case 'l':
|
||||
local_only = ISC_TRUE;
|
||||
break;
|
||||
@@ -1210,7 +1235,9 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
interactive = ISC_FALSE;
|
||||
if (!force_interactive) {
|
||||
interactive = ISC_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1237,7 +1264,12 @@ parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
|
||||
isc_buffer_init(&source, word, strlen(word));
|
||||
isc_buffer_add(&source, strlen(word));
|
||||
result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL);
|
||||
check_result(result, "dns_name_fromtext");
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
error("invalid owner name: %s", isc_result_totext(result));
|
||||
isc_buffer_invalidate(&source);
|
||||
dns_message_puttempname(msg, namep);
|
||||
return (STATUS_SYNTAX);
|
||||
}
|
||||
isc_buffer_invalidate(&source);
|
||||
return (STATUS_MORE);
|
||||
}
|
||||
@@ -1482,6 +1514,9 @@ evaluate_server(char *cmdline) {
|
||||
|
||||
memset(servers, 0, ns_alloc * sizeof(isc_sockaddr_t));
|
||||
ns_total = get_addresses(server, (in_port_t)port, servers, ns_alloc);
|
||||
if (ns_total == 0) {
|
||||
return (STATUS_SYNTAX);
|
||||
}
|
||||
|
||||
return (STATUS_MORE);
|
||||
}
|
||||
@@ -1562,7 +1597,10 @@ evaluate_key(char *cmdline) {
|
||||
|
||||
n = strchr(namestr, ':');
|
||||
if (n != NULL) {
|
||||
digestbits = parse_hmac(&hmacname, namestr, n - namestr);
|
||||
if (!parse_hmac(&hmacname, namestr, n - namestr,
|
||||
&digestbits)) {
|
||||
return (STATUS_SYNTAX);
|
||||
}
|
||||
namestr = n + 1;
|
||||
} else
|
||||
#ifndef PK11_MD5_DISABLE
|
||||
@@ -1657,8 +1695,10 @@ evaluate_realm(char *cmdline) {
|
||||
return (STATUS_MORE);
|
||||
|
||||
n = snprintf(buf, sizeof(buf), "@%s", word);
|
||||
if (n < 0 || (size_t)n >= sizeof(buf))
|
||||
fatal("realm is too long");
|
||||
if (n < 0 || (size_t)n >= sizeof(buf)) {
|
||||
error("realm is too long");
|
||||
return (STATUS_SYNTAX);
|
||||
}
|
||||
realm = isc_mem_strdup(gmctx, buf);
|
||||
if (realm == NULL)
|
||||
fatal("out of memory");
|
||||
@@ -1677,7 +1717,7 @@ evaluate_ttl(char *cmdline) {
|
||||
|
||||
word = nsu_strsep(&cmdline, " \t\r\n");
|
||||
if (word == NULL || *word == 0) {
|
||||
fprintf(stderr, "could not ttl\n");
|
||||
fprintf(stderr, "could not read ttl\n");
|
||||
return (STATUS_SYNTAX);
|
||||
}
|
||||
|
||||
@@ -2636,6 +2676,9 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
|
||||
memset(master_servers, 0, size);
|
||||
master_total = get_addresses(serverstr, dnsport,
|
||||
master_servers, master_alloc);
|
||||
if (master_total == 0) {
|
||||
exit(1);
|
||||
}
|
||||
master_inuse = 0;
|
||||
} else
|
||||
master_from_servers();
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
<command>nsupdate</command>
|
||||
<arg choice="opt" rep="norepeat"><option>-d</option></arg>
|
||||
<arg choice="opt" rep="norepeat"><option>-D</option></arg>
|
||||
<arg choice="opt" rep="norepeat"><option>-i</option></arg>
|
||||
<arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">level</replaceable></option></arg>
|
||||
<group choice="opt" rep="norepeat">
|
||||
<arg choice="opt" rep="norepeat"><option>-g</option></arg>
|
||||
@@ -156,6 +157,15 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-i</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Force interactive mode, even when standard input is not a terminal.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-k <replaceable class="parameter">keyfile</replaceable></term>
|
||||
<listitem>
|
||||
|
||||
@@ -759,6 +759,63 @@ grep "; Communication with 10.53.0.4#5300 failed: timed out" nsupdate.out-$n > /
|
||||
grep "not implemented" nsupdate.out-$n > /dev/null 2>&1 && ret=1
|
||||
[ $ret = 0 ] || { echo I:failed; status=1; }
|
||||
|
||||
n=`expr $n + 1`
|
||||
ret=0
|
||||
echo "I:ensure bad owner name is fatal in non-interactive mode ($n)"
|
||||
$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
|
||||
update add emptylabel..nil. 600 A 10.10.10.1
|
||||
END
|
||||
grep "invalid owner name: empty label" nsupdate.out > /dev/null || ret=1
|
||||
grep "syntax error" nsupdate.out > /dev/null || ret=1
|
||||
[ $ret = 0 ] || { echo I:failed; status=1; }
|
||||
|
||||
n=`expr $n + 1`
|
||||
ret=0
|
||||
echo "I:ensure bad owner name is not fatal in interactive mode ($n)"
|
||||
$NSUPDATE -i <<END > nsupdate.out 2>&1 || ret=1
|
||||
update add emptylabel..nil. 600 A 10.10.10.1
|
||||
END
|
||||
grep "invalid owner name: empty label" nsupdate.out > /dev/null || ret=1
|
||||
[ $ret = 0 ] || { echo I:failed; status=1; }
|
||||
|
||||
n=`expr $n + 1`
|
||||
ret=0
|
||||
echo "I:ensure invalid key type is fatal in non-interactive mode ($n)"
|
||||
$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
|
||||
key badkeytype:example abcd12345678
|
||||
END
|
||||
grep "unknown key type 'badkeytype'" nsupdate.out > /dev/null || ret=1
|
||||
grep "syntax error" nsupdate.out > /dev/null || ret=1
|
||||
[ $ret = 0 ] || { echo I:failed; status=1; }
|
||||
|
||||
n=`expr $n + 1`
|
||||
ret=0
|
||||
echo "I:ensure invalid key type is not fatal in interactive mode ($n)"
|
||||
$NSUPDATE -i <<END > nsupdate.out 2>&1 || ret=1
|
||||
key badkeytype:example abcd12345678
|
||||
END
|
||||
grep "unknown key type 'badkeytype'" nsupdate.out > /dev/null || ret=1
|
||||
[ $ret = 0 ] || { echo I:failed; status=1; }
|
||||
|
||||
n=`expr $n + 1`
|
||||
ret=0
|
||||
echo "I:ensure unresolvable server name is fatal in non-interactive mode ($n)"
|
||||
$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
|
||||
server unresolvable..
|
||||
END
|
||||
grep "couldn't get address for 'unresolvable..': not found" nsupdate.out > /dev/null || ret=1
|
||||
grep "syntax error" nsupdate.out > /dev/null || ret=1
|
||||
[ $ret = 0 ] || { echo I:failed; status=1; }
|
||||
|
||||
n=`expr $n + 1`
|
||||
ret=0
|
||||
echo "I:ensure unresolvable server name is not fatal in interactive mode ($n)"
|
||||
$NSUPDATE -i <<END > nsupdate.out 2>&1 || ret=1
|
||||
server unresolvable..
|
||||
END
|
||||
grep "couldn't get address for 'unresolvable..': not found" nsupdate.out > /dev/null || ret=1
|
||||
[ $ret = 0 ] || { echo I:failed; status=1; }
|
||||
|
||||
#
|
||||
# Add client library tests here
|
||||
#
|
||||
|
||||
@@ -81,6 +81,23 @@ output=`$DIG $DIGOPTS +short cname fred.example.nil.`
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:ensure too long realm name is fatal in non-interactive mode"
|
||||
ret=0
|
||||
$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
|
||||
realm namenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename
|
||||
END
|
||||
grep "realm is too long" nsupdate.out > /dev/null || ret=1
|
||||
grep "syntax error" nsupdate.out > /dev/null || ret=1
|
||||
[ $ret = 0 ] || { echo I:failed; status=1; }
|
||||
|
||||
echo "I:ensure too long realm name is not fatal in interactive mode"
|
||||
ret=0
|
||||
$NSUPDATE -i <<END > nsupdate.out 2>&1 || ret=1
|
||||
realm namenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename
|
||||
END
|
||||
grep "realm is too long" nsupdate.out > /dev/null || ret=1
|
||||
[ $ret = 0 ] || { echo I:failed; status=1; }
|
||||
|
||||
[ $status -eq 0 ] && echo "I:tsiggss tests all OK"
|
||||
|
||||
kill `cat authsock.pid`
|
||||
|
||||
Reference in New Issue
Block a user