agent,g10: Remove redundant SERIALNO request.
[gnupg.git] / g10 / keylist.c
index 60b8f23..32cf1e8 100644 (file)
@@ -16,7 +16,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include "gpg.h"
 #include "options.h"
 #include "packet.h"
-#include "status.h"
+#include "../common/status.h"
 #include "keydb.h"
 #include "photoid.h"
-#include "util.h"
-#include "ttyio.h"
+#include "../common/util.h"
+#include "../common/ttyio.h"
 #include "trustdb.h"
 #include "main.h"
-#include "i18n.h"
-#include "status.h"
+#include "../common/i18n.h"
+#include "../common/status.h"
 #include "call-agent.h"
-#include "mbox-util.h"
-#include "zb32.h"
+#include "../common/mbox-util.h"
+#include "../common/zb32.h"
 #include "tofu.h"
 
 
@@ -134,7 +134,7 @@ public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode)
   check_trustdb_stale (ctrl);
 
 #ifdef USE_TOFU
-  tofu_begin_batch_update ();
+  tofu_begin_batch_update (ctrl);
 #endif
 
   if (locate_mode)
@@ -145,7 +145,7 @@ public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode)
     list_one (ctrl, list, 0, opt.with_secret);
 
 #ifdef USE_TOFU
-  tofu_end_batch_update ();
+  tofu_end_batch_update (ctrl);
 #endif
 }
 
