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