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