* mainproc.c (check_sig_and_print): Use two different preferred keyserver
[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             if(sig->flags.pref_ks && (opt.list_options&LIST_SHOW_KEYSERVER))
849               show_keyserver_url(sig,3,0);
850
851             /* fixme: check or list other sigs here */
852         }
853     }
854     putchar('\n');
855 }
856
857
858 static void
859 list_keyblock_colon( KBNODE keyblock, int secret, int fpr )
860 {
861     int rc = 0;
862     KBNODE kbctx;
863     KBNODE node;
864     PKT_public_key *pk;
865     PKT_secret_key *sk;
866     u32 keyid[2];
867     int any=0;
868     int trustletter = 0;
869     int ulti_hack = 0;
870
871     /* get the keyid from the keyblock */
872     node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
873     if( !node ) {
874         log_error("Oops; key lost!\n");
875         dump_kbnode( keyblock );
876         return;
877     }
878
879     if( secret ) {
880         pk = NULL;
881         sk = node->pkt->pkt.secret_key;
882         keyid_from_sk( sk, keyid );
883         printf("sec::%u:%d:%08lX%08lX:%s:%s:::",
884                     nbits_from_sk( sk ),
885                     sk->pubkey_algo,
886                     (ulong)keyid[0],(ulong)keyid[1],
887                     colon_datestr_from_sk( sk ),
888                     colon_strtime (sk->expiredate)
889                     /* fixme: add LID here */ );
890     }
891     else {
892         pk = node->pkt->pkt.public_key;
893         sk = NULL;
894         keyid_from_pk( pk, keyid );
895         fputs( "pub:", stdout );
896         if ( !pk->is_valid )
897             putchar ('i');
898         else if ( pk->is_revoked )
899             putchar ('r');
900         else if ( pk->has_expired )
901             putchar ('e');
902         else if ( opt.fast_list_mode || opt.no_expensive_trust_checks ) 
903             ;
904         else {
905             trustletter = get_validity_info ( pk, NULL );
906             if( trustletter == 'u' )
907                 ulti_hack = 1;
908             putchar(trustletter);
909         }
910         printf(":%u:%d:%08lX%08lX:%s:%s:",
911                     nbits_from_pk( pk ),
912                     pk->pubkey_algo,
913                     (ulong)keyid[0],(ulong)keyid[1],
914                     colon_datestr_from_pk( pk ),
915                     colon_strtime (pk->expiredate) );
916         if( pk->local_id )
917             printf("%lu", pk->local_id );
918         putchar(':');
919         if( !opt.fast_list_mode && !opt.no_expensive_trust_checks  )
920             putchar( get_ownertrust_info(pk) );
921             putchar(':');
922     }
923     
924     if (opt.fixed_list_mode) {
925         /* do not merge the first uid with the primary key */
926         putchar(':');
927         putchar(':');
928         print_capabilities (pk, sk, keyblock);
929         putchar('\n');
930         if( fpr )
931             print_fingerprint( pk, sk, 0 );
932         if( opt.with_key_data )
933             print_key_data( pk, keyid );
934         any = 1;
935     }
936
937
938     for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
939         if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) {
940             PKT_user_id *uid=node->pkt->pkt.user_id;
941             if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL)
942               dump_attribs(node->pkt->pkt.user_id,pk,sk);
943             /*
944              * Fixme: We need a is_valid flag here too 
945              */
946             if( any ) {
947                 int i;
948                 char *str=uid->attrib_data?"uat":"uid";
949                 /* If we're listing a secret key, leave out the
950                    validity values for now.  This is handled better in
951                    1.9. */
952                 if ( sk )
953                     printf("%s:::::",str);
954                 else if ( uid->is_revoked )
955                     printf("%s:r::::",str);
956                 else if ( uid->is_expired )
957                     printf("%s:e::::",str);
958                 else if ( opt.no_expensive_trust_checks )
959                     printf("%s:::::",str);
960                 else {
961                     int uid_validity;
962
963                     if( pk && !ulti_hack )
964                       uid_validity=get_validity_info (pk, uid);
965                     else
966                         uid_validity = 'u';
967                     printf("%s:%c::::",str,uid_validity);
968                 }
969
970                 printf("%s:",colon_strtime(uid->created));
971                 printf("%s:",colon_strtime(uid->expiredate));
972
973                 namehash_from_uid(uid);
974
975                 for(i=0; i < 20; i++ )
976                   printf("%02X",uid->namehash[i]);
977
978                 printf("::");
979             }
980             if(uid->attrib_data)
981               printf("%u %lu",uid->numattribs,uid->attrib_len);
982             else
983               print_string(stdout,uid->name,uid->len, ':' );
984             putchar(':');
985             if (any)
986                 putchar('\n');
987             else {
988                 putchar(':');
989                 print_capabilities (pk, sk, keyblock);
990                 putchar('\n');
991                 if( fpr )
992                     print_fingerprint( pk, sk, 0 );
993                 if( opt.with_key_data )
994                     print_key_data( pk, keyid );
995                 any = 1;
996             }
997         }
998         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
999             u32 keyid2[2];
1000             PKT_public_key *pk2 = node->pkt->pkt.public_key;
1001
1002             if( !any ) {
1003                 putchar(':');
1004                 putchar(':');
1005                 print_capabilities (pk, sk, keyblock);
1006                 putchar('\n');
1007                 if( fpr )
1008                     print_fingerprint( pk, sk, 0 ); /* of the main key */
1009                 any = 1;
1010             }
1011
1012             keyid_from_pk( pk2, keyid2 );
1013             fputs ("sub:", stdout );
1014             if ( !pk2->is_valid )
1015                 putchar ('i');
1016             else if ( pk2->is_revoked )
1017                 putchar ('r');
1018             else if ( pk2->has_expired )
1019                 putchar ('e');
1020             else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1021                 ;
1022             else {
1023                 /* trustletter should always be defined here */
1024                 if(trustletter)
1025                   printf("%c", trustletter );
1026             }
1027             printf(":%u:%d:%08lX%08lX:%s:%s:",
1028                         nbits_from_pk( pk2 ),
1029                         pk2->pubkey_algo,
1030                         (ulong)keyid2[0],(ulong)keyid2[1],
1031                         colon_datestr_from_pk( pk2 ),
1032                         colon_strtime (pk2->expiredate)
1033                         /* fixme: add LID and ownertrust here */
1034                                                 );
1035             if( pk->local_id ) /* use the local_id of the main key??? */
1036                 printf("%lu", pk->local_id );
1037             putchar(':');
1038             putchar(':');
1039             putchar(':');
1040             putchar(':');
1041             print_capabilities (pk2, NULL, NULL);
1042             putchar('\n');
1043             if( fpr > 1 )
1044                 print_fingerprint( pk2, NULL, 0 );
1045             if( opt.with_key_data )
1046                 print_key_data( pk2, keyid2 );
1047         }
1048         else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1049             u32 keyid2[2];
1050             PKT_secret_key *sk2 = node->pkt->pkt.secret_key;
1051
1052             if( !any ) {
1053                 putchar(':');
1054                 putchar(':');
1055                 print_capabilities (pk, sk, keyblock);
1056                 putchar('\n');
1057                 if( fpr )
1058                     print_fingerprint( pk, sk, 0 ); /* of the main key */
1059                 any = 1;
1060             }
1061
1062             keyid_from_sk( sk2, keyid2 );
1063             printf("ssb::%u:%d:%08lX%08lX:%s:%s:::::",
1064                         nbits_from_sk( sk2 ),
1065                         sk2->pubkey_algo,
1066                         (ulong)keyid2[0],(ulong)keyid2[1],
1067                         colon_datestr_from_sk( sk2 ),
1068                         colon_strtime (sk2->expiredate)
1069                    /* fixme: add LID */ );
1070             print_capabilities (NULL, sk2, NULL);
1071             putchar ('\n');
1072             if( fpr > 1 )
1073                 print_fingerprint( NULL, sk2, 0 );
1074         }
1075         else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) {
1076             PKT_signature *sig = node->pkt->pkt.signature;
1077             int sigrc,fprokay=0;
1078             char *sigstr;
1079             size_t fplen;
1080             byte fparray[MAX_FINGERPRINT_LEN];
1081
1082             if( !any ) { /* no user id, (maybe a revocation follows)*/
1083                 if( sig->sig_class == 0x20 )
1084                     fputs("[revoked]:", stdout);
1085                 else if( sig->sig_class == 0x18 )
1086                     fputs("[key binding]:", stdout);
1087                 else if( sig->sig_class == 0x28 )
1088                     fputs("[subkey revoked]:", stdout);
1089                 else
1090                     putchar (':');
1091                 putchar(':');
1092                 print_capabilities (pk, sk, keyblock);
1093                 putchar('\n');
1094                 if( fpr )
1095                     print_fingerprint( pk, sk, 0 );
1096                 any=1;
1097             }
1098
1099             if( sig->sig_class == 0x20 || sig->sig_class == 0x28
1100                                        || sig->sig_class == 0x30 )
1101                sigstr = "rev";
1102             else if( (sig->sig_class&~3) == 0x10 )
1103                sigstr = "sig";
1104             else if( sig->sig_class == 0x18 )
1105                sigstr = "sig";
1106             else if( sig->sig_class == 0x1F )
1107                sigstr = "sig";
1108             else {
1109                 printf ("sig::::::::::%02x%c:\n",
1110                         sig->sig_class, sig->flags.exportable?'x':'l');
1111                 continue;
1112             }
1113             if( opt.check_sigs ) {
1114                 PKT_public_key *signer_pk=NULL;
1115
1116                 fflush(stdout);
1117                 if(opt.no_sig_cache)
1118                   signer_pk=m_alloc_clear(sizeof(PKT_public_key));
1119
1120                 rc = check_key_signature2( keyblock, node, NULL, signer_pk,
1121                                            NULL, NULL, NULL );
1122                 switch( rc ) {
1123                   case 0:                  sigrc = '!'; break;
1124                   case G10ERR_BAD_SIGN:    sigrc = '-'; break;
1125                   case G10ERR_NO_PUBKEY: 
1126                   case G10ERR_UNU_PUBKEY:  sigrc = '?'; break;
1127                   default:                 sigrc = '%'; break;
1128                 }
1129
1130                 if(opt.no_sig_cache)
1131                   {
1132                     if(rc==0)
1133                       {
1134                         fingerprint_from_pk (signer_pk, fparray, &fplen);
1135                         fprokay=1;
1136                       }
1137                     free_public_key(signer_pk);
1138                   }
1139             }
1140             else {
1141                 rc = 0;
1142                 sigrc = ' ';
1143             }
1144             fputs( sigstr, stdout );
1145             putchar(':');
1146             if( sigrc != ' ' )
1147                 putchar(sigrc);
1148             printf("::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo,
1149                    (ulong)sig->keyid[0], (ulong)sig->keyid[1],
1150                    colon_datestr_from_sig(sig),
1151                    colon_expirestr_from_sig(sig));
1152
1153             if(sig->trust_depth || sig->trust_value)
1154               printf("%d %d",sig->trust_depth,sig->trust_value);
1155             printf(":");
1156
1157             if(sig->trust_regexp)
1158               print_string(stdout,sig->trust_regexp,
1159                            strlen(sig->trust_regexp),':');
1160             printf(":");
1161
1162             if( sigrc == '%' )
1163                 printf("[%s] ", g10_errstr(rc) );
1164             else if( sigrc == '?' )
1165                 ;
1166             else if ( !opt.fast_list_mode ) {
1167                 size_t n;
1168                 char *p = get_user_id( sig->keyid, &n );
1169                 print_string( stdout, p, n, ':' );
1170                 m_free(p);
1171             }
1172             printf(":%02x%c:", sig->sig_class,sig->flags.exportable?'x':'l');
1173
1174             if(opt.no_sig_cache && opt.check_sigs && fprokay)
1175               {
1176                 size_t i;
1177
1178                 printf(":");
1179
1180                 for (i=0; i < fplen ; i++ )
1181                   printf ("%02X", fparray[i] );
1182
1183                 printf(":");
1184               }
1185
1186             printf("\n");
1187
1188             /* fixme: check or list other sigs here */
1189         }
1190     }
1191     if( !any ) {/* oops, no user id */
1192         putchar(':');
1193         putchar(':');
1194         print_capabilities (pk, sk, keyblock);
1195         putchar('\n');
1196     }
1197 }
1198
1199 /*
1200  * Reorder the keyblock so that the primary user ID (and not attribute
1201  * packet) comes first.  Fixme: Replace this by a generic sort
1202  * function.  */
1203 void
1204 reorder_keyblock (KBNODE keyblock)
1205 {
1206     KBNODE primary = NULL, primary0 = NULL, primary2 = NULL;
1207     KBNODE last, node;
1208
1209     for (node=keyblock; node; primary0=node, node = node->next) {
1210         if( node->pkt->pkttype == PKT_USER_ID &&
1211             !node->pkt->pkt.user_id->attrib_data &&
1212             node->pkt->pkt.user_id->is_primary ) {
1213             primary = primary2 = node;
1214             for (node=node->next; node; primary2=node, node = node->next ) {
1215                 if( node->pkt->pkttype == PKT_USER_ID 
1216                     || node->pkt->pkttype == PKT_PUBLIC_SUBKEY 
1217                     || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1218                     break;
1219                 }
1220             }
1221             break;
1222         }
1223     }
1224     if ( !primary )
1225         return;  /* no primary key flag found (should not happen) */
1226
1227     for (last=NULL, node=keyblock; node; last = node, node = node->next) {
1228         if( node->pkt->pkttype == PKT_USER_ID )
1229             break;
1230     }
1231     assert (node);
1232     assert (last); /* the user ID is never the first packet */
1233     assert (primary0);  /* ditto (this is the node before primary) */
1234     if ( node == primary )
1235         return; /* already the first one */
1236
1237     last->next = primary;
1238     primary0->next = primary2->next;
1239     primary2->next = node;
1240 }
1241
1242 void
1243 list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque )
1244 {
1245     reorder_keyblock (keyblock);
1246     if (opt.with_colons)
1247         list_keyblock_colon (keyblock, secret, fpr );
1248     else
1249         list_keyblock_print (keyblock, secret, fpr, opaque );
1250 }
1251
1252 /*
1253  * standard function to print the finperprint.
1254  * mode 0: as used in key listings, opt.with_colons is honored
1255  *      1: print using log_info ()
1256  *      2: direct use of tty
1257  *      3: direct use of tty but only primary key.
1258  * modes 1 and 2 will try and print both subkey and primary key fingerprints
1259  */
1260 void
1261 print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode )
1262 {
1263     byte array[MAX_FINGERPRINT_LEN], *p;
1264     size_t i, n;
1265     FILE *fp;
1266     const char *text;
1267     int primary=0;
1268
1269     if(sk)
1270       {
1271         if(sk->main_keyid[0]==sk->keyid[0] && sk->main_keyid[1]==sk->keyid[1])
1272           primary=1;
1273       }
1274     else
1275       {
1276         if(pk->main_keyid[0]==pk->keyid[0] && pk->main_keyid[1]==pk->keyid[1])
1277           primary=1;
1278       }
1279
1280     /* Just to be safe */
1281     if(mode&0x80 && !primary)
1282       {
1283         log_error("primary key is not really primary!\n");
1284         return;
1285       }
1286
1287     mode&=~0x80;
1288
1289     if(!primary && (mode==1 || mode==2))
1290       {
1291         if(sk)
1292           {
1293             PKT_secret_key *primary_sk=m_alloc_clear(sizeof(*primary_sk));
1294             get_seckey(primary_sk,sk->main_keyid);
1295             print_fingerprint(NULL,primary_sk,mode|0x80);
1296             free_secret_key(primary_sk);
1297           }
1298         else
1299           {
1300             PKT_public_key *primary_pk=m_alloc_clear(sizeof(*primary_pk));
1301             get_pubkey(primary_pk,pk->main_keyid);
1302             print_fingerprint(primary_pk,NULL,mode|0x80);
1303             free_public_key(primary_pk);
1304           }
1305       }
1306
1307     if (mode == 1) {
1308         fp = log_stream ();
1309         if(primary)
1310           text = _("Primary key fingerprint:");
1311         else
1312           text = _("     Subkey fingerprint:");
1313     }
1314     else if (mode == 2) {
1315         fp = NULL; /* use tty */
1316         /* Translators: this should fit into 24 bytes to that the fingerprint
1317          * data is properly aligned with the user ID */
1318         if(primary)
1319           text = _(" Primary key fingerprint:");
1320         else
1321           text = _("      Subkey fingerprint:");
1322     }
1323     else if (mode == 3) {
1324         fp = NULL; /* use tty */
1325         text = _("      Key fingerprint =");
1326     }
1327     else {
1328         fp = stdout;
1329         text = _("      Key fingerprint =");
1330     }
1331   
1332     if (sk)
1333         fingerprint_from_sk (sk, array, &n);
1334     else
1335         fingerprint_from_pk (pk, array, &n);
1336     p = array;
1337     if (opt.with_colons && !mode) {
1338         fprintf (fp, "fpr:::::::::");
1339         for (i=0; i < n ; i++, p++ )
1340             fprintf (fp, "%02X", *p );
1341         putc(':', fp);
1342     }
1343     else {
1344         if (fp)
1345             fputs (text, fp);
1346         else
1347             tty_printf ("%s", text);
1348         if (n == 20) {
1349             for (i=0; i < n ; i++, i++, p += 2 ) {
1350                 if (fp) {
1351                     if (i == 10 )
1352                         putc(' ', fp);
1353                     fprintf (fp, " %02X%02X", *p, p[1] );
1354                 }
1355                 else {
1356                     if (i == 10 )
1357                         tty_printf (" ");
1358                     tty_printf (" %02X%02X", *p, p[1]);
1359                 }
1360             }
1361         }
1362         else {
1363             for (i=0; i < n ; i++, p++ ) {
1364                 if (fp) {
1365                     if (i && !(i%8) )
1366                         putc (' ', fp);
1367                     fprintf (fp, " %02X", *p );
1368                 }
1369                 else {
1370                     if (i && !(i%8) )
1371                         tty_printf (" ");
1372                     tty_printf (" %02X", *p );
1373                 }
1374             }
1375         }
1376     }
1377     if (fp)
1378         putc ('\n', fp);
1379     else
1380         tty_printf ("\n");
1381 }
1382
1383 void set_attrib_fd(int fd)
1384 {
1385   static int last_fd=-1;
1386
1387   if ( fd != -1 && last_fd == fd )
1388     return;
1389
1390   if ( attrib_fp && attrib_fp != stdout && attrib_fp != stderr )
1391     fclose (attrib_fp);
1392   attrib_fp = NULL;
1393   if ( fd == -1 ) 
1394     return;
1395
1396   if( fd == 1 )
1397     attrib_fp = stdout;
1398   else if( fd == 2 )
1399     attrib_fp = stderr;
1400   else
1401     attrib_fp = fdopen( fd, "w" );
1402   if( !attrib_fp ) {
1403     log_fatal("can't open fd %d for attribute output: %s\n",
1404               fd, strerror(errno));
1405   }
1406   last_fd = fd;
1407 }