gpg: Emit status lines TOFU_STATS and TOFU_STATS_LONG.
authorWerner Koch <wk@gnupg.org>
Tue, 3 May 2016 08:26:55 +0000 (10:26 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 3 May 2016 08:26:55 +0000 (10:26 +0200)
* g10/tofu.c (NO_WARNING_THRESHOLD): Rename to BASIC_TRUST_THRESHOLD.
(FULL_TRUST_THRESHOLD): New.
(write_stats_status): New.
(show_statistics): Call new function.  Print TOFU_STATS_LONG.

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

index 7d5a5a8..5ceab68 100644 (file)
@@ -668,10 +668,54 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
        - shell :: The standard X.509 model.
        - chain :: The chain model.
        - steed :: The STEED model.
+       - tofu  :: The TOFU model
 
     Note that the term =TRUST_= in the status names is used for
     historic reasons; we now speak of validity.
 
+*** TOFU_USER <fingerprint_in_hex> <mbox>
+
+    This status identifies the key and the userid for all following
+    Tofu information.  The fingerprint is the fingerprint of the
+    primary key and the mbox is in general the mailbox part of the
+    userid encoded in UTF-8 and percent escaped.
+
+*** TOFU_STATS <validity> <sign-count> 0 [<policy> [<tm1> <tm2>]]
+
+    Statistics for the current user id.
+
+    Values for VALIDITY are:
+    - 0 :: conflict
+    - 1 :: key without history
+    - 2 :: key with too little history
+    - 3 :: key with enough history for basic trust
+    - 4 :: key with a lot of history
+
+    Values for POLICY are:
+    - none    :: No Policy set
+    - auto    :: Policy is "auto"
+    - good    :: Policy is "good"
+    - bad     :: Policy is "bad"
+    - 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.
+
+*** TOFU_STATS_SHORT <long_string>
+
+    Information about the TOFU binding for the signature.
+    Example: "15 signatures verified. 10 messages encrypted"
+
+*** TOFU_STATS_LONG <long_string>
+
+    Information about the TOFU binding for the signature in verbose
+    format.  The LONG_STRING is percent escaped.
+    Example: 'Verified 9 messages signed by "Werner Koch
+    (dist sig)" in the past 3 minutes, 40 seconds.  The most
+    recent message was verified 4 seconds ago.'
+
 *** PKA_TRUST_
     This is is one:
 
index ed8bbbe..5213e03 100644 (file)
 
 #define CONTROL_L ('L' - 'A' + 1)
 
-/* Number of signed messages required to not show extra warnings.  */
-#define NO_WARNING_THRESHOLD 10
+/* Number of signed messages required to indicate that enough history
+ * is available for basic trust.  */
+#define BASIC_TRUST_THRESHOLD  10
+/* Number of signed messages required to indicate that a lot of
+ * history is available.  */
+#define FULL_TRUST_THRESHOLD  100
 
 
 #define DEBUG_TOFU_CACHE 0
@@ -2365,6 +2369,40 @@ time_ago_str (long long int t)
 }
 
 
+/* Write TOFU_STATS status line.  */
+static void
+write_stats_status (long messages, enum tofu_policy policy,
+                    long first_seen_ago, long most_recent_seen_ago)
+{
+  char numbuf1[35];
+  char numbuf2[35];
+  char numbuf3[35];
+  const char *validity;
+
+  if (messages < 1)
+    validity = "1"; /* Key without history.  */
+  else if (messages < BASIC_TRUST_THRESHOLD)
+    validity = "2"; /* Key with too little history.  */
+  else if (messages < FULL_TRUST_THRESHOLD)
+    validity = "3"; /* Key with enough history for basic trust.  */
+  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)
+    {
+      snprintf (numbuf2, sizeof numbuf2, " %ld", first_seen_ago);
+      snprintf (numbuf3, sizeof numbuf3, " %ld", most_recent_seen_ago);
+    }
+
+  write_status_strings (STATUS_TOFU_STATS,
+                        validity, numbuf1, " 0",
+                        " ", tofu_policy_str (policy),
+                        numbuf2, numbuf3,
+                        NULL);
+}
+
 static void
 show_statistics (struct dbs *dbs, const char *fingerprint,
                 const char *email, const char *user_id,
@@ -2407,8 +2445,11 @@ show_statistics (struct dbs *dbs, const char *fingerprint,
                                 email, strlen (email), 0);
 
   if (! strlist)
-    log_info (_("Have never verified a message signed by key %s!\n"),
-              fingerprint_pp);
+    {
+      log_info (_("Have never verified a message signed by key %s!\n"),
+                fingerprint_pp);
+      write_stats_status (0,  TOFU_POLICY_NONE, -1, -1);
+    }
   else
     {
       signed long messages;
@@ -2432,15 +2473,21 @@ show_statistics (struct dbs *dbs, const char *fingerprint,
        }
 
       if (messages == -1 || first_seen_ago == 0)
-        log_info (_("Failed to collect signature statistics for \"%s\"\n"
-                    "(key %s)\n"),
-                  user_id, fingerprint_pp);
+        {
+          write_stats_status (0, TOFU_POLICY_NONE, -1, -1);
+          log_info (_("Failed to collect signature statistics for \"%s\"\n"
+                      "(key %s)\n"),
+                    user_id, fingerprint_pp);
+        }
       else
        {
          enum tofu_policy policy = get_policy (dbs, fingerprint, email, NULL);
          estream_t fp;
          char *msg;
 
+          write_stats_status (messages, policy,
+                              first_seen_ago, most_recent_seen_ago);
+
          fp = es_fopenmem (0, "rw,samethread");
          if (! fp)
             log_fatal ("error creating memory stream: %s\n",
@@ -2497,12 +2544,18 @@ show_statistics (struct dbs *dbs, const char *fingerprint,
             for (p=msg; *p; p++)
               if (*p == '~')
                 *p = ' ';
+
+            /* Print a status line but suppress the trailing LF.
+             * Spaces are not percent escaped. */
+            if (*msg)
+              write_status_buffer (STATUS_TOFU_STATS_LONG,
+                                   msg, strlen (msg)-1, -1);
           }
 
          log_string (GPGRT_LOG_INFO, msg);
           xfree (msg);
 
-         if (policy == TOFU_POLICY_AUTO && messages < NO_WARNING_THRESHOLD)
+         if (policy == TOFU_POLICY_AUTO && messages < BASIC_TRUST_THRESHOLD)
            {
              char *set_policy_command;
              char *text;