1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

PIN caching of cards does now work.

This commit is contained in:
Werner Koch 2006-02-09 18:29:31 +00:00
parent 3d7b030025
commit 4472efd12c
9 changed files with 256 additions and 30 deletions

127
scd/app.c
View file

@ -40,9 +40,15 @@ static struct
int initialized;
pth_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];
static void deallocate_app (app_t app);
/* Lock the reader SLOT. This function shall be used right before
calling any of the actual application functions to serialize access
to the reader. We do this always even if the reader is not
@ -68,6 +74,7 @@ lock_reader (int slot)
}
lock_table[slot].initialized = 1;
lock_table[slot].app = NULL;
lock_table[slot].last_app = NULL;
}
if (!pth_mutex_acquire (&lock_table[slot].lock, 0, NULL))
@ -121,13 +128,21 @@ app_dump_state (void)
log_info ("app_dump_state: slot=%d lock=", slot);
dump_mutex_state (&lock_table[slot].lock);
if (lock_table[slot].app)
log_printf (" app=%p type=`%s'",
lock_table[slot].app, lock_table[slot].app->apptype);
{
log_printf (" app=%p", lock_table[slot].app);
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");
}
}
/* Check wether the application NAME is allowed. This does not mean
we have support for it though. */
static int
@ -142,6 +157,46 @@ is_app_allowed (const char *name)
}
/* This may be called to tell this module about a removed card. */
void
application_notify_card_removed (int slot)
{
if (slot < 0 || slot >= DIM (lock_table))
return;
/* Deallocate a saved application for that slot, so that we won't
try to reuse it. */
if (lock_table[slot].initialized && lock_table[slot].last_app)
{
app_t app = lock_table[slot].last_app;
lock_table[slot].last_app = NULL;
deallocate_app (app);
}
}
/* This fucntion 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
already done a select_application. */
gpg_error_t
check_application_conflict (ctrl_t ctrl, const char *name)
{
int slot = ctrl->reader_slot;
app_t app;
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;
}
/* If called with NAME as NULL, select the best fitting application
and return a context; otherwise select the application with NAME
and return a context. SLOT identifies the reader device. Returns
@ -173,6 +228,32 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
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 - so the
PIN cache and other cached data are preserved. */
if (!app && lock_table[slot].initialized && lock_table[slot].last_app)
{
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;
}
}
/* If we can reuse an application, bump the reference count and
return it. */
if (app)
{
if (app->slot != slot)
@ -183,6 +264,7 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
return 0; /* Okay: We share that one. */
}
/* Need to allocate a new one. */
app = xtrycalloc (1, sizeof *app);
if (!app)
{
@ -281,9 +363,25 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
}
/* Deallocate the application. */
static void
deallocate_app (app_t app)
{
if (app->fnc.deinit)
{
app->fnc.deinit (app);
app->fnc.deinit = NULL;
}
xfree (app->serialno);
xfree (app);
}
/* Free the resources associated with the application APP. APP is
allowed to be NULL in which case this is a no-op. Note that we are
using reference counting to track the users of the application. */
using reference counting to track the users of the application and
actually deferiing the deallcoation to allow for a later resuse by
a new connection. */
void
release_application (app_t app)
{
@ -297,20 +395,19 @@ release_application (app_t app)
if (--app->ref_count)
return;
/* Clear the reference to the application from the lock table. */
/* Move the reference to the application in the lock table. */
for (slot = 0; slot < DIM (lock_table); slot++)
if (lock_table[slot].initialized && lock_table[slot].app == app)
lock_table[slot].app = NULL;
{
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;
return;
}
/* Deallocate. */
if (app->fnc.deinit)
{
app->fnc.deinit (app);
app->fnc.deinit = NULL;
}
xfree (app->serialno);
xfree (app);
log_debug ("application missing in lock table - deallocating anyway\n");
deallocate_app (app);
}