From c38a3230823a8a16eee4e3502419ccf5a309e354 Mon Sep 17 00:00:00 2001 From: Tony Finch Date: Mon, 29 Apr 2019 13:56:05 +0100 Subject: [PATCH] Teach dnssec-settime to read times that it writes The dnssec-settime -p and -up options print times in asctime() and UNIX time_t formats, respectively. The asctime() format can also be found inside K*.key public key files. Key files also contain times in the YYYYMMDDHHMMSS format that can be used in timing parameter options. The dnssec-settime -p and -up time formats are now acceptable in timing parameter options to dnssec-settime and dnssec-keygen, so it is no longer necessary to parse key files to retrieve times that are acceptable in timing parameter options. --- bin/dnssec/dnssec-keygen.rst | 23 +++++++++++++++-------- bin/dnssec/dnssec-settime.rst | 23 +++++++++++++++-------- bin/dnssec/dnssectool.c | 16 ++++++++++++++++ bin/tests/system/metadata/tests.sh | 16 ++++++++++++++++ doc/man/dnssec-keygen.1in | 23 +++++++++++++++-------- doc/man/dnssec-settime.1in | 23 +++++++++++++++-------- 6 files changed, 92 insertions(+), 32 deletions(-) diff --git a/bin/dnssec/dnssec-keygen.rst b/bin/dnssec/dnssec-keygen.rst index 700149ffc8..2c1df3b521 100644 --- a/bin/dnssec/dnssec-keygen.rst +++ b/bin/dnssec/dnssec-keygen.rst @@ -221,14 +221,21 @@ Options Timing Options ~~~~~~~~~~~~~~ -Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the -argument begins with a ``+`` or ``-``, it is interpreted as an offset from -the present time. For convenience, if such an offset is followed by one -of the suffixes ``y``, ``mo``, ``w``, ``d``, ``h``, or ``mi``, then the offset is -computed in years (defined as 365 24-hour days, ignoring leap years), -months (defined as 30 24-hour days), weeks, days, hours, or minutes, -respectively. Without a suffix, the offset is computed in seconds. To -explicitly prevent a date from being set, use ``none`` or ``never``. +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS +(which is the format used inside key files), +or 'Day Mon DD HH:MM:SS YYYY' (as printed by ``dnssec-settime -p``), +or UNIX epoch time (as printed by ``dnssec-settime -up``), +or the literal ``now``. + +The argument can be followed by '+' or '-' and an offset from the +given time. The literal ``now`` can be omitted before an offset. The +offset can be followed by one of the suffixes 'y', 'mo', 'w', 'd', +'h', or 'mi', so that it is computed in years (defined as 365 24-hour +days, ignoring leap years), months (defined as 30 24-hour days), +weeks, days, hours, or minutes, respectively. Without a suffix, the +offset is computed in seconds. + +To unset a date, use ``none`` or ``never``. .. option:: -P date/offset diff --git a/bin/dnssec/dnssec-settime.rst b/bin/dnssec/dnssec-settime.rst index a71712ca04..a9b1283c4a 100644 --- a/bin/dnssec/dnssec-settime.rst +++ b/bin/dnssec/dnssec-settime.rst @@ -108,14 +108,21 @@ Options Timing Options ~~~~~~~~~~~~~~ -Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the -argument begins with a ``+`` or ``-``, it is interpreted as an offset from -the present time. For convenience, if such an offset is followed by one -of the suffixes ``y``, ``mo``, ``w``, ``d``, ``h``, or ``mi``, then the offset is -computed in years (defined as 365 24-hour days, ignoring leap years), -months (defined as 30 24-hour days), weeks, days, hours, or minutes, -respectively. Without a suffix, the offset is computed in seconds. To -explicitly prevent a date from being set, use ``none`` or ``never``. +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS +(which is the format used inside key files), +or 'Day Mon DD HH:MM:SS YYYY' (as printed by ``dnssec-settime -p``), +or UNIX epoch time (as printed by ``dnssec-settime -up``), +or the literal ``now``. + +The argument can be followed by '+' or '-' and an offset from the +given time. The literal ``now`` can be omitted before an offset. The +offset can be followed by one of the suffixes 'y', 'mo', 'w', 'd', +'h', or 'mi', so that it is computed in years (defined as 365 24-hour +days, ignoring leap years), months (defined as 30 24-hour days), +weeks, days, hours, or minutes, respectively. Without a suffix, the +offset is computed in seconds. + +To unset a date, use ``none`` or ``never``. .. option:: -P date/offset diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c index dda814e4d9..53122249cb 100644 --- a/bin/dnssec/dnssectool.c +++ b/bin/dnssec/dnssectool.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -285,6 +286,7 @@ strtotime(const char *str, int64_t now, int64_t base, bool *setp) { const char *orig = str; char *endp; size_t n; + struct tm tm; if (isnone(str)) { if (setp != NULL) { @@ -306,6 +308,8 @@ strtotime(const char *str, int64_t now, int64_t base, bool *setp) { * now([+-]offset) * YYYYMMDD([+-]offset) * YYYYMMDDhhmmss([+-]offset) + * Day Mon DD HH:MM:SS YYYY([+-]offset) + * 1234567890([+-]offset) * [+-]offset */ n = strspn(str, "0123456789"); @@ -325,9 +329,21 @@ strtotime(const char *str, int64_t now, int64_t base, bool *setp) { } base = val; str += n; + } else if (n == 10u && + (str[n] == '\0' || str[n] == '-' || str[n] == '+')) { + base = strtoll(str, &endp, 0); + str += 10; } else if (strncmp(str, "now", 3) == 0) { base = now; str += 3; + } else if (str[0] >= 'A' && str[0] <= 'Z') { + /* parse ctime() format as written by `dnssec-settime -p` */ + endp = isc_tm_strptime(str, "%a %b %d %H:%M:%S %Y", &tm); + if (endp != str + 24) { + fatal("time value %s is invalid", orig); + } + base = mktime(&tm); + str += 24; } if (str[0] == '\0') { diff --git a/bin/tests/system/metadata/tests.sh b/bin/tests/system/metadata/tests.sh index b19d1cf7a9..b3c2cd3fec 100644 --- a/bin/tests/system/metadata/tests.sh +++ b/bin/tests/system/metadata/tests.sh @@ -208,5 +208,21 @@ n=`expr $n + 1` if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` +key=`$KEYGEN -q -a RSASHA1 $czone` + +echo_i "checking -p output time is accepted ($n)" +t=`$SETTIME -pA $key | sed 's/.*: //'` +$SETTIME -Psync "$t" $key > /dev/null 2>&1 || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +echo_i "checking -up output time is accepted ($n)" +t=`$SETTIME -upA $key | sed 's/.*: //'` +$SETTIME -Dsync "$t" $key > /dev/null 2>&1 || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 diff --git a/doc/man/dnssec-keygen.1in b/doc/man/dnssec-keygen.1in index f9fccee924..a2e9158955 100644 --- a/doc/man/dnssec-keygen.1in +++ b/doc/man/dnssec-keygen.1in @@ -250,14 +250,21 @@ This option sets the debugging level. .UNINDENT .SH TIMING OPTIONS .sp -Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the -argument begins with a \fB+\fP or \fB\-\fP, it is interpreted as an offset from -the present time. For convenience, if such an offset is followed by one -of the suffixes \fBy\fP, \fBmo\fP, \fBw\fP, \fBd\fP, \fBh\fP, or \fBmi\fP, then the offset is -computed in years (defined as 365 24\-hour days, ignoring leap years), -months (defined as 30 24\-hour days), weeks, days, hours, or minutes, -respectively. Without a suffix, the offset is computed in seconds. To -explicitly prevent a date from being set, use \fBnone\fP or \fBnever\fP\&. +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS +(which is the format used inside key files), +or \(aqDay Mon DD HH:MM:SS YYYY\(aq (as printed by \fBdnssec\-settime \-p\fP), +or UNIX epoch time (as printed by \fBdnssec\-settime \-up\fP), +or the literal \fBnow\fP\&. +.sp +The argument can be followed by \(aq+\(aq or \(aq\-\(aq and an offset from the +given time. The literal \fBnow\fP can be omitted before an offset. The +offset can be followed by one of the suffixes \(aqy\(aq, \(aqmo\(aq, \(aqw\(aq, \(aqd\(aq, +\(aqh\(aq, or \(aqmi\(aq, so that it is computed in years (defined as 365 24\-hour +days, ignoring leap years), months (defined as 30 24\-hour days), +weeks, days, hours, or minutes, respectively. Without a suffix, the +offset is computed in seconds. +.sp +To unset a date, use \fBnone\fP or \fBnever\fP\&. .INDENT 0.0 .TP .B \-P date/offset diff --git a/doc/man/dnssec-settime.1in b/doc/man/dnssec-settime.1in index 498bcd3b22..66313765d1 100644 --- a/doc/man/dnssec-settime.1in +++ b/doc/man/dnssec-settime.1in @@ -120,14 +120,21 @@ hardware service module (usually \fBpkcs11\fP). .UNINDENT .SH TIMING OPTIONS .sp -Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the -argument begins with a \fB+\fP or \fB\-\fP, it is interpreted as an offset from -the present time. For convenience, if such an offset is followed by one -of the suffixes \fBy\fP, \fBmo\fP, \fBw\fP, \fBd\fP, \fBh\fP, or \fBmi\fP, then the offset is -computed in years (defined as 365 24\-hour days, ignoring leap years), -months (defined as 30 24\-hour days), weeks, days, hours, or minutes, -respectively. Without a suffix, the offset is computed in seconds. To -explicitly prevent a date from being set, use \fBnone\fP or \fBnever\fP\&. +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS +(which is the format used inside key files), +or \(aqDay Mon DD HH:MM:SS YYYY\(aq (as printed by \fBdnssec\-settime \-p\fP), +or UNIX epoch time (as printed by \fBdnssec\-settime \-up\fP), +or the literal \fBnow\fP\&. +.sp +The argument can be followed by \(aq+\(aq or \(aq\-\(aq and an offset from the +given time. The literal \fBnow\fP can be omitted before an offset. The +offset can be followed by one of the suffixes \(aqy\(aq, \(aqmo\(aq, \(aqw\(aq, \(aqd\(aq, +\(aqh\(aq, or \(aqmi\(aq, so that it is computed in years (defined as 365 24\-hour +days, ignoring leap years), months (defined as 30 24\-hour days), +weeks, days, hours, or minutes, respectively. Without a suffix, the +offset is computed in seconds. +.sp +To unset a date, use \fBnone\fP or \fBnever\fP\&. .INDENT 0.0 .TP .B \-P date/offset