Fixed some card related problems.
[gnupg.git] / g10 / keylist.c
blobc4f5d26965697f8af8b59ecf377e9fb7e1bf03c0
1 /* keylist.c - print keys
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3 * 2008 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #ifdef HAVE_DOSISH_SYSTEM
28 #include <fcntl.h> /* for setmode() */
29 #endif
31 #include "gpg.h"
32 #include "options.h"
33 #include "packet.h"
34 #include "status.h"
35 #include "keydb.h"
36 #include "photoid.h"
37 #include "util.h"
38 #include "ttyio.h"
39 #include "trustdb.h"
40 #include "main.h"
41 #include "i18n.h"
42 #include "status.h"
44 static void list_all(int);
45 static void list_one( strlist_t names, int secret);
46 static void locate_one (strlist_t names);
47 static void print_card_serialno (PKT_secret_key *sk);
49 struct sig_stats
51 int inv_sigs;
52 int no_key;
53 int oth_err;
56 /* The stream used to write attribute packets to. */
57 static FILE *attrib_fp = NULL;
59 /****************
60 * List the keys
61 * If list is NULL, all available keys are listed
63 void
64 public_key_list( strlist_t list, int locate_mode )
66 if (opt.with_colons)
68 byte trust_model,marginals,completes,cert_depth;
69 ulong created,nextcheck;
71 read_trust_options(&trust_model,&created,&nextcheck,
72 &marginals,&completes,&cert_depth);
74 printf("tru:");
76 if(nextcheck && nextcheck <= make_timestamp())
77 printf("o");
78 if(trust_model!=opt.trust_model)
79 printf("t");
80 if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC)
82 if(marginals!=opt.marginals_needed)
83 printf("m");
84 if(completes!=opt.completes_needed)
85 printf("c");
86 if(cert_depth!=opt.max_cert_depth)
87 printf("d");
90 printf(":%d:%lu:%lu",trust_model,created,nextcheck);
92 /* Only show marginals, completes, and cert_depth in the classic
93 or PGP trust models since they are not meaningful
94 otherwise. */
96 if(trust_model==TM_PGP || trust_model==TM_CLASSIC)
97 printf(":%d:%d:%d",marginals,completes,cert_depth);
99 printf("\n");
102 /* We need to do the stale check right here because it might need to
103 update the keyring while we already have the keyring open. This
104 is very bad for W32 because of a sharing violation. For real OSes
105 it might lead to false results if we are later listing a keyring
106 which is associated with the inode of a deleted file. */
107 check_trustdb_stale ();
109 if (locate_mode)
110 locate_one (list);
111 else if (!list)
112 list_all (0);
113 else
114 list_one (list, 0);
118 void
119 secret_key_list( strlist_t list )
121 check_trustdb_stale ();
123 if( !list )
124 list_all(1);
125 else /* List by user id */
126 list_one( list, 1 );
129 void
130 print_seckey_info (PKT_secret_key *sk)
132 u32 keyid[2];
133 char *p;
135 keyid_from_sk (sk, keyid);
136 p=get_user_id_native(keyid);
138 tty_printf ("\nsec %4u%c/%s %s %s\n",
139 nbits_from_sk (sk),
140 pubkey_letter (sk->pubkey_algo),
141 keystr(keyid), datestr_from_sk (sk), p);
143 xfree (p);
146 /* Print information about the public key. With FP passed as NULL,
147 the tty output interface is used, otherwise output is directted to
148 the given stream. */
149 void
150 print_pubkey_info (FILE *fp, PKT_public_key *pk)
152 u32 keyid[2];
153 char *p;
155 keyid_from_pk (pk, keyid);
157 /* If the pk was chosen by a particular user ID, that is the one to
158 print. */
159 if(pk->user_id)
160 p=utf8_to_native(pk->user_id->name,pk->user_id->len,0);
161 else
162 p=get_user_id_native(keyid);
164 if (fp)
165 fprintf (fp, "pub %4u%c/%s %s %s\n",
166 nbits_from_pk (pk),
167 pubkey_letter (pk->pubkey_algo),
168 keystr(keyid), datestr_from_pk (pk), p);
169 else
170 tty_printf ("\npub %4u%c/%s %s %s\n",
171 nbits_from_pk (pk), pubkey_letter (pk->pubkey_algo),
172 keystr(keyid), datestr_from_pk (pk), p);
174 xfree (p);
178 /* Print basic information of a secret key including the card serial
179 number information. */
180 void
181 print_card_key_info (FILE *fp, KBNODE keyblock)
183 KBNODE node;
184 int i;
186 for (node = keyblock; node; node = node->next )
188 if (node->pkt->pkttype == PKT_SECRET_KEY
189 || (node->pkt->pkttype == PKT_SECRET_SUBKEY) )
191 PKT_secret_key *sk = node->pkt->pkt.secret_key;
193 tty_fprintf (fp, "%s%c %4u%c/%s ",
194 node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
195 (sk->protect.s2k.mode==1001)?'#':
196 (sk->protect.s2k.mode==1002)?'>':' ',
197 nbits_from_sk (sk),
198 pubkey_letter (sk->pubkey_algo),
199 keystr_from_sk(sk));
200 tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk));
201 tty_fprintf (fp, " ");
202 tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk));
203 if (sk->is_protected && sk->protect.s2k.mode == 1002)
205 tty_fprintf (fp, "\n ");
206 tty_fprintf (fp, _("card-no: "));
207 if (sk->protect.ivlen == 16
208 && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6))
210 /* This is an OpenPGP card. */
211 for (i=8; i < 14; i++)
213 if (i == 10)
214 tty_fprintf (fp, " ");
215 tty_fprintf (fp, "%02X", sk->protect.iv[i]);
218 else
219 { /* Something is wrong: Print all. */
220 for (i=0; i < sk->protect.ivlen; i++)
221 tty_fprintf (fp, "%02X", sk->protect.iv[i]);
224 tty_fprintf (fp, "\n");
231 /* Flags = 0x01 hashed 0x02 critical */
232 static void
233 status_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf)
235 char status[40];
237 /* Don't print these. */
238 if(len>256)
239 return;
241 sprintf(status,"%d %u %u ",type,flags,(unsigned int)len);
243 write_status_text_and_buffer(STATUS_SIG_SUBPACKET,status,buf,len,0);
247 mode=0 for stdout.
248 mode=1 for log_info + status messages
249 mode=2 for status messages only
252 void
253 show_policy_url(PKT_signature *sig,int indent,int mode)
255 const byte *p;
256 size_t len;
257 int seq=0,crit;
258 FILE *fp=mode?log_get_stream():stdout;
260 while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,&len,&seq,&crit)))
262 if(mode!=2)
264 int i;
265 const char *str;
267 for(i=0;i<indent;i++)
268 putchar(' ');
270 if(crit)
271 str=_("Critical signature policy: ");
272 else
273 str=_("Signature policy: ");
274 if(mode)
275 log_info("%s",str);
276 else
277 printf("%s",str);
278 print_utf8_string(fp,p,len);
279 fprintf(fp,"\n");
282 if(mode)
283 write_status_buffer ( STATUS_POLICY_URL, p, len, 0 );
288 mode=0 for stdout.
289 mode=1 for log_info + status messages
290 mode=2 for status messages only
292 /* TODO: use this */
293 void
294 show_keyserver_url(PKT_signature *sig,int indent,int mode)
296 const byte *p;
297 size_t len;
298 int seq=0,crit;
299 FILE *fp=mode?log_get_stream():stdout;
301 while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&len,&seq,&crit)))
303 if(mode!=2)
305 int i;
306 const char *str;
308 for(i=0;i<indent;i++)
309 putchar(' ');
311 if(crit)
312 str=_("Critical preferred keyserver: ");
313 else
314 str=_("Preferred keyserver: ");
315 if(mode)
316 log_info("%s",str);
317 else
318 printf("%s",str);
319 print_utf8_string(fp,p,len);
320 fprintf(fp,"\n");
323 if(mode)
324 status_one_subpacket(SIGSUBPKT_PREF_KS,len,(crit?0x02:0)|0x01,p);
329 mode=0 for stdout.
330 mode=1 for log_info + status messages
331 mode=2 for status messages only
333 which bits:
334 1 == standard notations
335 2 == user notations
338 void
339 show_notation(PKT_signature *sig,int indent,int mode,int which)
341 FILE *fp=mode?log_get_stream():stdout;
342 struct notation *nd,*notations;
344 if(which==0)
345 which=3;
347 notations=sig_to_notation(sig);
349 /* There may be multiple notations in the same sig. */
350 for(nd=notations;nd;nd=nd->next)
352 if(mode!=2)
354 int has_at=!!strchr(nd->name,'@');
356 if((which&1 && !has_at) || (which&2 && has_at))
358 int i;
359 const char *str;
361 for(i=0;i<indent;i++)
362 putchar(' ');
364 if(nd->flags.critical)
365 str=_("Critical signature notation: ");
366 else
367 str=_("Signature notation: ");
368 if(mode)
369 log_info("%s",str);
370 else
371 printf("%s",str);
372 /* This is all UTF8 */
373 print_utf8_string(fp,nd->name,strlen(nd->name));
374 fprintf(fp,"=");
375 print_utf8_string(fp,nd->value,strlen(nd->value));
376 fprintf(fp,"\n");
380 if(mode)
382 write_status_buffer(STATUS_NOTATION_NAME,
383 nd->name,strlen(nd->name),0);
384 write_status_buffer(STATUS_NOTATION_DATA,
385 nd->value,strlen(nd->value),50);
389 free_notation(notations);
392 static void
393 print_signature_stats(struct sig_stats *s)
395 if( s->inv_sigs == 1 )
396 tty_printf(_("1 bad signature\n") );
397 else if( s->inv_sigs )
398 tty_printf(_("%d bad signatures\n"), s->inv_sigs );
399 if( s->no_key == 1 )
400 tty_printf(_("1 signature not checked due to a missing key\n") );
401 else if( s->no_key )
402 tty_printf(_("%d signatures not checked due to missing keys\n"),s->no_key);
403 if( s->oth_err == 1 )
404 tty_printf(_("1 signature not checked due to an error\n") );
405 else if( s->oth_err )
406 tty_printf(_("%d signatures not checked due to errors\n"), s->oth_err );
409 static void
410 list_all( int secret )
412 KEYDB_HANDLE hd;
413 KBNODE keyblock = NULL;
414 int rc=0;
415 const char *lastresname, *resname;
416 struct sig_stats stats;
418 memset(&stats,0,sizeof(stats));
420 hd = keydb_new (secret);
421 if (!hd)
422 rc = G10ERR_GENERAL;
423 else
424 rc = keydb_search_first (hd);
425 if( rc ) {
426 if( rc != -1 )
427 log_error("keydb_search_first failed: %s\n", g10_errstr(rc) );
428 goto leave;
431 lastresname = NULL;
432 do {
433 rc = keydb_get_keyblock (hd, &keyblock);
434 if (rc) {
435 log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc));
436 goto leave;
438 if(!opt.with_colons)
440 resname = keydb_get_resource_name (hd);
441 if (lastresname != resname )
443 int i;
445 printf("%s\n", resname );
446 for(i=strlen(resname); i; i-- )
447 putchar('-');
448 putchar('\n');
449 lastresname = resname;
452 merge_keys_and_selfsig( keyblock );
453 list_keyblock( keyblock, secret, opt.fingerprint,
454 opt.check_sigs?&stats:NULL);
455 release_kbnode( keyblock );
456 keyblock = NULL;
457 } while (!(rc = keydb_search_next (hd)));
458 if( rc && rc != -1 )
459 log_error ("keydb_search_next failed: %s\n", g10_errstr(rc));
461 if(opt.check_sigs && !opt.with_colons)
462 print_signature_stats(&stats);
464 leave:
465 release_kbnode (keyblock);
466 keydb_release (hd);
470 static void
471 list_one( strlist_t names, int secret )
473 int rc = 0;
474 KBNODE keyblock = NULL;
475 GETKEY_CTX ctx;
476 const char *resname;
477 const char *keyring_str = _("Keyring");
478 int i;
479 struct sig_stats stats;
481 memset(&stats,0,sizeof(stats));
483 /* fixme: using the bynames function has the disadvantage that we
484 * don't know wether one of the names given was not found. OTOH,
485 * this function has the advantage to list the names in the
486 * sequence as defined by the keyDB and does not duplicate
487 * outputs. A solution could be do test whether all given have
488 * been listed (this needs a way to use the keyDB search
489 * functions) or to have the search function return indicators for
490 * found names. Yet another way is to use the keydb search
491 * facilities directly. */
492 if( secret ) {
493 rc = get_seckey_bynames( &ctx, NULL, names, &keyblock );
494 if( rc ) {
495 log_error("error reading key: %s\n", g10_errstr(rc) );
496 get_seckey_end( ctx );
497 return;
499 do {
500 if ((opt.list_options&LIST_SHOW_KEYRING) && !opt.with_colons) {
501 resname = keydb_get_resource_name (get_ctx_handle(ctx));
502 printf("%s: %s\n", keyring_str, resname);
503 for(i = strlen(resname) + strlen(keyring_str) + 2; i; i-- )
504 putchar('-');
505 putchar('\n');
507 list_keyblock( keyblock, 1, opt.fingerprint, NULL );
508 release_kbnode( keyblock );
509 } while( !get_seckey_next( ctx, NULL, &keyblock ) );
510 get_seckey_end( ctx );
512 else {
513 rc = get_pubkey_bynames( &ctx, NULL, names, &keyblock );
514 if( rc ) {
515 log_error("error reading key: %s\n", g10_errstr(rc) );
516 get_pubkey_end( ctx );
517 return;
519 do {
520 if ((opt.list_options&LIST_SHOW_KEYRING) && !opt.with_colons) {
521 resname = keydb_get_resource_name (get_ctx_handle(ctx));
522 printf("%s: %s\n", keyring_str, resname);
523 for(i = strlen(resname) + strlen(keyring_str) + 2; i; i-- )
524 putchar('-');
525 putchar('\n');
527 list_keyblock( keyblock, 0, opt.fingerprint,
528 opt.check_sigs?&stats:NULL );
529 release_kbnode( keyblock );
530 } while( !get_pubkey_next( ctx, NULL, &keyblock ) );
531 get_pubkey_end( ctx );
534 if(opt.check_sigs && !opt.with_colons)
535 print_signature_stats(&stats);
539 static void
540 locate_one (strlist_t names)
542 int rc = 0;
543 strlist_t sl;
544 GETKEY_CTX ctx = NULL;
545 KBNODE keyblock = NULL;
546 struct sig_stats stats;
548 memset (&stats,0,sizeof(stats));
550 for (sl=names; sl; sl = sl->next)
552 rc = get_pubkey_byname (&ctx, NULL, sl->d, &keyblock, NULL, 1, 0);
553 if (rc)
555 if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
556 log_error ("error reading key: %s\n", g10_errstr(rc) );
558 else
562 list_keyblock (keyblock, 0, opt.fingerprint,
563 opt.check_sigs? &stats : NULL );
564 release_kbnode (keyblock);
566 while ( ctx && !get_pubkey_next (ctx, NULL, &keyblock));
567 get_pubkey_end (ctx);
568 ctx = NULL;
572 if (opt.check_sigs && !opt.with_colons)
573 print_signature_stats (&stats);
577 static void
578 print_key_data( PKT_public_key *pk )
580 int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
581 int i;
583 for(i=0; i < n; i++ ) {
584 printf("pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
585 mpi_print(stdout, pk->pkey[i], 1 );
586 putchar(':');
587 putchar('\n');
591 static void
592 print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock)
594 if(pk || (sk && sk->protect.s2k.mode!=1001))
596 unsigned int use = pk? pk->pubkey_usage : sk->pubkey_usage;
598 if ( use & PUBKEY_USAGE_ENC )
599 putchar ('e');
601 if ( use & PUBKEY_USAGE_SIG )
603 putchar ('s');
604 if( pk? pk->is_primary : sk->is_primary )
605 putchar ('c');
608 if ( (use & PUBKEY_USAGE_AUTH) )
609 putchar ('a');
612 if ( keyblock ) { /* figure out the usable capabilities */
613 KBNODE k;
614 int enc=0, sign=0, cert=0, auth=0, disabled=0;
616 for (k=keyblock; k; k = k->next ) {
617 if ( k->pkt->pkttype == PKT_PUBLIC_KEY
618 || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
619 pk = k->pkt->pkt.public_key;
621 if(pk->is_primary)
622 disabled=pk_is_disabled(pk);
624 if ( pk->is_valid && !pk->is_revoked && !pk->has_expired ) {
625 if ( pk->pubkey_usage & PUBKEY_USAGE_ENC )
626 enc = 1;
627 if ( pk->pubkey_usage & PUBKEY_USAGE_SIG )
629 sign = 1;
630 if(pk->is_primary)
631 cert = 1;
633 if ( (pk->pubkey_usage & PUBKEY_USAGE_AUTH) )
634 auth = 1;
637 else if ( k->pkt->pkttype == PKT_SECRET_KEY
638 || k->pkt->pkttype == PKT_SECRET_SUBKEY ) {
639 sk = k->pkt->pkt.secret_key;
640 if ( sk->is_valid && !sk->is_revoked && !sk->has_expired
641 && sk->protect.s2k.mode!=1001 ) {
642 if ( sk->pubkey_usage & PUBKEY_USAGE_ENC )
643 enc = 1;
644 if ( sk->pubkey_usage & PUBKEY_USAGE_SIG )
646 sign = 1;
647 if(sk->is_primary)
648 cert = 1;
650 if ( (sk->pubkey_usage & PUBKEY_USAGE_AUTH) )
651 auth = 1;
655 if (enc)
656 putchar ('E');
657 if (sign)
658 putchar ('S');
659 if (cert)
660 putchar ('C');
661 if (auth)
662 putchar ('A');
663 if (disabled)
664 putchar ('D');
667 putchar(':');
670 /* Flags = 0x01 hashed 0x02 critical */
671 static void
672 print_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf)
674 size_t i;
676 printf("spk:%d:%u:%u:",type,flags,(unsigned int)len);
678 for(i=0;i<len;i++)
680 /* printable ascii other than : and % */
681 if(buf[i]>=32 && buf[i]<=126 && buf[i]!=':' && buf[i]!='%')
682 printf("%c",buf[i]);
683 else
684 printf("%%%02X",buf[i]);
687 printf("\n");
690 void
691 print_subpackets_colon(PKT_signature *sig)
693 byte *i;
695 assert(opt.show_subpackets);
697 for(i=opt.show_subpackets;*i;i++)
699 const byte *p;
700 size_t len;
701 int seq,crit;
703 seq=0;
705 while((p=enum_sig_subpkt(sig->hashed,*i,&len,&seq,&crit)))
706 print_one_subpacket(*i,len,0x01|(crit?0x02:0),p);
708 seq=0;
710 while((p=enum_sig_subpkt(sig->unhashed,*i,&len,&seq,&crit)))
711 print_one_subpacket(*i,len,0x00|(crit?0x02:0),p);
715 void
716 dump_attribs(const PKT_user_id *uid,PKT_public_key *pk,PKT_secret_key *sk)
718 int i;
720 if(!attrib_fp)
721 return;
723 for(i=0;i<uid->numattribs;i++)
725 if(is_status_enabled())
727 byte array[MAX_FINGERPRINT_LEN], *p;
728 char buf[(MAX_FINGERPRINT_LEN*2)+90];
729 size_t j,n;
731 if(pk)
732 fingerprint_from_pk( pk, array, &n );
733 else if(sk)
734 fingerprint_from_sk( sk, array, &n );
735 else
736 BUG();
738 p = array;
739 for(j=0; j < n ; j++, p++ )
740 sprintf(buf+2*j, "%02X", *p );
742 sprintf(buf+strlen(buf)," %lu %u %u %u %lu %lu %u",
743 (ulong)uid->attribs[i].len,uid->attribs[i].type,i+1,
744 uid->numattribs,(ulong)uid->created,(ulong)uid->expiredate,
745 ((uid->is_primary?0x01:0)|
746 (uid->is_revoked?0x02:0)|
747 (uid->is_expired?0x04:0)));
748 write_status_text(STATUS_ATTRIBUTE,buf);
751 fwrite(uid->attribs[i].data,uid->attribs[i].len,1,attrib_fp);
752 fflush (attrib_fp);
756 static void
757 list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
759 int rc = 0;
760 KBNODE kbctx;
761 KBNODE node;
762 PKT_public_key *pk;
763 PKT_secret_key *sk;
764 struct sig_stats *stats=opaque;
765 int skip_sigs=0;
767 /* get the keyid from the keyblock */
768 node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
769 if( !node ) {
770 log_error("Oops; key lost!\n");
771 dump_kbnode( keyblock );
772 return;
775 if( secret )
777 pk = NULL;
778 sk = node->pkt->pkt.secret_key;
780 printf("sec%c %4u%c/%s %s",(sk->protect.s2k.mode==1001)?'#':
781 (sk->protect.s2k.mode==1002)?'>':' ',
782 nbits_from_sk( sk ),pubkey_letter( sk->pubkey_algo ),
783 keystr_from_sk(sk),datestr_from_sk( sk ));
785 if(sk->has_expired)
787 printf(" [");
788 printf(_("expired: %s"),expirestr_from_sk(sk));
789 printf("]");
791 else if(sk->expiredate )
793 printf(" [");
794 printf(_("expires: %s"),expirestr_from_sk(sk));
795 printf("]");
798 printf("\n");
800 else
802 pk = node->pkt->pkt.public_key;
803 sk = NULL;
805 check_trustdb_stale();
807 printf("pub %4u%c/%s %s",
808 nbits_from_pk(pk),pubkey_letter(pk->pubkey_algo),
809 keystr_from_pk(pk),datestr_from_pk( pk ));
811 /* We didn't include this before in the key listing, but there
812 is room in the new format, so why not? */
814 if(pk->is_revoked)
816 printf(" [");
817 printf(_("revoked: %s"),revokestr_from_pk(pk));
818 printf("]");
820 else if(pk->has_expired)
822 printf(" [");
823 printf(_("expired: %s"),expirestr_from_pk(pk));
824 printf("]");
826 else if(pk->expiredate)
828 printf(" [");
829 printf(_("expires: %s"),expirestr_from_pk(pk));
830 printf("]");
833 #if 0
834 /* I need to think about this some more. It's easy enough to
835 include, but it looks sort of confusing in the
836 listing... */
837 if(opt.list_options&LIST_SHOW_VALIDITY)
839 int validity=get_validity(pk,NULL);
840 printf(" [%s]",trust_value_to_string(validity));
842 #endif
844 printf("\n");
847 if( fpr )
848 print_fingerprint( pk, sk, 0 );
849 print_card_serialno (sk);
850 if( opt.with_key_data )
851 print_key_data( pk );
853 for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
854 if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) {
855 PKT_user_id *uid=node->pkt->pkt.user_id;
857 if(pk && (uid->is_expired || uid->is_revoked)
858 && !(opt.list_options&LIST_SHOW_UNUSABLE_UIDS))
860 skip_sigs=1;
861 continue;
863 else
864 skip_sigs=0;
866 if(attrib_fp && uid->attrib_data!=NULL)
867 dump_attribs(uid,pk,sk);
869 if((uid->is_revoked || uid->is_expired)
870 || ((opt.list_options&LIST_SHOW_UID_VALIDITY) && pk))
872 const char *validity;
873 int indent;
875 validity=uid_trust_string_fixed(pk,uid);
876 indent=(keystrlen()+9)-atoi(uid_trust_string_fixed(NULL,NULL));
878 if(indent<0 || indent>40)
879 indent=0;
881 printf("uid%*s%s ",indent,"",validity);
883 else
884 printf("uid%*s", (int)keystrlen()+10,"");
886 print_utf8_string( stdout, uid->name, uid->len );
887 putchar('\n');
889 if((opt.list_options&LIST_SHOW_PHOTOS) && uid->attribs!=NULL)
890 show_photos(uid->attribs,uid->numattribs,pk,sk,uid);
892 else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
894 PKT_public_key *pk2 = node->pkt->pkt.public_key;
896 if((pk2->is_revoked || pk2->has_expired)
897 && !(opt.list_options&LIST_SHOW_UNUSABLE_SUBKEYS))
899 skip_sigs=1;
900 continue;
902 else
903 skip_sigs=0;
905 printf("sub %4u%c/%s %s",
906 nbits_from_pk( pk2 ),pubkey_letter( pk2->pubkey_algo ),
907 keystr_from_pk(pk2),datestr_from_pk(pk2));
908 if( pk2->is_revoked )
910 printf(" [");
911 printf(_("revoked: %s"),revokestr_from_pk(pk2));
912 printf("]");
914 else if( pk2->has_expired )
916 printf(" [");
917 printf(_("expired: %s"),expirestr_from_pk(pk2));
918 printf("]");
920 else if( pk2->expiredate )
922 printf(" [");
923 printf(_("expires: %s"),expirestr_from_pk(pk2));
924 printf("]");
926 putchar('\n');
927 if( fpr > 1 )
928 print_fingerprint( pk2, NULL, 0 );
929 if( opt.with_key_data )
930 print_key_data( pk2 );
932 else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
934 PKT_secret_key *sk2 = node->pkt->pkt.secret_key;
936 printf("ssb%c %4u%c/%s %s",
937 (sk2->protect.s2k.mode==1001)?'#':
938 (sk2->protect.s2k.mode==1002)?'>':' ',
939 nbits_from_sk( sk2 ),pubkey_letter( sk2->pubkey_algo ),
940 keystr_from_sk(sk2),datestr_from_sk( sk2 ) );
941 if( sk2->expiredate )
943 printf(" [");
944 printf(_("expires: %s"),expirestr_from_sk(sk2));
945 printf("]");
947 putchar('\n');
948 if( fpr > 1 )
950 print_fingerprint( NULL, sk2, 0 );
951 print_card_serialno (sk2);
954 else if( opt.list_sigs
955 && node->pkt->pkttype == PKT_SIGNATURE
956 && !skip_sigs ) {
957 PKT_signature *sig = node->pkt->pkt.signature;
958 int sigrc;
959 char *sigstr;
961 if( stats ) {
962 /*fflush(stdout);*/
963 rc = check_key_signature( keyblock, node, NULL );
964 switch( gpg_err_code (rc) ) {
965 case 0: sigrc = '!'; break;
966 case GPG_ERR_BAD_SIGNATURE:
967 stats->inv_sigs++; sigrc = '-'; break;
968 case GPG_ERR_NO_PUBKEY:
969 case GPG_ERR_UNUSABLE_PUBKEY: stats->no_key++; continue;
970 default: stats->oth_err++; sigrc = '%'; break;
973 /* TODO: Make sure a cached sig record here still has
974 the pk that issued it. See also
975 keyedit.c:print_and_check_one_sig */
977 else {
978 rc = 0;
979 sigrc = ' ';
982 if( sig->sig_class == 0x20 || sig->sig_class == 0x28
983 || sig->sig_class == 0x30 )
984 sigstr = "rev";
985 else if( (sig->sig_class&~3) == 0x10 )
986 sigstr = "sig";
987 else if( sig->sig_class == 0x18 )
988 sigstr = "sig";
989 else if( sig->sig_class == 0x1F )
990 sigstr = "sig";
991 else {
992 printf("sig "
993 "[unexpected signature class 0x%02x]\n",sig->sig_class );
994 continue;
997 fputs( sigstr, stdout );
998 printf("%c%c %c%c%c%c%c%c %s %s",
999 sigrc,(sig->sig_class-0x10>0 &&
1000 sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ',
1001 sig->flags.exportable?' ':'L',
1002 sig->flags.revocable?' ':'R',
1003 sig->flags.policy_url?'P':' ',
1004 sig->flags.notation?'N':' ',
1005 sig->flags.expired?'X':' ',
1006 (sig->trust_depth>9)?'T':
1007 (sig->trust_depth>0)?'0'+sig->trust_depth:' ',
1008 keystr(sig->keyid),datestr_from_sig(sig));
1009 if(opt.list_options&LIST_SHOW_SIG_EXPIRE)
1010 printf(" %s", expirestr_from_sig(sig));
1011 printf(" ");
1012 if( sigrc == '%' )
1013 printf("[%s] ", g10_errstr(rc) );
1014 else if( sigrc == '?' )
1016 else if ( !opt.fast_list_mode ) {
1017 size_t n;
1018 char *p = get_user_id( sig->keyid, &n );
1019 print_utf8_string( stdout, p, n );
1020 xfree(p);
1022 putchar('\n');
1024 if(sig->flags.policy_url
1025 && (opt.list_options&LIST_SHOW_POLICY_URLS))
1026 show_policy_url(sig,3,0);
1028 if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATIONS))
1029 show_notation(sig,3,0,
1030 ((opt.list_options&LIST_SHOW_STD_NOTATIONS)?1:0)+
1031 ((opt.list_options&LIST_SHOW_USER_NOTATIONS)?2:0));
1033 if(sig->flags.pref_ks
1034 && (opt.list_options&LIST_SHOW_KEYSERVER_URLS))
1035 show_keyserver_url(sig,3,0);
1037 /* fixme: check or list other sigs here */
1040 putchar('\n');
1043 void
1044 print_revokers(PKT_public_key *pk)
1046 /* print the revoker record */
1047 if( !pk->revkey && pk->numrevkeys )
1048 BUG();
1049 else
1051 int i,j;
1053 for (i=0; i < pk->numrevkeys; i++)
1055 byte *p;
1057 printf ("rvk:::%d::::::", pk->revkey[i].algid);
1058 p = pk->revkey[i].fpr;
1059 for (j=0; j < 20; j++, p++ )
1060 printf ("%02X", *p);
1061 printf (":%02x%s:\n", pk->revkey[i].class,
1062 (pk->revkey[i].class&0x40)?"s":"");
1067 static void
1068 list_keyblock_colon( KBNODE keyblock, int secret, int fpr )
1070 int rc = 0;
1071 KBNODE kbctx;
1072 KBNODE node;
1073 PKT_public_key *pk;
1074 PKT_secret_key *sk;
1075 u32 keyid[2];
1076 int trustletter = 0;
1077 int ulti_hack = 0;
1078 int i;
1080 /* get the keyid from the keyblock */
1081 node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
1082 if ( !node )
1084 log_error("Oops; key lost!\n");
1085 dump_kbnode( keyblock );
1086 return;
1089 if ( secret )
1091 pk = NULL;
1092 sk = node->pkt->pkt.secret_key;
1093 keyid_from_sk ( sk, keyid );
1094 printf ("sec::%u:%d:%08lX%08lX:%s:%s:::",
1095 nbits_from_sk( sk ),
1096 sk->pubkey_algo,
1097 (ulong)keyid[0],(ulong)keyid[1],
1098 colon_datestr_from_sk( sk ),
1099 colon_strtime (sk->expiredate)
1100 /* fixme: add LID here */ );
1102 else
1104 pk = node->pkt->pkt.public_key;
1105 sk = NULL;
1106 keyid_from_pk( pk, keyid );
1107 fputs( "pub:", stdout );
1108 if ( !pk->is_valid )
1109 putchar ('i');
1110 else if ( pk->is_revoked )
1111 putchar ('r');
1112 else if ( pk->has_expired )
1113 putchar ('e');
1114 else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1116 else
1118 trustletter = get_validity_info ( pk, NULL );
1119 if ( trustletter == 'u' )
1120 ulti_hack = 1;
1121 putchar(trustletter);
1123 printf (":%u:%d:%08lX%08lX:%s:%s::",
1124 nbits_from_pk( pk ),
1125 pk->pubkey_algo,
1126 (ulong)keyid[0],(ulong)keyid[1],
1127 colon_datestr_from_pk( pk ),
1128 colon_strtime (pk->expiredate) );
1129 if ( !opt.fast_list_mode && !opt.no_expensive_trust_checks )
1130 putchar( get_ownertrust_info(pk) );
1131 putchar(':');
1134 putchar (':');
1135 putchar (':');
1136 print_capabilities (pk, sk, keyblock);
1137 if (secret)
1139 putchar (':'); /* End of field 13. */
1140 putchar (':'); /* End of field 14. */
1141 if (sk->protect.s2k.mode == 1001)
1142 putchar ('#'); /* Key is just a stub. */
1143 else if (sk->protect.s2k.mode == 1002)
1145 /* Key is stored on an external token (card) or handled by
1146 the gpg-agent. Print the serial number of that token
1147 here. */
1148 for (i=0; i < sk->protect.ivlen; i++)
1149 printf ("%02X", sk->protect.iv[i]);
1151 putchar (':'); /* End of field 15. */
1153 putchar('\n');
1154 if (pk)
1155 print_revokers (pk);
1156 if (fpr)
1157 print_fingerprint (pk, sk, 0);
1158 if (opt.with_key_data)
1159 print_key_data (pk);
1162 for ( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; )
1164 if ( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode )
1166 char *str;
1167 PKT_user_id *uid=node->pkt->pkt.user_id;
1169 if (attrib_fp && node->pkt->pkt.user_id->attrib_data != NULL)
1170 dump_attribs (node->pkt->pkt.user_id,pk,sk);
1172 * Fixme: We need a is_valid flag here too
1174 str = uid->attrib_data? "uat":"uid";
1175 /* If we're listing a secret key, leave out the validity
1176 values for now. This is handled better in 1.9. */
1177 if (sk)
1178 printf ("%s:::::",str);
1179 else if ( uid->is_revoked )
1180 printf ("%s:r::::",str);
1181 else if ( uid->is_expired )
1182 printf ("%s:e::::",str);
1183 else if ( opt.no_expensive_trust_checks )
1184 printf ("%s:::::",str);
1185 else
1187 int uid_validity;
1189 if ( pk && !ulti_hack )
1190 uid_validity=get_validity_info (pk, uid);
1191 else
1192 uid_validity = 'u';
1193 printf ("%s:%c::::",str,uid_validity);
1196 printf ("%s:", colon_strtime (uid->created));
1197 printf ("%s:", colon_strtime (uid->expiredate));
1199 namehash_from_uid (uid);
1201 for (i=0; i < 20; i++ )
1202 printf ("%02X",uid->namehash[i]);
1204 printf ("::");
1206 if (uid->attrib_data)
1207 printf ("%u %lu",uid->numattribs,uid->attrib_len);
1208 else
1209 print_string (stdout,uid->name,uid->len, ':' );
1210 putchar (':');
1211 putchar ('\n');
1213 else if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1215 u32 keyid2[2];
1216 PKT_public_key *pk2 = node->pkt->pkt.public_key;
1218 keyid_from_pk ( pk2, keyid2 );
1219 fputs ("sub:", stdout );
1220 if ( !pk2->is_valid )
1221 putchar ('i');
1222 else if ( pk2->is_revoked )
1223 putchar ('r');
1224 else if ( pk2->has_expired )
1225 putchar ('e');
1226 else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1228 else
1230 /* TRUSTLETTER should always be defined here. */
1231 if (trustletter)
1232 printf ("%c", trustletter );
1234 printf(":%u:%d:%08lX%08lX:%s:%s:::::",
1235 nbits_from_pk( pk2 ),
1236 pk2->pubkey_algo,
1237 (ulong)keyid2[0],(ulong)keyid2[1],
1238 colon_datestr_from_pk( pk2 ),
1239 colon_strtime (pk2->expiredate)
1240 /* fixme: add LID and ownertrust here */
1242 print_capabilities (pk2, NULL, NULL);
1243 putchar ('\n');
1244 if ( fpr > 1 )
1245 print_fingerprint ( pk2, NULL, 0 );
1246 if ( opt.with_key_data )
1247 print_key_data( pk2 );
1249 else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
1251 u32 keyid2[2];
1252 PKT_secret_key *sk2 = node->pkt->pkt.secret_key;
1254 keyid_from_sk ( sk2, keyid2 );
1255 printf ("ssb::%u:%d:%08lX%08lX:%s:%s:::::",
1256 nbits_from_sk( sk2 ),
1257 sk2->pubkey_algo,
1258 (ulong)keyid2[0],(ulong)keyid2[1],
1259 colon_datestr_from_sk( sk2 ),
1260 colon_strtime (sk2->expiredate)
1261 /* fixme: add LID */ );
1262 print_capabilities (NULL, sk2, NULL);
1263 putchar(':'); /* End of field 13. */
1264 putchar(':'); /* End of field 14. */
1265 if (sk2->protect.s2k.mode == 1001)
1266 putchar ('#'); /* Key is just a stub. */
1267 else if (sk2->protect.s2k.mode == 1002)
1269 /* Key is stored on an external token (card) or handled by
1270 the gpg-agent. Print the serial number of that token
1271 here. */
1272 for (i=0; i < sk2->protect.ivlen; i++)
1273 printf ("%02X", sk2->protect.iv[i]);
1275 putchar(':'); /* End of field 15. */
1276 putchar ('\n');
1278 if ( fpr > 1 )
1279 print_fingerprint ( NULL, sk2, 0 );
1281 else if ( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE )
1283 PKT_signature *sig = node->pkt->pkt.signature;
1284 int sigrc,fprokay=0;
1285 char *sigstr;
1286 size_t fplen;
1287 byte fparray[MAX_FINGERPRINT_LEN];
1289 if ( sig->sig_class == 0x20 || sig->sig_class == 0x28
1290 || sig->sig_class == 0x30 )
1291 sigstr = "rev";
1292 else if ( (sig->sig_class&~3) == 0x10 )
1293 sigstr = "sig";
1294 else if ( sig->sig_class == 0x18 )
1295 sigstr = "sig";
1296 else if ( sig->sig_class == 0x1F )
1297 sigstr = "sig";
1298 else
1300 printf ("sig::::::::::%02x%c:\n",
1301 sig->sig_class, sig->flags.exportable?'x':'l');
1302 continue;
1305 if ( opt.check_sigs )
1307 PKT_public_key *signer_pk=NULL;
1309 fflush (stdout);
1310 if (opt.no_sig_cache)
1311 signer_pk = xmalloc_clear (sizeof(PKT_public_key));
1313 rc = check_key_signature2 ( keyblock, node, NULL, signer_pk,
1314 NULL, NULL, NULL );
1315 switch ( gpg_err_code (rc) )
1317 case 0: sigrc = '!'; break;
1318 case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break;
1319 case GPG_ERR_NO_PUBKEY:
1320 case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break;
1321 default: sigrc = '%'; break;
1324 if (opt.no_sig_cache)
1326 if (!rc)
1328 fingerprint_from_pk (signer_pk, fparray, &fplen);
1329 fprokay = 1;
1331 free_public_key(signer_pk);
1334 else
1336 rc = 0;
1337 sigrc = ' ';
1339 fputs ( sigstr, stdout );
1340 putchar (':');
1341 if ( sigrc != ' ' )
1342 putchar (sigrc);
1343 printf ("::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo,
1344 (ulong)sig->keyid[0], (ulong)sig->keyid[1],
1345 colon_datestr_from_sig(sig),
1346 colon_expirestr_from_sig(sig));
1348 if (sig->trust_depth || sig->trust_value)
1349 printf("%d %d",sig->trust_depth,sig->trust_value);
1350 printf (":");
1352 if (sig->trust_regexp)
1353 print_string (stdout,sig->trust_regexp,
1354 strlen(sig->trust_regexp),':');
1355 printf(":");
1357 if ( sigrc == '%' )
1358 printf("[%s] ", g10_errstr(rc) );
1359 else if ( sigrc == '?' )
1361 else if ( !opt.fast_list_mode )
1363 size_t n;
1364 char *p = get_user_id( sig->keyid, &n );
1365 print_string( stdout, p, n, ':' );
1366 xfree(p);
1368 printf (":%02x%c:", sig->sig_class,sig->flags.exportable?'x':'l');
1370 if (opt.no_sig_cache && opt.check_sigs && fprokay)
1372 putchar (':');
1374 for (i=0; i < fplen ; i++ )
1375 printf ("%02X", fparray[i] );
1377 putchar (':');
1380 printf ("\n");
1382 if (opt.show_subpackets)
1383 print_subpackets_colon (sig);
1385 /* fixme: check or list other sigs here */
1391 * Reorder the keyblock so that the primary user ID (and not attribute
1392 * packet) comes first. Fixme: Replace this by a generic sort
1393 * function. */
1394 static void
1395 do_reorder_keyblock (KBNODE keyblock,int attr)
1397 KBNODE primary = NULL, primary0 = NULL, primary2 = NULL;
1398 KBNODE last, node;
1400 for (node=keyblock; node; primary0=node, node = node->next) {
1401 if( node->pkt->pkttype == PKT_USER_ID &&
1402 ((attr && node->pkt->pkt.user_id->attrib_data) ||
1403 (!attr && !node->pkt->pkt.user_id->attrib_data)) &&
1404 node->pkt->pkt.user_id->is_primary ) {
1405 primary = primary2 = node;
1406 for (node=node->next; node; primary2=node, node = node->next ) {
1407 if( node->pkt->pkttype == PKT_USER_ID
1408 || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1409 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1410 break;
1413 break;
1416 if ( !primary )
1417 return; /* no primary key flag found (should not happen) */
1419 for (last=NULL, node=keyblock; node; last = node, node = node->next) {
1420 if( node->pkt->pkttype == PKT_USER_ID )
1421 break;
1423 assert (node);
1424 assert (last); /* the user ID is never the first packet */
1425 assert (primary0); /* ditto (this is the node before primary) */
1426 if ( node == primary )
1427 return; /* already the first one */
1429 last->next = primary;
1430 primary0->next = primary2->next;
1431 primary2->next = node;
1434 void
1435 reorder_keyblock (KBNODE keyblock)
1437 do_reorder_keyblock(keyblock,1);
1438 do_reorder_keyblock(keyblock,0);
1441 void
1442 list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque )
1444 reorder_keyblock (keyblock);
1445 if (opt.with_colons)
1446 list_keyblock_colon (keyblock, secret, fpr );
1447 else
1448 list_keyblock_print (keyblock, secret, fpr, opaque );
1452 * standard function to print the finperprint.
1453 * mode 0: as used in key listings, opt.with_colons is honored
1454 * 1: print using log_info ()
1455 * 2: direct use of tty
1456 * 3: direct use of tty but only primary key.
1457 * modes 1 and 2 will try and print both subkey and primary key fingerprints
1459 void
1460 print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode )
1462 byte array[MAX_FINGERPRINT_LEN], *p;
1463 size_t i, n;
1464 FILE *fp;
1465 const char *text;
1466 int primary=0;
1468 if(sk)
1470 if(sk->main_keyid[0]==sk->keyid[0] && sk->main_keyid[1]==sk->keyid[1])
1471 primary=1;
1473 else
1475 if(pk->main_keyid[0]==pk->keyid[0] && pk->main_keyid[1]==pk->keyid[1])
1476 primary=1;
1479 /* Just to be safe */
1480 if(mode&0x80 && !primary)
1482 log_error("primary key is not really primary!\n");
1483 return;
1486 mode&=~0x80;
1488 if(!primary && (mode==1 || mode==2))
1490 if(sk)
1492 PKT_secret_key *primary_sk=xmalloc_clear(sizeof(*primary_sk));
1493 get_seckey(primary_sk,sk->main_keyid);
1494 print_fingerprint(NULL,primary_sk,mode|0x80);
1495 free_secret_key(primary_sk);
1497 else
1499 PKT_public_key *primary_pk=xmalloc_clear(sizeof(*primary_pk));
1500 get_pubkey(primary_pk,pk->main_keyid);
1501 print_fingerprint(primary_pk,NULL,mode|0x80);
1502 free_public_key(primary_pk);
1506 if (mode == 1) {
1507 fp = log_get_stream ();
1508 if(primary)
1509 text = _("Primary key fingerprint:");
1510 else
1511 text = _(" Subkey fingerprint:");
1513 else if (mode == 2) {
1514 fp = NULL; /* use tty */
1515 if(primary)
1516 /* TRANSLATORS: this should fit into 24 bytes to that the
1517 * fingerprint data is properly aligned with the user ID */
1518 text = _(" Primary key fingerprint:");
1519 else
1520 text = _(" Subkey fingerprint:");
1522 else if (mode == 3) {
1523 fp = NULL; /* use tty */
1524 text = _(" Key fingerprint =");
1526 else {
1527 fp = stdout;
1528 text = _(" Key fingerprint =");
1531 if (sk)
1532 fingerprint_from_sk (sk, array, &n);
1533 else
1534 fingerprint_from_pk (pk, array, &n);
1535 p = array;
1536 if (opt.with_colons && !mode) {
1537 fprintf (fp, "fpr:::::::::");
1538 for (i=0; i < n ; i++, p++ )
1539 fprintf (fp, "%02X", *p );
1540 putc(':', fp);
1542 else {
1543 if (fp)
1544 fputs (text, fp);
1545 else
1546 tty_printf ("%s", text);
1547 if (n == 20) {
1548 for (i=0; i < n ; i++, i++, p += 2 ) {
1549 if (fp) {
1550 if (i == 10 )
1551 putc(' ', fp);
1552 fprintf (fp, " %02X%02X", *p, p[1] );
1554 else {
1555 if (i == 10 )
1556 tty_printf (" ");
1557 tty_printf (" %02X%02X", *p, p[1]);
1561 else {
1562 for (i=0; i < n ; i++, p++ ) {
1563 if (fp) {
1564 if (i && !(i%8) )
1565 putc (' ', fp);
1566 fprintf (fp, " %02X", *p );
1568 else {
1569 if (i && !(i%8) )
1570 tty_printf (" ");
1571 tty_printf (" %02X", *p );
1576 if (fp)
1577 putc ('\n', fp);
1578 else
1579 tty_printf ("\n");
1582 /* Print the serial number of an OpenPGP card if available. */
1583 static void
1584 print_card_serialno (PKT_secret_key *sk)
1586 int i;
1588 if (!sk)
1589 return;
1590 if (!sk->is_protected || sk->protect.s2k.mode != 1002)
1591 return; /* Not a card. */
1592 if (opt.with_colons)
1593 return; /* Handled elsewhere. */
1595 fputs (_(" Card serial no. ="), stdout);
1596 putchar (' ');
1597 if (sk->protect.ivlen == 16
1598 && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6) )
1599 { /* This is an OpenPGP card. Just print the relevant part. */
1600 for (i=8; i < 14; i++)
1602 if (i == 10)
1603 putchar (' ');
1604 printf ("%02X", sk->protect.iv[i]);
1607 else
1608 { /* Something is wrong: Print all. */
1609 for (i=0; i < sk->protect.ivlen; i++)
1610 printf ("%02X", sk->protect.iv[i]);
1612 putchar ('\n');
1617 void
1618 set_attrib_fd (int fd)
1620 static int last_fd=-1;
1622 if ( fd != -1 && last_fd == fd )
1623 return;
1625 if ( attrib_fp && attrib_fp != stdout && attrib_fp != stderr
1626 && attrib_fp != log_get_stream () )
1627 fclose (attrib_fp);
1628 attrib_fp = NULL;
1629 if ( fd == -1 )
1630 return;
1632 #ifdef HAVE_DOSISH_SYSTEM
1633 setmode (fd, O_BINARY);
1634 #endif
1635 if( fd == 1 )
1636 attrib_fp = stdout;
1637 else if( fd == 2 )
1638 attrib_fp = stderr;
1639 else
1640 attrib_fp = fdopen (fd, "wb");
1641 if (!attrib_fp)
1643 log_fatal("can't open fd %d for attribute output: %s\n",
1644 fd, strerror(errno));
1647 last_fd = fd;