diff options
Diffstat (limited to 'scd/command.c')
-rw-r--r-- | scd/command.c | 102 |
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); } |