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