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