summaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2017-02-17 11:39:28 +0100
committerNIIBE Yutaka <gniibe@fsij.org>2017-02-17 11:46:01 +0100
commit3f4f64b6ac0d7160fd9e1301f95820894b219c3f (patch)
tree68666aefebd3add0cda56297234bd3e875fd620c /agent
parentgpgscm: Guard use of tagged expressions. (diff)
downloadgnupg2-3f4f64b6ac0d7160fd9e1301f95820894b219c3f.tar.xz
gnupg2-3f4f64b6ac0d7160fd9e1301f95820894b219c3f.zip
agent: Send back all public keys for available cards.
* agent/call-scd.c (card_cardlist_cb, agent_card_cardlist): New. * agent/command-ssh.c (card_key_list): New. (ssh_handler_request_identities): Call card_key_list and loop for the list to send public keys for all available cards. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Diffstat (limited to 'agent')
-rw-r--r--agent/agent.h1
-rw-r--r--agent/call-scd.c66
-rw-r--r--agent/command-ssh.c76
3 files changed, 135 insertions, 8 deletions
diff --git a/agent/agent.h b/agent/agent.h
index 217838472..2a722fd24 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -556,6 +556,7 @@ int agent_card_writekey (ctrl_t ctrl, int force, const char *serialno,
int (*getpin_cb)(void *, 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 *, char*, size_t),
void *getpin_cb_arg, void *assuan_context);
diff --git a/agent/call-scd.c b/agent/call-scd.c
index 15a2ba529..71e0f581c 100644
--- a/agent/call-scd.c
+++ b/agent/call-scd.c
@@ -39,6 +39,7 @@
#include "agent.h"
#include <assuan.h>
+#include "strlist.h"
#ifdef _POSIX_OPEN_MAX
#define MAX_OPEN_FDS _POSIX_OPEN_MAX
@@ -1189,9 +1190,74 @@ agent_card_getattr (ctrl_t ctrl, const char *name, char **result)
return unlock_scd (ctrl, err);
}
+
+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)
+{
+ 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);
+ }
+
+ return 0;
+}
+
+/* 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);
+}
static gpg_error_t
pass_status_thru (void *opaque, const char *line)
diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index 1d4453c84..2c74618d6 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -2382,6 +2382,29 @@ 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;
+
+ err = agent_card_serialno (ctrl, r_serialno, NULL);
+ if (err)
+ {
+ if (opt.verbose)
+ log_info (_("error getting serial number of card: %s\n"),
+ gpg_strerror (err));
+ return err;
+ }
+
+ 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
@@ -2561,17 +2584,54 @@ ssh_handler_request_identities (ctrl_t ctrl,
reader - this should be allowed even without being listed in
sshcontrol. */
- if (!opt.disable_scdaemon
- && !card_key_available (ctrl, &key_public, &cardsn))
+ if (!opt.disable_scdaemon)
{
- err = ssh_send_key_public (key_blobs, key_public, cardsn);
- gcry_sexp_release (key_public);
- key_public = NULL;
- xfree (cardsn);
+ char *serialno;
+ strlist_t card_list, sl;
+
+ err = card_key_list (ctrl, &serialno, &card_list);
if (err)
- goto out;
+ {
+ if (opt.verbose)
+ log_info (_("error getting list of cards: %s\n"),
+ gpg_strerror (err));
+ goto out;
+ }
- key_counter++;
+ for (sl = card_list; sl; sl = sl->next)
+ {
+ char *serialno0;
+ err = agent_card_serialno (ctrl, &serialno0, sl->d);
+ if (err)
+ {
+ if (opt.verbose)
+ log_info (_("error getting serial number of card: %s\n"),
+ gpg_strerror (err));
+ xfree (serialno);
+ free_strlist (card_list);
+ goto out;
+ }
+
+ xfree (serialno0);
+ if (card_key_available (ctrl, &key_public, &cardsn))
+ continue;
+
+ err = ssh_send_key_public (key_blobs, key_public, cardsn);
+ gcry_sexp_release (key_public);
+ key_public = NULL;
+ xfree (cardsn);
+ if (err)
+ {
+ xfree (serialno);
+ free_strlist (card_list);
+ goto out;
+ }
+
+ key_counter++;
+ }
+
+ xfree (serialno);
+ free_strlist (card_list);
}
/* Then look at all the registered and non-disabled keys. */