[tor-commits] [tor/master] Add --format argument to --key-expiration option. #30045

nickm at torproject.org nickm at torproject.org
Tue Aug 4 17:28:57 UTC 2020


commit 1474ab33956eefd9b75ef9a3e238ec7f855b8c7e
Author: Daniel Pinto <danielpinto52 at gmail.com>
Date:   Sat Aug 1 00:03:06 2020 +0100

    Add --format argument to --key-expiration option. #30045
---
 changes/feature30045                     |  6 +++
 doc/man/tor.1.txt                        | 14 +++++--
 scripts/maint/practracker/exceptions.txt |  4 +-
 src/app/config/config.c                  | 35 ++++++++++++++++
 src/app/config/or_options_st.h           |  5 +++
 src/feature/relay/routerkeys.c           | 28 ++++++++++---
 src/test/test_key_expiration.sh          | 70 ++++++++++++++++++++++++++++++--
 7 files changed, 147 insertions(+), 15 deletions(-)

diff --git a/changes/feature30045 b/changes/feature30045
new file mode 100644
index 0000000000..9a0b8c041a
--- /dev/null
+++ b/changes/feature30045
@@ -0,0 +1,6 @@
+  o Minor features (admin tools):
+    - Add new --format argument to -key-expiration option to allow
+      specifying the time format of expiration date. Adds Unix
+      timestamp format support. Patch by Daniel Pinto. Closes
+      ticket 30045.
+
diff --git a/doc/man/tor.1.txt b/doc/man/tor.1.txt
index edb8593142..6e504c8a82 100644
--- a/doc/man/tor.1.txt
+++ b/doc/man/tor.1.txt
@@ -174,16 +174,22 @@ The following options in this section are only recognized on the
     If the file descriptor is not specified, the passphrase is read
     from the terminal by default.
 
-[[opt-key-expiration]] **`--key-expiration`** [__purpose__]::
+[[opt-key-expiration]] **`--key-expiration`** [__purpose__] [**`--format`** **`iso8601`**|**`timestamp`**]::
     The __purpose__ specifies which type of key certificate to determine
     the expiration of.  The only currently recognised __purpose__ is
     "sign". +
      +
     Running **`tor --key-expiration sign`** will attempt to find your
     signing key certificate and will output, both in the logs as well
-    as to stdout, the signing key certificate's expiration time in
-    ISO-8601 format.  For example, the output sent to stdout will be
-    of the form: "signing-cert-expiry: 2017-07-25 08:30:15 UTC"
+    as to stdout.  The optional **`--format`** argument lets you specify
+    the time format.  Currently, **`iso8601`** and **`timestamp`** are
+    supported.  If **`--format`** is not specified, the signing key
+    certificate's expiration time will be in ISO-8601 format.  For example,
+    the output sent to stdout will be of the form:
+    "signing-cert-expiry: 2017-07-25 08:30:15 UTC".  If **`--format`** **`timestamp`**
+    is specified, the signing key certificate's expiration time will be in
+    Unix timestamp format. For example, the output sent to stdout will be of the form:
+    "signing-cert-expiry: 1500971415".
 
 [[opt-dbg]] **--dbg-**...::
     Tor may support other options beginning with the string "dbg". These
diff --git a/scripts/maint/practracker/exceptions.txt b/scripts/maint/practracker/exceptions.txt
index b2a34b808a..95c5665fb3 100644
--- a/scripts/maint/practracker/exceptions.txt
+++ b/scripts/maint/practracker/exceptions.txt
@@ -37,7 +37,7 @@ problem file-size /src/app/config/config.c 7525
 problem include-count /src/app/config/config.c 81
 problem function-size /src/app/config/config.c:options_act() 381
 problem function-size /src/app/config/config.c:options_validate_cb() 794
-problem function-size /src/app/config/config.c:options_init_from_torrc() 198
+problem function-size /src/app/config/config.c:options_init_from_torrc() 231
 problem function-size /src/app/config/config.c:options_init_from_string() 103
 problem function-size /src/app/config/config.c:options_init_logs() 125
 problem function-size /src/app/config/config.c:parse_bridge_line() 104
@@ -47,7 +47,7 @@ problem function-size /src/app/config/config.c:parse_dir_fallback_line() 101
 problem function-size /src/app/config/config.c:port_parse_config() 435
 problem function-size /src/app/config/config.c:parse_ports() 132
 problem function-size /src/app/config/resolve_addr.c:resolve_my_address_v4() 197
-problem file-size /src/app/config/or_options_st.h 1050
+problem file-size /src/app/config/or_options_st.h 1069
 problem include-count /src/app/main/main.c 71
 problem function-size /src/app/main/main.c:dumpstats() 102
 problem function-size /src/app/main/main.c:tor_init() 109
