[svn] GnuPG - r4906 - in trunk: agent po scd
svn author wk
cvs at cvs.gnupg.org
Thu Dec 18 17:34:32 CET 2008
Author: wk
Date: 2008-12-18 17:34:28 +0100 (Thu, 18 Dec 2008)
New Revision: 4906
Modified:
trunk/agent/gpg-agent.c
trunk/po/be.po
trunk/po/ca.po
trunk/po/cs.po
trunk/po/da.po
trunk/po/de.po
trunk/po/el.po
trunk/po/eo.po
trunk/po/es.po
trunk/po/et.po
trunk/po/fi.po
trunk/po/fr.po
trunk/po/gl.po
trunk/po/hu.po
trunk/po/id.po
trunk/po/it.po
trunk/po/ja.po
trunk/po/nb.po
trunk/po/pl.po
trunk/po/pt.po
trunk/po/pt_BR.po
trunk/po/ro.po
trunk/po/ru.po
trunk/po/sk.po
trunk/po/sv.po
trunk/po/tr.po
trunk/po/zh_CN.po
trunk/po/zh_TW.po
trunk/scd/ChangeLog
trunk/scd/apdu.c
trunk/scd/ccid-driver.c
trunk/scd/command.c
Log:
Fixed some card related problems.
Modified: trunk/scd/ChangeLog
===================================================================
--- trunk/scd/ChangeLog 2008-12-17 19:42:17 UTC (rev 4905)
+++ trunk/scd/ChangeLog 2008-12-18 16:34:28 UTC (rev 4906)
@@ -1,3 +1,17 @@
+2008-12-18 Werner Koch <wk at g10code.com>
+
+ * ccid-driver.c (abort_cmd): New.
+ (bulk_in): Call abort_cmd after severe errors.
+
+ * apdu.c (reader_table_s): Add field ANY_STATUS.
+ (new_reader_slot): Clear it.
+ (apdu_get_status): Use ANY_STATUS to update the change counter.
+ Remove the use of the flag bit from LAST_STATUS everywhere.
+ * command.c (update_reader_status_file): Factor code out to ...
+ (send_client_notifications): New. Track signals already sent.
+ (update_reader_status_file): Shutdown the reader after a failed
+ apdu_get_status.
+
2008-12-09 Werner Koch <wk at g10code.com>
* scdaemon.c (main): Call i18n_init before init_common_subsystems.
Modified: trunk/agent/gpg-agent.c
===================================================================
--- trunk/agent/gpg-agent.c 2008-12-17 19:42:17 UTC (rev 4905)
+++ trunk/agent/gpg-agent.c 2008-12-18 16:34:28 UTC (rev 4906)
@@ -1602,7 +1602,7 @@
agent_sigusr2_action (void)
{
if (opt.verbose)
- log_info ("SIGUSR2 received - checking smartcard status\n");
+ log_info ("SIGUSR2 received - updating card event counter\n");
/* Nothing to check right now. We only increment a counter. */
bump_card_eventcounter ();
}
Modified: trunk/po/be.po [not shown]
Modified: trunk/po/ca.po [not shown]
Modified: trunk/po/cs.po [not shown]
Modified: trunk/po/da.po [not shown]
Modified: trunk/po/de.po [not shown]
Modified: trunk/po/el.po [not shown]
Modified: trunk/po/eo.po [not shown]
Modified: trunk/po/es.po [not shown]
Modified: trunk/po/et.po [not shown]
Modified: trunk/po/fi.po [not shown]
Modified: trunk/po/fr.po [not shown]
Modified: trunk/po/gl.po [not shown]
Modified: trunk/po/hu.po [not shown]
Modified: trunk/po/id.po [not shown]
Modified: trunk/po/it.po [not shown]
Modified: trunk/po/ja.po [not shown]
Modified: trunk/po/nb.po [not shown]
Modified: trunk/po/pl.po [not shown]
Modified: trunk/po/pt.po [not shown]
Modified: trunk/po/pt_BR.po [not shown]
Modified: trunk/po/ro.po [not shown]
Modified: trunk/po/ru.po [not shown]
Modified: trunk/po/sk.po [not shown]
Modified: trunk/po/sv.po [not shown]
Modified: trunk/po/tr.po [not shown]
Modified: trunk/po/zh_CN.po [not shown]
Modified: trunk/po/zh_TW.po [not shown]
Modified: trunk/scd/apdu.c
===================================================================
--- trunk/scd/apdu.c 2008-12-17 19:42:17 UTC (rev 4905)
+++ trunk/scd/apdu.c 2008-12-18 16:34:28 UTC (rev 4906)
@@ -133,6 +133,7 @@
} rapdu;
#endif /*USE_G10CODE_RAPDU*/
char *rdrname; /* Name of the connected reader or NULL if unknown. */
+ int any_status; /* True if we have seen any status. */
int last_status;
int status;
int is_t0; /* True if we know that we are running T=0. */
@@ -340,7 +341,8 @@
reader_table[reader].check_keypad = NULL;
reader_table[reader].dump_status_reader = NULL;
- reader_table[reader].used = 1;
+ reader_table[reader].used = 1;
+ reader_table[reader].any_status = 0;
reader_table[reader].last_status = 0;
reader_table[reader].is_t0 = 1;
#ifdef NEED_PCSC_WRAPPER
@@ -1289,8 +1291,7 @@
and usable. Remember this. */
reader_table[slot].last_status = ( APDU_CARD_USABLE
| APDU_CARD_PRESENT
- | APDU_CARD_ACTIVE
- | 0x8000);
+ | APDU_CARD_ACTIVE);
reader_table[slot].is_t0 = !!(card_protocol & PCSC_PROTOCOL_T0);
}
}
@@ -1743,8 +1744,7 @@
and usable. Thus remember this. */
slotp->last_status = ( APDU_CARD_USABLE
| APDU_CARD_PRESENT
- | APDU_CARD_ACTIVE
- | 0x8000);
+ | APDU_CARD_ACTIVE);
}
slotp->atrlen = len;
@@ -1947,8 +1947,7 @@
and usable. Thus remember this. */
reader_table[slot].last_status = (APDU_CARD_USABLE
| APDU_CARD_PRESENT
- | APDU_CARD_ACTIVE
- | 0x8000);
+ | APDU_CARD_ACTIVE);
}
reader_table[slot].close_reader = close_ccid_reader;
@@ -2615,8 +2614,7 @@
and usable. Thus remember this. */
reader_table[slot].last_status = (APDU_CARD_USABLE
| APDU_CARD_PRESENT
- | APDU_CARD_ACTIVE
- | 0x8000);
+ | APDU_CARD_ACTIVE);
}
unlock_slot (slot);
@@ -2662,8 +2660,7 @@
and usable. Thus remember this. */
reader_table[slot].last_status = (APDU_CARD_USABLE
| APDU_CARD_PRESENT
- | APDU_CARD_ACTIVE
- | 0x8000);
+ | APDU_CARD_ACTIVE);
}
}
}
@@ -2733,17 +2730,16 @@
return sw;
}
- /* Keep track of changes. We use one extra bit to test whether we
- have checked the status at least once. */
- if ( s != (reader_table[slot].last_status & 0x07ff)
- || !reader_table[slot].last_status )
+ /* Keep track of changes. */
+ if (s != reader_table[slot].last_status
+ || !reader_table[slot].any_status )
{
reader_table[slot].change_counter++;
/* Make sure that the ATR is invalid so that a reset will be by
activate. */
reader_table[slot].atrlen = 0;
}
- reader_table[slot].last_status = (s | 0x8000);
+ reader_table[slot].any_status = 1;
if (status)
*status = s;
Modified: trunk/scd/ccid-driver.c
===================================================================
--- trunk/scd/ccid-driver.c 2008-12-17 19:42:17 UTC (rev 4905)
+++ trunk/scd/ccid-driver.c 2008-12-18 16:34:28 UTC (rev 4906)
@@ -1,5 +1,6 @@
/* ccid-driver.c - USB ChipCardInterfaceDevices driver
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007
+ * 2008 Free Software Foundation, Inc.
* Written by Werner Koch.
*
* This file is part of GnuPG.
@@ -262,6 +263,7 @@
static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
size_t *nread, int expected_type, int seqno, int timeout,
int no_debug);
+static int abort_cmd (ccid_driver_t handle);
/* Convert a little endian stored 4 byte value into an unsigned
integer. */
@@ -1069,7 +1071,10 @@
/* Set the level of debugging to LEVEL and return the old level. -1
just returns the old level. A level of 0 disables debugging, 1
enables debugging, 2 enables additional tracing of the T=1
- protocol, other values are not yet defined. */
+ protocol, other values are not yet defined.
+
+ Note that libusb may provide its own debugging feature which is
+ enabled by setting the envvar USB_DEBUG. */
int
ccid_set_debug_level (int level)
{
@@ -1395,7 +1400,7 @@
rc = usb_bulk_write (handle->idev,
handle->ep_bulk_out,
(char*)msg, msglen,
- 1000 /* ms timeout */);
+ 5000 /* ms timeout */);
if (rc == msglen)
return 0;
if (rc == -1)
@@ -1463,17 +1468,20 @@
if (msglen < 10)
{
DEBUGOUT_1 ("bulk-in msg too short (%u)\n", (unsigned int)msglen);
+ abort_cmd (handle);
return CCID_DRIVER_ERR_INV_VALUE;
}
if (buffer[5] != 0)
{
DEBUGOUT_1 ("unexpected bulk-in slot (%d)\n", buffer[5]);
+ abort_cmd (handle);
return CCID_DRIVER_ERR_INV_VALUE;
}
if (buffer[6] != seqno)
{
DEBUGOUT_2 ("bulk-in seqno does not match (%d/%d)\n",
seqno, buffer[6]);
+ abort_cmd (handle);
return CCID_DRIVER_ERR_INV_VALUE;
}
@@ -1492,6 +1500,7 @@
if (buffer[0] != expected_type)
{
DEBUGOUT_1 ("unexpected bulk-in msg type (%02x)\n", buffer[0]);
+ abort_cmd (handle);
return CCID_DRIVER_ERR_INV_VALUE;
}
@@ -1521,6 +1530,113 @@
}
+
+/* Send an abort sequence and wait until everything settled. */
+static int
+abort_cmd (ccid_driver_t handle)
+{
+ int rc;
+ char dummybuf[8];
+ unsigned char seqno;
+ unsigned char msg[100];
+ size_t msglen;
+ int i;
+
+ if (!handle->idev)
+ {
+ /* I don't know how to send an abort to non-USB devices. */
+ rc = CCID_DRIVER_ERR_NOT_SUPPORTED;
+ }
+
+ DEBUGOUT ("sending abort sequence\n");
+ /* Send the abort command to the control pipe. Note that we don't
+ need to keep track of sent abort commands because there should
+ never be another thread using the same slot concurrently. */
+ seqno = (handle->seqno & 0xff);
+ rc = usb_control_msg (handle->idev,
+ 0x21,/* bmRequestType: host-to-device,
+ class specific, to interface. */
+ 1, /* ABORT */
+ (seqno << 8 | 0 /* slot */),
+ handle->ifc_no,
+ dummybuf, 0,
+ 1000 /* ms timeout */);
+ if (rc < 0)
+ {
+ DEBUGOUT_1 ("usb_control_msg error: %s\n", strerror (errno));
+ return CCID_DRIVER_ERR_CARD_IO_ERROR;
+ }
+
+ /* Now send the abort command to the bulk out pipe using the same
+ SEQNO and SLOT. */
+ msg[0] = PC_to_RDR_Abort;
+ msg[5] = 0; /* slot */
+ msg[6] = seqno;
+ msg[7] = 0; /* RFU */
+ msg[8] = 0; /* RFU */
+ msg[9] = 0; /* RFU */
+ msglen = 10;
+ set_msg_len (msg, 0);
+ handle->seqno++; /* Bumb up for the next use. */
+
+ DEBUGOUT ("sending");
+ for (i=0; i < msglen; i++)
+ DEBUGOUT_CONT_1 (" %02X", msg[i]);
+ DEBUGOUT_LF ();
+ rc = usb_bulk_write (handle->idev,
+ handle->ep_bulk_out,
+ (char*)msg, msglen,
+ 5000 /* ms timeout */);
+ if (rc == msglen)
+ rc = 0;
+ else if (rc == -1)
+ DEBUGOUT_1 ("usb_bulk_write error in abort_cmd: %s\n", strerror (errno));
+ else
+ DEBUGOUT_1 ("usb_bulk_write failed in abort_cmd: %d\n", rc);
+
+ if (rc)
+ return rc;
+
+ /* Wait for the expected response. */
+ do
+ {
+ rc = usb_bulk_read (handle->idev,
+ handle->ep_bulk_in,
+ (char*)msg, sizeof msg,
+ 5000 /*ms timeout*/);
+ if (rc < 0)
+ {
+ DEBUGOUT_1 ("usb_bulk_read error in abort_cmd: %s\n",
+ strerror (errno));
+ return CCID_DRIVER_ERR_CARD_IO_ERROR;
+ }
+ msglen = rc;
+
+ if (msglen < 10)
+ {
+ DEBUGOUT_1 ("bulk-in msg in abort_cmd too short (%u)\n",
+ (unsigned int)msglen);
+ return CCID_DRIVER_ERR_INV_VALUE;
+ }
+ if (msg[5] != 0)
+ {
+ DEBUGOUT_1 ("unexpected bulk-in slot (%d) in abort_cmd\n", msg[5]);
+ return CCID_DRIVER_ERR_INV_VALUE;
+ }
+
+ DEBUGOUT_3 ("status: %02X error: %02X octet[9]: %02X\n",
+ msg[7], msg[8], msg[9]);
+ if (CCID_COMMAND_FAILED (msg))
+ print_command_failed (msg);
+ }
+ while (msg[0] != RDR_to_PC_SlotStatus && msg[5] != 0 && msg[6] != seqno);
+
+ DEBUGOUT ("sending abort sequence succeeded\n");
+
+ return 0;
+}
+
+
/* Note that this function won't return the error codes NO_CARD or
CARD_INACTIVE. IF RESULT is not NULL, the result from the
operation will get returned in RESULT and its length in RESULTLEN.
Modified: trunk/scd/command.c
===================================================================
--- trunk/scd/command.c 2008-12-17 19:42:17 UTC (rev 4905)
+++ trunk/scd/command.c 2008-12-18 16:34:28 UTC (rev 4906)
@@ -1964,6 +1964,84 @@
}
+
+/* Helper to send the clients a status change notification. */
+static void
+send_client_notifications (void)
+{
+ struct {
+ pid_t pid;
+#ifdef HAVE_W32_SYSTEM
+ HANDLE handle;
+#else
+ int signo;
+#endif
+ } killed[50];
+ int killidx = 0;
+ int kidx;
+ struct server_local_s *sl;
+
+ for (sl=session_list; sl; sl = sl->next_session)
+ {
+ if (sl->event_signal && sl->assuan_ctx)
+ {
+ pid_t pid = assuan_get_pid (sl->assuan_ctx);
+#ifdef HAVE_W32_SYSTEM
+ HANDLE handle = (void *)sl->event_signal;
+
+ for (kidx=0; kidx < killidx; kidx++)
+ if (killed[kidx].pid == pid
+ && killed[kidx].handle == handle)
+ break;
+ if (kidx < killidx)
+ log_info ("event %lx (%p) already triggered for client %d\n",
+ sl->event_signal, handle, (int)pid);
+ else
+ {
+ log_info ("triggering event %lx (%p) for client %d\n",
+ sl->event_signal, handle, (int)pid);
+ if (!SetEvent (handle))
+ log_error ("SetEvent(%lx) failed: %s\n",
+ sl->event_signal, w32_strerror (-1));
+ if (killidx < DIM (killed))
+ {
+ killed[killidx].pid = pid;
+ killed[killidx].handle = handle;
+ killidx++;
+ }
+ }
+#else /*!HAVE_W32_SYSTEM*/
+ int signo = sl->event_signal;
+
+ if (pid != (pid_t)(-1) && pid && signo > 0)
+ {
+ for (kidx=0; kidx < killidx; kidx++)
+ if (killed[kidx].pid == pid
+ && killed[kidx].signo == signo)
+ break;
+ if (kidx < killidx)
+ log_info ("signal %d already sent to client %d\n",
+ signo, (int)pid);
+ else
+ {
+ log_info ("sending signal %d to client %d\n",
+ signo, (int)pid);
+ kill (pid, signo);
+ if (killidx < DIM (killed))
+ {
+ killed[killidx].pid = pid;
+ killed[killidx].signo = signo;
+ killidx++;
+ }
+ }
+#endif /*!HAVE_W32_SYSTEM*/
+ }
+ }
+ }
+}
+
+
+
/* This is the core of scd_update_reader_status_file but the caller
needs to take care of the locking. */
static void
@@ -1985,12 +2063,17 @@
{
struct slot_status_s *ss = slot_table + idx;
struct server_local_s *sl;
+ int sw_apdu;
if (!ss->valid || ss->slot == -1)
continue; /* Not valid or reader not yet open. */
- if ( apdu_get_status (ss->slot, 0, &status, &changed) )
- continue; /* Get status failed. */
+ sw_apdu = apdu_get_status (ss->slot, 0, &status, &changed);
+ if (sw_apdu)
+ {
+ /* Get status failed. Ignore that. */
+ continue;
+ }
if (!ss->any || ss->status != status || ss->changed != changed )
{
@@ -1998,8 +2081,10 @@
char templ[50];
FILE *fp;
- log_info ("updating status of slot %d to 0x%04X\n",
- ss->slot, status);
+ log_info ("updating slot %d status: 0x%04X->0x%04X (%u->%u)\n",
+ ss->slot, ss->status, status, ss->changed, changed);
+ ss->status = status;
+ ss->changed = changed;
/* FIXME: Should this be IDX instead of ss->slot? This
depends on how client sessions will associate the reader
@@ -2065,33 +2150,9 @@
update_card_removed (idx, 1);
ss->any = 1;
- ss->status = status;
- ss->changed = changed;
/* Send a signal to all clients who applied for it. */
- for (sl=session_list; sl; sl = sl->next_session)
- if (sl->event_signal && sl->assuan_ctx)
- {
- pid_t pid = assuan_get_pid (sl->assuan_ctx);
-
-#ifdef HAVE_W32_SYSTEM
- HANDLE handle = (void *)sl->event_signal;
-
- log_info ("client pid is %d, triggering event %lx (%p)\n",
- pid, sl->event_signal, handle);
- if (!SetEvent (handle))
- log_error ("SetEvent(%lx) failed: %s\n",
- sl->event_signal, w32_strerror (-1));
-#else
- int signo = sl->event_signal;
-
- log_info ("client pid is %d, sending signal %d\n",
- pid, signo);
- if (pid != (pid_t)(-1) && pid && signo > 0)
- kill (pid, signo);
-#endif
- }
-
+ send_client_notifications ();
}
/* Check whether a disconnect is pending. */
@@ -2104,7 +2165,7 @@
{
/* FIXME: Use a real timeout. */
/* At least one connection and all allow a disconnect. */
- log_debug ("disconnecting card in slot %d\n", ss->slot);
+ log_info ("disconnecting card in slot %d\n", ss->slot);
apdu_disconnect (ss->slot);
}
}
More information about the Gnupg-commits
mailing list