Adjust for changed macro names in libgpg-error master.
[gnupg.git] / g10 / keylist.c
index b8f32be..bcbad45 100644 (file)
@@ -44,6 +44,8 @@
 #include "../common/mbox-util.h"
 #include "../common/zb32.h"
 #include "tofu.h"
+#include "../common/compliance.h"
+#include "../common/pkscreening.h"
 
 
 static void list_all (ctrl_t, int, int);
@@ -92,7 +94,7 @@ public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode)
       byte trust_model, marginals, completes, cert_depth, min_cert_level;
       ulong created, nextcheck;
 
-      read_trust_options (&trust_model, &created, &nextcheck,
+      read_trust_options (ctrl, &trust_model, &created, &nextcheck,
                          &marginals, &completes, &cert_depth, &min_cert_level);
 
       es_fprintf (es_stdout, "tru:");
@@ -164,7 +166,7 @@ secret_key_list (ctrl_t ctrl, strlist_t list)
 }
 
 char *
-format_seckey_info (PKT_public_key *pk)
+format_seckey_info (ctrl_t ctrl, PKT_public_key *pk)
 {
   u32 keyid[2];
   char *p;
@@ -172,7 +174,7 @@ format_seckey_info (PKT_public_key *pk)
   char *info;
 
   keyid_from_pk (pk, keyid);
-  p = get_user_id_native (keyid);
+  p = get_user_id_native (ctrl, keyid);
 
   info = xtryasprintf ("sec  %s/%s %s %s",
                        pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
@@ -184,18 +186,18 @@ format_seckey_info (PKT_public_key *pk)
 }
 
 void
-print_seckey_info (PKT_public_key *pk)
+print_seckey_info (ctrl_t ctrl, PKT_public_key *pk)
 {
-  char *p = format_seckey_info (pk);
+  char *p = format_seckey_info (ctrl, pk);
   tty_printf ("\n%s\n", p);
   xfree (p);
 }
 
 /* Print information about the public key.  With FP passed as NULL,
-   the tty output interface is used, otherwise output is directted to
+   the tty output interface is used, otherwise output is directed to
    the given stream.  */
 void
-print_pubkey_info (estream_t fp, PKT_public_key *pk)
+print_pubkey_info (ctrl_t ctrl, estream_t fp, PKT_public_key *pk)
 {
   u32 keyid[2];
   char *p;
@@ -208,7 +210,7 @@ print_pubkey_info (estream_t fp, PKT_public_key *pk)
   if (pk->user_id)
     p = utf8_to_native (pk->user_id->name, pk->user_id->len, 0);
   else
-    p = get_user_id_native (keyid);
+    p = get_user_id_native (ctrl, keyid);
 
   if (fp)
     tty_printf ("\n");
@@ -375,7 +377,7 @@ show_keyserver_url (PKT_signature * sig, int indent, int mode)
          if (mode > 0)
            log_info ("%s", str);
          else
-           tty_fprintf (es_stdout, "%s", str);
+           tty_fprintf (fp, "%s", str);
          tty_print_utf8_string2 (fp, p, len, 0);
          tty_fprintf (fp, "\n");
        }
@@ -428,7 +430,7 @@ show_notation (PKT_signature * sig, int indent, int mode, int which)
              if (mode > 0)
                log_info ("%s", str);
              else
-               tty_fprintf (es_stdout, "%s", str);
+               tty_fprintf (fp, "%s", str);
              /* This is all UTF8 */
              tty_print_utf8_string2 (fp, nd->name, strlen (nd->name), 0);
              tty_fprintf (fp, "=");
@@ -553,7 +555,7 @@ list_all (ctrl_t ctrl, int secret, int mark_secret)
                   lastresname = resname;
                 }
             }
-          merge_keys_and_selfsig (keyblock);
+          merge_keys_and_selfsig (ctrl, keyblock);
           list_keyblock (ctrl, keyblock, secret, any_secret, opt.fingerprint,
                          &listctx);
         }
@@ -596,7 +598,7 @@ list_one (ctrl_t ctrl, strlist_t names, int secret, int mark_secret)
     listctx.check_sigs = 1;
 
   /* fixme: using the bynames function has the disadvantage that we
-   * don't know wether one of the names given was not found.  OTOH,
+   * don't know whether one of the names given was not found.  OTOH,
    * this function has the advantage to list the names in the
    * sequence as defined by the keyDB and does not duplicate
    * outputs.  A solution could be do test whether all given have
@@ -604,11 +606,11 @@ list_one (ctrl_t ctrl, strlist_t names, int secret, int mark_secret)
    * functions) or to have the search function return indicators for
    * found names.  Yet another way is to use the keydb search
    * facilities directly. */
