Moved 1.9 branch to trunk
[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_SIGNATURE:
921                    stats->inv_sigs++; sigrc = '-'; break;
922                  case GPG_ERR_NO_PUBKEY: 
923                  case GPG_ERR_UNUSABLE_PUBKEY: stats->no_key++; continue;
924                  default:               stats->oth_err++; sigrc = '%'; break;
925                 }
926
927                 /* TODO: Make sure a cached sig record here still has
928                    the pk that issued it.  See also
929                    keyedit.c:print_and_check_one_sig */
930             }
931             else {
932                 rc = 0;
933                 sigrc = ' ';
934             }
935
936             if( sig->sig_class == 0x20 || sig->sig_class == 0x28
937                                        || sig->sig_class == 0x30 )
938                sigstr = "rev";
939             else if( (sig->sig_class&~3) == 0x10 )
940                sigstr = "sig";
941             else if( sig->sig_class == 0x18 )
942                sigstr = "sig";
943             else if( sig->sig_class == 0x1F )
944                sigstr = "sig";
945             else {
946                 printf("sig                             "
947                        "[unexpected signature class 0x%02x]\n",sig->sig_class );
948                 continue;
949             }
950
951             fputs( sigstr, stdout );
952             printf("%c%c %c%c%c%c%c%c %s %s",
953                    sigrc,(sig->sig_class-0x10>0 &&
954                           sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ',
955                    sig->flags.exportable?' ':'L',
956                    sig->flags.revocable?' ':'R',
957                    sig->flags.policy_url?'P':' ',
958                    sig->flags.notation?'N':' ',
959                    sig->flags.expired?'X':' ',
960                    (sig->trust_depth>9)?'T':
961                    (sig->trust_depth>0)?'0'+sig->trust_depth:' ',
962                    keystr(sig->keyid),datestr_from_sig(sig));
963             if(opt.list_options&LIST_SHOW_SIG_EXPIRE)
964               printf(" %s", expirestr_from_sig(sig));
965             printf("  ");
966             if( sigrc == '%' )
967                 printf("[%s] ", g10_errstr(rc) );
968             else if( sigrc == '?' )
969                 ;
970             else if ( !opt.fast_list_mode ) {
971                 size_t n;
972                 char *p = get_user_id( sig->keyid, &n );
973                 print_utf8_string( stdout, p, n );
974                 xfree(p);
975             }
976             putchar('\n');
977
978             if(sig->flags.policy_url
979                && (opt.list_options&LIST_SHOW_POLICY_URLS))
980               show_policy_url(sig,3,0);
981
982             if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATIONS))
983               show_notation(sig,3,0,
984                             ((opt.list_options&LIST_SHOW_STD_NOTATIONS)?1:0)+
985                             ((opt.list_options&LIST_SHOW_USER_NOTATIONS)?2:0));
986
987             if(sig->flags.pref_ks
988                && (opt.list_options&LIST_SHOW_KEYSERVER_URLS))
989               show_keyserver_url(sig,3,0);
990
991             /* fixme: check or list other sigs here */
992         }
993     }
994     putchar('\n');
995 }
996
997 void
998 print_revokers(PKT_public_key *pk)
999 {
1000   /* print the revoker record */
1001   if( !pk->revkey && pk->numrevkeys )
1002     BUG();
1003   else
1004     {
1005       int i,j;
1006
1007       for (i=0; i < pk->numrevkeys; i++)
1008         {
1009           byte *p;
1010
1011           printf ("rvk:::%d::::::", pk->revkey[i].algid);
1012           p = pk->revkey[i].fpr;
1013           for (j=0; j < 20; j++, p++ )
1014             printf ("%02X", *p);
1015           printf (":%02x%s:\n", pk->revkey[i].class,
1016                   (pk->revkey[i].class&0x40)?"s":"");
1017         }
1018     }
1019 }
1020
1021 static void
1022 list_keyblock_colon( KBNODE keyblock, int secret, int fpr )
1023 {
1024     int rc = 0;
1025     KBNODE kbctx;
1026     KBNODE node;
1027     PKT_public_key *pk;
1028     PKT_secret_key *sk;
1029     u32 keyid[2];
1030     int any=0;
1031     int trustletter = 0;
1032     int ulti_hack = 0;
1033     int i;
1034
1035     /* get the keyid from the keyblock */
1036     node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
1037     if( !node ) {
1038         log_error("Oops; key lost!\n");
1039         dump_kbnode( keyblock );
1040         return;
1041     }
1042
1043     if( secret ) {
1044         pk = NULL;
1045         sk = node->pkt->pkt.secret_key;
1046         keyid_from_sk( sk, keyid );
1047         printf("sec::%u:%d:%08lX%08lX:%s:%s:::",
1048                     nbits_from_sk( sk ),
1049                     sk->pubkey_algo,
1050                     (ulong)keyid[0],(ulong)keyid[1],
1051                     colon_datestr_from_sk( sk ),
1052                     colon_strtime (sk->expiredate)
1053                     /* fixme: add LID here */ );
1054     }
1055     else {
1056         pk = node->pkt->pkt.public_key;
1057         sk = NULL;
1058         keyid_from_pk( pk, keyid );
1059         fputs( "pub:", stdout );
1060         if ( !pk->is_valid )
1061             putchar ('i');
1062         else if ( pk->is_revoked )
1063             putchar ('r');
1064         else if ( pk->has_expired )
1065             putchar ('e');
1066         else if ( opt.fast_list_mode || opt.no_expensive_trust_checks ) 
1067             ;
1068         else {
1069             trustletter = get_validity_info ( pk, NULL );
1070             if( trustletter == 'u' )
1071                 ulti_hack = 1;
1072             putchar(trustletter);
1073         }
1074         printf(":%u:%d:%08lX%08lX:%s:%s::",
1075                     nbits_from_pk( pk ),
1076                     pk->pubkey_algo,
1077                     (ulong)keyid[0],(ulong)keyid[1],
1078                     colon_datestr_from_pk( pk ),
1079                     colon_strtime (pk->expiredate) );
1080         if( !opt.fast_list_mode && !opt.no_expensive_trust_checks  )
1081             putchar( get_ownertrust_info(pk) );
1082             putchar(':');
1083     }
1084
1085     if (opt.fixed_list_mode) {
1086         /* do not merge the first uid with the primary key */
1087         putchar(':');
1088         putchar(':');
1089         print_capabilities (pk, sk, keyblock);
1090         if (secret) {
1091           putchar(':'); /* End of field 13. */
1092           putchar(':'); /* End of field 14. */
1093           if (sk->protect.s2k.mode == 1001)
1094             putchar('#'); /* Key is just a stub. */
1095           else if (sk->protect.s2k.mode == 1002) {
1096             /* Key is stored on an external token (card) or handled by
1097                the gpg-agent.  Print the serial number of that token
1098                here. */
1099             for (i=0; i < sk->protect.ivlen; i++)
1100               printf ("%02X", sk->protect.iv[i]);
1101           }
1102           putchar(':'); /* End of field 15. */
1103         }
1104         putchar('\n');
1105         if(pk)
1106           print_revokers(pk);
1107         if( fpr )
1108             print_fingerprint( pk, sk, 0 );
1109         if( opt.with_key_data )
1110             print_key_data( pk );
1111         any = 1;
1112     }
1113
1114     for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
1115         if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) {
1116             PKT_user_id *uid=node->pkt->pkt.user_id;
1117             if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL)
1118               dump_attribs(node->pkt->pkt.user_id,pk,sk);
1119             /*
1120              * Fixme: We need a is_valid flag here too 
1121              */
1122             if( any ) {
1123                 char *str=uid->attrib_data?"uat":"uid";
1124                 /* If we're listing a secret key, leave out the
1125                    validity values for now.  This is handled better in
1126                    1.9. */
1127                 if ( sk )
1128                     printf("%s:::::",str);
1129                 else if ( uid->is_revoked )
1130                     printf("%s:r::::",str);
1131                 else if ( uid->is_expired )
1132                     printf("%s:e::::",str);
1133                 else if ( opt.no_expensive_trust_checks )
1134                     printf("%s:::::",str);
1135                 else {
1136                     int uid_validity;
1137
1138                     if( pk && !ulti_hack )
1139                       uid_validity=get_validity_info (pk, uid);
1140                     else
1141                         uid_validity = 'u';
1142                     printf("%s:%c::::",str,uid_validity);
1143                 }
1144
1145                 printf("%s:",colon_strtime(uid->created));
1146                 printf("%s:",colon_strtime(uid->expiredate));
1147
1148                 namehash_from_uid(uid);
1149
1150                 for(i=0; i < 20; i++ )
1151                   printf("%02X",uid->namehash[i]);
1152
1153                 printf("::");
1154             }
1155             if(uid->attrib_data)
1156               printf("%u %lu",uid->numattribs,uid->attrib_len);
1157             else
1158               print_string(stdout,uid->name,uid->len, ':' );
1159             putchar(':');
1160             if (any)
1161                 putchar('\n');
1162             else {
1163                 putchar(':');
1164                 print_capabilities (pk, sk, keyblock);
1165                 putchar('\n');
1166                 if( fpr )
1167                     print_fingerprint( pk, sk, 0 );
1168                 if( opt.with_key_data )
1169                     print_key_data( pk );
1170                 any = 1;
1171             }
1172         }
1173         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1174             u32 keyid2[2];
1175             PKT_public_key *pk2 = node->pkt->pkt.public_key;
1176
1177             if( !any ) {
1178                 putchar(':');
1179                 putchar(':');
1180                 print_capabilities (pk, sk, keyblock);
1181                 putchar('\n');
1182                 if( fpr )
1183                     print_fingerprint( pk, sk, 0 ); /* of the main key */
1184                 any = 1;
1185             }
1186
1187             keyid_from_pk( pk2, keyid2 );
1188             fputs ("sub:", stdout );
1189             if ( !pk2->is_valid )
1190                 putchar ('i');
1191             else if ( pk2->is_revoked )
1192                 putchar ('r');
1193             else if ( pk2->has_expired )
1194                 putchar ('e');
1195             else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1196                 ;
1197             else {
1198                 /* trustletter should always be defined here */
1199                 if(trustletter)
1200                   printf("%c", trustletter );
1201             }
1202             printf(":%u:%d:%08lX%08lX:%s:%s:::::",
1203                         nbits_from_pk( pk2 ),
1204                         pk2->pubkey_algo,
1205                         (ulong)keyid2[0],(ulong)keyid2[1],
1206                         colon_datestr_from_pk( pk2 ),
1207                         colon_strtime (pk2->expiredate)
1208                         /* fixme: add LID and ownertrust here */
1209                                                 );
1210             print_capabilities (pk2, NULL, NULL);
1211             putchar('\n');
1212             if( fpr > 1 )
1213                 print_fingerprint( pk2, NULL, 0 );
1214             if( opt.with_key_data )
1215                 print_key_data( pk2 );
1216         }
1217         else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1218             u32 keyid2[2];
1219             PKT_secret_key *sk2 = node->pkt->pkt.secret_key;
1220
1221             if( !any ) {
1222                 putchar(':');
1223                 putchar(':');
1224                 print_capabilities (pk, sk, keyblock);
1225                 putchar('\n');
1226                 if( fpr )
1227                     print_fingerprint( pk, sk, 0 ); /* of the main key */
1228                 any = 1;
1229             }
1230
1231             keyid_from_sk( sk2, keyid2 );
1232             printf("ssb::%u:%d:%08lX%08lX:%s:%s:::::",
1233                         nbits_from_sk( sk2 ),
1234                         sk2->pubkey_algo,
1235                         (ulong)keyid2[0],(ulong)keyid2[1],
1236                         colon_datestr_from_sk( sk2 ),
1237                         colon_strtime (sk2->expiredate)
1238                    /* fixme: add LID */ );
1239             print_capabilities (NULL, sk2, NULL);
1240             if (opt.fixed_list_mode) {
1241               /* We print the serial number only in fixed list mode
1242                  for the primary key so, so avoid questions we print
1243                  it for subkeys also only in this mode.  There is no
1244                  technical reason, though. */
1245               putchar(':'); /* End of field 13. */
1246               putchar(':'); /* End of field 14. */
1247               if (sk2->protect.s2k.mode == 1001)
1248                 putchar('#'); /* Key is just a stub. */
1249               else if (sk2->protect.s2k.mode == 1002) {
1250                 /* Key is stored on an external token (card) or handled by
1251                    the gpg-agent.  Print the serial number of that token
1252                    here. */
1253                 for (i=0; i < sk2->protect.ivlen; i++)
1254                   printf ("%02X", sk2->protect.iv[i]);
1255               }
1256               putchar(':'); /* End of field 15. */
1257             }
1258             putchar ('\n');
1259             if( fpr > 1 )
1260               print_fingerprint( NULL, sk2, 0 );
1261         }
1262         else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) {
1263             PKT_signature *sig = node->pkt->pkt.signature;
1264             int sigrc,fprokay=0;
1265             char *sigstr;
1266             size_t fplen;
1267             byte fparray[MAX_FINGERPRINT_LEN];
1268
1269             if( !any ) { /* no user id, (maybe a revocation follows)*/
1270                 if( sig->sig_class == 0x20 )
1271                     fputs("[revoked]:", stdout);
1272                 else if( sig->sig_class == 0x18 )
1273                     fputs("[key binding]:", stdout);
1274                 else if( sig->sig_class == 0x28 )
1275                     fputs("[subkey revoked]:", stdout);
1276                 else
1277                     putchar (':');
1278                 putchar(':');
1279                 print_capabilities (pk, sk, keyblock);
1280                 putchar('\n');
1281                 if( fpr )
1282                     print_fingerprint( pk, sk, 0 );
1283                 any=1;
1284             }
1285
1286             if( sig->sig_class == 0x20 || sig->sig_class == 0x28
1287                                        || sig->sig_class == 0x30 )
1288                sigstr = "rev";
1289             else if( (sig->sig_class&~3) == 0x10 )
1290                sigstr = "sig";
1291             else if( sig->sig_class == 0x18 )
1292                sigstr = "sig";
1293             else if( sig->sig_class == 0x1F )
1294                sigstr = "sig";
1295             else {
1296                 printf ("sig::::::::::%02x%c:\n",
1297                         sig->sig_class, sig->flags.exportable?'x':'l');
1298                 continue;
1299             }
1300             if( opt.check_sigs ) {
1301                 PKT_public_key *signer_pk=NULL;
1302
1303                 fflush(stdout);
1304                 if(opt.no_sig_cache)
1305                   signer_pk=xmalloc_clear(sizeof(PKT_public_key));
1306
1307                 rc = check_key_signature2( keyblock, node, NULL, signer_pk,
1308                                            NULL, NULL, NULL );
1309                 switch ( gpg_err_code (rc) ) {
1310                   case 0:                       sigrc = '!'; break;
1311                   case GPG_ERR_BAD_SIGNATURE:   sigrc = '-'; break;
1312                   case GPG_ERR_NO_PUBKEY: 
1313                   case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break;
1314                   default:                      sigrc = '%'; break;
1315                 }
1316
1317                 if(opt.no_sig_cache)
1318                   {
1319                     if(rc==0)
1320                       {
1321                         fingerprint_from_pk (signer_pk, fparray, &fplen);
1322                         fprokay=1;
1323                       }
1324                     free_public_key(signer_pk);
1325                   }
1326             }
1327             else {
1328                 rc = 0;
1329                 sigrc = ' ';
1330             }
1331             fputs( sigstr, stdout );
1332             putchar(':');
1333             if( sigrc != ' ' )
1334                 putchar(sigrc);
1335             printf("::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo,
1336                    (ulong)sig->keyid[0], (ulong)sig->keyid[1],
1337                    colon_datestr_from_sig(sig),
1338                    colon_expirestr_from_sig(sig));
1339
1340             if(sig->trust_depth || sig->trust_value)
1341               printf("%d %d",sig->trust_depth,sig->trust_value);
1342             printf(":");
1343
1344             if(sig->trust_regexp)
1345               print_string(stdout,sig->trust_regexp,
1346                            strlen(sig->trust_regexp),':');
1347             printf(":");
1348
1349             if( sigrc == '%' )
1350                 printf("[%s] ", g10_errstr(rc) );
1351             else if( sigrc == '?' )
1352                 ;
1353             else if ( !opt.fast_list_mode ) {
1354                 size_t n;
1355                 char *p = get_user_id( sig->keyid, &n );
1356                 print_string( stdout, p, n, ':' );
1357                 xfree(p);
1358             }
1359             printf(":%02x%c:", sig->sig_class,sig->flags.exportable?'x':'l');
1360
1361             if(opt.no_sig_cache && opt.check_sigs && fprokay)
1362               {
1363                 printf(":");
1364
1365                 for (i=0; i < fplen ; i++ )
1366                   printf ("%02X", fparray[i] );
1367
1368                 printf(":");
1369               }
1370
1371             printf("\n");
1372
1373             if(opt.show_subpackets)
1374               print_subpackets_colon(sig);
1375
1376             /* fixme: check or list other sigs here */
1377         }
1378     }
1379     if( !any ) {/* oops, no user id */
1380         putchar(':');
1381         putchar(':');
1382         print_capabilities (pk, sk, keyblock);
1383         putchar('\n');
1384     }
1385 }
1386
1387 /*
1388  * Reorder the keyblock so that the primary user ID (and not attribute
1389  * packet) comes first.  Fixme: Replace this by a generic sort
1390  * function.  */
1391 static void
1392 do_reorder_keyblock (KBNODE keyblock,int attr)
1393 {
1394     KBNODE primary = NULL, primary0 = NULL, primary2 = NULL;
1395     KBNODE last, node;
1396
1397     for (node=keyblock; node; primary0=node, node = node->next) {
1398         if( node->pkt->pkttype == PKT_USER_ID &&
1399             ((attr && node->pkt->pkt.user_id->attrib_data) ||
1400              (!attr && !node->pkt->pkt.user_id->attrib_data)) &&
1401             node->pkt->pkt.user_id->is_primary ) {
1402             primary = primary2 = node;
1403             for (node=node->next; node; primary2=node, node = node->next ) {
1404                 if( node->pkt->pkttype == PKT_USER_ID 
1405                     || node->pkt->pkttype == PKT_PUBLIC_SUBKEY 
1406                     || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1407                     break;
1408                 }
1409             }
1410             break;
1411         }
1412     }
1413     if ( !primary )
1414         return;  /* no primary key flag found (should not happen) */
1415
1416     for (last=NULL, node=keyblock; node; last = node, node = node->next) {
1417         if( node->pkt->pkttype == PKT_USER_ID )
1418             break;
1419     }
1420     assert (node);
1421     assert (last); /* the user ID is never the first packet */
1422     assert (primary0);  /* ditto (this is the node before primary) */
1423     if ( node == primary )
1424         return; /* already the first one */
1425
1426     last->next = primary;
1427     primary0->next = primary2->next;
1428     primary2->next = node;
1429 }
1430
1431 void
1432 reorder_keyblock (KBNODE keyblock)
1433 {
1434   do_reorder_keyblock(keyblock,1);
1435   do_reorder_keyblock(keyblock,0);
1436 }
1437
1438 void
1439 list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque )
1440 {
1441     reorder_keyblock (keyblock);
1442     if (opt.with_colons)
1443         list_keyblock_colon (keyblock, secret, fpr );
1444     else
1445         list_keyblock_print (keyblock, secret, fpr, opaque );
1446 }
1447
1448 /*
1449  * standard function to print the finperprint.
1450  * mode 0: as used in key listings, opt.with_colons is honored
1451  *      1: print using log_info ()
1452  *      2: direct use of tty
1453  *      3: direct use of tty but only primary key.
1454  * modes 1 and 2 will try and print both subkey and primary key fingerprints
1455  */
1456 void
1457 print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode )
1458 {
1459     byte array[MAX_FINGERPRINT_LEN], *p;
1460     size_t i, n;
1461     FILE *fp;
1462     const char *text;
1463     int primary=0;
1464
1465     if(sk)
1466       {
1467         if(sk->main_keyid[0]==sk->keyid[0] && sk->main_keyid[1]==sk->keyid[1])
1468           primary=1;
1469       }
1470     else
1471       {
1472         if(pk->main_keyid[0]==pk->keyid[0] && pk->main_keyid[1]==pk->keyid[1])
1473           primary=1;
1474       }
1475
1476     /* Just to be safe */
1477     if(mode&0x80 && !primary)
1478       {
1479         log_error("primary key is not really primary!\n");
1480         return;
1481       }
1482
1483     mode&=~0x80;
1484
1485     if(!primary && (mode==1 || mode==2))
1486       {
1487         if(sk)
1488           {
1489             PKT_secret_key *primary_sk=xmalloc_clear(sizeof(*primary_sk));
1490             get_seckey(primary_sk,sk->main_keyid);
1491             print_fingerprint(NULL,primary_sk,mode|0x80);
1492             free_secret_key(primary_sk);
1493           }
1494         else
1495           {
1496             PKT_public_key *primary_pk=xmalloc_clear(sizeof(*primary_pk));
1497             get_pubkey(primary_pk,pk->main_keyid);
1498             print_fingerprint(primary_pk,NULL,mode|0x80);
1499             free_public_key(primary_pk);
1500           }
1501       }
1502
1503     if (mode == 1) {
1504         fp = log_get_stream ();
1505         if(primary)
1506           text = _("Primary key fingerprint:");
1507         else
1508           text = _("     Subkey fingerprint:");
1509     }
1510     else if (mode == 2) {
1511         fp = NULL; /* use tty */
1512         if(primary)
1513           /* TRANSLATORS: this should fit into 24 bytes to that the
1514            * fingerprint data is properly aligned with the user ID */
1515           text = _(" Primary key fingerprint:");
1516         else
1517           text = _("      Subkey fingerprint:");
1518     }
1519     else if (mode == 3) {
1520         fp = NULL; /* use tty */
1521         text = _("      Key fingerprint =");
1522     }
1523     else {
1524         fp = stdout;
1525         text = _("      Key fingerprint =");
1526     }
1527   
1528     if (sk)
1529         fingerprint_from_sk (sk, array, &n);
1530     else
1531         fingerprint_from_pk (pk, array, &n);
1532     p = array;
1533     if (opt.with_colons && !mode) {
1534         fprintf (fp, "fpr:::::::::");
1535         for (i=0; i < n ; i++, p++ )
1536             fprintf (fp, "%02X", *p );
1537         putc(':', fp);
1538     }
1539     else {
1540         if (fp)
1541             fputs (text, fp);
1542         else
1543             tty_printf ("%s", text);
1544         if (n == 20) {
1545             for (i=0; i < n ; i++, i++, p += 2 ) {
1546                 if (fp) {
1547                     if (i == 10 )
1548                         putc(' ', fp);
1549                     fprintf (fp, " %02X%02X", *p, p[1] );
1550                 }
1551                 else {
1552                     if (i == 10 )
1553                         tty_printf (" ");
1554                     tty_printf (" %02X%02X", *p, p[1]);
1555                 }
1556             }
1557         }
1558         else {
1559             for (i=0; i < n ; i++, p++ ) {
1560                 if (fp) {
1561                     if (i && !(i%8) )
1562                         putc (' ', fp);
1563                     fprintf (fp, " %02X", *p );
1564                 }
1565                 else {
1566                     if (i && !(i%8) )
1567                         tty_printf (" ");
1568                     tty_printf (" %02X", *p );
1569                 }
1570             }
1571         }
1572     }
1573     if (fp)
1574         putc ('\n', fp);
1575     else
1576         tty_printf ("\n");
1577 }
1578
1579 /* Print the serial number of an OpenPGP card if available. */
1580 static void
1581 print_card_serialno (PKT_secret_key *sk)
1582 {
1583   int i;
1584
1585   if (!sk)
1586     return;
1587   if (!sk->is_protected || sk->protect.s2k.mode != 1002) 
1588     return; /* Not a card. */
1589   if (opt.with_colons)
1590     return; /* Handled elsewhere. */
1591
1592   fputs (_("      Card serial no. ="), stdout);
1593   putchar (' ');
1594   if (sk->protect.ivlen == 16
1595       && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6) )
1596     { /* This is an OpenPGP card. Just print the relevant part. */
1597       for (i=8; i < 14; i++)
1598         {
1599           if (i == 10)
1600             putchar (' ');
1601           printf ("%02X", sk->protect.iv[i]);
1602         }
1603     }
1604   else
1605     { /* Something is wrong: Print all. */
1606       for (i=0; i < sk->protect.ivlen; i++)
1607         printf ("%02X", sk->protect.iv[i]);
1608     }
1609   putchar ('\n');
1610 }
1611
1612
1613
1614 void set_attrib_fd(int fd)
1615 {
1616   static int last_fd=-1;
1617
1618   if ( fd != -1 && last_fd == fd )
1619     return;
1620
1621   if ( attrib_fp && attrib_fp != stdout && attrib_fp != stderr )
1622     fclose (attrib_fp);
1623   attrib_fp = NULL;
1624   if ( fd == -1 ) 
1625     return;
1626
1627   if( fd == 1 )
1628     attrib_fp = stdout;
1629   else if( fd == 2 )
1630     attrib_fp = stderr;
1631   else
1632     attrib_fp = fdopen( fd, "wb" );
1633   if( !attrib_fp ) {
1634     log_fatal("can't open fd %d for attribute output: %s\n",
1635               fd, strerror(errno));
1636   }
1637
1638   last_fd = fd;
1639 }