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