diff options
author | Werner Koch <wk@gnupg.org> | 2019-09-04 12:08:07 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2019-09-04 12:08:07 +0200 |
commit | 5cf5a04bae03d622a42753735c60dfab3b24ade8 (patch) | |
tree | 7c404442c779861db16ee7a41e2180cdd85adb9d /scd | |
parent | scd: Use a macro for the flag parameter of learn_status. (diff) | |
download | gnupg2-5cf5a04bae03d622a42753735c60dfab3b24ade8.tar.xz gnupg2-5cf5a04bae03d622a42753735c60dfab3b24ade8.zip |
scd: Add option --multi to the LEARN command.
* scd/app-common.h (APP_LEARN_FLAG_MULTI): New.
* scd/command.c (cmd_learn): Add option --multi.
* scd/app.c (app_write_learn_status): Factor some code out to ...
(write_learn_status_core): new.
(app_write_learn_status): Implement flag --multi.
--
This new option is intended to return information about all active
applications of the current card. Thus if a "SERIALNO openpgp" and a
"SERIALNO piv" has been done in a session the command "LEARN --force
--multi" returns information about both applications.
Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'scd')
-rw-r--r-- | scd/app-common.h | 2 | ||||
-rw-r--r-- | scd/app.c | 69 | ||||
-rw-r--r-- | scd/command.c | 9 |
3 files changed, 61 insertions, 19 deletions
diff --git a/scd/app-common.h b/scd/app-common.h index 9fadafd6a..87f63bb7e 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -44,6 +44,8 @@ /* Flags used by the app_write_learn_status. */ #define APP_LEARN_FLAG_KEYPAIRINFO 1 /* Return only keypair infos. */ +#define APP_LEARN_FLAG_MULTI 2 /* Return info for all apps. */ + /* List of supported card types. Generic is the usual ISO7817-4 * compliant card. More specific card or token versions can be given @@ -1030,13 +1030,36 @@ maybe_switch_app (ctrl_t ctrl, card_t card) } +/* Helper for app_write_learn_status. */ +static gpg_error_t +write_learn_status_core (card_t card, app_t app, ctrl_t ctrl, + unsigned int flags) +{ + /* We do not send CARD and APPTYPE if only keypairinfo is requested. */ + if (!(flags & APP_LEARN_FLAG_KEYPAIRINFO)) + { + if (card && card->cardtype) + send_status_direct (ctrl, "CARDTYPE", strcardtype (card->cardtype)); + if (card && card->cardversion) + send_status_printf (ctrl, "CARDVERSION", "%X", card->cardversion); + if (app->apptype) + send_status_direct (ctrl, "APPTYPE", strapptype (app->apptype)); + if (app->appversion) + send_status_printf (ctrl, "APPVERSION", "%X", app->appversion); + } + + return app->fnc.learn_status (app, ctrl, flags); +} + + /* Write out the application specific status lines for the LEARN command. */ gpg_error_t app_write_learn_status (card_t card, ctrl_t ctrl, unsigned int flags) { - gpg_error_t err; + gpg_error_t err, err2; app_t app; + int any_reselect = 0; if (!card) return gpg_error (GPG_ERR_INV_VALUE); @@ -1045,29 +1068,43 @@ app_write_learn_status (card_t card, ctrl_t ctrl, unsigned int flags) 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))) ; else if (!card->app->fnc.learn_status) err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); else { - app = card->app; - - /* We do not send CARD and APPTYPE if only keypairinfo is requested. */ - if (!(flags & APP_LEARN_FLAG_KEYPAIRINFO)) + err = write_learn_status_core (card, card->app, ctrl, flags); + if (!err && card->app->fnc.reselect && (flags & APP_LEARN_FLAG_MULTI)) { - if (card->cardtype) - send_status_direct (ctrl, "CARDTYPE", strcardtype (card->cardtype)); - if (card->cardversion) - send_status_printf (ctrl, "CARDVERSION", "%X", card->cardversion); - if (app->apptype) - send_status_direct (ctrl, "APPTYPE", strapptype (app->apptype)); - if (app->appversion) - send_status_printf (ctrl, "APPVERSION", "%X", app->appversion); - /* FIXME: Send info for the other active apps of the card? */ + /* The current app has the reselect feature so that we can + * loop over all other apps which are capable of a reselect + * and finally reselect the first app again. Note that we + * did the learn for the currently selected card above. */ + app = card->app; + for (app = app->next; app && !err; app = app->next) + if (app->fnc.reselect) + { + any_reselect = 1; + err = app->fnc.reselect (app, ctrl); + if (!err) + err = write_learn_status_core (NULL, app, ctrl, flags); + } + app = card->app; + if (any_reselect) + { + err2 = app->fnc.reselect (app, ctrl); + if (err2) + { + log_error ("error re-selecting '%s': %s\n", + strapptype(app->apptype), gpg_strerror (err2)); + if (!err) + err = err2; + } + } } - - err = app->fnc.learn_status (app, ctrl, flags); } unlock_card (card); diff --git a/scd/command.c b/scd/command.c index 1baa9670d..b37b29c3f 100644 --- a/scd/command.c +++ b/scd/command.c @@ -338,7 +338,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" @@ -366,7 +366,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" @@ -413,6 +414,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; @@ -477,7 +479,8 @@ cmd_learn (assuan_context_t ctx, char *line) if (!rc) rc = app_write_learn_status (ctrl->card_ctx, ctrl, - (only_keypairinfo? APP_LEARN_FLAG_KEYPAIRINFO : 0)); + ( (only_keypairinfo? APP_LEARN_FLAG_KEYPAIRINFO : 0) + | (opt_multi? APP_LEARN_FLAG_MULTI : 0)) ); return rc; } |