* keyserver.c (path_makes_direct): New. (keyserver_spawn): Used here
[gnupg.git] / g10 / keylist.c
blob19f3d3f6286fb19a8dc85d9e00355a456af7128e
1 /* keylist.c
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 2 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, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <assert.h>
30 #include "options.h"
31 #include "packet.h"
32 #include "errors.h"
33 #include "keydb.h"
34 #include "memory.h"
35 #include "photoid.h"
36 #include "util.h"
37 #include "ttyio.h"
38 #include "trustdb.h"
39 #include "main.h"
40 #include "i18n.h"
41 #include "status.h"
43 static void list_all(int);
44 static void list_one( STRLIST names, int secret);
45 static void print_card_serialno (PKT_secret_key *sk);
47 struct sig_stats
49 int inv_sigs;
50 int no_key;
51 int oth_err;
54 static FILE *attrib_fp=NULL;
56 /****************
57 * List the keys
58 * If list is NULL, all available keys are listed
60 void
61 public_key_list( STRLIST list )
63 if(opt.with_colons)
65 byte trust_model,marginals,completes,cert_depth;
66 ulong created,nextcheck;
68 read_trust_options(&trust_model,&created,&nextcheck,
69 &marginals,&completes,&cert_depth);
71 printf("tru:");
73 if(nextcheck && nextcheck <= make_timestamp())
74 printf("o");
75 if(trust_model!=opt.trust_model)
76 printf("t");
77 if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC)
79 if(marginals!=opt.marginals_needed)
80 printf("m");
81 if(completes!=opt.completes_needed)
82 printf("c");
83 if(cert_depth!=opt.max_cert_depth)
84 printf("d");
87 printf(":%d:%lu:%lu",trust_model,created,nextcheck);
89 /* Only show marginals, completes, and cert_depth in the classic
90 or PGP trust models since they are not meaningful
91 otherwise. */
93 if(trust_model==TM_PGP || trust_model==TM_CLASSIC)
94 printf(":%d:%d:%d",marginals,completes,cert_depth);
96 printf("\n");
99 /* We need to do the stale check right here because it might need to
100 update the keyring while we already have the keyring open. This
101 is very bad for W32 because of a sharing violation. For real OSes
102 it might lead to false results if we are later listing a keyring
103 which is associated with the inode of a deleted file. */
104 check_trustdb_stale ();
106 if( !list )
107 list_all(0);
108 else
109 list_one( list, 0 );
112 void
113 secret_key_list( STRLIST list )
115 check_trustdb_stale ();
117 if( !list )
118 list_all(1);
119 else /* List by user id */
120 list_one( list, 1 );
123 void
124 print_seckey_info (PKT_secret_key *sk)
126 u32 keyid[2];
127 char *p;
129 keyid_from_sk (sk, keyid);
130 p=get_user_id_native(keyid);
132 tty_printf ("\nsec %4u%c/%s %s %s\n",
133 nbits_from_sk (sk),
134 pubkey_letter (sk->pubkey_algo),
135 keystr(keyid), datestr_from_sk (sk), p);
137 xfree (p);
140 /* Print information about the public key. With FP passed as NULL,
141 the tty output interface is used, otherwise output is directted to
142 the given stream. */
143 void
144 print_pubkey_info (FILE *fp, PKT_public_key *pk)
146 u32 keyid[2];
147 char *p;
149 keyid_from_pk (pk, keyid);
151 /* If the pk was chosen by a particular user ID, that is the one to
152 print. */
153 if(pk->user_id)
154 p=utf8_to_native(pk->user_id->name,pk->user_id->len,0);
155 else
156 p=get_user_id_native(keyid);
158 if (fp)
159 fprintf (fp, "pub %4u%c/%s %s %s\n",
160 nbits_from_pk (pk),
161 pubkey_letter (pk->pubkey_algo),
162 keystr(keyid), datestr_from_pk (pk), p);
163 else
164 tty_printf ("\npub %4u%c/%s %s %s\n",
165 nbits_from_pk (pk), pubkey_letter (pk->pubkey_algo),
166 keystr(keyid), datestr_from_pk (pk), p);
168 xfree (p);
172 /* Print basic information of a secret key including the card serial
173 number information. */
174 void
175 print_card_key_info (FILE *fp, KBNODE keyblock)
177 KBNODE node;
178 int i;
180 for (node = keyblock; node; node = node->next )
182 if (node->pkt->pkttype == PKT_SECRET_KEY
183 || (node->pkt->pkttype == PKT_SECRET_SUBKEY) )
185 PKT_secret_key *sk = node->pkt->pkt.secret_key;
187 tty_fprintf (fp, "%s%c %4u%c/%s ",
188 node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
189 (sk->protect.s2k.mode==1001)?'#':
190 (sk->protect.s2k.mode==1002)?'>':' ',
191 nbits_from_sk (sk),
192 pubkey_letter (sk->pubkey_algo),
193 keystr_from_sk(sk));
194 tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk));
195 tty_fprintf (fp, " ");
196 tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk));
197 if (sk->is_protected && sk->protect.s2k.mode == 1002)
199 tty_fprintf (fp, "\n ");
200 tty_fprintf (fp, _("card-no: "));
201 if (sk->protect.ivlen == 16
202 && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6))
204 /* This is an OpenPGP card. */
205 for (i=8; i < 14; i++)
207 if (i == 10)
208 tty_fprintf (fp, " ");
209 tty_fprintf (fp, "%02X", sk->protect.iv[i]);
212 else
213 { /* Something is wrong: Print all. */
214 for (i=0; i < sk->protect.ivlen; i++)
215 tty_fprintf (fp, "%02X", sk->protect.iv[i]);
218 tty_fprintf (fp, "\n");
225 /* Flags = 0x01 hashed 0x02 critical */
226 static void
227 status_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf)
229 char status[40];
231 /* Don't print these. */
232 if(len>256)
233 return;
235 sprintf(status,"%d %u %u ",type,flags,(unsigned int)len);
237 write_status_text_and_buffer(STATUS_SIG_SUBPACKET,status,buf,len,0);
241 mode=0 for stdout.
242 mode=1 for log_info + status messages
243 mode=2 for status messages only
246 void
247 show_policy_url(PKT_signature *sig,int indent,int mode)
249 const byte *p;
250 size_t len;
251 int seq=0,crit;
252 FILE *fp=mode?log_stream():stdout;
254 while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,&len,&seq,&crit)))
256 if(mode!=2)
258 int i;
259 const char *str;
261 for(i=0;i<indent;i++)
262 putchar(' ');
264 if(crit)
265 str=_("Critical signature policy: ");
266 else
267 str=_("Signature policy: ");
268 if(mode)
269 log_info("%s",str);
270 else
271 printf("%s",str);
272 print_utf8_string(fp,p,len);
273 fprintf(fp,"\n");
276 if(mode)
277 write_status_buffer ( STATUS_POLICY_URL, p, len, 0 );
282 mode=0 for stdout.
283 mode=1 for log_info + status messages
284 mode=2 for status messages only
286 /* TODO: use this */
287 void
288 show_keyserver_url(PKT_signature *sig,int indent,int mode)
290 const byte *p;
291 size_t len;
292 int seq=0,crit;
293 FILE *fp=mode?log_stream():stdout;
295 while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&len,&seq,&crit)))
297 if(mode!=2)
299 int i;
300 const char *str;
302 for(i=0;i<indent;i++)
303 putchar(' ');
305 if(crit)
306 str=_("Critical preferred keyserver: ");
307 else
308 str=_("Preferred keyserver: ");
309 if(mode)
310 log_info("%s",str);
311 else
312 printf("%s",str);
313 print_utf8_string(fp,p,len);
314 fprintf(fp,"\n");
317 if(mode)
318 status_one_subpacket(SIGSUBPKT_PREF_KS,len,(crit?0x02:0)|0x01,p);
323 mode=0 for stdout.
324 mode=1 for log_info + status messages
325 mode=2 for status messages only
327 which bits:
328 1 == standard notations
329 2 == user notations
332 void
333 show_notation(PKT_signature *sig,int indent,int mode,int which)
335 FILE *fp=mode?log_stream():stdout;
336 struct notation *nd,*notations;
338 if(which==0)
339 which=3;
341 notations=sig_to_notation(sig);
343 /* There may be multiple notations in the same sig. */
344 for(nd=notations;nd;nd=nd->next)
346 if(mode!=2)
348 int has_at=!!strchr(nd->name,'@');
350 if((which&1 && !has_at) || (which&2 && has_at))
352 int i;
353 const char *str;
355 for(i=0;i<indent;i++)
356 putchar(' ');
358 if(nd->flags.critical)
359 str=_("Critical signature notation: ");
360 else
361 str=_("Signature notation: ");
362 if(mode)
363 log_info("%s",str);
364 else
365 printf("%s",str);
366 /* This is all UTF8 */
367 print_utf8_string(fp,nd->name,strlen(nd->name));
368 fprintf(fp,"=");
369 print_utf8_string(fp,nd->value,strlen(nd->value));
370 fprintf(fp,"\n");
374 if(mode)
376 write_status_buffer(STATUS_NOTATION_NAME,
377 nd->name,strlen(nd->name),0);
378 write_status_buffer(STATUS_NOTATION_DATA,
379 nd->value,strlen(nd->value),50);
383 free_notation(notations);
386 static void
387 print_signature_stats(struct sig_stats *s)
389 if( s->inv_sigs == 1 )
390 tty_printf(_("1 bad signature\n") );
391 else if( s->inv_sigs )
392 tty_printf(_("%d bad signatures\n"), s->inv_sigs );
393 if( s->no_key == 1 )
394 tty_printf(_("1 signature not checked due to a missing key\n") );
395 else if( s->no_key )
396 tty_printf(_("%d signatures not checked due to missing keys\n"),s->no_key);
397 if( s->oth_err == 1 )
398 tty_printf(_("1 signature not checked due to an error\n") );
399 else if( s->oth_err )
400 tty_printf(_("%d signatures not checked due to errors\n"), s->oth_err );
403 static void
404 list_all( int secret )
406 KEYDB_HANDLE hd;
407 KBNODE keyblock = NULL;
408 int rc=0;
409 const char *lastresname, *resname;
410 struct sig_stats stats;
412 memset(&stats,0,sizeof(stats));
414 hd = keydb_new (secret);
415 if (!hd)
416 rc = G10ERR_GENERAL;
417 else
418 rc = keydb_search_first (hd);
419 if( rc ) {
420 if( rc != -1 )
421 log_error("keydb_search_first failed: %s\n", g10_errstr(rc) );
422 goto leave;
425 lastresname = NULL;
426 do {
427 rc = keydb_get_keyblock (hd, &keyblock);
428 if (rc) {
429 log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc));
430 goto leave;
432 if(!opt.with_colons)
434 resname = keydb_get_resource_name (hd);
435 if (lastresname != resname )
437 int i;
439 printf("%s\n", resname );
440 for(i=strlen(resname); i; i-- )
441 putchar('-');
442 putchar('\n');
443 lastresname = resname;
446 merge_keys_and_selfsig( keyblock );
447 list_keyblock( keyblock, secret, opt.fingerprint,
448 opt.check_sigs?&stats:NULL);
449 release_kbnode( keyblock );
450 keyblock = NULL;
451 } while (!(rc = keydb_search_next (hd)));
452 if( rc && rc != -1 )
453 log_error ("keydb_search_next failed: %s\n", g10_errstr(rc));
455 if(opt.check_sigs && !opt.with_colons)
456 print_signature_stats(&stats);
458 leave:
459 release_kbnode (keyblock);
460 keydb_release (hd);
464 static void
465 list_one( STRLIST names, int secret )
467 int rc = 0;
468 KBNODE keyblock = NULL;
469 GETKEY_CTX ctx;
470 const char *resname;
471 const char *keyring_str = _("Keyring");
472 int i;
473 struct sig_stats stats;
475 memset(&stats,0,sizeof(stats));
477 /* fixme: using the bynames function has the disadvantage that we
478 * don't know wether one of the names given was not found. OTOH,
479 * this function has the advantage to list the names in the
480 * sequence as defined by the keyDB and does not duplicate
481 * outputs. A solution could be do test whether all given have
482 * been listed (this needs a way to use the keyDB search
483 * functions) or to have the search function return indicators for
484 * found names. Yet another way is to use the keydb search
485 * facilities directly. */
486 if( secret ) {
487 rc = get_seckey_bynames( &ctx, NULL, names, &keyblock );
488 if( rc ) {
489 log_error("error reading key: %s\n", g10_errstr(rc) );
490 get_seckey_end( ctx );
491 return;
493 do {
494 if ((opt.list_options&LIST_SHOW_KEYRING) && !opt.with_colons) {
495 resname = keydb_get_resource_name (get_ctx_handle(ctx));
496 printf("%s: %s\n", keyring_str, resname);
497 for(i = strlen(resname) + strlen(keyring_str) + 2; i; i-- )
498 putchar('-');
499 putchar('\n');
501 list_keyblock( keyblock, 1, opt.fingerprint, NULL );
502 release_kbnode( keyblock );
503 } while( !get_seckey_next( ctx, NULL, &keyblock ) );
504 get_seckey_end( ctx );
506 else {
507 rc = get_pubkey_bynames( &ctx, NULL, names, &keyblock );
508 if( rc ) {
509 log_error("error reading key: %s\n", g10_errstr(rc) );
510 get_pubkey_end( ctx );
511 return;
513 do {
514 if ((opt.list_options&LIST_SHOW_KEYRING) && !opt.with_colons) {
515 resname = keydb_get_resource_name (get_ctx_handle(ctx));
516 printf("%s: %s\n", keyring_str, resname);
517 for(i = strlen(resname) + strlen(keyring_str) + 2; i; i-- )
518 putchar('-');
519 putchar('\n');
521 list_keyblock( keyblock, 0, opt.fingerprint,
522 opt.check_sigs?&stats:NULL );
523 release_kbnode( keyblock );
524 } while( !get_pubkey_next( ctx, NULL, &keyblock ) );
525 get_pubkey_end( ctx );
528 if(opt.check_sigs && !opt.with_colons)
529 print_signature_stats(&stats);
532 static void
533 print_key_data( PKT_public_key *pk )
535 int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
536 int i;
538 for(i=0; i < n; i++ ) {
539 printf("pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
540 mpi_print(stdout, pk->pkey[i], 1 );
541 putchar(':');
542 putchar('\n');
546 static void
547 print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock)
549 if(pk || (sk && sk->protect.s2k.mode!=1001))
551 unsigned int use = pk? pk->pubkey_usage : sk->pubkey_usage;
553 if ( use & PUBKEY_USAGE_ENC )
554 putchar ('e');
556 if ( use & PUBKEY_USAGE_SIG )
558 putchar ('s');
559 if( pk? pk->is_primary : sk->is_primary )
560 putchar ('c');
563 if ( (use & PUBKEY_USAGE_AUTH) )
564 putchar ('a');
567 if ( keyblock ) { /* figure out the usable capabilities */
568 KBNODE k;
569 int enc=0, sign=0, cert=0, auth=0, disabled=0;
571 for (k=keyblock; k; k = k->next ) {
572 if ( k->pkt->pkttype == PKT_PUBLIC_KEY
573 || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
574 pk = k->pkt->pkt.public_key;
576 if(pk->is_primary)
577 disabled=pk_is_disabled(pk);
579 if ( pk->is_valid && !pk->is_revoked && !pk->has_expired ) {
580 if ( pk->pubkey_usage & PUBKEY_USAGE_ENC )
581 enc = 1;
582 if ( pk->pubkey_usage & PUBKEY_USAGE_SIG )
584 sign = 1;
585 if(pk->is_primary)
586 cert = 1;
588 if ( (pk->pubkey_usage & PUBKEY_USAGE_AUTH) )
589 auth = 1;
592 else if ( k->pkt->pkttype == PKT_SECRET_KEY
593 || k->pkt->pkttype == PKT_SECRET_SUBKEY ) {
594 sk = k->pkt->pkt.secret_key;
595 if ( sk->is_valid && !sk->is_revoked && !sk->has_expired
596 && sk->protect.s2k.mode!=1001 ) {
597 if ( sk->pubkey_usage & PUBKEY_USAGE_ENC )
598 enc = 1;
599 if ( sk->pubkey_usage & PUBKEY_USAGE_SIG )
601 sign = 1;
602 if(sk->is_primary)
603 cert = 1;
605 if ( (sk->pubkey_usage & PUBKEY_USAGE_AUTH) )
606 auth = 1;
610 if (enc)
611 putchar ('E');
612 if (sign)
613 putchar ('S');
614 if (cert)
615 putchar ('C');
616 if (auth)
617 putchar ('A');
618 if (disabled)
619 putchar ('D');
622 putchar(':');
625 /* Flags = 0x01 hashed 0x02 critical */
626 static void
627 print_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf)
629 size_t i;
631 printf("spk:%d:%u:%u:",type,flags,(unsigned int)len);
633 for(i=0;i<len;i++)
635 /* printable ascii other than : and % */
636 if(buf[i]>=32 && buf[i]<=126 && buf[i]!=':' && buf[i]!='%')
637 printf("%c",buf[i]);
638 else
639 printf("%%%02X",buf[i]);
642 printf("\n");
645 void
646 print_subpackets_colon(PKT_signature *sig)
648 byte *i;
650 assert(opt.show_subpackets);
652 for(i=opt.show_subpackets;*i;i++)
654 const byte *p;
655 size_t len;
656 int seq,crit;
658 seq=0;
660 while((p=enum_sig_subpkt(sig->hashed,*i,&len,&seq,&crit)))
661 print_one_subpacket(*i,len,0x01|(crit?0x02:0),p);
663 seq=0;
665 while((p=enum_sig_subpkt(sig->unhashed,*i,&len,&seq,&crit)))
666 print_one_subpacket(*i,len,0x00|(crit?0x02:0),p);
670 void
671 dump_attribs(const PKT_user_id *uid,PKT_public_key *pk,PKT_secret_key *sk)
673 int i;
675 if(!attrib_fp)
676 return;
678 for(i=0;i<uid->numattribs;i++)
680 if(is_status_enabled())
682 byte array[MAX_FINGERPRINT_LEN], *p;
683 char buf[(MAX_FINGERPRINT_LEN*2)+90];
684 size_t j,n;
686 if(pk)
687 fingerprint_from_pk( pk, array, &n );
688 else if(sk)
689 fingerprint_from_sk( sk, array, &n );
690 else
691 BUG();
693 p = array;
694 for(j=0; j < n ; j++, p++ )
695 sprintf(buf+2*j, "%02X", *p );
697 sprintf(buf+strlen(buf)," %lu %u %u %u %lu %lu %u",
698 (ulong)uid->attribs[i].len,uid->attribs[i].type,i+1,
699 uid->numattribs,(ulong)uid->created,(ulong)uid->expiredate,
700 ((uid->is_primary?0x01:0)|
701 (uid->is_revoked?0x02:0)|
702 (uid->is_expired?0x04:0)));
703 write_status_text(STATUS_ATTRIBUTE,buf);
706 fwrite(uid->attribs[i].data,uid->attribs[i].len,1,attrib_fp);
710 static void
711 list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
713 int rc = 0;
714 KBNODE kbctx;
715 KBNODE node;
716 PKT_public_key *pk;
717 PKT_secret_key *sk;
718 struct sig_stats *stats=opaque;
719 int skip_sigs=0;
721 /* get the keyid from the keyblock */
722 node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
723 if( !node ) {
724 log_error("Oops; key lost!\n");
725 dump_kbnode( keyblock );
726 return;
729 if( secret )
731 pk = NULL;
732 sk = node->pkt->pkt.secret_key;
734 printf("sec%c %4u%c/%s %s",(sk->protect.s2k.mode==1001)?'#':
735 (sk->protect.s2k.mode==1002)?'>':' ',
736 nbits_from_sk( sk ),pubkey_letter( sk->pubkey_algo ),
737 keystr_from_sk(sk),datestr_from_sk( sk ));
739 if(sk->has_expired)
741 printf(" [");
742 printf(_("expired: %s"),expirestr_from_sk(sk));
743 printf("]");
745 else if(sk->expiredate )
747 printf(" [");
748 printf(_("expires: %s"),expirestr_from_sk(sk));
749 printf("]");
752 printf("\n");
754 else
756 pk = node->pkt->pkt.public_key;
757 sk = NULL;
759 check_trustdb_stale();
761 printf("pub %4u%c/%s %s",
762 nbits_from_pk(pk),pubkey_letter(pk->pubkey_algo),
763 keystr_from_pk(pk),datestr_from_pk( pk ));
765 /* We didn't include this before in the key listing, but there
766 is room in the new format, so why not? */
768 if(pk->is_revoked)
770 printf(" [");
771 printf(_("revoked: %s"),revokestr_from_pk(pk));
772 printf("]");
774 else if(pk->has_expired)
776 printf(" [");
777 printf(_("expired: %s"),expirestr_from_pk(pk));
778 printf("]");
780 else if(pk->expiredate)
782 printf(" [");
783 printf(_("expires: %s"),expirestr_from_pk(pk));
784 printf("]");
787 #if 0
788 /* I need to think about this some more. It's easy enough to
789 include, but it looks sort of confusing in the
790 listing... */
791 if(opt.list_options&LIST_SHOW_VALIDITY)
793 int validity=get_validity(pk,NULL);
794 printf(" [%s]",trust_value_to_string(validity));
796 #endif
798 printf("\n");
801 if( fpr )
802 print_fingerprint( pk, sk, 0 );
803 print_card_serialno (sk);
804 if( opt.with_key_data )
805 print_key_data( pk );
807 for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
808 if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) {
809 PKT_user_id *uid=node->pkt->pkt.user_id;
811 if(pk && (uid->is_expired || uid->is_revoked)
812 && !(opt.list_options&LIST_SHOW_UNUSABLE_UIDS))
814 skip_sigs=1;
815 continue;
817 else
818 skip_sigs=0;
820 if(attrib_fp && uid->attrib_data!=NULL)
821 dump_attribs(uid,pk,sk);
823 if((uid->is_revoked || uid->is_expired)
824 || ((opt.list_options&LIST_SHOW_UID_VALIDITY) && pk))
826 const char *validity;
827 int indent;
829 validity=uid_trust_string_fixed(pk,uid);
830 indent=(keystrlen()+9)-atoi(uid_trust_string_fixed(NULL,NULL));
832 if(indent<0 || indent>40)
833 indent=0;
835 printf("uid%*s%s ",indent,"",validity);
837 else
838 printf("uid%*s", (int)keystrlen()+10,"");
840 print_utf8_string( stdout, uid->name, uid->len );
841 putchar('\n');
843 if((opt.list_options&LIST_SHOW_PHOTOS) && uid->attribs!=NULL)
844 show_photos(uid->attribs,uid->numattribs,pk,sk);
846 else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
848 PKT_public_key *pk2 = node->pkt->pkt.public_key;
850 if((pk2->is_revoked || pk2->has_expired)
851 && !(opt.list_options&LIST_SHOW_UNUSABLE_SUBKEYS))
853 skip_sigs=1;
854 continue;
856 else
857 skip_sigs=0;
859 printf("sub %4u%c/%s %s",
860 nbits_from_pk( pk2 ),pubkey_letter( pk2->pubkey_algo ),
861 keystr_from_pk(pk2),datestr_from_pk(pk2));
862 if( pk2->is_revoked )
864 printf(" [");
865 printf(_("revoked: %s"),revokestr_from_pk(pk2));
866 printf("]");
868 else if( pk2->has_expired )
870 printf(" [");
871 printf(_("expired: %s"),expirestr_from_pk(pk2));
872 printf("]");
874 else if( pk2->expiredate )
876 printf(" [");
877 printf(_("expires: %s"),expirestr_from_pk(pk2));
878 printf("]");
880 putchar('\n');
881 if( fpr > 1 )
882 print_fingerprint( pk2, NULL, 0 );
883 if( opt.with_key_data )
884 print_key_data( pk2 );
886 else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
888 PKT_secret_key *sk2 = node->pkt->pkt.secret_key;
890 printf("ssb%c %4u%c/%s %s",
891 (sk2->protect.s2k.mode==1001)?'#':
892 (sk2->protect.s2k.mode==1002)?'>':' ',
893 nbits_from_sk( sk2 ),pubkey_letter( sk2->pubkey_algo ),
894 keystr_from_sk(sk2),datestr_from_sk( sk2 ) );
895 if( sk2->expiredate )
897 printf(" [");
898 printf(_("expires: %s"),expirestr_from_sk(sk2));
899 printf("]");
901 putchar('\n');
902 if( fpr > 1 )
904 print_fingerprint( NULL, sk2, 0 );
905 print_card_serialno (sk2);
908 else if( opt.list_sigs
909 && node->pkt->pkttype == PKT_SIGNATURE
910 && !skip_sigs ) {
911 PKT_signature *sig = node->pkt->pkt.signature;
912 int sigrc;
913 char *sigstr;
915 if( stats ) {
916 /*fflush(stdout);*/
917 rc = check_key_signature( keyblock, node, NULL );
918 switch( rc ) {
919 case 0: sigrc = '!'; break;
920 case G10ERR_BAD_SIGN: stats->inv_sigs++; sigrc = '-'; break;
921 case G10ERR_NO_PUBKEY:
922 case G10ERR_UNU_PUBKEY: stats->no_key++; continue;
923 default: stats->oth_err++; sigrc = '%'; break;
926 /* TODO: Make sure a cached sig record here still has
927 the pk that issued it. See also
928 keyedit.c:print_and_check_one_sig */
930 else {
931 rc = 0;
932 sigrc = ' ';
935 if( sig->sig_class == 0x20 || sig->sig_class == 0x28
936 || sig->sig_class == 0x30 )
937 sigstr = "rev";
938 else if( (sig->sig_class&~3) == 0x10 )
939 sigstr = "sig";
940 else if( sig->sig_class == 0x18 )
941 sigstr = "sig";
942 else if( sig->sig_class == 0x1F )
943 sigstr = "sig";
944 else {
945 printf("sig "
946 "[unexpected signature class 0x%02x]\n",sig->sig_class );
947 continue;
950 fputs( sigstr, stdout );
951 printf("%c%c %c%c%c%c%c%c %s %s",
952 sigrc,(sig->sig_class-0x10>0 &&
953 sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ',
954 sig->flags.exportable?' ':'L',
955 sig->flags.revocable?' ':'R',
956 sig->flags.policy_url?'P':' ',
957 sig->flags.notation?'N':' ',
958 sig->flags.expired?'X':' ',
959 (sig->trust_depth>9)?'T':
960 (sig->trust_depth>0)?'0'+sig->trust_depth:' ',
961 keystr(sig->keyid),datestr_from_sig(sig));
962 if(opt.list_options&LIST_SHOW_SIG_EXPIRE)
963 printf(" %s", expirestr_from_sig(sig));
964 printf(" ");
965 if( sigrc == '%' )
966 printf("[%s] ", g10_errstr(rc) );
967 else if( sigrc == '?' )
969 else if ( !opt.fast_list_mode ) {
970 size_t n;
971 char *p = get_user_id( sig->keyid, &n );
972 print_utf8_string( stdout, p, n );
973 xfree(p);
975 putchar('\n');
977 if(sig->flags.policy_url
978 && (opt.list_options&LIST_SHOW_POLICY_URLS))
979 show_policy_url(sig,3,0);
981 if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATIONS))
982 show_notation(sig,3,0,
983 ((opt.list_options&LIST_SHOW_STD_NOTATIONS)?1:0)+
984 ((opt.list_options&LIST_SHOW_USER_NOTATIONS)?2:0));
986 if(sig->flags.pref_ks
987 && (opt.list_options&LIST_SHOW_KEYSERVER_URLS))
988 show_keyserver_url(sig,3,0);
990 /* fixme: check or list other sigs here */
993 putchar('\n');
996 void
997 print_revokers(PKT_public_key *pk)
999 /* print the revoker record */
1000 if( !pk->revkey && pk->numrevkeys )
1001 BUG();
1002 else
1004 int i,j;
1006 for (i=0; i < pk->numrevkeys; i++)
1008 byte *p;
1010 printf ("rvk:::%d::::::", pk->revkey[i].algid);
1011 p = pk->revkey[i].fpr;
1012 for (j=0; j < 20; j++, p++ )
1013 printf ("%02X", *p);
1014 printf (":%02x%s:\n", pk->revkey[i].class,
1015 (pk->revkey[i].class&0x40)?"s":"");
1020 static void
1021 list_keyblock_colon( KBNODE keyblock, int secret, int fpr )
1023 int rc = 0;
1024 KBNODE kbctx;
1025 KBNODE node;
1026 PKT_public_key *pk;
1027 PKT_secret_key *sk;
1028 u32 keyid[2];
1029 int any=0;
1030 int trustletter = 0;
1031 int ulti_hack = 0;
1032 int i;
1034 /* get the keyid from the keyblock */
1035 node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
1036 if( !node ) {
1037 log_error("Oops; key lost!\n");
1038 dump_kbnode( keyblock );
1039 return;
1042 if( secret ) {
1043 pk = NULL;
1044 sk = node->pkt->pkt.secret_key;
1045 keyid_from_sk( sk, keyid );
1046 printf("sec::%u:%d:%08lX%08lX:%s:%s:::",
1047 nbits_from_sk( sk ),
1048 sk->pubkey_algo,
1049 (ulong)keyid[0],(ulong)keyid[1],
1050 colon_datestr_from_sk( sk ),
1051 colon_strtime (sk->expiredate)
1052 /* fixme: add LID here */ );
1054 else {
1055 pk = node->pkt->pkt.public_key;
1056 sk = NULL;
1057 keyid_from_pk( pk, keyid );
1058 fputs( "pub:", stdout );
1059 if ( !pk->is_valid )
1060 putchar ('i');
1061 else if ( pk->is_revoked )
1062 putchar ('r');
1063 else if ( pk->has_expired )
1064 putchar ('e');
1065 else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1067 else {
1068 trustletter = get_validity_info ( pk, NULL );
1069 if( trustletter == 'u' )
1070 ulti_hack = 1;
1071 putchar(trustletter);
1073 printf(":%u:%d:%08lX%08lX:%s:%s::",
1074 nbits_from_pk( pk ),
1075 pk->pubkey_algo,
1076 (ulong)keyid[0],(ulong)keyid[1],
1077 colon_datestr_from_pk( pk ),
1078 colon_strtime (pk->expiredate) );
1079 if( !opt.fast_list_mode && !opt.no_expensive_trust_checks )
1080 putchar( get_ownertrust_info(pk) );
1081 putchar(':');
1084 if (opt.fixed_list_mode) {
1085 /* do not merge the first uid with the primary key */
1086 putchar(':');
1087 putchar(':');
1088 print_capabilities (pk, sk, keyblock);
1089 if (secret) {
1090 putchar(':'); /* End of field 13. */
1091 putchar(':'); /* End of field 14. */
1092 if (sk->protect.s2k.mode == 1001)
1093 putchar('#'); /* Key is just a stub. */
1094 else if (sk->protect.s2k.mode == 1002) {
1095 /* Key is stored on an external token (card) or handled by
1096 the gpg-agent. Print the serial number of that token
1097 here. */
1098 for (i=0; i < sk->protect.ivlen; i++)
1099 printf ("%02X", sk->protect.iv[i]);
1101 putchar(':'); /* End of field 15. */
1103 putchar('\n');
1104 if(pk)
1105 print_revokers(pk);
1106 if( fpr )
1107 print_fingerprint( pk, sk, 0 );
1108 if( opt.with_key_data )
1109 print_key_data( pk );
1110 any = 1;
1113 for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
1114 if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) {
1115 PKT_user_id *uid=node->pkt->pkt.user_id;
1116 if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL)
1117 dump_attribs(node->pkt->pkt.user_id,pk,sk);
1119 * Fixme: We need a is_valid flag here too
1121 if( any ) {
1122 char *str=uid->attrib_data?"uat":"uid";
1123 /* If we're listing a secret key, leave out the
1124 validity values for now. This is handled better in
1125 1.9. */
1126 if ( sk )
1127 printf("%s:::::",str);
1128 else if ( uid->is_revoked )
1129 printf("%s:r::::",str);
1130 else if ( uid->is_expired )
1131 printf("%s:e::::",str);
1132 else if ( opt.no_expensive_trust_checks )
1133 printf("%s:::::",str);
1134 else {
1135 int uid_validity;
1137 if( pk && !ulti_hack )
1138 uid_validity=get_validity_info (pk, uid);
1139 else
1140 uid_validity = 'u';
1141 printf("%s:%c::::",str,uid_validity);
1144 printf("%s:",colon_strtime(uid->created));
1145 printf("%s:",colon_strtime(uid->expiredate));
1147 namehash_from_uid(uid);
1149 for(i=0; i < 20; i++ )
1150 printf("%02X",uid->namehash[i]);
1152 printf("::");
1154 if(uid->attrib_data)
1155 printf("%u %lu",uid->numattribs,uid->attrib_len);
1156 else
1157 print_string(stdout,uid->name,uid->len, ':' );
1158 putchar(':');
1159 if (any)
1160 putchar('\n');
1161 else {
1162 putchar(':');
1163 print_capabilities (pk, sk, keyblock);
1164 putchar('\n');
1165 if( fpr )
1166 print_fingerprint( pk, sk, 0 );
1167 if( opt.with_key_data )
1168 print_key_data( pk );
1169 any = 1;
1172 else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1173 u32 keyid2[2];
1174 PKT_public_key *pk2 = node->pkt->pkt.public_key;
1176 if( !any ) {
1177 putchar(':');
1178 putchar(':');
1179 print_capabilities (pk, sk, keyblock);
1180 putchar('\n');
1181 if( fpr )
1182 print_fingerprint( pk, sk, 0 ); /* of the main key */
1183 any = 1;
1186 keyid_from_pk( pk2, keyid2 );
1187 fputs ("sub:", stdout );
1188 if ( !pk2->is_valid )
1189 putchar ('i');
1190 else if ( pk2->is_revoked )
1191 putchar ('r');
1192 else if ( pk2->has_expired )
1193 putchar ('e');
1194 else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1196 else {
1197 /* trustletter should always be defined here */
1198 if(trustletter)
1199 printf("%c", trustletter );
1201 printf(":%u:%d:%08lX%08lX:%s:%s:::::",
1202 nbits_from_pk( pk2 ),
1203 pk2->pubkey_algo,
1204 (ulong)keyid2[0],(ulong)keyid2[1],
1205 colon_datestr_from_pk( pk2 ),
1206 colon_strtime (pk2->expiredate)
1207 /* fixme: add LID and ownertrust here */
1209 print_capabilities (pk2, NULL, NULL);
1210 putchar('\n');
1211 if( fpr > 1 )
1212 print_fingerprint( pk2, NULL, 0 );
1213 if( opt.with_key_data )
1214 print_key_data( pk2 );
1216 else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1217 u32 keyid2[2];
1218 PKT_secret_key *sk2 = node->pkt->pkt.secret_key;
1220 if( !any ) {
1221 putchar(':');
1222 putchar(':');
1223 print_capabilities (pk, sk, keyblock);
1224 putchar('\n');
1225 if( fpr )
1226 print_fingerprint( pk, sk, 0 ); /* of the main key */
1227 any = 1;
1230 keyid_from_sk( sk2, keyid2 );
1231 printf("ssb::%u:%d:%08lX%08lX:%s:%s:::::",
1232 nbits_from_sk( sk2 ),
1233 sk2->pubkey_algo,
1234 (ulong)keyid2[0],(ulong)keyid2[1],
1235 colon_datestr_from_sk( sk2 ),
1236 colon_strtime (sk2->expiredate)
1237 /* fixme: add LID */ );
1238 print_capabilities (NULL, sk2, NULL);
1239 if (opt.fixed_list_mode) {
1240 /* We print the serial number only in fixed list mode
1241 for the primary key so, so avoid questions we print
1242 it for subkeys also only in this mode. There is no
1243 technical reason, though. */
1244 putchar(':'); /* End of field 13. */
1245 putchar(':'); /* End of field 14. */
1246 if (sk2->protect.s2k.mode == 1001)
1247 putchar('#'); /* Key is just a stub. */
1248 else if (sk2->protect.s2k.mode == 1002) {
1249 /* Key is stored on an external token (card) or handled by
1250 the gpg-agent. Print the serial number of that token
1251 here. */
1252 for (i=0; i < sk2->protect.ivlen; i++)
1253 printf ("%02X", sk2->protect.iv[i]);
1255 putchar(':'); /* End of field 15. */
1257 putchar ('\n');
1258 if( fpr > 1 )
1259 print_fingerprint( NULL, sk2, 0 );
1261 else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) {
1262 PKT_signature *sig = node->pkt->pkt.signature;
1263 int sigrc,fprokay=0;
1264 char *sigstr;
1265 size_t fplen;
1266 byte fparray[MAX_FINGERPRINT_LEN];
1268 if( !any ) { /* no user id, (maybe a revocation follows)*/
1269 if( sig->sig_class == 0x20 )
1270 fputs("[revoked]:", stdout);
1271 else if( sig->sig_class == 0x18 )
1272 fputs("[key binding]:", stdout);
1273 else if( sig->sig_class == 0x28 )
1274 fputs("[subkey revoked]:", stdout);
1275 else
1276 putchar (':');
1277 putchar(':');
1278 print_capabilities (pk, sk, keyblock);
1279 putchar('\n');
1280 if( fpr )
1281 print_fingerprint( pk, sk, 0 );
1282 any=1;
1285 if( sig->sig_class == 0x20 || sig->sig_class == 0x28
1286 || sig->sig_class == 0x30 )
1287 sigstr = "rev";
1288 else if( (sig->sig_class&~3) == 0x10 )
1289 sigstr = "sig";
1290 else if( sig->sig_class == 0x18 )
1291 sigstr = "sig";
1292 else if( sig->sig_class == 0x1F )
1293 sigstr = "sig";
1294 else {
1295 printf ("sig::::::::::%02x%c:\n",
1296 sig->sig_class, sig->flags.exportable?'x':'l');
1297 continue;
1299 if( opt.check_sigs ) {
1300 PKT_public_key *signer_pk=NULL;
1302 fflush(stdout);
1303 if(opt.no_sig_cache)
1304 signer_pk=xmalloc_clear(sizeof(PKT_public_key));
1306 rc = check_key_signature2( keyblock, node, NULL, signer_pk,
1307 NULL, NULL, NULL );
1308 switch( rc ) {
1309 case 0: sigrc = '!'; break;
1310 case G10ERR_BAD_SIGN: sigrc = '-'; break;
1311 case G10ERR_NO_PUBKEY:
1312 case G10ERR_UNU_PUBKEY: sigrc = '?'; break;
1313 default: sigrc = '%'; break;
1316 if(opt.no_sig_cache)
1318 if(rc==0)
1320 fingerprint_from_pk (signer_pk, fparray, &fplen);
1321 fprokay=1;
1323 free_public_key(signer_pk);
1326 else {
1327 rc = 0;
1328 sigrc = ' ';
1330 fputs( sigstr, stdout );
1331 putchar(':');
1332 if( sigrc != ' ' )
1333 putchar(sigrc);
1334 printf("::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo,
1335 (ulong)sig->keyid[0], (ulong)sig->keyid[1],
1336 colon_datestr_from_sig(sig),
1337 colon_expirestr_from_sig(sig));
1339 if(sig->trust_depth || sig->trust_value)
1340 printf("%d %d",sig->trust_depth,sig->trust_value);
1341 printf(":");
1343 if(sig->trust_regexp)
1344 print_string(stdout,sig->trust_regexp,
1345 strlen(sig->trust_regexp),':');
1346 printf(":");
1348 if( sigrc == '%' )
1349 printf("[%s] ", g10_errstr(rc) );
1350 else if( sigrc == '?' )
1352 else if ( !opt.fast_list_mode ) {
1353 size_t n;
1354 char *p = get_user_id( sig->keyid, &n );
1355 print_string( stdout, p, n, ':' );
1356 xfree(p);
1358 printf(":%02x%c:", sig->sig_class,sig->flags.exportable?'x':'l');
1360 if(opt.no_sig_cache && opt.check_sigs && fprokay)
1362 printf(":");
1364 for (i=0; i < fplen ; i++ )
1365 printf ("%02X", fparray[i] );
1367 printf(":");
1370 printf("\n");
1372 if(opt.show_subpackets)
1373 print_subpackets_colon(sig);
1375 /* fixme: check or list other sigs here */
1378 if( !any ) {/* oops, no user id */
1379 putchar(':');
1380 putchar(':');
1381 print_capabilities (pk, sk, keyblock);
1382 putchar('\n');
1387 * Reorder the keyblock so that the primary user ID (and not attribute
1388 * packet) comes first. Fixme: Replace this by a generic sort
1389 * function. */
1390 static void
1391 do_reorder_keyblock (KBNODE keyblock,int attr)
1393 KBNODE primary = NULL, primary0 = NULL, primary2 = NULL;
1394 KBNODE last, node;
1396 for (node=keyblock; node; primary0=node, node = node->next) {
1397 if( node->pkt->pkttype == PKT_USER_ID &&
1398 ((attr && node->pkt->pkt.user_id->attrib_data) ||
1399 (!attr && !node->pkt->pkt.user_id->attrib_data)) &&
1400 node->pkt->pkt.user_id->is_primary ) {
1401 primary = primary2 = node;
1402 for (node=node->next; node; primary2=node, node = node->next ) {
1403 if( node->pkt->pkttype == PKT_USER_ID
1404 || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1405 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1406 break;
1409 break;
1412 if ( !primary )
1413 return; /* no primary key flag found (should not happen) */
1415 for (last=NULL, node=keyblock; node; last = node, node = node->next) {
1416 if( node->pkt->pkttype == PKT_USER_ID )
1417 break;
1419 assert (node);
1420 assert (last); /* the user ID is never the first packet */
1421 assert (primary0); /* ditto (this is the node before primary) */
1422 if ( node == primary )
1423 return; /* already the first one */
1425 last->next = primary;
1426 primary0->next = primary2->next;
1427 primary2->next = node;
1430 void
1431 reorder_keyblock (KBNODE keyblock)
1433 do_reorder_keyblock(keyblock,1);
1434 do_reorder_keyblock(keyblock,0);
1437 void
1438 list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque )
1440 reorder_keyblock (keyblock);
1441 if (opt.with_colons)
1442 list_keyblock_colon (keyblock, secret, fpr );
1443 else
1444 list_keyblock_print (keyblock, secret, fpr, opaque );
1448 * standard function to print the finperprint.
1449 * mode 0: as used in key listings, opt.with_colons is honored
1450 * 1: print using log_info ()
1451 * 2: direct use of tty
1452 * 3: direct use of tty but only primary key.
1453 * modes 1 and 2 will try and print both subkey and primary key fingerprints
1455 void
1456 print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode )
1458 byte array[MAX_FINGERPRINT_LEN], *p;
1459 size_t i, n;
1460 FILE *fp;
1461 const char *text;
1462 int primary=0;
1464 if(sk)
1466 if(sk->main_keyid[0]==sk->keyid[0] && sk->main_keyid[1]==sk->keyid[1])
1467 primary=1;
1469 else
1471 if(pk->main_keyid[0]==pk->keyid[0] && pk->main_keyid[1]==pk->keyid[1])
1472 primary=1;
1475 /* Just to be safe */
1476 if(mode&0x80 && !primary)
1478 log_error("primary key is not really primary!\n");
1479 return;
1482 mode&=~0x80;
1484 if(!primary && (mode==1 || mode==2))
1486 if(sk)
1488 PKT_secret_key *primary_sk=xmalloc_clear(sizeof(*primary_sk));
1489 get_seckey(primary_sk,sk->main_keyid);
1490 print_fingerprint(NULL,primary_sk,mode|0x80);
1491 free_secret_key(primary_sk);
1493 else
1495 PKT_public_key *primary_pk=xmalloc_clear(sizeof(*primary_pk));
1496 get_pubkey(primary_pk,pk->main_keyid);
1497 print_fingerprint(primary_pk,NULL,mode|0x80);
1498 free_public_key(primary_pk);
1502 if (mode == 1) {
1503 fp = log_stream ();
1504 if(primary)
1505 text = _("Primary key fingerprint:");
1506 else
1507 text = _(" Subkey fingerprint:");
1509 else if (mode == 2) {
1510 fp = NULL; /* use tty */
1511 if(primary)
1512 /* TRANSLATORS: this should fit into 24 bytes to that the
1513 * fingerprint data is properly aligned with the user ID */
1514 text = _(" Primary key fingerprint:");
1515 else
1516 text = _(" Subkey fingerprint:");
1518 else if (mode == 3) {
1519 fp = NULL; /* use tty */
1520 text = _(" Key fingerprint =");
1522 else {
1523 fp = stdout;
1524 text = _(" Key fingerprint =");
1527 if (sk)
1528 fingerprint_from_sk (sk, array, &n);
1529 else
1530 fingerprint_from_pk (pk, array, &n);
1531 p = array;
1532 if (opt.with_colons && !mode) {
1533 fprintf (fp, "fpr:::::::::");
1534 for (i=0; i < n ; i++, p++ )
1535 fprintf (fp, "%02X", *p );
1536 putc(':', fp);
1538 else {
1539 if (fp)
1540 fputs (text, fp);
1541 else
1542 tty_printf ("%s", text);
1543 if (n == 20) {
1544 for (i=0; i < n ; i++, i++, p += 2 ) {
1545 if (fp) {
1546 if (i == 10 )
1547 putc(' ', fp);
1548 fprintf (fp, " %02X%02X", *p, p[1] );
1550 else {
1551 if (i == 10 )
1552 tty_printf (" ");
1553 tty_printf (" %02X%02X", *p, p[1]);
1557 else {
1558 for (i=0; i < n ; i++, p++ ) {
1559 if (fp) {
1560 if (i && !(i%8) )
1561 putc (' ', fp);
1562 fprintf (fp, " %02X", *p );
1564 else {
1565 if (i && !(i%8) )
1566 tty_printf (" ");
1567 tty_printf (" %02X", *p );
1572 if (fp)
1573 putc ('\n', fp);
1574 else
1575 tty_printf ("\n");
1578 /* Print the serial number of an OpenPGP card if available. */
1579 static void
1580 print_card_serialno (PKT_secret_key *sk)
1582 int i;
1584 if (!sk)
1585 return;
1586 if (!sk->is_protected || sk->protect.s2k.mode != 1002)
1587 return; /* Not a card. */
1588 if (opt.with_colons)
1589 return; /* Handled elsewhere. */
1591 fputs (_(" Card serial no. ="), stdout);
1592 putchar (' ');
1593 if (sk->protect.ivlen == 16
1594 && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6) )
1595 { /* This is an OpenPGP card. Just print the relevant part. */
1596 for (i=8; i < 14; i++)
1598 if (i == 10)
1599 putchar (' ');
1600 printf ("%02X", sk->protect.iv[i]);
1603 else
1604 { /* Something is wrong: Print all. */
1605 for (i=0; i < sk->protect.ivlen; i++)
1606 printf ("%02X", sk->protect.iv[i]);
1608 putchar ('\n');
1613 void set_attrib_fd(int fd)
1615 static int last_fd=-1;
1617 if ( fd != -1 && last_fd == fd )
1618 return;
1620 if ( attrib_fp && attrib_fp != stdout && attrib_fp != stderr )
1621 fclose (attrib_fp);
1622 attrib_fp = NULL;
1623 if ( fd == -1 )
1624 return;
1626 if( fd == 1 )
1627 attrib_fp = stdout;
1628 else if( fd == 2 )
1629 attrib_fp = stderr;
1630 else
1631 attrib_fp = fdopen( fd, "wb" );
1632 if( !attrib_fp ) {
1633 log_fatal("can't open fd %d for attribute output: %s\n",
1634 fd, strerror(errno));
1637 last_fd = fd;