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