From 0fe6a1287fe447afb852dd9b4734c374c90d0740 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 24 Jul 2003 09:06:43 +0000 Subject: [PATCH] * g10.c: New command --card-status. * card-util.c (card_status): New. * call-agent.c (learn_status_cb): Parse more information. * keylist.c (print_pubkey_info): Add FP arg for optinal printing to a stream. Changed all callers. --- g10/ChangeLog | 9 +++ g10/call-agent.c | 52 +++++++++++++++++ g10/call-agent.h | 9 +++ g10/card-util.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++- g10/delkey.c | 2 +- g10/g10.c | 10 ++++ g10/keygen.c | 2 +- g10/keylist.c | 30 +++++++--- g10/main.h | 4 +- g10/revoke.c | 2 +- 10 files changed, 253 insertions(+), 13 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index f7fdea707..a7f8d4eb7 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,12 @@ +2003-07-24 Werner Koch + + * g10.c: New command --card-status. + * card-util.c (card_status): New. + * call-agent.c (learn_status_cb): Parse more information. + + * keylist.c (print_pubkey_info): Add FP arg for optinal printing + to a stream. Changed all callers. + 2003-07-23 Werner Koch * keygen.c (generate_keypair): Create an AUTHKEYTYPE entry for cards. diff --git a/g10/call-agent.c b/g10/call-agent.c index 3b40cd0dd..ed4fa9054 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -458,7 +458,9 @@ agent_release_card_info (struct agent_card_info_s *info) xfree (info->serialno); info->serialno = NULL; xfree (info->disp_name); info->disp_name = NULL; + xfree (info->disp_lang); info->disp_lang = NULL; xfree (info->pubkey_url); info->pubkey_url = NULL; + xfree (info->login_data); info->login_data = NULL; info->fpr1valid = info->fpr2valid = info->fpr3valid = 0; } @@ -468,6 +470,7 @@ learn_status_cb (void *opaque, const char *line) struct agent_card_info_s *parm = opaque; const char *keyword = line; int keywordlen; + int i; for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) ; @@ -482,10 +485,59 @@ learn_status_cb (void *opaque, const char *line) { parm->disp_name = unescape_status_string (line); } + else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen)) + { + parm->disp_lang = unescape_status_string (line); + } + else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen)) + { + parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0; + } else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen)) { parm->pubkey_url = unescape_status_string (line); } + else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen)) + { + parm->login_data = unescape_status_string (line); + } + else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen)) + { + parm->sig_counter = strtoul (line, NULL, 0); + } + else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen)) + { + char *p, *buf; + + buf = p = unescape_status_string (line); + if (buf) + { + while (spacep (p)) + p++; + parm->chv1_cached = atoi (p); + while (!spacep (p)) + p++; + while (spacep (p)) + p++; + for (i=0; *p && i < 3; i++) + { + parm->chvmaxlen[i] = atoi (p); + while (!spacep (p)) + p++; + while (spacep (p)) + p++; + } + for (i=0; *p && i < 3; i++) + { + parm->chvretry[i] = atoi (p); + while (!spacep (p)) + p++; + while (spacep (p)) + p++; + } + xfree (buf); + } + } else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen)) { int no = atoi (line); diff --git a/g10/call-agent.h b/g10/call-agent.h index 434295e79..e8abfbc7b 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -25,13 +25,22 @@ struct agent_card_info_s { int error; /* private. */ char *serialno; /* malloced hex string. */ char *disp_name; /* malloced. */ + char *disp_lang; /* malloced. */ + int disp_sex; /* 0 = unspecified, 1 = male, 2 = female */ char *pubkey_url; /* malloced. */ + char *login_data; /* malloced. */ char fpr1valid; char fpr2valid; char fpr3valid; char fpr1[20]; char fpr2[20]; char fpr3[20]; + unsigned long sig_counter; + int chv1_cached; /* True if a PIN is not required for each + signing. Note that the gpg-agent might cache + it anyway. */ + int chvmaxlen[3]; /* Maximum allowed length of a CHV. */ + int chvretry[3]; /* Allowed retries for the CHV; 0 = blocked. */ }; struct agent_card_genkey_s { diff --git a/g10/card-util.c b/g10/card-util.c index 36c432aee..9f665cc74 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -28,6 +28,8 @@ #include "gpg.h" #include "util.h" #include "i18n.h" +#include "ttyio.h" +#include "status.h" #include "options.h" #include "main.h" #include "call-agent.h" @@ -64,7 +66,6 @@ change_pin (int chvno) for (;;) { char *answer; - int reread = 0; tty_printf ("\n"); tty_printf ("1 - change signature PIN\n" @@ -111,6 +112,149 @@ change_pin (int chvno) } +static const char * +get_manufacturer (unsigned int no) +{ + switch (no) + { + case 0: + case 0xffff: return "test card"; + case 0x0001: return "PPC Card Systems"; + default: return "unknown"; + } +} + + +static void +print_sha1_fpr (FILE *fp, const unsigned char *fpr) +{ + int i; + + if (fpr) + { + for (i=0; i < 20 ; i+=2, fpr += 2 ) + { + if (i == 10 ) + putc (' ', fp); + fprintf (fp, " %02X%02X", *fpr, fpr[1]); + } + } + else + fputs (" [none]", fp); + putc ('\n', fp); +} + + +static void +print_name (FILE *fp, const char *text, const char *name) +{ + fputs (text, fp); + + if (name && *name) + print_utf8_string2 (fp, name, strlen (name), '\n'); + else + fputs (_("[not set]"), fp); + putc ('\n', fp); +} + +static void +print_isoname (FILE *fp, const char *text, const char *name) +{ + fputs (text, fp); + + if (name && *name) + { + char *p, *given, *buf = xstrdup (name); + + given = strstr (buf, "<<"); + for (p=buf; *p; p++) + if (*p == '<') + *p = ' '; + if (given && given[2]) + { + *given = 0; + given += 2; + print_utf8_string2 (fp, given, strlen (given), '\n'); + if (*buf) + putc (' ', fp); + } + print_utf8_string2 (fp, buf, strlen (buf), '\n'); + xfree (buf); + } + else + fputs (_("[not set]"), fp); + putc ('\n', fp); +} + + +/* Print all available information about the current card. */ +void +card_status (FILE *fp) +{ + struct agent_card_info_s info; + PKT_public_key *pk = xcalloc (1, sizeof *pk); + int rc; + + rc = agent_learn (&info); + if (rc) + { + log_error (_("OpenPGP card not available: %s\n"), + gpg_strerror (rc)); + return; + } + + fprintf (fp, "Application ID ...: %s\n", + info.serialno? info.serialno : "[none]"); + if (!info.serialno || strncmp (info.serialno, "D27600012401", 12) + || strlen (info.serialno) != 32 ) + { + log_info ("not an OpenPGP card\n"); + agent_release_card_info (&info); + } + fprintf (fp, "Version ..........: %.1s%c.%.1s%c\n", + info.serialno[12] == '0'?"":info.serialno+12, + info.serialno[13], + info.serialno[14] == '0'?"":info.serialno+14, + info.serialno[15]); + fprintf (fp, "Manufacturer .....: %s\n", + get_manufacturer (xtoi_2(info.serialno+16)*256 + + xtoi_2 (info.serialno+18))); + fprintf (fp, "Serial number ....: %.8s\n", info.serialno+20); + + print_isoname (fp, "Name of cardholder: ", info.disp_name); + print_name (fp, "Language prefs ...: ", info.disp_lang); + fprintf (fp, "Sex ..............: %s\n", info.disp_sex == 1? _("male"): + info.disp_sex == 2? _("female") : _("unspecified")); + print_name (fp, "URL of public key : ", info.pubkey_url); + print_name (fp, "Login data .......: ", info.login_data); + fprintf (fp, "Signature PIN ....: %s\n", + info.chv1_cached? _("cached"): _("not cached")); + fprintf (fp, "Max. PIN lengths .: %d %d %d\n", + info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]); + fprintf (fp, "PIN retry counter : %d %d %d\n", + info.chvretry[0], info.chvretry[1], info.chvretry[2]); + fputs ("Signature key ....:", fp); + print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL); + fputs ("Encryption key....:", fp); + print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL); + fputs ("Authentication key:", fp); + print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL); + fputs ("General key info..: ", fp); + if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20)) + print_pubkey_info (fp, pk); + else + fputs ("[none]\n", fp); + fprintf (fp, "Signature counter : %lu\n", info.sig_counter); + + free_public_key (pk); + agent_release_card_info (&info); +} + + + + + + diff --git a/g10/delkey.c b/g10/delkey.c index 34a2e1b32..6263dec47 100644 --- a/g10/delkey.c +++ b/g10/delkey.c @@ -130,7 +130,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) if( secret ) print_seckey_info( sk ); else - print_pubkey_info( pk ); + print_pubkey_info (NULL, pk ); tty_printf( "\n" ); yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay" diff --git a/g10/g10.c b/g10/g10.c index b7ad9d746..2f0a78cd0 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -128,6 +128,7 @@ enum cmd_and_opt_values { aNull = 0, aPipeMode, aRebuildKeydbCaches, aRefreshKeys, + aCardStatus, aChangePIN, oTextmode, @@ -363,6 +364,7 @@ static ARGPARSE_OPTS opts[] = { { aExportSecretSub, "export-secret-subkeys" , 256, "@" }, { aImport, "import", 256 , N_("import/merge keys")}, { aFastImport, "fast-import", 256 , "@"}, + { aCardStatus, "card-status", 256, N_("print the card status")}, { aChangePIN, "change-pin", 256, N_("change a card's PIN")}, { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, @@ -1444,6 +1446,7 @@ main( int argc, char **argv ) case aPipeMode: set_cmd( &cmd, aPipeMode); break; case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break; + case aCardStatus: set_cmd (&cmd, aCardStatus); break; case aChangePIN: set_cmd (&cmd, aChangePIN); break; case oArmor: opt.armor = 1; opt.no_armor=0; break; @@ -2346,6 +2349,7 @@ main( int argc, char **argv ) case aDeArmor: case aEnArmor: case aFixTrustDB: + case aCardStatus: case aChangePIN: break; case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break; @@ -2867,6 +2871,12 @@ main( int argc, char **argv ) keydb_rebuild_caches (); break; + case aCardStatus: + if (argc) + wrong_args ("--card-status"); + card_status (stdout); + break; + case aChangePIN: if (!argc) change_pin (0); diff --git a/g10/keygen.c b/g10/keygen.c index e2552085a..515d4867a 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -2712,7 +2712,7 @@ show_smartcard (struct agent_card_info_s *info) show_sha1_fpr (info->fpr3valid? info->fpr3:NULL); if (info->fpr1valid && !get_pubkey_byfprint (pk, info->fpr1, 20)) - print_pubkey_info (pk); + print_pubkey_info (NULL, pk); free_public_key( pk ); } diff --git a/g10/keylist.c b/g10/keylist.c index ef2cb5676..b5549fb47 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -93,25 +93,39 @@ print_seckey_info (PKT_secret_key *sk) tty_printf ("\n"); } +/* Print information about the public key. With FP passed as NULL, + the tty output interface is used, otherwise output is directted to + the given stream. */ void -print_pubkey_info (PKT_public_key *pk) +print_pubkey_info (FILE *fp, PKT_public_key *pk) { u32 pk_keyid[2]; size_t n; char *p; keyid_from_pk (pk, pk_keyid); - tty_printf ("\npub %4u%c/%08lX %s ", - nbits_from_pk (pk), - pubkey_letter (pk->pubkey_algo), - (ulong)pk_keyid[1], datestr_from_pk (pk)); - + if (fp) + fprintf (fp, "pub %4u%c/%08lX %s ", + nbits_from_pk (pk), + pubkey_letter (pk->pubkey_algo), + (ulong)pk_keyid[1], datestr_from_pk (pk)); + else + tty_printf ("\npub %4u%c/%08lX %s ", + nbits_from_pk (pk), + pubkey_letter (pk->pubkey_algo), + (ulong)pk_keyid[1], datestr_from_pk (pk)); p = get_user_id (pk_keyid, &n); - tty_print_utf8_string (p, n); + if (fp) + print_utf8_string2 (fp, p, n, '\n'); + else + tty_print_utf8_string (p, n); xfree (p); - tty_printf ("\n\n"); + if (fp) + putc ('\n', fp); + else + tty_printf ("\n\n"); } /* diff --git a/g10/main.h b/g10/main.h index 991c09a3d..cb81192d3 100644 --- a/g10/main.h +++ b/g10/main.h @@ -236,7 +236,7 @@ void dump_attribs(const PKT_user_id *uid, PKT_public_key *pk,PKT_secret_key *sk); void set_attrib_fd(int fd); void print_seckey_info (PKT_secret_key *sk); -void print_pubkey_info (PKT_public_key *pk); +void print_pubkey_info (FILE *fp, PKT_public_key *pk); /*-- verify.c --*/ void print_file_status( int status, const char *name, int what ); @@ -256,6 +256,8 @@ void run_in_pipemode (void); /*-- card-util.c --*/ void change_pin (int no); +void card_status (FILE *fp); + /*-- signal.c --*/ void init_signals(void); diff --git a/g10/revoke.c b/g10/revoke.c index 80e32a32e..cf1bfe17a 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -264,7 +264,7 @@ gen_desig_revoke( const char *uname ) any = 1; - print_pubkey_info (pk); + print_pubkey_info (NULL, pk); tty_printf ("\n"); tty_printf (_("To be revoked by:\n"));