aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2003-10-29 10:07:44 +0000
committerWerner Koch <[email protected]>2003-10-29 10:07:44 +0000
commitfcc72f915bbafe2e1f1f68be7e79d7b45561da62 (patch)
treecabc573682cc56a710a40e251b33847d38ef1cb9
parent* DETAILS: Add the 'a' value for field 12 and the new field 15. (diff)
downloadgnupg-fcc72f915bbafe2e1f1f68be7e79d7b45561da62.tar.gz
gnupg-fcc72f915bbafe2e1f1f68be7e79d7b45561da62.zip
* cardglue.c (open_card): Ask for card insertion.
(check_card_serialno): New. (agent_scd_pksign, agent_scd_pkdecrypt): Use it here. * cardglue.c (open_card): Issue insertion status message. * status.h, status.c (STATUS_CARDCTRL): New. * status.c (cpr_get_answer_okay_cancel): New. * miscutil.c (answer_is_okay_cancel): New.
-rw-r--r--doc/DETAILS8
-rw-r--r--g10/ChangeLog10
-rw-r--r--g10/cardglue.c99
-rw-r--r--g10/status.c45
-rw-r--r--g10/status.h4
-rw-r--r--include/util.h1
-rw-r--r--util/ChangeLog4
-rw-r--r--util/miscutil.c35
8 files changed, 204 insertions, 2 deletions
diff --git a/doc/DETAILS b/doc/DETAILS
index e88300b74..0010f549c 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -462,6 +462,14 @@ more arguments in future versions.
0x02 = this attribute packet is revoked
0x04 = this attribute packet is expired
+ STATUSCTRL <what> [<serialno>]
+ This is used to control smartcard operations.
+ Defined values for WHAT are:
+ 1 = Request insertion of a card. Serialnumber may be given
+ to request a specific card.
+ 2 = Request removal of a card.
+ 3 = Card with serialnumber detected
+
Format of the "--attribute-fd" output
=====================================
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 5896c5d88..2c6b1bc3e 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,13 @@
+2003-10-29 Werner Koch <[email protected]>
+
+ * cardglue.c (open_card): Ask for card insertion.
+ (check_card_serialno): New.
+ (agent_scd_pksign, agent_scd_pkdecrypt): Use it here.
+ * cardglue.c (open_card): Issue insertion status message.
+ * status.h, status.c (STATUS_CARDCTRL): New.
+
+ * status.c (cpr_get_answer_okay_cancel): New.
+
2003-10-28 Werner Koch <[email protected]>
* keylist.c (list_keyblock_print): Denote secrets keys stored on a
diff --git a/g10/cardglue.c b/g10/cardglue.c
index 3173248cb..55729bf7d 100644
--- a/g10/cardglue.c
+++ b/g10/cardglue.c
@@ -20,7 +20,7 @@
#include <config.h>
#ifndef ENABLE_CARD_SUPPORT
-#error no configured for card support.
+#error not configured for card support.
#endif
#include <stdio.h>
#include <stdlib.h>
@@ -36,6 +36,7 @@
#include "util.h"
#include "main.h"
#include "status.h"
+#include "ttyio.h"
#include "i18n.h"
#include "cardglue.h"
@@ -250,6 +251,8 @@ open_card (void)
APP app;
card_close ();
+
+ retry:
slot = apdu_open_reader (default_reader_port);
if (slot == -1)
{
@@ -260,16 +263,42 @@ open_card (void)
app = xcalloc (1, sizeof *app);
app->slot = slot;
rc = app_select_openpgp (app, &app->serialno, &app->serialnolen);
+ if (rc && !opt.batch)
+ {
+ write_status_text (STATUS_CARDCTRL, "1");
+
+ if ( cpr_get_answer_okay_cancel ("cardctrl.insert_card.okay",
+ _("Please insert the card and hit return or enter 'c' to cancel: "),
+ 1) )
+ {
+ apdu_close_reader (slot);
+ xfree (app);
+ goto retry;
+ }
+ }
if (rc)
{
- apdu_close_reader (slot);
log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
+ apdu_close_reader (slot);
xfree (app);
return NULL;
}
app->initialized = 1;
current_app = app;
+ if (is_status_enabled () )
+ {
+ int i;
+ char *p, *buf;
+
+ buf = xmalloc (5 + app->serialnolen * 2 + 1);
+ p = stpcpy (buf, "3 ");
+ for (i=0; i < app->serialnolen; p +=2, i++)
+ sprintf (p, "%02X", app->serialno[i]);
+ write_status_text (STATUS_CARDCTRL, buf);
+ xfree (buf);
+ }
+
return app;
}
@@ -287,6 +316,56 @@ card_close (void)
}
+/* Check that the serial number of the current card (as described by
+ APP) matches SERIALNO. If there is no match and we are not in
+ batch mode, present a prompt to insert the desired card. The
+ function return 0 is the present card is okay, -1 if the user
+ selected to insert a new card or an error value. Note that the
+ card context will be closed in all cases except for 0 as return
+ value. */
+static int
+check_card_serialno (APP app, const char *serialno)
+{
+ const char *s;
+ int ask = 0;
+ int n;
+
+ for (s = serialno, n=0; *s != '/' && hexdigitp (s); s++, n++)
+ ;
+ if (n != 32)
+ {
+ log_error ("invalid serial number in keyring detected\n");
+ return gpg_error (GPG_ERR_INV_ID);
+ }
+ if (app->serialnolen != 16)
+ ask = 1;
+ for (s = serialno, n=0; !ask && n < 16; s += 2, n++)
+ if (app->serialno[n] != xtoi_2 (s))
+ ask = 1;
+ if (ask)
+ {
+ char buf[5+32+1];
+
+ card_close ();
+ tty_printf (_("Please remove the current card and "
+ "insert the one with the serial number:\n"
+ " %.*s\n"), 32, serialno);
+
+ sprintf (buf, "1 %.32s", serialno);
+ write_status_text (STATUS_CARDCTRL, buf);
+
+ if ( cpr_get_answer_okay_cancel ("cardctrl.change_card.okay",
+ _("Hit return when ready "
+ "or enter 'c' to cancel: "),
+ 1) )
+ return -1;
+ return gpg_error (GPG_ERR_INV_ID);
+ }
+ return 0;
+}
+
+
+
/* Return a new malloced string by unescaping the string S. Escaping
is percent escaping and '+'/space mapping. A binary nul will
silently be replaced by a 0xFF. Function returns NULL to indicate
@@ -626,14 +705,21 @@ agent_scd_pksign (const char *serialno, int hashalgo,
unsigned char **r_buf, size_t *r_buflen)
{
APP app;
+ int rc;
*r_buf = NULL;
*r_buflen = 0;
+ retry:
app = current_app? current_app : open_card ();
if (!app)
return gpg_error (GPG_ERR_CARD);
/* Check that the card's serialnumber is as required.*/
+ rc = check_card_serialno (app, serialno);
+ if (rc == -1)
+ goto retry;
+ if (rc)
+ return rc;
return app->fnc.sign (app, serialno, hashalgo,
pin_cb, NULL,
@@ -649,13 +735,22 @@ agent_scd_pkdecrypt (const char *serialno,
unsigned char **r_buf, size_t *r_buflen)
{
APP app;
+ int rc;
*r_buf = NULL;
*r_buflen = 0;
+ retry:
app = current_app? current_app : open_card ();
if (!app)
return gpg_error (GPG_ERR_CARD);
+ /* Check that the card's serialnumber is as required.*/
+ rc = check_card_serialno (app, serialno);
+ if (rc == -1)
+ goto retry;
+ if (rc)
+ return rc;
+
return app->fnc.decipher (app, serialno,
pin_cb, NULL,
indata, indatalen,
diff --git a/g10/status.c b/g10/status.c
index cde0c8d77..d39bc683b 100644
--- a/g10/status.c
+++ b/g10/status.c
@@ -150,6 +150,7 @@ get_status_string ( int no )
case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break;
case STATUS_REVKEYSIG : s = "REVKEYSIG"; break;
case STATUS_ATTRIBUTE : s = "ATTRIBUTE"; break;
+ case STATUS_CARDCTRL : s = "CARDCTRL"; break;
default: s = "?"; break;
}
return s;
@@ -692,3 +693,47 @@ cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt )
}
}
}
+
+
+int
+cpr_get_answer_okay_cancel (const char *keyword,
+ const char *prompt,
+ int def_answer)
+{
+ int yes;
+ char *answer = NULL;
+ char *p;
+
+ if( opt.command_fd != -1 )
+ answer = do_get_from_fd ( keyword, 0, 0 );
+#ifdef USE_SHM_COPROCESSING
+ else if( opt.shm_coprocess )
+ answer = do_shm_get( keyword, 0, 0 );
+#endif
+
+ if (answer)
+ {
+ yes = answer_is_okay_cancel (answer, def_answer);
+ m_free (answer);
+ return yes;
+ }
+
+ for(;;)
+ {
+ p = tty_get( prompt );
+ trim_spaces(p); /* it is okay to do this here */
+ if (*p == '?' && !p[1])
+ {
+ m_free(p);
+ display_online_help (keyword);
+ }
+ else
+ {
+ tty_kill_prompt();
+ yes = answer_is_okay_cancel (p, def_answer);
+ m_free(p);
+ return yes;
+ }
+ }
+}
+
diff --git a/g10/status.h b/g10/status.h
index 68da60d28..73cc3f1a9 100644
--- a/g10/status.h
+++ b/g10/status.h
@@ -100,6 +100,7 @@
#define STATUS_IMPORT_OK 68
#define STATUS_IMPORT_CHECK 69
#define STATUS_REVKEYSIG 70
+#define STATUS_CARDCTRL 71
/*-- status.c --*/
void set_status_fd ( int fd );
@@ -123,6 +124,9 @@ char *cpr_get_hidden( const char *keyword, const char *prompt );
void cpr_kill_prompt(void);
int cpr_get_answer_is_yes( const char *keyword, const char *prompt );
int cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt );
+int cpr_get_answer_okay_cancel (const char *keyword,
+ const char *prompt,
+ int def_answer);
#endif /*G10_STATUS_H*/
diff --git a/include/util.h b/include/util.h
index 08ea7a78e..da2758a02 100644
--- a/include/util.h
+++ b/include/util.h
@@ -175,6 +175,7 @@ char *make_printable_string( const byte *p, size_t n, int delim );
int answer_is_yes_no_default( const char *s, int def_answer );
int answer_is_yes( const char *s );
int answer_is_yes_no_quit( const char *s );
+int answer_is_okay_cancel (const char *s, int def_answer);
/*-- strgutil.c --*/
void free_strlist( STRLIST sl );
diff --git a/util/ChangeLog b/util/ChangeLog
index 50e25370b..5501fd5c8 100644
--- a/util/ChangeLog
+++ b/util/ChangeLog
@@ -1,3 +1,7 @@
+2003-10-29 Werner Koch <[email protected]>
+
+ * miscutil.c (answer_is_okay_cancel): New.
+
2003-10-25 Werner Koch <[email protected]>
* Makefile.am: Replaced INTLLIBS by LIBINTL.
diff --git a/util/miscutil.c b/util/miscutil.c
index b266d27d4..e0ea0e7d2 100644
--- a/util/miscutil.c
+++ b/util/miscutil.c
@@ -359,3 +359,38 @@ answer_is_yes_no_quit( const char *s )
return -1;
return 0;
}
+
+
+/*
+ Return 1 for okay, 0 for for cancel or DEF_ANSWER for default.
+ */
+int
+answer_is_okay_cancel (const char *s, int def_answer)
+{
+ const char *long_okay = _("okay");
+ const char *long_cancel = _("cancel");
+ const char *short_okay = _("oO");
+ const char *short_cancel = _("cC");
+
+ /* Note: We have to use the locale dependent strcasecmp */
+ if ( !strcasecmp(s, long_okay ) )
+ return 1;
+ if ( !strcasecmp(s, long_cancel ) )
+ return 0;
+ if ( *s && strchr( short_okay, *s ) && !s[1] )
+ return 1;
+ if ( *s && strchr( short_cancel, *s ) && !s[1] )
+ return 0;
+ /* Always test for the English values (not locale here) */
+ if ( !ascii_strcasecmp(s, "okay" ) )
+ return 1;
+ if ( !ascii_strcasecmp(s, "ok" ) )
+ return 1;
+ if ( !ascii_strcasecmp(s, "cancel" ) )
+ return 0;
+ if ( *s && strchr( "oO", *s ) && !s[1] )
+ return 1;
+ if ( *s && strchr( "cC", *s ) && !s[1] )
+ return 0;
+ return def_answer;
+}