aboutsummaryrefslogtreecommitdiffstats
path: root/agent/command.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--agent/command.c203
1 files changed, 137 insertions, 66 deletions
diff --git a/agent/command.c b/agent/command.c
index 55ee8b84a..3573c27f8 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -77,6 +77,48 @@ has_option (const char *line, const char *name)
return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
}
+/* Parse a hex string. Return an Assuan error code or 0 on success and the
+ length of the parsed string in LEN. */
+static int
+parse_hexstring (ASSUAN_CONTEXT ctx, const char *string, size_t *len)
+{
+ const char *p;
+ size_t n;
+
+ /* parse the hash value */
+ for (p=string, n=0; hexdigitp (p); p++, n++)
+ ;
+ if (*p)
+ return set_error (Parameter_Error, "invalid hexstring");
+ if ((n&1))
+ return set_error (Parameter_Error, "odd number of digits");
+ *len = n;
+ return 0;
+}
+
+/* Parse the keygrip in STRING into the provided buffer BUF. BUF must
+ provide space for 20 bytes. BUF is not changed if the fucntions
+ returns an error. */
+static int
+parse_keygrip (ASSUAN_CONTEXT ctx, const char *string, unsigned char *buf)
+{
+ int rc;
+ size_t n;
+ const unsigned char *p;
+
+ rc = parse_hexstring (ctx, string, &n);
+ if (rc)
+ return rc;
+ n /= 2;
+ if (n != 20)
+ return set_error (Parameter_Error, "invalid length of keygrip");
+
+ for (p=string, n=0; n < 20; p += 2, n++)
+ buf[n] = xtoi_2 (p);
+
+ return 0;
+}
+
@@ -136,6 +178,7 @@ cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line)
static int
cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
{
+ CTRL ctrl = assuan_get_pointer (ctx);
int rc, n, i;
char *p;
char fpr[41];
@@ -164,7 +207,7 @@ cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
while (spacep (p))
p++;
- rc = agent_marktrusted (p, fpr, flag);
+ rc = agent_marktrusted (ctrl, p, fpr, flag);
if (rc)
log_error ("command marktrusted failed: %s\n", gnupg_strerror (rc));
return map_to_assuan_status (rc);
@@ -179,23 +222,12 @@ cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
static int
cmd_havekey (ASSUAN_CONTEXT ctx, char *line)
{
- int n;
- char *p;
+ int rc;
unsigned char buf[20];
- /* parse the hash value */
- for (p=line,n=0; hexdigitp (p); p++, n++)
- ;
- if (*p)
- return set_error (Parameter_Error, "invalid hexstring");
- if ((n&1))
- return set_error (Parameter_Error, "odd number of digits");
- n /= 2;
- if (n != 20)
- return set_error (Parameter_Error, "invalid length of keygrip");
-
- for (p=line, n=0; n < 20; p += 2, n++)
- buf[n] = xtoi_2 (p);
+ rc = parse_keygrip (ctx, line, buf);
+ if (rc)
+ return rc;
if (agent_key_available (buf))
return ASSUAN_No_Secret_Key;
@@ -211,29 +243,17 @@ cmd_havekey (ASSUAN_CONTEXT ctx, char *line)
static int
cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
{
- int n;
- char *p;
+ int rc;
CTRL ctrl = assuan_get_pointer (ctx);
- unsigned char *buf;
-
- /* parse the hash value */
- for (p=line,n=0; hexdigitp (p); p++, n++)
- ;
- if (*p)
- return set_error (Parameter_Error, "invalid hexstring");
- if ((n&1))
- return set_error (Parameter_Error, "odd number of digits");
- n /= 2;
- if (n != 20)
- return set_error (Parameter_Error, "invalid length of keygrip");
- buf = ctrl->keygrip;
- for (p=line, n=0; n < 20; p += 2, n++)
- buf[n] = xtoi_2 (p);
+ rc = parse_keygrip (ctx, line, ctrl->keygrip);
+ if (rc)
+ return rc;
ctrl->have_keygrip = 1;
return 0;
}
+
/* SETHASH <algonumber> <hexstring>
The client can use this command to tell the server about the data
@@ -241,7 +261,8 @@ cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
static int
cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
{
- int n;
+ int rc;
+ size_t n;
char *p;
CTRL ctrl = assuan_get_pointer (ctx);
unsigned char *buf;
@@ -257,12 +278,9 @@ cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
ctrl->digest.algo = algo;
/* parse the hash value */
- for (p=line,n=0; hexdigitp (p); p++, n++)
- ;
- if (*p)
- return set_error (Parameter_Error, "invalid hexstring");
- if ((n&1))
- return set_error (Parameter_Error, "odd number of digits");
+ rc = parse_hexstring (ctx, line, &n);
+ if (rc)
+ return rc;
n /= 2;
if (n != 16 && n != 20 && n != 24 && n != 32)
return set_error (Parameter_Error, "unsupported length of hash");
@@ -386,6 +404,7 @@ plus_to_blank (char *s)
static int
cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
{
+ CTRL ctrl = assuan_get_pointer (ctx);
int rc;
const char *pw;
char *response;
@@ -459,7 +478,7 @@ cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
if (desc)
plus_to_blank (desc);
- rc = agent_get_passphrase (&response, desc, prompt, errtext);
+ rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
if (!rc)
{
if (cacheid)
@@ -520,52 +539,92 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
+/* PASSWD <hexstring_with_keygrip>
+
+ Change the passphrase/PID for the key identified by keygrip in LINE. */
+static int
+cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
+{
+ CTRL ctrl = assuan_get_pointer (ctx);
+ int rc;
+ unsigned char grip[20];
+ GCRY_SEXP s_skey = NULL;
+ unsigned char *shadow_info = NULL;
+
+ rc = parse_keygrip (ctx, line, grip);
+ if (rc)
+ return rc; /* we can't jump to leave because this is already an
+ Assuan error code. */
+
+ s_skey = agent_key_from_file (ctrl, grip, &shadow_info, 1);
+ if (!s_skey && !shadow_info)
+ rc = seterr (No_Secret_Key);
+ else if (!s_skey)
+ {
+ log_error ("changing a smartcard PIN is not yet supported\n");
+ rc = seterr (Not_Implemented);
+ }
+ else
+ rc = agent_protect_and_store (ctrl, s_skey);
+
+ gcry_sexp_release (s_skey);
+ xfree (shadow_info);
+ if (rc)
+ log_error ("command passwd failed: %s\n", gnupg_strerror (rc));
+ return map_to_assuan_status (rc);
+}
+
+
+
static int
option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
{
CTRL ctrl = assuan_get_pointer (ctx);
- /* FIXME: We should not change opt. here. It is not a problem right
- now but as soon as we are allowing concurrent connections we mess
- things up */
if (!strcmp (key, "display"))
{
- if (opt.display)
- free (opt.display);
- opt.display = strdup (value);
- if (!opt.display)
+ if (ctrl->display)
+ free (ctrl->display);
+ ctrl->display = strdup (value);
+ if (!ctrl->display)
return ASSUAN_Out_Of_Core;
}
else if (!strcmp (key, "ttyname"))
{
- if (opt.ttyname)
- free (opt.ttyname);
- opt.ttyname = strdup (value);
- if (!opt.ttyname)
- return ASSUAN_Out_Of_Core;
+ if (!opt.keep_tty)
+ {
+ if (ctrl->ttyname)
+ free (ctrl->ttyname);
+ ctrl->ttyname = strdup (value);
+ if (!ctrl->ttyname)
+ return ASSUAN_Out_Of_Core;
+ }
}
else if (!strcmp (key, "ttytype"))
{
- if (opt.ttytype)
- free (opt.ttytype);
- opt.ttytype = strdup (value);
- if (!opt.ttytype)
- return ASSUAN_Out_Of_Core;
+ if (!opt.keep_tty)
+ {
+ if (ctrl->ttytype)
+ free (ctrl->ttytype);
+ ctrl->ttytype = strdup (value);
+ if (!ctrl->ttytype)
+ return ASSUAN_Out_Of_Core;
+ }
}
else if (!strcmp (key, "lc-ctype"))
{
- if (opt.lc_ctype)
- free (opt.lc_ctype);
- opt.lc_ctype = strdup (value);
- if (!opt.lc_ctype)
+ if (ctrl->lc_ctype)
+ free (ctrl->lc_ctype);
+ ctrl->lc_ctype = strdup (value);
+ if (!ctrl->lc_ctype)
return ASSUAN_Out_Of_Core;
}
else if (!strcmp (key, "lc-messages"))
{
- if (opt.lc_messages)
- free (opt.lc_messages);
- opt.lc_messages = strdup (value);
- if (!opt.lc_messages)
+ if (ctrl->lc_messages)
+ free (ctrl->lc_messages);
+ ctrl->lc_messages = strdup (value);
+ if (!ctrl->lc_messages)
return ASSUAN_Out_Of_Core;
}
else if (!strcmp (key, "use-cache-for-signing"))
@@ -599,6 +658,7 @@ register_commands (ASSUAN_CONTEXT ctx)
{ "LISTTRUSTED", 0, cmd_listtrusted },
{ "MARKTRUSTED", 0, cmd_marktrusted },
{ "LEARN", 0, cmd_learn },
+ { "PASSWD", 0, cmd_passwd },
{ "", ASSUAN_CMD_INPUT, NULL },
{ "", ASSUAN_CMD_OUTPUT, NULL },
{ NULL }
@@ -630,6 +690,7 @@ start_command_handler (int listen_fd, int fd)
struct server_control_s ctrl;
memset (&ctrl, 0, sizeof ctrl);
+ agent_init_default_ctrl (&ctrl);
if (listen_fd == -1 && fd == -1)
{
@@ -693,5 +754,15 @@ start_command_handler (int listen_fd, int fd)
assuan_deinit_server (ctx);
+ if (ctrl.display)
+ free (ctrl.display);
+ if (ctrl.ttyname)
+ free (ctrl.ttyname);
+ if (ctrl.ttytype)
+ free (ctrl.ttytype);
+ if (ctrl.lc_ctype)
+ free (ctrl.lc_ctype);
+ if (ctrl.lc_messages)
+ free (ctrl.lc_messages);
}