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