-  rc = getkey_bynames (&ctx, NULL, names, secret, &keyblock);
+  rc = getkey_bynames (ctrl, &ctx, NULL, names, secret, &keyblock);
   if (rc)
     {
       log_error ("error reading key: %s\n", gpg_strerror (rc));
-      getkey_end (ctx);
+      getkey_end (ctrl, ctx);
       return;
     }
 
@@ -626,8 +628,8 @@ list_one (ctrl_t ctrl, strlist_t names, int secret, int mark_secret)
                      keyblock, secret, mark_secret, opt.fingerprint, &listctx);
       release_kbnode (keyblock);
     }
-  while (!getkey_next (ctx, NULL, &keyblock));
-  getkey_end (ctx);
+  while (!getkey_next (ctrl, ctx, NULL, &keyblock));
+  getkey_end (ctrl, ctx);
 
   if (opt.check_sigs && !opt.with_colons)
     print_signature_stats (&listctx);
@@ -667,8 +669,8 @@ locate_one (ctrl_t ctrl, strlist_t names)
              list_keyblock (ctrl, keyblock, 0, 0, opt.fingerprint, &listctx);
              release_kbnode (keyblock);
            }
-         while (ctx && !getkey_next (ctx, NULL, &keyblock));
-         getkey_end (ctx);
+         while (ctx && !getkey_next (ctrl, ctx, NULL, &keyblock));
+         getkey_end (ctrl, ctx);
          ctx = NULL;
        }
     }
@@ -695,8 +697,39 @@ print_key_data (PKT_public_key * pk)
     }
 }
 
+
+/* Various public key screenings.  (Right now just ROCA).  With
+ * COLON_MODE set the output is formatted for use in the compliance
+ * field of a colon listing.
+ */
+static void
+print_pk_screening (PKT_public_key *pk, int colon_mode)
+{
+  gpg_error_t err;
+
+  if (is_RSA (pk->pubkey_algo) && pubkey_get_npkey (pk->pubkey_algo))
+    {
+      err = screen_key_for_roca (pk->pkey[0]);
+      if (!err)
+        ;
+      else if (gpg_err_code (err) == GPG_ERR_TRUE)
+        {
+          if (colon_mode)
+            es_fprintf (es_stdout, colon_mode > 1? " %d":"%d", 6001);
+          else
+            es_fprintf (es_stdout,
+                        "      Screening: ROCA vulnerability detected\n");
+        }
+      else if (!colon_mode)
+        es_fprintf (es_stdout, "      Screening: [ROCA check failed: %s]\n",
+                    gpg_strerror (err));
+    }
+
+}
+
+
 static void
-print_capabilities (PKT_public_key *pk, KBNODE keyblock)
+print_capabilities (ctrl_t ctrl, PKT_public_key *pk, KBNODE keyblock)
 {
   unsigned int use = pk->pubkey_usage;
   int c_printed = 0;
@@ -907,10 +940,10 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
     check_trustdb_stale (ctrl);
 
   /* Print the "pub" line and in KF_NONE mode the fingerprint.  */
-  print_key_line (es_stdout, pk, secret);
+  print_key_line (ctrl, es_stdout, pk, secret);
 
   if (fpr)
-    print_fingerprint (NULL, pk, 0);
+    print_fingerprint (ctrl, NULL, pk, 0);
 
   if (opt.with_keygrip && hexgrip)
     es_fprintf (es_stdout, "      Keygrip = %s\n", hexgrip);
@@ -921,6 +954,24 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
   if (opt.with_key_data)
     print_key_data (pk);
 
+  if (opt.with_key_screening)
+    print_pk_screening (pk, 0);
+
+  if (opt.with_key_origin
+      && (pk->keyorg || pk->keyupdate || pk->updateurl))
+    {
+      char updatestr[MK_DATESTR_SIZE];
+
+      es_fprintf (es_stdout, "      origin=%s last=%s %s",
+                  key_origin_string (pk->keyorg),
+                  mk_datestr (updatestr, sizeof updatestr, pk->keyupdate),
+                  pk->updateurl? "url=":"");
+      if (pk->updateurl)
+        print_utf8_string (es_stdout, pk->updateurl);
+      es_putc ('\n', es_stdout);
+    }
+
+
   for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
     {
       if (node->pkt->pkttype == PKT_USER_ID)
@@ -986,6 +1037,22 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
               xfree (mbox);
             }
 
+          if (opt.with_key_origin
+              && (uid->keyorg || uid->keyupdate || uid->updateurl))
+            {
+              char updatestr[MK_DATESTR_SIZE];
+
+              es_fprintf (es_stdout, "   %*sorigin=%s last=%s %s",
+                          indent, "",
+                          key_origin_string (uid->keyorg),
+                          mk_datestr (updatestr, sizeof updatestr,
+                                      uid->keyupdate),
+                          uid->updateurl? "url=":"");
+              if (uid->updateurl)
+                print_utf8_string (es_stdout, uid->updateurl);
+              es_putc ('\n', es_stdout);
+            }
+
          if ((opt.list_options & LIST_SHOW_PHOTOS) && uid->attribs != NULL)
            show_photos (ctrl, uid->attribs, uid->numattribs, pk, uid);
        }
