diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c index f03d2e8265..7dc8db1d5b 100644 --- a/bin/dnssec/dnssectool.c +++ b/bin/dnssec/dnssectool.c @@ -17,7 +17,10 @@ * DNSSEC Support Routines. */ +#include +#include #include +#include #include #include #include @@ -223,19 +226,35 @@ isnone(const char *str) { dns_ttl_t strtottl(const char *str) { const char *orig = str; - dns_ttl_t ttl; + const char *p = str; + unsigned long val; char *endp; if (isnone(str)) { return (dns_ttl_t)0; } - ttl = strtol(str, &endp, 0); - if (ttl == 0 && endp == str) { - fatal("TTL must be numeric"); + /* + * strtoul() silently negates a leading '-', producing + * ULONG_MAX-class values that then truncate to a near-UINT32_MAX + * TTL. Reject the sign explicitly before parsing. + */ + while (isspace((unsigned char)*p)) { + p++; } - ttl = time_units(ttl, endp, orig); - return ttl; + if (*p == '-') { + fatal("TTL must be non-negative: %s", orig); + } + + errno = 0; + val = strtoul(str, &endp, 0); + if (endp == str) { + fatal("TTL must be numeric: %s", orig); + } + if (errno == ERANGE || val > UINT32_MAX) { + fatal("TTL %s out of range (max %u)", orig, UINT32_MAX); + } + return time_units((dns_ttl_t)val, endp, orig); } dst_key_state_t diff --git a/bin/tests/system/dnssectools/tests.sh b/bin/tests/system/dnssectools/tests.sh index 96e4500b57..8b5065b19b 100644 --- a/bin/tests/system/dnssectools/tests.sh +++ b/bin/tests/system/dnssectools/tests.sh @@ -342,6 +342,33 @@ n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) +echo_i "checking that a negative DNSKEY TTL is rejected ($n)" +ret=0 +zone=example +$KEYGEN -L -1 -a $DEFAULT_ALGORITHM $zone >dnssectools.out.test$n 2>&1 && ret=1 +grep -q "TTL must be non-negative" dnssectools.out.test$n || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that an out-of-range DNSKEY TTL is rejected ($n)" +ret=0 +zone=example +$KEYGEN -L 9999999999 -a $DEFAULT_ALGORITHM $zone >dnssectools.out.test$n 2>&1 && ret=1 +grep -q "out of range" dnssectools.out.test$n || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that a negative DNSKEY TTL with a unit suffix is rejected ($n)" +ret=0 +zone=example +$KEYGEN -L -1d -a $DEFAULT_ALGORITHM $zone >dnssectools.out.test$n 2>&1 && ret=1 +grep -q "TTL must be non-negative" dnssectools.out.test$n || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + echo_i "checking that a DS record cannot be generated for a key using an unsupported algorithm ($n)" ret=0 zone=example