diff options
Diffstat (limited to 'scd/command.c')
-rw-r--r-- | scd/command.c | 295 |
1 files changed, 160 insertions, 135 deletions
diff --git a/scd/command.c b/scd/command.c index 52b22c6..fc1f5a2 100644 --- a/scd/command.c +++ b/scd/command.c @@ -34,6 +34,7 @@ #include <assuan.h> #include <ksba.h> #include "app-common.h" +#include "iso7816.h" #include "apdu.h" /* Required for apdu_*_reader (). */ #include "exechelp.h" #ifdef HAVE_LIBUSB @@ -46,6 +47,9 @@ /* Maximum allowed size of key data as used in inquiries. */ #define MAXLEN_KEYDATA 4096 +/* Maximum allowed total data size for SETDATA. */ +#define MAXLEN_SETDATA 4096 + /* Maximum allowed size of certificate data as used in inquiries. */ #define MAXLEN_CERTDATA 16384 @@ -60,6 +64,7 @@ int _r = (r); \ if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \ || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED \ + || gpg_err_code (_r) == GPG_ERR_CARD_RESET \ || gpg_err_code (_r) == GPG_ERR_ENODEV ) \ update_card_removed ((c)->reader_slot, 1); \ } while (0) @@ -70,12 +75,8 @@ && (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 +struct slot_status_s { int valid; /* True if the other objects are valid. */ int slot; /* Slot number of the reader or -1 if not open. */ @@ -92,11 +93,11 @@ struct slot_status_s /* Data used to associate an Assuan context with local server data. This object describes the local properties of one session. */ -struct server_local_s +struct server_local_s { /* We keep a list of all active sessions with the anchor at SESSION_LIST (see below). This field is used for linking. */ - struct server_local_s *next_session; + struct server_local_s *next_session; /* This object is usually assigned to a CTRL object (which is globally visible). While enumerating all sessions we sometimes @@ -112,10 +113,10 @@ struct server_local_s #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; + int card_removed; /* Flag indicating that the application context needs to be released at the next opportunity. */ @@ -126,7 +127,7 @@ struct server_local_s /* If set to true we will be terminate ourself at the end of the this session. */ - int stopme; + int stopme; }; @@ -180,6 +181,9 @@ update_card_removed (int slot, int value) { struct server_local_s *sl; + if (slot == -1) + return; + for (sl=session_list; sl; sl = sl->next_session) if (sl->ctrl_backlink && sl->ctrl_backlink->reader_slot == slot) @@ -256,7 +260,7 @@ hex_to_buffer (const char *string, size_t *r_length) return NULL; for (s=string, n=0; *s; s++) { - if (spacep (s) || *s == ':') + if (spacep (s) || *s == ':') continue; if (hexdigitp (s) && hexdigitp (s+1)) { @@ -293,7 +297,7 @@ do_reset (ctrl_t ctrl, int send_reset) if (send_reset) { struct server_local_s *sl; - + for (sl=session_list; sl; sl = sl->next_session) if (sl->ctrl_backlink && sl->ctrl_backlink->reader_slot == slot) @@ -307,11 +311,19 @@ do_reset (ctrl_t ctrl, int send_reset) tell the application layer about it. */ if (slot != -1 && send_reset && !IS_LOCKED (ctrl) ) { - if (apdu_reset (slot)) - { - slot_table[slot].valid = 0; - } application_notify_card_reset (slot); + switch (apdu_reset (slot)) + { + case 0: + break; + case SW_HOST_NO_CARD: + case SW_HOST_CARD_INACTIVE: + break; + default: + apdu_close_reader (slot); + slot_table[slot].slot = -1; + break; + } } /* If we hold a lock, unlock now. */ @@ -345,7 +357,7 @@ do_reset (ctrl_t ctrl, int send_reset) static gpg_error_t reset_notify (assuan_context_t ctx, char *line) { - ctrl_t ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); (void) line; @@ -399,39 +411,29 @@ get_reader_slot (void) /* Try to open the reader. */ if (ss->slot == -1) { - int no_service_flag; - ss->slot = apdu_open_reader (opt.reader_port, &no_service_flag); + ss->slot = apdu_open_reader (opt.reader_port); /* If we still don't have a slot, we have no readers. Invalidate for now until a reader is attached. */ if(ss->slot == -1) { ss->valid = 0; + return -1; } - - if (no_service_flag) - { - log_info ("no card services - disabling scdaemon\n"); - reader_disabled = 1; - } } /* Return the slot_table index. */ return 0; } -/* If the card has not yet been opened, do it. Note that this - function returns an Assuan error, so don't map the error a second - time. */ + +/* If the card has not yet been opened, do it. */ static gpg_error_t 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. */ @@ -464,7 +466,7 @@ open_card (ctrl_t ctrl, const char *apptype) slot = get_reader_slot (); ctrl->reader_slot = slot; if (slot == -1) - err = gpg_error (reader_disabled? GPG_ERR_NOT_OPERATIONAL: GPG_ERR_CARD); + err = gpg_error (GPG_ERR_CARD); else { /* Fixme: We should move the apdu_connect call to @@ -477,6 +479,8 @@ open_card (ctrl_t ctrl, const char *apptype) { if (sw == SW_HOST_NO_CARD) err = gpg_error (GPG_ERR_CARD_NOT_PRESENT); + else if (sw == SW_HOST_CARD_INACTIVE) + err = gpg_error (GPG_ERR_CARD_RESET); else err = gpg_error (GPG_ERR_CARD); } @@ -489,7 +493,7 @@ open_card (ctrl_t ctrl, const char *apptype) } -static const char hlp_serialno[] = +static const char hlp_serialno[] = "SERIALNO [<apptype>]\n" "\n" "Return the serial number of the card using a status reponse. This\n" @@ -516,9 +520,11 @@ cmd_serialno (assuan_context_t ctx, char *line) char *serial_and_stamp; char *serial; time_t stamp; + int retries = 0; /* Clear the remove flag so that the open_card is able to reread it. */ - if (!reader_disabled && ctrl->server_local->card_removed) + retry: + if (ctrl->server_local->card_removed) { if ( IS_LOCKED (ctrl) ) return gpg_error (GPG_ERR_LOCKED); @@ -526,7 +532,12 @@ cmd_serialno (assuan_context_t ctx, char *line) } if ((rc = open_card (ctrl, *line? line:NULL))) - return rc; + { + /* In case of an inactive card, retry once. */ + if (gpg_err_code (rc) == GPG_ERR_CARD_RESET && retries++ < 1) + goto retry; + return rc; + } rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); if (rc) @@ -544,7 +555,7 @@ cmd_serialno (assuan_context_t ctx, char *line) } -static const char hlp_learn[] = +static const char hlp_learn[] = "LEARN [--force] [--keypairinfo]\n" "\n" "Learn all useful information of the currently inserted card. When\n" @@ -632,7 +643,7 @@ cmd_learn (assuan_context_t ctx, char *line) char *serial_and_stamp; char *serial; time_t stamp; - + rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); if (rc) return rc; @@ -643,11 +654,11 @@ cmd_learn (assuan_context_t ctx, char *line) return out_of_core (); rc = 0; assuan_write_status (ctx, "SERIALNO", serial_and_stamp); - + if (!has_option (line, "--force")) { char *command; - + rc = estream_asprintf (&command, "KNOWNCARDP %s", serial_and_stamp); if (rc < 0) { @@ -655,7 +666,7 @@ cmd_learn (assuan_context_t ctx, char *line) return out_of_core (); } rc = 0; - rc = assuan_inquire (ctx, command, NULL, NULL, 0); + rc = assuan_inquire (ctx, command, NULL, NULL, 0); xfree (command); if (rc) { @@ -663,13 +674,13 @@ cmd_learn (assuan_context_t ctx, char *line) log_error ("inquire KNOWNCARDP failed: %s\n", gpg_strerror (rc)); xfree (serial_and_stamp); - return rc; + return rc; } /* Not canceled, so we have to proceeed. */ } xfree (serial_and_stamp); } - + /* Let the application print out its collection of useful status information. */ if (!rc) @@ -715,7 +726,7 @@ cmd_readcert (assuan_context_t ctx, char *line) } -static const char hlp_readkey[] = +static const char hlp_readkey[] = "READKEY <keyid>\n" "\n" "Return the public key for the given cert or key ID as a standard\n" @@ -753,7 +764,7 @@ cmd_readkey (assuan_context_t ctx, char *line) if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION) log_error ("app_readkey failed: %s\n", gpg_strerror (rc)); - else + else { rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert); if (rc) @@ -763,7 +774,7 @@ cmd_readkey (assuan_context_t ctx, char *line) line = NULL; if (rc) goto leave; - + rc = ksba_cert_new (&kc); if (rc) { @@ -798,18 +809,25 @@ cmd_readkey (assuan_context_t ctx, char *line) -static const char hlp_setdata[] = - "SETDATA <hexstring> \n" +static const char hlp_setdata[] = + "SETDATA [--append] <hexstring>\n" "\n" - "The client should use this command to tell us the data he want to sign."; + "The client should use this command to tell us the data he want to sign.\n" + "With the option --append, the data is appended to the data set by a\n" + "previous SETDATA command."; static gpg_error_t cmd_setdata (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); - int n; + int append; + int n, i, off; char *p; unsigned char *buf; + append = (ctrl->in_data.value && has_option (line, "--append")); + + line = skip_options (line); + if (locked_session && locked_session != ctrl->server_local) return gpg_error (GPG_ERR_LOCKED); @@ -823,20 +841,36 @@ cmd_setdata (assuan_context_t ctx, char *line) if ((n&1)) return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits"); n /= 2; + if (append) + { + if (ctrl->in_data.valuelen + n > MAXLEN_SETDATA) + return set_error (GPG_ERR_TOO_LARGE, + "limit on total size of data reached"); + buf = xtrymalloc (ctrl->in_data.valuelen + n); + } + else buf = xtrymalloc (n); if (!buf) return out_of_core (); + if (append) + { + memcpy (buf, ctrl->in_data.value, ctrl->in_data.valuelen); + off = ctrl->in_data.valuelen; + } + else + off = 0; + for (p=line, i=0; i < n; p += 2, i++) + buf[off+i] = xtoi_2 (p); + ctrl->in_data.value = buf; - ctrl->in_data.valuelen = n; - for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++) - buf[n] = xtoi_2 (p); + ctrl->in_data.valuelen = off + n; return 0; } -static gpg_error_t +static gpg_error_t pin_cb (void *opaque, const char *info, char **retstr) { assuan_context_t ctx = opaque; @@ -847,23 +881,23 @@ pin_cb (void *opaque, const char *info, char **retstr) if (!retstr) { - /* We prompt for keypad entry. To make sure that the popup has + /* We prompt for pinpad entry. To make sure that the popup has been show we use an inquire and not just a status message. We ignore any value returned. */ if (info) { - log_debug ("prompting for keypad entry '%s'\n", info); - rc = estream_asprintf (&command, "POPUPKEYPADPROMPT %s", info); + log_debug ("prompting for pinpad entry '%s'\n", info); + rc = estream_asprintf (&command, "POPUPPINPADPROMPT %s", info); if (rc < 0) return gpg_error (gpg_err_code_from_errno (errno)); - rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); - xfree (command); + rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); + xfree (command); } else { - log_debug ("dismiss keypad entry prompt\n"); - rc = assuan_inquire (ctx, "DISMISSKEYPADPROMPT", - &value, &valuelen, MAXLEN_PIN); + log_debug ("dismiss pinpad entry prompt\n"); + rc = assuan_inquire (ctx, "DISMISSPINPADPROMPT", + &value, &valuelen, MAXLEN_PIN); } if (!rc) xfree (value); @@ -879,8 +913,8 @@ pin_cb (void *opaque, const char *info, char **retstr) /* Fixme: Write an inquire function which returns the result in secure memory and check all further handling of the PIN. */ - rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); - xfree (command); + rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); + xfree (command); if (rc) return rc; @@ -895,7 +929,7 @@ pin_cb (void *opaque, const char *info, char **retstr) } -static const char hlp_pksign[] = +static const char hlp_pksign[] = "PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] <hexified_id>\n" "\n" "The --hash option is optional; the default is SHA1."; @@ -924,7 +958,7 @@ cmd_pksign (assuan_context_t ctx, char *line) else if (has_option (line, "--hash=md5")) hash_algo = GCRY_MD_MD5; else if (!strstr (line, "--")) - hash_algo = GCRY_MD_SHA1; + hash_algo = GCRY_MD_SHA1; else return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm"); @@ -942,7 +976,7 @@ cmd_pksign (assuan_context_t ctx, char *line) keyidstr = xtrystrdup (line); if (!keyidstr) return out_of_core (); - + rc = app_sign (ctrl->app_ctx, keyidstr, hash_algo, pin_cb, ctx, @@ -967,7 +1001,7 @@ cmd_pksign (assuan_context_t ctx, char *line) } -static const char hlp_pkauth[] = +static const char hlp_pkauth[] = "PKAUTH <hexified_id>"; static gpg_error_t cmd_pkauth (assuan_context_t ctx, char *line) @@ -993,7 +1027,7 @@ cmd_pkauth (assuan_context_t ctx, char *line) keyidstr = xtrystrdup (line); if (!keyidstr) return out_of_core (); - + rc = app_auth (ctrl->app_ctx, keyidstr, pin_cb, ctx, @@ -1017,7 +1051,7 @@ cmd_pkauth (assuan_context_t ctx, char *line) } -static const char hlp_pkdecrypt[] = +static const char hlp_pkdecrypt[] = "PKDECRYPT <hexified_id>"; static gpg_error_t cmd_pkdecrypt (assuan_context_t ctx, char *line) @@ -1038,7 +1072,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line) if (!keyidstr) return out_of_core (); rc = app_decipher (ctrl->app_ctx, - keyidstr, + keyidstr, pin_cb, ctx, ctrl->in_data.value, ctrl->in_data.valuelen, &outdata, &outdatalen); @@ -1061,7 +1095,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line) } -static const char hlp_getattr[] = +static const char hlp_getattr[] = "GETATTR <name>\n" "\n" "This command is used to retrieve data from a smartcard. The\n" @@ -1100,7 +1134,7 @@ cmd_getattr (assuan_context_t ctx, char *line) } -static const char hlp_setattr[] = +static const char hlp_setattr[] = "SETATTR <name> <value> \n" "\n" "This command is used to store data on a a smartcard. The allowed\n" @@ -1153,7 +1187,7 @@ cmd_setattr (assuan_context_t ctx, char *orig_line) } -static const char hlp_writecert[] = +static const char hlp_writecert[] = "WRITECERT <hexified_certid>\n" "\n" "This command is used to store a certifciate on a smartcard. The\n" @@ -1205,7 +1239,7 @@ cmd_writecert (assuan_context_t ctx, char *line) } /* Write the certificate to the card. */ - rc = app_writecert (ctrl->app_ctx, ctrl, certid, + rc = app_writecert (ctrl->app_ctx, ctrl, certid, pin_cb, ctx, certdata, certdatalen); xfree (certid); xfree (certdata); @@ -1215,7 +1249,7 @@ cmd_writecert (assuan_context_t ctx, char *line) } -static const char hlp_writekey[] = +static const char hlp_writekey[] = "WRITEKEY [--force] <keyid> \n" "\n" "This command is used to store a secret key on a a smartcard. The\n" @@ -1282,7 +1316,7 @@ cmd_writekey (assuan_context_t ctx, char *line) } -static const char hlp_genkey[] = +static const char hlp_genkey[] = "GENKEY [--force] [--timestamp=<isodate>] <no>\n" "\n" "Generate a key on-card identified by NO, which is application\n" @@ -1360,7 +1394,7 @@ cmd_genkey (assuan_context_t ctx, char *line) } -static const char hlp_random[] = +static const char hlp_random[] = "RANDOM <nbytes>\n" "\n" "Get NBYTES of random from the card and send them back as data.\n" @@ -1377,7 +1411,7 @@ cmd_random (assuan_context_t ctx, char *line) unsigned char *buffer; if (!*line) - return set_error (GPG_ERR_ASS_PARAMETER, + return set_error (GPG_ERR_ASS_PARAMETER, "number of requested bytes missing"); nbytes = strtoul (line, NULL, 0); @@ -1443,7 +1477,7 @@ cmd_passwd (assuan_context_t ctx, char *line) if (!ctrl->app_ctx) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - + chvnostr = xtrystrdup (chvnostr); if (!chvnostr) return out_of_core (); @@ -1457,7 +1491,7 @@ cmd_passwd (assuan_context_t ctx, char *line) } -static const char hlp_checkpin[] = +static const char hlp_checkpin[] = "CHECKPIN <idstr>\n" "\n" "Perform a VERIFY operation without doing anything else. This may\n" @@ -1511,7 +1545,7 @@ cmd_checkpin (assuan_context_t ctx, char *line) idstr = xtrystrdup (line); if (!idstr) return out_of_core (); - + rc = app_check_pin (ctrl->app_ctx, idstr, pin_cb, ctx); xfree (idstr); if (rc) @@ -1522,7 +1556,7 @@ cmd_checkpin (assuan_context_t ctx, char *line) } -static const char hlp_lock[] = +static const char hlp_lock[] = "LOCK [--wait]\n" "\n" "Grant exclusive card access to this session. Note that there is\n" @@ -1559,14 +1593,14 @@ cmd_lock (assuan_context_t ctx, char *line) goto retry; } #endif /*USE_GNU_PTH*/ - + if (rc) log_error ("cmd_lock failed: %s\n", gpg_strerror (rc)); return rc; } -static const char hlp_unlock[] = +static const char hlp_unlock[] = "UNLOCK\n" "\n" "Release exclusive card access."; @@ -1594,7 +1628,7 @@ cmd_unlock (assuan_context_t ctx, char *line) } -static const char hlp_getinfo[] = +static const char hlp_getinfo[] = "GETINFO <what>\n" "\n" "Multi purpose command to return certain information. \n" @@ -1656,16 +1690,13 @@ cmd_getinfo (assuan_context_t ctx, char *line) if (!ctrl->server_local->card_removed && slot != -1) { struct slot_status_s *ss; - + if (!(slot >= 0 && slot < DIM(slot_table))) BUG (); ss = &slot_table[slot]; - if (!ss->valid) - BUG (); - - if (ss->any && (ss->status & 1)) + if (ss->valid && ss->any && (ss->status & 1)) flag = 'u'; } rc = assuan_send_data (ctx, &flag, 1); @@ -1677,7 +1708,7 @@ cmd_getinfo (assuan_context_t ctx, char *line) #else char *s = NULL; #endif - + if (s) rc = assuan_send_data (ctx, s, strlen (s)); else @@ -1701,7 +1732,7 @@ cmd_getinfo (assuan_context_t ctx, char *line) } -static const char hlp_restart[] = +static const char hlp_restart[] = "RESTART\n" "\n" "Restart the current connection; this is a kind of warm reset. It\n" @@ -1732,7 +1763,7 @@ cmd_restart (assuan_context_t ctx, char *line) } -static const char hlp_disconnect[] = +static const char hlp_disconnect[] = "DISCONNECT\n" "\n" "Disconnect the card if it is not any longer used by other\n" @@ -1743,14 +1774,14 @@ cmd_disconnect (assuan_context_t ctx, char *line) ctrl_t ctrl = assuan_get_pointer (ctx); (void)line; - + ctrl->server_local->disconnect_allowed = 1; return 0; } -static const char hlp_apdu[] = +static const char hlp_apdu[] = "APDU [--atr] [--more] [--exlen[=N]] [hexstring]\n" "\n" "Send an APDU to the current reader. This command bypasses the high\n" @@ -1807,7 +1838,7 @@ cmd_apdu (assuan_context_t ctx, char *line) unsigned char *atr; size_t atrlen; char hexbuf[400]; - + atr = apdu_get_atr (ctrl->reader_slot, &atrlen); if (!atr || atrlen > sizeof hexbuf - 2 ) { @@ -1849,7 +1880,7 @@ cmd_apdu (assuan_context_t ctx, char *line) } -static const char hlp_killscd[] = +static const char hlp_killscd[] = "KILLSCD\n" "\n" "Commit suicide."; @@ -1883,8 +1914,8 @@ register_commands (assuan_context_t ctx) { "PKSIGN", cmd_pksign, hlp_pksign }, { "PKAUTH", cmd_pkauth, hlp_pkauth }, { "PKDECRYPT", cmd_pkdecrypt,hlp_pkdecrypt }, - { "INPUT", NULL }, - { "OUTPUT", NULL }, + { "INPUT", NULL }, + { "OUTPUT", NULL }, { "GETATTR", cmd_getattr, hlp_getattr }, { "SETATTR", cmd_setattr, hlp_setattr }, { "WRITECERT", cmd_writecert,hlp_writecert }, @@ -1910,7 +1941,7 @@ register_commands (assuan_context_t ctx) table[i].help); if (rc) return rc; - } + } assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready"); assuan_register_reset_notify (ctx, reset_notify); @@ -1928,7 +1959,7 @@ scd_command_handler (ctrl_t ctrl, int fd) int rc; assuan_context_t ctx = NULL; int stopme; - + rc = assuan_new (&ctx); if (rc) { @@ -1996,7 +2027,7 @@ scd_command_handler (ctrl_t ctrl, int fd) log_info ("Assuan accept problem: %s\n", gpg_strerror (rc)); break; } - + rc = assuan_process (ctx); if (rc) { @@ -2006,7 +2037,7 @@ scd_command_handler (ctrl_t ctrl, int fd) } /* Cleanup. We don't send an explicit reset to the card. */ - do_reset (ctrl, 0); + do_reset (ctrl, 0); /* Release the server object. */ if (session_list == ctrl->server_local) @@ -2014,7 +2045,7 @@ scd_command_handler (ctrl_t ctrl, int fd) else { struct server_local_s *sl; - + for (sl=session_list; sl->next_session; sl = sl->next_session) if (sl->next_session == ctrl->server_local) break; @@ -2022,7 +2053,7 @@ scd_command_handler (ctrl_t ctrl, int fd) BUG (); sl->next_session = ctrl->server_local->next_session; } - stopme = ctrl->server_local->stopme || reader_disabled; + stopme = ctrl->server_local->stopme; xfree (ctrl->server_local); ctrl->server_local = NULL; @@ -2049,10 +2080,10 @@ send_status_info (ctrl_t ctrl, const char *keyword, ...) char buf[950], *p; size_t n; assuan_context_t ctx = ctrl->server_local->assuan_ctx; - + va_start (arg_ptr, keyword); - p = buf; + p = buf; n = 0; while ( (value = va_arg (arg_ptr, const unsigned char *)) ) { @@ -2102,17 +2133,17 @@ static void send_client_notifications (void) { struct { - pid_t pid; + pid_t pid; #ifdef HAVE_W32_SYSTEM HANDLE handle; #else - int signo; + 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) @@ -2120,9 +2151,9 @@ send_client_notifications (void) 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 + if (killed[kidx].pid == pid && killed[kidx].handle == handle) break; if (kidx < killidx) @@ -2144,11 +2175,11 @@ send_client_notifications (void) } #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 + if (killed[kidx].pid == pid && killed[kidx].signo == signo) break; if (kidx < killidx) @@ -2182,11 +2213,6 @@ update_reader_status_file (int set_card_removed_flag) 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 @@ -2199,11 +2225,12 @@ update_reader_status_file (int set_card_removed_flag) if (!ss->valid || ss->slot == -1) continue; /* Not valid or reader not yet open. */ - + sw_apdu = apdu_get_status (ss->slot, 0, &status, &changed); if (sw_apdu == SW_HOST_NO_READER) { /* Most likely the _reader_ has been unplugged. */ + application_notify_card_reset (ss->slot); apdu_close_reader (ss->slot); ss->valid = 0; status = 0; @@ -2212,7 +2239,7 @@ update_reader_status_file (int set_card_removed_flag) else if (sw_apdu) { /* Get status failed. Ignore that. */ - continue; + continue; } if (!ss->any || ss->status != status || ss->changed != changed ) @@ -2241,14 +2268,14 @@ update_reader_status_file (int set_card_removed_flag) fclose (fp); } xfree (fname); - + /* If a status script is executable, run it. */ { const char *args[9], *envs[2]; char numbuf1[30], numbuf2[30], numbuf3[30]; char *homestr, *envstr; gpg_error_t err; - + homestr = make_filename (opt.homedir, NULL); if (estream_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0) log_error ("out of core while building environment\n"); @@ -2261,16 +2288,16 @@ update_reader_status_file (int set_card_removed_flag) sprintf (numbuf2, "0x%04X", ss->status); sprintf (numbuf3, "0x%04X", status); args[0] = "--reader-port"; - args[1] = numbuf1; + args[1] = numbuf1; args[2] = "--old-code"; - args[3] = numbuf2; + args[3] = numbuf2; args[4] = "--new-code"; - args[5] = numbuf3; + args[5] = numbuf3; args[6] = "--status"; args[7] = ((status & 1)? "USABLE": (status & 4)? "ACTIVE": (status & 2)? "PRESENT": "NOCARD"); - args[8] = NULL; + args[8] = NULL; fname = make_filename (opt.homedir, "scd-event", NULL); err = gnupg_spawn_process_detached (fname, args, envs); @@ -2283,24 +2310,22 @@ update_reader_status_file (int set_card_removed_flag) xfree (homestr); } - /* Set the card removed flag for all current sessions. We - will set this on any card change because a reset or - SERIALNO request must be done in any case. */ - if (ss->any && set_card_removed_flag) + /* Set the card removed flag for all current sessions. */ + if (ss->any && ss->status == 0 && set_card_removed_flag) update_card_removed (idx, 1); - + ss->any = 1; /* Send a signal to all clients who applied for it. */ send_client_notifications (); } - + /* Check whether a disconnect is pending. */ if (opt.card_timeout) { for (sl=session_list; sl; sl = sl->next_session) if (!sl->disconnect_allowed) - break; + break; if (session_list && !sl) { /* FIXME: Use a real timeout. */ @@ -2309,7 +2334,7 @@ update_reader_status_file (int set_card_removed_flag) apdu_disconnect (ss->slot); } } - + } } |