@@ -1016,14 +1083,14 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
               if (!agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
                 secret = serialno? 3 : 1;
               else
-                secret = '2';  /* Key not found.  */
+                secret = 2;  /* Key not found.  */
             }
 
           /* Print the "sub" line.  */
-          print_key_line (es_stdout, pk2, secret);
+          print_key_line (ctrl, es_stdout, pk2, secret);
          if (fpr > 1 || opt.with_subkey_fingerprint)
             {
-              print_fingerprint (NULL, pk2, 0);
+              print_fingerprint (ctrl, NULL, pk2, 0);
               if (serialno)
                 print_card_serialno (serialno);
             }
@@ -1031,6 +1098,8 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
             es_fprintf (es_stdout, "      Keygrip = %s\n", hexgrip);
          if (opt.with_key_data)
            print_key_data (pk2);
+          if (opt.with_key_screening)
+            print_pk_screening (pk2, 0);
        }
       else if (opt.list_sigs
               && node->pkt->pkttype == PKT_SIGNATURE && !skip_sigs)
@@ -1041,7 +1110,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
 
          if (listctx->check_sigs)
            {
-             rc = check_key_signature (keyblock, node, NULL);
+             rc = check_key_signature (ctrl, keyblock, node, NULL);
              switch (gpg_err_code (rc))
                {
                case 0:
@@ -1113,7 +1182,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
          else if (!opt.fast_list_mode)
            {
              size_t n;
-             char *p = get_user_id (sig->keyid, &n);
+             char *p = get_user_id (ctrl, sig->keyid, &n);
              print_utf8_buffer (es_stdout, p, n);
              xfree (p);
            }
@@ -1180,16 +1249,24 @@ print_compliance_flags (PKT_public_key *pk,
 {
   int any = 0;
 
+  if (!keylength)
+    keylength = nbits_from_pk (pk);
+
   if (pk->version == 5)
     {
-      es_fputs ("8", es_stdout);
+      es_fputs (gnupg_status_compliance_flag (CO_GNUPG), es_stdout);
       any++;
     }
-  if (gnupg_pk_is_compliant (CO_DE_VS, pk, keylength, curvename))
+  if (gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
+                            keylength, curvename))
     {
-      es_fputs (any? " 23":"23", es_stdout);
+      es_fprintf (es_stdout, any ? " %s" : "%s",
+                 gnupg_status_compliance_flag (CO_DE_VS));
       any++;
     }
+
+  if (opt.with_key_screening)
+    print_pk_screening (pk, 1+any);
 }
 
 
@@ -1261,7 +1338,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
     }
 
   if (!opt.fast_list_mode && !opt.no_expensive_trust_checks)
-    ownertrust_print = get_ownertrust_info (pk, 0);
+    ownertrust_print = get_ownertrust_info (ctrl, pk, 0);
   else
     ownertrust_print = 0;
 
@@ -1282,7 +1359,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
 
   es_putc (':', es_stdout);
   es_putc (':', es_stdout);
-  print_capabilities (pk, keyblock);
+  print_capabilities (ctrl, pk, keyblock);
   es_putc (':', es_stdout);            /* End of field 13. */
   es_putc (':', es_stdout);            /* End of field 14. */
   if (secret || has_secret)
@@ -1308,11 +1385,19 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
     }
   es_putc (':', es_stdout);            /* End of field 17. */
   print_compliance_flags (pk, keylength, curvename);
-  es_putc (':', es_stdout);            /* End of field 18. */
+  es_putc (':', es_stdout);            /* End of field 18 (compliance). */
+  if (pk->keyupdate)
+    es_fputs (colon_strtime (pk->keyupdate), es_stdout);
+  es_putc (':', es_stdout);            /* End of field 19 (last_update). */
+  es_fprintf (es_stdout, "%d%s", pk->keyorg, pk->updateurl? " ":"");
+  if (pk->updateurl)
+    es_write_sanitized (es_stdout, pk->updateurl, strlen (pk->updateurl),
+                        ":", NULL);
+  es_putc (':', es_stdout);            /* End of field 20 (origin). */
   es_putc ('\n', es_stdout);
 
   print_revokers (es_stdout, pk);
-  print_fingerprint (NULL, pk, 0);
+  print_fingerprint (ctrl, NULL, pk, 0);
   if (hexgrip)
     es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
   if (opt.with_key_data)
