mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
scd: Fix access to list of cards (3/3).
* scd/app-common.h (card_reset): Simplify more. (select_additional_application): Supply CARD. (card_ref, card_unref): Remove. (card_get, card_put): New. * scd/app.c (card_reset): No locking/unlocking inside. (app_switch_current_card): Fix comment. (select_additional_application): No locking/unlocking inside. (do_with_keygrip): New, unlocked version. (card_get): New, with support of KEYGRIP. (card_unref): Remove. (card_put): New. (app_write_learn_status, app_readcert: No locking/unlocking inside. (app_readkey, app_getattr, app_setattr, app_sign, app_auth): Likewise. (app_decipher, app_writecert, app_writekey): Likewise. (app_genkey, app_get_challenge, app_change_pin): Likewise. (app_check_pin, app_switch_active_app): Likewise. * scd/command.c (do_reset): Use card_get/card_put. (open_card_with_request): Use card_get/card_put, return CARD locked. (cmd_serialno): Follow the change of open_card_with_request. (cmd_switchapp): Use card_get/card_put. (cmd_learn, cmd_readcert, cmd_readkey, cmd_pksign): Likewise. (cmd_pkauth, cmd_pkdecrypt, cmd_getattr): Likewise. (cmd_setattr, cmd_writecert, cmd_writekey): Likewise. (cmd_genkey, cmd_random, cmd_passwd): Likewise. (cmd_checkpin, cmd_getinfo, cmd_restart): Likewise. (cmd_disconnect, cmd_apdu, cmd_devinfo): Likewise. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
b436fb6766
commit
0d6b4210cf
@ -255,11 +255,12 @@ void application_notify_card_reset (int slot);
|
||||
gpg_error_t check_application_conflict (card_t card, const char *name,
|
||||
const unsigned char *serialno_bin,
|
||||
size_t serialno_bin_len);
|
||||
gpg_error_t card_reset (card_t card, ctrl_t ctrl);
|
||||
gpg_error_t card_reset (card_t card);
|
||||
gpg_error_t select_application (ctrl_t ctrl, const char *name,
|
||||
int scan, const unsigned char *serialno_bin,
|
||||
size_t serialno_bin_len);
|
||||
gpg_error_t select_additional_application (ctrl_t ctrl, const char *name);
|
||||
gpg_error_t select_additional_application (card_t card,
|
||||
ctrl_t ctrl, const char *name);
|
||||
|
||||
gpg_error_t app_switch_current_card (ctrl_t ctrl,
|
||||
const unsigned char *serialno,
|
||||
@ -269,8 +270,8 @@ gpg_error_t app_switch_active_app (card_t card, ctrl_t ctrl,
|
||||
|
||||
char *get_supported_applications (void);
|
||||
|
||||
card_t card_ref (card_t card);
|
||||
void card_unref (card_t card);
|
||||
card_t card_get (ctrl_t ctrl, const char *keygrip);
|
||||
void card_put (card_t card);
|
||||
void card_unref_locked (card_t card);
|
||||
|
||||
gpg_error_t app_munge_serialno (card_t card);
|
||||
|
291
scd/app.c
291
scd/app.c
@ -503,18 +503,16 @@ check_application_conflict (card_t card, const char *name,
|
||||
|
||||
|
||||
gpg_error_t
|
||||
card_reset (card_t card, ctrl_t ctrl)
|
||||
card_reset (card_t card)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
int sw;
|
||||
|
||||
lock_card (card, ctrl);
|
||||
sw = apdu_reset (card->slot);
|
||||
if (sw)
|
||||
err = gpg_error (GPG_ERR_CARD_RESET);
|
||||
|
||||
card->reset_requested = 1;
|
||||
unlock_card (card);
|
||||
scd_kick_the_loop ();
|
||||
gnupg_sleep (1);
|
||||
|
||||
@ -862,7 +860,6 @@ select_application (ctrl_t ctrl, const char *name,
|
||||
|
||||
if (!err)
|
||||
{
|
||||
/* Note: We do not use card_ref as we are already locked. */
|
||||
card->ref_count++;
|
||||
ctrl->card_ctx = card;
|
||||
if (card_prev)
|
||||
@ -895,7 +892,8 @@ app_switch_current_card (ctrl_t ctrl,
|
||||
|
||||
lock_r_card_list ();
|
||||
|
||||
if (!ctrl->card_ctx)
|
||||
cardtmp = ctrl->card_ctx;
|
||||
if (!cardtmp)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
goto leave;
|
||||
@ -915,10 +913,10 @@ app_switch_current_card (ctrl_t ctrl,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Note: We do not use card_ref here because we only swap the
|
||||
* context of the current session and there is no chance of a
|
||||
* context switch. This also works if the card stays the same. */
|
||||
cardtmp = ctrl->card_ctx;
|
||||
/* Note: We do not lock CARD and CARDTMP here because we only
|
||||
* swap the context of the current session and there is no
|
||||
* chance of a context switch. This also works if the card
|
||||
* stays the same. */
|
||||
ctrl->card_ctx = card;
|
||||
card->ref_count++;
|
||||
card_unref_locked (cardtmp);
|
||||
@ -1077,11 +1075,10 @@ select_all_additional_applications_internal (ctrl_t ctrl, card_t card)
|
||||
* active application. On error no new application is allocated.
|
||||
* Selecting an already selected application has no effect. */
|
||||
gpg_error_t
|
||||
select_additional_application (ctrl_t ctrl, const char *name)
|
||||
select_additional_application (card_t card, ctrl_t ctrl, const char *name)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
apptype_t req_apptype;
|
||||
card_t card;
|
||||
|
||||
if (!name)
|
||||
req_apptype = 0;
|
||||
@ -1092,14 +1089,6 @@ select_additional_application (ctrl_t ctrl, const char *name)
|
||||
return gpg_error (GPG_ERR_NOT_FOUND);
|
||||
}
|
||||
|
||||
card = ctrl->card_ctx;
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (req_apptype)
|
||||
{
|
||||
err = select_additional_application_internal (card, req_apptype);
|
||||
@ -1115,7 +1104,6 @@ select_additional_application (ctrl_t ctrl, const char *name)
|
||||
err = select_all_additional_applications_internal (ctrl, card);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1183,35 +1171,104 @@ deallocate_card (card_t card)
|
||||
}
|
||||
|
||||
|
||||
/* Increment the reference counter of CARD. Returns CARD. */
|
||||
card_t
|
||||
card_ref (card_t card)
|
||||
static card_t
|
||||
do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str,
|
||||
int capability)
|
||||
{
|
||||
lock_card (card, NULL);
|
||||
++card->ref_count;
|
||||
unlock_card (card);
|
||||
return card;
|
||||
int locked = 0;
|
||||
card_t c;
|
||||
app_t a, a_prev;
|
||||
|
||||
for (c = card_top; c; c = c->next)
|
||||
{
|
||||
if (lock_card (c, ctrl))
|
||||
{
|
||||
c = NULL;
|
||||
goto leave_the_loop;
|
||||
}
|
||||
locked = 1;
|
||||
a_prev = NULL;
|
||||
for (a = c->app; a; a = a->next)
|
||||
{
|
||||
if (!a->fnc.with_keygrip || a->need_reset)
|
||||
continue;
|
||||
|
||||
/* Note that we need to do a re-select even for the current
|
||||
* app because the last selected application (e.g. after
|
||||
* init) might be a different one and we do not run
|
||||
* maybe_switch_app here. Of course we we do this only iff
|
||||
* we have an additional app. */
|
||||
if (c->app->next)
|
||||
{
|
||||
if (run_reselect (ctrl, c, a, a_prev))
|
||||
continue;
|
||||
}
|
||||
a_prev = a;
|
||||
|
||||
if (DBG_APP)
|
||||
log_debug ("slot %d, app %s: calling with_keygrip(%s)\n",
|
||||
c->slot, xstrapptype (a),
|
||||
action == KEYGRIP_ACTION_SEND_DATA? "send_data":
|
||||
action == KEYGRIP_ACTION_WRITE_STATUS? "status":
|
||||
action == KEYGRIP_ACTION_LOOKUP? "lookup":"?");
|
||||
if (!a->fnc.with_keygrip (a, ctrl, action, keygrip_str, capability))
|
||||
goto leave_the_loop; /* ACTION_LOOKUP succeeded. */
|
||||
}
|
||||
|
||||
/* Select the first app again. */
|
||||
if (c->app->next)
|
||||
run_reselect (ctrl, c, c->app, a_prev);
|
||||
|
||||
unlock_card (c);
|
||||
locked = 0;
|
||||
}
|
||||
|
||||
leave_the_loop:
|
||||
/* Force switching of the app if the selected one is not the current
|
||||
* one. Changing the current apptype is sufficient to do this. */
|
||||
if (c && c->app && c->app->apptype != a->apptype)
|
||||
ctrl->current_apptype = a->apptype;
|
||||
|
||||
if (locked && c)
|
||||
{
|
||||
unlock_card (c);
|
||||
locked = 0;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/* Decrement the reference counter for CARD. Note that we are using
|
||||
* reference counting to track the users of the card's application and
|
||||
* are deferring the actual deallocation to allow for a later reuse by
|
||||
* a new connection. Using NULL for CARD is a no-op. */
|
||||
void
|
||||
card_unref (card_t card)
|
||||
/* Locking access to the card-list and CARD, returns CARD. */
|
||||
card_t
|
||||
card_get (ctrl_t ctrl, const char *keygrip)
|
||||
{
|
||||
if (!card)
|
||||
return;
|
||||
card_t card;
|
||||
|
||||
lock_r_card_list ();
|
||||
if (keygrip)
|
||||
card = do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, keygrip, 0);
|
||||
else
|
||||
card = ctrl->card_ctx;
|
||||
if (!card)
|
||||
{
|
||||
unlock_r_card_list ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lock_card (card, NULL);
|
||||
return card;
|
||||
}
|
||||
|
||||
/* Release the lock of CARD and the card-list. */
|
||||
void
|
||||
card_put (card_t card)
|
||||
{
|
||||
/* We don't deallocate CARD 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. */
|
||||
|
||||
lock_card (card, NULL);
|
||||
card_unref_locked (card);
|
||||
unlock_card (card);
|
||||
unlock_r_card_list ();
|
||||
}
|
||||
|
||||
|
||||
@ -1698,13 +1755,6 @@ app_write_learn_status (card_t card, ctrl_t ctrl, unsigned int flags)
|
||||
app_t app, last_app;
|
||||
int any_reselect = 0;
|
||||
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Always make sure that the current app for this connection has
|
||||
* been selected and is at the top of the list. */
|
||||
if ((err = maybe_switch_app (ctrl, card, NULL)))
|
||||
@ -1766,7 +1816,6 @@ app_write_learn_status (card_t card, ctrl_t ctrl, unsigned int flags)
|
||||
}
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1781,12 +1830,6 @@ app_readcert (card_t card, ctrl_t ctrl, const char *certid,
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((err = maybe_switch_app (ctrl, card, certid)))
|
||||
;
|
||||
else if (!card->app->fnc.readcert)
|
||||
@ -1802,7 +1845,6 @@ app_readcert (card_t card, ctrl_t ctrl, const char *certid,
|
||||
err = card->app->fnc.readcert (card->app, certid, cert, certlen);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1826,11 +1868,8 @@ app_readkey (card_t card, ctrl_t ctrl, const char *keyid, unsigned int flags,
|
||||
if (pklen)
|
||||
*pklen = 0;
|
||||
|
||||
if (!card || !keyid)
|
||||
if (!keyid)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((err = maybe_switch_app (ctrl, card, keyid)))
|
||||
;
|
||||
@ -1847,7 +1886,6 @@ app_readkey (card_t card, ctrl_t ctrl, const char *keyid, unsigned int flags,
|
||||
err = card->app->fnc.readkey (card->app, ctrl, keyid, flags, pk, pklen);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1858,11 +1896,8 @@ app_getattr (card_t card, ctrl_t ctrl, const char *name)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (!card || !name || !*name)
|
||||
if (!name || !*name)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((err = maybe_switch_app (ctrl, card, NULL)))
|
||||
;
|
||||
@ -1900,7 +1935,6 @@ app_getattr (card_t card, ctrl_t ctrl, const char *name)
|
||||
err = card->app->fnc.getattr (card->app, ctrl, name);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1914,11 +1948,8 @@ app_setattr (card_t card, ctrl_t ctrl, const char *name,
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (!card || !name || !*name || !value)
|
||||
if (!name || !*name || !value)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((err = maybe_switch_app (ctrl, card, NULL)))
|
||||
;
|
||||
@ -1936,7 +1967,6 @@ app_setattr (card_t card, ctrl_t ctrl, const char *name,
|
||||
value, valuelen);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1953,11 +1983,8 @@ app_sign (card_t card, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb)
|
||||
if (!indata || !indatalen || !outdata || !outdatalen || !pincb)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((err = maybe_switch_app (ctrl, card, keyidstr)))
|
||||
;
|
||||
@ -1977,7 +2004,6 @@ app_sign (card_t card, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
||||
outdata, outdatalen);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
if (opt.verbose)
|
||||
log_info ("operation sign result: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
@ -1997,11 +2023,8 @@ app_auth (card_t card, ctrl_t ctrl, const char *keyidstr,
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb)
|
||||
if (!indata || !indatalen || !outdata || !outdatalen || !pincb)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((err = maybe_switch_app (ctrl, card, keyidstr)))
|
||||
;
|
||||
@ -2021,7 +2044,6 @@ app_auth (card_t card, ctrl_t ctrl, const char *keyidstr,
|
||||
outdata, outdatalen);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
if (opt.verbose)
|
||||
log_info ("operation auth result: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
@ -2043,11 +2065,8 @@ app_decipher (card_t card, ctrl_t ctrl, const char *keyidstr,
|
||||
|
||||
*r_info = 0;
|
||||
|
||||
if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb)
|
||||
if (!indata || !indatalen || !outdata || !outdatalen || !pincb)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((err = maybe_switch_app (ctrl, card, keyidstr)))
|
||||
;
|
||||
@ -2068,7 +2087,6 @@ app_decipher (card_t card, ctrl_t ctrl, const char *keyidstr,
|
||||
r_info);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
if (opt.verbose)
|
||||
log_info ("operation decipher result: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
@ -2085,11 +2103,8 @@ app_writecert (card_t card, ctrl_t ctrl,
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (!card || !certidstr || !*certidstr || !pincb)
|
||||
if (!certidstr || !*certidstr || !pincb)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((err = maybe_switch_app (ctrl, card, certidstr)))
|
||||
;
|
||||
@ -2107,7 +2122,6 @@ app_writecert (card_t card, ctrl_t ctrl,
|
||||
pincb, pincb_arg, data, datalen);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
if (opt.verbose)
|
||||
log_info ("operation writecert result: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
@ -2124,11 +2138,8 @@ app_writekey (card_t card, ctrl_t ctrl,
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (!card || !keyidstr || !*keyidstr || !pincb)
|
||||
if (!keyidstr || !*keyidstr || !pincb)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((err = maybe_switch_app (ctrl, card, keyidstr)))
|
||||
;
|
||||
@ -2146,7 +2157,6 @@ app_writekey (card_t card, ctrl_t ctrl,
|
||||
pincb, pincb_arg, keydata, keydatalen);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
if (opt.verbose)
|
||||
log_info ("operation writekey result: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
@ -2162,11 +2172,8 @@ app_genkey (card_t card, ctrl_t ctrl, const char *keynostr,
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (!card || !keynostr || !*keynostr || !pincb)
|
||||
if (!keynostr || !*keynostr || !pincb)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((err = maybe_switch_app (ctrl, card, keynostr)))
|
||||
;
|
||||
@ -2184,7 +2191,6 @@ app_genkey (card_t card, ctrl_t ctrl, const char *keynostr,
|
||||
createtime, pincb, pincb_arg);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
if (opt.verbose)
|
||||
log_info ("operation genkey result: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
@ -2200,18 +2206,15 @@ app_get_challenge (card_t card, ctrl_t ctrl,
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (!card || !nbytes || !buffer)
|
||||
(void)ctrl;
|
||||
if (!nbytes || !buffer)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!card->ref_count)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||
else
|
||||
err = iso7816_get_challenge (card->slot, nbytes, buffer);
|
||||
|
||||
unlock_card (card);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -2225,11 +2228,8 @@ app_change_pin (card_t card, ctrl_t ctrl, const char *chvnostr,
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (!card || !chvnostr || !*chvnostr || !pincb)
|
||||
if (!chvnostr || !*chvnostr || !pincb)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((err = maybe_switch_app (ctrl, card, NULL)))
|
||||
;
|
||||
@ -2247,7 +2247,6 @@ app_change_pin (card_t card, ctrl_t ctrl, const char *chvnostr,
|
||||
chvnostr, flags, pincb, pincb_arg);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
if (opt.verbose)
|
||||
log_info ("operation change_pin result: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
@ -2264,11 +2263,8 @@ app_check_pin (card_t card, ctrl_t ctrl, const char *keyidstr,
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (!card || !keyidstr || !*keyidstr || !pincb)
|
||||
if (!keyidstr || !*keyidstr || !pincb)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((err = maybe_switch_app (ctrl, card, NULL)))
|
||||
;
|
||||
@ -2286,7 +2282,6 @@ app_check_pin (card_t card, ctrl_t ctrl, const char *keyidstr,
|
||||
pincb, pincb_arg);
|
||||
}
|
||||
|
||||
unlock_card (card);
|
||||
if (opt.verbose)
|
||||
log_info ("operation check_pin result: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
@ -2616,12 +2611,6 @@ app_switch_active_app (card_t card, ctrl_t ctrl, const char *appname)
|
||||
gpg_error_t err;
|
||||
apptype_t apptype;
|
||||
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
err = lock_card (card, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Note that in case the additional applications have not yet been
|
||||
* added to the card context (which is commonly done by means of
|
||||
* "SERIALNO --all", we do that here. */
|
||||
@ -2648,7 +2637,6 @@ app_switch_active_app (card_t card, ctrl_t ctrl, const char *appname)
|
||||
err = send_serialno_and_app_status (card, 1, ctrl);
|
||||
|
||||
leave:
|
||||
unlock_card (card);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -2682,69 +2670,12 @@ card_t
|
||||
app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str,
|
||||
int capability)
|
||||
{
|
||||
int locked = 0;
|
||||
card_t c;
|
||||
app_t a, a_prev;
|
||||
card_t card;
|
||||
|
||||
lock_r_card_list ();
|
||||
|
||||
for (c = card_top; c; c = c->next)
|
||||
{
|
||||
if (lock_card (c, ctrl))
|
||||
{
|
||||
c = NULL;
|
||||
goto leave_the_loop;
|
||||
}
|
||||
locked = 1;
|
||||
a_prev = NULL;
|
||||
for (a = c->app; a; a = a->next)
|
||||
{
|
||||
if (!a->fnc.with_keygrip || a->need_reset)
|
||||
continue;
|
||||
|
||||
/* Note that we need to do a re-select even for the current
|
||||
* app because the last selected application (e.g. after
|
||||
* init) might be a different one and we do not run
|
||||
* maybe_switch_app here. Of course we we do this only iff
|
||||
* we have an additional app. */
|
||||
if (c->app->next)
|
||||
{
|
||||
if (run_reselect (ctrl, c, a, a_prev))
|
||||
continue;
|
||||
}
|
||||
a_prev = a;
|
||||
|
||||
if (DBG_APP)
|
||||
log_debug ("slot %d, app %s: calling with_keygrip(%s)\n",
|
||||
c->slot, xstrapptype (a),
|
||||
action == KEYGRIP_ACTION_SEND_DATA? "send_data":
|
||||
action == KEYGRIP_ACTION_WRITE_STATUS? "status":
|
||||
action == KEYGRIP_ACTION_LOOKUP? "lookup":"?");
|
||||
if (!a->fnc.with_keygrip (a, ctrl, action, keygrip_str, capability))
|
||||
goto leave_the_loop; /* ACTION_LOOKUP succeeded. */
|
||||
}
|
||||
|
||||
/* Select the first app again. */
|
||||
if (c->app->next)
|
||||
run_reselect (ctrl, c, c->app, a_prev);
|
||||
|
||||
unlock_card (c);
|
||||
locked = 0;
|
||||
}
|
||||
|
||||
leave_the_loop:
|
||||
/* Force switching of the app if the selected one is not the current
|
||||
* one. Changing the current apptype is sufficient to do this. */
|
||||
if (c && c->app && c->app->apptype != a->apptype)
|
||||
ctrl->current_apptype = a->apptype;
|
||||
|
||||
if (locked && c)
|
||||
{
|
||||
unlock_card (c);
|
||||
locked = 0;
|
||||
}
|
||||
card = do_with_keygrip (ctrl, action, keygrip_str, capability);
|
||||
unlock_r_card_list ();
|
||||
return c;
|
||||
return card;
|
||||
}
|
||||
|
||||
void
|
||||
|
334
scd/command.c
334
scd/command.c
@ -154,18 +154,19 @@ hex_to_buffer (const char *string, size_t *r_length)
|
||||
static void
|
||||
do_reset (ctrl_t ctrl, int send_reset, int keep_lock)
|
||||
{
|
||||
card_t card = ctrl->card_ctx;
|
||||
card_t card = card_get (ctrl, NULL);
|
||||
|
||||
if (card)
|
||||
{
|
||||
if (!IS_LOCKED (ctrl) && send_reset)
|
||||
card_reset (card, ctrl);
|
||||
card_reset (card);
|
||||
else
|
||||
{
|
||||
ctrl->card_ctx = NULL;
|
||||
ctrl->current_apptype = APPTYPE_NONE;
|
||||
card_unref (card);
|
||||
card_unref_locked (card);
|
||||
}
|
||||
card_put (card);
|
||||
}
|
||||
|
||||
/* If we hold a lock, unlock now. */
|
||||
@ -238,14 +239,14 @@ open_card (ctrl_t ctrl)
|
||||
/* Explicitly open a card for a specific use of APPTYPE or SERIALNO.
|
||||
* If OPT_ALL is set also add all possible additional apps. */
|
||||
static gpg_error_t
|
||||
open_card_with_request (ctrl_t ctrl,
|
||||
open_card_with_request (card_t *card_p, ctrl_t ctrl,
|
||||
const char *apptypestr, const char *serialno,
|
||||
int opt_all)
|
||||
{
|
||||
gpg_error_t err;
|
||||
unsigned char *serialno_bin = NULL;
|
||||
size_t serialno_bin_len = 0;
|
||||
card_t card = ctrl->card_ctx;
|
||||
card_t card = card_get (ctrl, NULL);
|
||||
|
||||
if (serialno)
|
||||
serialno_bin = hex_to_buffer (serialno, &serialno_bin_len);
|
||||
@ -253,30 +254,45 @@ open_card_with_request (ctrl_t ctrl,
|
||||
/* If we are already initialized for one specific application we
|
||||
need to check that the client didn't requested a specific
|
||||
application different from the one in use before we continue. */
|
||||
if (apptypestr && ctrl->card_ctx)
|
||||
if (apptypestr && card)
|
||||
{
|
||||
err = check_application_conflict (ctrl->card_ctx, apptypestr,
|
||||
err = check_application_conflict (card, apptypestr,
|
||||
serialno_bin, serialno_bin_len);
|
||||
if (gpg_err_code (err) == GPG_ERR_FALSE)
|
||||
{
|
||||
/* Different application but switching is supported. */
|
||||
err = select_additional_application (ctrl, apptypestr);
|
||||
err = select_additional_application (card, ctrl, apptypestr);
|
||||
}
|
||||
if (err)
|
||||
card_put (card);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Re-scan USB devices. Release CARD, before the scan. */
|
||||
/* FIXME: Is a card_unref sufficient or do we need to deallocate? */
|
||||
ctrl->card_ctx = NULL;
|
||||
ctrl->current_apptype = APPTYPE_NONE;
|
||||
card_unref (card);
|
||||
if (card)
|
||||
{
|
||||
ctrl->card_ctx = NULL;
|
||||
ctrl->current_apptype = APPTYPE_NONE;
|
||||
card_unref_locked (card);
|
||||
card_put (card);
|
||||
}
|
||||
|
||||
err = select_application (ctrl, apptypestr, 1,
|
||||
serialno_bin, serialno_bin_len);
|
||||
card = card_get (ctrl, NULL);
|
||||
if (!err && opt_all)
|
||||
err = select_additional_application (ctrl, NULL);
|
||||
{
|
||||
if (card)
|
||||
{
|
||||
err = select_additional_application (card, ctrl, NULL);
|
||||
if (err)
|
||||
card_put (card);
|
||||
}
|
||||
}
|
||||
|
||||
leave:
|
||||
if (!err)
|
||||
*card_p = card;
|
||||
xfree (serialno_bin);
|
||||
return err;
|
||||
}
|
||||
@ -311,10 +327,11 @@ cmd_serialno (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
struct server_local_s *sl;
|
||||
int rc = 0;
|
||||
gpg_error_t err = 0;
|
||||
char *serial;
|
||||
const char *demand;
|
||||
int opt_all = has_option (line, "--all");
|
||||
card_t card = NULL;
|
||||
int thisslot;
|
||||
|
||||
if ( IS_LOCKED (ctrl) )
|
||||
@ -337,30 +354,31 @@ cmd_serialno (assuan_context_t ctx, char *line)
|
||||
|
||||
/* Clear the remove flag so that the open_card is able to reread it. */
|
||||
ctrl->server_local->card_removed = 0;
|
||||
rc = open_card_with_request (ctrl, *line? line:NULL, demand, opt_all);
|
||||
err = open_card_with_request (&card, ctrl, *line? line:NULL, demand, opt_all);
|
||||
/* Now clear or set the card_removed flag for all sessions using the
|
||||
* current slot. In the error case make sure that the flag is set
|
||||
* for the current session. */
|
||||
thisslot = ctrl->card_ctx? ctrl->card_ctx->slot : -1;
|
||||
thisslot = card? card->slot : -1;
|
||||
for (sl=session_list; sl; sl = sl->next_session)
|
||||
{
|
||||
ctrl_t c = sl->ctrl_backlink;
|
||||
if (c && c->card_ctx && c->card_ctx->slot == thisslot)
|
||||
c->server_local->card_removed = rc? 1 : 0;
|
||||
c->server_local->card_removed = err? 1 : 0;
|
||||
}
|
||||
if (rc)
|
||||
if (err)
|
||||
{
|
||||
ctrl->server_local->card_removed = 1;
|
||||
return rc;
|
||||
return err;
|
||||
}
|
||||
|
||||
serial = card_get_serialno (ctrl->card_ctx);
|
||||
serial = card_get_serialno (card);
|
||||
card_put (card);
|
||||
if (!serial)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
rc = assuan_write_status (ctx, "SERIALNO", serial);
|
||||
err = assuan_write_status (ctx, "SERIALNO", serial);
|
||||
xfree (serial);
|
||||
return rc;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@ -419,12 +437,22 @@ cmd_switchapp (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err = 0;
|
||||
card_t card;
|
||||
|
||||
if ((err = open_card (ctrl)))
|
||||
return err;
|
||||
|
||||
line = skip_options (line);
|
||||
return app_switch_active_app (ctrl->card_ctx, ctrl, line);
|
||||
card = card_get (ctrl, NULL);
|
||||
if (card)
|
||||
{
|
||||
err = app_switch_active_app (card, ctrl, line);
|
||||
card_put (card);
|
||||
}
|
||||
else
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@ -510,10 +538,15 @@ cmd_learn (assuan_context_t ctx, char *line)
|
||||
int opt_multi = has_option (line, "--multi");
|
||||
int opt_reread = has_option (line, "--reread");
|
||||
unsigned int flags;
|
||||
card_t card;
|
||||
|
||||
if ((rc = open_card (ctrl)))
|
||||
return rc;
|
||||
|
||||
card = card_get (ctrl, NULL);
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
|
||||
|
||||
/* Unless the force option is used we try a shortcut by identifying
|
||||
the card using a serial number and inquiring the client with
|
||||
that. The client may choose to cancel the operation if he already
|
||||
@ -522,25 +555,28 @@ cmd_learn (assuan_context_t ctx, char *line)
|
||||
{
|
||||
const char *reader;
|
||||
char *serial;
|
||||
card_t card = ctrl->card_ctx;
|
||||
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
|
||||
|
||||
reader = apdu_get_reader_name (card->slot);
|
||||
if (!reader)
|
||||
return out_of_core ();
|
||||
{
|
||||
card_put (card);
|
||||
return out_of_core ();
|
||||
}
|
||||
send_status_direct (ctrl, "READER", reader);
|
||||
/* No need to free the string of READER. */
|
||||
|
||||
serial = card_get_serialno (ctrl->card_ctx);
|
||||
serial = card_get_serialno (card);
|
||||
if (!serial)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
{
|
||||
card_put (card);
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
}
|
||||
|
||||
rc = assuan_write_status (ctx, "SERIALNO", serial);
|
||||
if (rc < 0)
|
||||
{
|
||||
xfree (serial);
|
||||
card_put (card);
|
||||
return out_of_core ();
|
||||
}
|
||||
|
||||
@ -552,6 +588,7 @@ cmd_learn (assuan_context_t ctx, char *line)
|
||||
if (rc < 0)
|
||||
{
|
||||
xfree (serial);
|
||||
card_put (card);
|
||||
return out_of_core ();
|
||||
}
|
||||
rc = assuan_inquire (ctx, command, NULL, NULL, 0);
|
||||
@ -562,6 +599,7 @@ cmd_learn (assuan_context_t ctx, char *line)
|
||||
log_error ("inquire KNOWNCARDP failed: %s\n",
|
||||
gpg_strerror (rc));
|
||||
xfree (serial);
|
||||
card_put (card);
|
||||
return rc;
|
||||
}
|
||||
/* Not canceled, so we have to proceed. */
|
||||
@ -580,8 +618,9 @@ cmd_learn (assuan_context_t ctx, char *line)
|
||||
flags |= APP_LEARN_FLAG_REREAD;
|
||||
|
||||
if (!rc)
|
||||
rc = app_write_learn_status (ctrl->card_ctx, ctrl, flags);
|
||||
rc = app_write_learn_status (card, ctrl, flags);
|
||||
|
||||
card_put (card);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -598,6 +637,7 @@ cmd_readcert (assuan_context_t ctx, char *line)
|
||||
int rc;
|
||||
unsigned char *cert;
|
||||
size_t ncert;
|
||||
card_t card;
|
||||
|
||||
if ((rc = open_card (ctrl)))
|
||||
return rc;
|
||||
@ -606,9 +646,17 @@ cmd_readcert (assuan_context_t ctx, char *line)
|
||||
if (!line)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
rc = app_readcert (ctrl->card_ctx, ctrl, line, &cert, &ncert);
|
||||
card = card_get (ctrl, NULL);
|
||||
if (!card)
|
||||
{
|
||||
xfree (line);
|
||||
return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
|
||||
}
|
||||
|
||||
rc = app_readcert (card, ctrl, line, &cert, &ncert);
|
||||
if (rc)
|
||||
log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
|
||||
card_put (card);
|
||||
xfree (line);
|
||||
line = NULL;
|
||||
if (!rc)
|
||||
@ -708,7 +756,7 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
||||
unsigned char *pk = NULL;
|
||||
size_t pklen;
|
||||
card_t card;
|
||||
int direct = 0;
|
||||
const char *keygrip = NULL;
|
||||
|
||||
if ((rc = open_card (ctrl)))
|
||||
return rc;
|
||||
@ -727,22 +775,13 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
if (strlen (line) == 40)
|
||||
{
|
||||
card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, line, 0);
|
||||
direct = 1;
|
||||
}
|
||||
else
|
||||
card = ctrl->card_ctx;
|
||||
keygrip = line;
|
||||
|
||||
card = card_get (ctrl, keygrip);
|
||||
if (card)
|
||||
{
|
||||
if (direct)
|
||||
card_ref (card);
|
||||
|
||||
rc = do_readkey (card, ctrl, line, opt_info, &pk, &pklen);
|
||||
|
||||
if (direct)
|
||||
card_unref (card);
|
||||
card_put (card);
|
||||
}
|
||||
else
|
||||
rc = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
@ -923,7 +962,7 @@ cmd_pksign (assuan_context_t ctx, char *line)
|
||||
char *keyidstr;
|
||||
int hash_algo;
|
||||
card_t card;
|
||||
int direct = 0;
|
||||
const char *keygrip = NULL;
|
||||
|
||||
if (has_option (line, "--hash=rmd160"))
|
||||
hash_algo = GCRY_MD_RMD160;
|
||||
@ -961,24 +1000,17 @@ cmd_pksign (assuan_context_t ctx, char *line)
|
||||
/* When it's a keygrip, we directly use the card, with no change of
|
||||
ctrl->card_ctx. */
|
||||
if (strlen (keyidstr) == 40)
|
||||
{
|
||||
card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, keyidstr, 0);
|
||||
direct = 1;
|
||||
}
|
||||
else
|
||||
card = ctrl->card_ctx;
|
||||
keygrip = keyidstr;
|
||||
|
||||
card = card_get (ctrl, keygrip);
|
||||
if (card)
|
||||
{
|
||||
if (direct)
|
||||
card_ref (card);
|
||||
rc = app_sign (card, ctrl,
|
||||
keyidstr, hash_algo,
|
||||
pin_cb, ctx,
|
||||
ctrl->in_data.value, ctrl->in_data.valuelen,
|
||||
&outdata, &outdatalen);
|
||||
if (direct)
|
||||
card_unref (card);
|
||||
card_put (card);
|
||||
}
|
||||
else
|
||||
rc = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
@ -1011,14 +1043,11 @@ cmd_pkauth (assuan_context_t ctx, char *line)
|
||||
size_t outdatalen;
|
||||
char *keyidstr;
|
||||
card_t card;
|
||||
int direct = 0;
|
||||
const char *keygrip = NULL;
|
||||
|
||||
if ((rc = open_card (ctrl)))
|
||||
return rc;
|
||||
|
||||
if (!ctrl->card_ctx)
|
||||
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
|
||||
/* We have to use a copy of the key ID because the function may use
|
||||
the pin_cb which in turn uses the assuan line buffer and thus
|
||||
overwriting the original line with the keyid */
|
||||
@ -1029,25 +1058,18 @@ cmd_pkauth (assuan_context_t ctx, char *line)
|
||||
/* When it's a keygrip, we directly use CARD, with no change of
|
||||
ctrl->card_ctx. */
|
||||
if (strlen (keyidstr) == 40)
|
||||
{
|
||||
card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, keyidstr, 0);
|
||||
direct = 1;
|
||||
}
|
||||
else
|
||||
card = ctrl->card_ctx;
|
||||
keygrip = keyidstr;
|
||||
|
||||
card = card_get (ctrl, keygrip);
|
||||
if (card)
|
||||
{
|
||||
if (direct)
|
||||
card_ref (card);
|
||||
rc = app_auth (card, ctrl, keyidstr, pin_cb, ctx,
|
||||
ctrl->in_data.value, ctrl->in_data.valuelen,
|
||||
&outdata, &outdatalen);
|
||||
if (direct)
|
||||
card_unref (card);
|
||||
card_put (card);
|
||||
}
|
||||
else
|
||||
rc = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
rc = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
|
||||
xfree (keyidstr);
|
||||
if (rc)
|
||||
@ -1078,7 +1100,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
|
||||
char *keyidstr;
|
||||
unsigned int infoflags;
|
||||
card_t card;
|
||||
int direct = 0;
|
||||
const char *keygrip = NULL;
|
||||
|
||||
if ((rc = open_card (ctrl)))
|
||||
return rc;
|
||||
@ -1090,22 +1112,15 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
|
||||
/* When it's a keygrip, we directly use CARD, with no change of
|
||||
ctrl->card_ctx. */
|
||||
if (strlen (keyidstr) == 40)
|
||||
{
|
||||
card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, keyidstr, 0);
|
||||
direct = 1;
|
||||
}
|
||||
else
|
||||
card = ctrl->card_ctx;
|
||||
keygrip = keyidstr;
|
||||
|
||||
card = card_get (ctrl, keygrip);
|
||||
if (card)
|
||||
{
|
||||
if (direct)
|
||||
card_ref (card);
|
||||
rc = app_decipher (card, ctrl, keyidstr, pin_cb, ctx,
|
||||
ctrl->in_data.value, ctrl->in_data.valuelen,
|
||||
&outdata, &outdatalen, &infoflags);
|
||||
if (direct)
|
||||
card_unref (card);
|
||||
card_put (card);
|
||||
}
|
||||
else
|
||||
rc = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
@ -1154,7 +1169,7 @@ cmd_getattr (assuan_context_t ctx, char *line)
|
||||
int rc;
|
||||
const char *keyword;
|
||||
card_t card;
|
||||
int direct = 0;
|
||||
const char *keygrip = NULL;
|
||||
|
||||
if ((rc = open_card (ctrl)))
|
||||
return rc;
|
||||
@ -1166,24 +1181,15 @@ cmd_getattr (assuan_context_t ctx, char *line)
|
||||
*line++ = 0;
|
||||
|
||||
if (strlen (line) == 40)
|
||||
{
|
||||
card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, line, 0);
|
||||
direct = 1;
|
||||
}
|
||||
else
|
||||
card = ctrl->card_ctx;
|
||||
keygrip = line;
|
||||
|
||||
card = card_get (ctrl, keygrip);
|
||||
if (card)
|
||||
{
|
||||
if (direct)
|
||||
card_ref (card);
|
||||
|
||||
/* FIXME: Applications should not return sensitive data if the card
|
||||
is locked. */
|
||||
rc = app_getattr (card, ctrl, keyword);
|
||||
|
||||
if (direct)
|
||||
card_unref (card);
|
||||
card_put (card);
|
||||
}
|
||||
else
|
||||
rc = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
@ -1219,6 +1225,7 @@ cmd_setattr (assuan_context_t ctx, char *orig_line)
|
||||
size_t nbytes;
|
||||
char *line, *linebuf;
|
||||
int opt_inquire;
|
||||
card_t card;
|
||||
|
||||
opt_inquire = has_option (orig_line, "--inquire");
|
||||
orig_line = skip_options (orig_line);
|
||||
@ -1232,6 +1239,13 @@ cmd_setattr (assuan_context_t ctx, char *orig_line)
|
||||
if (!line)
|
||||
return out_of_core ();
|
||||
|
||||
card = card_get (ctrl, NULL);
|
||||
if (!card)
|
||||
{
|
||||
xfree (linebuf);
|
||||
return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
|
||||
}
|
||||
|
||||
keyword = line;
|
||||
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
|
||||
;
|
||||
@ -1248,7 +1262,7 @@ cmd_setattr (assuan_context_t ctx, char *orig_line)
|
||||
assuan_end_confidential (ctx);
|
||||
if (!err)
|
||||
{
|
||||
err = app_setattr (ctrl->card_ctx, ctrl, keyword, pin_cb, ctx,
|
||||
err = app_setattr (card, ctrl, keyword, pin_cb, ctx,
|
||||
value, nbytes);
|
||||
wipememory (value, nbytes);
|
||||
xfree (value);
|
||||
@ -1258,10 +1272,11 @@ cmd_setattr (assuan_context_t ctx, char *orig_line)
|
||||
else
|
||||
{
|
||||
nbytes = percent_plus_unescape_inplace (line, 0);
|
||||
err = app_setattr (ctrl->card_ctx, ctrl, keyword, pin_cb, ctx,
|
||||
err = app_setattr (card, ctrl, keyword, pin_cb, ctx,
|
||||
(const unsigned char*)line, nbytes);
|
||||
}
|
||||
|
||||
card_put (card);
|
||||
xfree (linebuf);
|
||||
return err;
|
||||
}
|
||||
@ -1286,6 +1301,7 @@ cmd_writecert (assuan_context_t ctx, char *line)
|
||||
char *certid;
|
||||
unsigned char *certdata;
|
||||
size_t certdatalen;
|
||||
card_t card;
|
||||
|
||||
line = skip_options (line);
|
||||
|
||||
@ -1299,25 +1315,31 @@ cmd_writecert (assuan_context_t ctx, char *line)
|
||||
if ((rc = open_card (ctrl)))
|
||||
return rc;
|
||||
|
||||
if (!ctrl->card_ctx)
|
||||
card = card_get (ctrl, NULL);
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
|
||||
certid = xtrystrdup (certid);
|
||||
if (!certid)
|
||||
return out_of_core ();
|
||||
{
|
||||
card_put (card);
|
||||
return out_of_core ();
|
||||
}
|
||||
|
||||
/* Now get the actual keydata. */
|
||||
rc = assuan_inquire (ctx, "CERTDATA",
|
||||
&certdata, &certdatalen, MAXLEN_CERTDATA);
|
||||
if (rc)
|
||||
{
|
||||
card_put (card);
|
||||
xfree (certid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Write the certificate to the card. */
|
||||
rc = app_writecert (ctrl->card_ctx, ctrl, certid,
|
||||
rc = app_writecert (card, ctrl, certid,
|
||||
pin_cb, ctx, certdata, certdatalen);
|
||||
card_put (card);
|
||||
xfree (certid);
|
||||
xfree (certdata);
|
||||
|
||||
@ -1348,6 +1370,7 @@ cmd_writekey (assuan_context_t ctx, char *line)
|
||||
int force = has_option (line, "--force");
|
||||
unsigned char *keydata;
|
||||
size_t keydatalen;
|
||||
card_t card;
|
||||
|
||||
line = skip_options (line);
|
||||
|
||||
@ -1361,12 +1384,16 @@ cmd_writekey (assuan_context_t ctx, char *line)
|
||||
if ((rc = open_card (ctrl)))
|
||||
return rc;
|
||||
|
||||
if (!ctrl->card_ctx)
|
||||
card = card_get (ctrl, NULL);
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
|
||||
keyid = xtrystrdup (keyid);
|
||||
if (!keyid)
|
||||
return out_of_core ();
|
||||
{
|
||||
card_put (card);
|
||||
return out_of_core ();
|
||||
}
|
||||
|
||||
/* Now get the actual keydata. */
|
||||
assuan_begin_confidential (ctx);
|
||||
@ -1379,8 +1406,9 @@ cmd_writekey (assuan_context_t ctx, char *line)
|
||||
}
|
||||
|
||||
/* Write the key to the card. */
|
||||
rc = app_writekey (ctrl->card_ctx, ctrl, keyid, force? 1:0,
|
||||
rc = app_writekey (card, ctrl, keyid, force? 1:0,
|
||||
pin_cb, ctx, keydata, keydatalen);
|
||||
card_put (card);
|
||||
xfree (keyid);
|
||||
xfree (keydata);
|
||||
|
||||
@ -1427,6 +1455,7 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
||||
const char *s;
|
||||
char *opt_algo = NULL;
|
||||
time_t timestamp;
|
||||
card_t card;
|
||||
|
||||
force = has_option (line, "--force");
|
||||
|
||||
@ -1459,7 +1488,8 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
||||
if ((err = open_card (ctrl)))
|
||||
goto leave;
|
||||
|
||||
if (!ctrl->card_ctx)
|
||||
card = card_get (ctrl, NULL);
|
||||
if (!card)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
goto leave;
|
||||
@ -1469,11 +1499,13 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
||||
if (!keyref)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
card_put (card);
|
||||
goto leave;
|
||||
}
|
||||
err = app_genkey (ctrl->card_ctx, ctrl, keyref, opt_algo,
|
||||
err = app_genkey (card, ctrl, keyref, opt_algo,
|
||||
force? APP_GENKEY_FLAG_FORCE : 0,
|
||||
timestamp, pin_cb, ctx);
|
||||
card_put (card);
|
||||
|
||||
leave:
|
||||
xfree (keyref_buffer);
|
||||
@ -1497,6 +1529,7 @@ cmd_random (assuan_context_t ctx, char *line)
|
||||
int rc;
|
||||
size_t nbytes;
|
||||
unsigned char *buffer;
|
||||
card_t card;
|
||||
|
||||
if (!*line)
|
||||
return set_error (GPG_ERR_ASS_PARAMETER,
|
||||
@ -1506,14 +1539,19 @@ cmd_random (assuan_context_t ctx, char *line)
|
||||
if ((rc = open_card (ctrl)))
|
||||
return rc;
|
||||
|
||||
if (!ctrl->card_ctx)
|
||||
card = card_get (ctrl, NULL);
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
|
||||
buffer = xtrymalloc (nbytes);
|
||||
if (!buffer)
|
||||
return out_of_core ();
|
||||
{
|
||||
card_put (card);
|
||||
return out_of_core ();
|
||||
}
|
||||
|
||||
rc = app_get_challenge (ctrl->card_ctx, ctrl, nbytes, buffer);
|
||||
rc = app_get_challenge (card, ctrl, nbytes, buffer);
|
||||
card_put (card);
|
||||
if (!rc)
|
||||
{
|
||||
rc = assuan_send_data (ctx, buffer, nbytes);
|
||||
@ -1542,6 +1580,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
|
||||
int rc;
|
||||
char *chvnostr;
|
||||
unsigned int flags = 0;
|
||||
card_t card;
|
||||
|
||||
if (has_option (line, "--reset"))
|
||||
flags |= APP_CHANGE_FLAG_RESET;
|
||||
@ -1567,13 +1606,18 @@ cmd_passwd (assuan_context_t ctx, char *line)
|
||||
if ((rc = open_card (ctrl)))
|
||||
return rc;
|
||||
|
||||
if (!ctrl->card_ctx)
|
||||
card = card_get (ctrl, NULL);
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
|
||||
chvnostr = xtrystrdup (chvnostr);
|
||||
if (!chvnostr)
|
||||
return out_of_core ();
|
||||
rc = app_change_pin (ctrl->card_ctx, ctrl, chvnostr, flags, pin_cb, ctx);
|
||||
{
|
||||
card_put (card);
|
||||
return out_of_core ();
|
||||
}
|
||||
rc = app_change_pin (card, ctrl, chvnostr, flags, pin_cb, ctx);
|
||||
card_put (card);
|
||||
if (rc)
|
||||
log_error ("command passwd failed: %s\n", gpg_strerror (rc));
|
||||
xfree (chvnostr);
|
||||
@ -1622,13 +1666,15 @@ static gpg_error_t
|
||||
cmd_checkpin (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
gpg_error_t err;
|
||||
char *idstr;
|
||||
card_t card;
|
||||
|
||||
if ((rc = open_card (ctrl)))
|
||||
return rc;
|
||||
if ((err = open_card (ctrl)))
|
||||
return err;
|
||||
|
||||
if (!ctrl->card_ctx)
|
||||
card = card_get (ctrl, NULL);
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
|
||||
/* We have to use a copy of the key ID because the function may use
|
||||
@ -1636,14 +1682,18 @@ cmd_checkpin (assuan_context_t ctx, char *line)
|
||||
overwriting the original line with the keyid. */
|
||||
idstr = xtrystrdup (line);
|
||||
if (!idstr)
|
||||
return out_of_core ();
|
||||
{
|
||||
card_put (card);
|
||||
return out_of_core ();
|
||||
}
|
||||
|
||||
rc = app_check_pin (ctrl->card_ctx, ctrl, idstr, pin_cb, ctx);
|
||||
err = app_check_pin (card, ctrl, idstr, pin_cb, ctx);
|
||||
card_put (card);
|
||||
xfree (idstr);
|
||||
if (rc)
|
||||
log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
|
||||
if (err)
|
||||
log_error ("app_check_pin failed: %s\n", gpg_strerror (err));
|
||||
|
||||
return rc;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@ -1863,10 +1913,15 @@ cmd_getinfo (assuan_context_t ctx, char *line)
|
||||
else if (!strcmp (line, "active_apps"))
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
if (!ctrl->card_ctx)
|
||||
card_t card = card_get (ctrl, NULL);
|
||||
|
||||
if (!card)
|
||||
rc = 0; /* No current card - no active apps. */
|
||||
else
|
||||
rc = app_send_active_apps (ctrl->card_ctx, ctrl);
|
||||
{
|
||||
rc = app_send_active_apps (card, ctrl);
|
||||
card_put (card);
|
||||
}
|
||||
}
|
||||
else if (!strcmp (line, "all_active_apps"))
|
||||
{
|
||||
@ -1899,7 +1954,7 @@ static gpg_error_t
|
||||
cmd_restart (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
card_t card = ctrl->card_ctx;
|
||||
card_t card = card_get (ctrl, NULL);
|
||||
|
||||
(void)line;
|
||||
|
||||
@ -1907,7 +1962,8 @@ cmd_restart (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl->card_ctx = NULL;
|
||||
ctrl->current_apptype = APPTYPE_NONE;
|
||||
card_unref (card);
|
||||
card_unref_locked (card);
|
||||
card_put (card);
|
||||
}
|
||||
if (locked_session && ctrl->server_local == locked_session)
|
||||
{
|
||||
@ -1926,14 +1982,19 @@ static gpg_error_t
|
||||
cmd_disconnect (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
card_t card;
|
||||
|
||||
(void)line;
|
||||
|
||||
if (!ctrl->card_ctx)
|
||||
card = card_get (ctrl, NULL);
|
||||
if (card)
|
||||
{
|
||||
apdu_disconnect (card->slot);
|
||||
card_put (card);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
|
||||
apdu_disconnect (ctrl->card_ctx->slot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1993,7 +2054,7 @@ cmd_apdu (assuan_context_t ctx, char *line)
|
||||
if ((rc = open_card (ctrl)))
|
||||
return rc;
|
||||
|
||||
card = ctrl->card_ctx;
|
||||
card = card_get (ctrl, NULL);
|
||||
if (!card)
|
||||
return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
|
||||
|
||||
@ -2074,6 +2135,7 @@ cmd_apdu (assuan_context_t ctx, char *line)
|
||||
xfree (apdu);
|
||||
|
||||
leave:
|
||||
card_put (card);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -2208,6 +2270,7 @@ cmd_devinfo (assuan_context_t ctx, char *line)
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err = 0;
|
||||
int watch = 0;
|
||||
card_t card;
|
||||
|
||||
if (has_option (line, "--watch"))
|
||||
{
|
||||
@ -2237,10 +2300,15 @@ cmd_devinfo (assuan_context_t ctx, char *line)
|
||||
|
||||
err = 0;
|
||||
|
||||
/* Remove reference(s) to the card. */
|
||||
ctrl->card_ctx = NULL;
|
||||
ctrl->current_apptype = APPTYPE_NONE;
|
||||
card_unref (ctrl->card_ctx);
|
||||
card = card_get (ctrl, NULL);
|
||||
if (card)
|
||||
{
|
||||
/* If any, remove reference to the card in CTRL. */
|
||||
ctrl->card_ctx = NULL;
|
||||
ctrl->current_apptype = APPTYPE_NONE;
|
||||
card_unref_locked (card);
|
||||
card_put (card);
|
||||
}
|
||||
|
||||
/* Then, keep watching the status change. */
|
||||
while (!err)
|
||||
|
Loading…
x
Reference in New Issue
Block a user