From 57b8ed61ab93dd5aa73159f6db8adeb83d54b85f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 9 Jan 2020 11:55:42 +0900 Subject: [PATCH] agent: SSH: SCD KEYINFO to list available keys. * agent/agent.h (agent_card_cardlist): Remove. (agent_card_keyinfo): Add CAP argument. * agent/call-scd.c (card_cardlist_cb): Remove. (agent_card_cardlist): Remove. (agent_card_keyinfo): Support CAP constraint. * agent/command-ssh.c (card_key_list): Remove. (ssh_handler_request_identities): Use SCD KEYINFO command. * agent/command.c (cmd_keyinfo): Follow the API change. * agent/divert-scd.c (ask_for_card): Likewise. Signed-off-by: NIIBE Yutaka --- agent/agent.h | 3 +- agent/call-scd.c | 91 ++++++++------------------------------------- agent/command-ssh.c | 57 +++++++++++----------------- agent/command.c | 2 +- agent/divert-scd.c | 2 +- 5 files changed, 39 insertions(+), 116 deletions(-) diff --git a/agent/agent.h b/agent/agent.h index e08507cb2..b47cf4dc9 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -614,14 +614,13 @@ gpg_error_t agent_card_writekey (ctrl_t ctrl, int force, const char *serialno, const char *, char*, size_t), void *getpin_cb_arg); gpg_error_t agent_card_getattr (ctrl_t ctrl, const char *name, char **result); -gpg_error_t agent_card_cardlist (ctrl_t ctrl, strlist_t *result); int agent_card_scd (ctrl_t ctrl, const char *cmdline, int (*getpin_cb)(void *, const char *, const char *, char*, size_t), void *getpin_cb_arg, void *assuan_context); void agent_card_free_keyinfo (struct card_key_info_s *l); gpg_error_t agent_card_keyinfo (ctrl_t ctrl, const char *keygrip, - struct card_key_info_s **result); + int cap, struct card_key_info_s **result); void agent_card_killscd (void); diff --git a/agent/call-scd.c b/agent/call-scd.c index 0bd40173e..d10bde835 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -1360,78 +1360,6 @@ agent_card_getattr (ctrl_t ctrl, const char *name, char **result) -struct card_cardlist_parm_s { - int error; - strlist_t list; -}; - -/* Callback function for agent_card_cardlist. */ -static gpg_error_t -card_cardlist_cb (void *opaque, const char *line) -{ - gpg_error_t err = 0; - struct card_cardlist_parm_s *parm = opaque; - const char *keyword = line; - int keywordlen; - - for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) - ; - while (spacep (line)) - line++; - - if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen)) - { - const char *s; - int n; - - for (n=0,s=line; hexdigitp (s); s++, n++) - ; - - if (!n || (n&1) || *s) - parm->error = gpg_error (GPG_ERR_ASS_PARAMETER); - else - add_to_strlist (&parm->list, line); - } - else if (keywordlen == 12 && !memcmp (keyword, "PINCACHE_PUT", keywordlen)) - err = handle_pincache_put (line); - - return err; -} - -/* Call the scdaemon to retrieve list of available cards. On success - the allocated strlist is stored at RESULT. On error an error code is - returned and NULL stored at RESULT. */ -gpg_error_t -agent_card_cardlist (ctrl_t ctrl, strlist_t *result) -{ - int err; - struct card_cardlist_parm_s parm; - char line[ASSUAN_LINELENGTH]; - - *result = NULL; - - memset (&parm, 0, sizeof parm); - strcpy (line, "GETINFO card_list"); - - err = start_scd (ctrl); - if (err) - return err; - - err = assuan_transact (ctrl->scd_local->ctx, line, - NULL, NULL, NULL, NULL, - card_cardlist_cb, &parm); - if (!err && parm.error) - err = parm.error; - - if (!err) - *result = parm.list; - else - free_strlist (parm.list); - - return unlock_scd (ctrl, err); -} - - struct card_keyinfo_parm_s { int error; struct card_key_info_s *list; @@ -1552,21 +1480,32 @@ agent_card_free_keyinfo (struct card_key_info_s *l) } /* Call the scdaemon to check if a key of KEYGRIP is available, or - retrieve list of available keys on cards. On success the allocated - structure is stored at RESULT. On error an error code is returned + retrieve list of available keys on cards. With CAP, we can limit + keys with specified capability. On success, the allocated + structure is stored at RESULT. On error, an error code is returned and NULL is stored at RESULT. */ gpg_error_t -agent_card_keyinfo (ctrl_t ctrl, const char *keygrip, +agent_card_keyinfo (ctrl_t ctrl, const char *keygrip, int cap, struct card_key_info_s **result) { int err; struct card_keyinfo_parm_s parm; char line[ASSUAN_LINELENGTH]; + char *list_option; *result = NULL; + switch (cap) + { + case 0: list_option = "--list"; break; + case GCRY_PK_USAGE_SIGN: list_option = "--list=sign"; break; + case GCRY_PK_USAGE_ENCR: list_option = "--list=encr"; break; + case GCRY_PK_USAGE_AUTH: list_option = "--list=auth"; break; + default: return gpg_error (GPG_ERR_INV_VALUE); + } + memset (&parm, 0, sizeof parm); - snprintf (line, sizeof line, "KEYINFO %s", keygrip ? keygrip : "--list"); + snprintf (line, sizeof line, "KEYINFO %s", keygrip ? keygrip : list_option); err = start_scd (ctrl); if (err) diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 0849a06fc..0e3a50947 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -2374,34 +2374,6 @@ ssh_key_grip (gcry_sexp_t key, unsigned char *buffer) } -static gpg_error_t -card_key_list (ctrl_t ctrl, char **r_serialno, strlist_t *result) -{ - gpg_error_t err; - - *r_serialno = NULL; - *result = NULL; - - err = agent_card_serialno (ctrl, r_serialno, NULL); - if (err) - { - if (gpg_err_code (err) != GPG_ERR_ENODEV && opt.verbose) - log_info (_("error getting serial number of card: %s\n"), - gpg_strerror (err)); - - /* Nothing available. */ - return 0; - } - - err = agent_card_cardlist (ctrl, result); - if (err) - { - xfree (*r_serialno); - *r_serialno = NULL; - } - return err; -} - /* Check whether a smartcard is available and whether it has a usable key. Store a copy of that key at R_PK and return 0. If no key is available store NULL at R_PK and return an error code. If CARDSN @@ -2582,9 +2554,18 @@ ssh_handler_request_identities (ctrl_t ctrl, if (!opt.disable_scdaemon) { char *serialno; - strlist_t card_list, sl; + struct card_key_info_s *keyinfo_list; + struct card_key_info_s *keyinfo; + + /* Scan device(s), and get list of KEYGRIP. */ + err = agent_card_serialno (ctrl, &serialno, NULL); + if (!err) + { + xfree (serialno); + err = agent_card_keyinfo (ctrl, NULL, GCRY_PK_USAGE_AUTH, + &keyinfo_list); + } - err = card_key_list (ctrl, &serialno, &card_list); if (err) { if (opt.verbose) @@ -2593,12 +2574,18 @@ ssh_handler_request_identities (ctrl_t ctrl, goto scd_out; } - for (sl = card_list; sl; sl = sl->next) + for (keyinfo = keyinfo_list; keyinfo; keyinfo = keyinfo->next) { char *serialno0; char *cardsn; - err = agent_card_serialno (ctrl, &serialno0, sl->d); + /* + * FIXME: Do access by KEYGRIP directly, not by $AUTHKEYID. + * In scdaemon, implement SCD READKEY and + * SCD GETATTR . + * Then, no switch of foreground card occurrs. + */ + err = agent_card_serialno (ctrl, &serialno0, keyinfo->serialno); if (err) { if (opt.verbose) @@ -2619,16 +2606,14 @@ ssh_handler_request_identities (ctrl_t ctrl, xfree (cardsn); if (err) { - xfree (serialno); - free_strlist (card_list); + agent_card_free_keyinfo (keyinfo_list); goto out; } key_counter++; } - xfree (serialno); - free_strlist (card_list); + agent_card_free_keyinfo (keyinfo_list); } scd_out: diff --git a/agent/command.c b/agent/command.c index b59532ce5..e38685c11 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1307,7 +1307,7 @@ cmd_keyinfo (assuan_context_t ctx, char *line) if (opt_with_ssh || list_mode == 2) cf = ssh_open_control_file (); - agent_card_keyinfo (ctrl, NULL, &keyinfo_on_cards); + agent_card_keyinfo (ctrl, NULL, 0, &keyinfo_on_cards); if (list_mode == 2) { diff --git a/agent/divert-scd.c b/agent/divert-scd.c index ee97a7e7e..de072e629 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -77,7 +77,7 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, struct card_key_info_s *keyinfo; xfree (serialno); - err = agent_card_keyinfo (ctrl, hexgrip, &keyinfo); + err = agent_card_keyinfo (ctrl, hexgrip, 0, &keyinfo); if (!err) { /* Key for GRIP found, use it directly. */