SCD changes for PC/SC under W32.

This commit is contained in:
Werner Koch 2008-10-14 18:18:21 +00:00
parent c1329ec7c6
commit d0ca953014
36 changed files with 10449 additions and 8846 deletions

View File

@ -1,3 +1,8 @@
2008-10-14 Werner Koch <wk@g10code.com>
* gpg-agent.c (get_agent_scd_notify_event): Need to use a manual
reset event.
2008-09-29 Werner Koch <wk@g10code.com>
* agent.h (GCRY_MD_USER): Rename to GCRY_MODULE_ID_USER.

View File

@ -378,8 +378,10 @@ start_scd (ctrl_t ctrl)
char buf[100];
#ifdef HAVE_W32_SYSTEM
snprintf (buf, sizeof buf, "OPTION event-signal=%lx",
(unsigned long)get_agent_scd_notify_event ());
/* Use estream snprintf due to a bug in mingw32 related to the l
modifier. */
estream_snprintf (buf, sizeof buf, "OPTION event-signal=%lx",
(unsigned long)get_agent_scd_notify_event ());
#else
snprintf (buf, sizeof buf, "OPTION event-signal=%d", SIGUSR2);
#endif

View File

@ -1268,12 +1268,34 @@ get_agent_scd_notify_event (void)
if (!the_event)
{
HANDLE h, h2;
SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
the_event = CreateEvent ( &sa, FALSE, FALSE, NULL);
if (!the_event)
/* We need to use manual reset evet object due to the way our
w32-pth wait function works: If we would use an automatic
reset event we are not able to figure out which handle has
been signaled because at the time we single out the signaled
handles using WFSO the event has already been reset due to
the WFMO. */
h = CreateEvent (&sa, TRUE, FALSE, NULL);
if (!h)
log_error ("can't create scd notify event: %s\n", w32_strerror (-1) );
else if (!DuplicateHandle (GetCurrentProcess(), h,
GetCurrentProcess(), &h2,
EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0))
{
log_error ("setting syncronize for scd notify event failed: %s\n",
w32_strerror (-1) );
CloseHandle (h);
}
else
{
CloseHandle (h);
the_event = h2;
}
}
log_debug ("returning notify handle %p\n", the_event);
return the_event;
}
#endif /*HAVE_W32_SYSTEM*/

View File

@ -226,7 +226,7 @@ checked right before it is used.
@opindex delete-keys
Delete the keys matching @var{pattern}. Note that there is no command
to delete the secret part of the key directly. In case you need to do
this, you should run the command @code{gpg --dump-secret-keys KEYID}
this, you should run the command @code{gpgsm --dump-secret-keys KEYID}
before you delete the key, copy the string of hex-digits in the
``keygrip'' line and delete the file consisting of these hex-digits
and the suffix @code{.key} from the @file{private-keys-v1.d} directory

693
po/be.po

File diff suppressed because it is too large Load Diff

705
po/ca.po

File diff suppressed because it is too large Load Diff

696
po/cs.po

File diff suppressed because it is too large Load Diff

695
po/da.po

File diff suppressed because it is too large Load Diff

697
po/de.po

File diff suppressed because it is too large Load Diff

696
po/el.po

File diff suppressed because it is too large Load Diff

696
po/eo.po

File diff suppressed because it is too large Load Diff

700
po/es.po

File diff suppressed because it is too large Load Diff

696
po/et.po

File diff suppressed because it is too large Load Diff

696
po/fi.po

File diff suppressed because it is too large Load Diff

696
po/gl.po

File diff suppressed because it is too large Load Diff

696
po/hu.po

File diff suppressed because it is too large Load Diff

696
po/id.po

File diff suppressed because it is too large Load Diff

698
po/it.po

File diff suppressed because it is too large Load Diff

696
po/ja.po

File diff suppressed because it is too large Load Diff

695
po/nb.po

File diff suppressed because it is too large Load Diff

699
po/pl.po

File diff suppressed because it is too large Load Diff

696
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

696
po/ro.po

File diff suppressed because it is too large Load Diff

694
po/ru.po

File diff suppressed because it is too large Load Diff

696
po/sk.po

File diff suppressed because it is too large Load Diff

