aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scd/app.c98
-rw-r--r--scd/command.c18
2 files changed, 105 insertions, 11 deletions
diff --git a/scd/app.c b/scd/app.c
index e5ec59252..74a188f49 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -753,6 +753,78 @@ select_additional_application_internal (card_t card, apptype_t req_apptype)
return err;
}
+
+/* Add all possible additional applications to the card context but do
+ * not change the current one. This current works only for Yubikeys. */
+static gpg_error_t
+select_all_additional_applications_internal (card_t card)
+{
+ gpg_error_t err = 0;
+ apptype_t candidates[3];
+ int i, j;
+
+ if (card->cardtype == CARDTYPE_YUBIKEY)
+ {
+ candidates[0] = APPTYPE_OPENPGP;
+ candidates[1] = APPTYPE_PIV;
+ candidates[2] = APPTYPE_NONE;
+ }
+ else
+ {
+ candidates[0] = APPTYPE_NONE;
+ }
+
+ /* Find the app and run the select. */
+ for (i=0; app_priority_list[i].apptype; i++)
+ {
+ app_t app, app_r, app_prev;
+
+ for (j=0; candidates[j]; j++)
+ if (candidates[j] == app_priority_list[i].apptype
+ && is_app_allowed (app_priority_list[i].name))
+ break;
+ if (!candidates[j])
+ continue;
+
+ for (app = card->app; app; app = app->next)
+ if (app->apptype == candidates[j])
+ break;
+ if (app)
+ continue; /* Already on the list of apps. */
+
+ app = xtrycalloc (1, sizeof *app);
+ if (!app)
+ {
+ err = gpg_error_from_syserror ();
+ log_info ("error allocating app context: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+ app->card = card;
+ err = app_priority_list[i].select_func (app);
+ if (err)
+ {
+ log_error ("error selecting additional app '%s': %s - skipped\n",
+ strapptype (candidates[j]), gpg_strerror (err));
+ err = 0;
+ xfree (app);
+ }
+ else
+ {
+ /* Append to the list of apps. */
+ app_prev = card->app;
+ for (app_r=app_prev->next; app_r; app_prev=app_r, app_r=app_r->next)
+ ;
+ app_prev->next = app;
+ log_info ("added app '%s' to the card context\n",
+ strapptype (app->apptype));
+ }
+ }
+
+ leave:
+ return err;
+}
+
+
/* This function needs to be called with the NAME of the new
* application to be selected on CARD. On success the application is
* added to the list of the card's active applications as currently
@@ -765,9 +837,14 @@ select_additional_application (ctrl_t ctrl, const char *name)
apptype_t req_apptype;
card_t card;
- req_apptype = apptype_from_name (name);
- if (!req_apptype)
- return gpg_error (GPG_ERR_NOT_FOUND);
+ if (!name)
+ req_apptype = 0;
+ else
+ {
+ req_apptype = apptype_from_name (name);
+ if (!req_apptype)
+ return gpg_error (GPG_ERR_NOT_FOUND);
+ }
card = ctrl->card_ctx;
if (!card)
@@ -777,11 +854,18 @@ select_additional_application (ctrl_t ctrl, const char *name)
if (err)
return err;
- err = select_additional_application_internal (card, req_apptype);
- if (!err)
+ if (req_apptype)
+ {
+ err = select_additional_application_internal (card, req_apptype);
+ if (!err)
+ {
+ ctrl->current_apptype = req_apptype;
+ log_debug ("current_apptype is set to %s\n", name);
+ }
+ }
+ else
{
- ctrl->current_apptype = req_apptype;
- log_debug ("current_apptype is set to %s\n", name);
+ err = select_all_additional_applications_internal (card);
}
unlock_card (card);
diff --git a/scd/command.c b/scd/command.c
index b37b29c3f..9d750e3fe 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -218,10 +218,12 @@ open_card (ctrl_t ctrl)
return select_application (ctrl, NULL, &ctrl->card_ctx, 0, NULL, 0);
}
-/* Explicitly open a card for a specific use of APPTYPE or SERIALNO. */
+/* Explicitly open a card for a specific use of APPTYPE or SERIALNO.
+ * If OPT_ALL ist set also add all possible additional apps. */
static gpg_error_t
open_card_with_request (ctrl_t ctrl,
- const char *apptypestr, const char *serialno)
+ const char *apptypestr, const char *serialno,
+ int opt_all)
{
gpg_error_t err;
unsigned char *serialno_bin = NULL;
@@ -254,6 +256,8 @@ open_card_with_request (ctrl_t ctrl,
err = select_application (ctrl, apptypestr, &ctrl->card_ctx, 1,
serialno_bin, serialno_bin_len);
+ if (!err && opt_all)
+ err = select_additional_application (ctrl, APPTYPE_NONE);
leave:
xfree (serialno_bin);
@@ -262,7 +266,7 @@ open_card_with_request (ctrl_t ctrl,
static const char hlp_serialno[] =
- "SERIALNO [--demand=<serialno>] [<apptype>]\n"
+ "SERIALNO [--demand=<serialno>] [--all] [<apptype>]\n"
"\n"
"Return the serial number of the card using a status response. This\n"
"function should be used to check for the presence of a card.\n"
@@ -270,6 +274,9 @@ static const char hlp_serialno[] =
"If --demand is given, an application on the card with SERIALNO is\n"
"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"
+ "will also be selected for on-the-fly swicthing.\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"
"The default is to auto-select the application using a hardwired\n"
@@ -291,6 +298,7 @@ cmd_serialno (assuan_context_t ctx, char *line)
int rc = 0;
char *serial;
const char *demand;
+ int opt_all = has_option (line, "--all");
if ( IS_LOCKED (ctrl) )
return gpg_error (GPG_ERR_LOCKED);
@@ -308,11 +316,13 @@ cmd_serialno (assuan_context_t ctx, char *line)
else
demand = NULL;
+ line = skip_options (line);
+
/* Clear the remove flag so that the open_card is able to reread it. */
if (ctrl->server_local->card_removed)
ctrl->server_local->card_removed = 0;
- if ((rc = open_card_with_request (ctrl, *line? line:NULL, demand)))
+ if ((rc = open_card_with_request (ctrl, *line? line:NULL, demand, opt_all)))
{
ctrl->server_local->card_removed = 1;
return rc;