From d9787447fe6a57e39113b60305b4ab672b9ba897 Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Tue, 9 Feb 2021 16:00:19 +0900 Subject: Imported Upstream version 2.1.19 --- scd/app.c | 160 +++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 85 insertions(+), 75 deletions(-) (limited to 'scd/app.c') diff --git a/scd/app.c b/scd/app.c index b10a452..1d81631 100644 --- a/scd/app.c +++ b/scd/app.c @@ -136,45 +136,38 @@ check_application_conflict (const char *name, app_t app) } -static void -release_application_internal (app_t app) -{ - if (!app->ref_count) - log_bug ("trying to release an already released context\n"); - - --app->ref_count; -} - gpg_error_t app_reset (app_t app, ctrl_t ctrl, int send_reset) { - gpg_error_t err; - - err = lock_app (app, ctrl); - if (err) - return err; + gpg_error_t err = 0; if (send_reset) { - int sw = apdu_reset (app->slot); + int sw; + + lock_app (app, ctrl); + sw = apdu_reset (app->slot); if (sw) err = gpg_error (GPG_ERR_CARD_RESET); - /* Release the same application which is used by other sessions. */ - send_client_notifications (app, 1); + app->reset_requested = 1; + unlock_app (app); + + scd_kick_the_loop (); + gnupg_sleep (1); } else { ctrl->app_ctx = NULL; - release_application_internal (app); + release_application (app, 0); } - unlock_app (app); return err; } static gpg_error_t -app_new_register (int slot, ctrl_t ctrl, const char *name) +app_new_register (int slot, ctrl_t ctrl, const char *name, + int periodical_check_needed) { gpg_error_t err = 0; app_t app = NULL; @@ -192,6 +185,7 @@ app_new_register (int slot, ctrl_t ctrl, const char *name) } app->slot = slot; + app->card_status = (unsigned int)-1; if (npth_mutex_init (&app->lock, NULL)) { @@ -302,7 +296,7 @@ app_new_register (int slot, ctrl_t ctrl, const char *name) return err; } - app->require_get_status = 1; /* For token, this can be 0. */ + app->periodical_check_needed = periodical_check_needed; npth_mutex_lock (&app_list_lock); app->next = app_top; @@ -329,7 +323,9 @@ select_application (ctrl_t ctrl, const char *name, app_t *r_app, if (scan || !app_top) { struct dev_list *l; + int periodical_check_needed = 0; + /* Scan the devices to find new device(s). */ err = apdu_dev_list_start (opt.reader_port, &l); if (err) return err; @@ -337,38 +333,36 @@ select_application (ctrl_t ctrl, const char *name, app_t *r_app, while (1) { int slot; - int sw; + int periodical_check_needed_this; - slot = apdu_open_reader (l); + slot = apdu_open_reader (l, !app_top); if (slot < 0) break; - err = 0; - sw = apdu_connect (slot); - - if (sw == SW_HOST_CARD_INACTIVE) + periodical_check_needed_this = apdu_connect (slot); + if (periodical_check_needed_this < 0) { - /* Try again. */ - sw = apdu_reset (slot); + /* We close a reader with no card. */ + err = gpg_error (GPG_ERR_ENODEV); } - - if (!sw || sw == SW_HOST_ALREADY_CONNECTED) - err = 0; - else if (sw == SW_HOST_NO_CARD) - err = gpg_error (GPG_ERR_CARD_NOT_PRESENT); - else - err = gpg_error (GPG_ERR_ENODEV); - - if (!err) - err = app_new_register (slot, ctrl, name); else { - /* We close a reader with no card. */ - apdu_close_reader (slot); + err = app_new_register (slot, ctrl, name, + periodical_check_needed_this); + if (periodical_check_needed_this) + periodical_check_needed = 1; } + + if (err) + apdu_close_reader (slot); } apdu_dev_list_finish (l); + + /* If periodical check is needed for new device(s), kick the + scdaemon loop. */ + if (periodical_check_needed) + scd_kick_the_loop (); } npth_mutex_lock (&app_list_lock); @@ -464,6 +458,8 @@ deallocate_app (app_t app) } xfree (app->serialno); + + unlock_app (app); xfree (app); } @@ -473,7 +469,7 @@ deallocate_app (app_t app) actually deferring the deallocation to allow for a later reuse by a new connection. */ void -release_application (app_t app) +release_application (app_t app, int locked_already) { if (!app) return; @@ -483,9 +479,15 @@ release_application (app_t app) is using the card - this way the PIN cache and other cached data are preserved. */ - lock_app (app, NULL); - release_application_internal (app); - unlock_app (app); + if (!locked_already) + lock_app (app, NULL); + + if (!app->ref_count) + log_bug ("trying to release an already released context\n"); + + --app->ref_count; + if (!locked_already) + unlock_app (app); } @@ -1014,21 +1016,26 @@ report_change (int slot, int old_status, int cur_status) xfree (homestr); } -void +int scd_update_reader_status_file (void) { app_t a, app_next; + int periodical_check_needed = 0; npth_mutex_lock (&app_list_lock); for (a = app_top; a; a = app_next) { + int sw; + unsigned int status; + + lock_app (a, NULL); app_next = a->next; - if (a->require_get_status) + + if (a->reset_requested) + status = 0; + else { - int sw; - unsigned int status; sw = apdu_get_status (a->slot, 0, &status); - if (sw == SW_HOST_NO_READER) { /* Most likely the _reader_ has been unplugged. */ @@ -1037,26 +1044,42 @@ scd_update_reader_status_file (void) else if (sw) { /* Get status failed. Ignore that. */ + if (a->periodical_check_needed) + periodical_check_needed = 1; + unlock_app (a); continue; } + } - if (a->card_status != status) + if (a->card_status != status) + { + report_change (a->slot, a->card_status, status); + send_client_notifications (a, status == 0); + + if (status == 0) { - report_change (a->slot, a->card_status, status); - send_client_notifications (a, status == 0); - - if (status == 0) - { - log_debug ("Removal of a card: %d\n", a->slot); - apdu_close_reader (a->slot); - deallocate_app (a); - } - else - a->card_status = status; + log_debug ("Removal of a card: %d\n", a->slot); + apdu_close_reader (a->slot); + deallocate_app (a); } + else + { + a->card_status = status; + if (a->periodical_check_needed) + periodical_check_needed = 1; + unlock_app (a); + } + } + else + { + if (a->periodical_check_needed) + periodical_check_needed = 1; + unlock_app (a); } } npth_mutex_unlock (&app_list_lock); + + return periodical_check_needed; } /* This function must be called once to initialize this module. This @@ -1078,19 +1101,6 @@ initialize_module_command (void) return apdu_init (); } -app_t -app_list_start (void) -{ - npth_mutex_lock (&app_list_lock); - return app_top; -} - -void -app_list_finish (void) -{ - npth_mutex_unlock (&app_list_lock); -} - void app_send_card_list (ctrl_t ctrl) { -- cgit v1.2.3