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