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