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