aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2010-05-03 11:10:49 +0000
committerWerner Koch <[email protected]>2011-01-25 20:51:58 +0000
commitca2d3157656d542ceec50607d0b92f13542a0fe7 (patch)
tree45557ff38af38a9eca3690dadbbf4a7523974487
parentFix setting of default homedir for Wince (diff)
downloadgnupg-ca2d3157656d542ceec50607d0b92f13542a0fe7.tar.gz
gnupg-ca2d3157656d542ceec50607d0b92f13542a0fe7.zip
Detect non operational readers.
Backport from 2.0.
Diffstat (limited to '')
-rw-r--r--scd/ChangeLog13
-rw-r--r--scd/apdu.c20
-rw-r--r--scd/apdu.h4
-rw-r--r--scd/command.c23
-rw-r--r--scd/sc-copykeys.c2
5 files changed, 52 insertions, 10 deletions
diff --git a/scd/ChangeLog b/scd/ChangeLog
index 41a0f76e1..d1e942a62 100644
--- a/scd/ChangeLog
+++ b/scd/ChangeLog
@@ -1,3 +1,16 @@
+2011-01-25 Werner Koch <[email protected]>
+
+ From 2.0 branch, 2010-03-17:
+
+ * command.c (open_card): Return GPG_ERR_NOT_OPERATIONAL if no
+ card services are available.
+ (get_reader_slot): Detect no services status.
+ (cmd_serialno): No reset if there are no services.
+ (scd_command_handler): Stop scdaemon in that case.
+ * apdu.c (pcsc_no_service): New.
+ (open_pcsc_reader_direct): Set it.
+ (apdu_open_reader): Add arg R_NO_SERVICE.
+
2011-01-05 Werner Koch <[email protected]>
* ccid-driver.c (ccid_transceive_secure): Support the gnuk token.
diff --git a/scd/apdu.c b/scd/apdu.c
index 80c933e59..dcb0e23bb 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -304,6 +304,9 @@ long (* DLSTDCALL pcsc_transmit) (unsigned long card,
long (* DLSTDCALL pcsc_set_timeout) (unsigned long context,
unsigned long timeout);
+/* Flag set if PC/SC returned the no-service error. */
+static int pcsc_no_service;
+
/* Prototypes. */
static int pcsc_get_status (int slot, unsigned int *status);
@@ -1504,8 +1507,11 @@ open_pcsc_reader_direct (const char *portstr)
log_error ("pcsc_establish_context failed: %s (0x%lx)\n",
pcsc_error_string (err), err);
reader_table[slot].used = 0;
+ if (err == 0x8010001d)
+ pcsc_no_service = 1;
return -1;
}
+ pcsc_no_service = 0;
err = pcsc_list_readers (reader_table[slot].pcsc.context,
NULL, NULL, &nreader);
@@ -2338,14 +2344,18 @@ unlock_slot (int slot)
error. If PORTSTR is NULL we default to a suitable port (for ctAPI:
the first USB reader. For PC/SC the first listed reader). */
int
-apdu_open_reader (const char *portstr)
+apdu_open_reader (const char *portstr, int *r_no_service)
{
static int pcsc_api_loaded, ct_api_loaded;
+ int slot;
+
+ if (r_no_service)
+ *r_no_service = 0;
#ifdef HAVE_LIBUSB
if (!opt.disable_ccid)
{
- int slot, i;
+ int i;
const char *s;
slot = open_ccid_reader (portstr);
@@ -2475,7 +2485,11 @@ apdu_open_reader (const char *portstr)
pcsc_api_loaded = 1;
}
- return open_pcsc_reader (portstr);
+ slot = open_pcsc_reader (portstr);
+ if (slot == -1 && r_no_service && pcsc_no_service)
+ *r_no_service = 1;
+
+ return slot;
}
diff --git a/scd/apdu.h b/scd/apdu.h
index c47dea882..d79f8b48f 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -80,8 +80,8 @@ enum {
#define APDU_CARD_ACTIVE (4) /* Card is active. */
-/* Note , that apdu_open_reader returns no status word but -1 on error. */
-int apdu_open_reader (const char *portstr);
+/* Note, that apdu_open_reader returns no status word but -1 on error. */
+int apdu_open_reader (const char *portstr, int *r_no_service);
int apdu_open_remote_reader (const char *portstr,
const unsigned char *cookie, size_t length,
int (*readfnc) (void *opaque,
diff --git a/scd/command.c b/scd/command.c
index fa1d46ce1..36aff9762 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -70,6 +70,10 @@
&& (c)->reader_slot == locked_session->ctrl_backlink->reader_slot)
+/* Flag indicating that the reader has been disabled. */
+static int reader_disabled;
+
+
/* This structure is used to keep track of open readers (slots). */
struct slot_status_s
{
@@ -394,7 +398,15 @@ get_reader_slot (void)
/* Try to open the reader. */
if (ss->slot == -1)
- ss->slot = apdu_open_reader (opt.reader_port);
+ {
+ int no_service_flag;
+ ss->slot = apdu_open_reader (opt.reader_port, &no_service_flag);
+ if (no_service_flag)
+ {
+ log_info ("no card services - disabling scdaemon\n");
+ reader_disabled = 1;
+ }
+ }
/* Return the slot_table index. */
return 0;
@@ -409,6 +421,9 @@ open_card (ctrl_t ctrl, const char *apptype)
gpg_error_t err;
int slot;
+ if (reader_disabled)
+ return gpg_error (GPG_ERR_NOT_OPERATIONAL);
+
/* If we ever got a card not present error code, return that. Only
the SERIALNO command and a reset are able to clear from that
state. */
@@ -441,7 +456,7 @@ open_card (ctrl_t ctrl, const char *apptype)
slot = get_reader_slot ();
ctrl->reader_slot = slot;
if (slot == -1)
- err = gpg_error (GPG_ERR_CARD);
+ err = gpg_error (reader_disabled? GPG_ERR_NOT_OPERATIONAL: GPG_ERR_CARD);
else
{
/* Fixme: We should move the apdu_connect call to
@@ -495,7 +510,7 @@ cmd_serialno (assuan_context_t ctx, char *line)
time_t stamp;
/* Clear the remove flag so that the open_card is able to reread it. */
- if (ctrl->server_local->card_removed)
+ if (!reader_disabled && ctrl->server_local->card_removed)
{
if ( IS_LOCKED (ctrl) )
return gpg_error (GPG_ERR_LOCKED);
@@ -1993,7 +2008,7 @@ scd_command_handler (ctrl_t ctrl, int fd)
BUG ();
sl->next_session = ctrl->server_local->next_session;
}
- stopme = ctrl->server_local->stopme;
+ stopme = ctrl->server_local->stopme || reader_disabled;
xfree (ctrl->server_local);
ctrl->server_local = NULL;
diff --git a/scd/sc-copykeys.c b/scd/sc-copykeys.c
index 615e4b28a..b863b01b3 100644
--- a/scd/sc-copykeys.c
+++ b/scd/sc-copykeys.c
@@ -139,7 +139,7 @@ main (int argc, char **argv )
if (argc != 1)
usage (1);
- slot = apdu_open_reader (reader_port);
+ slot = apdu_open_reader (reader_port, NULL);
if (slot == -1)
exit (1);
if (apdu_connect (slot))