diff options
author | NIIBE Yutaka <[email protected]> | 2015-12-04 05:13:23 +0000 |
---|---|---|
committer | NIIBE Yutaka <[email protected]> | 2015-12-04 05:13:23 +0000 |
commit | 9639af5f16a7ed908cbce2415330b9fcd88edc90 (patch) | |
tree | 8017012c310bf1d417583d45b8d4fd49048a2bdd | |
parent | scd: More fix for Curve25519 prefix handling. (diff) | |
download | gnupg-9639af5f16a7ed908cbce2415330b9fcd88edc90.tar.gz gnupg-9639af5f16a7ed908cbce2415330b9fcd88edc90.zip |
scd: Simplify saving application context.
* scd/app.c (lock_table): Remove LAST_APP field.
(lock_reader, app_dump_state, application_notify_card_reset)
(release_application): Follow the change.
(check_conflict): New.
(check_application_conflict): Lock the slot and call check_conflict.
(select_application): Call check_conflict and not use LAST_APP.
--
We don't need LAST_APP field but just keep the application context by
APP field. Since we have a reference counter, it is possible if we
can deallocate or not.
Diffstat (limited to '')
-rw-r--r-- | scd/app.c | 103 |
1 files changed, 41 insertions, 62 deletions
@@ -39,7 +39,6 @@ static struct int initialized; npth_mutex_t lock; app_t app; /* Application context in use or NULL. */ - app_t last_app; /* Last application object used as this slot or NULL. */ } lock_table[10]; @@ -87,7 +86,6 @@ lock_reader (int slot, ctrl_t ctrl) } lock_table[slot].initialized = 1; lock_table[slot].app = NULL; - lock_table[slot].last_app = NULL; } res = npth_mutex_lock (&lock_table[slot].lock); @@ -139,12 +137,6 @@ app_dump_state (void) if (lock_table[slot].app->apptype) log_printf (" type='%s'", lock_table[slot].app->apptype); } - if (lock_table[slot].last_app) - { - log_printf (" lastapp=%p", lock_table[slot].last_app); - if (lock_table[slot].last_app->apptype) - log_printf (" type='%s'", lock_table[slot].last_app->apptype); - } log_printf ("\n"); } } @@ -167,8 +159,6 @@ is_app_allowed (const char *name) void application_notify_card_reset (int slot) { - app_t app; - if (slot < 0 || slot >= DIM (lock_table)) return; @@ -182,20 +172,35 @@ application_notify_card_reset (int slot) lock_table[slot].app = NULL; } - /* Deallocate a saved application for that slot, so that we won't - try to reuse it. If there is no saved application, set a flag so - that we won't save the current state. */ - app = lock_table[slot].last_app; + unlock_reader (slot); +} - if (app) + +/* + * This function is called with lock held. + */ +static gpg_error_t +check_conflict (int slot, const char *name) +{ + app_t app = lock_table[slot].app; + + if (!app || !name || (app->apptype && !ascii_strcasecmp (app->apptype, name))) + return 0; + + if (!app->ref_count) { - lock_table[slot].last_app = NULL; + lock_table[slot].app = NULL; deallocate_app (app); + return 0; + } + else + { + log_info ("application '%s' in use by reader %d - can't switch\n", + app->apptype? app->apptype : "<null>", slot); + return gpg_error (GPG_ERR_CONFLICT); } - unlock_reader (slot); } - /* This function is used by the serialno command to check for an application conflict which may appear if the serialno command is used to request a specific application and the connection has @@ -203,18 +208,18 @@ application_notify_card_reset (int slot) gpg_error_t check_application_conflict (ctrl_t ctrl, int slot, const char *name) { - app_t app; - - (void)ctrl; + gpg_error_t err; if (slot < 0 || slot >= DIM (lock_table)) return gpg_error (GPG_ERR_INV_VALUE); - app = lock_table[slot].initialized ? lock_table[slot].app : NULL; - if (app && app->apptype && name) - if ( ascii_strcasecmp (app->apptype, name)) - return gpg_error (GPG_ERR_CONFLICT); - return 0; + err = lock_reader (slot, ctrl); + if (err) + return err; + + err = check_conflict (slot, name); + unlock_reader (slot); + return err; } @@ -243,41 +248,15 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) return err; /* First check whether we already have an application to share. */ - app = lock_table[slot].initialized ? lock_table[slot].app : NULL; - if (app && name) - if (!app->apptype || ascii_strcasecmp (app->apptype, name)) - { - unlock_reader (slot); - if (app->apptype) - log_info ("application '%s' in use by reader %d - can't switch\n", - app->apptype, slot); - return gpg_error (GPG_ERR_CONFLICT); - } - - /* If we don't have an app, check whether we have a saved - application for that slot. This is useful so that a card does - not get reset even if only one session is using the card - this - way the PIN cache and other cached data are preserved. */ - if (!app && lock_table[slot].initialized && lock_table[slot].last_app) + err = check_conflict (slot, name); + if (err) { - app = lock_table[slot].last_app; - if (!name || (app->apptype && !ascii_strcasecmp (app->apptype, name)) ) - { - /* Yes, we can reuse this application - either the caller - requested an unspecific one or the requested one matches - the saved one. */ - lock_table[slot].app = app; - lock_table[slot].last_app = NULL; - } - else - { - /* No, this saved application can't be used - deallocate it. */ - lock_table[slot].last_app = NULL; - deallocate_app (app); - app = NULL; - } + unlock_reader (slot); + return err; } + app = lock_table[slot].app; + /* If we can reuse an application, bump the reference count and return it. */ if (app) @@ -486,10 +465,10 @@ release_application (app_t app) return; } - if (lock_table[slot].last_app) - deallocate_app (lock_table[slot].last_app); - lock_table[slot].last_app = lock_table[slot].app; - lock_table[slot].app = NULL; + /* We don't deallocate app here. Instead, we keep it. This is + useful so that a card does not get reset even if only one session + is using the card - this way the PIN cache and other cached data + are preserved. */ unlock_reader (slot); } |