2008-02-01 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / g10 / keylist.c
blobdb4ef50f334c5488eb9d46ad6335b90a289f503f
1 /* keylist.c - print keys
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
3 * 2004, 2005 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>
28 #include "gpg.h"
29 #include "options.h"
30 #include "packet.h"
31 #include "status.h"
32 #include "keydb.h"
33 #include "photoid.h"
34 #include "util.h"
35 #include "ttyio.h"
36 #include "trustdb.h"
37 #include "main.h"
38 #include "i18n.h"
39 #include "status.h"
41 static void list_all(int);
42 static void list_one( strlist_t names, int secret);
43 static void print_card_serialno (PKT_secret_key *sk);
45 struct sig_stats
47 int inv_sigs;
48 int no_key;
49 int oth_err;
52 static FILE *attrib_fp=NULL;
54 /****************
55 * List the keys
56 * If list is NULL, all available keys are listed
58 void
59 public_key_list( strlist_t list )
61 if(opt.with_colons)
63 byte trust_model,marginals,completes,cert_depth;
64 ulong created,nextcheck;
66 read_trust_options(&trust_model,&created,&nextcheck,
67 &marginals,&completes,&cert_depth);
69 printf("tru:");
71 if(nextcheck && nextcheck <= make_timestamp())
72 printf("o");
73 if(trust_model!=opt.trust_model)
74 printf("t");
75 if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC)
77 if(marginals!=opt.marginals_needed)
78 printf("m");
79 if(completes!=opt.completes_needed)
80 printf("c");
81 if(cert_depth!=opt.max_cert_depth)
82 printf("d");
85 printf(":%d:%lu:%lu",trust_model,created,nextcheck);
87 /* Only show marginals, completes, and cert_depth in the classic
88 or PGP trust models since they are not meaningful
89 otherwise. */
91 if(trust_model==TM_PGP || trust_model==TM_CLASSIC)
92 printf(":%d:%d:%d",marginals,completes,cert_depth);
94 printf("\n");
97 /* We need to do the stale check right here because it might need to
98 update the keyring while we already have the keyring open. This
99 is very bad for W32 because of a sharing violation. For real OSes
100 it might lead to false results if we are later listing a keyring
101 which is associated with the inode of a deleted file. */
102 check_trustdb_stale ();
104 if( !list )
105 list_all(0);
106 else
107 list_one( list, 0 );
110 void
111 secret_key_list( strlist_t list )
113 check_trustdb_stale ();
115 if( !list )
116 list_all(1);
117 else /* List by user id */
118 list_one( list, 1 );
121 void
122 print_seckey_info (PKT_secret_key *sk)
124 u32 keyid[2];
125 char *p;
127 keyid_from_sk (sk, keyid);
128 p=get_user_id_native(keyid);
130 tty_printf ("\nsec %4u%c/%s %s %s\n",
131 nbits_from_sk (sk),
132 pubkey_letter (sk->pubkey_algo),
133 keystr(keyid), datestr_from_sk (sk), p);
135 xfree (p);
138 /* Print information about the public key. With FP passed as NULL,
139 the tty output interface is used, otherwise output is directted to
140 the given stream. */
141 void
142 print_pubkey_info (FILE *fp, PKT_public_key *pk)
144 u32 keyid[2];
145 char *p;
147 keyid_from_pk (pk, keyid);
149 /* If the pk was chosen by a particular user ID, that is the one to
150 print. */
151 if(pk->user_id)
152 p=utf8_to_native(pk->user_id->name,pk->user_id->len,0);
153 else
154 p=get_user_id_native(keyid);
156 if (fp)
157 fprintf (fp, "pub %4u%c/%s %s %s\n",
158 nbits_from_pk (pk),
159 pubkey_letter (pk->pubkey_algo),
160 keystr(keyid), datestr_from_pk (pk), p);
161 else
162 tty_printf ("\npub %4u%c/%s %s %s\n",
163 nbits_from_pk (pk), pubkey_letter (pk->pubkey_algo),
164 keystr(keyid), datestr_from_pk (pk), p);
166 xfree (p);
170 /* Print basic information of a secret key including the card serial
171 number information. */
172 void
173 print_card_key_info (FILE *fp, KBNODE keyblock)
175 KBNODE node;
176 int i;
178 for (node = keyblock; node; node = node->next )
180 if (node->pkt->pkttype == PKT_SECRET_KEY
181 || (node->pkt->pkttype == PKT_SECRET_SUBKEY) )
183 PKT_secret_key *sk = node->pkt->pkt.secret_key;
185 tty_fprintf (fp, "%s%c %4u%c/%s ",
186 node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
187 (sk->protect.s2k.mode==1001)?'#':
188 (sk->protect.s2k.mode==1002)?'>':' ',
189 nbits_from_sk (sk),
190 pubkey_letter (sk->pubkey_algo),
191 keystr_from_sk(sk));
192 tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk));
193 tty_fprintf (fp, " ");
194 tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk));
195 if (sk->is_protected && sk->protect.s2k.mode == 1002)
197 tty_fprintf (fp, "\n ");
198 tty_fprintf (fp, _("card-no: "));
199 if (sk->protect.ivlen == 16
200 && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6))
202 /* This is an OpenPGP card. */
203 for (i=8; i < 14; i++)
205 if (i == 10)
206 tty_fprintf (fp, " ");
207 tty_fprintf (fp, "%02X", sk->protect.iv[i]);
210 else
211 { /* Something is wrong: Print all. */
212 for (i=0; i < sk->protect.ivlen; i++)
213 tty_fprintf (fp, "%02X", sk->protect.iv[i]);
216 tty_fprintf (fp, "\n");
223 /* Flags = 0x01 hashed 0x02 critical */
224 static void
225 status_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf)
227 char status[40];
229 /* Don't print these. */
230 if(len>256)
231 return;
233 sprintf(status,"%d %u %u ",type,flags,(unsigned int)len);
235 write_status_text_and_buffer(STATUS_SIG_SUBPACKET,status,buf,len,0);
239 mode=0 for stdout.
240 mode=1 for log_info + status messages
241 mode=2 for status messages only
244 void
245 show_policy_url(PKT_signature *sig,int indent,int mode)
247 const byte *p;
248 size_t len;
249 int seq=0,crit;
250 FILE *fp=mode?log_get_stream():stdout;
252 while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,&len,&seq,&crit)))
254 if(mode!=2)
256 int i;
257 const char *str;
259 for(i=0;i<indent;i++)
260 putchar(' ');
262 if(crit)
263 str=_("Critical signature policy: ");
264 else
265 str=_("Signature policy: ");
266 if(mode)
267 log_info("%s",str);
268 else
269 printf("%s",str);
270 print_utf8_string(fp,p,len);
271 fprintf(fp,"\n");
274 if(mode)
275 write_status_buffer ( STATUS_POLICY_URL, p, len, 0 );
280 mode=0 for stdout.
281 mode=1 for log_info + status messages
282 mode=2 for status messages only
284 /* TODO: use this */
285 void
286 show_keyserver_url(PKT_signature *sig,int indent,int mode)
288 const byte *p;
289 size_t len;
290 int seq=0,crit;
291 FILE *fp=mode?log_get_stream():stdout;
293 while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&len,&seq,&crit)))
295 if(mode!=2)
297 int i;
298 const char *str;
300 for(i=0;i<indent;i++)
301 putchar(' ');
303 if(crit)
304 str=_("Critical preferred keyserver: ");
305 else
306 str=_("Preferred keyserver: ");
307 if(mode)
308 log_info("%s",str);
309 else
310 printf("%s",str);
311 print_utf8_string(fp,p,len);
312 fprintf(fp,"\n");
315 if(mode)
316 status_one_subpacket(SIGSUBPKT_PREF_KS,len,(crit?0x02:0)|0x01,p);
321 mode=0 for stdout.
322 mode=1 for log_info + status messages
323 mode=2 for status messages only
325 which bits:
326 1 == standard notations
327 2 == user notations
330 void
331 show_notation(PKT_signature *sig,int indent,int mode,int which)
333 FILE *fp=mode?log_get_stream():stdout;
334 struct notation *nd,*notations;
336 if(which==0)
337 which=3;
339 notations=sig_to_notation(sig);
341 /* There may be multiple notations in the same sig. */
342 for(nd=notations;nd;nd=nd->next)
344 if(mode!=2)
346 int has_at=!!strchr(nd->name,'@');
348 if((which&1 && !has_at) || (which&2 && has_at))
350 int i;
351 const char *str;
353 for(i=0;i<indent;i++)
354 putchar(' ');
356 if(nd->flags.critical)
357 str=_("Critical signature notation: ");
358 else
359 str=_("Signature notation: ");
360 if(mode)
361 log_info("%s",str);
362 else
363 printf("%s",str);
364 /* This is all UTF8 */
365 print_utf8_string(fp,nd->name,strlen(nd->name));
366 fprintf(fp,"=");
367 print_utf8_string(fp,nd->value,strlen(nd->value));
368 fprintf(fp,"\n");
372 if(mode)
374 write_status_buffer(STATUS_NOTATION_NAME,
375 nd->name,strlen(nd->name),0);
376 write_status_buffer(STATUS_NOTATION_DATA,
377 nd->value,strlen(nd->value),50);
381 free_notation(notations);
384 static void
385 print_signature_stats(struct sig_stats *s)
387 if( s->inv_sigs == 1 )
388 tty_printf(_("1 bad signature\n") );
389 else if( s->inv_sigs )
390 tty_printf(_("%d bad signatures\n"), s->inv_sigs );
391 if( s->no_key == 1 )
392 tty_printf(_("1 signature not checked due to a missing key\n") );
393 else if( s->no_key )
394 tty_printf(_("%d signatures not checked due to missing keys\n"),s->no_key);
395 if( s->oth_err == 1 )
396 tty_printf(_("1 signature not checked due to an error\n") );
397 else if( s->oth_err )
398 tty_printf(_("%d signatures not checked due to errors\n"), s->oth_err );
401 static void
402 list_all( int secret )
404 KEYDB_HANDLE hd;
405 KBNODE keyblock = NULL;
406 int rc=0;
407 const char *lastresname, *resname;
408 struct sig_stats stats;
410 memset(&stats,0,sizeof(stats));
412 hd = keydb_new (secret);
413 if (!hd)
414 rc = G10ERR_GENERAL;
415 else
416 rc = keydb_search_first (hd);
417 if( rc ) {
418 if( rc != -1 )
419 log_error("keydb_search_first failed: %s\n", g10_errstr(rc) );
420 goto leave;
423 lastresname = NULL;
424 do {
425 rc = keydb_get_keyblock (hd, &keyblock);
426 if (rc) {
427 log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc));
428 goto leave;
430 if(!opt.with_colons)
432 resname = keydb_get_resource_name (hd);
433 if (lastresname != resname )
435 int i;
437 printf("%s\n", resname );
438 for(i=strlen(resname); i; i-- )
439 putchar('-');
440 putchar('\n');
441 lastresname = resname;
444 merge_keys_and_selfsig( keyblock );
445 list_keyblock( keyblock, secret, opt.fingerprint,
446 opt.check_sigs?&stats:NULL);
447 release_kbnode( keyblock );
448 keyblock = NULL;
449 } while (!(rc = keydb_search_next (hd)));
450 if( rc && rc != -1 )
451 log_error ("keydb_search_next failed: %s\n", g10_errstr(rc));
453 if(opt.check_sigs && !opt.with_colons)
454 print_signature_stats(&stats);
456 leave:
457 release_kbnode (keyblock);
458 keydb_release (hd);
462 static void
463 list_one( strlist_t names, int secret )
465 int rc = 0;
466 KBNODE keyblock = NULL;
467 GETKEY_CTX ctx;
468 const char *resname;
469 const char *keyring_str = _("Keyring");
470 int i;
471 struct sig_stats stats;
473 memset(&stats,0,sizeof(stats));
475 /* fixme: using the bynames function has the disadvantage that we
476 * don't know wether one of the names given was not found. OTOH,
477 * this function has the advantage to list the names in the
478 * sequence as defined by the keyDB and does not duplicate
479 * outputs. A solution could be do test whether all given have
480 * been listed (this needs a way to use the keyDB search
481 * functions) or to have the search function return indicators for
482 * found names. Yet another way is to use the keydb search
483 * facilities directly. */
484 if( secret ) {
485 rc = get_seckey_bynames( &ctx, NULL, names, &keyblock );
486 if( rc ) {
487 log_error("error reading key: %s\n", g10_errstr(rc) );
488 get_seckey_end( ctx );
489 return;
491 do {
492 if ((opt.list_options&LIST_SHOW_KEYRING) && !opt.with_colons) {
493 resname = keydb_get_resource_name (get_ctx_handle(ctx));
494 printf("%s: %s\n", keyring_str, resname);
495 for(i = strlen(resname) + strlen(keyring_str) + 2; i; i-- )
496 putchar('-');
497 putchar('\n');
499 list_keyblock( keyblock, 1, opt.fingerprint, NULL );
500 release_kbnode( keyblock );
501 } while( !get_seckey_next( ctx, NULL, &keyblock ) );
502 get_seckey_end( ctx );
504 else {
505 rc = get_pubkey_bynames( &ctx, NULL, names, &keyblock );
506 if( rc ) {
507 log_error("error reading key: %s\n", g10_errstr(rc) );
508 get_pubkey_end( ctx );
509 return;
511 do {
512 if ((opt.list_options&LIST_SHOW_KEYRING) && !opt.with_colons) {
513 resname = keydb_get_resource_name (get_ctx_handle(ctx));
514 printf("%s: %s\n", keyring_str, resname);
515 for(i = strlen(resname) + strlen(keyring_str) + 2; i; i-- )
516 putchar('-');
517 putchar('\n');
519 list_keyblock( keyblock, 0, opt.fingerprint,
520 opt.check_sigs?&stats:NULL );
521 release_kbnode( keyblock );
522 } while( !get_pubkey_next( ctx, NULL, &keyblock ) );
523 get_pubkey_end( ctx );
526 if(opt.check_sigs && !opt.with_colons)
527 print_signature_stats(&stats);
530 static void
531 print_key_data( PKT_public_key *pk )
533 int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
534 int i;
536 for(i=0; i < n; i++ ) {
537 printf("pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
538 mpi_print(stdout, pk->pkey[i], 1 );
539 putchar(':');
540 putchar('\n');
544 static void
545 print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock)
547 if(pk || (sk && sk->protect.s2k.mode!=1001))
549 unsigned int use = pk? pk->pubkey_usage : sk->pubkey_usage;
551 if ( use & PUBKEY_USAGE_ENC )
552 putchar ('e');
554 if ( use & PUBKEY_USAGE_SIG )
556 putchar ('s');
557 if( pk? pk->is_primary : sk->is_primary )
558 putchar ('c');
561 if ( (use & PUBKEY_USAGE_AUTH) )
562 putchar ('a');
565 if ( keyblock ) { /* figure out the usable capabilities */
566 KBNODE k;
567 int enc=0, sign=0, cert=0, auth=0, disabled=0;
569 for (k=keyblock; k; k = k->next ) {
570 if ( k->pkt->pkttype == PKT_PUBLIC_KEY
571 || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
572 pk = k->pkt->pkt.public_key;
574 if(pk->is_primary)
575 disabled=pk_is_disabled(pk);
577 if ( pk->is_valid && !pk->is_revoked && !pk->has_expired ) {
578 if ( pk->pubkey_usage & PUBKEY_USAGE_ENC )
579 enc = 1;
580 if ( pk->pubkey_usage & PUBKEY_USAGE_SIG )
582 sign = 1;
583 if(pk->is_primary)
584 cert = 1;
586 if ( (pk->pubkey_usage & PUBKEY_USAGE_AUTH) )
587 auth = 1;
590 else if ( k->pkt->pkttype == PKT_SECRET_KEY
591 || k->pkt->pkttype == PKT_SECRET_SUBKEY ) {
592 sk = k->pkt->pkt.secret_key;
593 if ( sk->is_valid && !sk->is_revoked && !sk->has_expired
594 && sk->protect.s2k.mode!=1001 ) {
595 if ( sk->pubkey_usage & PUBKEY_USAGE_ENC )
596 enc = 1;
597 if ( sk->pubkey_usage & PUBKEY_USAGE_SIG )
599 sign = 1;
600 if(sk->is_primary)
601 cert = 1;
603 if ( (sk->pubkey_usage & PUBKEY_USAGE_AUTH) )
604 auth = 1;
608 if (enc)
609 putchar ('E');
610 if (sign)
611 putchar ('S');
612 if (cert)
613 putchar ('C');
614 if (auth)
615 putchar ('A');
616 if (disabled)
617 putchar ('D');
620 putchar(':');
623 /* Flags = 0x01 hashed 0x02 critical */
624 static void
625 print_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf)
627 size_t i;
629 printf("spk:%d:%u:%u:",type,flags,(unsigned int)len);
631 for(i=0;i<len;i++)
633 /* printable ascii other than : and % */
634 if(buf[i]>=32 && buf[i]<=126 && buf[i]!=':' && buf[i]!='%')
635 printf("%c",buf[i]);
636 else
637 printf("%%%02X",buf[i]);
640 printf("\n");
643 void
644 print_subpackets_colon(PKT_signature *sig)
646 byte *i;
648 assert(opt.show_subpackets);
650 for(i=opt.show_subpackets;*i;i++)
652 const byte *p;
653 size_t len;
654 int seq,crit;
656 seq=0;
658 while((p=enum_sig_subpkt(sig->hashed,*i,&len,&seq,&crit)))
659 print_one_subpacket(*i,len,0x01|(crit?0x02:0),p);
661 seq=0;
663 while((p=enum_sig_subpkt(sig->unhashed,*i,&len,&seq,&crit)))
664 print_one_subpacket(*i,len,0x00|(crit?0x02:0),p);
668 void
669 dump_attribs(const PKT_user_id *uid,PKT_public_key *pk,PKT_secret_key *sk)
671 int i;
673 if(!attrib_fp)
674 return;
676 for(i=0;i<uid->numattribs;i++)
678 if(is_status_enabled())
680 byte array[MAX_FINGERPRINT_LEN], *p;
681 char buf[(MAX_FINGERPRINT_LEN*2)+90];
682 size_t j,n;
684 if(pk)
685 fingerprint_from_pk( pk, array, &n );
686 else if(sk)
687 fingerprint_from_sk( sk, array, &n );
688 else
689 BUG();
691 p = array;
692 for(j=0; j < n ; j++, p++ )
693 sprintf(buf+2*j, "%02X", *p );
695 sprintf(buf+strlen(buf)," %lu %u %u %u %lu %lu %u",
696 (ulong)uid->attribs[i].len,uid->attribs[i].type,i+1,
697 uid->numattribs,(ulong)uid->created,(ulong)uid->expiredate,
698 ((uid->is_primary?0x01:0)|
699 (uid->is_revoked?0x02:0)|
700 (uid->is_expired?0x04:0)));
701 write_status_text(STATUS_ATTRIBUTE,buf);
704 fwrite(uid->attribs[i].data,uid->attribs[i].len,1,attrib_fp);
708 static void
709 list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
711 int rc = 0;
712 KBNODE kbctx;
713 KBNODE node;
714 PKT_public_key *pk;
715 PKT_secret_key *sk;
716 struct sig_stats *stats=opaque;
717 int skip_sigs=0;
719 /* get the keyid from the keyblock */
720 node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
721 if( !node ) {
722 log_error("Oops; key lost!\n");
723 dump_kbnode( keyblock );
724 return;
727 if( secret )
729 pk = NULL;
730 sk = node->pkt->pkt.secret_key;
732 printf("sec%c %4u%c/%s %s",(sk->protect.s2k.mode==1001)?'#':
733 (sk->protect.s2k.mode==1002)?'>':' ',
734 nbits_from_sk( sk ),pubkey_letter( sk->pubkey_algo ),
735 keystr_from_sk(sk),datestr_from_sk( sk ));
737 if(sk->has_expired)
739 printf(" [");
740 printf(_("expired: %s"),expirestr_from_sk(sk));
741 printf("]");
743 else if(sk->expiredate )
745 printf(" [");
746 printf(_("expires: %s"),expirestr_from_sk(sk));
747 printf("]");
750 printf("\n");
752 else
754 pk = node->pkt->pkt.public_key;
755 sk = NULL;
757 check_trustdb_stale();
759 printf("pub %4u%c/%s %s",
760 nbits_from_pk(pk),pubkey_letter(pk->pubkey_algo),
761 keystr_from_pk(pk),datestr_from_pk( pk ));
763 /* We didn't include this before in the key listing, but there
764 is room in the new format, so why not? */
766 if(pk->is_revoked)
768 printf(" [");
769 printf(_("revoked: %s"),revokestr_from_pk(pk));
770 printf("]");
772 else if(pk->has_expired)
774 printf(" [");
775 printf(_("expired: %s"),expirestr_from_pk(pk));
776 printf("]");
778 else if(pk->expiredate)
780 printf(" [");
781 printf(_("expires: %s"),expirestr_from_pk(pk));
782 printf("]");
785 #if 0
786 /* I need to think about this some more. It's easy enough to
787 include, but it looks sort of confusing in the
788 listing... */
789 if(opt.list_options&LIST_SHOW_VALIDITY)
791 int validity=get_validity(pk,NULL);
792 printf(" [%s]",trust_value_to_string(validity));
794 #endif
796 printf("\n");
799 if( fpr )
800 print_fingerprint( pk, sk, 0 );
801 print_card_serialno (sk);
802 if( opt.with_key_data )
803 print_key_data( pk );
805 for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
806 if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) {
807 PKT_user_id *uid=node->pkt->pkt.user_id;
809 if(pk && (uid->is_expired || uid->is_revoked)
810 && !(opt.list_options&LIST_SHOW_UNUSABLE_UIDS))
812 skip_sigs=1;
813 continue;
815 else
816 skip_sigs=0;
818 if(attrib_fp && uid->attrib_data!=NULL)
819 dump_attribs(uid,pk,sk);
821 if((uid->is_revoked || uid->is_expired)
822 || ((opt.list_options&LIST_SHOW_UID_VALIDITY) && pk))
824 const char *validity;
825 int indent;
827 validity=uid_trust_string_fixed(pk,uid);
828 indent=(keystrlen()+9)-atoi(uid_trust_string_fixed(NULL,NULL));
830 if(indent<0 || indent>40)
831 indent=0;
833 printf("uid%*s%s ",indent,"",validity);
835 else
836 printf("uid%*s", (int)keystrlen()+10,"");
838 print_utf8_string( stdout, uid->name, uid->len );
839 putchar('\n');
841 if((opt.list_options&LIST_SHOW_PHOTOS) && uid->attribs!=NULL)
842 show_photos(uid->attribs,uid->numattribs,pk,sk);
844 else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
846 PKT_public_key *pk2 = node->pkt->pkt.public_key;
848 if((pk2->is_revoked || pk2->has_expired)
849 && !(opt.list_options&LIST_SHOW_UNUSABLE_SUBKEYS))
851 skip_sigs=1;
852 continue;
854 else
855 skip_sigs=0;
857 printf("sub %4u%c/%s %s",
858 nbits_from_pk( pk2 ),pubkey_letter( pk2->pubkey_algo ),
859 keystr_from_pk(pk2),datestr_from_pk(pk2));
860 if( pk2->is_revoked )
862 printf(" [");
863 printf(_("revoked: %s"),revokestr_from_pk(pk2));
864 printf("]");
866 else if( pk2->has_expired )
868 printf(" [");
869 printf(_("expired: %s"),expirestr_from_pk(pk2));
870 printf("]");
872 else if( pk2->expiredate )
874 printf(" [");
875 printf(_("expires: %s"),expirestr_from_pk(pk2));
876 printf("]");
878 putchar('\n');
879 if( fpr > 1 )
880 print_fingerprint( pk2, NULL, 0 );
881 if( opt.with_key_data )
882 print_key_data( pk2 );
884 else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
886 PKT_secret_key *sk2 = node->pkt->pkt.secret_key;
888 printf("ssb%c %4u%c/%s %s",
889 (sk2->protect.s2k.mode==1001)?'#':
890 (sk2->protect.s2k.mode==1002)?'>':' ',
891 nbits_from_sk( sk2 ),pubkey_letter( sk2->pubkey_algo ),
892 keystr_from_sk(sk2),datestr_from_sk( sk2 ) );
893 if( sk2->expiredate )
895 printf(" [");
896 printf(_("expires: %s"),expirestr_from_sk(sk2));
897 printf("]");
899 putchar('\n');
900 if( fpr > 1 )
902 print_fingerprint( NULL, sk2, 0 );
903 print_card_serialno (sk2);
906 else if( opt.list_sigs
907 && node->pkt->pkttype == PKT_SIGNATURE
908 && !skip_sigs ) {
909 PKT_signature *sig = node->pkt->pkt.signature;
910 int sigrc;
911 char *sigstr;
913 if( stats ) {
914 /*fflush(stdout);*/
915 rc = check_key_signature( keyblock, node, NULL );
916 switch( gpg_err_code (rc) ) {
917 case 0: sigrc = '!'; break;
918 case GPG_ERR_BAD_SIGNATURE:
919 stats->inv_sigs++; sigrc = '-'; break;
920 case GPG_ERR_NO_PUBKEY:
921 case GPG_ERR_UNUSABLE_PUBKEY: stats->no_key++; continue;
922 default: stats->oth_err++; sigrc = '%'; break;
925 /* TODO: Make sure a cached sig record here still has
926 the pk that issued it. See also
927 keyedit.c:print_and_check_one_sig */
929 else {
930 rc = 0;
931 sigrc = ' ';
934 if( sig->sig_class == 0x20 || sig->sig_class == 0x28
935 || sig->sig_class == 0x30 )
936 sigstr = "rev";
937 else if( (sig->sig_class&~3) == 0x10 )
938 sigstr = "sig";
939 else if( sig->sig_class == 0x18 )
940 sigstr = "sig";
941 else if( sig->sig_class == 0x1F )
942 sigstr = "sig";
943 else {
944 printf("sig "
945 "[unexpected signature class 0x%02x]\n",sig->sig_class );
946 continue;
949 fputs( sigstr, stdout );
950 printf("%c%c %c%c%c%c%c%c %s %s",
951 sigrc,(sig->sig_class-0x10>0 &&
952 sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ',
953 sig->flags.exportable?' ':'L',
954 sig->flags.revocable?' ':'R',
955 sig->flags.policy_url?'P':' ',
956 sig->flags.notation?'N':' ',
957 sig->flags.expired?'X':' ',
958 (sig->trust_depth>9)?'T':
959 (sig->trust_depth>0)?'0'+sig->trust_depth:' ',
960 keystr(sig->keyid),datestr_from_sig(sig));
961 if(opt.list_options&LIST_SHOW_SIG_EXPIRE)
962 printf(" %s", expirestr_from_sig(sig));
963 printf(" ");
964 if( sigrc == '%' )
965 printf("[%s] ", g10_errstr(rc) );
966 else if( sigrc == '?' )
968 else if ( !opt.fast_list_mode ) {
969 size_t n;
970 char *p = get_user_id( sig->keyid, &n );
971 print_utf8_string( stdout, p, n );
972 xfree(p);
974 putchar('\n');
976 if(sig->flags.policy_url
977 && (opt.list_options&LIST_SHOW_POLICY_URLS))
978 show_policy_url(sig,3,0);
980 if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATIONS))
981 show_notation(sig,3,0,
982 ((opt.list_options&LIST_SHOW_STD_NOTATIONS)?1:0)+
983 ((opt.list_options&LIST_SHOW_USER_NOTATIONS)?2:0));
985 if(sig->flags.pref_ks
986 && (opt.list_options&LIST_SHOW_KEYSERVER_URLS))
987 show_keyserver_url(sig,3,0);
989 /* fixme: check or list other sigs here */
992 putchar('\n');
995 void
996 print_revokers(PKT_public_key *pk)
998 /* print the revoker record */
999 if( !pk->revkey && pk->numrevkeys )
1000 BUG();
1001 else
1003 int i,j;
1005 for (i=0; i < pk->numrevkeys; i++)
1007 byte *p;
1009 printf ("rvk:::%d::::::", pk->revkey[i].algid);
1010 p = pk->revkey[i].fpr;
1011 for (j=0; j < 20; j++, p++ )
1012 printf ("%02X", *p);
1013 printf (":%02x%s:\n", pk->revkey[i].class,
1014 (pk->revkey[i].class&0x40)?"s":"");
1019 static void
1020 list_keyblock_colon( KBNODE keyblock, int secret, int fpr )
1022 int rc = 0;
1023 KBNODE kbctx;
1024 KBNODE node;
1025 PKT_public_key *pk;
1026 PKT_secret_key *sk;
1027 u32 keyid[2];
1028 int any=0;
1029 int trustletter = 0;
1030 int ulti_hack = 0;
1031 int i;
1033 /* get the keyid from the keyblock */
1034 node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
1035 if( !node ) {
1036 log_error("Oops; key lost!\n");
1037 dump_kbnode( keyblock );
1038 return;
1041 if( secret ) {
1042 pk = NULL;
1043 sk = node->pkt->pkt.secret_key;
1044 keyid_from_sk( sk, keyid );
1045 printf("sec::%u:%d:%08lX%08lX:%s:%s:::",
1046 nbits_from_sk( sk ),
1047 sk->pubkey_algo,
1048 (ulong)keyid[0],(ulong)keyid[1],
1049 colon_datestr_from_sk( sk ),
1050 colon_strtime (sk->expiredate)
1051 /* fixme: add LID here */ );
1053 else {
1054 pk = node->pkt->pkt.public_key;
1055 sk = NULL;
1056 keyid_from_pk( pk, keyid );
1057 fputs( "pub:", stdout );
1058 if ( !pk->is_valid )
1059 putchar ('i');
1060 else if ( pk->is_revoked )
1061 putchar ('r');
1062 else if ( pk->has_expired )
1063 putchar ('e');
1064 else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1066 else {
1067 trustletter = get_validity_info ( pk, NULL );
1068 if( trustletter == 'u' )
1069 ulti_hack = 1;
1070 putchar(trustletter);
1072 printf(":%u:%d:%08lX%08lX:%s:%s::",
1073 nbits_from_pk( pk ),
1074 pk->pubkey_algo,
1075 (ulong)keyid[0],(ulong)keyid[1],
1076 colon_datestr_from_pk( pk ),
1077 colon_strtime (pk->expiredate) );
1078 if( !opt.fast_list_mode && !opt.no_expensive_trust_checks )
1079 putchar( get_ownertrust_info(pk) );
1080 putchar(':');
1083 if (opt.fixed_list_mode) {
1084 /* do not merge the first uid with the primary key */
1085 putchar(':');
1086 putchar(':');
1087 print_capabilities (pk, sk, keyblock);
1088 if (secret) {
1089 putchar(':'); /* End of field 13. */
1090 putchar(':'); /* End of field 14. */
1091 if (sk->protect.s2k.mode == 1001)
1092 putchar('#'); /* Key is just a stub. */
1093 else if (sk->protect.s2k.mode == 1002) {
1094 /* Key is stored on an external token (card) or handled by
1095 the gpg-agent. Print the serial number of that token
1096 here. */
1097 for (i=0; i < sk->protect.ivlen; i++)
1098 printf ("%02X", sk->protect.iv[i]);
1100 putchar(':'); /* End of field 15. */
1102 putchar('\n');
1103 if(pk)
1104 print_revokers(pk);
1105 if( fpr )
1106 print_fingerprint( pk, sk, 0 );
1107 if( opt.with_key_data )
1108 print_key_data( pk );
1109 any = 1;
1112 for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
1113 if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) {
1114 PKT_user_id *uid=node->pkt->pkt.user_id;
1115 if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL)
1116 dump_attribs(node->pkt->pkt.user_id,pk,sk);
1118 * Fixme: We need a is_valid flag here too
1120 if( any ) {
1121 char *str=uid->attrib_data?"uat":"uid";
1122 /* If we're listing a secret key, leave out the
1123 validity values for now. This is handled better in
1124 1.9. */
1125 if ( sk )
1126 printf("%s:::::",str);
1127 else if ( uid->is_revoked )
1128 printf("%s:r::::",str);
1129 else if ( uid->is_expired )
1130 printf("%s:e::::",str);
1131 else if ( opt.no_expensive_trust_checks )
1132 printf("%s:::::",str);
1133 else {
1134 int uid_validity;
1136 if( pk && !ulti_hack )
1137 uid_validity=get_validity_info (pk, uid);
1138 else
1139 uid_validity = 'u';
1140 printf("%s:%c::::",str,uid_validity);
1143 printf("%s:",colon_strtime(uid->created));
1144 printf("%s:",colon_strtime(uid->expiredate));
1146 namehash_from_uid(uid);
1148 for(i=0; i < 20; i++ )
1149 printf("%02X",uid->namehash[i]);
1151 printf("::");
1153 if(uid->attrib_data)
1154 printf("%u %lu",uid->numattribs,uid->attrib_len);
1155 else
1156 print_string(stdout,uid->name,uid->len, ':' );
1157 putchar(':');
1158 if (any)
1159 putchar('\n');
1160 else {
1161 putchar(':');
1162 print_capabilities (pk, sk, keyblock);
1163 putchar('\n');
1164 if( fpr )
1165 print_fingerprint( pk, sk, 0 );
1166 if( opt.with_key_data )
1167 print_key_data( pk );
1168 any = 1;
1171 else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1172 u32 keyid2[2];
1173 PKT_public_key *pk2 = node->pkt->pkt.public_key;
1175 if( !any ) {
1176 putchar(':');
1177 putchar(':');
1178 print_capabilities (pk, sk, keyblock);
1179 putchar('\n');
1180 if( fpr )
1181 print_fingerprint( pk, sk, 0 ); /* of the main key */
1182 any = 1;
1185 keyid_from_pk( pk2, keyid2 );
1186 fputs ("sub:", stdout );
1187 if ( !pk2->is_valid )
1188 putchar ('i');
1189 else if ( pk2->is_revoked )
1190 putchar ('r');
1191 else if ( pk2->has_expired )
1192 putchar ('e');
1193 else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1195 else {
1196 /* trustletter should always be defined here */
1197 if(trustletter)
1198 printf("%c", trustletter );
1200 printf(":%u:%d:%08lX%08lX:%s:%s:::::",
1201 nbits_from_pk( pk2 ),
1202 pk2->pubkey_algo,
1203 (ulong)keyid2[0],(ulong)keyid2[1],
1204 colon_datestr_from_pk( pk2 ),
1205 colon_strtime (pk2->expiredate)
1206 /* fixme: add LID and ownertrust here */
1208 print_capabilities (pk2, NULL, NULL);
1209 putchar('\n');
1210 if( fpr > 1 )
1211 print_fingerprint( pk2, NULL, 0 );
1212 if( opt.with_key_data )
1213 print_key_data( pk2 );
1215 else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1216 u32 keyid2[2];
1217 PKT_secret_key *sk2 = node->pkt->pkt.secret_key;
1219 if( !any ) {
1220 putchar(':');
1221 putchar(':');
1222 print_capabilities (pk, sk, keyblock);
1223 putchar('\n');
1224 if( fpr )
1225 print_fingerprint( pk, sk, 0 ); /* of the main key */
1226 any = 1;
1229 keyid_from_sk( sk2, keyid2 );
1230 printf("ssb::%u:%d:%08lX%08lX:%s:%s:::::",
1231 nbits_from_sk( sk2 ),
1232 sk2->pubkey_algo,
1233 (ulong)keyid2[0],(ulong)keyid2[1],
1234 colon_datestr_from_sk( sk2 ),
1235 colon_strtime (sk2->expiredate)
1236 /* fixme: add LID */ );
1237 print_capabilities (NULL, sk2, NULL);
1238 if (opt.fixed_list_mode) {
1239 /* We print the serial number only in fixed list mode
1240 for the primary key so, so avoid questions we print
1241 it for subkeys also only in this mode. There is no
1242 technical reason, though. */
1243 putchar(':'); /* End of field 13. */
1244 putchar(':'); /* End of field 14. */
1245 if (sk2->protect.s2k.mode == 1001)
1246 putchar('#'); /* Key is just a stub. */
1247 else if (sk2->protect.s2k.mode == 1002) {
1248 /* Key is stored on an external token (card) or handled by
1249 the gpg-agent. Print the serial number of that token
1250 here. */
1251 for (i=0; i < sk2->protect.ivlen; i++)
1252 printf ("%02X", sk2->protect.iv[i]);
1254 putchar(':'); /* End of field 15. */
1256 putchar ('\n');
1257 if( fpr > 1 )
1258 print_fingerprint( NULL, sk2, 0 );
1260 else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) {
1261 PKT_signature *sig = node->pkt->pkt.signature;
1262 int sigrc,fprokay=0;
1263 char *sigstr;
1264 size_t fplen;
1265 byte fparray[MAX_FINGERPRINT_LEN];
1267 if( !any ) { /* no user id, (maybe a revocation follows)*/
1268 if( sig->sig_class == 0x20 )
1269 fputs("[revoked]:", stdout);
1270 else if( sig->sig_class == 0x18 )
1271 fputs("[key binding]:", stdout);
1272 else if( sig->sig_class == 0x28 )
1273 fputs("[subkey revoked]:", stdout);
1274 else
1275 putchar (':');
1276 putchar(':');
1277 print_capabilities (pk, sk, keyblock);
1278 putchar('\n');
1279 if( fpr )
1280 print_fingerprint( pk, sk, 0 );
1281 any=1;
1284 if( sig->sig_class == 0x20 || sig->sig_class == 0x28
1285 || sig->sig_class == 0x30 )
1286 sigstr = "rev";
1287 else if( (sig->sig_class&~3) == 0x10 )
1288 sigstr = "sig";
1289 else if( sig->sig_class == 0x18 )
1290 sigstr = "sig";
1291 else if( sig->sig_class == 0x1F )
1292 sigstr = "sig";
1293 else {
1294 printf ("sig::::::::::%02x%c:\n",
1295 sig->sig_class, sig->flags.exportable?'x':'l');
1296 continue;
1298 if( opt.check_sigs ) {
1299 PKT_public_key *signer_pk=NULL;
1301 fflush(stdout);
1302 if(opt.no_sig_cache)
1303 signer_pk=xmalloc_clear(sizeof(PKT_public_key));
1305 rc = check_key_signature2( keyblock, node, NULL, signer_pk,
1306 NULL, NULL, NULL );
1307 switch ( gpg_err_code (rc) ) {
1308 case 0: sigrc = '!'; break;
1309 case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break;
1310 case GPG_ERR_NO_PUBKEY:
1311 case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break;
1312 default: sigrc = '%'; break;
1315 if(opt.no_sig_cache)
1317 if(rc==0)
1319 fingerprint_from_pk (signer_pk, fparray, &fplen);
1320 fprokay=1;
1322 free_public_key(signer_pk);
1325 else {
1326 rc = 0;
1327 sigrc = ' ';
1329 fputs( sigstr, stdout );
1330 putchar(':');
1331 if( sigrc != ' ' )
1332 putchar(sigrc);
1333 printf("::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo,
1334 (ulong)sig->keyid[0], (ulong)sig->keyid[1],
1335 colon_datestr_from_sig(sig),
1336 colon_expirestr_from_sig(sig));
1338 if(sig->trust_depth || sig->trust_value)
1339 printf("%d %d",sig->trust_depth,sig->trust_value);
1340 printf(":");
1342 if(sig->trust_regexp)
1343 print_string(stdout,sig->trust_regexp,
1344 strlen(sig->trust_regexp),':');
1345 printf(":");
1347 if( sigrc == '%' )
1348 printf("[%s] ", g10_errstr(rc) );
1349 else if( sigrc == '?' )
1351 else if ( !opt.fast_list_mode ) {
1352 size_t n;
1353 char *p = get_user_id( sig->keyid, &n );
1354 print_string( stdout, p, n, ':' );
1355 xfree(p);
1357 printf(":%02x%c:", sig->sig_class,sig->flags.exportable?'x':'l');
1359 if(opt.no_sig_cache && opt.check_sigs && fprokay)
1361 printf(":");
1363 for (i=0; i < fplen ; i++ )
1364 printf ("%02X", fparray[i] );
1366 printf(":");
1369 printf("\n");
1371 if(opt.show_subpackets)
1372 print_subpackets_colon(sig);
1374 /* fixme: check or list other sigs here */
1377 if( !any ) {/* oops, no user id */
1378 putchar(':');
1379 putchar(':');
1380 print_capabilities (pk, sk, keyblock);
1381 putchar('\n');
1386 * Reorder the keyblock so that the primary user ID (and not attribute
1387 * packet) comes first. Fixme: Replace this by a generic sort
1388 * function. */
1389 static void
1390 do_reorder_keyblock (KBNODE keyblock,int attr)
1392 KBNODE primary = NULL, primary0 = NULL, primary2 = NULL;
1393 KBNODE last, node;
1395 for (node=keyblock; node; primary0=node, node = node->next) {
1396 if( node->pkt->pkttype == PKT_USER_ID &&
1397 ((attr && node->pkt->pkt.user_id->attrib_data) ||
1398 (!attr && !node->pkt->pkt.user_id->attrib_data)) &&
1399 node->pkt->pkt.user_id->is_primary ) {
1400 primary = primary2 = node;
1401 for (node=node->next; node; primary2=node, node = node->next ) {
1402 if( node->pkt->pkttype == PKT_USER_ID
1403 || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1404 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1405 break;
1408 break;
1411 if ( !primary )
1412 return; /* no primary key flag found (should not happen) */
1414 for (last=NULL, node=keyblock; node; last = node, node = node->next) {
1415 if( node->pkt->pkttype == PKT_USER_ID )
1416 break;
1418 assert (node);
1419 assert (last); /* the user ID is never the first packet */
1420 assert (primary0); /* ditto (this is the node before primary) */
1421 if ( node == primary )
1422 return; /* already the first one */
1424 last->next = primary;
1425 primary0->next = primary2->next;
1426 primary2->next = node;
1429 void
1430 reorder_keyblock (KBNODE keyblock)
1432 do_reorder_keyblock(keyblock,1);
1433 do_reorder_keyblock(keyblock,0);
1436 void
1437 list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque )
1439 reorder_keyblock (keyblock);
1440 if (opt.with_colons)
1441 list_keyblock_colon (keyblock, secret, fpr );
1442 else
1443 list_keyblock_print (keyblock, secret, fpr, opaque );
1447 * standard function to print the finperprint.
1448 * mode 0: as used in key listings, opt.with_colons is honored
1449 * 1: print using log_info ()
1450 * 2: direct use of tty
1451 * 3: direct use of tty but only primary key.
1452 * modes 1 and 2 will try and print both subkey and primary key fingerprints
1454 void
1455 print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode )
1457 byte array[MAX_FINGERPRINT_LEN], *p;
1458 size_t i, n;
1459 FILE *fp;
1460 const char *text;
1461 int primary=0;
1463 if(sk)
1465 if(sk->main_keyid[0]==sk->keyid[0] && sk->main_keyid[1]==sk->keyid[1])
1466 primary=1;
1468 else
1470 if(pk->main_keyid[0]==pk->keyid[0] && pk->main_keyid[1]==pk->keyid[1])
1471 primary=1;
1474 /* Just to be safe */
1475 if(mode&0x80 && !primary)
1477 log_error("primary key is not really primary!\n");
1478 return;
1481 mode&=~0x80;
1483 if(!primary && (mode==1 || mode==2))
1485 if(sk)
1487 PKT_secret_key *primary_sk=xmalloc_clear(sizeof(*primary_sk));
1488 get_seckey(primary_sk,sk->main_keyid);
1489 print_fingerprint(NULL,primary_sk,mode|0x80);
1490 free_secret_key(primary_sk);
1492 else
1494 PKT_public_key *primary_pk=xmalloc_clear(sizeof(*primary_pk));
1495 get_pubkey(primary_pk,pk->main_keyid);
1496 print_fingerprint(primary_pk,NULL,mode|0x80);
1497 free_public_key(primary_pk);
1501 if (mode == 1) {
1502 fp = log_get_stream ();
1503 if(primary)
1504 text = _("Primary key fingerprint:");
1505 else
1506 text = _(" Subkey fingerprint:");
1508 else if (mode == 2) {
1509 fp = NULL; /* use tty */
1510 if(primary)
1511 /* TRANSLATORS: this should fit into 24 bytes to that the
1512 * fingerprint data is properly aligned with the user ID */
1513 text = _(" Primary key fingerprint:");
1514 else
1515 text = _(" Subkey fingerprint:");
1517 else if (mode == 3) {
1518 fp = NULL; /* use tty */
1519 text = _(" Key fingerprint =");
1521 else {
1522 fp = stdout;
1523 text = _(" Key fingerprint =");
1526 if (sk)
1527 fingerprint_from_sk (sk, array, &n);
1528 else
1529 fingerprint_from_pk (pk, array, &n);
1530 p = array;
1531 if (opt.with_colons && !mode) {
1532 fprintf (fp, "fpr:::::::::");
1533 for (i=0; i < n ; i++, p++ )
1534 fprintf (fp, "%02X", *p );
1535 putc(':', fp);
1537 else {
1538 if (fp)
1539 fputs (text, fp);
1540 else
1541 tty_printf ("%s", text);
1542 if (n == 20) {
1543 for (i=0; i < n ; i++, i++, p += 2 ) {
1544 if (fp) {
1545 if (i == 10 )
1546 putc(' ', fp);
1547 fprintf (fp, " %02X%02X", *p, p[1] );
1549 else {
1550 if (i == 10 )
1551 tty_printf (" ");
1552 tty_printf (" %02X%02X", *p, p[1]);
1556 else {
1557 for (i=0; i < n ; i++, p++ ) {
1558 if (fp) {
1559 if (i && !(i%8) )
1560 putc (' ', fp);
1561 fprintf (fp, " %02X", *p );
1563 else {
1564 if (i && !(i%8) )
1565 tty_printf (" ");
1566 tty_printf (" %02X", *p );
1571 if (fp)
1572 putc ('\n', fp);
1573 else
1574 tty_printf ("\n");
1577 /* Print the serial number of an OpenPGP card if available. */
1578 static void
1579 print_card_serialno (PKT_secret_key *sk)
1581 int i;
1583 if (!sk)
1584 return;
1585 if (!sk->is_protected || sk->protect.s2k.mode != 1002)
1586 return; /* Not a card. */
1587 if (opt.with_colons)
1588 return; /* Handled elsewhere. */
1590 fputs (_(" Card serial no. ="), stdout);
1591 putchar (' ');
1592 if (sk->protect.ivlen == 16
1593 && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6) )
1594 { /* This is an OpenPGP card. Just print the relevant part. */
1595 for (i=8; i < 14; i++)
1597 if (i == 10)
1598 putchar (' ');
1599 printf ("%02X", sk->protect.iv[i]);
1602 else
1603 { /* Something is wrong: Print all. */
1604 for (i=0; i < sk->protect.ivlen; i++)
1605 printf ("%02X", sk->protect.iv[i]);
1607 putchar ('\n');
1612 void set_attrib_fd(int fd)
1614 static int last_fd=-1;
1616 if ( fd != -1 && last_fd == fd )
1617 return;
1619 if ( attrib_fp && attrib_fp != stdout && attrib_fp != stderr )
1620 fclose (attrib_fp);
1621 attrib_fp = NULL;
1622 if ( fd == -1 )
1623 return;
1625 if( fd == 1 )
1626 attrib_fp = stdout;
1627 else if( fd == 2 )
1628 attrib_fp = stderr;
1629 else
1630 attrib_fp = fdopen( fd, "wb" );
1631 if( !attrib_fp ) {
1632 log_fatal("can't open fd %d for attribute output: %s\n",
1633 fd, strerror(errno));
1636 last_fd = fd;