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