aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--agent/call-scd.c2
-rw-r--r--scd/app-piv.c4
-rw-r--r--scd/app.c139
-rw-r--r--scd/command.c2
-rw-r--r--tools/card-call-scd.c4
5 files changed, 94 insertions, 57 deletions
diff --git a/agent/call-scd.c b/agent/call-scd.c
index b4a2974b4..39726c423 100644
--- a/agent/call-scd.c
+++ b/agent/call-scd.c
@@ -854,7 +854,7 @@ agent_card_serialno (ctrl_t ctrl, char **r_serialno, const char *demand)
return rc;
if (!demand)
- strcpy (line, "SERIALNO");
+ strcpy (line, "SERIALNO --all");
else
snprintf (line, DIM(line), "SERIALNO --demand=%s", demand);
diff --git a/scd/app-piv.c b/scd/app-piv.c
index be61d562d..d74cf9239 100644
--- a/scd/app-piv.c
+++ b/scd/app-piv.c
@@ -764,13 +764,13 @@ get_dispserialno (app_t app, int failmode)
/* The verify command can be used to retrieve the security status of
- * the card. Given the PIN name (e.g. "PIV.80" for thge application
+ * the card. Given the PIN name (e.g. "PIV.80" for the application
* pin, a status is returned:
*
* -1 = Error retrieving the data,
* -2 = No such PIN,
* -3 = PIN blocked,
- * -5 = Verify still valid,
+ * -5 = Verified and still valid,
* n >= 0 = Number of verification attempts left.
*/
static int
diff --git a/scd/app.c b/scd/app.c
index 3b71f54dc..86c153676 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -300,7 +300,7 @@ is_app_allowed (const char *name)
* to switch to the requested application.
* Other code - Switching is not possible.
*
- * If SERIALNO_BIN is not NULL a coflict is onl asserted if the
+ * If SERIALNO_BIN is not NULL a conflict is only asserted if the
* serialno of the card matches.
*/
gpg_error_t
@@ -1032,7 +1032,7 @@ card_unref_locked (card_t card)
FF 02 00 = Serial number from Yubikey config
FF 7F 00 = No serialno.
- All other serial number not starting with FF are used as they are.
+ All other serial numbers not starting with FF are used as they are.
*/
gpg_error_t
app_munge_serialno (card_t card)
@@ -1094,6 +1094,46 @@ app_get_serialno (app_t app)
}
+/* Helper to run the reselect function. */
+static gpg_error_t
+run_reselect (ctrl_t ctrl, card_t c, app_t a, app_t a_prev)
+{
+ gpg_error_t err;
+
+ if (!a->fnc.reselect)
+ {
+ log_info ("slot %d, app %s: re-select not implemented\n",
+ c->slot, xstrapptype (a));
+ return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
+ }
+
+ /* Give the current app a chance to save some state before another
+ * app is selected. We ignore errors here because that state saving
+ * (e.g. putting PINs into a cache) is a convenience feature and not
+ * required to always work. */
+ if (a_prev && a_prev->fnc.prep_reselect)
+ {
+ err = a_prev->fnc.prep_reselect (a_prev, ctrl);
+ if (err)
+ log_error ("slot %d, app %s: preparing re-select from %s failed: %s\n",
+ c->slot, xstrapptype (a),
+ xstrapptype (a_prev), gpg_strerror (err));
+ }
+
+ err = a->fnc.reselect (a, ctrl);
+ if (err)
+ {
+ log_error ("slot %d, app %s: error re-selecting: %s\n",
+ c->slot, xstrapptype (a), gpg_strerror (err));
+ return err;
+ }
+ if (DBG_APP)
+ log_debug ("slot %d, app %s: re-selected\n", c->slot, xstrapptype (a));
+
+ return 0;
+}
+
+
/* Check that the card has been initialized and whether we need to
* switch to another application on the same card. Switching means
* that the new active app will be moved to the head of the list at
@@ -1162,33 +1202,9 @@ maybe_switch_app (ctrl_t ctrl, card_t card, const char *keyref)
if (!app)
return gpg_error (GPG_ERR_WRONG_CARD);
- if (!app->fnc.reselect)
- {
- log_error ("oops: reselect function missing for '%s'\n",
- strapptype (app->apptype));
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- }
-
- /* Give the current app a chance to save some state before another
- * app is selected. We ignore errors here because that state saving
- * (e.g. putting PINs into a cache) is a convenience feature and not
- * required to always work. */
- if (app_prev && app_prev->fnc.prep_reselect)
- {
- err = app_prev->fnc.prep_reselect (app_prev, ctrl);
- if (err)
- log_info ("card %d: preparing re-select failed for '%s': %s\n",
- card->slot, xstrapptype (app_prev), gpg_strerror (err));
- err = 0;
- }
-
- err = app->fnc.reselect (app, ctrl);
+ err = run_reselect (ctrl, card, app, app_prev);
if (err)
- {
- log_error ("card %d: error re-selecting '%s': %s\n",
- card->slot, xstrapptype (app), gpg_strerror (err));
- return err;
- }
+ return err;
/* Swap APP with the head of the app list if needed. Note that APP
* is not the head of the list. */
@@ -1200,9 +1216,9 @@ maybe_switch_app (ctrl_t ctrl, card_t card, const char *keyref)
}
if (opt.verbose)
- log_info ("card %d: %s '%s'\n",
- card->slot, app_prev? "switched to":"re-selected",
- xstrapptype (app));
+ log_info ("slot %d, app %s: %s\n",
+ card->slot, xstrapptype (app),
+ app_prev? "switched":"re-selected");
ctrl->current_apptype = app->apptype;
@@ -1271,8 +1287,10 @@ app_write_learn_status (card_t card, ctrl_t ctrl, unsigned int flags)
{
tmperr = last_app->fnc.prep_reselect (last_app, ctrl);
if (tmperr)
- log_info ("card %d: preparing re-select failed for '%s'"
- ": %s\n", card->slot, xstrapptype (last_app),
+ log_info ("slot %d, app %s:"
+ " preparing re-select from %s failed: %s\n",
+ card->slot, xstrapptype (app),
+ xstrapptype (last_app),
gpg_strerror (tmperr));
}
any_reselect = 1;
@@ -1290,9 +1308,10 @@ app_write_learn_status (card_t card, ctrl_t ctrl, unsigned int flags)
{
tmperr = last_app->fnc.prep_reselect (last_app, ctrl);
if (tmperr)
- log_info ("card %d: preparing re-select failed for '%s'"
- ": %s\n", card->slot, xstrapptype (last_app),
- gpg_strerror (tmperr));
+ log_info ("slot %d, app %s:"
+ " preparing re-select from %s failed: %s\n",
+ card->slot, xstrapptype (app),
+ xstrapptype (last_app), gpg_strerror (tmperr));
}
err2 = app->fnc.reselect (app, ctrl);
if (err2)
@@ -2027,8 +2046,9 @@ app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str,
int capability)
{
int locked = 0;
+ gpg_error_t err;
card_t c;
- app_t a;
+ app_t a, a_prev;
npth_mutex_lock (&card_list_lock);
@@ -2040,26 +2060,43 @@ app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str,
goto leave_the_loop;
}
locked = 1;
+ a_prev = NULL;
for (a = c->app; a; a = a->next)
- if (a->fnc.with_keygrip)
- {
- if (DBG_APP)
- log_debug ("slot %d app %s: calling with_keygrip(action=%d)\n",
- c->slot, xstrapptype (a), action);
- if (!a->fnc.with_keygrip (a, ctrl, action, keygrip_str, capability))
- goto leave_the_loop;
- }
+ {
+ if (!a->fnc.with_keygrip)
+ 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? "write_data":
+ 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:
-
- /* FIXME: Add app switching logic. The above code assumes that the
- * actions can be performend without switching. This needs to be
- * checked. */
-
/* 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)
diff --git a/scd/command.c b/scd/command.c
index 9c58484c4..08e790992 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -282,7 +282,7 @@ static const char hlp_serialno[] =
"selected and an error is returned if no such card available.\n"
"\n"
"If --all is given, all possible other applications of the card are\n"
- "also selected to prepare for \"LEARN --force --multi\".\n"
+ "also selected to prepare for things like \"LEARN --force --multi\".\n"
"\n"
"If APPTYPE is given, an application of that type is selected and an\n"
"error is returned if the application is not supported or available.\n"
diff --git a/tools/card-call-scd.c b/tools/card-call-scd.c
index c2580bf5c..e4fa6abd3 100644
--- a/tools/card-call-scd.c
+++ b/tools/card-call-scd.c
@@ -360,7 +360,7 @@ start_agent (unsigned int flags)
err = warn_version_mismatch (agent_ctx, SCDAEMON_NAME, 2);
if (!err)
- err = assuan_transact (agent_ctx, "SCD SERIALNO",
+ err = assuan_transact (agent_ctx, "SCD SERIALNO --all",
NULL, NULL, NULL, NULL,
learn_status_cb, &info);
if (err && !(flags & START_AGENT_SUPPRESS_ERRORS))
@@ -1284,7 +1284,7 @@ scd_serialno (char **r_serialno, const char *demand)
return err;
if (!demand)
- strcpy (line, "SCD SERIALNO");
+ strcpy (line, "SCD SERIALNO --all");
else
snprintf (line, DIM(line), "SCD SERIALNO --demand=%s", demand);