gpg: Change TOFU_STATS to return timestamps.
authorWerner Koch <wk@gnupg.org>
Wed, 24 Aug 2016 17:56:14 +0000 (19:56 +0200)
committerWerner Koch <wk@gnupg.org>
Wed, 24 Aug 2016 17:56:14 +0000 (19:56 +0200)
* g10/tofu.c (write_stats_status): Add arg FP to print a colon
formated line.  Adjust for changed TOFU_STATS interface.
(show_statistics): Let the query return timestamps and use
gnupg_get-time to compute the "time ago" values.

Signed-off-by: Werner Koch <wk@gnupg.org>
doc/DETAILS
g10/tofu.c

index 332e686..454f2e3 100644 (file)
@@ -60,6 +60,7 @@ described here.
     - pkd :: Public key data [*]
     - grp :: Keygrip
     - rvk :: Revocation key
+    - tfs :: TOFU statistics [*]
     - tru :: Trust database information [*]
     - spk :: Signature subpacket [*]
     - cfg :: Configuration data [*]
@@ -230,6 +231,20 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
     !--------- index (eg. DSA goes from 0 to 3: p,q,g,y)
 #+end_example
 
+*** TFS - TOFU statistics
+
+    This field may follows a UID record to convey information about
+    the TOFU database.  The information is similar to a TOFU_STATS
+    status line.
+
+    - Field 2 :: tfs record version (must be 1)
+    - Field 3 :: validity -  A number with validity code.
+    - Field 4 :: signcount - The number of signatures seen.
+    - Field 5 :: encrcount - The number of encryptions done.
+    - Field 6 :: policy - A string with the policy
+    - Field 7 :: first-seen - a timestamp or 0 if not known.
+    - Field 8 :: most-recent-seen - a timestamp or 0 if not known.
+
 *** TRU - Trust database information
     Example for a "tru" trust base record:
 #+begin_example
@@ -723,9 +738,9 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
     - ask     :: Policy is "ask"
     - unknown :: Policy is not known.
 
-    TM1 gives the number of seconds since the the first messages was
-    verified.  TM2 gives the number of seconds since the most recent
-    message was verified.
+    TM1 ist the time the first messages was verified.  TM2 is the time
+    the most recent message was verified.  Both may either be seconds
+    since Epoch or an ISO time string (yyyymmddThhmmss).
 
 *** TOFU_STATS_SHORT <long_string>
 
index ef14e85..29318c7 100644 (file)
@@ -1872,14 +1872,13 @@ time_ago_str (long long int t)
 }
 
 
-/* Write TOFU_STATS status line.  */
+/* If FP is NULL, write TOFU_STATS status line.  If FP is not NULL
+ * write a "tfs" record to that stream. */
 static void
