aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--agent/agent.h3
-rw-r--r--agent/call-scd.c91
-rw-r--r--agent/command-ssh.c57
-rw-r--r--agent/command.c2
-rw-r--r--agent/divert-scd.c2
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 <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:
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. */