697
po/sv.po

File diff suppressed because it is too large Load Diff

699
po/tr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,45 @@
2008-10-14 Werner Koch <wk@g10code.com>
* apdu.c (reader_table_s): Add fields connect_card and
disconnect_card.
(new_reader_slot): Set them to NULL.
(apdu_connect, apdu_disconnect): New.
(apdu_close_reader, apdu_shutdown_reader): Call apdu_disconnect.
(connect_pcsc_card, disconnect_pcsc_card): new.
(reset_pcsc_reader_direct): Implement in terms of
disconnect_pcsc_card and connect_pcsc_card.
(apdu_get_atr): Return NULL if there is no ATR.
* sc-copykeys.c (main): Add call to apdu_connect.
* command.c (open_card): Ditto.
* apdu.h (SW_HOST_ALREADY_CONNECTED): New.
(APDU_CARD_USABLE, APDU_CARD_PRESENT, APDU_CARD_ACTIVE): New.
* apdu.c: Replace constants by the new macros.
(open_pcsc_reader): Factor code out to ...
(open_pcsc_reader_direct, open_pcsc_reader_wrapped): New.
(reset_pcsc_reader): Factor code out to ...
(reset_pcsc_reader_direct, reset_pcsc_reader_wrapped): New.
(pcsc_get_status): Factor code out to ...
(pcsc_get_status_direct, pcsc_get_status_wrapped): New.
(pcsc_send_apdu): Factor code out to ...
(pcsc_send_apdu_direct, pcsc_send_apdu_wrapped): New.
(close_pcsc_reader): Factor code out to ...
(close_pcsc_reader_direct, close_pcsc_reader_wrapped): New.
* command.c (update_reader_status_file): Open the reader if not
yet done.
* scdaemon.c (TIMERTICK_INTERVAL_SEC, TIMERTICK_INTERVAL_USEC):
New to replace TIMERTICK_INTERVAL. Chnage from 2s (4 under W32)
to 250ms.
2008-10-13 Werner Koch <wk@g10code.com>
* command.c (option_handler) [W32]: Use strtoul with base 16.
(update_reader_status_file) [W32]: Set Event.
(scd_command_handler): Use INT2FD to silent warning.
2008-09-29 Werner Koch <wk@g10code.com>
* scdaemon.h (GCRY_MD_USER): Rename to GCRY_MODULE_ID_USER.

1018
scd/apdu.c

File diff suppressed because it is too large Load Diff

View File

