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 <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2020-01-09 11:55:42 +09:00
parent fbf97a7856
commit 57b8ed61ab
5 changed files with 39 additions and 116 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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 <KEYGRIP> and
* SCD GETATTR <KEYGRIP>.
* 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:

View File

@ -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)
{

View File

@ -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. */