LCOV - code coverage report
Current view: top level - g10 - keylist.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 352 1005 35.0 %
Date: 2015-11-05 17:10:59 Functions: 14 31 45.2 %

          Line data    Source code
       1             : /* keylist.c - Print information about OpenPGP keys
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
       3             :  *               2008, 2010, 2012 Free Software Foundation, Inc.
       4             :  * Copyright (C) 2013, 2014  Werner Koch
       5             :  *
       6             :  * This file is part of GnuPG.
       7             :  *
       8             :  * GnuPG is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU General Public License as published by
      10             :  * the Free Software Foundation; either version 3 of the License, or
      11             :  * (at your option) any later version.
      12             :  *
      13             :  * GnuPG is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  * GNU General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License
      19             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include <config.h>
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : #include <errno.h>
      27             : #include <assert.h>
      28             : #ifdef HAVE_DOSISH_SYSTEM
      29             : #include <fcntl.h>                /* for setmode() */
      30             : #endif
      31             : 
      32             : #include "gpg.h"
      33             : #include "options.h"
      34             : #include "packet.h"
      35             : #include "status.h"
      36             : #include "keydb.h"
      37             : #include "photoid.h"
      38             : #include "util.h"
      39             : #include "ttyio.h"
      40             : #include "trustdb.h"
      41             : #include "main.h"
      42             : #include "i18n.h"
      43             : #include "status.h"
      44             : #include "call-agent.h"
      45             : #include "mbox-util.h"
      46             : #include "zb32.h"
      47             : #include "tofu.h"
      48             : 
      49             : 
      50             : static void list_all (ctrl_t, int, int);
      51             : static void list_one (ctrl_t ctrl,
      52             :                       strlist_t names, int secret, int mark_secret);
      53             : static void locate_one (ctrl_t ctrl, strlist_t names);
      54             : static void print_card_serialno (const char *serialno);
      55             : 
      56             : struct keylist_context
      57             : {
      58             :   int check_sigs;  /* If set signatures shall be verified.  */
      59             :   int good_sigs;   /* Counter used if CHECK_SIGS is set.  */
      60             :   int inv_sigs;    /* Counter used if CHECK_SIGS is set.  */
      61             :   int no_key;      /* Counter used if CHECK_SIGS is set.  */
      62             :   int oth_err;     /* Counter used if CHECK_SIGS is set.  */
      63             : };
      64             : 
      65             : 
      66             : static void list_keyblock (ctrl_t ctrl,
      67             :                            kbnode_t keyblock, int secret, int has_secret,
      68             :                            int fpr, struct keylist_context *listctx);
      69             : 
      70             : 
      71             : /* The stream used to write attribute packets to.  */
      72             : static estream_t attrib_fp;
      73             : 
      74             : 
      75             : /* Release resources from a keylist context.  */
      76             : static void
      77          87 : keylist_context_release (struct keylist_context *listctx)
      78             : {
      79             :   (void)listctx; /* Nothing to release.  */
      80          87 : }
      81             : 
      82             : 
      83             : /* List the keys.  If list is NULL, all available keys are listed.
      84             :    With LOCATE_MODE set the locate algorithm is used to find a
      85             :    key.  */
      86             : void
      87          87 : public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode)
      88             : {
      89             : #ifndef NO_TRUST_MODELS
      90          87 :   if (opt.with_colons)
      91             :     {
      92             :       byte trust_model, marginals, completes, cert_depth, min_cert_level;
      93             :       ulong created, nextcheck;
      94             : 
      95          84 :       read_trust_options (&trust_model, &created, &nextcheck,
      96             :                           &marginals, &completes, &cert_depth, &min_cert_level);
      97             : 
      98          84 :       es_fprintf (es_stdout, "tru:");
      99             : 
     100          84 :       if (nextcheck && nextcheck <= make_timestamp ())
     101          84 :         es_fprintf (es_stdout, "o");
     102          84 :       if (trust_model != opt.trust_model)
     103          82 :         es_fprintf (es_stdout, "t");
     104          84 :       if (opt.trust_model == TM_PGP || opt.trust_model == TM_CLASSIC
     105          82 :           || opt.trust_model == TM_TOFU_PGP)
     106             :         {
     107           2 :           if (marginals != opt.marginals_needed)
     108           0 :             es_fprintf (es_stdout, "m");
     109           2 :           if (completes != opt.completes_needed)
     110           0 :             es_fprintf (es_stdout, "c");
     111           2 :           if (cert_depth != opt.max_cert_depth)
     112           0 :             es_fprintf (es_stdout, "d");
     113           2 :           if (min_cert_level != opt.min_cert_level)
     114           0 :             es_fprintf (es_stdout, "l");
     115             :         }
     116             : 
     117          84 :       es_fprintf (es_stdout, ":%d:%lu:%lu", trust_model, created, nextcheck);
     118             : 
     119             :       /* Only show marginals, completes, and cert_depth in the classic
     120             :          or PGP trust models since they are not meaningful
     121             :          otherwise. */
     122             : 
     123          84 :       if (trust_model == TM_PGP || trust_model == TM_CLASSIC)
     124          84 :         es_fprintf (es_stdout, ":%d:%d:%d", marginals, completes, cert_depth);
     125          84 :       es_fprintf (es_stdout, "\n");
     126             :     }
     127             : #endif /*!NO_TRUST_MODELS*/
     128             : 
     129             :   /* We need to do the stale check right here because it might need to
     130             :      update the keyring while we already have the keyring open.  This
     131             :      is very bad for W32 because of a sharing violation. For real OSes
     132             :      it might lead to false results if we are later listing a keyring
     133             :      which is associated with the inode of a deleted file.  */
     134          87 :   check_trustdb_stale ();
     135             : 
     136             : #ifdef USE_TOFU
     137          87 :   tofu_begin_batch_update ();
     138             : #endif
     139             : 
     140          87 :   if (locate_mode)
     141           0 :     locate_one (ctrl, list);
     142          87 :   else if (!list)
     143           0 :     list_all (ctrl, 0, opt.with_secret);
     144             :   else
     145          87 :     list_one (ctrl, list, 0, opt.with_secret);
     146             : 
     147             : #ifdef USE_TOFU
     148          87 :   tofu_end_batch_update ();
     149             : #endif
     150          87 : }
     151             : 
     152             : 
     153             : void
     154           0 : secret_key_list (ctrl_t ctrl, strlist_t list)
     155             : {
     156             :   (void)ctrl;
     157             : 
     158           0 :   check_trustdb_stale ();
     159             : 
     160           0 :   if (!list)
     161           0 :     list_all (ctrl, 1, 0);
     162             :   else                          /* List by user id */
     163           0 :     list_one (ctrl, list, 1, 0);
     164           0 : }
     165             : 
     166             : void
     167           0 : print_seckey_info (PKT_public_key *pk)
     168             : {
     169             :   u32 keyid[2];
     170             :   char *p;
     171             :   char pkstrbuf[PUBKEY_STRING_SIZE];
     172             : 
     173           0 :   keyid_from_pk (pk, keyid);
     174           0 :   p = get_user_id_native (keyid);
     175             : 
     176           0 :   tty_printf ("\nsec  %s/%s %s %s\n",
     177             :               pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
     178             :               keystr (keyid), datestr_from_pk (pk), p);
     179             : 
     180           0 :   xfree (p);
     181           0 : }
     182             : 
     183             : /* Print information about the public key.  With FP passed as NULL,
     184             :    the tty output interface is used, otherwise output is directted to
     185             :    the given stream.  */
     186             : void
     187           0 : print_pubkey_info (estream_t fp, PKT_public_key *pk)
     188             : {
     189             :   u32 keyid[2];
     190             :   char *p;
     191             :   char pkstrbuf[PUBKEY_STRING_SIZE];
     192             : 
     193           0 :   keyid_from_pk (pk, keyid);
     194             : 
     195             :   /* If the pk was chosen by a particular user ID, that is the one to
     196             :      print.  */
     197           0 :   if (pk->user_id)
     198           0 :     p = utf8_to_native (pk->user_id->name, pk->user_id->len, 0);
     199             :   else
     200           0 :     p = get_user_id_native (keyid);
     201             : 
     202           0 :   if (fp)
     203           0 :     tty_printf ("\n");
     204           0 :   tty_fprintf (fp, "%s  %s/%s %s %s\n",
     205           0 :                pk->flags.primary? "pub":"sub",
     206             :                pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
     207             :                keystr (keyid), datestr_from_pk (pk), p);
     208           0 :   xfree (p);
     209           0 : }
     210             : 
     211             : 
     212             : /* Print basic information of a secret key including the card serial
     213             :    number information.  */
     214             : #ifdef ENABLE_CARD_SUPPORT
     215             : void
     216           0 : print_card_key_info (estream_t fp, kbnode_t keyblock)
     217             : {
     218             :   kbnode_t node;
     219             :   char *hexgrip;
     220             :   char *serialno;
     221             :   int s2k_char;
     222             :   char pkstrbuf[PUBKEY_STRING_SIZE];
     223             :   int indent;
     224             : 
     225           0 :   for (node = keyblock; node; node = node->next)
     226             :     {
     227           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY
     228           0 :           || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
     229             :         {
     230             :           int rc;
     231           0 :           PKT_public_key *pk = node->pkt->pkt.public_key;
     232             : 
     233           0 :           serialno = NULL;
     234           0 :           rc = hexkeygrip_from_pk (pk, &hexgrip);
     235           0 :           if (rc)
     236             :             {
     237           0 :               log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
     238           0 :               s2k_char = '?';
     239             :             }
     240           0 :           else if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
     241           0 :             s2k_char = serialno? '>':' ';
     242             :           else
     243           0 :             s2k_char = '#';  /* Key not found.  */
     244             : 
     245           0 :           tty_fprintf (fp, "%s%c  %s/%s  %n",
     246           0 :                        node->pkt->pkttype == PKT_PUBLIC_KEY ? "sec" : "ssb",
     247             :                        s2k_char,
     248             :                        pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
     249             :                        keystr_from_pk (pk),
     250             :                        &indent);
     251           0 :           tty_fprintf (fp, _("created: %s"), datestr_from_pk (pk));
     252           0 :           tty_fprintf (fp, "  ");
     253           0 :           tty_fprintf (fp, _("expires: %s"), expirestr_from_pk (pk));
     254           0 :           if (serialno)
     255             :             {
     256           0 :               tty_fprintf (fp, "\n%*s%s", indent, "", _("card-no: "));
     257           0 :               if (strlen (serialno) == 32
     258           0 :                   && !strncmp (serialno, "D27600012401", 12))
     259             :                 {
     260             :                   /* This is an OpenPGP card.  Print the relevant part.  */
     261             :                   /* Example: D2760001240101010001000003470000 */
     262             :                   /*                          xxxxyyyyyyyy     */
     263           0 :                   tty_fprintf (fp, "%.*s %.*s", 4, serialno+16, 8, serialno+20);
     264             :                 }
     265             :               else
     266           0 :                 tty_fprintf (fp, "%s", serialno);
     267             :             }
     268           0 :           tty_fprintf (fp, "\n");
     269           0 :           xfree (hexgrip);
     270           0 :           xfree (serialno);
     271             :         }
     272             :     }
     273           0 : }
     274             : #endif /*ENABLE_CARD_SUPPORT*/
     275             : 
     276             : 
     277             : /* Flags = 0x01 hashed 0x02 critical.  */
     278             : static void
     279           0 : status_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
     280             :                       const byte * buf)
     281             : {
     282             :   char status[40];
     283             : 
     284             :   /* Don't print these. */
     285           0 :   if (len > 256)
     286           0 :     return;
     287             : 
     288           0 :   snprintf (status, sizeof status,
     289             :             "%d %u %u ", type, flags, (unsigned int) len);
     290             : 
     291           0 :   write_status_text_and_buffer (STATUS_SIG_SUBPACKET, status, buf, len, 0);
     292             : }
     293             : 
     294             : 
     295             : /* Print a policy URL.  Allowed values for MODE are:
     296             :  *   0 - print to stdout.
     297             :  *   1 - use log_info and emit status messages.
     298             :  *   2 - emit only status messages.
     299             :  */
     300             : void
     301         143 : show_policy_url (PKT_signature * sig, int indent, int mode)
     302             : {
     303             :   const byte *p;
     304             :   size_t len;
     305         143 :   int seq = 0, crit;
     306         143 :   estream_t fp = mode ? log_get_stream () : es_stdout;
     307             : 
     308         286 :   while ((p =
     309         143 :           enum_sig_subpkt (sig->hashed, SIGSUBPKT_POLICY, &len, &seq, &crit)))
     310             :     {
     311           0 :       if (mode != 2)
     312             :         {
     313             :           int i;
     314             :           const char *str;
     315             : 
     316           0 :           for (i = 0; i < indent; i++)
     317           0 :             es_putc (' ', fp);
     318             : 
     319           0 :           if (crit)
     320           0 :             str = _("Critical signature policy: ");
     321             :           else
     322           0 :             str = _("Signature policy: ");
     323           0 :           if (mode)
     324           0 :             log_info ("%s", str);
     325             :           else
     326           0 :             es_fprintf (fp, "%s", str);
     327           0 :           print_utf8_buffer (fp, p, len);
     328           0 :           es_fprintf (fp, "\n");
     329             :         }
     330             : 
     331           0 :       if (mode)
     332           0 :         write_status_buffer (STATUS_POLICY_URL, p, len, 0);
     333             :     }
     334         143 : }
     335             : 
     336             : 
     337             : /*
     338             :   mode=0 for stdout.
     339             :   mode=1 for log_info + status messages
     340             :   mode=2 for status messages only
     341             : */
     342             : /* TODO: use this */
     343             : void
     344         143 : show_keyserver_url (PKT_signature * sig, int indent, int mode)
     345             : {
     346             :   const byte *p;
     347             :   size_t len;
     348         143 :   int seq = 0, crit;
     349         143 :   estream_t fp = mode ? log_get_stream () : es_stdout;
     350             : 
     351         286 :   while ((p =
     352         143 :           enum_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_KS, &len, &seq,
     353             :                            &crit)))
     354             :     {
     355           0 :       if (mode != 2)
     356             :         {
     357             :           int i;
     358             :           const char *str;
     359             : 
     360           0 :           for (i = 0; i < indent; i++)
     361           0 :             es_putc (' ', es_stdout);
     362             : 
     363           0 :           if (crit)
     364           0 :             str = _("Critical preferred keyserver: ");
     365             :           else
     366           0 :             str = _("Preferred keyserver: ");
     367           0 :           if (mode)
     368           0 :             log_info ("%s", str);
     369             :           else
     370           0 :             es_fprintf (es_stdout, "%s", str);
     371           0 :           print_utf8_buffer (fp, p, len);
     372           0 :           es_fprintf (fp, "\n");
     373             :         }
     374             : 
     375           0 :       if (mode)
     376           0 :         status_one_subpacket (SIGSUBPKT_PREF_KS, len,
     377           0 :                               (crit ? 0x02 : 0) | 0x01, p);
     378             :     }
     379         143 : }
     380             : 
     381             : /*
     382             :   mode=0 for stdout.
     383             :   mode=1 for log_info + status messages
     384             :   mode=2 for status messages only
     385             : 
     386             :   Defined bits in WHICH:
     387             :     1 == standard notations
     388             :     2 == user notations
     389             : */
     390             : void
     391         143 : show_notation (PKT_signature * sig, int indent, int mode, int which)
     392             : {
     393         143 :   estream_t fp = mode ? log_get_stream () : es_stdout;
     394             :   struct notation *nd, *notations;
     395             : 
     396         143 :   if (which == 0)
     397           0 :     which = 3;
     398             : 
     399         143 :   notations = sig_to_notation (sig);
     400             : 
     401             :   /* There may be multiple notations in the same sig. */
     402         143 :   for (nd = notations; nd; nd = nd->next)
     403             :     {
     404           0 :       if (mode != 2)
     405             :         {
     406           0 :           int has_at = !!strchr (nd->name, '@');
     407             : 
     408           0 :           if ((which & 1 && !has_at) || (which & 2 && has_at))
     409             :             {
     410             :               int i;
     411             :               const char *str;
     412             : 
     413           0 :               for (i = 0; i < indent; i++)
     414           0 :                 es_putc (' ', es_stdout);
     415             : 
     416           0 :               if (nd->flags.critical)
     417           0 :                 str = _("Critical signature notation: ");
     418             :               else
     419           0 :                 str = _("Signature notation: ");
     420           0 :               if (mode)
     421           0 :                 log_info ("%s", str);
     422             :               else
     423           0 :                 es_fprintf (es_stdout, "%s", str);
     424             :               /* This is all UTF8 */
     425           0 :               print_utf8_buffer (fp, nd->name, strlen (nd->name));
     426           0 :               es_fprintf (fp, "=");
     427           0 :               print_utf8_buffer (fp, nd->value, strlen (nd->value));
     428             :               /* (We need to use log_printf so that the next call to a
     429             :                   log function does not insert an extra LF.)  */
     430           0 :               if (mode)
     431           0 :                 log_printf ("\n");
     432             :               else
     433           0 :                 es_putc ('\n', fp);
     434             :             }
     435             :         }
     436             : 
     437           0 :       if (mode)
     438             :         {
     439           0 :           write_status_buffer (STATUS_NOTATION_NAME,
     440           0 :                                nd->name, strlen (nd->name), 0);
     441           0 :           write_status_buffer (STATUS_NOTATION_DATA,
     442           0 :                                nd->value, strlen (nd->value), 50);
     443             :         }
     444             :     }
     445             : 
     446         143 :   free_notation (notations);
     447         143 : }
     448             : 
     449             : 
     450             : static void
     451           0 : print_signature_stats (struct keylist_context *s)
     452             : {
     453           0 :   if (!s->check_sigs)
     454           0 :     return;  /* Signature checking was not requested.  */
     455             : 
     456           0 :   if (s->good_sigs == 1)
     457           0 :     log_info (_("1 good signature\n"));
     458           0 :   else if (s->good_sigs)
     459           0 :     log_info (_("%d good signatures\n"), s->good_sigs);
     460             : 
     461           0 :   if (s->inv_sigs == 1)
     462           0 :     log_info (_("1 bad signature\n"));
     463           0 :   else if (s->inv_sigs)
     464           0 :     log_info (_("%d bad signatures\n"), s->inv_sigs);
     465             : 
     466           0 :   if (s->no_key == 1)
     467           0 :     log_info (_("1 signature not checked due to a missing key\n"));
     468           0 :   else if (s->no_key)
     469           0 :     log_info (_("%d signatures not checked due to missing keys\n"), s->no_key);
     470             : 
     471           0 :   if (s->oth_err == 1)
     472           0 :     log_info (_("1 signature not checked due to an error\n"));
     473           0 :   else if (s->oth_err)
     474           0 :     log_info (_("%d signatures not checked due to errors\n"), s->oth_err);
     475             : }
     476             : 
     477             : 
     478             : /* List all keys.  If SECRET is true only secret keys are listed.  If
     479             :    MARK_SECRET is true secret keys are indicated in a public key
     480             :    listing.  */
     481             : static void
     482           0 : list_all (ctrl_t ctrl, int secret, int mark_secret)
     483             : {
     484             :   KEYDB_HANDLE hd;
     485           0 :   KBNODE keyblock = NULL;
     486           0 :   int rc = 0;
     487             :   int any_secret;
     488             :   const char *lastresname, *resname;
     489             :   struct keylist_context listctx;
     490             : 
     491           0 :   memset (&listctx, 0, sizeof (listctx));
     492           0 :   if (opt.check_sigs)
     493           0 :     listctx.check_sigs = 1;
     494             : 
     495           0 :   hd = keydb_new ();
     496           0 :   if (!hd)
     497           0 :     rc = gpg_error (GPG_ERR_GENERAL);
     498             :   else
     499           0 :     rc = keydb_search_first (hd);
     500           0 :   if (rc)
     501             :     {
     502           0 :       if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
     503           0 :         log_error ("keydb_search_first failed: %s\n", gpg_strerror (rc));
     504           0 :       goto leave;
     505             :     }
     506             : 
     507           0 :   lastresname = NULL;
     508             :   do
     509             :     {
     510           0 :       rc = keydb_get_keyblock (hd, &keyblock);
     511           0 :       if (rc)
     512             :         {
     513           0 :           if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
     514           0 :             continue;  /* Skip legacy keys.  */
     515           0 :           log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc));
     516           0 :           goto leave;
     517             :         }
     518             : 
     519           0 :       if (secret || mark_secret)
     520           0 :         any_secret = !agent_probe_any_secret_key (NULL, keyblock);
     521             :       else
     522           0 :         any_secret = 0;
     523             : 
     524           0 :       if (secret && !any_secret)
     525             :         ; /* Secret key listing requested but this isn't one.  */
     526             :       else
     527             :         {
     528           0 :           if (!opt.with_colons)
     529             :             {
     530           0 :               resname = keydb_get_resource_name (hd);
     531           0 :               if (lastresname != resname)
     532             :                 {
     533             :                   int i;
     534             : 
     535           0 :                   es_fprintf (es_stdout, "%s\n", resname);
     536           0 :                   for (i = strlen (resname); i; i--)
     537           0 :                     es_putc ('-', es_stdout);
     538           0 :                   es_putc ('\n', es_stdout);
     539           0 :                   lastresname = resname;
     540             :                 }
     541             :             }
     542           0 :           merge_keys_and_selfsig (keyblock);
     543           0 :           list_keyblock (ctrl, keyblock, secret, any_secret, opt.fingerprint,
     544             :                          &listctx);
     545             :         }
     546           0 :       release_kbnode (keyblock);
     547           0 :       keyblock = NULL;
     548             :     }
     549           0 :   while (!(rc = keydb_search_next (hd)));
     550           0 :   es_fflush (es_stdout);
     551           0 :   if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
     552           0 :     log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc));
     553           0 :   if (keydb_get_skipped_counter (hd))
     554           0 :     log_info (_("Warning: %lu key(s) skipped due to their large size\n"),
     555             :               keydb_get_skipped_counter (hd));
     556             : 
     557           0 :   if (opt.check_sigs && !opt.with_colons)
     558           0 :     print_signature_stats (&listctx);
     559             : 
     560             :  leave:
     561           0 :   keylist_context_release (&listctx);
     562           0 :   release_kbnode (keyblock);
     563           0 :   keydb_release (hd);
     564           0 : }
     565             : 
     566             : 
     567             : static void
     568          87 : list_one (ctrl_t ctrl, strlist_t names, int secret, int mark_secret)
     569             : {
     570          87 :   int rc = 0;
     571          87 :   KBNODE keyblock = NULL;
     572             :   GETKEY_CTX ctx;
     573             :   const char *resname;
     574          87 :   const char *keyring_str = _("Keyring");
     575             :   int i;
     576             :   struct keylist_context listctx;
     577             : 
     578          87 :   memset (&listctx, 0, sizeof (listctx));
     579          87 :   if (!secret && opt.check_sigs)
     580           0 :     listctx.check_sigs = 1;
     581             : 
     582             :   /* fixme: using the bynames function has the disadvantage that we
     583             :    * don't know wether one of the names given was not found.  OTOH,
     584             :    * this function has the advantage to list the names in the
     585             :    * sequence as defined by the keyDB and does not duplicate
     586             :    * outputs.  A solution could be do test whether all given have
     587             :    * been listed (this needs a way to use the keyDB search
     588             :    * functions) or to have the search function return indicators for
     589             :    * found names.  Yet another way is to use the keydb search
     590             :    * facilities directly. */
     591          87 :   rc = getkey_bynames (&ctx, NULL, names, secret, &keyblock);
     592          87 :   if (rc)
     593             :     {
     594           0 :       log_error ("error reading key: %s\n", gpg_strerror (rc));
     595           0 :       getkey_end (ctx);
     596          87 :       return;
     597             :     }
     598             : 
     599             :   do
     600             :     {
     601          88 :       if ((opt.list_options & LIST_SHOW_KEYRING) && !opt.with_colons)
     602             :         {
     603           0 :           resname = keydb_get_resource_name (get_ctx_handle (ctx));
     604           0 :           es_fprintf (es_stdout, "%s: %s\n", keyring_str, resname);
     605           0 :           for (i = strlen (resname) + strlen (keyring_str) + 2; i; i--)
     606           0 :             es_putc ('-', es_stdout);
     607           0 :           es_putc ('\n', es_stdout);
     608             :         }
     609          88 :       list_keyblock (ctrl,
     610             :                      keyblock, secret, mark_secret, opt.fingerprint, &listctx);
     611          88 :       release_kbnode (keyblock);
     612             :     }
     613          88 :   while (!getkey_next (ctx, NULL, &keyblock));
     614          87 :   getkey_end (ctx);
     615             : 
     616          87 :   if (opt.check_sigs && !opt.with_colons)
     617           0 :     print_signature_stats (&listctx);
     618             : 
     619          87 :   keylist_context_release (&listctx);
     620             : }
     621             : 
     622             : 
     623             : static void
     624           0 : locate_one (ctrl_t ctrl, strlist_t names)
     625             : {
     626           0 :   int rc = 0;
     627             :   strlist_t sl;
     628           0 :   GETKEY_CTX ctx = NULL;
     629           0 :   KBNODE keyblock = NULL;
     630             :   struct keylist_context listctx;
     631             : 
     632           0 :   memset (&listctx, 0, sizeof (listctx));
     633           0 :   if (opt.check_sigs)
     634           0 :     listctx.check_sigs = 1;
     635             : 
     636           0 :   for (sl = names; sl; sl = sl->next)
     637             :     {
     638           0 :       rc = get_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, NULL, 1, 0);
     639           0 :       if (rc)
     640             :         {
     641           0 :           if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
     642           0 :             log_error ("error reading key: %s\n", gpg_strerror (rc));
     643           0 :           else if (opt.verbose)
     644           0 :             log_info (_("key \"%s\" not found: %s\n"),
     645           0 :                       sl->d, gpg_strerror (rc));
     646             :         }
     647             :       else
     648             :         {
     649             :           do
     650             :             {
     651           0 :               list_keyblock (ctrl, keyblock, 0, 0, opt.fingerprint, &listctx);
     652           0 :               release_kbnode (keyblock);
     653             :             }
     654           0 :           while (ctx && !getkey_next (ctx, NULL, &keyblock));
     655           0 :           getkey_end (ctx);
     656           0 :           ctx = NULL;
     657             :         }
     658             :     }
     659             : 
     660           0 :   if (opt.check_sigs && !opt.with_colons)
     661           0 :     print_signature_stats (&listctx);
     662             : 
     663           0 :   keylist_context_release (&listctx);
     664           0 : }
     665             : 
     666             : 
     667             : static void
     668           0 : print_key_data (PKT_public_key * pk)
     669             : {
     670           0 :   int n = pk ? pubkey_get_npkey (pk->pubkey_algo) : 0;
     671             :   int i;
     672             : 
     673           0 :   for (i = 0; i < n; i++)
     674             :     {
     675           0 :       es_fprintf (es_stdout, "pkd:%d:%u:", i, mpi_get_nbits (pk->pkey[i]));
     676           0 :       mpi_print (es_stdout, pk->pkey[i], 1);
     677           0 :       es_putc (':', es_stdout);
     678           0 :       es_putc ('\n', es_stdout);
     679             :     }
     680           0 : }
     681             : 
     682             : static void
     683         167 : print_capabilities (PKT_public_key *pk, KBNODE keyblock)
     684             : {
     685         167 :   unsigned int use = pk->pubkey_usage;
     686         167 :   int c_printed = 0;
     687             : 
     688         167 :   if (use & PUBKEY_USAGE_ENC)
     689          82 :     es_putc ('e', es_stdout);
     690             : 
     691         167 :   if (use & PUBKEY_USAGE_SIG)
     692             :     {
     693          85 :       es_putc ('s', es_stdout);
     694          85 :       if (pk->flags.primary)
     695             :         {
     696          85 :           es_putc ('c', es_stdout);
     697             :           /* The PUBKEY_USAGE_CERT flag was introduced later and we
     698             :              used to always print 'c' for a primary key.  To avoid any
     699             :              regression here we better track whether we printed 'c'
     700             :              already.  */
     701          85 :           c_printed = 1;
     702             :         }
     703             :     }
     704             : 
     705         167 :   if ((use & PUBKEY_USAGE_CERT) && !c_printed)
     706           0 :     es_putc ('c', es_stdout);
     707             : 
     708         167 :   if ((use & PUBKEY_USAGE_AUTH))
     709           0 :     es_putc ('a', es_stdout);
     710             : 
     711         167 :   if ((use & PUBKEY_USAGE_UNKNOWN))
     712           0 :     es_putc ('?', es_stdout);
     713             : 
     714         167 :   if (keyblock)
     715             :     {
     716             :       /* Figure out the usable capabilities.  */
     717             :       KBNODE k;
     718          85 :       int enc = 0, sign = 0, cert = 0, auth = 0, disabled = 0;
     719             : 
     720         505 :       for (k = keyblock; k; k = k->next)
     721             :         {
     722         420 :           if (k->pkt->pkttype == PKT_PUBLIC_KEY
     723         335 :               || k->pkt->pkttype == PKT_PUBLIC_SUBKEY)
     724             :             {
     725         167 :               pk = k->pkt->pkt.public_key;
     726             : 
     727         167 :               if (pk->flags.primary)
     728          85 :                 disabled = pk_is_disabled (pk);
     729             : 
     730         167 :               if (pk->flags.valid && !pk->flags.revoked && !pk->has_expired)
     731             :                 {
     732         166 :                   if (pk->pubkey_usage & PUBKEY_USAGE_ENC)
     733          82 :                     enc = 1;
     734         166 :                   if (pk->pubkey_usage & PUBKEY_USAGE_SIG)
     735             :                     {
     736          84 :                       sign = 1;
     737          84 :                       if (pk->flags.primary)
     738          84 :                         cert = 1;
     739             :                     }
     740         166 :                   if (pk->pubkey_usage & PUBKEY_USAGE_CERT)
     741          84 :                     cert = 1;
     742         166 :                   if ((pk->pubkey_usage & PUBKEY_USAGE_AUTH))
     743           0 :                     auth = 1;
     744             :                 }
     745             :             }
     746             :         }
     747          85 :       if (enc)
     748          82 :         es_putc ('E', es_stdout);
     749          85 :       if (sign)
     750          84 :         es_putc ('S', es_stdout);
     751          85 :       if (cert)
     752          84 :         es_putc ('C', es_stdout);
     753          85 :       if (auth)
     754           0 :         es_putc ('A', es_stdout);
     755          85 :       if (disabled)
     756           0 :         es_putc ('D', es_stdout);
     757             :     }
     758             : 
     759         167 :   es_putc (':', es_stdout);
     760         167 : }
     761             : 
     762             : 
     763             : /* FLAGS: 0x01 hashed
     764             :           0x02 critical  */
     765             : static void
     766           0 : print_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
     767             :                      const byte * buf)
     768             : {
     769             :   size_t i;
     770             : 
     771           0 :   es_fprintf (es_stdout, "spk:%d:%u:%u:", type, flags, (unsigned int) len);
     772             : 
     773           0 :   for (i = 0; i < len; i++)
     774             :     {
     775             :       /* printable ascii other than : and % */
     776           0 :       if (buf[i] >= 32 && buf[i] <= 126 && buf[i] != ':' && buf[i] != '%')
     777           0 :         es_fprintf (es_stdout, "%c", buf[i]);
     778             :       else
     779           0 :         es_fprintf (es_stdout, "%%%02X", buf[i]);
     780             :     }
     781             : 
     782           0 :   es_fprintf (es_stdout, "\n");
     783           0 : }
     784             : 
     785             : 
     786             : void
     787           0 : print_subpackets_colon (PKT_signature * sig)
     788             : {
     789             :   byte *i;
     790             : 
     791           0 :   assert (opt.show_subpackets);
     792             : 
     793           0 :   for (i = opt.show_subpackets; *i; i++)
     794             :     {
     795             :       const byte *p;
     796             :       size_t len;
     797             :       int seq, crit;
     798             : 
     799           0 :       seq = 0;
     800             : 
     801           0 :       while ((p = enum_sig_subpkt (sig->hashed, *i, &len, &seq, &crit)))
     802           0 :         print_one_subpacket (*i, len, 0x01 | (crit ? 0x02 : 0), p);
     803             : 
     804           0 :       seq = 0;
     805             : 
     806           0 :       while ((p = enum_sig_subpkt (sig->unhashed, *i, &len, &seq, &crit)))
     807           0 :         print_one_subpacket (*i, len, 0x00 | (crit ? 0x02 : 0), p);
     808             :     }
     809           0 : }
     810             : 
     811             : 
     812             : void
     813           0 : dump_attribs (const PKT_user_id *uid, PKT_public_key *pk)
     814             : {
     815             :   int i;
     816             : 
     817           0 :   if (!attrib_fp)
     818           0 :     return;
     819             : 
     820           0 :   for (i = 0; i < uid->numattribs; i++)
     821             :     {
     822           0 :       if (is_status_enabled ())
     823             :         {
     824             :           byte array[MAX_FINGERPRINT_LEN], *p;
     825             :           char buf[(MAX_FINGERPRINT_LEN * 2) + 90];
     826             :           size_t j, n;
     827             : 
     828           0 :           if (!pk)
     829           0 :             BUG ();
     830           0 :           fingerprint_from_pk (pk, array, &n);
     831             : 
     832           0 :           p = array;
     833           0 :           for (j = 0; j < n; j++, p++)
     834           0 :             sprintf (buf + 2 * j, "%02X", *p);
     835             : 
     836           0 :           sprintf (buf + strlen (buf), " %lu %u %u %u %lu %lu %u",
     837           0 :                    (ulong) uid->attribs[i].len, uid->attribs[i].type, i + 1,
     838           0 :                    uid->numattribs, (ulong) uid->created,
     839           0 :                    (ulong) uid->expiredate,
     840           0 :                    ((uid->is_primary ? 0x01 : 0) | (uid->
     841           0 :                                                     is_revoked ? 0x02 : 0) |
     842           0 :                     (uid->is_expired ? 0x04 : 0)));
     843           0 :           write_status_text (STATUS_ATTRIBUTE, buf);
     844             :         }
     845             : 
     846           0 :       es_fwrite (uid->attribs[i].data, uid->attribs[i].len, 1, attrib_fp);
     847           0 :       es_fflush (attrib_fp);
     848             :     }
     849             : }
     850             : 
     851             : 
     852             : /* Print IPGP cert records instead of a standard key listing.  */
     853             : static void
     854           0 : list_keyblock_pka (ctrl_t ctrl, kbnode_t keyblock)
     855             : {
     856             :   kbnode_t kbctx;
     857             :   kbnode_t node;
     858             :   PKT_public_key *pk;
     859             :   char pkstrbuf[PUBKEY_STRING_SIZE];
     860             :   char *hexfpr;
     861           0 :   char *hexkeyblock = NULL;
     862             :   unsigned int hexkeyblocklen;
     863             :   const char *s;
     864             : 
     865             :   /* Get the keyid from the keyblock.  */
     866           0 :   node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
     867           0 :   if (!node)
     868             :     {
     869           0 :       log_error ("Oops; key lost!\n");
     870           0 :       dump_kbnode (keyblock);
     871           0 :       return;
     872             :     }
     873             : 
     874           0 :   pk = node->pkt->pkt.public_key;
     875             : 
     876             :   /* First print an overview of the key with all userids.  */
     877           0 :   es_fprintf (es_stdout, ";; pub  %s/%s %s\n;;",
     878             :               pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
     879             :               keystr_from_pk (pk), datestr_from_pk (pk));
     880           0 :   print_fingerprint (NULL, pk, 10);
     881           0 :   for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
     882             :     {
     883           0 :       if (node->pkt->pkttype == PKT_USER_ID)
     884             :         {
     885           0 :           PKT_user_id *uid = node->pkt->pkt.user_id;
     886             : 
     887           0 :           if (pk && (uid->is_expired || uid->is_revoked)
     888           0 :               && !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
     889           0 :             continue;
     890             : 
     891           0 :           es_fputs (";; uid  ", es_stdout);
     892           0 :           print_utf8_buffer (es_stdout, uid->name, uid->len);
     893           0 :           es_putc ('\n', es_stdout);
     894             :         }
     895             :     }
     896             : 
     897             : 
     898           0 :   hexfpr = hexfingerprint (pk);
     899           0 :   if (opt.print_dane_records)
     900             :     {
     901             :       kbnode_t dummy_keyblock;
     902             :       void *data;
     903             :       size_t datalen;
     904             :       gpg_error_t err;
     905             : 
     906             :       /* We do not have an export fucntion which allows to pass a
     907             :          keyblock, thus we need to search the key again.  */
     908           0 :       err = export_pubkey_buffer (ctrl, hexfpr,
     909             :                                   EXPORT_DANE_FORMAT,
     910             :                                   &dummy_keyblock, &data, &datalen);
     911           0 :       release_kbnode (dummy_keyblock);
     912           0 :       if (!err)
     913             :         {
     914           0 :           hexkeyblocklen = datalen;
     915           0 :           hexkeyblock = bin2hex (data, datalen, NULL);
     916           0 :           if (!hexkeyblock)
     917           0 :             err = gpg_error_from_syserror ();
     918           0 :           xfree (data);
     919           0 :           ascii_strlwr (hexkeyblock);
     920             :         }
     921           0 :       if (err)
     922           0 :         log_error (_("skipped \"%s\": %s\n"), hexfpr, gpg_strerror (err));
     923             : 
     924             :     }
     925             : 
     926           0 :   for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
     927             :     {
     928           0 :       if (node->pkt->pkttype == PKT_USER_ID)
     929             :         {
     930           0 :           PKT_user_id *uid = node->pkt->pkt.user_id;
     931             :           char *mbox;
     932             :           char *p;
     933             : 
     934           0 :           if (pk && (uid->is_expired || uid->is_revoked)
     935           0 :               && !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
     936           0 :             continue;
     937             : 
     938           0 :           mbox = mailbox_from_userid (uid->name);
     939           0 :           if (mbox && (p = strchr (mbox, '@')))
     940             :             {
     941             :               char hashbuf[32];
     942             :               char *hash;
     943             :               unsigned int len;
     944             : 
     945           0 :               *p++ = 0;
     946           0 :               if (opt.print_pka_records)
     947             :                 {
     948           0 :                   es_fprintf (es_stdout, "$ORIGIN _pka.%s.\n; %s\n; ",
     949             :                               p, hexfpr);
     950           0 :                   print_utf8_buffer (es_stdout, uid->name, uid->len);
     951           0 :                   es_putc ('\n', es_stdout);
     952           0 :                   gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf,
     953             :                                        mbox, strlen (mbox));
     954           0 :                   hash = zb32_encode (hashbuf, 8*20);
     955           0 :                   if (hash)
     956             :                     {
     957           0 :                       len = strlen (hexfpr)/2;
     958           0 :                       es_fprintf (es_stdout,
     959             :                                   "%s TYPE37 \\# %u 0006 0000 00 %02X %s\n",
     960             :                                   hash, 6 + len, len, hexfpr);
     961           0 :                       xfree (hash);
     962             :                     }
     963             :                 }
     964           0 :               if (opt.print_dane_records && hexkeyblock)
     965             :                 {
     966           0 :                   es_fprintf (es_stdout, "$ORIGIN _openpgpkey.%s.\n; %s\n; ",
     967             :                               p, hexfpr);
     968           0 :                   print_utf8_buffer (es_stdout, uid->name, uid->len);
     969           0 :                   es_putc ('\n', es_stdout);
     970           0 :                   gcry_md_hash_buffer (GCRY_MD_SHA256, hashbuf,
     971             :                                        mbox, strlen (mbox));
     972           0 :                   hash = bin2hex (hashbuf, 28, NULL);
     973           0 :                   if (hash)
     974             :                     {
     975           0 :                       ascii_strlwr (hash);
     976           0 :                       es_fprintf (es_stdout, "%s TYPE61 \\# %u (\n",
     977             :                                   hash, hexkeyblocklen);
     978           0 :                       xfree (hash);
     979           0 :                       s = hexkeyblock;
     980             :                       for (;;)
     981             :                         {
     982           0 :                           es_fprintf (es_stdout, "\t%.64s\n", s);
     983           0 :                           if (strlen (s) < 64)
     984           0 :                             break;
     985           0 :                           s += 64;
     986           0 :                         }
     987           0 :                       es_fputs ("\t)\n", es_stdout);
     988             :                     }
     989             :                 }
     990             :             }
     991           0 :           xfree (mbox);
     992             :         }
     993             : 
     994             :     }
     995           0 :   es_putc ('\n', es_stdout);
     996             : 
     997           0 :   xfree (hexkeyblock);
     998           0 :   xfree (hexfpr);
     999             : }
    1000             : 
    1001             : 
    1002             : static void
    1003           3 : list_keyblock_print (KBNODE keyblock, int secret, int fpr,
    1004             :                      struct keylist_context *listctx)
    1005             : {
    1006             :   int rc;
    1007             :   KBNODE kbctx;
    1008             :   KBNODE node;
    1009             :   PKT_public_key *pk;
    1010           3 :   int skip_sigs = 0;
    1011             :   int s2k_char;
    1012           3 :   char *hexgrip = NULL;
    1013           3 :   char *serialno = NULL;
    1014             :   char pkstrbuf[PUBKEY_STRING_SIZE];
    1015             : 
    1016             :   /* Get the keyid from the keyblock.  */
    1017           3 :   node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
    1018           3 :   if (!node)
    1019             :     {
    1020           0 :       log_error ("Oops; key lost!\n");
    1021           0 :       dump_kbnode (keyblock);
    1022           3 :       return;
    1023             :     }
    1024             : 
    1025           3 :   pk = node->pkt->pkt.public_key;
    1026             : 
    1027           3 :   if (secret || opt.with_keygrip)
    1028             :     {
    1029           0 :       rc = hexkeygrip_from_pk (pk, &hexgrip);
    1030           0 :       if (rc)
    1031           0 :         log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
    1032             :     }
    1033             : 
    1034           3 :   if (secret)
    1035             :     {
    1036           0 :       if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
    1037           0 :         s2k_char = serialno? '>':' ';
    1038             :       else
    1039           0 :         s2k_char = '#';  /* Key not found.  */
    1040             :     }
    1041             :   else
    1042           3 :     s2k_char = ' ';
    1043             : 
    1044           3 :   check_trustdb_stale ();
    1045             : 
    1046             : 
    1047           3 :   es_fprintf (es_stdout, "%s%c  %s/%s %s",
    1048             :               secret? "sec":"pub",
    1049             :               s2k_char,
    1050             :               pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
    1051             :               keystr_from_pk (pk), datestr_from_pk (pk));
    1052             : 
    1053           3 :   if ((opt.list_options & LIST_SHOW_USAGE))
    1054             :     {
    1055           0 :       es_fprintf (es_stdout, " [%s]", usagestr_from_pk (pk, 0));
    1056             :     }
    1057           3 :   if (pk->flags.revoked)
    1058             :     {
    1059           0 :       es_fprintf (es_stdout, " [");
    1060           0 :       es_fprintf (es_stdout, _("revoked: %s"), revokestr_from_pk (pk));
    1061           0 :       es_fprintf (es_stdout, "]");
    1062             :     }
    1063           3 :   else if (pk->has_expired)
    1064             :     {
    1065           0 :       es_fprintf (es_stdout, " [");
    1066           0 :       es_fprintf (es_stdout, _("expired: %s"), expirestr_from_pk (pk));
    1067           0 :       es_fprintf (es_stdout, "]");
    1068             :     }
    1069           3 :   else if (pk->expiredate)
    1070             :     {
    1071           3 :       es_fprintf (es_stdout, " [");
    1072           3 :       es_fprintf (es_stdout, _("expires: %s"), expirestr_from_pk (pk));
    1073           3 :       es_fprintf (es_stdout, "]");
    1074             :     }
    1075             : 
    1076             : #if 0
    1077             :   /* I need to think about this some more.  It's easy enough to
    1078             :      include, but it looks sort of confusing in the listing... */
    1079             :   if (opt.list_options & LIST_SHOW_VALIDITY)
    1080             :     {
    1081             :       int validity = get_validity (pk, NULL, NULL, 0);
    1082             :       es_fprintf (es_stdout, " [%s]", trust_value_to_string (validity));
    1083             :     }
    1084             : #endif
    1085             : 
    1086           3 :   if (pk->pubkey_algo >= 100)
    1087           0 :     es_fprintf (es_stdout, " [experimental algorithm %d]", pk->pubkey_algo);
    1088             : 
    1089           3 :   es_fprintf (es_stdout, "\n");
    1090             : 
    1091           3 :   if (fpr)
    1092           0 :     print_fingerprint (NULL, pk, 0);
    1093             : 
    1094           3 :   if (opt.with_keygrip && hexgrip)
    1095           0 :     es_fprintf (es_stdout, "      Keygrip = %s\n", hexgrip);
    1096             : 
    1097           3 :   if (serialno)
    1098           0 :     print_card_serialno (serialno);
    1099             : 
    1100           3 :   if (opt.with_key_data)
    1101           0 :     print_key_data (pk);
    1102             : 
    1103          21 :   for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
    1104             :     {
    1105          15 :       if (node->pkt->pkttype == PKT_USER_ID)
    1106             :         {
    1107           3 :           PKT_user_id *uid = node->pkt->pkt.user_id;
    1108             : 
    1109           3 :           if ((uid->is_expired || uid->is_revoked)
    1110           0 :               && !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
    1111             :             {
    1112           0 :               skip_sigs = 1;
    1113           0 :               continue;
    1114             :             }
    1115             :           else
    1116           3 :             skip_sigs = 0;
    1117             : 
    1118           3 :           if (attrib_fp && uid->attrib_data != NULL)
    1119           0 :             dump_attribs (uid, pk);
    1120             : 
    1121           3 :           if ((uid->is_revoked || uid->is_expired)
    1122           3 :               || (opt.list_options & LIST_SHOW_UID_VALIDITY))
    1123           3 :             {
    1124             :               const char *validity;
    1125             :               int indent;
    1126             : 
    1127           3 :               validity = uid_trust_string_fixed (pk, uid);
    1128           9 :               indent =
    1129           6 :                 (keystrlen () + (opt.legacy_list_mode? 9:11)) -
    1130           3 :                 atoi (uid_trust_string_fixed (NULL, NULL));
    1131             : 
    1132           3 :               if (indent < 0 || indent > 40)
    1133           0 :                 indent = 0;
    1134             : 
    1135           3 :               es_fprintf (es_stdout, "uid%*s%s ", indent, "", validity);
    1136             :             }
    1137             :           else
    1138           0 :             es_fprintf (es_stdout, "uid%*s",
    1139           0 :                         (int) keystrlen () + (opt.legacy_list_mode? 10:12), "");
    1140             : 
    1141           3 :           print_utf8_buffer (es_stdout, uid->name, uid->len);
    1142           3 :           es_putc ('\n', es_stdout);
    1143             : 
    1144           3 :           if ((opt.list_options & LIST_SHOW_PHOTOS) && uid->attribs != NULL)
    1145           0 :             show_photos (uid->attribs, uid->numattribs, pk, uid);
    1146             :         }
    1147          12 :       else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    1148             :         {
    1149           3 :           PKT_public_key *pk2 = node->pkt->pkt.public_key;
    1150             : 
    1151           3 :           if ((pk2->flags.revoked || pk2->has_expired)
    1152           0 :               && !(opt.list_options & LIST_SHOW_UNUSABLE_SUBKEYS))
    1153             :             {
    1154           0 :               skip_sigs = 1;
    1155           0 :               continue;
    1156             :             }
    1157             :           else
    1158           3 :             skip_sigs = 0;
    1159             : 
    1160           3 :           xfree (serialno); serialno = NULL;
    1161           3 :           xfree (hexgrip); hexgrip = NULL;
    1162           3 :           if (secret || opt.with_keygrip)
    1163             :             {
    1164           0 :               rc = hexkeygrip_from_pk (pk2, &hexgrip);
    1165           0 :               if (rc)
    1166           0 :                 log_error ("error computing a keygrip: %s\n",
    1167             :                            gpg_strerror (rc));
    1168             :             }
    1169           3 :           if (secret)
    1170             :             {
    1171           0 :               if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
    1172           0 :                 s2k_char = serialno? '>':' ';
    1173             :               else
    1174           0 :                 s2k_char = '#';  /* Key not found.  */
    1175             :             }
    1176             :           else
    1177           3 :             s2k_char = ' ';
    1178             : 
    1179           3 :           es_fprintf (es_stdout, "%s%c  %s/%s %s",
    1180             :                   secret? "ssb":"sub",
    1181             :                   s2k_char,
    1182             :                   pubkey_string (pk2, pkstrbuf, sizeof pkstrbuf),
    1183             :                   keystr_from_pk (pk2), datestr_from_pk (pk2));
    1184             : 
    1185           3 :           if ((opt.list_options & LIST_SHOW_USAGE))
    1186             :             {
    1187           0 :               es_fprintf (es_stdout, " [%s]", usagestr_from_pk (pk2, 0));
    1188             :             }
    1189           3 :           if (pk2->flags.revoked)
    1190             :             {
    1191           0 :               es_fprintf (es_stdout, " [");
    1192           0 :               es_fprintf (es_stdout, _("revoked: %s"), revokestr_from_pk (pk2));
    1193           0 :               es_fprintf (es_stdout, "]");
    1194             :             }
    1195           3 :           else if (pk2->has_expired)
    1196             :             {
    1197           0 :               es_fprintf (es_stdout, " [");
    1198           0 :               es_fprintf (es_stdout, _("expired: %s"), expirestr_from_pk (pk2));
    1199           0 :               es_fprintf (es_stdout, "]");
    1200             :             }
    1201           3 :           else if (pk2->expiredate)
    1202             :             {
    1203           3 :               es_fprintf (es_stdout, " [");
    1204           3 :               es_fprintf (es_stdout, _("expires: %s"), expirestr_from_pk (pk2));
    1205           3 :               es_fprintf (es_stdout, "]");
    1206             :             }
    1207           3 :           es_putc ('\n', es_stdout);
    1208           3 :           if (fpr > 1)
    1209             :             {
    1210           0 :               print_fingerprint (NULL, pk2, 0);
    1211           0 :               if (serialno)
    1212           0 :                 print_card_serialno (serialno);
    1213             :             }
    1214           3 :           if (opt.with_keygrip && hexgrip)
    1215           0 :             es_fprintf (es_stdout, "      Keygrip = %s\n", hexgrip);
    1216           3 :           if (opt.with_key_data)
    1217           0 :             print_key_data (pk2);
    1218             :         }
    1219           9 :       else if (opt.list_sigs
    1220           0 :                && node->pkt->pkttype == PKT_SIGNATURE && !skip_sigs)
    1221             :         {
    1222           0 :           PKT_signature *sig = node->pkt->pkt.signature;
    1223             :           int sigrc;
    1224             :           char *sigstr;
    1225             : 
    1226           0 :           if (listctx->check_sigs)
    1227             :             {
    1228           0 :               rc = check_key_signature (keyblock, node, NULL);
    1229           0 :               switch (gpg_err_code (rc))
    1230             :                 {
    1231             :                 case 0:
    1232           0 :                   listctx->good_sigs++;
    1233           0 :                   sigrc = '!';
    1234           0 :                   break;
    1235             :                 case GPG_ERR_BAD_SIGNATURE:
    1236           0 :                   listctx->inv_sigs++;
    1237           0 :                   sigrc = '-';
    1238           0 :                   break;
    1239             :                 case GPG_ERR_NO_PUBKEY:
    1240             :                 case GPG_ERR_UNUSABLE_PUBKEY:
    1241           0 :                   listctx->no_key++;
    1242           0 :                   continue;
    1243             :                 default:
    1244           0 :                   listctx->oth_err++;
    1245           0 :                   sigrc = '%';
    1246           0 :                   break;
    1247             :                 }
    1248             : 
    1249             :               /* TODO: Make sure a cached sig record here still has
    1250             :                  the pk that issued it.  See also
    1251             :                  keyedit.c:print_and_check_one_sig */
    1252             :             }
    1253             :           else
    1254             :             {
    1255           0 :               rc = 0;
    1256           0 :               sigrc = ' ';
    1257             :             }
    1258             : 
    1259           0 :           if (sig->sig_class == 0x20 || sig->sig_class == 0x28
    1260           0 :               || sig->sig_class == 0x30)
    1261           0 :             sigstr = "rev";
    1262           0 :           else if ((sig->sig_class & ~3) == 0x10)
    1263           0 :             sigstr = "sig";
    1264           0 :           else if (sig->sig_class == 0x18)
    1265           0 :             sigstr = "sig";
    1266           0 :           else if (sig->sig_class == 0x1F)
    1267           0 :             sigstr = "sig";
    1268             :           else
    1269             :             {
    1270           0 :               es_fprintf (es_stdout, "sig                             "
    1271             :                       "[unexpected signature class 0x%02x]\n",
    1272           0 :                       sig->sig_class);
    1273           0 :               continue;
    1274             :             }
    1275             : 
    1276           0 :           es_fputs (sigstr, es_stdout);
    1277           0 :           es_fprintf (es_stdout, "%c%c %c%c%c%c%c%c %s %s",
    1278           0 :                   sigrc, (sig->sig_class - 0x10 > 0 &&
    1279           0 :                           sig->sig_class - 0x10 <
    1280           0 :                           4) ? '0' + sig->sig_class - 0x10 : ' ',
    1281           0 :                   sig->flags.exportable ? ' ' : 'L',
    1282           0 :                   sig->flags.revocable ? ' ' : 'R',
    1283           0 :                   sig->flags.policy_url ? 'P' : ' ',
    1284           0 :                   sig->flags.notation ? 'N' : ' ',
    1285           0 :                   sig->flags.expired ? 'X' : ' ',
    1286           0 :                   (sig->trust_depth > 9) ? 'T' : (sig->trust_depth >
    1287           0 :                                                   0) ? '0' +
    1288           0 :                   sig->trust_depth : ' ', keystr (sig->keyid),
    1289             :                   datestr_from_sig (sig));
    1290           0 :           if (opt.list_options & LIST_SHOW_SIG_EXPIRE)
    1291           0 :             es_fprintf (es_stdout, " %s", expirestr_from_sig (sig));
    1292           0 :           es_fprintf (es_stdout, "  ");
    1293           0 :           if (sigrc == '%')
    1294           0 :             es_fprintf (es_stdout, "[%s] ", gpg_strerror (rc));
    1295           0 :           else if (sigrc == '?')
    1296             :             ;
    1297           0 :           else if (!opt.fast_list_mode)
    1298             :             {
    1299             :               size_t n;
    1300           0 :               char *p = get_user_id (sig->keyid, &n);
    1301           0 :               print_utf8_buffer (es_stdout, p, n);
    1302           0 :               xfree (p);
    1303             :             }
    1304           0 :           es_putc ('\n', es_stdout);
    1305             : 
    1306           0 :           if (sig->flags.policy_url
    1307           0 :               && (opt.list_options & LIST_SHOW_POLICY_URLS))
    1308           0 :             show_policy_url (sig, 3, 0);
    1309             : 
    1310           0 :           if (sig->flags.notation && (opt.list_options & LIST_SHOW_NOTATIONS))
    1311           0 :             show_notation (sig, 3, 0,
    1312           0 :                            ((opt.
    1313           0 :                              list_options & LIST_SHOW_STD_NOTATIONS) ? 1 : 0)
    1314             :                            +
    1315           0 :                            ((opt.
    1316           0 :                              list_options & LIST_SHOW_USER_NOTATIONS) ? 2 :
    1317             :                             0));
    1318             : 
    1319           0 :           if (sig->flags.pref_ks
    1320           0 :               && (opt.list_options & LIST_SHOW_KEYSERVER_URLS))
    1321           0 :             show_keyserver_url (sig, 3, 0);
    1322             : 
    1323             :           /* fixme: check or list other sigs here */
    1324             :         }
    1325             :     }
    1326           3 :   es_putc ('\n', es_stdout);
    1327           3 :   xfree (serialno);
    1328           3 :   xfree (hexgrip);
    1329             : }
    1330             : 
    1331             : void
    1332          85 : print_revokers (estream_t fp, PKT_public_key * pk)
    1333             : {
    1334             :   /* print the revoker record */
    1335          85 :   if (!pk->revkey && pk->numrevkeys)
    1336           0 :     BUG ();
    1337             :   else
    1338             :     {
    1339             :       int i, j;
    1340             : 
    1341          86 :       for (i = 0; i < pk->numrevkeys; i++)
    1342             :         {
    1343             :           byte *p;
    1344             : 
    1345           1 :           es_fprintf (fp, "rvk:::%d::::::", pk->revkey[i].algid);
    1346           1 :           p = pk->revkey[i].fpr;
    1347          21 :           for (j = 0; j < 20; j++, p++)
    1348          20 :             es_fprintf (fp, "%02X", *p);
    1349           2 :           es_fprintf (fp, ":%02x%s:\n",
    1350           1 :                       pk->revkey[i].class,
    1351           1 :                       (pk->revkey[i].class & 0x40) ? "s" : "");
    1352             :         }
    1353             :     }
    1354          85 : }
    1355             : 
    1356             : 
    1357             : /* List a key in colon mode.  If SECRET is true this is a secret key
    1358             :    record (i.e. requested via --list-secret-key).  If HAS_SECRET a
    1359             :    secret key is available even if SECRET is not set.  */
    1360             : static void
    1361          85 : list_keyblock_colon (KBNODE keyblock, int secret, int has_secret, int fpr)
    1362             : {
    1363             :   int rc;
    1364             :   KBNODE kbctx;
    1365             :   KBNODE node;
    1366             :   PKT_public_key *pk;
    1367             :   u32 keyid[2];
    1368          85 :   int trustletter = 0;
    1369          85 :   int ulti_hack = 0;
    1370             :   int i;
    1371             :   char *p;
    1372          85 :   char *hexgrip = NULL;
    1373          85 :   char *serialno = NULL;
    1374             :   int stubkey;
    1375             : 
    1376             :   /* Get the keyid from the keyblock.  */
    1377          85 :   node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
    1378          85 :   if (!node)
    1379             :     {
    1380           0 :       log_error ("Oops; key lost!\n");
    1381           0 :       dump_kbnode (keyblock);
    1382          85 :       return;
    1383             :     }
    1384             : 
    1385          85 :   pk = node->pkt->pkt.public_key;
    1386          85 :   if (secret || has_secret || opt.with_keygrip || opt.with_key_data)
    1387             :     {
    1388           0 :       rc = hexkeygrip_from_pk (pk, &hexgrip);
    1389           0 :       if (rc)
    1390           0 :         log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
    1391             :     }
    1392          85 :   stubkey = 0;
    1393          85 :   if ((secret||has_secret) && agent_get_keyinfo (NULL, hexgrip, &serialno))
    1394           0 :     stubkey = 1;  /* Key not found.  */
    1395             : 
    1396          85 :   keyid_from_pk (pk, keyid);
    1397          85 :   es_fputs (secret? "sec:":"pub:", es_stdout);
    1398          85 :   if (!pk->flags.valid)
    1399           0 :     es_putc ('i', es_stdout);
    1400          85 :   else if (pk->flags.revoked)
    1401           0 :     es_putc ('r', es_stdout);
    1402          85 :   else if (pk->has_expired)
    1403           1 :     es_putc ('e', es_stdout);
    1404          84 :   else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
    1405             :     ;
    1406             :   else
    1407             :     {
    1408          84 :       trustletter = get_validity_info (pk, NULL);
    1409          84 :       if (trustletter == 'u')
    1410           0 :         ulti_hack = 1;
    1411          84 :       es_putc (trustletter, es_stdout);
    1412             :     }
    1413             : 
    1414         340 :   es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s::",
    1415             :           nbits_from_pk (pk),
    1416          85 :           pk->pubkey_algo,
    1417         170 :           (ulong) keyid[0], (ulong) keyid[1],
    1418             :           colon_datestr_from_pk (pk), colon_strtime (pk->expiredate));
    1419             : 
    1420          85 :   if (!opt.fast_list_mode && !opt.no_expensive_trust_checks)
    1421          85 :     es_putc (get_ownertrust_info (pk), es_stdout);
    1422          85 :   es_putc (':', es_stdout);
    1423             : 
    1424          85 :   es_putc (':', es_stdout);
    1425          85 :   es_putc (':', es_stdout);
    1426          85 :   print_capabilities (pk, keyblock);
    1427          85 :   es_putc (':', es_stdout);             /* End of field 13. */
    1428          85 :   es_putc (':', es_stdout);             /* End of field 14. */
    1429          85 :   if (secret || has_secret)
    1430             :     {
    1431           0 :       if (stubkey)
    1432           0 :         es_putc ('#', es_stdout);
    1433           0 :       else if (serialno)
    1434           0 :         es_fputs (serialno, es_stdout);
    1435           0 :       else if (has_secret)
    1436           0 :         es_putc ('+', es_stdout);
    1437             :     }
    1438          85 :   es_putc (':', es_stdout);             /* End of field 15. */
    1439          85 :   es_putc (':', es_stdout);             /* End of field 16. */
    1440          85 :   if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
    1441          85 :       || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
    1442          85 :       || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
    1443             :     {
    1444           0 :       char *curve = openpgp_oid_to_str (pk->pkey[0]);
    1445           0 :       const char *name = openpgp_oid_to_curve (curve, 0);
    1446           0 :       if (!name)
    1447           0 :         name = curve;
    1448           0 :       es_fputs (name, es_stdout);
    1449           0 :       xfree (curve);
    1450             :     }
    1451          85 :   es_putc (':', es_stdout);             /* End of field 17. */
    1452          85 :   es_putc (':', es_stdout);             /* End of field 18. */
    1453          85 :   es_putc ('\n', es_stdout);
    1454             : 
    1455          85 :   print_revokers (es_stdout, pk);
    1456          85 :   if (fpr)
    1457           0 :     print_fingerprint (NULL, pk, 0);
    1458          85 :   if (opt.with_key_data || opt.with_keygrip)
    1459             :     {
    1460           0 :       if (hexgrip)
    1461           0 :         es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
    1462           0 :       if (opt.with_key_data)
    1463           0 :         print_key_data (pk);
    1464             :     }
    1465             : 
    1466         590 :   for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
    1467             :     {
    1468         420 :       if (node->pkt->pkttype == PKT_USER_ID)
    1469             :         {
    1470             :           char *str;
    1471          85 :           PKT_user_id *uid = node->pkt->pkt.user_id;
    1472             : 
    1473          85 :           if (attrib_fp && node->pkt->pkt.user_id->attrib_data != NULL)
    1474           0 :             dump_attribs (node->pkt->pkt.user_id, pk);
    1475             :           /*
    1476             :            * Fixme: We need a valid flag here too
    1477             :            */
    1478          85 :           str = uid->attrib_data ? "uat" : "uid";
    1479          85 :           if (uid->is_revoked)
    1480           0 :             es_fprintf (es_stdout, "%s:r::::", str);
    1481          85 :           else if (uid->is_expired)
    1482           0 :             es_fprintf (es_stdout, "%s:e::::", str);
    1483          85 :           else if (opt.no_expensive_trust_checks)
    1484           0 :             es_fprintf (es_stdout, "%s:::::", str);
    1485             :           else
    1486             :             {
    1487             :               int uid_validity;
    1488             : 
    1489          85 :               if (!ulti_hack)
    1490          85 :                 uid_validity = get_validity_info (pk, uid);
    1491             :               else
    1492           0 :                 uid_validity = 'u';
    1493          85 :               es_fprintf (es_stdout, "%s:%c::::", str, uid_validity);
    1494             :             }
    1495             : 
    1496          85 :           es_fprintf (es_stdout, "%s:", colon_strtime (uid->created));
    1497          85 :           es_fprintf (es_stdout, "%s:", colon_strtime (uid->expiredate));
    1498             : 
    1499          85 :           namehash_from_uid (uid);
    1500             : 
    1501        1785 :           for (i = 0; i < 20; i++)
    1502        1700 :             es_fprintf (es_stdout, "%02X", uid->namehash[i]);
    1503             : 
    1504          85 :           es_fprintf (es_stdout, "::");
    1505             : 
    1506          85 :           if (uid->attrib_data)
    1507           0 :             es_fprintf (es_stdout, "%u %lu", uid->numattribs, uid->attrib_len);
    1508             :           else
    1509          85 :             es_write_sanitized (es_stdout, uid->name, uid->len, ":", NULL);
    1510          85 :           es_fprintf (es_stdout, "::::::::");
    1511          85 :           if (opt.trust_model == TM_TOFU || opt.trust_model == TM_TOFU_PGP)
    1512             :             {
    1513             : #ifdef USE_TOFU
    1514             :               enum tofu_policy policy;
    1515          82 :               if (! tofu_get_policy (pk, uid, &policy)
    1516          82 :                   && policy != TOFU_POLICY_NONE)
    1517          82 :                 es_fprintf (es_stdout, "%s", tofu_policy_str (policy));
    1518             : #endif /*USE_TOFU*/
    1519             :             }
    1520          85 :           es_putc (':', es_stdout);
    1521          85 :           es_putc ('\n', es_stdout);
    1522             :         }
    1523         335 :       else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    1524             :         {
    1525             :           u32 keyid2[2];
    1526             :           PKT_public_key *pk2;
    1527             : 
    1528          82 :           pk2 = node->pkt->pkt.public_key;
    1529          82 :           xfree (hexgrip); hexgrip = NULL;
    1530          82 :           xfree (serialno); serialno = NULL;
    1531          82 :           if (secret || has_secret || opt.with_keygrip || opt.with_key_data)
    1532             :             {
    1533           0 :               rc = hexkeygrip_from_pk (pk2, &hexgrip);
    1534           0 :               if (rc)
    1535           0 :                 log_error ("error computing a keygrip: %s\n",
    1536             :                            gpg_strerror (rc));
    1537             :             }
    1538          82 :           stubkey = 0;
    1539          82 :           if ((secret||has_secret)
    1540           0 :               && agent_get_keyinfo (NULL, hexgrip, &serialno))
    1541           0 :             stubkey = 1;  /* Key not found.  */
    1542             : 
    1543          82 :           keyid_from_pk (pk2, keyid2);
    1544          82 :           es_fputs (secret? "ssb:":"sub:", es_stdout);
    1545          82 :           if (!pk2->flags.valid)
    1546           0 :             es_putc ('i', es_stdout);
    1547          82 :           else if (pk2->flags.revoked)
    1548           0 :             es_putc ('r', es_stdout);
    1549          82 :           else if (pk2->has_expired)
    1550           0 :             es_putc ('e', es_stdout);
    1551          82 :           else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
    1552             :             ;
    1553             :           else
    1554             :             {
    1555             :               /* TRUSTLETTER should always be defined here. */
    1556          82 :               if (trustletter)
    1557          82 :                 es_fprintf (es_stdout, "%c", trustletter);
    1558             :             }
    1559         328 :           es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s:::::",
    1560             :                   nbits_from_pk (pk2),
    1561          82 :                   pk2->pubkey_algo,
    1562         164 :                   (ulong) keyid2[0], (ulong) keyid2[1],
    1563             :                   colon_datestr_from_pk (pk2), colon_strtime (pk2->expiredate)
    1564             :                   /* fixme: add LID and ownertrust here */
    1565             :             );
    1566          82 :           print_capabilities (pk2, NULL);
    1567          82 :           es_putc (':', es_stdout);     /* End of field 13. */
    1568          82 :           es_putc (':', es_stdout);     /* End of field 14. */
    1569          82 :           if (secret || has_secret)
    1570             :             {
    1571           0 :               if (stubkey)
    1572           0 :                 es_putc ('#', es_stdout);
    1573           0 :               else if (serialno)
    1574           0 :                 es_fputs (serialno, es_stdout);
    1575           0 :               else if (has_secret)
    1576           0 :                 es_putc ('+', es_stdout);
    1577             :             }
    1578          82 :           es_putc (':', es_stdout);     /* End of field 15. */
    1579          82 :           es_putc (':', es_stdout);     /* End of field 16. */
    1580          82 :           if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
    1581          82 :               || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
    1582          82 :               || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
    1583             :             {
    1584           0 :               char *curve = openpgp_oid_to_str (pk->pkey[0]);
    1585           0 :               const char *name = openpgp_oid_to_curve (curve, 0);
    1586           0 :               if (!name)
    1587           0 :                 name = curve;
    1588           0 :               es_fputs (name, es_stdout);
    1589           0 :               xfree (curve);
    1590             :             }
    1591          82 :           es_putc (':', es_stdout);     /* End of field 17. */
    1592          82 :           es_putc ('\n', es_stdout);
    1593          82 :           if (fpr > 1)
    1594           0 :             print_fingerprint (NULL, pk2, 0);
    1595          82 :           if (opt.with_key_data || opt.with_keygrip)
    1596             :             {
    1597           0 :               if (hexgrip)
    1598           0 :                 es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
    1599           0 :               if (opt.with_key_data)
    1600           0 :                 print_key_data (pk2);
    1601             :             }
    1602             :         }
    1603         253 :       else if (opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE)
    1604             :         {
    1605           0 :           PKT_signature *sig = node->pkt->pkt.signature;
    1606           0 :           int sigrc, fprokay = 0;
    1607             :           char *sigstr;
    1608             :           size_t fplen;
    1609             :           byte fparray[MAX_FINGERPRINT_LEN];
    1610             : 
    1611           0 :           if (sig->sig_class == 0x20 || sig->sig_class == 0x28
    1612           0 :               || sig->sig_class == 0x30)
    1613           0 :             sigstr = "rev";
    1614           0 :           else if ((sig->sig_class & ~3) == 0x10)
    1615           0 :             sigstr = "sig";
    1616           0 :           else if (sig->sig_class == 0x18)
    1617           0 :             sigstr = "sig";
    1618           0 :           else if (sig->sig_class == 0x1F)
    1619           0 :             sigstr = "sig";
    1620             :           else
    1621             :             {
    1622           0 :               es_fprintf (es_stdout, "sig::::::::::%02x%c:\n",
    1623           0 :                       sig->sig_class, sig->flags.exportable ? 'x' : 'l');
    1624           0 :               continue;
    1625             :             }
    1626             : 
    1627           0 :           if (opt.check_sigs)
    1628             :             {
    1629           0 :               PKT_public_key *signer_pk = NULL;
    1630             : 
    1631           0 :               fflush (stdout);
    1632           0 :               if (opt.no_sig_cache)
    1633           0 :                 signer_pk = xmalloc_clear (sizeof (PKT_public_key));
    1634             : 
    1635           0 :               rc = check_key_signature2 (keyblock, node, NULL, signer_pk,
    1636             :                                          NULL, NULL, NULL);
    1637           0 :               switch (gpg_err_code (rc))
    1638             :                 {
    1639             :                 case 0:
    1640           0 :                   sigrc = '!';
    1641           0 :                   break;
    1642             :                 case GPG_ERR_BAD_SIGNATURE:
    1643           0 :                   sigrc = '-';
    1644           0 :                   break;
    1645             :                 case GPG_ERR_NO_PUBKEY:
    1646             :                 case GPG_ERR_UNUSABLE_PUBKEY:
    1647           0 :                   sigrc = '?';
    1648           0 :                   break;
    1649             :                 default:
    1650           0 :                   sigrc = '%';
    1651           0 :                   break;
    1652             :                 }
    1653             : 
    1654           0 :               if (opt.no_sig_cache)
    1655             :                 {
    1656           0 :                   if (!rc)
    1657             :                     {
    1658           0 :                       fingerprint_from_pk (signer_pk, fparray, &fplen);
    1659           0 :                       fprokay = 1;
    1660             :                     }
    1661           0 :                   free_public_key (signer_pk);
    1662             :                 }
    1663             :             }
    1664             :           else
    1665             :             {
    1666           0 :               rc = 0;
    1667           0 :               sigrc = ' ';
    1668             :             }
    1669           0 :           es_fputs (sigstr, es_stdout);
    1670           0 :           es_putc (':', es_stdout);
    1671           0 :           if (sigrc != ' ')
    1672           0 :             es_putc (sigrc, es_stdout);
    1673           0 :           es_fprintf (es_stdout, "::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo,
    1674           0 :                   (ulong) sig->keyid[0], (ulong) sig->keyid[1],
    1675             :                   colon_datestr_from_sig (sig),
    1676             :                   colon_expirestr_from_sig (sig));
    1677             : 
    1678           0 :           if (sig->trust_depth || sig->trust_value)
    1679           0 :             es_fprintf (es_stdout, "%d %d", sig->trust_depth, sig->trust_value);
    1680           0 :           es_fprintf (es_stdout, ":");
    1681             : 
    1682           0 :           if (sig->trust_regexp)
    1683           0 :             es_write_sanitized (es_stdout, sig->trust_regexp,
    1684           0 :                                 strlen (sig->trust_regexp), ":", NULL);
    1685           0 :           es_fprintf (es_stdout, ":");
    1686             : 
    1687           0 :           if (sigrc == '%')
    1688           0 :             es_fprintf (es_stdout, "[%s] ", gpg_strerror (rc));
    1689           0 :           else if (sigrc == '?')
    1690             :             ;
    1691           0 :           else if (!opt.fast_list_mode)
    1692             :             {
    1693             :               size_t n;
    1694           0 :               p = get_user_id (sig->keyid, &n);
    1695           0 :               es_write_sanitized (es_stdout, p, n, ":", NULL);
    1696           0 :               xfree (p);
    1697             :             }
    1698           0 :           es_fprintf (es_stdout, ":%02x%c::", sig->sig_class,
    1699           0 :                   sig->flags.exportable ? 'x' : 'l');
    1700             : 
    1701           0 :           if (opt.no_sig_cache && opt.check_sigs && fprokay)
    1702             :             {
    1703           0 :               for (i = 0; i < fplen; i++)
    1704           0 :                 es_fprintf (es_stdout, "%02X", fparray[i]);
    1705             :             }
    1706             : 
    1707           0 :           es_fprintf (es_stdout, ":::%d:\n", sig->digest_algo);
    1708             : 
    1709           0 :           if (opt.show_subpackets)
    1710           0 :             print_subpackets_colon (sig);
    1711             : 
    1712             :           /* fixme: check or list other sigs here */
    1713             :         }
    1714             :     }
    1715             : 
    1716          85 :   xfree (hexgrip);
    1717          85 :   xfree (serialno);
    1718             : }
    1719             : 
    1720             : /*
    1721             :  * Reorder the keyblock so that the primary user ID (and not attribute
    1722             :  * packet) comes first.  Fixme: Replace this by a generic sort
    1723             :  * function.  */
    1724             : static void
    1725         176 : do_reorder_keyblock (KBNODE keyblock, int attr)
    1726             : {
    1727         176 :   KBNODE primary = NULL, primary0 = NULL, primary2 = NULL;
    1728             :   KBNODE last, node;
    1729             : 
    1730         700 :   for (node = keyblock; node; primary0 = node, node = node->next)
    1731             :     {
    1732         612 :       if (node->pkt->pkttype == PKT_USER_ID &&
    1733          88 :           ((attr && node->pkt->pkt.user_id->attrib_data) ||
    1734         176 :            (!attr && !node->pkt->pkt.user_id->attrib_data)) &&
    1735          88 :           node->pkt->pkt.user_id->is_primary)
    1736             :         {
    1737          88 :           primary = primary2 = node;
    1738         176 :           for (node = node->next; node; primary2 = node, node = node->next)
    1739             :             {
    1740         173 :               if (node->pkt->pkttype == PKT_USER_ID
    1741         173 :                   || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    1742          88 :                   || node->pkt->pkttype == PKT_SECRET_SUBKEY)
    1743             :                 {
    1744             :                   break;
    1745             :                 }
    1746             :             }
    1747          88 :           break;
    1748             :         }
    1749             :     }
    1750         176 :   if (!primary)
    1751          88 :     return; /* No primary key flag found (should not happen).  */
    1752             : 
    1753         177 :   for (last = NULL, node = keyblock; node; last = node, node = node->next)
    1754             :     {
    1755         177 :       if (node->pkt->pkttype == PKT_USER_ID)
    1756          88 :         break;
    1757             :     }
    1758          88 :   assert (node);
    1759          88 :   assert (last);         /* The user ID is never the first packet.  */
    1760          88 :   assert (primary0);     /* Ditto (this is the node before primary).  */
    1761          88 :   if (node == primary)
    1762          88 :     return; /* Already the first one.  */
    1763             : 
    1764           0 :   last->next = primary;
    1765           0 :   primary0->next = primary2->next;
    1766           0 :   primary2->next = node;
    1767             : }
    1768             : 
    1769             : void
    1770          88 : reorder_keyblock (KBNODE keyblock)
    1771             : {
    1772          88 :   do_reorder_keyblock (keyblock, 1);
    1773          88 :   do_reorder_keyblock (keyblock, 0);
    1774          88 : }
    1775             : 
    1776             : static void
    1777          88 : list_keyblock (ctrl_t ctrl,
    1778             :                KBNODE keyblock, int secret, int has_secret, int fpr,
    1779             :                struct keylist_context *listctx)
    1780             : {
    1781          88 :   reorder_keyblock (keyblock);
    1782          88 :   if (opt.print_pka_records || opt.print_dane_records)
    1783           0 :     list_keyblock_pka (ctrl, keyblock);
    1784          88 :   else if (opt.with_colons)
    1785          85 :     list_keyblock_colon (keyblock, secret, has_secret, fpr);
    1786             :   else
    1787           3 :     list_keyblock_print (keyblock, secret, fpr, listctx);
    1788          88 :   if (secret)
    1789           0 :     es_fflush (es_stdout);
    1790          88 : }
    1791             : 
    1792             : 
    1793             : /* Public function used by keygen to list a keyblock.  */
    1794             : void
    1795           0 : list_keyblock_direct (ctrl_t ctrl,
    1796             :                       kbnode_t keyblock, int secret, int has_secret, int fpr)
    1797             : {
    1798             :   struct keylist_context listctx;
    1799             : 
    1800           0 :   memset (&listctx, 0, sizeof (listctx));
    1801           0 :   list_keyblock (ctrl, keyblock, secret, has_secret, fpr, &listctx);
    1802           0 :   keylist_context_release (&listctx);
    1803           0 : }
    1804             : 
    1805             : 
    1806             : /* Print an hex digit in ICAO spelling.  */
    1807             : static void
    1808           0 : print_icao_hexdigit (estream_t fp, int c)
    1809             : {
    1810             :   static const char *list[16] = {
    1811             :     "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven",
    1812             :     "Eight", "Niner", "Alfa", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot"
    1813             :   };
    1814             : 
    1815           0 :   tty_fprintf (fp, "%s", list[c&15]);
    1816           0 : }
    1817             : 
    1818             : 
    1819             : /*
    1820             :  * Function to print the finperprint.
    1821             :  * mode 0: as used in key listings, opt.with_colons is honored
    1822             :  *      1: print using log_info ()
    1823             :  *      2: direct use of tty
    1824             :  *      3: direct use of tty but only primary key.
    1825             :  *      4: direct use of tty but only subkey.
    1826             :  *     10: Same as 0 but with_colons etc is ignored.
    1827             :  *
    1828             :  * Modes 1 and 2 will try and print both subkey and primary key
    1829             :  * fingerprints.  A MODE with bit 7 set is used internally.  If
    1830             :  * OVERRIDE_FP is not NULL that stream will be used in  0 instead
    1831             :  * of es_stdout or instead of the TTY in modes 2 and 3.
    1832             :  */
    1833             : void
    1834         145 : print_fingerprint (estream_t override_fp, PKT_public_key *pk, int mode)
    1835             : {
    1836             :   byte array[MAX_FINGERPRINT_LEN], *p;
    1837             :   size_t i, n;
    1838             :   estream_t fp;
    1839             :   const char *text;
    1840         145 :   int primary = 0;
    1841         145 :   int with_colons = opt.with_colons;
    1842         145 :   int with_icao   = opt.with_icao_spelling;
    1843             : 
    1844         145 :   if (mode == 10)
    1845             :     {
    1846           0 :       mode = 0;
    1847           0 :       with_colons = 0;
    1848           0 :       with_icao = 0;
    1849             :     }
    1850             : 
    1851         145 :   if (pk->main_keyid[0] == pk->keyid[0]
    1852         145 :       && pk->main_keyid[1] == pk->keyid[1])
    1853         145 :     primary = 1;
    1854             : 
    1855             :   /* Just to be safe */
    1856         145 :   if ((mode & 0x80) && !primary)
    1857             :     {
    1858           0 :       log_error ("primary key is not really primary!\n");
    1859         145 :       return;
    1860             :     }
    1861             : 
    1862         145 :   mode &= ~0x80;
    1863             : 
    1864         145 :   if (!primary && (mode == 1 || mode == 2))
    1865             :     {
    1866           0 :       PKT_public_key *primary_pk = xmalloc_clear (sizeof (*primary_pk));
    1867           0 :       get_pubkey (primary_pk, pk->main_keyid);
    1868           0 :       print_fingerprint (override_fp, primary_pk, (mode | 0x80));
    1869           0 :       free_public_key (primary_pk);
    1870             :     }
    1871             : 
    1872         145 :   if (mode == 1)
    1873             :     {
    1874         143 :       fp = log_get_stream ();
    1875         143 :       if (primary)
    1876         143 :         text = _("Primary key fingerprint:");
    1877             :       else
    1878           0 :         text = _("     Subkey fingerprint:");
    1879             :     }
    1880           2 :   else if (mode == 2)
    1881             :     {
    1882           0 :       fp = override_fp; /* Use tty or given stream.  */
    1883           0 :       if (primary)
    1884             :         /* TRANSLATORS: this should fit into 24 bytes so that the
    1885             :          * fingerprint data is properly aligned with the user ID */
    1886           0 :         text = _(" Primary key fingerprint:");
    1887             :       else
    1888           0 :         text = _("      Subkey fingerprint:");
    1889             :     }
    1890           2 :   else if (mode == 3)
    1891             :     {
    1892           2 :       fp = override_fp; /* Use tty or given stream.  */
    1893           2 :       text = _("      Key fingerprint =");
    1894             :     }
    1895           0 :   else if (mode == 4)
    1896             :     {
    1897           0 :       fp = override_fp; /* Use tty or given stream.  */
    1898           0 :       text = _("      Subkey fingerprint:");
    1899             :     }
    1900             :   else
    1901             :     {
    1902           0 :       fp = override_fp? override_fp : es_stdout;
    1903           0 :       text = _("      Key fingerprint =");
    1904             :     }
    1905             : 
    1906         145 :   fingerprint_from_pk (pk, array, &n);
    1907         145 :   p = array;
    1908         145 :   if (with_colons && !mode)
    1909             :     {
    1910           0 :       es_fprintf (fp, "fpr:::::::::");
    1911           0 :       for (i = 0; i < n; i++, p++)
    1912           0 :         es_fprintf (fp, "%02X", *p);
    1913           0 :       es_putc (':', fp);
    1914             :     }
    1915             :   else
    1916             :     {
    1917         145 :       tty_fprintf (fp, "%s", text);
    1918         145 :       if (n == 20)
    1919             :         {
    1920        1595 :           for (i = 0; i < n; i++, i++, p += 2)
    1921        1450 :             tty_fprintf (fp, "%s %02X%02X", i==10? " ":"", *p, p[1]);
    1922             :         }
    1923             :       else
    1924             :         {
    1925           0 :           for (i = 0; i < n; i++, p++)
    1926           0 :             tty_fprintf (fp, "%s %02X", (i && !(i % 8))? " ":"", *p);
    1927             :         }
    1928             :     }
    1929         145 :   tty_fprintf (fp, "\n");
    1930         145 :   if (!with_colons && with_icao)
    1931             :     {
    1932           0 :       p = array;
    1933           0 :       tty_fprintf (fp, "%*s\"", (int)strlen(text)+1, "");
    1934           0 :       for (i = 0; i < n; i++, p++)
    1935             :         {
    1936           0 :           if (!i)
    1937             :             ;
    1938           0 :           else if (!(i%4))
    1939           0 :             tty_fprintf (fp, "\n%*s ", (int)strlen(text)+1, "");
    1940           0 :           else if (!(i%2))
    1941           0 :             tty_fprintf (fp, "  ");
    1942             :           else
    1943           0 :             tty_fprintf (fp, " ");
    1944           0 :           print_icao_hexdigit (fp, *p >> 4);
    1945           0 :           tty_fprintf (fp, " ");
    1946           0 :           print_icao_hexdigit (fp, *p & 15);
    1947             :         }
    1948           0 :       tty_fprintf (fp, "\"\n");
    1949             :     }
    1950             : }
    1951             : 
    1952             : /* Print the serial number of an OpenPGP card if available.  */
    1953             : static void
    1954           0 : print_card_serialno (const char *serialno)
    1955             : {
    1956           0 :   if (!serialno)
    1957           0 :     return;
    1958           0 :   if (opt.with_colons)
    1959           0 :     return; /* Handled elsewhere. */
    1960             : 
    1961           0 :   es_fputs (_("      Card serial no. ="), es_stdout);
    1962           0 :   es_putc (' ', es_stdout);
    1963           0 :   if (strlen (serialno) == 32 && !strncmp (serialno, "D27600012401", 12))
    1964             :     {
    1965             :       /* This is an OpenPGP card.  Print the relevant part.  */
    1966             :       /* Example: D2760001240101010001000003470000 */
    1967             :       /*                          xxxxyyyyyyyy     */
    1968           0 :       es_fprintf (es_stdout, "%.*s %.*s", 4, serialno+16, 8, serialno+20);
    1969             :     }
    1970             :  else
    1971           0 :    es_fputs (serialno, es_stdout);
    1972           0 :   es_putc ('\n', es_stdout);
    1973             : }
    1974             : 
    1975             : 
    1976             : 
    1977             : void
    1978           0 : set_attrib_fd (int fd)
    1979             : {
    1980             :   static int last_fd = -1;
    1981             : 
    1982           0 :   if (fd != -1 && last_fd == fd)
    1983           0 :     return;
    1984             : 
    1985             :   /* Fixme: Do we need to check for the log stream here?  */
    1986           0 :   if (attrib_fp && attrib_fp != log_get_stream ())
    1987           0 :     es_fclose (attrib_fp);
    1988           0 :   attrib_fp = NULL;
    1989           0 :   if (fd == -1)
    1990           0 :     return;
    1991             : 
    1992             : #ifdef HAVE_DOSISH_SYSTEM
    1993             :   setmode (fd, O_BINARY);
    1994             : #endif
    1995           0 :   if (fd == 1)
    1996           0 :     attrib_fp = es_stdout;
    1997           0 :   else if (fd == 2)
    1998           0 :     attrib_fp = es_stderr;
    1999             :   else
    2000           0 :     attrib_fp = es_fdopen (fd, "wb");
    2001           0 :   if (!attrib_fp)
    2002             :     {
    2003           0 :       log_fatal ("can't open fd %d for attribute output: %s\n",
    2004           0 :                  fd, strerror (errno));
    2005             :     }
    2006             : 
    2007           0 :   last_fd = fd;
    2008             : }

Generated by: LCOV version 1.11