@ -65,13 +65,20 @@ enum {
SW_HOST_GENERAL_ERROR = 0x1000b,
SW_HOST_NO_READER = 0x1000c,
SW_HOST_ABORTED = 0x1000d,
SW_HOST_NO_KEYPAD = 0x1000e
SW_HOST_NO_KEYPAD = 0x1000e,
SW_HOST_ALREADY_CONNECTED = 0x1000f
};
#define SW_EXACT_LENGTH_P(a) (((a)&~0xff) == SW_EXACT_LENGTH)
/* Bit flags for the card status. */
#define APDU_CARD_USABLE (1) /* Card is present and ready for use. */
#define APDU_CARD_PRESENT (2) /* Card is just present. */
#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);
int apdu_open_remote_reader (const char *portstr,
@ -92,7 +99,10 @@ unsigned char *apdu_get_atr (int slot, size_t *atrlen);
const char *apdu_strerror (int rc);
/* These apdu functions do return status words. */
/* These APDU functions return status words. */
int apdu_connect (int slot);
int apdu_disconnect (int slot);
int apdu_activate (int slot);
int apdu_reset (int slot);

View File

@ -102,8 +102,12 @@ struct server_local_s
/* The Assuan context used by this session/server. */
assuan_context_t assuan_ctx;
int event_signal; /* Or 0 if not used. */
#ifdef HAVE_W32_SYSTEM
unsigned long event_signal; /* Or 0 if not used. */
#else
int event_signal; /* Or 0 if not used. */
#endif
/* True if the card has been removed and a reset is required to
continue operation. */
int card_removed;
@ -165,6 +169,7 @@ update_card_removed (int slot, int value)
{
sl->card_removed = value;
}
/* Let the card application layer know about the removal. */
if (value)
application_notify_card_removed (slot);
}
@ -319,10 +324,16 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
if (!strcmp (key, "event-signal"))
{
/* A value of 0 is allowed to reset the event signal. */
#ifdef HAVE_W32_SYSTEM
if (!*value)
return gpg_error (GPG_ERR_ASS_PARAMETER);
ctrl->server_local->event_signal = strtoul (value, NULL, 16);
#else
int i = *value? atoi (value) : -1;
if (i < 0)
return gpg_error (GPG_ERR_ASS_PARAMETER);
ctrl->server_local->event_signal = i;
#endif
}
return 0;
@ -389,7 +400,15 @@ open_card (ctrl_t ctrl, const char *apptype)
if (slot == -1)
err = gpg_error (GPG_ERR_CARD);
else
err = select_application (ctrl, slot, apptype, &ctrl->app_ctx);
{
/* Fixme: We should move the apdu_connect call to
select_application. */
int sw = apdu_connect (slot);
if (sw && sw != SW_HOST_ALREADY_CONNECTED)
err = gpg_error (GPG_ERR_CARD);
else
err = select_application (ctrl, slot, apptype, &ctrl->app_ctx);
}
TEST_CARD_REMOVAL (ctrl, err);
return err;
@ -1774,7 +1793,7 @@ scd_command_handler (ctrl_t ctrl, int fd)
}
else
{
rc = assuan_init_socket_server_ext (&ctx, fd, 2);
rc = assuan_init_socket_server_ext (&ctx, INT2FD(fd), 2);
}
if (rc)
{
@ -1911,6 +1930,11 @@ update_reader_status_file (void)
int idx;
unsigned int status, changed;
/* Make sure that the reader has been opened. Like get_reader_slot,
this part of the code assumes that there is only one reader. */
if (!slot_table[0].valid)
(void)get_reader_slot ();
/* Note, that we only try to get the status, because it does not
make sense to wait here for a operation to complete. If we are
busy working with a card, delays in the status file update should
@ -2007,11 +2031,20 @@ update_reader_status_file (void)
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);
#ifndef HAVE_W32_SYSTEM
if (pid != (pid_t)(-1) && pid && signo > 0)
kill (pid, signo);
#endif

View File

@ -142,6 +142,8 @@ main (int argc, char **argv )
slot = apdu_open_reader (reader_port);
if (slot == -1)
exit (1);
if (apdu_connect (slot))
exit (1);
/* FIXME: Use select_application. */
appbuf.slot = slot;

View File

@ -148,15 +148,18 @@ static ARGPARSE_OPTS opts[] = {
#define DEFAULT_PCSC_DRIVER "libpcsclite.so"
#endif
/* The timer tick used for housekeeping stuff. For Windows we use a
longer period as the SetWaitableTimer seems to signal earlier than
the 2 seconds. */
#ifdef HAVE_W32_SYSTEM
#define TIMERTICK_INTERVAL (4)
#else
#define TIMERTICK_INTERVAL (2) /* Seconds. */
#endif
/* The timer tick used for housekeeping stuff. We poll every 250ms to
let the user immediately know a status change.
This is not too good for power saving but given that there is no
easy way to block on card status changes it is the best we can do.
For PC/SC we could in theory use an extra thread to wait for status
changes but that requires a native thread because there is no way
to make the underlying PC/SC card change function block using a Pth
mechanism. Given that a native thread could only be used under W32
we don't do that at all. */
#define TIMERTICK_INTERVAL_SEC (0)
#define TIMERTICK_INTERVAL_USEC (250000)
/* Flag to indicate that a shutdown was requested. */
static int shutdown_pending;
@ -1107,7 +1110,8 @@ handle_connections (int listen_fd)
/* Create a timeout event if needed. */
if (!time_ev)
time_ev = pth_event (PTH_EVENT_TIME,
pth_timeout (TIMERTICK_INTERVAL, 0));
pth_timeout (TIMERTICK_INTERVAL_SEC,
TIMERTICK_INTERVAL_USEC));
/* POSIX says that fd_set should be implemented as a structure,
thus a simple assignment is fine to copy the entire set. */