diff --git a/src/app/config/config.c b/src/app/config/config.c
index a70c1d651e..1c6d4acd3e 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -2468,6 +2468,8 @@ static const struct {
   { .name="--key-expiration",
     .takes_argument=ARGUMENT_OPTIONAL,
     .command=CMD_KEY_EXPIRATION },
+  { .name="--format",
+    .takes_argument=ARGUMENT_NECESSARY },
   { .name="--newpass" },
   { .name="--no-passphrase" },
   { .name="--passphrase-fd",
@@ -4425,6 +4427,39 @@ options_init_from_torrc(int argc, char **argv)
     }
   }
 
+  const config_line_t *format_line = config_line_find(cmdline_only_options,
+                                                      "--format");
+  if (format_line) {
+    if (command == CMD_KEY_EXPIRATION) {
+      const char *v = format_line->value;
+      // keep the same order as enum key_expiration_format
+      const char *formats[] = { "iso8601", "timestamp" };
+      const int formats_len = sizeof(formats) / sizeof(formats[0]);
+      int format = -1;
+      for (int i = 0; i < formats_len; i++) {
+        if (!strcmp(v, formats[i])) {
+          format = i;
+          break;
+        }
+      }
+
+      if (format < 0) {
+        log_err(LD_CONFIG, "Invalid --format value %s", escaped(v));
+        retval = -1;
+        goto err;
+      } else {
+        get_options_mutable()->key_expiration_format = format;
+      }
+    } else {
+      log_err(LD_CONFIG, "--format specified without --key-expiration!");
+      retval = -1;
+      goto err;
+    }
+  } else {
+    get_options_mutable()->key_expiration_format =
+      KEY_EXPIRATION_FORMAT_ISO8601;
+  }
+
   if (config_line_find(cmdline_only_options, "--newpass")) {
     if (command == CMD_KEYGEN) {
       get_options_mutable()->change_key_passphrase = 1;
diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h
index 68be5711ce..774b476476 100644
--- a/src/app/config/or_options_st.h
+++ b/src/app/config/or_options_st.h
@@ -944,6 +944,11 @@ struct or_options_t {
    * ed25519 identity key except from tor --keygen */
   int OfflineMasterKey;
 
+  enum {
+    KEY_EXPIRATION_FORMAT_ISO8601 = 0,
+    KEY_EXPIRATION_FORMAT_TIMESTAMP
+  } key_expiration_format;
+
   enum {
     FORCE_PASSPHRASE_AUTO=0,
     FORCE_PASSPHRASE_ON,
diff --git a/src/feature/relay/routerkeys.c b/src/feature/relay/routerkeys.c
index d3de83cb86..f0fd101efd 100644
--- a/src/feature/relay/routerkeys.c
+++ b/src/feature/relay/routerkeys.c
@@ -519,19 +519,34 @@ print_cert_expiration(const char *expiration,
 
 /**
  * Log when a certificate, <b>cert</b>, with some <b>description</b> and
- * stored in a file named <b>fname</b>, is going to expire.
+ * stored in a file named <b>fname</b>, is going to expire. Formats the expire
+ * time according to <b>time_format</b>. Valid time formats are in the
+ * key_expiration_format enum, in or_options_t.
  */
 static void
 log_ed_cert_expiration(const tor_cert_t *cert,
                        const char *description,
-                       const char *fname) {
-  char expiration[ISO_TIME_LEN+1];
-
+                       const char *fname,
+                       int time_format) {
   if (BUG(!cert)) { /* If the specified key hasn't been loaded */
     log_warn(LD_OR, "No %s key loaded; can't get certificate expiration.",
              description);
   } else {
-    format_local_iso_time(expiration, cert->valid_until);
+    char expiration[ISO_TIME_LEN+1];
+    switch (time_format) {
+      case KEY_EXPIRATION_FORMAT_ISO8601:
+        format_local_iso_time(expiration, cert->valid_until);
+        break;
+
+      case KEY_EXPIRATION_FORMAT_TIMESTAMP:
+        tor_snprintf(expiration, sizeof(expiration), "%"PRId64,
+                     (int64_t) cert->valid_until);
+        break;
+
+      default:
+        log_err(LD_BUG, "Unknown time format value: %d.", time_format);
+        return;
+    }
     log_notice(LD_OR, "The %s certificate stored in %s is valid until %s.",
                description, fname, expiration);
     print_cert_expiration(expiration, description);
@@ -567,7 +582,8 @@ log_master_signing_key_cert_expiration(const or_options_t *options)
 
   /* If we do have a signing key, log the expiration time. */
   if (signing_key) {
-    log_ed_cert_expiration(signing_key, "signing", fn);
+    int time_format = options->key_expiration_format;
+    log_ed_cert_expiration(signing_key, "signing", fn, time_format);
   } else {
     log_warn(LD_OR, "Could not load signing key certificate from %s, so " \
              "we couldn't learn anything about certificate expiration.", fn);
diff --git a/src/test/test_key_expiration.sh b/src/test/test_key_expiration.sh
index 2238f7aa78..1ba8179aa1 100755
--- a/src/test/test_key_expiration.sh
+++ b/src/test/test_key_expiration.sh
@@ -61,6 +61,11 @@ fi
 CASE1=$dflt
 CASE2=$dflt
 CASE3=$dflt
+CASE4=$dflt
+CASE5=$dflt
+CASE6=$dflt
+CASE7=$dflt
+CASE8=$dflt
 
 if [ $# -ge 1 ]; then
   eval "CASE${1}"=1
@@ -125,16 +130,17 @@ if [ "$CASE1" = 1 ]; then
 
   ${TOR} ${QUIETLY} --key-expiration 2>"$FN" || true
   grep "No valid argument to --key-expiration found!" "$FN" >/dev/null || \
-    die "Tor didn't mention supported --key-expiration argmuents"
+    die "Tor didn't mention supported --key-expiration arguments"
 
   echo "==== Case 1: ok"
 fi
 
 if [ "$CASE2" = 1 ]; then
-  echo "==== Case 2: Start Tor with --key-expiration 'sign' and make sure it prints an expiration."
+  echo "==== Case 2: Start Tor with --key-expiration 'sign' and make sure it"
+  echo "             prints an expiration using ISO8601 date format."
 
   ${TOR} ${QUIETLY} --key-expiration sign 2>"$FN"
-  grep "signing-cert-expiry:" "$FN" >/dev/null || \
+  grep "signing-cert-expiry: [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\} [0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}" "$FN" >/dev/null || \
     die "Tor didn't print an expiration"
 
   echo "==== Case 2: ok"
@@ -160,3 +166,61 @@ if [ "$CASE3" = 1 ]; then
 
   echo "==== Case 3: ok"
 fi
+
+if [ "$CASE4" = 1 ]; then
+  echo "==== Case 4: Start Tor with --format iso8601 and make sure it prints an"
+  echo "             error message due to missing --key-expiration argument."
+
+  ${TOR} --format iso8601 > "$FN" 2>&1 || true
+  grep -- "--format specified without --key-expiration!" "$FN" >/dev/null || \
+    die "Tor didn't print a missing --key-expiration error message"
+
+  echo "==== Case 4: ok"
+fi
+
+if [ "$CASE5" = 1 ]; then
+  echo "==== Case 5: Start Tor with --key-expiration 'sign' --format '' and"
+  echo "             make sure it prints an error message due to missing value."
+
+  ${TOR} --key-expiration sign --format > "$FN" 2>&1 || true
+  grep "Command-line option '--format' with no value. Failing." "$FN" >/dev/null || \
+    die "Tor didn't print a missing format value error message"
+
+  echo "==== Case 5: ok"
+fi
+
+if [ "$CASE6" = 1 ]; then
+  echo "==== Case 6: Start Tor with --key-expiration 'sign' --format 'invalid'"
+  echo "             and make sure it prints an error message due to invalid"
+  echo "             value."
+
+  ${TOR} --key-expiration sign --format invalid > "$FN" 2>&1 || true
+  grep "Invalid --format value" "$FN" >/dev/null || \
+    die "Tor didn't print an invalid format value error message"
+
+  echo "==== Case 6: ok"
+fi
+
+if [ "$CASE7" = 1 ]; then
+  echo "==== Case 7: Start Tor with --key-expiration 'sign' --format 'iso8601'"
+  echo "             and make sure it prints an expiration using ISO8601 date"
+  echo "             format."
+
+  ${TOR} ${QUIETLY} --key-expiration sign --format iso8601 2>"$FN"
+  grep "signing-cert-expiry: [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\} [0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}" "$FN" >/dev/null || \
+    die "Tor didn't print an expiration"
+
+  echo "==== Case 7: ok"
+fi
+
+if [ "$CASE8" = 1 ]; then
+  echo "==== Case 8: Start Tor with --key-expiration 'sign' --format 'timestamp'"
+  echo "             and make sure it prints an expiration using timestamp date"
+  echo "             format."
+
+  ${TOR} ${QUIETLY} --key-expiration sign --format timestamp 2>"$FN"
+  grep "signing-cert-expiry: [0-9]\{5,\}" "$FN" >/dev/null || \
+    die "Tor didn't print an expiration"
+
+  echo "==== Case 8: ok"
+fi





More information about the tor-commits mailing list