diff options
author | Werner Koch <[email protected]> | 2011-12-14 09:30:01 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2011-12-14 09:30:31 +0000 |
commit | 2d91febbd8d30beb7eb33f7aa80ffd5691d1d3cc (patch) | |
tree | 6067bc98a1271e4ce7c45f61ef0283949b77765f | |
parent | scd: Add debug option for reader function calls. (diff) | |
download | gnupg-2d91febbd8d30beb7eb33f7aa80ffd5691d1d3cc.tar.gz gnupg-2d91febbd8d30beb7eb33f7aa80ffd5691d1d3cc.zip |
scd: Fix resetting and closing of the reader.
* scd/command.c (update_card_removed): Do no act on an invalid VRDR.
(do_reset): Ignore apdu_reset error codes for no and inactive card.
Close the reader before setting the slot to -1.
(update_reader_status_file): Notify the application before closing the
reader.
--
With this change the scd now works as it did in the past. In
particular there is no more endless loop trying to open the reader by
the update_reader_status_file ticker function. That bug basically
blocked all card operations until the scdaemon was killed.
-rw-r--r-- | scd/command.c | 57 |
1 files changed, 33 insertions, 24 deletions
diff --git a/scd/command.c b/scd/command.c index 2ade38afb..0f5744829 100644 --- a/scd/command.c +++ b/scd/command.c @@ -180,6 +180,19 @@ initialize_module_command (void) } +/* Helper to return the slot number for a given virtual reader index + VRDR. In case on an error -1 is returned. */ +static int +vreader_slot (int vrdr) +{ + if (vrdr == -1 || !(vrdr >= 0 && vrdr < DIM(vreader_table))) + return -1; + if (!vreader_table [vrdr].valid) + return -1; + return vreader_table[vrdr].slot; +} + + /* Update the CARD_REMOVED element of all sessions using the virtual reader given by VRDR to VALUE. */ static void @@ -187,6 +200,9 @@ update_card_removed (int vrdr, int value) { struct server_local_s *sl; + if (vrdr == -1) + return; + for (sl=session_list; sl; sl = sl->next_session) if (sl->ctrl_backlink && sl->ctrl_backlink->server_local->vreader_idx == vrdr) @@ -195,20 +211,7 @@ update_card_removed (int vrdr, int value) } /* Let the card application layer know about the removal. */ if (value) - application_notify_card_reset (vrdr); -} - - -/* Helper to return the slot number for a given virtual reader index - VRDR. In case on an error -1 is returned. */ -static int -vreader_slot (int vrdr) -{ - if (vrdr == -1 || !(vrdr >= 0 && vrdr < DIM(vreader_table))) - return -1; - if (!vreader_table [vrdr].valid) - return -1; - return vreader_table[vrdr].slot; + application_notify_card_reset (vreader_slot (vrdr)); } @@ -298,6 +301,7 @@ static void do_reset (ctrl_t ctrl, int send_reset) { int vrdr = ctrl->server_local->vreader_idx; + int slot; if (!(vrdr == -1 || (vrdr >= 0 && vrdr < DIM(vreader_table)))) BUG (); @@ -324,13 +328,22 @@ do_reset (ctrl_t ctrl, int send_reset) /* If we want a real reset for the card, send the reset APDU and tell the application layer about it. */ - if (vrdr != -1 && send_reset && !IS_LOCKED (ctrl) ) + slot = vreader_slot (vrdr); + if (slot != -1 && send_reset && !IS_LOCKED (ctrl) ) { - if (apdu_reset (vreader_table[vrdr].slot)) + application_notify_card_reset (slot); + switch (apdu_reset (slot)) { - vreader_table[vrdr].valid = 0; + case 0: + break; + case SW_HOST_NO_CARD: + case SW_HOST_CARD_INACTIVE: + break; + default: + apdu_close_reader (slot); + vreader_table[vrdr].slot = slot = -1; + break; } - application_notify_card_reset (vrdr); } /* If we hold a lock, unlock now. */ @@ -1696,11 +1709,7 @@ cmd_getinfo (assuan_context_t ctx, char *line) BUG (); vr = &vreader_table[vrdr]; - - if (!vr->valid) - BUG (); - - if (vr->any && (vr->status & 1)) + if (vr->valid && vr->any && (vr->status & 1)) flag = 'u'; } rc = assuan_send_data (ctx, &flag, 1); @@ -2248,9 +2257,9 @@ update_reader_status_file (int set_card_removed_flag) if (sw_apdu == SW_HOST_NO_READER) { /* Most likely the _reader_ has been unplugged. */ + application_notify_card_reset (vr->slot); apdu_close_reader (vr->slot); vr->slot = -1; - vr->valid = 0; status = 0; changed = vr->changed; } |