@@ -304,6 +304,7 @@ status_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
 
 
 /* Print a policy URL.  Allowed values for MODE are:
+ *  -1 - print to the TTY
  *   0 - print to stdout.
  *   1 - use log_info and emit status messages.
  *   2 - emit only status messages.
@@ -314,50 +315,48 @@ show_policy_url (PKT_signature * sig, int indent, int mode)
   const byte *p;
   size_t len;
   int seq = 0, crit;
-  estream_t fp = mode ? log_get_stream () : es_stdout;
+  estream_t fp = mode < 0? NULL : mode ? log_get_stream () : es_stdout;
 
   while ((p =
          enum_sig_subpkt (sig->hashed, SIGSUBPKT_POLICY, &len, &seq, &crit)))
     {
       if (mode != 2)
        {
-         int i;
          const char *str;
 
-         for (i = 0; i < indent; i++)
-           es_putc (' ', fp);
+          tty_fprintf (fp, "%*s", indent, "");
 
          if (crit)
            str = _("Critical signature policy: ");
          else
            str = _("Signature policy: ");
-         if (mode)
+         if (mode > 0)
            log_info ("%s", str);
          else
-           es_fprintf (fp, "%s", str);
-         print_utf8_buffer (fp, p, len);
-         es_fprintf (fp, "\n");
+           tty_fprintf (fp, "%s", str);
+         tty_print_utf8_string2 (fp, p, len, 0);
+         tty_fprintf (fp, "\n");
        }
 
-      if (mode)
+      if (mode > 0)
        write_status_buffer (STATUS_POLICY_URL, p, len, 0);
     }
 }
 
 
-/*
-  mode=0 for stdout.
-  mode=1 for log_info + status messages
-  mode=2 for status messages only
-*/
-/* TODO: use this */
+/* Print a keyserver URL.  Allowed values for MODE are:
+ *  -1 - print to the TTY
+ *   0 - print to stdout.
+ *   1 - use log_info and emit status messages.
+ *   2 - emit only status messages.
+ */
 void
 show_keyserver_url (PKT_signature * sig, int indent, int mode)
 {
   const byte *p;
   size_t len;
   int seq = 0, crit;
-  estream_t fp = mode ? log_get_stream () : es_stdout;
+  estream_t fp = mode < 0? NULL : mode ? log_get_stream () : es_stdout;
 
   while ((p =
          enum_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_KS, &len, &seq,
@@ -365,43 +364,43 @@ show_keyserver_url (PKT_signature * sig, int indent, int mode)
     {
       if (mode != 2)
        {
-         int i;
          const char *str;
 
-         for (i = 0; i < indent; i++)
-           es_putc (' ', es_stdout);
+          tty_fprintf (fp, "%*s", indent, "");
 
          if (crit)
            str = _("Critical preferred keyserver: ");
          else
            str = _("Preferred keyserver: ");
-         if (mode)
+         if (mode > 0)
            log_info ("%s", str);
          else
-           es_fprintf (es_stdout, "%s", str);
-         print_utf8_buffer (fp, p, len);
-         es_fprintf (fp, "\n");
+           tty_fprintf (es_stdout, "%s", str);
+         tty_print_utf8_string2 (fp, p, len, 0);
+         tty_fprintf (fp, "\n");
        }
 
-      if (mode)
+      if (mode > 0)
        status_one_subpacket (SIGSUBPKT_PREF_KS, len,
                              (crit ? 0x02 : 0) | 0x01, p);
     }
 }
 
-/*
-  mode=0 for stdout.
-  mode=1 for log_info + status messages
-  mode=2 for status messages only
-
-  Defined bits in WHICH:
-    1 == standard notations
-    2 == user notations
-*/
+
+/* Print notation data.  Allowed values for MODE are:
+ *  -1 - print to the TTY
+ *   0 - print to stdout.
+ *   1 - use log_info and emit status messages.
+ *   2 - emit only status messages.
+ *
+ * Defined bits in WHICH:
+ *   1 - standard notations
+ *   2 - user notations
+ */
 void
 show_notation (PKT_signature * sig, int indent, int mode, int which)
 {
-  estream_t fp = mode ? log_get_stream () : es_stdout;
+  estream_t fp = mode < 0? NULL : mode ? log_get_stream () : es_stdout;
   notation_t nd, notations;
 
   if (which == 0)
@@ -418,34 +417,32 @@ show_notation (PKT_signature * sig, int indent, int mode, int which)
 
          if ((which & 1 && !has_at) || (which & 2 && has_at))
            {
-             int i;
              const char *str;
 
-             for (i = 0; i < indent; i++)
-               es_putc (' ', es_stdout);
+              tty_fprintf (fp, "%*s", indent, "");
 
              if (nd->flags.critical)
                str = _("Critical signature notation: ");
              else
                str = _("Signature notation: ");
-             if (mode)
+             if (mode > 0)
                log_info ("%s", str);
              else
-               es_fprintf (es_stdout, "%s", str);
+               tty_fprintf (es_stdout, "%s", str);
              /* This is all UTF8 */
-             print_utf8_buffer (fp, nd->name, strlen (nd->name));
-             es_fprintf (fp, "=");
-             print_utf8_buffer (fp, nd->value, strlen (nd->value));
+             tty_print_utf8_string2 (fp, nd->name, strlen (nd->name), 0);
+             tty_fprintf (fp, "=");
+             tty_print_utf8_string2 (fp, nd->value, strlen (nd->value), 0);
               /* (We need to use log_printf so that the next call to a
                   log function does not insert an extra LF.)  */
-              if (mode)
+              if (mode > 0)
                 log_printf ("\n");
               else
-                es_putc ('\n', fp);
+                tty_fprintf (fp, "\n");
            }
        }
 
-      if (mode)
+      if (mode > 0)
        {
          write_status_buffer (STATUS_NOTATION_NAME,
                               nd->name, strlen (nd->name), 0);
@@ -468,6 +465,10 @@ print_signature_stats (struct keylist_context *s)
   if (!s->check_sigs)
     return;  /* Signature checking was not requested.  */
 
+  /* Better flush stdout so that the stats are always printed after
+   * the output.  */
+  es_fflush (es_stdout);
+
   if (s->good_sigs)
     log_info (ngettext("%d good signature\n",
                        "%d good signatures\n", s->good_sigs), s->good_sigs);
@@ -650,7 +651,7 @@ locate_one (ctrl_t ctrl, strlist_t names)
 
   for (sl = names; sl; sl = sl->next)
     {
-      rc = get_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, NULL, 1, 0);
+      rc = get_best_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, 1, 0);
       if (rc)
        {
          if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
@@ -852,9 +853,8 @@ dump_attribs (const PKT_user_id *uid, PKT_public_key *pk)
                   (ulong) uid->attribs[i].len, uid->attribs[i].type, i + 1,
                   uid->numattribs, (ulong) uid->created,
                   (ulong) uid->expiredate,
-                  ((uid->is_primary ? 0x01 : 0) | (uid->
-                                                   is_revoked ? 0x02 : 0) |
-                   (uid->is_expired ? 0x04 : 0)));
+                  ((uid->flags.primary ? 0x01 : 0) | (uid->flags.revoked ? 0x02 : 0) |
+                   (uid->flags.expired ? 0x04 : 0)));
          write_status_text (STATUS_ATTRIBUTE, buf);
        }
 
@@ -909,7 +909,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
   /* Print the "pub" line and in KF_NONE mode the fingerprint.  */
   print_key_line (es_stdout, pk, secret);
 
-  if (fpr && opt.keyid_format != KF_NONE)
+  if (fpr)
     print_fingerprint (NULL, pk, 0);
 
   if (opt.with_keygrip && hexgrip)
@@ -929,7 +929,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
           int indent;
           int kl = opt.keyid_format == KF_NONE? 10 : keystrlen ();
 
