From 316dc2fd60875bc102bd459a4b3d4a5a59086b02 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 30 Sep 2003 17:34:38 +0000 Subject: [PATCH] * keylist.c (print_card_serialno): New. (list_keyblock_print): Use it here. * card-util.c (toggle_forcesig): New. (card_edit): New command "forcesig". * card-util.c (print_name, print_isoname): Use 0 and not LF fro the max_n arg of tty_print_utf8_string2. * call-agent.c (agent_scd_getattr): New. (learn_status_cb): Release values before assignment so that it can be used by getattr to update the structure. * card-util.c (change_pin): Simplified. We now have only a PIN and an Admin PIN. --- g10/ChangeLog | 18 ++++++++++ g10/call-agent.c | 42 +++++++++++++++++++++--- g10/call-agent.h | 3 ++ g10/card-util.c | 85 +++++++++++++++++++++++++++++++----------------- g10/keylist.c | 41 +++++++++++++++++++++++ 5 files changed, 155 insertions(+), 34 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index f8120230f..0e0e715fc 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,21 @@ +2003-09-30 Werner Koch + + * keylist.c (print_card_serialno): New. + (list_keyblock_print): Use it here. + + * card-util.c (toggle_forcesig): New. + (card_edit): New command "forcesig". + + * card-util.c (print_name, print_isoname): Use 0 and not LF fro + the max_n arg of tty_print_utf8_string2. + + * call-agent.c (agent_scd_getattr): New. + (learn_status_cb): Release values before assignment so that it can + be used by getattr to update the structure. + + * card-util.c (change_pin): Simplified. We now have only a PIN + and an Admin PIN. + 2003-09-27 Werner Koch * sign.c (do_sign): Removed disabled testcode. diff --git a/g10/call-agent.c b/g10/call-agent.c index 00d124f0b..f07c01f2a 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -479,14 +479,17 @@ learn_status_cb (void *opaque, const char *line) if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen)) { + xfree (parm->serialno); parm->serialno = store_serialno (line); } else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen)) { + xfree (parm->disp_name); parm->disp_name = unescape_status_string (line); } else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen)) { + xfree (parm->disp_lang); parm->disp_lang = unescape_status_string (line); } else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen)) @@ -495,10 +498,12 @@ learn_status_cb (void *opaque, const char *line) } else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen)) { + xfree (parm->pubkey_url); parm->pubkey_url = unescape_status_string (line); } else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen)) { + xfree (parm->login_data); parm->login_data = unescape_status_string (line); } else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen)) @@ -574,6 +579,34 @@ agent_learn (struct agent_card_info_s *info) return map_assuan_err (rc); } +/* Call the agent to retrieve a data object. This function returns + the data in the same structure as used by the learn command. It is + allowed to update such a structure using this commmand. */ +int +agent_scd_getattr (const char *name, struct agent_card_info_s *info) +{ + int rc; + char line[ASSUAN_LINELENGTH]; + + if (!*name) + return gpg_error (GPG_ERR_INV_VALUE); + + /* We assume that NAME does not need escaping. */ + if (12 + strlen (name) > DIM(line)-1) + return gpg_error (GPG_ERR_TOO_LARGE); + stpcpy (stpcpy (line, "SCD GETATTR "), name); + + rc = start_agent (); + if (rc) + return rc; + + memset (info, 0, sizeof *info); + rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, + learn_status_cb, info); + + return map_assuan_err (rc); +} + /* Send an setattr command to the SCdaemon. */ int @@ -809,12 +842,11 @@ agent_scd_pkdecrypt (const char *serialno, /* Change the PIN of an OpenPGP card or reset the retry counter. - CHVNO 1: Change the digital signature PIN - 2: Change the decryption and authentication PIN + CHVNO 1: Change the PIN + 2: Same as 1 3: Change the admin PIN - 101: Set a new digital signature PIN and reset the retry counter - 102: Set a decryption and authentication PIN - and reset the retry counter + 101: Set a new PIN and reset the retry counter + 102: Same as 101 */ int agent_scd_change_pin (int chvno) diff --git a/g10/call-agent.h b/g10/call-agent.h index e8abfbc7b..101db9574 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -58,6 +58,9 @@ void agent_release_card_info (struct agent_card_info_s *info); /* Return card info. */ int agent_learn (struct agent_card_info_s *info); +/* Update INFO with the attribute NAME. */ +int agent_scd_getattr (const char *name, struct agent_card_info_s *info); + /* Check whether the secret key for the key identified by HEXKEYGRIP is available. Return 0 for yes or an error code. */ int agent_havekey (const char *hexkeygrip); diff --git a/g10/card-util.c b/g10/card-util.c index f42efde61..1028cd373 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -44,7 +44,6 @@ change_pin (int chvno) { struct agent_card_info_s info; int rc; - int reset_mode = 0; rc = agent_learn (&info); if (rc) @@ -70,17 +69,11 @@ change_pin (int chvno) char *answer; tty_printf ("\n"); - tty_printf ("1 - change signature PIN\n" - "2 - change decryption and authentication PIN\n" - "3 - change Admin's PIN\n" - "R - toggle reset retry counter mode\n" + tty_printf ("1 - change PIN\n" + "2 - unblock PIN\n" + "3 - change Admin PIN\n" "Q - quit\n"); tty_printf ("\n"); - if (reset_mode) - { - tty_printf ("Reset Retry Counter mode active\n"); - tty_printf ("\n"); - } answer = cpr_get("cardutil.change_pin.menu",_("Your selection? ")); cpr_kill_prompt(); @@ -88,30 +81,35 @@ change_pin (int chvno) continue; rc = 0; - if (reset_mode && *answer == '3') + if (*answer == '1') { - tty_printf ("Sorry, reset of the Admin PIN's retry counter " - "is not possible.\n"); - } - else if (*answer == '1' || *answer == '2' || *answer == '3') - { - rc = agent_scd_change_pin (*answer - '0' + (reset_mode?100:0)); + rc = agent_scd_change_pin (1); if (rc) - tty_printf ("Error changing/resetting the PIN: %s\n", - gpg_strerror (rc)); + tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc)); else - tty_printf ("New PIN successfully set.\n"); + tty_printf ("PIN changed.\n"); } - else if (*answer == 'r' || *answer == 'R') + else if (*answer == '2') { - reset_mode = !reset_mode; + rc = agent_scd_change_pin (101); + if (rc) + tty_printf ("Error unblocking the PIN: %s\n", gpg_strerror (rc)); + else + tty_printf ("PIN unblocked and new PIN set.\n"); + } + else if (*answer == '3') + { + rc = agent_scd_change_pin (3); + if (rc) + tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc)); + else + tty_printf ("PIN changed.\n"); } else if (*answer == 'q' || *answer == 'Q') { break; } } - } static const char * @@ -175,7 +173,7 @@ print_name (FILE *fp, const char *text, const char *name) if (fp) print_utf8_string2 (fp, name, strlen (name), '\n'); else - tty_print_utf8_string2 (name, strlen (name), '\n'); + tty_print_utf8_string2 (name, strlen (name), 0); } else tty_fprintf (fp, _("[not set]")); @@ -207,7 +205,7 @@ print_isoname (FILE *fp, const char *text, const char *tag, const char *name) else if (fp) print_utf8_string2 (fp, given, strlen (given), '\n'); else - tty_print_utf8_string2 (given, strlen (given), '\n'); + tty_print_utf8_string2 (given, strlen (given), 0); if (opt.with_colons) putc (':', fp); @@ -220,7 +218,7 @@ print_isoname (FILE *fp, const char *text, const char *tag, const char *name) else if (fp) print_utf8_string2 (fp, buf, strlen (buf), '\n'); else - tty_print_utf8_string2 (buf, strlen (buf), '\n'); + tty_print_utf8_string2 (buf, strlen (buf), 0); xfree (buf); } else @@ -339,7 +337,7 @@ card_status (FILE *fp) print_name (fp, "URL of public key : ", info.pubkey_url); print_name (fp, "Login data .......: ", info.login_data); tty_fprintf (fp, "Signature PIN ....: %s\n", - info.chv1_cached? _("cached"): _("not cached")); + info.chv1_cached? _("not forced"): _("forced")); tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n", info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]); tty_fprintf (fp, "PIN retry counter : %d %d %d\n", @@ -542,6 +540,30 @@ change_sex (void) } +static void +toggle_forcesig (void) +{ + struct agent_card_info_s info; + int rc; + int newstate; + + memset (&info, 0, sizeof info); + rc = agent_scd_getattr ("CHV-STATUS", &info); + if (rc) + { + log_error ("error getting current status: %s\n", gpg_strerror (rc)); + return; + } + newstate = !info.chv1_cached; + agent_release_card_info (&info); + + rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1); + if (rc) + log_error ("error toggling signature PIN flag: %s\n", gpg_strerror (rc)); +} + + + /* Menu to edit all user changeable values on an OpenPGP card. Only Key creation is not handled here. */ void @@ -551,7 +573,7 @@ card_edit (STRLIST commands) cmdNOP = 0, cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG, cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX, - + cmdFORCESIG, cmdINVCMD }; @@ -572,9 +594,10 @@ card_edit (STRLIST commands) { N_("login") , cmdLOGIN , N_("change the login name") }, { N_("lang") , cmdLANG , N_("change the language preferences") }, { N_("sex") , cmdSEX , N_("change card holder's sex") }, + { N_("forcesig"), cmdFORCESIG, N_("toggle the signature force PIN flag") }, { NULL, cmdINVCMD } }; - + enum cmdids cmd = cmdNOP; int have_commands = !!commands; int redisplay = 1; @@ -692,6 +715,10 @@ card_edit (STRLIST commands) change_sex (); break; + case cmdFORCESIG: + toggle_forcesig (); + break; + case cmdQUIT: goto leave; diff --git a/g10/keylist.c b/g10/keylist.c index f4344f204..50850de71 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -41,6 +41,7 @@ static void list_all(int); static void list_one( STRLIST names, int secret); +static void print_card_serialno (PKT_secret_key *sk); struct sig_stats { @@ -710,6 +711,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) if( !any ) { if( fpr ) print_fingerprint( pk, sk, 0 ); + print_card_serialno (sk); if( opt.with_key_data ) print_key_data( pk, keyid ); any = 1; @@ -755,6 +757,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) putchar('\n'); if( fpr ) print_fingerprint( pk, sk, 0 ); /* of the main key */ + print_card_serialno (sk); any = 1; } @@ -770,7 +773,10 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) printf(_(" [expires: %s]"), expirestr_from_sk( sk2 ) ); putchar('\n'); if( fpr > 1 ) + { print_fingerprint( NULL, sk2, 0 ); + print_card_serialno (sk); + } } else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) { PKT_signature *sig = node->pkt->pkt.signature; @@ -813,6 +819,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) putchar('\n'); if( fpr ) print_fingerprint( pk, sk, 0 ); + print_card_serialno (sk); any=1; } @@ -1398,6 +1405,40 @@ print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode ) tty_printf ("\n"); } + +/* Print the serial number of an OpenPGP card if available. */ +static void +print_card_serialno (PKT_secret_key *sk) +{ + int i; + + if (!sk) + return; + if (!sk->is_protected || sk->protect.s2k.mode != 1002) + return; /* Not a card. */ + if (opt.with_colons) + return; /* Format not yet defined. */ + + fputs (_(" Card serial no. ="), stdout); + putchar (' '); + if (sk->protect.ivlen == 16 + && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6) ) + { /* This is an OpenPGP card. Just print the relevant part. */ + for (i=8; i < 14; i++) + { + if (i == 10) + putchar (' '); + printf ("%02X", sk->protect.iv[i]); + } + } + else + { /* Something is wrong: Print all. */ + for (i=0; i < sk->protect.ivlen; i++) + printf ("%02X", sk->protect.iv[i]); + } + putchar ('\n'); +} + void set_attrib_fd(int fd) { static int last_fd=-1;