diff options
Diffstat (limited to 'scd')
-rw-r--r-- | scd/apdu.c | 56 | ||||
-rw-r--r-- | scd/app-openpgp.c | 5 | ||||
-rw-r--r-- | scd/ccid-driver.c | 3 | ||||
-rw-r--r-- | scd/scdaemon.c | 36 |
4 files changed, 64 insertions, 36 deletions
diff --git a/scd/apdu.c b/scd/apdu.c index 60270ede0..66a16f820 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -119,6 +119,7 @@ struct reader_table_s { pcsc_dword_t modify_ioctl; int pinmin; int pinmax; + pcsc_dword_t current_state; } pcsc; #ifdef USE_G10CODE_RAPDU struct { @@ -228,6 +229,7 @@ static npth_mutex_t reader_table_lock; #define PCSC_E_READER_UNAVAILABLE 0x80100017 #define PCSC_E_NO_SERVICE 0x8010001D #define PCSC_E_SERVICE_STOPPED 0x8010001E +#define PCSC_W_RESET_CARD 0x80100068 #define PCSC_W_REMOVED_CARD 0x80100069 /* Fix pcsc-lite ABI incompatibility. */ @@ -453,6 +455,7 @@ new_reader_slot (void) reader_table[reader].pcsc.modify_ioctl = 0; reader_table[reader].pcsc.pinmin = -1; reader_table[reader].pcsc.pinmax = -1; + reader_table[reader].pcsc.current_state = PCSC_STATE_UNAWARE; return reader; } @@ -653,12 +656,12 @@ pcsc_get_status (int slot, unsigned int *status, int on_wire) (void)on_wire; memset (rdrstates, 0, sizeof *rdrstates); rdrstates[0].reader = reader_table[slot].rdrname; - rdrstates[0].current_state = PCSC_STATE_UNAWARE; + rdrstates[0].current_state = reader_table[slot].pcsc.current_state; err = pcsc_get_status_change (reader_table[slot].pcsc.context, 0, rdrstates, 1); if (err == PCSC_E_TIMEOUT) - err = 0; /* Timeout is no error error here. */ + err = 0; /* Timeout is no error here. */ if (err) { log_error ("pcsc_get_status_change failed: %s (0x%lx)\n", @@ -666,24 +669,29 @@ pcsc_get_status (int slot, unsigned int *status, int on_wire) return pcsc_error_to_sw (err); } - /* log_debug */ - /* ("pcsc_get_status_change: %s%s%s%s%s%s%s%s%s%s\n", */ - /* (rdrstates[0].event_state & PCSC_STATE_IGNORE)? " ignore":"", */ - /* (rdrstates[0].event_state & PCSC_STATE_CHANGED)? " changed":"", */ - /* (rdrstates[0].event_state & PCSC_STATE_UNKNOWN)? " unknown":"", */ - /* (rdrstates[0].event_state & PCSC_STATE_UNAVAILABLE)?" unavail":"", */ - /* (rdrstates[0].event_state & PCSC_STATE_EMPTY)? " empty":"", */ - /* (rdrstates[0].event_state & PCSC_STATE_PRESENT)? " present":"", */ - /* (rdrstates[0].event_state & PCSC_STATE_ATRMATCH)? " atr":"", */ - /* (rdrstates[0].event_state & PCSC_STATE_EXCLUSIVE)? " excl":"", */ - /* (rdrstates[0].event_state & PCSC_STATE_INUSE)? " unuse":"", */ - /* (rdrstates[0].event_state & PCSC_STATE_MUTE)? " mute":"" ); */ + if ((rdrstates[0].event_state & PCSC_STATE_CHANGED)) + reader_table[slot].pcsc.current_state = + (rdrstates[0].event_state & ~PCSC_STATE_CHANGED); + + if (DBG_CARD_IO) + log_debug + ("pcsc_get_status_change: %s%s%s%s%s%s%s%s%s%s\n", + (rdrstates[0].event_state & PCSC_STATE_IGNORE)? " ignore":"", + (rdrstates[0].event_state & PCSC_STATE_CHANGED)? " changed":"", + (rdrstates[0].event_state & PCSC_STATE_UNKNOWN)? " unknown":"", + (rdrstates[0].event_state & PCSC_STATE_UNAVAILABLE)?" unavail":"", + (rdrstates[0].event_state & PCSC_STATE_EMPTY)? " empty":"", + (rdrstates[0].event_state & PCSC_STATE_PRESENT)? " present":"", + (rdrstates[0].event_state & PCSC_STATE_ATRMATCH)? " atr":"", + (rdrstates[0].event_state & PCSC_STATE_EXCLUSIVE)? " excl":"", + (rdrstates[0].event_state & PCSC_STATE_INUSE)? " inuse":"", + (rdrstates[0].event_state & PCSC_STATE_MUTE)? " mute":"" ); *status = 0; - if ( (rdrstates[0].event_state & PCSC_STATE_PRESENT) ) + if ( (reader_table[slot].pcsc.current_state & PCSC_STATE_PRESENT) ) { *status |= APDU_CARD_PRESENT; - if ( !(rdrstates[0].event_state & PCSC_STATE_MUTE) ) + if ( !(reader_table[slot].pcsc.current_state & PCSC_STATE_MUTE) ) *status |= APDU_CARD_ACTIVE; } #ifndef HAVE_W32_SYSTEM @@ -692,7 +700,7 @@ pcsc_get_status (int slot, unsigned int *status, int on_wire) mode. */ if ( (*status & (APDU_CARD_PRESENT|APDU_CARD_ACTIVE)) == (APDU_CARD_PRESENT|APDU_CARD_ACTIVE) - && !(rdrstates[0].event_state & PCSC_STATE_INUSE) ) + && !(reader_table[slot].pcsc.current_state & PCSC_STATE_INUSE) ) *status |= APDU_CARD_USABLE; #else /* Some winscard drivers may set EXCLUSIVE and INUSE at the same @@ -702,7 +710,11 @@ pcsc_get_status (int slot, unsigned int *status, int on_wire) *status |= APDU_CARD_USABLE; #endif - return 0; + if (!on_wire && (rdrstates[0].event_state & PCSC_STATE_CHANGED)) + /* Event like sleep/resume occurs, which requires RESET. */ + return SW_HOST_NO_READER; + else + return 0; } @@ -741,6 +753,14 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, log_error ("pcsc_transmit failed: %s (0x%lx)\n", pcsc_error_string (err), err); + /* Handle fatal errors which require shutdown of reader. */ + if (err == PCSC_E_NOT_TRANSACTED || err == PCSC_W_RESET_CARD + || err == PCSC_W_REMOVED_CARD) + { + reader_table[slot].pcsc.current_state = PCSC_STATE_UNAWARE; + scd_kick_the_loop (); + } + return pcsc_error_to_sw (err); } diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 54f04c612..dc775f77e 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1018,7 +1018,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) snprintf (tmp, sizeof tmp, "gc=%d ki=%d fc=%d pd=%d mcl3=%u aac=%d " - "sm=%d si=%u dec=%d bt=%d", + "sm=%d si=%u dec=%d bt=%d kdf=%d", app->app_local->extcap.get_challenge, app->app_local->extcap.key_import, app->app_local->extcap.change_force_chv, @@ -1032,7 +1032,8 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) : 0), app->app_local->status_indicator, app->app_local->extcap.has_decrypt, - app->app_local->extcap.has_button); + app->app_local->extcap.has_button, + app->app_local->extcap.kdf_do); send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0); return 0; } diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 5046da555..f33a36c83 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -1467,7 +1467,8 @@ intr_cb (struct libusb_transfer *transfer) DEBUGOUT_1 ("CCID: interrupt callback %d\n", transfer->status); - if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) + if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT + || transfer->status == LIBUSB_TRANSFER_NO_DEVICE) { int err; diff --git a/scd/scdaemon.c b/scd/scdaemon.c index cebeea9d3..8f8a02619 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -393,7 +393,21 @@ cleanup (void) } } - +static void +setup_signal_mask (void) +{ +#ifndef HAVE_W32_SYSTEM + npth_sigev_init (); + npth_sigev_add (SIGHUP); + npth_sigev_add (SIGUSR1); + npth_sigev_add (SIGUSR2); + npth_sigev_add (SIGINT); + npth_sigev_add (SIGCONT); + npth_sigev_add (SIGTERM); + npth_sigev_fini (); + main_thread_pid = getpid (); +#endif +} int main (int argc, char **argv ) @@ -744,6 +758,7 @@ main (int argc, char **argv ) #endif npth_init (); + setup_signal_mask (); gpgrt_set_syscall_clamp (npth_unprotect, npth_protect); /* If --debug-allow-core-dump has been given we also need to @@ -884,6 +899,7 @@ main (int argc, char **argv ) /* This is the child. */ npth_init (); + setup_signal_mask (); gpgrt_set_syscall_clamp (npth_unprotect, npth_protect); /* Detach from tty and put process into a new session. */ @@ -1206,18 +1222,16 @@ start_connection_thread (void *arg) void scd_kick_the_loop (void) { - int ret; - /* Kick the select loop. */ #ifdef HAVE_W32_SYSTEM - ret = SetEvent (the_event); + int ret = SetEvent (the_event); if (ret == 0) log_error ("SetEvent for scd_kick_the_loop failed: %s\n", w32_strerror (-1)); #elif defined(HAVE_PSELECT_NO_EINTR) write (notify_fd, "", 1); #else - ret = kill (main_thread_pid, SIGCONT); + int ret = kill (main_thread_pid, SIGCONT); if (ret < 0) log_error ("SetEvent for scd_kick_the_loop failed: %s\n", gpg_strerror (gpg_error_from_syserror ())); @@ -1292,16 +1306,6 @@ handle_connections (int listen_fd) events[0] = the_event = h2; } } -#else - npth_sigev_init (); - npth_sigev_add (SIGHUP); - npth_sigev_add (SIGUSR1); - npth_sigev_add (SIGUSR2); - npth_sigev_add (SIGINT); - npth_sigev_add (SIGCONT); - npth_sigev_add (SIGTERM); - npth_sigev_fini (); - main_thread_pid = getpid (); #endif FD_ZERO (&fdset); @@ -1348,6 +1352,8 @@ handle_connections (int listen_fd) FD_SET (pipe_fd[0], &read_fdset); if (max_fd < pipe_fd[0]) max_fd = pipe_fd[0]; +#else + (void)max_fd; #endif #ifndef HAVE_W32_SYSTEM |