-         if ((uid->is_expired || uid->is_revoked)
+         if ((uid->flags.expired || uid->flags.revoked)
              && !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
            {
              skip_sigs = 1;
@@ -941,7 +941,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
          if (attrib_fp && uid->attrib_data != NULL)
            dump_attribs (uid, pk);
 
-         if ((uid->is_revoked || uid->is_expired)
+         if ((uid->flags.revoked || uid->flags.expired)
              || ((opt.list_options & LIST_SHOW_UID_VALIDITY)
                   && !listctx->no_validity))
            {
@@ -1183,9 +1183,10 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
   PKT_public_key *pk;
   u32 keyid[2];
   int trustletter = 0;
+  int trustletter_print;
+  int ownertrust_print;
   int ulti_hack = 0;
   int i;
-  char *p;
   char *hexgrip_buffer = NULL;
   const char *hexgrip = NULL;
   char *serialno = NULL;
@@ -1217,31 +1218,38 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
     stubkey = 1;  /* Key not found.  */
 
   keyid_from_pk (pk, keyid);
-  es_fputs (secret? "sec:":"pub:", es_stdout);
   if (!pk->flags.valid)
-    es_putc ('i', es_stdout);
+    trustletter_print = 'i';
   else if (pk->flags.revoked)
-    es_putc ('r', es_stdout);
+    trustletter_print = 'r';
   else if (pk->has_expired)
-    es_putc ('e', es_stdout);
+    trustletter_print = 'e';
   else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
-    ;
+    trustletter_print = 0;
   else
     {
-      trustletter = get_validity_info (ctrl, pk, NULL);
+      trustletter = get_validity_info (ctrl, keyblock, pk, NULL);
       if (trustletter == 'u')
         ulti_hack = 1;
-      es_putc (trustletter, es_stdout);
+      trustletter_print = trustletter;
     }
 
+  if (!opt.fast_list_mode && !opt.no_expensive_trust_checks)
+    ownertrust_print = get_ownertrust_info (pk, 0);
+  else
+    ownertrust_print = 0;
+
+  es_fputs (secret? "sec:":"pub:", es_stdout);
+  if (trustletter_print)
+    es_putc (trustletter_print, es_stdout);
   es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s::",
           nbits_from_pk (pk),
           pk->pubkey_algo,
           (ulong) keyid[0], (ulong) keyid[1],
           colon_datestr_from_pk (pk), colon_strtime (pk->expiredate));
 
-  if (!opt.fast_list_mode && !opt.no_expensive_trust_checks)
-    es_putc (get_ownertrust_info (pk), es_stdout);
+  if (ownertrust_print)
+    es_putc (ownertrust_print, es_stdout);
   es_putc (':', es_stdout);
 
   es_putc (':', es_stdout);
@@ -1286,31 +1294,27 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
     {
       if (node->pkt->pkttype == PKT_USER_ID)
        {
-         char *str;
          PKT_user_id *uid = node->pkt->pkt.user_id;
+          int uid_validity;
+
+         if (attrib_fp && uid->attrib_data != NULL)
+           dump_attribs (uid, pk);
 
-         if (attrib_fp && node->pkt->pkt.user_id->attrib_data != NULL)
-           dump_attribs (node->pkt->pkt.user_id, pk);
-         /*
-          * Fixme: We need a valid flag here too
-          */
-         str = uid->attrib_data ? "uat" : "uid";
-         if (uid->is_revoked)
-           es_fprintf (es_stdout, "%s:r::::", str);
-         else if (uid->is_expired)
-           es_fprintf (es_stdout, "%s:e::::", str);
+         if (uid->flags.revoked)
+           uid_validity = 'r';
+         else if (uid->flags.expired)
+           uid_validity = 'e';
          else if (opt.no_expensive_trust_checks)
-           es_fprintf (es_stdout, "%s:::::", str);
-         else
-           {
-             int uid_validity;
+           uid_validity = 0;
+         else if (ulti_hack)
+            uid_validity = 'u';
+          else
+            uid_validity = get_validity_info (ctrl, keyblock, pk, uid);
 
-             if (!ulti_hack)
-               uid_validity = get_validity_info (ctrl, pk, uid);
-             else
-               uid_validity = 'u';
-             es_fprintf (es_stdout, "%s:%c::::", str, uid_validity);
-           }
+          es_fputs (uid->attrib_data? "uat:":"uid:", es_stdout);
+          if (uid_validity)
+            es_putc (uid_validity, es_stdout);
+          es_fputs ("::::", es_stdout);
 
          es_fprintf (es_stdout, "%s:", colon_strtime (uid->created));
          es_fprintf (es_stdout, "%s:", colon_strtime (uid->expiredate));
@@ -1326,18 +1330,16 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
            es_fprintf (es_stdout, "%u %lu", uid->numattribs, uid->attrib_len);
          else
            es_write_sanitized (es_stdout, uid->name, uid->len, ":", NULL);
-         es_fprintf (es_stdout, "::::::::");
-         if (opt.trust_model == TM_TOFU || opt.trust_model == TM_TOFU_PGP)
-           {
-#ifdef USE_TOFU
-             enum tofu_policy policy;
-             if (! tofu_get_policy (ctrl, pk, uid, &policy)
-                 && policy != TOFU_POLICY_NONE)
-               es_fprintf (es_stdout, "%s", tofu_policy_str (policy));
-#endif /*USE_TOFU*/
-           }
          es_putc (':', es_stdout);
          es_putc ('\n', es_stdout);
+#ifdef USE_TOFU
+         if (!uid->attrib_data && opt.with_tofu_info
+              && (opt.trust_model == TM_TOFU || opt.trust_model == TM_TOFU_PGP))
+           {
+              /* Print a "tfs" record.  */
+              tofu_write_tfs_record (ctrl, es_stdout, pk, uid->name);
+           }
+#endif /*USE_TOFU*/
        }
       else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
        {
@@ -1425,6 +1427,8 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
          char *sigstr;
          size_t fplen;
          byte fparray[MAX_FINGERPRINT_LEN];
+          char *siguid;
+          size_t siguidlen;
 
          if (sig->sig_class == 0x20 || sig->sig_class == 0x28
              || sig->sig_class == 0x30)
@@ -1446,7 +1450,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
            {
              PKT_public_key *signer_pk = NULL;
 
-             fflush (stdout);
+             es_fflush (es_stdout);
              if (opt.no_sig_cache)
                signer_pk = xmalloc_clear (sizeof (PKT_public_key));
 
@@ -1484,6 +1488,16 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
              rc = 0;
              sigrc = ' ';
            }
+
+         if (sigrc != '%' && sigrc != '?' && !opt.fast_list_mode)
+            siguid = get_user_id (sig->keyid, &siguidlen);
+          else
+            {
+              siguid = NULL;
+              siguidlen = 0;
+            }
+
+
          es_fputs (sigstr, es_stdout);
          es_putc (':', es_stdout);
          if (sigrc != ' ')
@@ -1504,17 +1518,11 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
 
          if (sigrc == '%')
            es_fprintf (es_stdout, "[%s] ", gpg_strerror (rc));
-         else if (sigrc == '?')
-           ;
-         else if (!opt.fast_list_mode)
-           {
-             size_t n;
-             p = get_user_id (sig->keyid, &n);
-             es_write_sanitized (es_stdout, p, n, ":", NULL);
-             xfree (p);
-           }
+         else if (siguid)
+            es_write_sanitized (es_stdout, siguid, siguidlen, ":", NULL);
+
          es_fprintf (es_stdout, ":%02x%c::", sig->sig_class,
-                 sig->flags.exportable ? 'x' : 'l');
+                      sig->flags.exportable ? 'x' : 'l');
 
          if (opt.no_sig_cache && opt.check_sigs && fprokay)
            {
@@ -1528,6 +1536,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
            print_subpackets_colon (sig);
 
          /* fixme: check or list other sigs here */
+          xfree (siguid);
        }
     }
 
@@ -1550,7 +1559,7 @@ do_reorder_keyblock (KBNODE keyblock, int attr)
       if (node->pkt->pkttype == PKT_USER_ID &&
          ((attr && node->pkt->pkt.user_id->attrib_data) ||
           (!attr && !node->pkt->pkt.user_id->attrib_data)) &&
-         node->pkt->pkt.user_id->is_primary)
+         node->pkt->pkt.user_id->flags.primary)
        {
          primary = primary2 = node;
          for (node = node->next; node; primary2 = node, node = node->next)
@@ -1679,7 +1688,7 @@ print_fingerprint (estream_t override_fp, PKT_public_key *pk, int mode)
     }
 
   if (!opt.fingerprint && !opt.with_fingerprint
-      && opt.with_subkey_fingerprint && opt.keyid_format == KF_NONE)
+      && opt.with_subkey_fingerprint)
     compact = 1;
 
   if (pk->main_keyid[0] == pk->keyid[0]
@@ -1871,7 +1880,10 @@ print_key_line (estream_t fp, PKT_public_key *pk, int secret)
 
   tty_fprintf (fp, "\n");
 
-  if (pk->flags.primary && opt.keyid_format == KF_NONE)
+  /* if the user hasn't explicitly asked for human-readable
+     fingerprints, show compact fpr of primary key: */
+  if (pk->flags.primary &&
+      !opt.fingerprint && !opt.with_fingerprint)
     print_fingerprint (fp, pk, 20);
 }
 
@@ -1891,6 +1903,9 @@ set_attrib_fd (int fd)
   if (fd == -1)
     return;
 
+  if (! gnupg_fd_valid (fd))
+    log_fatal ("attribute-fd is invalid: %s\n", strerror (errno));
+
 #ifdef HAVE_DOSISH_SYSTEM
   setmode (fd, O_BINARY);
 #endif