aboutsummaryrefslogtreecommitdiffstats
path: root/scd/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'scd/command.c')
-rw-r--r--scd/command.c102
1 files changed, 80 insertions, 22 deletions
diff --git a/scd/command.c b/scd/command.c
index 0096ca96d..73a524b49 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -105,6 +105,12 @@ static struct server_local_s *session_list;
in this variable. */
static struct server_local_s *locked_session;
+
+
+/* Local prototypes. */
+static int command_has_option (const char *cmd, const char *cmdopt);
+
+
/* Convert the STRING into a newly allocated buffer while translating
the hex numbers. Stops at the first invalid character. Blanks and
@@ -218,10 +224,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;
@@ -249,10 +257,13 @@ open_card_with_request (ctrl_t ctrl,
/* 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);
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);
@@ -261,7 +272,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"
@@ -269,6 +280,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"
@@ -290,6 +304,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);
@@ -307,11 +322,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;
@@ -337,7 +354,7 @@ cmd_serialno (assuan_context_t ctx, char *line)
static const char hlp_learn[] =
- "LEARN [--force] [--keypairinfo]\n"
+ "LEARN [--force] [--keypairinfo] [--multi]\n"
"\n"
"Learn all useful information of the currently inserted card. When\n"
"used without the force options, the command might do an INQUIRE\n"
@@ -365,7 +382,8 @@ static const char hlp_learn[] =
" PIV = PIV card\n"
" NKS = NetKey card\n"
"\n"
- "are implemented. These strings are aliases for the AID\n"
+ "are implemented. These strings are aliases for the AID. With option\n"
+ "--multi information for all switchable apps are returned.\n"
"\n"
" S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id> [<usage>]\n"
"\n"
@@ -412,6 +430,7 @@ cmd_learn (assuan_context_t ctx, char *line)
ctrl_t ctrl = assuan_get_pointer (ctx);
int rc = 0;
int only_keypairinfo = has_option (line, "--keypairinfo");
+ int opt_multi = has_option (line, "--multi");
if ((rc = open_card (ctrl)))
return rc;
@@ -474,7 +493,10 @@ cmd_learn (assuan_context_t ctx, char *line)
/* Let the application print out its collection of useful status
information. */
if (!rc)
- rc = app_write_learn_status (ctrl->card_ctx, ctrl, only_keypairinfo);
+ rc = app_write_learn_status
+ (ctrl->card_ctx, ctrl,
+ ( (only_keypairinfo? APP_LEARN_FLAG_KEYPAIRINFO : 0)
+ | (opt_multi? APP_LEARN_FLAG_MULTI : 0)) );
return rc;
}
@@ -1557,7 +1579,9 @@ static const char hlp_getinfo[] =
" application per line, fields delimited by colons,\n"
" first field is the name.\n"
" card_list - Return a list of serial numbers of active cards,\n"
- " using a status response.";
+ " using a status response.\n"
+ " cmd_has_option CMD OPT\n"
+ " - Returns OK if command CMD has option OPT.\n";
static gpg_error_t
cmd_getinfo (assuan_context_t ctx, char *line)
{
@@ -1575,6 +1599,38 @@ cmd_getinfo (assuan_context_t ctx, char *line)
snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
}
+ else if (!strncmp (line, "cmd_has_option", 14)
+ && (line[14] == ' ' || line[14] == '\t' || !line[14]))
+ {
+ char *cmd, *cmdopt;
+ line += 14;
+ while (*line == ' ' || *line == '\t')
+ line++;
+ if (!*line)
+ rc = gpg_error (GPG_ERR_MISSING_VALUE);
+ else
+ {
+ cmd = line;
+ while (*line && (*line != ' ' && *line != '\t'))
+ line++;
+ if (!*line)
+ rc = gpg_error (GPG_ERR_MISSING_VALUE);
+ else
+ {
+ *line++ = 0;
+ while (*line == ' ' || *line == '\t')
+ line++;
+ if (!*line)
+ rc = gpg_error (GPG_ERR_MISSING_VALUE);
+ else
+ {
+ cmdopt = line;
+ if (!command_has_option (cmd, cmdopt))
+ rc = gpg_error (GPG_ERR_FALSE);
+ }
+ }
+ }
+ }
else if (!strcmp (line, "socket_name"))
{
const char *s = scd_get_socket_name ();
@@ -1661,6 +1717,7 @@ cmd_restart (assuan_context_t ctx, char *line)
if (card)
{
ctrl->card_ctx = NULL;
+ ctrl->current_apptype = APPTYPE_NONE;
card_unref (card);
}
if (locked_session && ctrl->server_local == locked_session)
@@ -1917,6 +1974,20 @@ send_keyinfo (ctrl_t ctrl, int data, const char *keygrip_str,
+/* Return true if the command CMD implements the option OPT. */
+static int
+command_has_option (const char *cmd, const char *cmdopt)
+{
+ if (!strcmp (cmd, "SERIALNO"))
+ {
+ if (!strcmp (cmdopt, "all"))
+ return 1;
+ }
+
+ return 0;
+}
+
+
/* Tell the assuan library about our commands */
static int
register_commands (assuan_context_t ctx)
@@ -2079,20 +2150,6 @@ scd_command_handler (ctrl_t ctrl, int fd)
}
-/* Clear the current application info for CARD from all sessions.
- * This is used while deallocating a card. */
-void
-scd_clear_current_app (card_t card)
-{
- struct server_local_s *sl;
-
- for (sl=session_list; sl; sl = sl->next_session)
- {
- if (sl->ctrl_backlink->card_ctx == card)
- sl->ctrl_backlink->current_apptype = APPTYPE_NONE;
- }
-}
-
/* Send a line with status information via assuan and escape all given
buffers. The variable elements are pairs of (char *, size_t),
terminated with a (NULL, 0). */
@@ -2234,6 +2291,7 @@ send_client_notifications (card_t card, int removal)
if (removal)
{
sl->ctrl_backlink->card_ctx = NULL;
+ sl->ctrl_backlink->current_apptype = APPTYPE_NONE;
sl->card_removed = 1;
card_unref_locked (card);
}