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