@@ -1358,7 +1443,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_putc (':', es_stdout);
+         es_fputs (":::::::::", es_stdout);
+          if (uid->keyupdate)
+            es_fputs (colon_strtime (uid->keyupdate), es_stdout);
+          es_putc (':', es_stdout);    /* End of field 19 (last_update). */
+          es_fprintf (es_stdout, "%d%s", uid->keyorg, uid->updateurl? " ":"");
+          if (uid->updateurl)
+            es_write_sanitized (es_stdout,
+                                uid->updateurl, strlen (uid->updateurl),
+                                ":", NULL);
+          es_putc (':', es_stdout);    /* End of field 20 (origin). */
          es_putc ('\n', es_stdout);
 #ifdef USE_TOFU
          if (!uid->attrib_data && opt.with_tofu_info
@@ -1415,7 +1509,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
                       (ulong) keyid2[0], (ulong) keyid2[1],
                       colon_datestr_from_pk (pk2),
                       colon_strtime (pk2->expiredate));
-         print_capabilities (pk2, NULL);
+         print_capabilities (ctrl, pk2, NULL);
           es_putc (':', es_stdout);    /* End of field 13. */
           es_putc (':', es_stdout);    /* End of field 14. */
           if (secret || has_secret)
@@ -1444,7 +1538,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
           print_compliance_flags (pk2, keylength, curvename);
           es_putc (':', es_stdout);    /* End of field 18. */
          es_putc ('\n', es_stdout);
-          print_fingerprint (NULL, pk2, 0);
+          print_fingerprint (ctrl, NULL, pk2, 0);
           if (hexgrip)
             es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
           if (opt.with_key_data)
@@ -1484,7 +1578,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
              if (opt.no_sig_cache)
                signer_pk = xmalloc_clear (sizeof (PKT_public_key));
 
-             rc = check_key_signature2 (keyblock, node, NULL, signer_pk,
+             rc = check_key_signature2 (ctrl, keyblock, node, NULL, signer_pk,
                                         NULL, NULL, NULL);
              switch (gpg_err_code (rc))
                {
@@ -1520,7 +1614,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
            }
 
          if (sigrc != '%' && sigrc != '?' && !opt.fast_list_mode)
-            siguid = get_user_id (sig->keyid, &siguidlen);
+            siguid = get_user_id (ctrl, sig->keyid, &siguidlen);
           else
             {
               siguid = NULL;
@@ -1693,7 +1787,8 @@ print_icao_hexdigit (estream_t fp, int c)
  * of es_stdout or instead of the TTY in modes 2 and 3.
  */
 void
-print_fingerprint (estream_t override_fp, PKT_public_key *pk, int mode)
+print_fingerprint (ctrl_t ctrl, estream_t override_fp,
+                   PKT_public_key *pk, int mode)
 {
   char hexfpr[2*MAX_FINGERPRINT_LEN+1];
   char *p;
@@ -1738,8 +1833,8 @@ print_fingerprint (estream_t override_fp, PKT_public_key *pk, int mode)
   if (!primary && (mode == 1 || mode == 2))
     {
       PKT_public_key *primary_pk = xmalloc_clear (sizeof (*primary_pk));
-      get_pubkey (primary_pk, pk->main_keyid);
-      print_fingerprint (override_fp, primary_pk, (mode | 0x80));
+      get_pubkey (ctrl, primary_pk, pk->main_keyid);
+      print_fingerprint (ctrl, override_fp, primary_pk, (mode | 0x80));
       free_public_key (primary_pk);
     }
 
@@ -1851,6 +1946,9 @@ print_card_serialno (const char *serialno)
  * pub   dsa2048 2007-12-31 [SC] [expires: 2018-12-31]
  *       80615870F5BAD690333686D0F2AD85AC1E42B367
  *
+ * pub   rsa2048 2017-12-31 [SC] [expires: 2028-12-31]
+ *       80615870F5BAD690333686D0F2AD85AC1E42B3671122334455
+ *
  * Some global options may result in a different output format.  If
  * SECRET is set, "sec" or "ssb" is used instead of "pub" or "sub" and
  * depending on the value a flag character is shown:
@@ -1860,7 +1958,7 @@ print_card_serialno (const char *serialno)
  *    3 := '>' Secret key is on a token.
  */
 void
-print_key_line (estream_t fp, PKT_public_key *pk, int secret)
+print_key_line (ctrl_t ctrl, estream_t fp, PKT_public_key *pk, int secret)
 {
   char pkstrbuf[PUBKEY_STRING_SIZE];
 
@@ -1915,7 +2013,7 @@ print_key_line (estream_t fp, PKT_public_key *pk, int secret)
      fingerprints, show compact fpr of primary key: */
   if (pk->flags.primary &&
       !opt.fingerprint && !opt.with_fingerprint)
-    print_fingerprint (fp, pk, 20);
+    print_fingerprint (ctrl, fp, pk, 20);
 }