2006-09-24 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / g10 / keylist.c
blob4416062996c2ec07bddbd4a18c29ac75bc320c7e
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 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 "gpg.h"
31 #include "options.h"
32 #include "packet.h"
33 #include "errors.h"
34 #include "keydb.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_get_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_get_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_get_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( gpg_err_code (rc) ) {
919 case 0: sigrc = '!'; break;
920 case GPG_ERR_BAD_SIGNATURE:
921 stats->inv_sigs++; sigrc = '-'; break;
922 case GPG_ERR_NO_PUBKEY:
923 case GPG_ERR_UNUSABLE_PUBKEY: stats->no_key++; continue;
924 default: stats->oth_err++; sigrc = '%'; break;
927 /* TODO: Make sure a cached sig record here still has
928 the pk that issued it. See also
929 keyedit.c:print_and_check_one_sig */
931 else {
932 rc = 0;
933 sigrc = ' ';
936 if( sig->sig_class == 0x20 || sig->sig_class == 0x28
937 || sig->sig_class == 0x30 )
938 sigstr = "rev";
939 else if( (sig->sig_class&~3) == 0x10 )
940 sigstr = "sig";
941 else if( sig->sig_class == 0x18 )
942 sigstr = "sig";
943 else if( sig->sig_class == 0x1F )
944 sigstr = "sig";
945 else {
946 printf("sig "
947 "[unexpected signature class 0x%02x]\n",sig->sig_class );
948 continue;
951 fputs( sigstr, stdout );
952 printf("%c%c %c%c%c%c%c%c %s %s",
953 sigrc,(sig->sig_class-0x10>0 &&
954 sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ',
955 sig->flags.exportable?' ':'L',
956 sig->flags.revocable?' ':'R',
957 sig->flags.policy_url?'P':' ',
958 sig->flags.notation?'N':' ',
959 sig->flags.expired?'X':' ',
960 (sig->trust_depth>9)?'T':
961 (sig->trust_depth>0)?'0'+sig->trust_depth:' ',
962 keystr(sig->keyid),datestr_from_sig(sig));
963 if(opt.list_options&LIST_SHOW_SIG_EXPIRE)
964 printf(" %s", expirestr_from_sig(sig));
965 printf(" ");
966 if( sigrc == '%' )
967 printf("[%s] ", g10_errstr(rc) );
968 else if( sigrc == '?' )
970 else if ( !opt.fast_list_mode ) {
971 size_t n;
972 char *p = get_user_id( sig->keyid, &n );
973 print_utf8_string( stdout, p, n );
974 xfree(p);
976 putchar('\n');
978 if(sig->flags.policy_url
979 && (opt.list_options&LIST_SHOW_POLICY_URLS))
980 show_policy_url(sig,3,0);
982 if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATIONS))
983 show_notation(sig,3,0,
984 ((opt.list_options&LIST_SHOW_STD_NOTATIONS)?1:0)+
985 ((opt.list_options&LIST_SHOW_USER_NOTATIONS)?2:0));
987 if(sig->flags.pref_ks
988 && (opt.list_options&LIST_SHOW_KEYSERVER_URLS))
989 show_keyserver_url(sig,3,0);
991 /* fixme: check or list other sigs here */
994 putchar('\n');
997 void
998 print_revokers(PKT_public_key *pk)
1000 /* print the revoker record */
1001 if( !pk->revkey && pk->numrevkeys )
1002 BUG();
1003 else
1005 int i,j;
1007 for (i=0; i < pk->numrevkeys; i++)
1009 byte *p;
1011 printf ("rvk:::%d::::::", pk->revkey[i].algid);
1012 p = pk->revkey[i].fpr;
1013 for (j=0; j < 20; j++, p++ )
1014 printf ("%02X", *p);
1015 printf (":%02x%s:\n", pk->revkey[i].class,
1016 (pk->revkey[i].class&0x40)?"s":"");
1021 static void
1022 list_keyblock_colon( KBNODE keyblock, int secret, int fpr )
1024 int rc = 0;
1025 KBNODE kbctx;
1026 KBNODE node;
1027 PKT_public_key *pk;
1028 PKT_secret_key *sk;
1029 u32 keyid[2];
1030 int any=0;
1031 int trustletter = 0;
1032 int ulti_hack = 0;
1033 int i;
1035 /* get the keyid from the keyblock */
1036 node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
1037 if( !node ) {
1038 log_error("Oops; key lost!\n");
1039 dump_kbnode( keyblock );
1040 return;
1043 if( secret ) {
1044 pk = NULL;
1045 sk = node->pkt->pkt.secret_key;
1046 keyid_from_sk( sk, keyid );
1047 printf("sec::%u:%d:%08lX%08lX:%s:%s:::",
1048 nbits_from_sk( sk ),
1049 sk->pubkey_algo,
1050 (ulong)keyid[0],(ulong)keyid[1],
1051 colon_datestr_from_sk( sk ),
1052 colon_strtime (sk->expiredate)
1053 /* fixme: add LID here */ );
1055 else {
1056 pk = node->pkt->pkt.public_key;
1057 sk = NULL;
1058 keyid_from_pk( pk, keyid );
1059 fputs( "pub:", stdout );
1060 if ( !pk->is_valid )
1061 putchar ('i');
1062 else if ( pk->is_revoked )
1063 putchar ('r');
1064 else if ( pk->has_expired )
1065 putchar ('e');
1066 else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1068 else {
1069 trustletter = get_validity_info ( pk, NULL );
1070 if( trustletter == 'u' )
1071 ulti_hack = 1;
1072 putchar(trustletter);
1074 printf(":%u:%d:%08lX%08lX:%s:%s::",
1075 nbits_from_pk( pk ),
1076 pk->pubkey_algo,
1077 (ulong)keyid[0],(ulong)keyid[1],
1078 colon_datestr_from_pk( pk ),
1079 colon_strtime (pk->expiredate) );
1080 if( !opt.fast_list_mode && !opt.no_expensive_trust_checks )
1081 putchar( get_ownertrust_info(pk) );
1082 putchar(':');
1085 if (opt.fixed_list_mode) {
1086 /* do not merge the first uid with the primary key */
1087 putchar(':');
1088 putchar(':');
1089 print_capabilities (pk, sk, keyblock);
1090 if (secret) {
1091 putchar(':'); /* End of field 13. */
1092 putchar(':'); /* End of field 14. */
1093 if (sk->protect.s2k.mode == 1001)
1094 putchar('#'); /* Key is just a stub. */
1095 else if (sk->protect.s2k.mode == 1002) {
1096 /* Key is stored on an external token (card) or handled by
1097 the gpg-agent. Print the serial number of that token
1098 here. */
1099 for (i=0; i < sk->protect.ivlen; i++)
1100 printf ("%02X", sk->protect.iv[i]);
1102 putchar(':'); /* End of field 15. */
1104 putchar('\n');
1105 if(pk)
1106 print_revokers(pk);
1107 if( fpr )
1108 print_fingerprint( pk, sk, 0 );
1109 if( opt.with_key_data )
1110 print_key_data( pk );
1111 any = 1;
1114 for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
1115 if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) {
1116 PKT_user_id *uid=node->pkt->pkt.user_id;
1117 if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL)
1118 dump_attribs(node->pkt->pkt.user_id,pk,sk);
1120 * Fixme: We need a is_valid flag here too
1122 if( any ) {
1123 char *str=uid->attrib_data?"uat":"uid";
1124 /* If we're listing a secret key, leave out the
1125 validity values for now. This is handled better in
1126 1.9. */
1127 if ( sk )
1128 printf("%s:::::",str);
1129 else if ( uid->is_revoked )
1130 printf("%s:r::::",str);
1131 else if ( uid->is_expired )
1132 printf("%s:e::::",str);
1133 else if ( opt.no_expensive_trust_checks )
1134 printf("%s:::::",str);
1135 else {
1136 int uid_validity;
1138 if( pk && !ulti_hack )
1139 uid_validity=get_validity_info (pk, uid);
1140 else
1141 uid_validity = 'u';
1142 printf("%s:%c::::",str,uid_validity);
1145 printf("%s:",colon_strtime(uid->created));
1146 printf("%s:",colon_strtime(uid->expiredate));
1148 namehash_from_uid(uid);
1150 for(i=0; i < 20; i++ )
1151 printf("%02X",uid->namehash[i]);
1153 printf("::");
1155 if(uid->attrib_data)
1156 printf("%u %lu",uid->numattribs,uid->attrib_len);
1157 else
1158 print_string(stdout,uid->name,uid->len, ':' );
1159 putchar(':');
1160 if (any)
1161 putchar('\n');
1162 else {
1163 putchar(':');
1164 print_capabilities (pk, sk, keyblock);
1165 putchar('\n');
1166 if( fpr )
1167 print_fingerprint( pk, sk, 0 );
1168 if( opt.with_key_data )
1169 print_key_data( pk );
1170 any = 1;
1173 else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1174 u32 keyid2[2];
1175 PKT_public_key *pk2 = node->pkt->pkt.public_key;
1177 if( !any ) {
1178 putchar(':');
1179 putchar(':');
1180 print_capabilities (pk, sk, keyblock);
1181 putchar('\n');
1182 if( fpr )
1183 print_fingerprint( pk, sk, 0 ); /* of the main key */
1184 any = 1;
1187 keyid_from_pk( pk2, keyid2 );
1188 fputs ("sub:", stdout );
1189 if ( !pk2->is_valid )
1190 putchar ('i');
1191 else if ( pk2->is_revoked )
1192 putchar ('r');
1193 else if ( pk2->has_expired )
1194 putchar ('e');
1195 else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1197 else {
1198 /* trustletter should always be defined here */
1199 if(trustletter)
1200 printf("%c", trustletter );
1202 printf(":%u:%d:%08lX%08lX:%s:%s:::::",
1203 nbits_from_pk( pk2 ),
1204 pk2->pubkey_algo,
1205 (ulong)keyid2[0],(ulong)keyid2[1],
1206 colon_datestr_from_pk( pk2 ),
1207 colon_strtime (pk2->expiredate)
1208 /* fixme: add LID and ownertrust here */
1210 print_capabilities (pk2, NULL, NULL);
1211 putchar('\n');
1212 if( fpr > 1 )
1213 print_fingerprint( pk2, NULL, 0 );
1214 if( opt.with_key_data )
1215 print_key_data( pk2 );
1217 else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1218 u32 keyid2[2];
1219 PKT_secret_key *sk2 = node->pkt->pkt.secret_key;
1221 if( !any ) {
1222 putchar(':');
1223 putchar(':');
1224 print_capabilities (pk, sk, keyblock);
1225 putchar('\n');
1226 if( fpr )
1227 print_fingerprint( pk, sk, 0 ); /* of the main key */
1228 any = 1;
1231 keyid_from_sk( sk2, keyid2 );
1232 printf("ssb::%u:%d:%08lX%08lX:%s:%s:::::",
1233 nbits_from_sk( sk2 ),
1234 sk2->pubkey_algo,
1235 (ulong)keyid2[0],(ulong)keyid2[1],
1236 colon_datestr_from_sk( sk2 ),
1237 colon_strtime (sk2->expiredate)
1238 /* fixme: add LID */ );
1239 print_capabilities (NULL, sk2, NULL);
1240 if (opt.fixed_list_mode) {
1241 /* We print the serial number only in fixed list mode
1242 for the primary key so, so avoid questions we print
1243 it for subkeys also only in this mode. There is no
1244 technical reason, though. */
1245 putchar(':'); /* End of field 13. */
1246 putchar(':'); /* End of field 14. */
1247 if (sk2->protect.s2k.mode == 1001)
1248 putchar('#'); /* Key is just a stub. */
1249 else if (sk2->protect.s2k.mode == 1002) {
1250 /* Key is stored on an external token (card) or handled by
1251 the gpg-agent. Print the serial number of that token
1252 here. */
1253 for (i=0; i < sk2->protect.ivlen; i++)
1254 printf ("%02X", sk2->protect.iv[i]);
1256 putchar(':'); /* End of field 15. */
1258 putchar ('\n');
1259 if( fpr > 1 )
1260 print_fingerprint( NULL, sk2, 0 );
1262 else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) {
1263 PKT_signature *sig = node->pkt->pkt.signature;
1264 int sigrc,fprokay=0;
1265 char *sigstr;
1266 size_t fplen;
1267 byte fparray[MAX_FINGERPRINT_LEN];
1269 if( !any ) { /* no user id, (maybe a revocation follows)*/
1270 if( sig->sig_class == 0x20 )
1271 fputs("[revoked]:", stdout);
1272 else if( sig->sig_class == 0x18 )
1273 fputs("[key binding]:", stdout);
1274 else if( sig->sig_class == 0x28 )
1275 fputs("[subkey revoked]:", stdout);
1276 else
1277 putchar (':');
1278 putchar(':');
1279 print_capabilities (pk, sk, keyblock);
1280 putchar('\n');
1281 if( fpr )
1282 print_fingerprint( pk, sk, 0 );
1283 any=1;
1286 if( sig->sig_class == 0x20 || sig->sig_class == 0x28
1287 || sig->sig_class == 0x30 )
1288 sigstr = "rev";
1289 else if( (sig->sig_class&~3) == 0x10 )
1290 sigstr = "sig";
1291 else if( sig->sig_class == 0x18 )
1292 sigstr = "sig";
1293 else if( sig->sig_class == 0x1F )
1294 sigstr = "sig";
1295 else {
1296 printf ("sig::::::::::%02x%c:\n",
1297 sig->sig_class, sig->flags.exportable?'x':'l');
1298 continue;
1300 if( opt.check_sigs ) {
1301 PKT_public_key *signer_pk=NULL;
1303 fflush(stdout);
1304 if(opt.no_sig_cache)
1305 signer_pk=xmalloc_clear(sizeof(PKT_public_key));
1307 rc = check_key_signature2( keyblock, node, NULL, signer_pk,
1308 NULL, NULL, NULL );
1309 switch ( gpg_err_code (rc) ) {
1310 case 0: sigrc = '!'; break;
1311 case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break;
1312 case GPG_ERR_NO_PUBKEY:
1313 case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break;
1314 default: sigrc = '%'; break;
1317 if(opt.no_sig_cache)
1319 if(rc==0)
1321 fingerprint_from_pk (signer_pk, fparray, &fplen);
1322 fprokay=1;
1324 free_public_key(signer_pk);
1327 else {
1328 rc = 0;
1329 sigrc = ' ';
1331 fputs( sigstr, stdout );
1332 putchar(':');
1333 if( sigrc != ' ' )
1334 putchar(sigrc);
1335 printf("::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo,
1336 (ulong)sig->keyid[0], (ulong)sig->keyid[1],
1337 colon_datestr_from_sig(sig),
1338 colon_expirestr_from_sig(sig));
1340 if(sig->trust_depth || sig->trust_value)
1341 printf("%d %d",sig->trust_depth,sig->trust_value);
1342 printf(":");
1344 if(sig->trust_regexp)
1345 print_string(stdout,sig->trust_regexp,
1346 strlen(sig->trust_regexp),':');
1347 printf(":");
1349 if( sigrc == '%' )
1350 printf("[%s] ", g10_errstr(rc) );
1351 else if( sigrc == '?' )
1353 else if ( !opt.fast_list_mode ) {
1354 size_t n;
1355 char *p = get_user_id( sig->keyid, &n );
1356 print_string( stdout, p, n, ':' );
1357 xfree(p);
1359 printf(":%02x%c:", sig->sig_class,sig->flags.exportable?'x':'l');
1361 if(opt.no_sig_cache && opt.check_sigs && fprokay)
1363 printf(":");
1365 for (i=0; i < fplen ; i++ )
1366 printf ("%02X", fparray[i] );
1368 printf(":");
1371 printf("\n");
1373 if(opt.show_subpackets)
1374 print_subpackets_colon(sig);
1376 /* fixme: check or list other sigs here */
1379 if( !any ) {/* oops, no user id */
1380 putchar(':');
1381 putchar(':');
1382 print_capabilities (pk, sk, keyblock);
1383 putchar('\n');
1388 * Reorder the keyblock so that the primary user ID (and not attribute
1389 * packet) comes first. Fixme: Replace this by a generic sort
1390 * function. */
1391 static void
1392 do_reorder_keyblock (KBNODE keyblock,int attr)
1394 KBNODE primary = NULL, primary0 = NULL, primary2 = NULL;
1395 KBNODE last, node;
1397 for (node=keyblock; node; primary0=node, node = node->next) {
1398 if( node->pkt->pkttype == PKT_USER_ID &&
1399 ((attr && node->pkt->pkt.user_id->attrib_data) ||
1400 (!attr && !node->pkt->pkt.user_id->attrib_data)) &&
1401 node->pkt->pkt.user_id->is_primary ) {
1402 primary = primary2 = node;
1403 for (node=node->next; node; primary2=node, node = node->next ) {
1404 if( node->pkt->pkttype == PKT_USER_ID
1405 || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1406 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1407 break;
1410 break;
1413 if ( !primary )
1414 return; /* no primary key flag found (should not happen) */
1416 for (last=NULL, node=keyblock; node; last = node, node = node->next) {
1417 if( node->pkt->pkttype == PKT_USER_ID )
1418 break;
1420 assert (node);
1421 assert (last); /* the user ID is never the first packet */
1422 assert (primary0); /* ditto (this is the node before primary) */
1423 if ( node == primary )
1424 return; /* already the first one */
1426 last->next = primary;
1427 primary0->next = primary2->next;
1428 primary2->next = node;
1431 void
1432 reorder_keyblock (KBNODE keyblock)
1434 do_reorder_keyblock(keyblock,1);
1435 do_reorder_keyblock(keyblock,0);
1438 void
1439 list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque )
1441 reorder_keyblock (keyblock);
1442 if (opt.with_colons)
1443 list_keyblock_colon (keyblock, secret, fpr );
1444 else
1445 list_keyblock_print (keyblock, secret, fpr, opaque );
1449 * standard function to print the finperprint.
1450 * mode 0: as used in key listings, opt.with_colons is honored
1451 * 1: print using log_info ()
1452 * 2: direct use of tty
1453 * 3: direct use of tty but only primary key.
1454 * modes 1 and 2 will try and print both subkey and primary key fingerprints
1456 void
1457 print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode )
1459 byte array[MAX_FINGERPRINT_LEN], *p;
1460 size_t i, n;
1461 FILE *fp;
1462 const char *text;
1463 int primary=0;
1465 if(sk)
1467 if(sk->main_keyid[0]==sk->keyid[0] && sk->main_keyid[1]==sk->keyid[1])
1468 primary=1;
1470 else
1472 if(pk->main_keyid[0]==pk->keyid[0] && pk->main_keyid[1]==pk->keyid[1])
1473 primary=1;
1476 /* Just to be safe */
1477 if(mode&0x80 && !primary)
1479 log_error("primary key is not really primary!\n");
1480 return;
1483 mode&=~0x80;
1485 if(!primary && (mode==1 || mode==2))
1487 if(sk)
1489 PKT_secret_key *primary_sk=xmalloc_clear(sizeof(*primary_sk));
1490 get_seckey(primary_sk,sk->main_keyid);
1491 print_fingerprint(NULL,primary_sk,mode|0x80);
1492 free_secret_key(primary_sk);
1494 else
1496 PKT_public_key *primary_pk=xmalloc_clear(sizeof(*primary_pk));
1497 get_pubkey(primary_pk,pk->main_keyid);
1498 print_fingerprint(primary_pk,NULL,mode|0x80);
1499 free_public_key(primary_pk);
1503 if (mode == 1) {
1504 fp = log_get_stream ();
1505 if(primary)
1506 text = _("Primary key fingerprint:");
1507 else
1508 text = _(" Subkey fingerprint:");
1510 else if (mode == 2) {
1511 fp = NULL; /* use tty */
1512 if(primary)
1513 /* TRANSLATORS: this should fit into 24 bytes to that the
1514 * fingerprint data is properly aligned with the user ID */
1515 text = _(" Primary key fingerprint:");
1516 else
1517 text = _(" Subkey fingerprint:");
1519 else if (mode == 3) {
1520 fp = NULL; /* use tty */
1521 text = _(" Key fingerprint =");
1523 else {
1524 fp = stdout;
1525 text = _(" Key fingerprint =");
1528 if (sk)
1529 fingerprint_from_sk (sk, array, &n);
1530 else
1531 fingerprint_from_pk (pk, array, &n);
1532 p = array;
1533 if (opt.with_colons && !mode) {
1534 fprintf (fp, "fpr:::::::::");
1535 for (i=0; i < n ; i++, p++ )
1536 fprintf (fp, "%02X", *p );
1537 putc(':', fp);
1539 else {
1540 if (fp)
1541 fputs (text, fp);
1542 else
1543 tty_printf ("%s", text);
1544 if (n == 20) {
1545 for (i=0; i < n ; i++, i++, p += 2 ) {
1546 if (fp) {
1547 if (i == 10 )
1548 putc(' ', fp);
1549 fprintf (fp, " %02X%02X", *p, p[1] );
1551 else {
1552 if (i == 10 )
1553 tty_printf (" ");
1554 tty_printf (" %02X%02X", *p, p[1]);
1558 else {
1559 for (i=0; i < n ; i++, p++ ) {
1560 if (fp) {
1561 if (i && !(i%8) )
1562 putc (' ', fp);
1563 fprintf (fp, " %02X", *p );
1565 else {
1566 if (i && !(i%8) )
1567 tty_printf (" ");
1568 tty_printf (" %02X", *p );
1573 if (fp)
1574 putc ('\n', fp);
1575 else
1576 tty_printf ("\n");
1579 /* Print the serial number of an OpenPGP card if available. */
1580 static void
1581 print_card_serialno (PKT_secret_key *sk)
1583 int i;
1585 if (!sk)
1586 return;
1587 if (!sk->is_protected || sk->protect.s2k.mode != 1002)
1588 return; /* Not a card. */
1589 if (opt.with_colons)
1590 return; /* Handled elsewhere. */
1592 fputs (_(" Card serial no. ="), stdout);
1593 putchar (' ');
1594 if (sk->protect.ivlen == 16
1595 && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6) )
1596 { /* This is an OpenPGP card. Just print the relevant part. */
1597 for (i=8; i < 14; i++)
1599 if (i == 10)
1600 putchar (' ');
1601 printf ("%02X", sk->protect.iv[i]);
1604 else
1605 { /* Something is wrong: Print all. */
1606 for (i=0; i < sk->protect.ivlen; i++)
1607 printf ("%02X", sk->protect.iv[i]);
1609 putchar ('\n');
1614 void set_attrib_fd(int fd)
1616 static int last_fd=-1;
1618 if ( fd != -1 && last_fd == fd )
1619 return;
1621 if ( attrib_fp && attrib_fp != stdout && attrib_fp != stderr )
1622 fclose (attrib_fp);
1623 attrib_fp = NULL;
1624 if ( fd == -1 )
1625 return;
1627 if( fd == 1 )
1628 attrib_fp = stdout;
1629 else if( fd == 2 )
1630 attrib_fp = stderr;
1631 else
1632 attrib_fp = fdopen( fd, "wb" );
1633 if( !attrib_fp ) {
1634 log_fatal("can't open fd %d for attribute output: %s\n",
1635 fd, strerror(errno));
1638 last_fd = fd;