Removed more secret key related code.
[gnupg.git] / g10 / keylist.c
1 /* keylist.c - Print information about OpenPGP keys
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3  *               2008, 2010 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #ifdef HAVE_DOSISH_SYSTEM
28 #include <fcntl.h>              /* for setmode() */
29 #endif
30
31 #include "gpg.h"
32 #include "options.h"
33 #include "packet.h"
34 #include "status.h"
35 #include "keydb.h"
36 #include "photoid.h"
37 #include "util.h"
38 #include "ttyio.h"
39 #include "trustdb.h"
40 #include "main.h"
41 #include "i18n.h"
42 #include "status.h"
43
44 static void list_all (int);
45 static void list_one (strlist_t names, int secret);
46 static void locate_one (strlist_t names);
47 static void print_card_serialno (PKT_public_key *sk);
48
49 struct sig_stats
50 {
51   int inv_sigs;
52   int no_key;
53   int oth_err;
54 };
55
56 /* The stream used to write attribute packets to.  */
57 static estream_t attrib_fp;
58
59
60 /* List the keys.  If list is NULL, all available keys are listed.
61    With LOCATE_MODE set the locate algorithm is used to find a
62    key.  */
63 void
64 public_key_list (strlist_t list, int locate_mode)
65 {
66   if (opt.with_colons)
67     {
68       byte trust_model, marginals, completes, cert_depth;
69       ulong created, nextcheck;
70
71       read_trust_options (&trust_model, &created, &nextcheck,
72                           &marginals, &completes, &cert_depth);
73
74       es_fprintf (es_stdout, "tru:");
75
76       if (nextcheck && nextcheck <= make_timestamp ())
77         es_fprintf (es_stdout, "o");
78       if (trust_model != opt.trust_model)
79         es_fprintf (es_stdout, "t");
80       if (opt.trust_model == TM_PGP || opt.trust_model == TM_CLASSIC)
81         {
82           if (marginals != opt.marginals_needed)
83             es_fprintf (es_stdout, "m");
84           if (completes != opt.completes_needed)
85             es_fprintf (es_stdout, "c");
86           if (cert_depth != opt.max_cert_depth)
87             es_fprintf (es_stdout, "d");
88         }
89
90       es_fprintf (es_stdout, ":%d:%lu:%lu", trust_model, created, nextcheck);
91
92       /* Only show marginals, completes, and cert_depth in the classic
93          or PGP trust models since they are not meaningful
94          otherwise. */
95
96       if (trust_model == TM_PGP || trust_model == TM_CLASSIC)
97         es_fprintf (es_stdout, ":%d:%d:%d", marginals, completes, cert_depth);
98
99       es_fprintf (es_stdout, "\n");
100     }
101
102   /* We need to do the stale check right here because it might need to
103      update the keyring while we already have the keyring open.  This
104      is very bad for W32 because of a sharing violation. For real OSes
105      it might lead to false results if we are later listing a keyring
106      which is associated with the inode of a deleted file.  */
107   check_trustdb_stale ();
108
109   if (locate_mode)
110     locate_one (list);
111   else if (!list)
112     list_all (0);
113   else
114     list_one (list, 0);
115 }
116
117
118 void
119 secret_key_list (strlist_t list)
120 {
121   check_trustdb_stale ();
122
123   if (!list)
124     list_all (1);
125   else                          /* List by user id */
126     list_one (list, 1);
127 }
128
129 void
130 print_seckey_info (PKT_public_key *pk)
131 {
132   u32 keyid[2];
133   char *p;
134
135   keyid_from_pk (pk, keyid);
136   p = get_user_id_native (keyid);
137
138   tty_printf ("\nsec  %4u%c/%s %s %s\n",
139               nbits_from_pk (pk),
140               pubkey_letter (pk->pubkey_algo),
141               keystr (keyid), datestr_from_pk (pk), p);
142
143   xfree (p);
144 }
145
146 /* Print information about the public key.  With FP passed as NULL,
147    the tty output interface is used, otherwise output is directted to
148    the given stream.  */
149 void
150 print_pubkey_info (estream_t fp, PKT_public_key * pk)
151 {
152   u32 keyid[2];
153   char *p;
154
155   keyid_from_pk (pk, keyid);
156
157   /* If the pk was chosen by a particular user ID, that is the one to
158      print.  */
159   if (pk->user_id)
160     p = utf8_to_native (pk->user_id->name, pk->user_id->len, 0);
161   else
162     p = get_user_id_native (keyid);
163
164   if (fp)
165     tty_printf ("\n");
166   tty_fprintf (fp, "pub  %4u%c/%s %s %s\n",
167                nbits_from_pk (pk),
168                pubkey_letter (pk->pubkey_algo),
169                keystr (keyid), datestr_from_pk (pk), p);
170   xfree (p);
171 }
172
173
174 /* Print basic information of a secret key including the card serial
175    number information.  */
176 void
177 print_card_key_info (estream_t fp, kbnode_t keyblock)
178 {
179   /* KBNODE node; */
180   /* int i; */
181
182   log_debug ("Fixme: Needs to be adjusted to gpg-agent\n");
183   /* for (node = keyblock; node; node = node->next) */
184   /*   { */
185   /*     if (node->pkt->pkttype == PKT_SECRET_KEY */
186   /*         || (node->pkt->pkttype == PKT_SECRET_SUBKEY)) */
187   /*       { */
188   /*         PKT_public_key *pk = node->pkt->pkt.public_key; */
189
190   /*         tty_fprintf (fp, "%s%c  %4u%c/%s  ", */
191   /*                   node->pkt->pkttype == PKT_SECRET_KEY ? "sec" : "ssb", */
192   /*                   (sk->protect.s2k.mode == 1001) ? '#' : */
193   /*                   (sk->protect.s2k.mode == 1002) ? '>' : ' ', */
194   /*                   nbits_from_sk (sk), */
195   /*                   pubkey_letter (sk->pubkey_algo), keystr_from_sk (sk)); */
196   /*         tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk)); */
197   /*         tty_fprintf (fp, "  "); */
198   /*         tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk)); */
199   /*         if (sk->is_protected && sk->protect.s2k.mode == 1002) */
200   /*           { */
201   /*             tty_fprintf (fp, "\n                      "); */
202   /*             tty_fprintf (fp, _("card-no: ")); */
203   /*             if (sk->protect.ivlen == 16 */
204   /*              && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) */
205   /*            { */
206   /*              /\* This is an OpenPGP card. *\/ */
207   /*              for (i = 8; i < 14; i++) */
208   /*                { */
209   /*                  if (i == 10) */
210   /*                    tty_fprintf (fp, " "); */
211   /*                  tty_fprintf (fp, "%02X", sk->protect.iv[i]); */
212   /*                } */
213   /*            } */
214   /*             else */
215   /*            { */
216   /*                 /\* Something is wrong: Print all. *\/ */
217   /*              for (i = 0; i < sk->protect.ivlen; i++) */
218   /*                tty_fprintf (fp, "%02X", sk->protect.iv[i]); */
219   /*            } */
220   /*           } */
221   /*         tty_fprintf (fp, "\n"); */
222   /*       } */
223   /*   } */
224 }
225
226
227
228 /* Flags = 0x01 hashed 0x02 critical.  */
229 static void
230 status_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
231                       const byte * buf)
232 {
233   char status[40];
234
235   /* Don't print these. */
236   if (len > 256)
237     return;
238
239   snprintf (status, sizeof status, 
240             "%d %u %u ", type, flags, (unsigned int) len);
241
242   write_status_text_and_buffer (STATUS_SIG_SUBPACKET, status, buf, len, 0);
243 }
244
245
246 /* Print a policy URL.  Allowed values for MODE are:
247  *   0 - print to stdout.
248  *   1 - use log_info and emit status messages.
249  *   2 - emit only status messages.
250  */
251 void
252 show_policy_url (PKT_signature * sig, int indent, int mode)
253 {
254   const byte *p;
255   size_t len;
256   int seq = 0, crit;
257   estream_t fp = mode ? log_get_stream () : es_stdout;
258
259   while ((p =
260           enum_sig_subpkt (sig->hashed, SIGSUBPKT_POLICY, &len, &seq, &crit)))
261     {
262       if (mode != 2)
263         {
264           int i;
265           const char *str;
266
267           for (i = 0; i < indent; i++)
268             es_putc (' ', fp);
269
270           if (crit)
271             str = _("Critical signature policy: ");
272           else
273             str = _("Signature policy: ");
274           if (mode)
275             log_info ("%s", str);
276           else
277             es_fprintf (fp, "%s", str);
278           print_utf8_buffer (fp, p, len);
279           es_fprintf (fp, "\n");
280         }
281
282       if (mode)
283         write_status_buffer (STATUS_POLICY_URL, p, len, 0);
284     }
285 }
286
287
288 /*
289   mode=0 for stdout.
290   mode=1 for log_info + status messages
291   mode=2 for status messages only
292 */
293 /* TODO: use this */
294 void
295 show_keyserver_url (PKT_signature * sig, int indent, int mode)
296 {
297   const byte *p;
298   size_t len;
299   int seq = 0, crit;
300   estream_t fp = mode ? log_get_stream () : es_stdout;
301
302   while ((p =
303           enum_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_KS, &len, &seq,
304                            &crit)))
305     {
306       if (mode != 2)
307         {
308           int i;
309           const char *str;
310
311           for (i = 0; i < indent; i++)
312             es_putc (' ', es_stdout);
313
314           if (crit)
315             str = _("Critical preferred keyserver: ");
316           else
317             str = _("Preferred keyserver: ");
318           if (mode)
319             log_info ("%s", str);
320           else
321             es_fprintf (es_stdout, "%s", str);
322           print_utf8_buffer (fp, p, len);
323           es_fprintf (fp, "\n");
324         }
325
326       if (mode)
327         status_one_subpacket (SIGSUBPKT_PREF_KS, len,
328                               (crit ? 0x02 : 0) | 0x01, p);
329     }
330 }
331
332 /*
333   mode=0 for stdout.
334   mode=1 for log_info + status messages
335   mode=2 for status messages only
336
337   Defined bits in WHICH:
338     1 == standard notations
339     2 == user notations
340 */
341 void
342 show_notation (PKT_signature * sig, int indent, int mode, int which)
343 {
344   estream_t fp = mode ? log_get_stream () : es_stdout;
345   struct notation *nd, *notations;
346
347   if (which == 0)
348     which = 3;
349
350   notations = sig_to_notation (sig);
351
352   /* There may be multiple notations in the same sig. */
353   for (nd = notations; nd; nd = nd->next)
354     {
355       if (mode != 2)
356         {
357           int has_at = !!strchr (nd->name, '@');
358
359           if ((which & 1 && !has_at) || (which & 2 && has_at))
360             {
361               int i;
362               const char *str;
363
364               for (i = 0; i < indent; i++)
365                 es_putc (' ', es_stdout);
366
367               if (nd->flags.critical)
368                 str = _("Critical signature notation: ");
369               else
370                 str = _("Signature notation: ");
371               if (mode)
372                 log_info ("%s", str);
373               else
374                 es_fprintf (es_stdout, "%s", str);
375               /* This is all UTF8 */
376               print_utf8_buffer (fp, nd->name, strlen (nd->name));
377               es_fprintf (fp, "=");
378               print_utf8_buffer (fp, nd->value, strlen (nd->value));
379               es_fprintf (fp, "\n");
380             }
381         }
382
383       if (mode)
384         {
385           write_status_buffer (STATUS_NOTATION_NAME,
386                                nd->name, strlen (nd->name), 0);
387           write_status_buffer (STATUS_NOTATION_DATA,
388                                nd->value, strlen (nd->value), 50);
389         }
390     }
391
392   free_notation (notations);
393 }
394
395 static void
396 print_signature_stats (struct sig_stats *s)
397 {
398   if (s->inv_sigs == 1)
399     tty_printf (_("1 bad signature\n"));
400   else if (s->inv_sigs)
401     tty_printf (_("%d bad signatures\n"), s->inv_sigs);
402   if (s->no_key == 1)
403     tty_printf (_("1 signature not checked due to a missing key\n"));
404   else if (s->no_key)
405     tty_printf (_("%d signatures not checked due to missing keys\n"),
406                 s->no_key);
407   if (s->oth_err == 1)
408     tty_printf (_("1 signature not checked due to an error\n"));
409   else if (s->oth_err)
410     tty_printf (_("%d signatures not checked due to errors\n"), s->oth_err);
411 }
412
413 static void
414 list_all (int secret)
415 {
416   KEYDB_HANDLE hd;
417   KBNODE keyblock = NULL;
418   int rc = 0;
419   const char *lastresname, *resname;
420   struct sig_stats stats;
421
422   memset (&stats, 0, sizeof (stats));
423
424   hd = keydb_new ();
425   if (!hd)
426     rc = G10ERR_GENERAL;
427   else
428     rc = keydb_search_first (hd);
429   if (rc)
430     {
431       if (rc != -1)
432         log_error ("keydb_search_first failed: %s\n", g10_errstr (rc));
433       goto leave;
434     }
435
436   lastresname = NULL;
437   do
438     {
439       rc = keydb_get_keyblock (hd, &keyblock);
440       if (rc)
441         {
442           log_error ("keydb_get_keyblock failed: %s\n", g10_errstr (rc));
443           goto leave;
444         }
445       if (secret && !have_any_secret_key (NULL, keyblock))
446         ; /* Secret key listing requested but this isn't one.  */
447       else
448         {
449           if (!opt.with_colons)
450             {
451               resname = keydb_get_resource_name (hd);
452               if (lastresname != resname)
453                 {
454                   int i;
455                   
456                   es_fprintf (es_stdout, "%s\n", resname);
457                   for (i = strlen (resname); i; i--)
458                     es_putc ('-', es_stdout);
459                   es_putc ('\n', es_stdout);
460                   lastresname = resname;
461                 }
462             }
463           merge_keys_and_selfsig (keyblock);
464           list_keyblock (keyblock, secret, opt.fingerprint,
465                          opt.check_sigs ? &stats : NULL);
466         }
467       release_kbnode (keyblock);
468       keyblock = NULL;
469     }
470   while (!(rc = keydb_search_next (hd)));
471   if (rc && rc != -1)
472     log_error ("keydb_search_next failed: %s\n", g10_errstr (rc));
473
474   if (opt.check_sigs && !opt.with_colons)
475     print_signature_stats (&stats);
476
477 leave:
478   release_kbnode (keyblock);
479   keydb_release (hd);
480 }
481
482
483 static void
484 list_one (strlist_t names, int secret)
485 {
486   int rc = 0;
487   KBNODE keyblock = NULL;
488   GETKEY_CTX ctx;
489   const char *resname;
490   const char *keyring_str = _("Keyring");
491   int i;
492   struct sig_stats stats;
493
494   memset (&stats, 0, sizeof (stats));
495
496   /* fixme: using the bynames function has the disadvantage that we
497    * don't know wether one of the names given was not found.  OTOH,
498    * this function has the advantage to list the names in the
499    * sequence as defined by the keyDB and does not duplicate
500    * outputs.  A solution could be do test whether all given have
501    * been listed (this needs a way to use the keyDB search
502    * functions) or to have the search function return indicators for
503    * found names.  Yet another way is to use the keydb search
504    * facilities directly. */
505   rc = getkey_bynames (&ctx, NULL, names, secret, &keyblock);
506   if (rc)
507     {
508       log_error ("error reading key: %s\n", g10_errstr (rc));
509       get_pubkey_end (ctx);
510       return;
511     }
512
513   do
514     {
515       if ((opt.list_options & LIST_SHOW_KEYRING) && !opt.with_colons)
516         {
517           resname = keydb_get_resource_name (get_ctx_handle (ctx));
518           es_fprintf (es_stdout, "%s: %s\n", keyring_str, resname);
519           for (i = strlen (resname) + strlen (keyring_str) + 2; i; i--)
520             es_putc ('-', es_stdout);
521           es_putc ('\n', es_stdout);
522         }
523       list_keyblock (keyblock, secret, opt.fingerprint,
524                      (!secret && opt.check_sigs)? &stats : NULL);
525       release_kbnode (keyblock);
526     }
527   while (!getkey_next (ctx, NULL, &keyblock));
528   getkey_end (ctx);
529   
530   if (opt.check_sigs && !opt.with_colons)
531     print_signature_stats (&stats);
532 }
533
534
535 static void
536 locate_one (strlist_t names)
537 {
538   int rc = 0;
539   strlist_t sl;
540   GETKEY_CTX ctx = NULL;
541   KBNODE keyblock = NULL;
542   struct sig_stats stats;
543
544   memset (&stats, 0, sizeof (stats));
545
546   for (sl = names; sl; sl = sl->next)
547     {
548       rc = get_pubkey_byname (&ctx, NULL, sl->d, &keyblock, NULL, 1, 0);
549       if (rc)
550         {
551           if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
552             log_error ("error reading key: %s\n", g10_errstr (rc));
553         }
554       else
555         {
556           do
557             {
558               list_keyblock (keyblock, 0, opt.fingerprint,
559                              opt.check_sigs ? &stats : NULL);
560               release_kbnode (keyblock);
561             }
562           while (ctx && !get_pubkey_next (ctx, NULL, &keyblock));
563           get_pubkey_end (ctx);
564           ctx = NULL;
565         }
566     }
567
568   if (opt.check_sigs && !opt.with_colons)
569     print_signature_stats (&stats);
570 }
571
572
573 static void
574 print_key_data (PKT_public_key * pk)
575 {
576   int n = pk ? pubkey_get_npkey (pk->pubkey_algo) : 0;
577   int i;
578
579   for (i = 0; i < n; i++)
580     {
581       es_fprintf (es_stdout, "pkd:%d:%u:", i, mpi_get_nbits (pk->pkey[i]));
582       mpi_print (es_stdout, pk->pkey[i], 1);
583       es_putc (':', es_stdout);
584       es_putc ('\n', es_stdout);
585     }
586 }
587
588 static void
589 print_capabilities (PKT_public_key *pk, KBNODE keyblock)
590 {
591   unsigned int use = pk->pubkey_usage;
592   int c_printed = 0;
593
594   if (use & PUBKEY_USAGE_ENC)
595     es_putc ('e', es_stdout);
596   
597   if (use & PUBKEY_USAGE_SIG)
598     {
599       es_putc ('s', es_stdout);
600       if (pk->is_primary)
601         {
602           es_putc ('c', es_stdout);
603           /* The PUBKEY_USAGE_CERT flag was introduced later and we
604              used to always print 'c' for a primary key.  To avoid any
605              regression here we better track whether we printed 'c'
606              already.  */
607           c_printed = 1;
608         }
609     }
610
611   if ((use & PUBKEY_USAGE_CERT) && !c_printed)
612     es_putc ('c', es_stdout);
613
614   if ((use & PUBKEY_USAGE_AUTH))
615     es_putc ('a', es_stdout);
616
617   if (keyblock)
618     {
619       /* Figure out the usable capabilities.  */
620       KBNODE k;
621       int enc = 0, sign = 0, cert = 0, auth = 0, disabled = 0;
622
623       for (k = keyblock; k; k = k->next)
624         {
625           if (k->pkt->pkttype == PKT_PUBLIC_KEY
626               || k->pkt->pkttype == PKT_PUBLIC_SUBKEY)
627             {
628               pk = k->pkt->pkt.public_key;
629
630               if (pk->is_primary)
631                 disabled = pk_is_disabled (pk);
632
633               if (pk->is_valid && !pk->is_revoked && !pk->has_expired)
634                 {
635                   if (pk->pubkey_usage & PUBKEY_USAGE_ENC)
636                     enc = 1;
637                   if (pk->pubkey_usage & PUBKEY_USAGE_SIG)
638                     {
639                       sign = 1;
640                       if (pk->is_primary)
641                         cert = 1;
642                     }
643                   if (pk->pubkey_usage & PUBKEY_USAGE_CERT)
644                     cert = 1;
645                   if ((pk->pubkey_usage & PUBKEY_USAGE_AUTH))
646                     auth = 1;
647                 }
648             }
649         }
650       if (enc)
651         es_putc ('E', es_stdout);
652       if (sign)
653         es_putc ('S', es_stdout);
654       if (cert)
655         es_putc ('C', es_stdout);
656       if (auth)
657         es_putc ('A', es_stdout);
658       if (disabled)
659         es_putc ('D', es_stdout);
660     }
661   
662   es_putc (':', es_stdout);
663 }
664
665
666 /* FLAGS: 0x01 hashed
667           0x02 critical  */
668 static void
669 print_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
670                      const byte * buf)
671 {
672   size_t i;
673
674   es_fprintf (es_stdout, "spk:%d:%u:%u:", type, flags, (unsigned int) len);
675
676   for (i = 0; i < len; i++)
677     {
678       /* printable ascii other than : and % */
679       if (buf[i] >= 32 && buf[i] <= 126 && buf[i] != ':' && buf[i] != '%')
680         es_fprintf (es_stdout, "%c", buf[i]);
681       else
682         es_fprintf (es_stdout, "%%%02X", buf[i]);
683     }
684
685   es_fprintf (es_stdout, "\n");
686 }
687
688
689 void
690 print_subpackets_colon (PKT_signature * sig)
691 {
692   byte *i;
693
694   assert (opt.show_subpackets);
695
696   for (i = opt.show_subpackets; *i; i++)
697     {
698       const byte *p;
699       size_t len;
700       int seq, crit;
701
702       seq = 0;
703
704       while ((p = enum_sig_subpkt (sig->hashed, *i, &len, &seq, &crit)))
705         print_one_subpacket (*i, len, 0x01 | (crit ? 0x02 : 0), p);
706
707       seq = 0;
708
709       while ((p = enum_sig_subpkt (sig->unhashed, *i, &len, &seq, &crit)))
710         print_one_subpacket (*i, len, 0x00 | (crit ? 0x02 : 0), p);
711     }
712 }
713
714
715 void
716 dump_attribs (const PKT_user_id *uid, PKT_public_key *pk)
717 {
718   int i;
719
720   if (!attrib_fp)
721     return;
722
723   for (i = 0; i < uid->numattribs; i++)
724     {
725       if (is_status_enabled ())
726         {
727           byte array[MAX_FINGERPRINT_LEN], *p;
728           char buf[(MAX_FINGERPRINT_LEN * 2) + 90];
729           size_t j, n;
730
731           if (!pk)
732             BUG ();
733           fingerprint_from_pk (pk, array, &n);
734
735           p = array;
736           for (j = 0; j < n; j++, p++)
737             sprintf (buf + 2 * j, "%02X", *p);
738
739           sprintf (buf + strlen (buf), " %lu %u %u %u %lu %lu %u",
740                    (ulong) uid->attribs[i].len, uid->attribs[i].type, i + 1,
741                    uid->numattribs, (ulong) uid->created,
742                    (ulong) uid->expiredate,
743                    ((uid->is_primary ? 0x01 : 0) | (uid->
744                                                     is_revoked ? 0x02 : 0) |
745                     (uid->is_expired ? 0x04 : 0)));
746           write_status_text (STATUS_ATTRIBUTE, buf);
747         }
748
749       es_fwrite (uid->attribs[i].data, uid->attribs[i].len, 1, attrib_fp);
750       es_fflush (attrib_fp);
751     }
752 }
753
754
755 static void
756 list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
757 {
758   int rc = 0;
759   KBNODE kbctx;
760   KBNODE node;
761   PKT_public_key *pk;
762   struct sig_stats *stats = opaque;
763   int skip_sigs = 0;
764   int s2k_char;
765
766   /* Get the keyid from the keyblock.  */
767   node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
768   if (!node)
769     {
770       log_error ("Oops; key lost!\n");
771       dump_kbnode (keyblock);
772       return;
773     }
774
775   pk = node->pkt->pkt.public_key;
776   
777   /* Fixme: Get s2k mode from the agent.  */
778   s2k_char = (/*(sk->protect.s2k.mode == 1001)? '#' :
779                 (sk->protect.s2k.mode == 1002)? '>' : */' ');
780   
781   check_trustdb_stale ();
782
783   es_fprintf (es_stdout, "%s%c  %4u%c/%s %s", 
784           secret? "sec":"pub",
785           s2k_char,
786           nbits_from_pk (pk), pubkey_letter (pk->pubkey_algo),
787           keystr_from_pk (pk), datestr_from_pk (pk));
788
789   if (pk->is_revoked)
790     {
791       es_fprintf (es_stdout, " [");
792       es_fprintf (es_stdout, _("revoked: %s"), revokestr_from_pk (pk));
793       es_fprintf (es_stdout, "]");
794     }
795   else if (pk->has_expired)
796     {
797       es_fprintf (es_stdout, " [");
798       es_fprintf (es_stdout, _("expired: %s"), expirestr_from_pk (pk));
799       es_fprintf (es_stdout, "]");
800     }
801   else if (pk->expiredate)
802     {
803       es_fprintf (es_stdout, " [");
804       es_fprintf (es_stdout, _("expires: %s"), expirestr_from_pk (pk));
805       es_fprintf (es_stdout, "]");
806     }
807
808 #if 0
809   /* I need to think about this some more.  It's easy enough to
810      include, but it looks sort of confusing in the listing... */
811   if (opt.list_options & LIST_SHOW_VALIDITY)
812     {
813       int validity = get_validity (pk, NULL);
814       es_fprintf (es_stdout, " [%s]", trust_value_to_string (validity));
815     }
816 #endif
817
818   es_fprintf (es_stdout, "\n");
819
820   if (fpr)
821     print_fingerprint (pk, 0);
822
823   /* FIXME: Change this function to take a PK and ask the agent:  */
824   /* if (secret) print_card_serialno (sk); */
825
826   if (opt.with_key_data)
827     print_key_data (pk);
828
829   for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
830     {
831       if (node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode)
832         {
833           PKT_user_id *uid = node->pkt->pkt.user_id;
834
835           if (pk && (uid->is_expired || uid->is_revoked)
836               && !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
837             {
838               skip_sigs = 1;
839               continue;
840             }
841           else
842             skip_sigs = 0;
843
844           if (attrib_fp && uid->attrib_data != NULL)
845             dump_attribs (uid, pk);
846
847           if ((uid->is_revoked || uid->is_expired)
848               || ((opt.list_options & LIST_SHOW_UID_VALIDITY) && pk))
849             {
850               const char *validity;
851               int indent;
852
853               validity = uid_trust_string_fixed (pk, uid);
854               indent =
855                 (keystrlen () + 9) -
856                 atoi (uid_trust_string_fixed (NULL, NULL));
857
858               if (indent < 0 || indent > 40)
859                 indent = 0;
860
861               es_fprintf (es_stdout, "uid%*s%s ", indent, "", validity);
862             }
863           else
864             es_fprintf (es_stdout, "uid%*s", (int) keystrlen () + 10, "");
865
866           print_utf8_buffer (es_stdout, uid->name, uid->len);
867           es_putc ('\n', es_stdout);
868
869           if ((opt.list_options & LIST_SHOW_PHOTOS) && uid->attribs != NULL)
870             show_photos (uid->attribs, uid->numattribs, pk, uid);
871         }
872       else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
873         {
874           PKT_public_key *pk2 = node->pkt->pkt.public_key;
875
876           if ((pk2->is_revoked || pk2->has_expired)
877               && !(opt.list_options & LIST_SHOW_UNUSABLE_SUBKEYS))
878             {
879               skip_sigs = 1;
880               continue;
881             }
882           else
883             skip_sigs = 0;
884
885           /* Fixme: Get s2k mode from the agent.  */
886           s2k_char = (/*(sk->protect.s2k.mode == 1001)? '#' :
887                         (sk->protect.s2k.mode == 1002)? '>' : */' ');
888
889           es_fprintf (es_stdout, "%s%c  %4u%c/%s %s",
890                   secret? "ssb":"sub",
891                   s2k_char,
892                   nbits_from_pk (pk2), pubkey_letter (pk2->pubkey_algo),
893                   keystr_from_pk (pk2), datestr_from_pk (pk2));
894           if (pk2->is_revoked)
895             {
896               es_fprintf (es_stdout, " [");
897               es_fprintf (es_stdout, _("revoked: %s"), revokestr_from_pk (pk2));
898               es_fprintf (es_stdout, "]");
899             }
900           else if (pk2->has_expired)
901             {
902               es_fprintf (es_stdout, " [");
903               es_fprintf (es_stdout, _("expired: %s"), expirestr_from_pk (pk2));
904               es_fprintf (es_stdout, "]");
905             }
906           else if (pk2->expiredate)
907             {
908               es_fprintf (es_stdout, " [");
909               es_fprintf (es_stdout, _("expires: %s"), expirestr_from_pk (pk2));
910               es_fprintf (es_stdout, "]");
911             }
912           es_putc ('\n', es_stdout);
913           if (fpr > 1)
914             {
915               print_fingerprint (pk2, 0);
916               /* FIXME: (see above) */
917               /* if (secret) */
918               /*   print_card_serialno (sk2); */
919             }
920           if (opt.with_key_data)
921             print_key_data (pk2);
922         }
923       else if (opt.list_sigs
924                && node->pkt->pkttype == PKT_SIGNATURE && !skip_sigs)
925         {
926           PKT_signature *sig = node->pkt->pkt.signature;
927           int sigrc;
928           char *sigstr;
929
930           if (stats)
931             {
932               rc = check_key_signature (keyblock, node, NULL);
933               switch (gpg_err_code (rc))
934                 {
935                 case 0:
936                   sigrc = '!';
937                   break;
938                 case GPG_ERR_BAD_SIGNATURE:
939                   stats->inv_sigs++;
940                   sigrc = '-';
941                   break;
942                 case GPG_ERR_NO_PUBKEY:
943                 case GPG_ERR_UNUSABLE_PUBKEY:
944                   stats->no_key++;
945                   continue;
946                 default:
947                   stats->oth_err++;
948                   sigrc = '%';
949                   break;
950                 }
951
952               /* TODO: Make sure a cached sig record here still has
953                  the pk that issued it.  See also
954                  keyedit.c:print_and_check_one_sig */
955             }
956           else
957             {
958               rc = 0;
959               sigrc = ' ';
960             }
961
962           if (sig->sig_class == 0x20 || sig->sig_class == 0x28
963               || sig->sig_class == 0x30)
964             sigstr = "rev";
965           else if ((sig->sig_class & ~3) == 0x10)
966             sigstr = "sig";
967           else if (sig->sig_class == 0x18)
968             sigstr = "sig";
969           else if (sig->sig_class == 0x1F)
970             sigstr = "sig";
971           else
972             {
973               es_fprintf (es_stdout, "sig                             "
974                       "[unexpected signature class 0x%02x]\n",
975                       sig->sig_class);
976               continue;
977             }
978
979           es_fputs (sigstr, es_stdout);
980           es_fprintf (es_stdout, "%c%c %c%c%c%c%c%c %s %s",
981                   sigrc, (sig->sig_class - 0x10 > 0 &&
982                           sig->sig_class - 0x10 <
983                           4) ? '0' + sig->sig_class - 0x10 : ' ',
984                   sig->flags.exportable ? ' ' : 'L',
985                   sig->flags.revocable ? ' ' : 'R',
986                   sig->flags.policy_url ? 'P' : ' ',
987                   sig->flags.notation ? 'N' : ' ',
988                   sig->flags.expired ? 'X' : ' ',
989                   (sig->trust_depth > 9) ? 'T' : (sig->trust_depth >
990                                                   0) ? '0' +
991                   sig->trust_depth : ' ', keystr (sig->keyid),
992                   datestr_from_sig (sig));
993           if (opt.list_options & LIST_SHOW_SIG_EXPIRE)
994             es_fprintf (es_stdout, " %s", expirestr_from_sig (sig));
995           es_fprintf (es_stdout, "  ");
996           if (sigrc == '%')
997             es_fprintf (es_stdout, "[%s] ", g10_errstr (rc));
998           else if (sigrc == '?')
999             ;
1000           else if (!opt.fast_list_mode)
1001             {
1002               size_t n;
1003               char *p = get_user_id (sig->keyid, &n);
1004               print_utf8_buffer (es_stdout, p, n);
1005               xfree (p);
1006             }
1007           es_putc ('\n', es_stdout);
1008
1009           if (sig->flags.policy_url
1010               && (opt.list_options & LIST_SHOW_POLICY_URLS))
1011             show_policy_url (sig, 3, 0);
1012
1013           if (sig->flags.notation && (opt.list_options & LIST_SHOW_NOTATIONS))
1014             show_notation (sig, 3, 0,
1015                            ((opt.
1016                              list_options & LIST_SHOW_STD_NOTATIONS) ? 1 : 0)
1017                            +
1018                            ((opt.
1019                              list_options & LIST_SHOW_USER_NOTATIONS) ? 2 :
1020                             0));
1021
1022           if (sig->flags.pref_ks
1023               && (opt.list_options & LIST_SHOW_KEYSERVER_URLS))
1024             show_keyserver_url (sig, 3, 0);
1025
1026           /* fixme: check or list other sigs here */
1027         }
1028     }
1029   es_putc ('\n', es_stdout);
1030 }
1031
1032 void
1033 print_revokers (PKT_public_key * pk)
1034 {
1035   /* print the revoker record */
1036   if (!pk->revkey && pk->numrevkeys)
1037     BUG ();
1038   else
1039     {
1040       int i, j;
1041
1042       for (i = 0; i < pk->numrevkeys; i++)
1043         {
1044           byte *p;
1045
1046           es_fprintf (es_stdout, "rvk:::%d::::::", pk->revkey[i].algid);
1047           p = pk->revkey[i].fpr;
1048           for (j = 0; j < 20; j++, p++)
1049             es_fprintf (es_stdout, "%02X", *p);
1050           es_fprintf (es_stdout, ":%02x%s:\n", pk->revkey[i].class,
1051                   (pk->revkey[i].class & 0x40) ? "s" : "");
1052         }
1053     }
1054 }
1055
1056 static void
1057 list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
1058 {
1059   int rc = 0;
1060   KBNODE kbctx;
1061   KBNODE node;
1062   PKT_public_key *pk;
1063   u32 keyid[2];
1064   int trustletter = 0;
1065   int ulti_hack = 0;
1066   int i;
1067   char *p;
1068
1069   /* Get the keyid from the keyblock.  */
1070   node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
1071   if (!node)
1072     {
1073       log_error ("Oops; key lost!\n");
1074       dump_kbnode (keyblock);
1075       return;
1076     }
1077
1078   pk = node->pkt->pkt.public_key;
1079
1080   keyid_from_pk (pk, keyid);
1081   es_fputs (secret? "sec:":"pub:", es_stdout);
1082   if (!pk->is_valid)
1083     es_putc ('i', es_stdout);
1084   else if (pk->is_revoked)
1085     es_putc ('r', es_stdout);
1086   else if (pk->has_expired)
1087     es_putc ('e', es_stdout);
1088   else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
1089     ;
1090   else
1091     {
1092       trustletter = get_validity_info (pk, NULL);
1093       if (trustletter == 'u')
1094         ulti_hack = 1;
1095       es_putc (trustletter, es_stdout);
1096     }
1097
1098   es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s::",
1099           nbits_from_pk (pk),
1100           pk->pubkey_algo,
1101           (ulong) keyid[0], (ulong) keyid[1],
1102           colon_datestr_from_pk (pk), colon_strtime (pk->expiredate));
1103
1104   if (!opt.fast_list_mode && !opt.no_expensive_trust_checks)
1105     es_putc (get_ownertrust (pk), es_stdout);
1106   es_putc (':', es_stdout);
1107
1108   es_putc (':', es_stdout);
1109   es_putc (':', es_stdout);
1110   print_capabilities (pk, keyblock);
1111   if (secret)
1112     {
1113       es_putc (':', es_stdout);         /* End of field 13. */
1114       es_putc (':', es_stdout);         /* End of field 14. */
1115       if (/*FIXME sk->protect.s2k.mode*/1 == 1001)
1116         es_putc ('#', es_stdout);               /* Key is just a stub. */
1117       else if (/*FIXME sk->protect.s2k.mode*/1 == 1002)
1118         {
1119           /* Key is stored on an external token (card) or handled by
1120              the gpg-agent.  Print the serial number of that token
1121              here. */
1122           /* FIXME: for (i = 0; i < sk->protect.ivlen; i++) */
1123           /*   es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
1124         }
1125       es_putc (':', es_stdout);         /* End of field 15. */
1126     }
1127   es_putc ('\n', es_stdout);
1128
1129   print_revokers (pk);
1130   if (fpr)
1131     print_fingerprint (pk, 0);
1132   if (opt.with_key_data)
1133     {
1134       if (!hexkeygrip_from_pk (pk, &p))
1135         {
1136           es_fprintf (es_stdout, "grp:::::::::%s:\n", p);
1137           xfree (p);
1138         }
1139       print_key_data (pk);
1140     }
1141
1142   for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
1143     {
1144       if (node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode)
1145         {
1146           char *str;
1147           PKT_user_id *uid = node->pkt->pkt.user_id;
1148
1149           if (attrib_fp && node->pkt->pkt.user_id->attrib_data != NULL)
1150             dump_attribs (node->pkt->pkt.user_id, pk);
1151           /*
1152            * Fixme: We need a is_valid flag here too 
1153            */
1154           str = uid->attrib_data ? "uat" : "uid";
1155           if (uid->is_revoked)
1156             es_fprintf (es_stdout, "%s:r::::", str);
1157           else if (uid->is_expired)
1158             es_fprintf (es_stdout, "%s:e::::", str);
1159           else if (opt.no_expensive_trust_checks)
1160             es_fprintf (es_stdout, "%s:::::", str);
1161           else
1162             {
1163               int uid_validity;
1164
1165               if (pk && !ulti_hack)
1166                 uid_validity = get_validity_info (pk, uid);
1167               else
1168                 uid_validity = 'u';
1169               es_fprintf (es_stdout, "%s:%c::::", str, uid_validity);
1170             }
1171
1172           es_fprintf (es_stdout, "%s:", colon_strtime (uid->created));
1173           es_fprintf (es_stdout, "%s:", colon_strtime (uid->expiredate));
1174
1175           namehash_from_uid (uid);
1176
1177           for (i = 0; i < 20; i++)
1178             es_fprintf (es_stdout, "%02X", uid->namehash[i]);
1179
1180           es_fprintf (es_stdout, "::");
1181
1182           if (uid->attrib_data)
1183             es_fprintf (es_stdout, "%u %lu", uid->numattribs, uid->attrib_len);
1184           else
1185             es_write_sanitized (es_stdout, uid->name, uid->len, ":", NULL);
1186           es_putc (':', es_stdout);
1187           es_putc ('\n', es_stdout);
1188         }
1189       else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
1190         {
1191           u32 keyid2[2];
1192           PKT_public_key *pk2 = node->pkt->pkt.public_key;
1193
1194           keyid_from_pk (pk2, keyid2);
1195           es_fputs (secret? "ssb:":"sub:", es_stdout);
1196           if (!pk2->is_valid)
1197             es_putc ('i', es_stdout);
1198           else if (pk2->is_revoked)
1199             es_putc ('r', es_stdout);
1200           else if (pk2->has_expired)
1201             es_putc ('e', es_stdout);
1202           else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
1203             ;
1204           else
1205             {
1206               /* TRUSTLETTER should always be defined here. */
1207               if (trustletter)
1208                 es_fprintf (es_stdout, "%c", trustletter);
1209             }
1210           es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s:::::",
1211                   nbits_from_pk (pk2),
1212                   pk2->pubkey_algo,
1213                   (ulong) keyid2[0], (ulong) keyid2[1],
1214                   colon_datestr_from_pk (pk2), colon_strtime (pk2->expiredate)
1215                   /* fixme: add LID and ownertrust here */
1216             );
1217           print_capabilities (pk2, NULL);
1218           if (secret)
1219             {
1220               es_putc (':', es_stdout); /* End of field 13. */
1221               es_putc (':', es_stdout); /* End of field 14. */
1222               if (/*FIXME:sk2->protect.s2k.mode*/1 == 1001)
1223                 es_putc ('#', es_stdout);       /* Key is just a stub. */
1224               else if (/*FIXME: sk2->protect.s2k.mode*/1 == 1002)
1225                 {
1226                   /* Key is stored on an external token (card) or
1227                      handled by the gpg-agent.  Print the serial
1228                      number of that token here. */
1229                   /* FIXME: for (i = 0; i < sk2->protect.ivlen; i++)
1230                      es_fprintf (es_stdout, "%02X", sk2->protect.iv[i]); */
1231                 }
1232               es_putc (':', es_stdout); /* End of field 15. */
1233             }
1234           es_putc ('\n', es_stdout);
1235           if (fpr > 1)
1236             print_fingerprint (pk2, 0);
1237           if (opt.with_key_data)
1238             {
1239               if (!hexkeygrip_from_pk (pk2, &p))
1240                 {
1241                   es_fprintf (es_stdout, "grp:::::::::%s:\n", p);
1242                   xfree (p);
1243                 }
1244               print_key_data (pk2);
1245             }
1246         }
1247       else if (opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE)
1248         {
1249           PKT_signature *sig = node->pkt->pkt.signature;
1250           int sigrc, fprokay = 0;
1251           char *sigstr;
1252           size_t fplen;
1253           byte fparray[MAX_FINGERPRINT_LEN];
1254
1255           if (sig->sig_class == 0x20 || sig->sig_class == 0x28
1256               || sig->sig_class == 0x30)
1257             sigstr = "rev";
1258           else if ((sig->sig_class & ~3) == 0x10)
1259             sigstr = "sig";
1260           else if (sig->sig_class == 0x18)
1261             sigstr = "sig";
1262           else if (sig->sig_class == 0x1F)
1263             sigstr = "sig";
1264           else
1265             {
1266               es_fprintf (es_stdout, "sig::::::::::%02x%c:\n",
1267                       sig->sig_class, sig->flags.exportable ? 'x' : 'l');
1268               continue;
1269             }
1270
1271           if (opt.check_sigs)
1272             {
1273               PKT_public_key *signer_pk = NULL;
1274
1275               fflush (stdout);
1276               if (opt.no_sig_cache)
1277                 signer_pk = xmalloc_clear (sizeof (PKT_public_key));
1278
1279               rc = check_key_signature2 (keyblock, node, NULL, signer_pk,
1280                                          NULL, NULL, NULL);
1281               switch (gpg_err_code (rc))
1282                 {
1283                 case 0:
1284                   sigrc = '!';
1285                   break;
1286                 case GPG_ERR_BAD_SIGNATURE:
1287                   sigrc = '-';
1288                   break;
1289                 case GPG_ERR_NO_PUBKEY:
1290                 case GPG_ERR_UNUSABLE_PUBKEY:
1291                   sigrc = '?';
1292                   break;
1293                 default:
1294                   sigrc = '%';
1295                   break;
1296                 }
1297
1298               if (opt.no_sig_cache)
1299                 {
1300                   if (!rc)
1301                     {
1302                       fingerprint_from_pk (signer_pk, fparray, &fplen);
1303                       fprokay = 1;
1304                     }
1305                   free_public_key (signer_pk);
1306                 }
1307             }
1308           else
1309             {
1310               rc = 0;
1311               sigrc = ' ';
1312             }
1313           es_fputs (sigstr, es_stdout);
1314           es_putc (':', es_stdout);
1315           if (sigrc != ' ')
1316             es_putc (sigrc, es_stdout);
1317           es_fprintf (es_stdout, "::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo,
1318                   (ulong) sig->keyid[0], (ulong) sig->keyid[1],
1319                   colon_datestr_from_sig (sig),
1320                   colon_expirestr_from_sig (sig));
1321
1322           if (sig->trust_depth || sig->trust_value)
1323             es_fprintf (es_stdout, "%d %d", sig->trust_depth, sig->trust_value);
1324           es_fprintf (es_stdout, ":");
1325
1326           if (sig->trust_regexp)
1327             es_write_sanitized (es_stdout, sig->trust_regexp,
1328                                 strlen (sig->trust_regexp), ":", NULL);
1329           es_fprintf (es_stdout, ":");
1330
1331           if (sigrc == '%')
1332             es_fprintf (es_stdout, "[%s] ", g10_errstr (rc));
1333           else if (sigrc == '?')
1334             ;
1335           else if (!opt.fast_list_mode)
1336             {
1337               size_t n;
1338               p = get_user_id (sig->keyid, &n);
1339               es_write_sanitized (es_stdout, p, n, ":", NULL);
1340               xfree (p);
1341             }
1342           es_fprintf (es_stdout, ":%02x%c:", sig->sig_class,
1343                   sig->flags.exportable ? 'x' : 'l');
1344
1345           if (opt.no_sig_cache && opt.check_sigs && fprokay)
1346             {
1347               es_putc (':', es_stdout);
1348
1349               for (i = 0; i < fplen; i++)
1350                 es_fprintf (es_stdout, "%02X", fparray[i]);
1351
1352               es_putc (':', es_stdout);
1353             }
1354
1355           es_fprintf (es_stdout, "\n");
1356
1357           if (opt.show_subpackets)
1358             print_subpackets_colon (sig);
1359
1360           /* fixme: check or list other sigs here */
1361         }
1362     }
1363 }
1364
1365 /*
1366  * Reorder the keyblock so that the primary user ID (and not attribute
1367  * packet) comes first.  Fixme: Replace this by a generic sort
1368  * function.  */
1369 static void
1370 do_reorder_keyblock (KBNODE keyblock, int attr)
1371 {
1372   KBNODE primary = NULL, primary0 = NULL, primary2 = NULL;
1373   KBNODE last, node;
1374
1375   for (node = keyblock; node; primary0 = node, node = node->next)
1376     {
1377       if (node->pkt->pkttype == PKT_USER_ID &&
1378           ((attr && node->pkt->pkt.user_id->attrib_data) ||
1379            (!attr && !node->pkt->pkt.user_id->attrib_data)) &&
1380           node->pkt->pkt.user_id->is_primary)
1381         {
1382           primary = primary2 = node;
1383           for (node = node->next; node; primary2 = node, node = node->next)
1384             {
1385               if (node->pkt->pkttype == PKT_USER_ID
1386                   || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1387                   || node->pkt->pkttype == PKT_SECRET_SUBKEY)
1388                 {
1389                   break;
1390                 }
1391             }
1392           break;
1393         }
1394     }
1395   if (!primary)
1396     return; /* No primary key flag found (should not happen).  */
1397
1398   for (last = NULL, node = keyblock; node; last = node, node = node->next)
1399     {
1400       if (node->pkt->pkttype == PKT_USER_ID)
1401         break;
1402     }
1403   assert (node);
1404   assert (last);         /* The user ID is never the first packet.  */
1405   assert (primary0);     /* Ditto (this is the node before primary).  */
1406   if (node == primary)
1407     return; /* Already the first one.  */
1408
1409   last->next = primary;
1410   primary0->next = primary2->next;
1411   primary2->next = node;
1412 }
1413
1414 void
1415 reorder_keyblock (KBNODE keyblock)
1416 {
1417   do_reorder_keyblock (keyblock, 1);
1418   do_reorder_keyblock (keyblock, 0);
1419 }
1420
1421 void
1422 list_keyblock (KBNODE keyblock, int secret, int fpr, void *opaque)
1423 {
1424   reorder_keyblock (keyblock);
1425   if (opt.with_colons)
1426     list_keyblock_colon (keyblock, secret, fpr);
1427   else
1428     list_keyblock_print (keyblock, secret, fpr, opaque);
1429 }
1430
1431 /*
1432  * Function to print the finperprint.
1433  * mode 0: as used in key listings, opt.with_colons is honored
1434  *      1: print using log_info ()
1435  *      2: direct use of tty
1436  *      3: direct use of tty but only primary key.
1437  *
1438  * Modes 1 and 2 will try and print both subkey and primary key
1439  * fingerprints.  A MODE with bit 7 set is used internally.
1440  */
1441 void
1442 print_fingerprint (PKT_public_key *pk, int mode)
1443 {
1444   byte array[MAX_FINGERPRINT_LEN], *p;
1445   size_t i, n;
1446   estream_t fp;
1447   const char *text;
1448   int primary = 0;
1449
1450   if (pk->main_keyid[0] == pk->keyid[0]
1451       && pk->main_keyid[1] == pk->keyid[1])
1452     primary = 1;
1453
1454   /* Just to be safe */
1455   if ((mode & 0x80) && !primary)
1456     {
1457       log_error ("primary key is not really primary!\n");
1458       return;
1459     }
1460
1461   mode &= ~0x80;
1462
1463   if (!primary && (mode == 1 || mode == 2))
1464     {
1465       PKT_public_key *primary_pk = xmalloc_clear (sizeof (*primary_pk));
1466       get_pubkey (primary_pk, pk->main_keyid);
1467       print_fingerprint (primary_pk, mode | 0x80);
1468       free_public_key (primary_pk);
1469     }
1470
1471   if (mode == 1)
1472     {
1473       fp = log_get_stream ();
1474       if (primary)
1475         text = _("Primary key fingerprint:");
1476       else
1477         text = _("     Subkey fingerprint:");
1478     }
1479   else if (mode == 2)
1480     {
1481       fp = NULL; /* Use tty.  */
1482       if (primary)
1483         /* TRANSLATORS: this should fit into 24 bytes to that the
1484          * fingerprint data is properly aligned with the user ID */
1485         text = _(" Primary key fingerprint:");
1486       else
1487         text = _("      Subkey fingerprint:");
1488     }
1489   else if (mode == 3)
1490     {
1491       fp = NULL; /* Use tty.  */
1492       text = _("      Key fingerprint =");
1493     }
1494   else
1495     {
1496       fp = es_stdout;
1497       text = _("      Key fingerprint =");
1498     }
1499
1500   fingerprint_from_pk (pk, array, &n);
1501   p = array;
1502   if (opt.with_colons && !mode)
1503     {
1504       es_fprintf (fp, "fpr:::::::::");
1505       for (i = 0; i < n; i++, p++)
1506         es_fprintf (fp, "%02X", *p);
1507       es_putc (':', fp);
1508     }
1509   else
1510     {
1511       tty_fprintf (fp, "%s", text);
1512       if (n == 20)
1513         {
1514           for (i = 0; i < n; i++, i++, p += 2)
1515             tty_fprintf (fp, "%s %02X%02X", i==10? " ":"", *p, p[1]);
1516         }
1517       else
1518         {
1519           for (i = 0; i < n; i++, p++)
1520             tty_fprintf (fp, "%s %02X", (i && !(i % 8))? " ":"", *p);
1521         }
1522     }
1523   tty_fprintf (fp, "\n");
1524 }
1525
1526 /* Print the serial number of an OpenPGP card if available.  */
1527 static void
1528 print_card_serialno (PKT_public_key *pk)
1529 {
1530   log_debug ("Fixme: Needs to be adjusted to gpg-agent\n");
1531   /* int i; */
1532
1533   /* if (!sk) */
1534   /*   return; */
1535   /* if (!sk->is_protected || sk->protect.s2k.mode != 1002) */
1536   /*   return; /\* Not a card. *\/ */
1537   /* if (opt.with_colons) */
1538   /*   return; /\* Handled elsewhere. *\/ */
1539
1540   /* es_fputs (_("      Card serial no. ="), es_stdout); */
1541   /* es_putc (' ', es_stdout); */
1542   /* if (sk->protect.ivlen == 16 */
1543   /*     && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) */
1544   /*   {                 */
1545   /*     /\* This is an OpenPGP card. Just print the relevant part.  *\/ */
1546   /*     for (i = 8; i < 14; i++) */
1547   /*       { */
1548   /*         if (i == 10) */
1549   /*           es_putc (' ', es_stdout); */
1550   /*         es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
1551   /*       } */
1552   /*   } */
1553   /* else */
1554   /*   { */
1555   /*     /\* Something is wrong: Print all.  *\/ */
1556   /*     for (i = 0; i < sk->protect.ivlen; i++) */
1557   /*       es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
1558   /*   } */
1559   /* es_putc ('\n', es_stdout); */
1560 }
1561
1562
1563
1564 void
1565 set_attrib_fd (int fd)
1566 {
1567   static int last_fd = -1;
1568
1569   if (fd != -1 && last_fd == fd)
1570     return;
1571
1572   /* Fixme: Do we need to check for the log stream here?  */
1573   if (attrib_fp && attrib_fp != log_get_stream ())
1574     es_fclose (attrib_fp);
1575   attrib_fp = NULL;
1576   if (fd == -1)
1577     return;
1578
1579 #ifdef HAVE_DOSISH_SYSTEM
1580   setmode (fd, O_BINARY);
1581 #endif
1582   if (fd == 1)
1583     attrib_fp = es_stdout;
1584   else if (fd == 2)
1585     attrib_fp = es_stderr;
1586   else
1587     attrib_fp = es_fdopen (fd, "wb");
1588   if (!attrib_fp)
1589     {
1590       log_fatal ("can't open fd %d for attribute output: %s\n",
1591                  fd, strerror (errno));
1592     }
1593
1594   last_fd = fd;
1595 }