-write_stats_status (long messages, enum tofu_policy policy,
-                    long first_seen_ago, long most_recent_seen_ago)
+write_stats_status (estream_t fp, long messages, enum tofu_policy policy,
+                    unsigned long first_seen,
+                    unsigned long most_recent_seen)
 {
-  char numbuf1[35];
-  char numbuf2[35];
-  char numbuf3[35];
   const char *validity;
 
   if (messages < 1)
@@ -1891,19 +1890,33 @@ write_stats_status (long messages, enum tofu_policy policy,
   else
     validity = "4"; /* Key with a lot of history.  */
 
-  snprintf (numbuf1, sizeof numbuf1, " %ld", messages);
-  *numbuf2 = *numbuf3 = 0;
-  if (first_seen_ago >= 0 && most_recent_seen_ago >= 0)
+  if (fp)
     {
-      snprintf (numbuf2, sizeof numbuf2, " %ld", first_seen_ago);
-      snprintf (numbuf3, sizeof numbuf3, " %ld", most_recent_seen_ago);
+      es_fprintf (fp, "tfs:1:%s:%ld:0:%s:%lu:%lu:\n",
+                  validity, messages,
+                  tofu_policy_str (policy),
+                  first_seen, most_recent_seen);
     }
+  else
+    {
+      char numbuf1[35];
+      char numbuf2[35];
+      char numbuf3[35];
+
+      snprintf (numbuf1, sizeof numbuf1, " %ld", messages);
+      *numbuf2 = *numbuf3 = 0;
+      if (first_seen && most_recent_seen)
+        {
+          snprintf (numbuf2, sizeof numbuf2, " %lu", first_seen);
+          snprintf (numbuf3, sizeof numbuf3, " %lu", most_recent_seen);
+        }
 
-  write_status_strings (STATUS_TOFU_STATS,
-                        validity, numbuf1, " 0",
-                        " ", tofu_policy_str (policy),
-                        numbuf2, numbuf3,
-                        NULL);
+      write_status_strings (STATUS_TOFU_STATS,
+                            validity, numbuf1, " 0",
+                            " ", tofu_policy_str (policy),
+                            numbuf2, numbuf3,
+                            NULL);
+    }
 }
 
 static void
@@ -1920,8 +1933,7 @@ show_statistics (tofu_dbs_t dbs, const char *fingerprint,
 
   rc = gpgsql_exec_printf
     (dbs->db, strings_collect_cb, &strlist, &err,
-     "select count (*), strftime('%%s','now') - min (signatures.time),\n"
-     "  strftime('%%s','now') - max (signatures.time)\n"
+     "select count (*), min (signatures.time), max (signatures.time)\n"
      " from signatures\n"
      " left join bindings on signatures.binding = bindings.oid\n"
      " where fingerprint = %Q and email = %Q and sig_digest %s%s%s;",
@@ -1939,6 +1951,7 @@ show_statistics (tofu_dbs_t dbs, const char *fingerprint,
       goto out;
     }
 
+
   write_status_text_and_buffer (STATUS_TOFU_USER, fingerprint,
                                 email, strlen (email), 0);
 
@@ -1946,13 +1959,14 @@ show_statistics (tofu_dbs_t dbs, const char *fingerprint,
     {
       log_info (_("Have never verified a message signed by key %s!\n"),
                 fingerprint_pp);
-      write_stats_status (0,  TOFU_POLICY_NONE, -1, -1);
+      write_stats_status (NULL, 0, TOFU_POLICY_NONE, 0, 0);
     }
   else
     {
+      unsigned long now = gnupg_get_time ();
       signed long messages;
-      signed long first_seen_ago;
-      signed long most_recent_seen_ago;
+      unsigned long first_seen;
+      unsigned long most_recent_seen;
 
       log_assert (strlist_length (strlist) == 3);
 
@@ -1960,19 +1974,32 @@ show_statistics (tofu_dbs_t dbs, const char *fingerprint,
 
       if (messages == 0 && *strlist->next->d == '\0')
         { /* min(NULL) => NULL => "".  */
-          first_seen_ago = -1;
-          most_recent_seen_ago = -1;
+          first_seen = 0;
+          most_recent_seen = 0;
         }
       else
        {
-          string_to_long (&first_seen_ago, strlist->next->d, -1, __LINE__);
-         string_to_long (&most_recent_seen_ago, strlist->next->next->d, -1,
-                          __LINE__);
+          string_to_ulong (&first_seen, strlist->next->d, -1, __LINE__);
+          if (first_seen > now)
+            {
+              log_debug ("time-warp - tofu DB has a future value (%lu, %lu)\n",
+                         first_seen, now);
+              first_seen = now;
+            }
+         string_to_ulong (&most_recent_seen, strlist->next->next->d, -1,
+                           __LINE__);
+          if (most_recent_seen > now)
+            {
+              log_debug ("time-warp - tofu DB has a future value (%lu, %lu)\n",
+                         most_recent_seen, now);
+              most_recent_seen = now;
+            }
+
        }
 
-      if (messages == -1 || first_seen_ago == -1)
+      if (messages == -1 || !first_seen)
         {
-          write_stats_status (0, TOFU_POLICY_NONE, -1, -1);
+          write_stats_status (NULL, 0, TOFU_POLICY_NONE, 0, 0);
           log_info (_("Failed to collect signature statistics for \"%s\"\n"
                       "(key %s)\n"),
                     user_id, fingerprint_pp);
@@ -1983,8 +2010,8 @@ show_statistics (tofu_dbs_t dbs, const char *fingerprint,
          estream_t fp;
          char *msg;
 
-          write_stats_status (messages, policy,
-                              first_seen_ago, most_recent_seen_ago);
+          write_stats_status (NULL, messages, policy,
+                              first_seen, most_recent_seen);
 
          fp = es_fopenmem (0, "rw,samethread");
          if (! fp)
@@ -1999,7 +2026,7 @@ show_statistics (tofu_dbs_t dbs, const char *fingerprint,
             }
          else
            {
-              char *first_seen_ago_str = time_ago_str (first_seen_ago);
+              char *first_seen_ago_str = time_ago_str (now - first_seen);
 
               /* TRANSLATORS: The final %s is replaced by a string like
                  "7 months, 1 day, 5 minutes, 0 seconds". */
@@ -2013,7 +2040,7 @@ show_statistics (tofu_dbs_t dbs, const char *fingerprint,
 
               if (messages > 1)
                 {
-                  char *tmpstr = time_ago_str (most_recent_seen_ago);
+                  char *tmpstr = time_ago_str (now - most_recent_seen);
                   es_fputs ("  ", fp);
                   es_fprintf (fp, _("The most recent message was"
                                     " verified %s ago."), tmpstr);