Replace a call to BUG by an error return.
[gnupg.git] / g10 / keylist.c
blob4a76ee0655bcf669530098d8ad67184ed9f8549a
1 /* keylist.c - print keys
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3 * 2008 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
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.
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.
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/>.
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
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"
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);
49 struct sig_stats
51 int inv_sigs;
52 int no_key;
53 int oth_err;
56 /* The stream used to write attribute packets to. */
57 static FILE *attrib_fp = NULL;
59 /****************
60 * List the keys
61 * If list is NULL, all available keys are listed
63 void
64 public_key_list( strlist_t list, int locate_mode )
66 if (opt.with_colons)
68 byte trust_model,marginals,completes,cert_depth;
69 ulong created,nextcheck;
71 read_trust_options(&trust_model,&created,&nextcheck,
72 &marginals,&completes,&cert_depth);
74 printf("tru:");
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)
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");
90 printf(":%d:%lu:%lu",trust_model,created,nextcheck);
92 /* Only show marginals, completes, and cert_depth in the classic
93 or PGP trust models since they are not meaningful
94 otherwise. */
96 if(trust_model==TM_PGP || trust_model==TM_CLASSIC)
97 printf(":%d:%d:%d",marginals,completes,cert_depth);
99 printf("\n");
102 /* We need to do the stale check right here because it might need to
103 update the keyring while we already have the keyring open. This
104 is very bad for W32 because of a sharing violation. For real OSes
105 it might lead to false results if we are later listing a keyring
106 which is associated with the inode of a deleted file. */
107 check_trustdb_stale ();
109 if (locate_mode)
110 locate_one (list);
111 else if (!list)
112 list_all (0);
113 else
114 list_one (list, 0);
118 void
119 secret_key_list( strlist_t list )
121 check_trustdb_stale ();
123 if( !list )
124 list_all(1);
125 else /* List by user id */
126 list_one( list, 1 );
129 void
130 print_seckey_info (PKT_secret_key *sk)
132 u32 keyid[2];
133 char *p;
135 keyid_from_sk (sk, keyid);
136 p=get_user_id_native(keyid);
138 tty_printf ("\nsec %4u%c/%s %s %s\n",
139 nbits_from_sk (sk),
140 pubkey_letter (sk->pubkey_algo),
141 keystr(keyid), datestr_from_sk (sk), p);
143 xfree (p);
146 /* Print information about the public key. With FP passed as NULL,
147 the tty output interface is used, otherwise output is directted to
148 the given stream. */
149 void
150 print_pubkey_info (FILE *fp, PKT_public_key *pk)
152 u32 keyid[2];
153 char *p;
155 keyid_from_pk (pk, keyid);
157 /* If the pk was chosen by a particular user ID, that is the one to
158 print. */
159 if(pk->user_id)
160 p=utf8_to_native(pk->user_id->name,pk->user_id->len,0);
161 else
162 p=get_user_id_native(keyid);
164 if (fp)
165 fprintf (fp, "pub %4u%c/%s %s %s\n",
166 nbits_from_pk (pk),
167 pubkey_letter (pk->pubkey_algo),
168 keystr(keyid), datestr_from_pk (pk), p);
169 else
170 tty_printf ("\npub %4u%c/%s %s %s\n",
171 nbits_from_pk (pk), pubkey_letter (pk->pubkey_algo),
172 keystr(keyid), datestr_from_pk (pk), p);
174 xfree (p);
178 /* Print basic information of a secret key including the card serial
179 number information. */
180 void
181 print_card_key_info (FILE *fp, KBNODE keyblock)
183 KBNODE node;
184 int i;
186 for (node = keyblock; node; node = node->next )
188 if (node->pkt->pkttype == PKT_SECRET_KEY
189 || (node->pkt->pkttype == PKT_SECRET_SUBKEY) )
191 PKT_secret_key *sk = node->pkt->pkt.secret_key;
193 tty_fprintf (fp, "%s%c %4u%c/%s ",
194 node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
195 (sk->protect.s2k.mode==1001)?'#':
196 (sk->protect.s2k.mode==1002)?'>':' ',
197 nbits_from_sk (sk),
198 pubkey_letter (sk->pubkey_algo),
199 keystr_from_sk(sk));
200 tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk));
201 tty_fprintf (fp, " ");
202 tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk));
203 if (sk->is_protected && sk->protect.s2k.mode == 1002)
205 tty_fprintf (fp, "\n ");
206 tty_fprintf (fp, _("card-no: "));
207 if (sk->protect.ivlen == 16
208 && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6))
210 /* This is an OpenPGP card. */
211 for (i=8; i < 14; i++)
213 if (i == 10)
214 tty_fprintf (fp, " ");
215 tty_fprintf (fp, "%02X", sk->protect.iv[i]);
218 else
219 { /* Something is wrong: Print all. */
220 for (i=0; i < sk->protect.ivlen; i++)
221 tty_fprintf (fp, "%02X", sk->protect.iv[i]);
224 tty_fprintf (fp, "\n");
231 /* Flags = 0x01 hashed 0x02 critical */
232 static void
233 status_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf)
235 char status[40];
237 /* Don't print these. */
238 if(len>256)
239 return;
241 sprintf(status,"%d %u %u ",type,flags,(unsigned int)len);
243 write_status_text_and_buffer(STATUS_SIG_SUBPACKET,status,buf,len,0);
247 mode=0 for stdout.
248 mode=1 for log_info + status messages
249 mode=2 for status messages only
252 void
253 show_policy_url(PKT_signature *sig,int indent,int mode)
255 const byte *p;
256 size_t len;
257 int seq=0,crit;
258 FILE *fp=mode?log_get_stream():stdout;
260 while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,&len,&seq,&crit)))
262 if(mode!=2)
264 int i;
265 const char *str;
267 for(i=0;i<indent;i++)
268 putchar(' ');
270 if(crit)
271 str=_("Critical signature policy: ");
272 else
273 str=_("Signature policy: ");
274 if(mode)
275 log_info("%s",str);
276 else
277 printf("%s",str);
278 print_utf8_string(fp,p,len);
279 fprintf(fp,"\n");
282 if(mode)
283 write_status_buffer ( STATUS_POLICY_URL, p, len, 0 );
288 mode=0 for stdout.
289 mode=1 for log_info + status messages
290 mode=2 for status messages only
292 /* TODO: use this */
293 void
294 show_keyserver_url(PKT_signature *sig,int indent,int mode)
296 const byte *p;
297 size_t len;
298 int seq=0,crit;
299 FILE *fp=mode?log_get_stream():stdout;
301 while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&len,&seq,&crit)))
303 if(mode!=2)
305 int i;
306 const char *str;
308 for(i=0;i<indent;i++)
309 putchar(' ');
311 if(crit)
312 str=_("Critical preferred keyserver: ");
313 else
314 str=_("Preferred keyserver: ");
315 if(mode)
316 log_info("%s",str);
317 else
318 printf("%s",str);
319 print_utf8_string(fp,p,len);
320 fprintf(fp,"\n");
323 if(mode)
324 status_one_subpacket(SIGSUBPKT_PREF_KS,len,(crit?0x02:0)|0x01,p);
329 mode=0 for stdout.
330 mode=1 for log_info + status messages
331 mode=2 for status messages only
333 which bits:
334 1 == standard notations
335 2 == user notations
338 void
339 show_notation(PKT_signature *sig,int indent,int mode,int which)
341 FILE *fp=mode?log_get_stream():stdout;
342 struct notation *nd,*notations;
344 if(which==0)
345 which=3;
347 notations=sig_to_notation(sig);
349 /* There may be multiple notations in the same sig. */
350 for(nd=notations;nd;nd=nd->next)
352 if(mode!=2)
354 int has_at=!!strchr(nd->name,'@');
356 if((which&1 && !has_at) || (which&2 && has_at))
358 int i;
359 const char *str;
361 for(i=0;i<indent;i++)
362 putchar(' ');
364 if(nd->flags.critical)
365 str=_("Critical signature notation: ");
366 else
367 str=_("Signature notation: ");
368 if(mode)
369 log_info("%s",str);
370 else
371 printf("%s",str);
372 /* This is all UTF8 */
373 print_utf8_string(fp,nd->name,strlen(nd->name));
374 fprintf(fp,"=");
375 print_utf8_string(fp,nd->value,strlen(nd->value));
376 fprintf(fp,"\n");
380 if(mode)
382 write_status_buffer(STATUS_NOTATION_NAME,
383 nd->name,strlen(nd->name),0);
384 write_status_buffer(STATUS_NOTATION_DATA,
385 nd->value,strlen(nd->value),50);
389 free_notation(notations);
392 static void
393 print_signature_stats(struct sig_stats *s)
395 if( s->inv_sigs == 1 )
396 tty_printf(_("1 bad signature\n") );
397 else if( s->inv_sigs )
398 tty_printf(_("%d bad signatures\n"), s->inv_sigs );
399 if( s->no_key == 1 )
400 tty_printf(_("1 signature not checked due to a missing key\n") );
401 else if( s->no_key )
402 tty_printf(_("%d signatures not checked due to missing keys\n"),s->no_key);
403 if( s->oth_err == 1 )
404 tty_printf(_("1 signature not checked due to an error\n") );
405 else if( s->oth_err )
406 tty_printf(_("%d signatures not checked due to errors\n"), s->oth_err );
409 static void
410 list_all( int secret )
412 KEYDB_HANDLE hd;
413 KBNODE keyblock = NULL;
414 int rc=0;
415 const char *lastresname, *resname;
416 struct sig_stats stats;
418 memset(&stats,0,sizeof(stats));
420 hd = keydb_new (secret);
421 if (!hd)
422 rc = G10ERR_GENERAL;
423 else
424 rc = keydb_search_first (hd);
425 if( rc ) {
426 if( rc != -1 )
427 log_error("keydb_search_first failed: %s\n", g10_errstr(rc) );
428 goto leave;
431 lastresname = NULL;
432 do {
433 rc = keydb_get_keyblock (hd, &keyblock);
434 if (rc) {
435 log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc));
436 goto leave;
438 if(!opt.with_colons)
440 resname = keydb_get_resource_name (hd);
441 if (lastresname != resname )
443 int i;
445 printf("%s\n", resname );
446 for(i=strlen(resname); i; i-- )
447 putchar('-');
448 putchar('\n');
449 lastresname = resname;
452 merge_keys_and_selfsig( keyblock );
453 list_keyblock( keyblock, secret, opt.fingerprint,
454 opt.check_sigs?&stats:NULL);
455 release_kbnode( keyblock );
456 keyblock = NULL;
457 } while (!(rc = keydb_search_next (hd)));
458 if( rc && rc != -1 )
459 log_error ("keydb_search_next failed: %s\n", g10_errstr(rc));
461 if(opt.check_sigs && !opt.with_colons)
462 print_signature_stats(&stats);
464 leave:
465 release_kbnode (keyblock);
466 keydb_release (hd);
470 static void
471 list_one( strlist_t names, int secret )
473 int rc = 0;
474 KBNODE keyblock = NULL;
475 GETKEY_CTX ctx;
476 const char *resname;
477 const char *keyring_str = _("Keyring");
478 int i;
479 struct sig_stats stats;
481 memset(&stats,0,sizeof(stats));
483 /* fixme: using the bynames function has the disadvantage that we
484 * don't know wether one of the names given was not found. OTOH,
485 * this function has the advantage to list the names in the
486 * sequence as defined by the keyDB and does not duplicate
487 * outputs. A solution could be do test whether all given have
488 * been listed (this needs a way to use the keyDB search
489 * functions) or to have the search function return indicators for
490 * found names. Yet another way is to use the keydb search
491 * facilities directly. */
492 if( secret ) {
493 rc = get_seckey_bynames( &ctx, NULL, names, &keyblock );
494 if( rc ) {
495 log_error("error reading key: %s\n", g10_errstr(rc) );
496 get_seckey_end( ctx );
497 return;
499 do {
500 if ((opt.list_options&LIST_SHOW_KEYRING) && !opt.with_colons) {
501 resname = keydb_get_resource_name (get_ctx_handle(ctx));
502 printf("%s: %s\n", keyring_str, resname);
503 for(i = strlen(resname) + strlen(keyring_str) + 2; i; i-- )
504 putchar('-');
505 putchar('\n');
507 list_keyblock( keyblock, 1, opt.fingerprint, NULL );
508 release_kbnode( keyblock );
509 } while( !get_seckey_next( ctx, NULL, &keyblock ) );
510 get_seckey_end( ctx );
512 else {
513 rc = get_pubkey_bynames( &ctx, NULL, names, &keyblock );
514 if( rc ) {
515 log_error("error reading key: %s\n", g10_errstr(rc) );
516 get_pubkey_end( ctx );
517 return;
519 do {
520 if ((opt.list_options&LIST_SHOW_KEYRING) && !opt.with_colons) {
521 resname = keydb_get_resource_name (get_ctx_handle(ctx));
522 printf("%s: %s\n", keyring_str, resname);
523 for(i = strlen(resname) + strlen(keyring_str) + 2; i; i-- )
524 putchar('-');
525 putchar('\n');
527 list_keyblock( keyblock, 0, opt.fingerprint,
528 opt.check_sigs?&stats:NULL );
529 release_kbnode( keyblock );
530 } while( !get_pubkey_next( ctx, NULL, &keyblock ) );
531 get_pubkey_end( ctx );
534 if(opt.check_sigs && !opt.with_colons)
535 print_signature_stats(&stats);
539 static void
540 locate_one (strlist_t names)
542 int rc = 0;
543 strlist_t sl;
544 GETKEY_CTX ctx = NULL;
545 KBNODE keyblock = NULL;
546 struct sig_stats stats;
548 memset (&stats,0,sizeof(stats));
550 for (sl=names; sl; sl = sl->next)
552 rc = get_pubkey_byname (&ctx, NULL, sl->d, &keyblock, NULL, 1, 0);
553 if (rc)
555 if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
556 log_error ("error reading key: %s\n", g10_errstr(rc) );
558 else
562 list_keyblock (keyblock, 0, opt.fingerprint,
563 opt.check_sigs? &stats : NULL );
564 release_kbnode (keyblock);
566 while ( ctx && !get_pubkey_next (ctx, NULL, &keyblock));
567 get_pubkey_end (ctx);
568 ctx = NULL;
572 if (opt.check_sigs && !opt.with_colons)
573 print_signature_stats (&stats);
577 static void
578 print_key_data( PKT_public_key *pk )
580 int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
581 int i;
583 for(i=0; i < n; i++ ) {
584 printf("pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
585 mpi_print(stdout, pk->pkey[i], 1 );
586 putchar(':');
587 putchar('\n');
591 static void
592 print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock)
594 if(pk || (sk && sk->protect.s2k.mode!=1001))
596 unsigned int use = pk? pk->pubkey_usage : sk->pubkey_usage;
597 int c_printed = 0;
599 if ( use & PUBKEY_USAGE_ENC )
600 putchar ('e');
602 if ( use & PUBKEY_USAGE_SIG )
604 putchar ('s');
605 if( pk? pk->is_primary : sk->is_primary )
607 putchar ('c');
608 /* The PUBKEY_USAGE_CERT flag was introduced later and
609 we used to always print 'c' for a primary key. To
610 avoid any regression here we better track whether we
611 printed 'c' already. */
612 c_printed = 1;
616 if ( (use & PUBKEY_USAGE_CERT) && !c_printed )
617 putchar ('c');
619 if ( (use & PUBKEY_USAGE_AUTH) )
620 putchar ('a');
623 if ( keyblock ) { /* figure out the usable capabilities */
624 KBNODE k;
625 int enc=0, sign=0, cert=0, auth=0, disabled=0;
627 for (k=keyblock; k; k = k->next ) {
628 if ( k->pkt->pkttype == PKT_PUBLIC_KEY
629 || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
630 pk = k->pkt->pkt.public_key;
632 if(pk->is_primary)
633 disabled=pk_is_disabled(pk);
635 if ( pk->is_valid && !pk->is_revoked && !pk->has_expired ) {
636 if ( pk->pubkey_usage & PUBKEY_USAGE_ENC )
637 enc = 1;
638 if ( pk->pubkey_usage & PUBKEY_USAGE_SIG )
640 sign = 1;
641 if(pk->is_primary)
642 cert = 1;
644 if ( pk->pubkey_usage & PUBKEY_USAGE_CERT )
645 cert = 1;
646 if ( (pk->pubkey_usage & PUBKEY_USAGE_AUTH) )
647 auth = 1;
650 else if ( k->pkt->pkttype == PKT_SECRET_KEY
651 || k->pkt->pkttype == PKT_SECRET_SUBKEY ) {
652 sk = k->pkt->pkt.secret_key;
653 if ( sk->is_valid && !sk->is_revoked && !sk->has_expired
654 && sk->protect.s2k.mode!=1001 ) {
655 if ( sk->pubkey_usage & PUBKEY_USAGE_ENC )
656 enc = 1;
657 if ( sk->pubkey_usage & PUBKEY_USAGE_SIG )
659 sign = 1;
660 if(sk->is_primary)
661 cert = 1;
663 if ( (sk->pubkey_usage & PUBKEY_USAGE_CERT) )
664 cert = 1;
665 if ( (sk->pubkey_usage & PUBKEY_USAGE_AUTH) )
666 auth = 1;
670 if (enc)
671 putchar ('E');
672 if (sign)
673 putchar ('S');
674 if (cert)
675 putchar ('C');
676 if (auth)
677 putchar ('A');
678 if (disabled)
679 putchar ('D');
682 putchar(':');
685 /* Flags = 0x01 hashed 0x02 critical */
686 static void
687 print_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf)
689 size_t i;
691 printf("spk:%d:%u:%u:",type,flags,(unsigned int)len);
693 for(i=0;i<len;i++)
695 /* printable ascii other than : and % */
696 if(buf[i]>=32 && buf[i]<=126 && buf[i]!=':' && buf[i]!='%')
697 printf("%c",buf[i]);
698 else
699 printf("%%%02X",buf[i]);
702 printf("\n");
705 void
706 print_subpackets_colon(PKT_signature *sig)
708 byte *i;
710 assert(opt.show_subpackets);
712 for(i=opt.show_subpackets;*i;i++)
714 const byte *p;
715 size_t len;
716 int seq,crit;
718 seq=0;
720 while((p=enum_sig_subpkt(sig->hashed,*i,&len,&seq,&crit)))
721 print_one_subpacket(*i,len,0x01|(crit?0x02:0),p);
723 seq=0;
725 while((p=enum_sig_subpkt(sig->unhashed,*i,&len,&seq,&crit)))
726 print_one_subpacket(*i,len,0x00|(crit?0x02:0),p);
730 void
731 dump_attribs(const PKT_user_id *uid,PKT_public_key *pk,PKT_secret_key *sk)
733 int i;
735 if(!attrib_fp)
736 return;
738 for(i=0;i<uid->numattribs;i++)
740 if(is_status_enabled())
742 byte array[MAX_FINGERPRINT_LEN], *p;
743 char buf[(MAX_FINGERPRINT_LEN*2)+90];
744 size_t j,n;
746 if(pk)
747 fingerprint_from_pk( pk, array, &n );
748 else if(sk)
749 fingerprint_from_sk( sk, array, &n );
750 else
751 BUG();
753 p = array;
754 for(j=0; j < n ; j++, p++ )
755 sprintf(buf+2*j, "%02X", *p );
757 sprintf(buf+strlen(buf)," %lu %u %u %u %lu %lu %u",
758 (ulong)uid->attribs[i].len,uid->attribs[i].type,i+1,
759 uid->numattribs,(ulong)uid->created,(ulong)uid->expiredate,
760 ((uid->is_primary?0x01:0)|
761 (uid->is_revoked?0x02:0)|
762 (uid->is_expired?0x04:0)));
763 write_status_text(STATUS_ATTRIBUTE,buf);
766 fwrite(uid->attribs[i].data,uid->attribs[i].len,1,attrib_fp);
767 fflush (attrib_fp);
771 static void
772 list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
774 int rc = 0;
775 KBNODE kbctx;
776 KBNODE node;
777 PKT_public_key *pk;
778 PKT_secret_key *sk;
779 struct sig_stats *stats=opaque;
780 int skip_sigs=0;
782 /* get the keyid from the keyblock */
783 node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
784 if( !node ) {
785 log_error("Oops; key lost!\n");
786 dump_kbnode( keyblock );
787 return;
790 if( secret )
792 pk = NULL;
793 sk = node->pkt->pkt.secret_key;
795 printf("sec%c %4u%c/%s %s",(sk->protect.s2k.mode==1001)?'#':
796 (sk->protect.s2k.mode==1002)?'>':' ',
797 nbits_from_sk( sk ),pubkey_letter( sk->pubkey_algo ),
798 keystr_from_sk(sk),datestr_from_sk( sk ));
800 if(sk->has_expired)
802 printf(" [");
803 printf(_("expired: %s"),expirestr_from_sk(sk));
804 printf("]");
806 else if(sk->expiredate )
808 printf(" [");
809 printf(_("expires: %s"),expirestr_from_sk(sk));
810 printf("]");
813 printf("\n");
815 else
817 pk = node->pkt->pkt.public_key;
818 sk = NULL;
820 check_trustdb_stale();
822 printf("pub %4u%c/%s %s",
823 nbits_from_pk(pk),pubkey_letter(pk->pubkey_algo),
824 keystr_from_pk(pk),datestr_from_pk( pk ));
826 /* We didn't include this before in the key listing, but there
827 is room in the new format, so why not? */
829 if(pk->is_revoked)
831 printf(" [");
832 printf(_("revoked: %s"),revokestr_from_pk(pk));
833 printf("]");
835 else if(pk->has_expired)
837 printf(" [");
838 printf(_("expired: %s"),expirestr_from_pk(pk));
839 printf("]");
841 else if(pk->expiredate)
843 printf(" [");
844 printf(_("expires: %s"),expirestr_from_pk(pk));
845 printf("]");
848 #if 0
849 /* I need to think about this some more. It's easy enough to
850 include, but it looks sort of confusing in the
851 listing... */
852 if(opt.list_options&LIST_SHOW_VALIDITY)
854 int validity=get_validity(pk,NULL);
855 printf(" [%s]",trust_value_to_string(validity));
857 #endif
859 printf("\n");
862 if( fpr )
863 print_fingerprint( pk, sk, 0 );
864 print_card_serialno (sk);
865 if( opt.with_key_data )
866 print_key_data( pk );
868 for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
869 if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) {
870 PKT_user_id *uid=node->pkt->pkt.user_id;
872 if(pk && (uid->is_expired || uid->is_revoked)
873 && !(opt.list_options&LIST_SHOW_UNUSABLE_UIDS))
875 skip_sigs=1;
876 continue;
878 else
879 skip_sigs=0;
881 if(attrib_fp && uid->attrib_data!=NULL)
882 dump_attribs(uid,pk,sk);
884 if((uid->is_revoked || uid->is_expired)
885 || ((opt.list_options&LIST_SHOW_UID_VALIDITY) && pk))
887 const char *validity;
888 int indent;
890 validity=uid_trust_string_fixed(pk,uid);
891 indent=(keystrlen()+9)-atoi(uid_trust_string_fixed(NULL,NULL));
893 if(indent<0 || indent>40)
894 indent=0;
896 printf("uid%*s%s ",indent,"",validity);
898 else
899 printf("uid%*s", (int)keystrlen()+10,"");
901 print_utf8_string( stdout, uid->name, uid->len );
902 putchar('\n');
904 if((opt.list_options&LIST_SHOW_PHOTOS) && uid->attribs!=NULL)
905 show_photos(uid->attribs,uid->numattribs,pk,sk,uid);
907 else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
909 PKT_public_key *pk2 = node->pkt->pkt.public_key;
911 if((pk2->is_revoked || pk2->has_expired)
912 && !(opt.list_options&LIST_SHOW_UNUSABLE_SUBKEYS))
914 skip_sigs=1;
915 continue;
917 else
918 skip_sigs=0;
920 printf("sub %4u%c/%s %s",
921 nbits_from_pk( pk2 ),pubkey_letter( pk2->pubkey_algo ),
922 keystr_from_pk(pk2),datestr_from_pk(pk2));
923 if( pk2->is_revoked )
925 printf(" [");
926 printf(_("revoked: %s"),revokestr_from_pk(pk2));
927 printf("]");
929 else if( pk2->has_expired )
931 printf(" [");
932 printf(_("expired: %s"),expirestr_from_pk(pk2));
933 printf("]");
935 else if( pk2->expiredate )
937 printf(" [");
938 printf(_("expires: %s"),expirestr_from_pk(pk2));
939 printf("]");
941 putchar('\n');
942 if( fpr > 1 )
943 print_fingerprint( pk2, NULL, 0 );
944 if( opt.with_key_data )
945 print_key_data( pk2 );
947 else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
949 PKT_secret_key *sk2 = node->pkt->pkt.secret_key;
951 printf("ssb%c %4u%c/%s %s",
952 (sk2->protect.s2k.mode==1001)?'#':
953 (sk2->protect.s2k.mode==1002)?'>':' ',
954 nbits_from_sk( sk2 ),pubkey_letter( sk2->pubkey_algo ),
955 keystr_from_sk(sk2),datestr_from_sk( sk2 ) );
956 if( sk2->expiredate )
958 printf(" [");
959 printf(_("expires: %s"),expirestr_from_sk(sk2));
960 printf("]");
962 putchar('\n');
963 if( fpr > 1 )
965 print_fingerprint( NULL, sk2, 0 );
966 print_card_serialno (sk2);
969 else if( opt.list_sigs
970 && node->pkt->pkttype == PKT_SIGNATURE
971 && !skip_sigs ) {
972 PKT_signature *sig = node->pkt->pkt.signature;
973 int sigrc;
974 char *sigstr;
976 if( stats ) {
977 /*fflush(stdout);*/
978 rc = check_key_signature( keyblock, node, NULL );
979 switch( gpg_err_code (rc) ) {
980 case 0: sigrc = '!'; break;
981 case GPG_ERR_BAD_SIGNATURE:
982 stats->inv_sigs++; sigrc = '-'; break;
983 case GPG_ERR_NO_PUBKEY:
984 case GPG_ERR_UNUSABLE_PUBKEY: stats->no_key++; continue;
985 default: stats->oth_err++; sigrc = '%'; break;
988 /* TODO: Make sure a cached sig record here still has
989 the pk that issued it. See also
990 keyedit.c:print_and_check_one_sig */
992 else {
993 rc = 0;
994 sigrc = ' ';
997 if( sig->sig_class == 0x20 || sig->sig_class == 0x28
998 || sig->sig_class == 0x30 )
999 sigstr = "rev";
1000 else if( (sig->sig_class&~3) == 0x10 )
1001 sigstr = "sig";
1002 else if( sig->sig_class == 0x18 )
1003 sigstr = "sig";
1004 else if( sig->sig_class == 0x1F )
1005 sigstr = "sig";
1006 else {
1007 printf("sig "
1008 "[unexpected signature class 0x%02x]\n",sig->sig_class );
1009 continue;
1012 fputs( sigstr, stdout );
1013 printf("%c%c %c%c%c%c%c%c %s %s",
1014 sigrc,(sig->sig_class-0x10>0 &&
1015 sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ',
1016 sig->flags.exportable?' ':'L',
1017 sig->flags.revocable?' ':'R',
1018 sig->flags.policy_url?'P':' ',
1019 sig->flags.notation?'N':' ',
1020 sig->flags.expired?'X':' ',
1021 (sig->trust_depth>9)?'T':
1022 (sig->trust_depth>0)?'0'+sig->trust_depth:' ',
1023 keystr(sig->keyid),datestr_from_sig(sig));
1024 if(opt.list_options&LIST_SHOW_SIG_EXPIRE)
1025 printf(" %s", expirestr_from_sig(sig));
1026 printf(" ");
1027 if( sigrc == '%' )
1028 printf("[%s] ", g10_errstr(rc) );
1029 else if( sigrc == '?' )
1031 else if ( !opt.fast_list_mode ) {
1032 size_t n;
1033 char *p = get_user_id( sig->keyid, &n );
1034 print_utf8_string( stdout, p, n );
1035 xfree(p);
1037 putchar('\n');
1039 if(sig->flags.policy_url
1040 && (opt.list_options&LIST_SHOW_POLICY_URLS))
1041 show_policy_url(sig,3,0);
1043 if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATIONS))
1044 show_notation(sig,3,0,
1045 ((opt.list_options&LIST_SHOW_STD_NOTATIONS)?1:0)+
1046 ((opt.list_options&LIST_SHOW_USER_NOTATIONS)?2:0));
1048 if(sig->flags.pref_ks
1049 && (opt.list_options&LIST_SHOW_KEYSERVER_URLS))
1050 show_keyserver_url(sig,3,0);
1052 /* fixme: check or list other sigs here */
1055 putchar('\n');
1058 void
1059 print_revokers(PKT_public_key *pk)
1061 /* print the revoker record */
1062 if( !pk->revkey && pk->numrevkeys )
1063 BUG();
1064 else
1066 int i,j;
1068 for (i=0; i < pk->numrevkeys; i++)
1070 byte *p;
1072 printf ("rvk:::%d::::::", pk->revkey[i].algid);
1073 p = pk->revkey[i].fpr;
1074 for (j=0; j < 20; j++, p++ )
1075 printf ("%02X", *p);
1076 printf (":%02x%s:\n", pk->revkey[i].class,
1077 (pk->revkey[i].class&0x40)?"s":"");
1082 static void
1083 list_keyblock_colon( KBNODE keyblock, int secret, int fpr )
1085 int rc = 0;
1086 KBNODE kbctx;
1087 KBNODE node;
1088 PKT_public_key *pk;
1089 PKT_secret_key *sk;
1090 u32 keyid[2];
1091 int trustletter = 0;
1092 int ulti_hack = 0;
1093 int i;
1095 /* get the keyid from the keyblock */
1096 node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
1097 if ( !node )
1099 log_error("Oops; key lost!\n");
1100 dump_kbnode( keyblock );
1101 return;
1104 if ( secret )
1106 pk = NULL;
1107 sk = node->pkt->pkt.secret_key;
1108 keyid_from_sk ( sk, keyid );
1109 printf ("sec::%u:%d:%08lX%08lX:%s:%s:::",
1110 nbits_from_sk( sk ),
1111 sk->pubkey_algo,
1112 (ulong)keyid[0],(ulong)keyid[1],
1113 colon_datestr_from_sk( sk ),
1114 colon_strtime (sk->expiredate)
1115 /* fixme: add LID here */ );
1117 else
1119 pk = node->pkt->pkt.public_key;
1120 sk = NULL;
1121 keyid_from_pk( pk, keyid );
1122 fputs( "pub:", stdout );
1123 if ( !pk->is_valid )
1124 putchar ('i');
1125 else if ( pk->is_revoked )
1126 putchar ('r');
1127 else if ( pk->has_expired )
1128 putchar ('e');
1129 else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1131 else
1133 trustletter = get_validity_info ( pk, NULL );
1134 if ( trustletter == 'u' )
1135 ulti_hack = 1;
1136 putchar(trustletter);
1138 printf (":%u:%d:%08lX%08lX:%s:%s::",
1139 nbits_from_pk( pk ),
1140 pk->pubkey_algo,
1141 (ulong)keyid[0],(ulong)keyid[1],
1142 colon_datestr_from_pk( pk ),
1143 colon_strtime (pk->expiredate) );
1144 if ( !opt.fast_list_mode && !opt.no_expensive_trust_checks )
1145 putchar( get_ownertrust_info(pk) );
1146 putchar(':');
1149 putchar (':');
1150 putchar (':');
1151 print_capabilities (pk, sk, keyblock);
1152 if (secret)
1154 putchar (':'); /* End of field 13. */
1155 putchar (':'); /* End of field 14. */
1156 if (sk->protect.s2k.mode == 1001)
1157 putchar ('#'); /* Key is just a stub. */
1158 else if (sk->protect.s2k.mode == 1002)
1160 /* Key is stored on an external token (card) or handled by
1161 the gpg-agent. Print the serial number of that token
1162 here. */
1163 for (i=0; i < sk->protect.ivlen; i++)
1164 printf ("%02X", sk->protect.iv[i]);
1166 putchar (':'); /* End of field 15. */
1168 putchar('\n');
1169 if (pk)
1170 print_revokers (pk);
1171 if (fpr)
1172 print_fingerprint (pk, sk, 0);
1173 if (opt.with_key_data)
1174 print_key_data (pk);
1177 for ( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; )
1179 if ( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode )
1181 char *str;
1182 PKT_user_id *uid=node->pkt->pkt.user_id;
1184 if (attrib_fp && node->pkt->pkt.user_id->attrib_data != NULL)
1185 dump_attribs (node->pkt->pkt.user_id,pk,sk);
1187 * Fixme: We need a is_valid flag here too
1189 str = uid->attrib_data? "uat":"uid";
1190 /* If we're listing a secret key, leave out the validity
1191 values for now. This is handled better in 1.9. */
1192 if (sk)
1193 printf ("%s:::::",str);
1194 else if ( uid->is_revoked )
1195 printf ("%s:r::::",str);
1196 else if ( uid->is_expired )
1197 printf ("%s:e::::",str);
1198 else if ( opt.no_expensive_trust_checks )
1199 printf ("%s:::::",str);
1200 else
1202 int uid_validity;
1204 if ( pk && !ulti_hack )
1205 uid_validity=get_validity_info (pk, uid);
1206 else
1207 uid_validity = 'u';
1208 printf ("%s:%c::::",str,uid_validity);
1211 printf ("%s:", colon_strtime (uid->created));
1212 printf ("%s:", colon_strtime (uid->expiredate));
1214 namehash_from_uid (uid);
1216 for (i=0; i < 20; i++ )
1217 printf ("%02X",uid->namehash[i]);
1219 printf ("::");
1221 if (uid->attrib_data)
1222 printf ("%u %lu",uid->numattribs,uid->attrib_len);
1223 else
1224 print_string (stdout,uid->name,uid->len, ':' );
1225 putchar (':');
1226 putchar ('\n');
1228 else if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1230 u32 keyid2[2];
1231 PKT_public_key *pk2 = node->pkt->pkt.public_key;
1233 keyid_from_pk ( pk2, keyid2 );
1234 fputs ("sub:", stdout );
1235 if ( !pk2->is_valid )
1236 putchar ('i');
1237 else if ( pk2->is_revoked )
1238 putchar ('r');
1239 else if ( pk2->has_expired )
1240 putchar ('e');
1241 else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1243 else
1245 /* TRUSTLETTER should always be defined here. */
1246 if (trustletter)
1247 printf ("%c", trustletter );
1249 printf(":%u:%d:%08lX%08lX:%s:%s:::::",
1250 nbits_from_pk( pk2 ),
1251 pk2->pubkey_algo,
1252 (ulong)keyid2[0],(ulong)keyid2[1],
1253 colon_datestr_from_pk( pk2 ),
1254 colon_strtime (pk2->expiredate)
1255 /* fixme: add LID and ownertrust here */
1257 print_capabilities (pk2, NULL, NULL);
1258 putchar ('\n');
1259 if ( fpr > 1 )
1260 print_fingerprint ( pk2, NULL, 0 );
1261 if ( opt.with_key_data )
1262 print_key_data( pk2 );
1264 else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
1266 u32 keyid2[2];
1267 PKT_secret_key *sk2 = node->pkt->pkt.secret_key;
1269 keyid_from_sk ( sk2, keyid2 );
1270 printf ("ssb::%u:%d:%08lX%08lX:%s:%s:::::",
1271 nbits_from_sk( sk2 ),
1272 sk2->pubkey_algo,
1273 (ulong)keyid2[0],(ulong)keyid2[1],
1274 colon_datestr_from_sk( sk2 ),
1275 colon_strtime (sk2->expiredate)
1276 /* fixme: add LID */ );
1277 print_capabilities (NULL, sk2, NULL);
1278 putchar(':'); /* End of field 13. */
1279 putchar(':'); /* End of field 14. */
1280 if (sk2->protect.s2k.mode == 1001)
1281 putchar ('#'); /* Key is just a stub. */
1282 else if (sk2->protect.s2k.mode == 1002)
1284 /* Key is stored on an external token (card) or handled by
1285 the gpg-agent. Print the serial number of that token
1286 here. */
1287 for (i=0; i < sk2->protect.ivlen; i++)
1288 printf ("%02X", sk2->protect.iv[i]);
1290 putchar(':'); /* End of field 15. */
1291 putchar ('\n');
1293 if ( fpr > 1 )
1294 print_fingerprint ( NULL, sk2, 0 );
1296 else if ( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE )
1298 PKT_signature *sig = node->pkt->pkt.signature;
1299 int sigrc,fprokay=0;
1300 char *sigstr;
1301 size_t fplen;
1302 byte fparray[MAX_FINGERPRINT_LEN];
1304 if ( sig->sig_class == 0x20 || sig->sig_class == 0x28
1305 || sig->sig_class == 0x30 )
1306 sigstr = "rev";
1307 else if ( (sig->sig_class&~3) == 0x10 )
1308 sigstr = "sig";
1309 else if ( sig->sig_class == 0x18 )
1310 sigstr = "sig";
1311 else if ( sig->sig_class == 0x1F )
1312 sigstr = "sig";
1313 else
1315 printf ("sig::::::::::%02x%c:\n",
1316 sig->sig_class, sig->flags.exportable?'x':'l');
1317 continue;
1320 if ( opt.check_sigs )
1322 PKT_public_key *signer_pk=NULL;
1324 fflush (stdout);
1325 if (opt.no_sig_cache)
1326 signer_pk = xmalloc_clear (sizeof(PKT_public_key));
1328 rc = check_key_signature2 ( keyblock, node, NULL, signer_pk,
1329 NULL, NULL, NULL );
1330 switch ( gpg_err_code (rc) )
1332 case 0: sigrc = '!'; break;
1333 case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break;
1334 case GPG_ERR_NO_PUBKEY:
1335 case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break;
1336 default: sigrc = '%'; break;
1339 if (opt.no_sig_cache)
1341 if (!rc)
1343 fingerprint_from_pk (signer_pk, fparray, &fplen);
1344 fprokay = 1;
1346 free_public_key(signer_pk);
1349 else
1351 rc = 0;
1352 sigrc = ' ';
1354 fputs ( sigstr, stdout );
1355 putchar (':');
1356 if ( sigrc != ' ' )
1357 putchar (sigrc);
1358 printf ("::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo,
1359 (ulong)sig->keyid[0], (ulong)sig->keyid[1],
1360 colon_datestr_from_sig(sig),
1361 colon_expirestr_from_sig(sig));
1363 if (sig->trust_depth || sig->trust_value)
1364 printf("%d %d",sig->trust_depth,sig->trust_value);
1365 printf (":");
1367 if (sig->trust_regexp)
1368 print_string (stdout,sig->trust_regexp,
1369 strlen(sig->trust_regexp),':');
1370 printf(":");
1372 if ( sigrc == '%' )
1373 printf("[%s] ", g10_errstr(rc) );
1374 else if ( sigrc == '?' )
1376 else if ( !opt.fast_list_mode )
1378 size_t n;
1379 char *p = get_user_id( sig->keyid, &n );
1380 print_string( stdout, p, n, ':' );
1381 xfree(p);
1383 printf (":%02x%c:", sig->sig_class,sig->flags.exportable?'x':'l');
1385 if (opt.no_sig_cache && opt.check_sigs && fprokay)
1387 putchar (':');
1389 for (i=0; i < fplen ; i++ )
1390 printf ("%02X", fparray[i] );
1392 putchar (':');
1395 printf ("\n");
1397 if (opt.show_subpackets)
1398 print_subpackets_colon (sig);
1400 /* fixme: check or list other sigs here */
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)
1412 KBNODE primary = NULL, primary0 = NULL, primary2 = NULL;
1413 KBNODE last, node;
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;
1428 break;
1431 if ( !primary )
1432 return; /* no primary key flag found (should not happen) */
1434 for (last=NULL, node=keyblock; node; last = node, node = node->next) {
1435 if( node->pkt->pkttype == PKT_USER_ID )
1436 break;
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 */
1444 last->next = primary;
1445 primary0->next = primary2->next;
1446 primary2->next = node;
1449 void
1450 reorder_keyblock (KBNODE keyblock)
1452 do_reorder_keyblock(keyblock,1);
1453 do_reorder_keyblock(keyblock,0);
1456 void
1457 list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque )
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 );
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
1474 void
1475 print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode )
1477 byte array[MAX_FINGERPRINT_LEN], *p;
1478 size_t i, n;
1479 FILE *fp;
1480 const char *text;
1481 int primary=0;
1483 if(sk)
1485 if(sk->main_keyid[0]==sk->keyid[0] && sk->main_keyid[1]==sk->keyid[1])
1486 primary=1;
1488 else
1490 if(pk->main_keyid[0]==pk->keyid[0] && pk->main_keyid[1]==pk->keyid[1])
1491 primary=1;
1494 /* Just to be safe */
1495 if(mode&0x80 && !primary)
1497 log_error("primary key is not really primary!\n");
1498 return;
1501 mode&=~0x80;
1503 if(!primary && (mode==1 || mode==2))
1505 if(sk)
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);
1512 else
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);
1521 if (mode == 1) {
1522 fp = log_get_stream ();
1523 if(primary)
1524 text = _("Primary key fingerprint:");
1525 else
1526 text = _(" Subkey fingerprint:");
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:");
1537 else if (mode == 3) {
1538 fp = NULL; /* use tty */
1539 text = _(" Key fingerprint =");
1541 else {
1542 fp = stdout;
1543 text = _(" Key fingerprint =");
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);
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] );
1569 else {
1570 if (i == 10 )
1571 tty_printf (" ");
1572 tty_printf (" %02X%02X", *p, p[1]);
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 );
1583 else {
1584 if (i && !(i%8) )
1585 tty_printf (" ");
1586 tty_printf (" %02X", *p );
1591 if (fp)
1592 putc ('\n', fp);
1593 else
1594 tty_printf ("\n");
1597 /* Print the serial number of an OpenPGP card if available. */
1598 static void
1599 print_card_serialno (PKT_secret_key *sk)
1601 int i;
1603 if (!sk)
1604 return;
1605 if (!sk->is_protected || sk->protect.s2k.mode != 1002)
1606 return; /* Not a card. */
1607 if (opt.with_colons)
1608 return; /* Handled elsewhere. */
1610 fputs (_(" Card serial no. ="), stdout);
1611 putchar (' ');
1612 if (sk->protect.ivlen == 16
1613 && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6) )
1614 { /* This is an OpenPGP card. Just print the relevant part. */
1615 for (i=8; i < 14; i++)
1617 if (i == 10)
1618 putchar (' ');
1619 printf ("%02X", sk->protect.iv[i]);
1622 else
1623 { /* Something is wrong: Print all. */
1624 for (i=0; i < sk->protect.ivlen; i++)
1625 printf ("%02X", sk->protect.iv[i]);
1627 putchar ('\n');
1632 void
1633 set_attrib_fd (int fd)
1635 static int last_fd=-1;
1637 if ( fd != -1 && last_fd == fd )
1638 return;
1640 if ( attrib_fp && attrib_fp != stdout && attrib_fp != stderr
1641 && attrib_fp != log_get_stream () )
1642 fclose (attrib_fp);
1643 attrib_fp = NULL;
1644 if ( fd == -1 )
1645 return;
1647 #ifdef HAVE_DOSISH_SYSTEM
1648 setmode (fd, O_BINARY);
1649 #endif
1650 if( fd == 1 )
1651 attrib_fp = stdout;
1652 else if( fd == 2 )
1653 attrib_fp = stderr;
1654 else
1655 attrib_fp = fdopen (fd, "wb");
1656 if (!attrib_fp)
1658 log_fatal("can't open fd %d for attribute output: %s\n",
1659 fd, strerror(errno));
1662 last_fd = fd;