aboutsummaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
Diffstat (limited to 'agent')
-rw-r--r--agent/ChangeLog73
-rw-r--r--agent/agent.h31
-rw-r--r--agent/cache.c2
-rw-r--r--agent/command.c203
-rw-r--r--agent/divert-scd.c23
-rw-r--r--agent/findkey.c12
-rw-r--r--agent/genkey.c50
-rw-r--r--agent/gpg-agent.c187
-rw-r--r--agent/pkdecrypt.c4
-rw-r--r--agent/pksign.c8
-rw-r--r--agent/protect-tool.c2
-rw-r--r--agent/query.c50
-rw-r--r--agent/simple-pwquery.c7
-rw-r--r--agent/trustlist.c6
14 files changed, 501 insertions, 157 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog
index c19193b23..dc1bedf55 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,3 +1,76 @@
+2002-12-04 Werner Koch <[email protected]>
+
+ * gpg-agent.c: New variable config_filename.
+ (parse_rereadable_options): New.
+ (main): Use it here. Add setting of default values, set
+ config_filename.
+ (reread_configuration): Filled with actual code.
+
+2002-12-03 Werner Koch <[email protected]>
+
+ * protect-tool.c (read_key): Don't run make_canonical on a NULL buffer.
+
+ * command.c (parse_hexstring): New.
+ (cmd_sethash): Use it.
+ (parse_keygrip): New.
+ (cmd_havekey, cmd_sigkey): Use it.
+ (cmd_passwd): New.
+ * genkey.c (agent_protect_and_store): New.
+ (store_key): Add arg FORCE.
+ (agent_genkey): Pass false to this force of store_key.
+
+2002-11-13 Werner Koch <[email protected]>
+
+ * gpg-agent.c (main): Switch all messages to utf-8.
+
+ * simple-pwquery.c (agent_send_all_options): Use $GPG_TTY and
+ stdin with ttyname.
+
+ * cache.c (new_data): Uiih - /sizeof d/sizeof *d/.
+
+2002-11-10 Werner Koch <[email protected]>
+
+ * command.c (option_handler): Fix keep_tty check.
+
+2002-11-06 Werner Koch <[email protected]>
+
+ * gpg-agent.c (main): Make sure we have a default ttyname.
+ * command.c (option_handler): Check opt.keep_tty here
+ * query.c (start_pinentry): but not anymore here.
+
+2002-11-05 Werner Koch <[email protected]>
+
+ * agent.h (opt,server_control_s): Move display and lc_ variables
+ to the control struct so that they are per connection.
+ * gpg-agent.c (agent_init_default_ctrl): New.
+ (main): Assign those command line options to new default_* variables.
+ Reset DISPLAY in server mode so that tehre is no implicit default.
+ * command.c (start_command_handler): Initialize and deinitialize
+ the control values.
+ (option_handler): Work on the ctrl values and not on the opt.
+ * query.c (start_pinentry): New argument CTRL to set the display
+ connection specific. Changed all callers to pass this value.
+ (agent_askpin,agent_get_passphrase,agent_get_confirmation): Add
+ CTRL arg and pass it ot start_pinentry.
+ * command.c (cmd_get_passphrase): Pass CTRL argument.
+ * trustlist.c (agent_marktrusted): Add CTRL argument
+ * command.c (cmd_marktrusted): Pass CTRL argument
+ * divert-scd.c (ask_for_card): Add CTRL arg.
+ (divert_pksign,divert_pkdecrypt): Ditto. Changed caller.
+ (getpin_cb): Use OPAQUE to pass the CTRL variable. Changed both
+ users.
+ * findkey.c (unprotect): Add CTRL arg.
+ (agent_key_from_file): Ditto.
+
+ * query.c (unlock_pinentry): Disconnect the pinentry so that we
+ start a new one for each request. This is required to support
+ clients with different environments (e.g. X magic cookies).
+
+2002-09-05 Neal H. Walfield <[email protected]>
+
+ * gpg-agent.c (main) [USE_GNU_PTH]: No need to call
+ assuan_set_io_func as assuan is smart.
+
2002-09-25 Werner Koch <[email protected]>
* gpg-agent.c (handle_signal): Flush cache on SIGHUP.
diff --git a/agent/agent.h b/agent/agent.h
index 24267b06a..bd7b36a5d 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -1,5 +1,5 @@
/* agent.h - Global definitions for the agent
- * Copyright (C) 2001 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -36,11 +36,6 @@ struct {
int batch; /* batch mode */
const char *homedir; /* configuration directory name */
const char *pinentry_program;
- char *display;
- char *ttyname;
- char *ttytype;
- char *lc_ctype;
- char *lc_messages;
const char *scdaemon_program;
int no_grab; /* don't let the pinentry grab the keyboard */
unsigned long def_cache_ttl;
@@ -73,6 +68,11 @@ struct server_local_s;
struct server_control_s {
struct server_local_s *server_local;
+ char *display;
+ char *ttyname;
+ char *ttytype;
+ char *lc_ctype;
+ char *lc_messages;
struct {
int algo;
unsigned char value[MAX_DIGEST_LEN];
@@ -107,6 +107,7 @@ enum {
/*-- gpg-agent.c --*/
void agent_exit (int rc); /* also implemented in other tools */
+void agent_init_default_ctrl (struct server_control_s *ctrl);
/*-- command.c --*/
void start_command_handler (int, int);
@@ -114,16 +115,17 @@ void start_command_handler (int, int);
/*-- findkey.c --*/
int agent_write_private_key (const unsigned char *grip,
const void *buffer, size_t length, int force);
-GCRY_SEXP agent_key_from_file (const unsigned char *grip,
+GCRY_SEXP agent_key_from_file (CTRL ctrl, const unsigned char *grip,
unsigned char **shadow_info, int ignore_cache);
int agent_key_available (const unsigned char *grip);
/*-- query.c --*/
-int agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo);
-int agent_get_passphrase (char **retpass,
+int agent_askpin (CTRL ctrl,
+ const char *desc_text, struct pin_entry_info_s *pininfo);
+int agent_get_passphrase (CTRL ctrl, char **retpass,
const char *desc, const char *prompt,
const char *errtext);
-int agent_get_confirmation (const char *desc, const char *ok,
+int agent_get_confirmation (CTRL ctrl, const char *desc, const char *ok,
const char *cancel);
/*-- cache.c --*/
@@ -143,6 +145,7 @@ int agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
/*-- genkey.c --*/
int agent_genkey (CTRL ctrl,
const char *keyparam, size_t keyparmlen, FILE *outfp);
+int agent_protect_and_store (CTRL ctrl, GCRY_SEXP s_skey);
/*-- protect.c --*/
int agent_protect (const unsigned char *plainkey, const char *passphrase,
@@ -160,13 +163,15 @@ int agent_get_shadow_info (const unsigned char *shadowkey,
/*-- trustlist.c --*/
int agent_istrusted (const char *fpr);
int agent_listtrusted (void *assuan_context);
-int agent_marktrusted (const char *name, const char *fpr, int flag);
+int agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag);
/*-- divert-scd.c --*/
-int divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
+int divert_pksign (CTRL ctrl,
+ const unsigned char *digest, size_t digestlen, int algo,
const unsigned char *shadow_info, unsigned char **r_sig);
-int divert_pkdecrypt (const unsigned char *cipher,
+int divert_pkdecrypt (CTRL ctrl,
+ const unsigned char *cipher,
const unsigned char *shadow_info,
char **r_buf, size_t *r_len);
diff --git a/agent/cache.c b/agent/cache.c
index 8f5bf9d3d..b6ab55085 100644
--- a/agent/cache.c
+++ b/agent/cache.c
@@ -67,7 +67,7 @@ new_data (const void *data, size_t length)
secure storage provider*/
total = length + 32 - (length % 32);
- d = gcry_malloc_secure (sizeof d + total - 1);
+ d = gcry_malloc_secure (sizeof *d + total - 1);
if (d)
{
d->totallen = total;
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);
}
diff --git a/agent/divert-scd.c b/agent/divert-scd.c
index 40b6bcfa3..38f8173c0 100644
--- a/agent/divert-scd.c
+++ b/agent/divert-scd.c
@@ -34,7 +34,7 @@
static int
-ask_for_card (const unsigned char *shadow_info, char **r_kid)
+ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid)
{
int rc, i;
const unsigned char *s;
@@ -119,7 +119,7 @@ ask_for_card (const unsigned char *shadow_info, char **r_kid)
}
else
{
- rc = agent_get_confirmation (desc, NULL, NULL);
+ rc = agent_get_confirmation (ctrl, desc, NULL, NULL);
free (desc);
}
}
@@ -174,8 +174,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
struct pin_entry_info_s *pi;
int rc;
char *desc;
-
- assert (!opaque);
+ CTRL ctrl = opaque;
if (maxbuf < 2)
return GNUPG_Invalid_Value;
@@ -195,7 +194,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
info? info:"",
info? "')":"") < 0)
desc = NULL;
- rc = agent_askpin (desc?desc:info, pi);
+ rc = agent_askpin (ctrl, desc?desc:info, pi);
free (desc);
if (!rc)
{
@@ -210,7 +209,8 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
int
-divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
+divert_pksign (CTRL ctrl,
+ const unsigned char *digest, size_t digestlen, int algo,
const unsigned char *shadow_info, unsigned char **r_sig)
{
int rc;
@@ -220,7 +220,7 @@ divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
unsigned char *data;
size_t ndata;
- rc = ask_for_card (shadow_info, &kid);
+ rc = ask_for_card (ctrl, shadow_info, &kid);
if (rc)
return rc;
@@ -229,7 +229,7 @@ divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
if (rc)
return rc;
- rc = agent_card_pksign (kid, getpin_cb, NULL,
+ rc = agent_card_pksign (kid, getpin_cb, ctrl,
data, ndata, &sigval, &siglen);
if (!rc)
*r_sig = sigval;
@@ -244,7 +244,8 @@ divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
key identified by SHADOW_INFO and return the plaintext in an
allocated buffer in R_BUF. */
int
-divert_pkdecrypt (const unsigned char *cipher,
+divert_pkdecrypt (CTRL ctrl,
+ const unsigned char *cipher,
const unsigned char *shadow_info,
char **r_buf, size_t *r_len)
{
@@ -288,11 +289,11 @@ divert_pkdecrypt (const unsigned char *cipher,
ciphertext = s;
ciphertextlen = n;
- rc = ask_for_card (shadow_info, &kid);
+ rc = ask_for_card (ctrl, shadow_info, &kid);
if (rc)
return rc;
- rc = agent_card_pkdecrypt (kid, getpin_cb, NULL,
+ rc = agent_card_pkdecrypt (kid, getpin_cb, ctrl,
ciphertext, ciphertextlen,
&plaintext, &plaintextlen);
if (!rc)
diff --git a/agent/findkey.c b/agent/findkey.c
index 8ec230fa0..96a1f360c 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -131,9 +131,10 @@ try_unprotect_cb (struct pin_entry_info_s *pi)
/* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
should be the hex encoded keygrip of that key to be used with the
- cahing mechanism. */
+ caching mechanism. */
static int
-unprotect (unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
+unprotect (CTRL ctrl,
+ unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
{
struct pin_entry_info_s *pi;
struct try_unprotect_arg_s arg;
@@ -176,7 +177,7 @@ unprotect (unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
arg.unprotected_key = NULL;
pi->check_cb_arg = &arg;
- rc = agent_askpin (NULL, pi);
+ rc = agent_askpin (ctrl, NULL, pi);
if (!rc)
{
assert (arg.unprotected_key);
@@ -197,7 +198,8 @@ unprotect (unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
With IGNORE_CACHE passed as true the passphrase is not taken from
the cache.*/
GCRY_SEXP
-agent_key_from_file (const unsigned char *grip, unsigned char **shadow_info,
+agent_key_from_file (CTRL ctrl,
+ const unsigned char *grip, unsigned char **shadow_info,
int ignore_cache)
{
int i, rc;
@@ -271,7 +273,7 @@ agent_key_from_file (const unsigned char *grip, unsigned char **shadow_info,
case PRIVATE_KEY_CLEAR:
break; /* no unprotection needed */
case PRIVATE_KEY_PROTECTED:
- rc = unprotect (&buf, grip, ignore_cache);
+ rc = unprotect (ctrl, &buf, grip, ignore_cache);
if (rc)
log_error ("failed to unprotect the secret key: %s\n",
gnupg_strerror (rc));
diff --git a/agent/genkey.c b/agent/genkey.c
index dccac94da..6def5cd8a 100644
--- a/agent/genkey.c
+++ b/agent/genkey.c
@@ -30,7 +30,7 @@
#include "i18n.h"
static int
-store_key (GCRY_SEXP private, const char *passphrase)
+store_key (GCRY_SEXP private, const char *passphrase, int force)
{
int rc;
char *buf;
@@ -65,13 +65,13 @@ store_key (GCRY_SEXP private, const char *passphrase)
buf = p;
}
- rc = agent_write_private_key (grip, buf, len, 0);
+ rc = agent_write_private_key (grip, buf, len, force);
xfree (buf);
return rc;
}
/* Callback function to compare the first entered PIN with the one
- currently beeing entered. */
+ currently being entered. */
static int
reenter_compare_cb (struct pin_entry_info_s *pi)
{
@@ -119,9 +119,9 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
pi2->check_cb = reenter_compare_cb;
pi2->check_cb_arg = pi->pin;
- rc = agent_askpin (text1, pi);
+ rc = agent_askpin (ctrl, text1, pi);
if (!rc)
- rc = agent_askpin (text2, pi2);
+ rc = agent_askpin (ctrl, text2, pi2);
if (rc)
return rc;
if (!*pi->pin)
@@ -162,7 +162,7 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
/* store the secret key */
log_debug ("storing private key\n");
- rc = store_key (s_private, pi? pi->pin:NULL);
+ rc = store_key (s_private, pi? pi->pin:NULL, 0);
xfree (pi); pi = NULL;
gcry_sexp_release (s_private);
if (rc)
@@ -198,3 +198,41 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
return 0;
}
+
+
+/* Apply a new passpahrse to the key S_SKEY and store it. */
+int
+agent_protect_and_store (CTRL ctrl, GCRY_SEXP s_skey)
+{
+ struct pin_entry_info_s *pi, *pi2;
+ int rc;
+
+ {
+ const char *text1 = _("Please enter the new passphrase");
+ const char *text2 = _("Please re-enter this passphrase");
+
+ pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
+ pi2 = pi + (sizeof *pi + 100);
+ pi->max_length = 100;
+ pi->max_tries = 3;
+ pi2->max_length = 100;
+ pi2->max_tries = 3;
+ pi2->check_cb = reenter_compare_cb;
+ pi2->check_cb_arg = pi->pin;
+
+ rc = agent_askpin (ctrl, text1, pi);
+ if (!rc)
+ rc = agent_askpin (ctrl, text2, pi2);
+ if (rc)
+ return rc;
+ if (!*pi->pin)
+ {
+ xfree (pi);
+ pi = NULL; /* User does not want a passphrase. */
+ }
+ }
+
+ rc = store_key (s_skey, pi? pi->pin:NULL, 1);
+ xfree (pi);
+ return 0;
+}
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 3c823e5f6..780dfaddd 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -137,6 +137,18 @@ static int maybe_setuid = 1;
/* Name of the communication socket */
static char socket_name[128];
+/* Default values for options passed to the pinentry. */
+static char *default_display;
+static char *default_ttyname;
+static char *default_ttytype;
+static char *default_lc_ctype;
+static char *default_lc_messages;
+
+/* Name of a config file, which will be reread on a HUP if it is not NULL. */
+static char *config_filename;
+
+
+/* Local prototypes. */
static void create_directories (void);
#ifdef USE_GNU_PTH
static void handle_connections (int listen_fd);
@@ -248,6 +260,51 @@ cleanup_sh (int sig)
raise( sig );
}
+
+/* Handle options which are allowed to be reset after program start.
+ Return true when the current option in PARGS could be handled and
+ false if not. As a special feature, passing a value of NULL for
+ PARGS, resets the options to the default. */
+static int
+parse_rereadable_options (ARGPARSE_ARGS *pargs)
+{
+ if (!pargs)
+ { /* reset mode */
+ opt.quiet = 0;
+ opt.verbose = 0;
+ opt.debug = 0;
+ opt.no_grab = 0;
+ opt.pinentry_program = NULL;
+ opt.scdaemon_program = NULL;
+ opt.def_cache_ttl = 10*60; /* default to 10 minutes */
+ opt.ignore_cache_for_signing = 0;
+ return 1;
+ }
+
+ switch (pargs->r_opt)
+ {
+ case oQuiet: opt.quiet = 1; break;
+ case oVerbose: opt.verbose++; break;
+
+ case oDebug: opt.debug |= pargs->r.ret_ulong; break;
+ case oDebugAll: opt.debug = ~0; break;
+
+ case oNoGrab: opt.no_grab = 1; break;
+
+ case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break;
+ case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break;
+
+ case oDefCacheTTL: opt.def_cache_ttl = pargs->r.ret_ulong; break;
+
+ case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
+
+ default:
+ return 0; /* not handled */
+ }
+ return 1; /* handled */
+}
+
+
int
main (int argc, char **argv )
{
@@ -288,15 +345,14 @@ main (int argc, char **argv )
}
assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
-#ifdef USE_GNU_PTH
- assuan_set_io_func (pth_read, pth_write);
-#endif
gcry_set_log_handler (my_gcry_logger, NULL);
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
may_coredump = disable_core_dumps ();
+ parse_rereadable_options (NULL); /* Reset them to default values. */
+
shell = getenv ("SHELL");
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
csh_style = 1;
@@ -304,7 +360,6 @@ main (int argc, char **argv )
opt.homedir = getenv("GNUPGHOME");
if (!opt.homedir || !*opt.homedir)
opt.homedir = GNUPG_DEFAULT_HOMEDIR;
- opt.def_cache_ttl = 10*60; /* default to 10 minutes */
/* check whether we have a config file on the commandline */
@@ -375,14 +430,12 @@ main (int argc, char **argv )
while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) )
{
+ if (parse_rereadable_options (&pargs))
+ continue; /* Already handled */
switch (pargs.r_opt)
{
- case oQuiet: opt.quiet = 1; break;
- case oVerbose: opt.verbose++; break;
case oBatch: opt.batch=1; break;
- case oDebug: opt.debug |= pargs.r.ret_ulong; break;
- case oDebugAll: opt.debug = ~0; break;
case oDebugWait: debug_wait = pargs.r.ret_int; break;
case oOptions:
@@ -399,7 +452,6 @@ main (int argc, char **argv )
case oNoOptions: break; /* no-options */
case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oNoDetach: nodetach = 1; break;
- case oNoGrab: opt.no_grab = 1; break;
case oLogFile: logfile = pargs.r.ret_str; break;
case oCsh: csh_style = 1; break;
case oSh: csh_style = 0; break;
@@ -407,16 +459,12 @@ main (int argc, char **argv )
case oDaemon: is_daemon = 1; break;
case oDisablePth: disable_pth = 1; break;
- case oPinentryProgram: opt.pinentry_program = pargs.r.ret_str; break;
- case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
- case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
- case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
- case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
- case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
- case oScdaemonProgram: opt.scdaemon_program = pargs.r.ret_str; break;
- case oDefCacheTTL: opt.def_cache_ttl = pargs.r.ret_ulong; break;
+ case oDisplay: default_display = xstrdup (pargs.r.ret_str); break;
+ case oTTYname: default_ttyname = xstrdup (pargs.r.ret_str); break;
+ case oTTYtype: default_ttytype = xstrdup (pargs.r.ret_str); break;
+ case oLCctype: default_lc_ctype = xstrdup (pargs.r.ret_str); break;
+ case oLCmessages: default_lc_messages = xstrdup (pargs.r.ret_str); break;
- case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
case oKeepTTY: opt.keep_tty = 1; break;
case oKeepDISPLAY: opt.keep_display = 1; break;
@@ -427,7 +475,8 @@ main (int argc, char **argv )
{
fclose( configfp );
configfp = NULL;
- xfree(configname);
+ /* Keep a copy of the name so that it can be read on SIGHUP. */
+ config_filename = configname;
configname = NULL;
goto next_pass;
}
@@ -465,7 +514,22 @@ main (int argc, char **argv )
sleep (debug_wait);
log_debug ("... okay\n");
}
+
+ if (!pipe_server && !is_daemon)
+ log_info (_("please use the option `--daemon'"
+ " to run the program in the background\n"));
+#ifdef ENABLE_NLS
+ /* gpg-agent usdually does not ooutput any messages becuase it runs
+ in the background. For log files it is acceptable to have
+ messages always encoded in utf-8. We switch here to utf-8, so
+ that commands like --help still give native messages. It is far
+ easier to swicthnonly once instead of for every message and it
+ actually helps when more then one thread is active (avoids
+ required an extra copy step). */
+ bind_textdomain_codeset (PACKAGE, "UTF-8");
+#endif
+
/* now start with logging to a file if this is desired */
if (logfile)
{
@@ -473,16 +537,18 @@ main (int argc, char **argv )
log_set_prefix (NULL, 1|2|4);
}
+ /* Make sure that we have a default ttyname. */
+ if (!default_ttyname && ttyname (1))
+ default_ttyname = xstrdup (ttyname (1));
+ if (!default_ttytype && getenv ("TERM"))
+ default_ttytype = xstrdup (getenv ("TERM"));
if (pipe_server)
{ /* this is the simple pipe based server */
start_command_handler (-1, -1);
}
else if (!is_daemon)
- {
- log_info (_("please use the option `--daemon'"
- " to run the program in the background\n"));
- }
+ ;
else
{ /* regular server mode */
int fd;
@@ -491,6 +557,13 @@ main (int argc, char **argv )
struct sockaddr_un serv_addr;
char *p;
+ /* Remove the DISPLAY variable so that a pinentry does not
+ default to a specific display. There is still a default
+ display when gpg-agent weas started using --display or a
+ client requested this using an OPTION command. */
+ if (!opt.keep_display)
+ unsetenv ("DISPLAY");
+
*socket_name = 0;
snprintf (socket_name, DIM(socket_name)-1,
"/tmp/gpg-XXXXXX/S.gpg-agent");
@@ -702,10 +775,76 @@ agent_exit (int rc)
}
+void
+agent_init_default_ctrl (struct server_control_s *ctrl)
+{
+ /* Note we ignore malloc errors because we can't do much about it
+ and the request will fail anyway shortly after this
+ initialization. */
+ if (ctrl->display)
+ free (ctrl->display);
+ ctrl->display = default_display? strdup (default_display) : NULL;
+
+ if (ctrl->ttyname)
+ free (ctrl->ttyname);
+ ctrl->ttyname = default_ttyname? strdup (default_ttyname) : NULL;
+
+ if (ctrl->ttytype)
+ free (ctrl->ttytype);
+ ctrl->ttytype = default_ttytype? strdup (default_ttytype) : NULL;
+
+ if (ctrl->lc_ctype)
+ free (ctrl->lc_ctype);
+ ctrl->lc_ctype = default_lc_ctype? strdup (default_lc_ctype) : NULL;
+
+ if (ctrl->lc_messages)
+ free (ctrl->lc_messages);
+ ctrl->lc_messages = default_lc_messages? strdup (default_lc_messages) : NULL;
+}
+
+
+/* Reread parts of the configuration. Note, that this function is
+ obviously not thread-safe and should only be called from the PTH
+ signal handler.
+
+ Fixme: Due to the way the argument parsing works, we create a
+ memory leak here for all string type arguments. There is currently
+ no clean way to tell whether the memory for the argument has been
+ allocated or points into the process' original arguments. Unless
+ we have a mechanism to tell this, we need to live on with this. */
static void
reread_configuration (void)
{
- /* FIXME: Move parts of the option parsing to here. */
+ ARGPARSE_ARGS pargs;
+ FILE *fp;
+ unsigned int configlineno = 0;
+ int dummy;
+
+ if (!config_filename)
+ return; /* No config file. */
+
+ fp = fopen (config_filename, "r");
+ if (!fp)
+ {
+ log_error (_("option file `%s': %s\n"),
+ config_filename, strerror(errno) );
+ return;
+ }
+
+ parse_rereadable_options (NULL); /* Start from the default values. */
+
+ memset (&pargs, 0, sizeof pargs);
+ dummy = 0;
+ pargs.argc = &dummy;
+ pargs.flags = 1; /* do not remove the args */
+ while (optfile_parse (fp, config_filename, &configlineno, &pargs, opts) )
+ {
+ if (pargs.r_opt < -1)
+ pargs.err = 1; /* Print a warning. */
+ else /* Try to parse this option - ignore unchangeable ones. */
+ parse_rereadable_options (&pargs);
+ }
+ fclose (fp);
}
diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c
index 6add3d467..094736c69 100644
--- a/agent/pkdecrypt.c
+++ b/agent/pkdecrypt.c
@@ -64,7 +64,7 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
log_printhex ("keygrip:", ctrl->keygrip, 20);
log_printhex ("cipher: ", ciphertext, ciphertextlen);
}
- s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info, 0);
+ s_skey = agent_key_from_file (ctrl, ctrl->keygrip, &shadow_info, 0);
if (!s_skey && !shadow_info)
{
log_error ("failed to read the secret key\n");
@@ -81,7 +81,7 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
goto leave;
}
- rc = divert_pkdecrypt (ciphertext, shadow_info, &buf, &len );
+ rc = divert_pkdecrypt (ctrl, ciphertext, shadow_info, &buf, &len );
if (rc)
{
log_error ("smartcard decryption failed: %s\n", gnupg_strerror (rc));
diff --git a/agent/pksign.c b/agent/pksign.c
index 2acc63dd9..1d84d4870 100644
--- a/agent/pksign.c
+++ b/agent/pksign.c
@@ -1,5 +1,5 @@
/* pksign.c - public key signing (well, acually using a secret key)
- * Copyright (C) 2001 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -98,7 +98,8 @@ agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache)
if (!ctrl->have_keygrip)
return seterr (No_Secret_Key);
- s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info, ignore_cache);
+ s_skey = agent_key_from_file (ctrl,
+ ctrl->keygrip, &shadow_info, ignore_cache);
if (!s_skey && !shadow_info)
{
log_error ("failed to read the secret key\n");
@@ -110,7 +111,8 @@ agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache)
{ /* divert operation to the smartcard */
unsigned char *sigbuf;
- rc = divert_pksign (ctrl->digest.value,
+ rc = divert_pksign (ctrl,
+ ctrl->digest.value,
ctrl->digest.valuelen,
ctrl->digest.algo,
shadow_info, &sigbuf);
diff --git a/agent/protect-tool.c b/agent/protect-tool.c
index 1d706ea2b..d501abd79 100644
--- a/agent/protect-tool.c
+++ b/agent/protect-tool.c
@@ -275,6 +275,8 @@ read_key (const char *fname)
unsigned char *key;
buf = read_file (fname, &buflen);
+ if (!buf)
+ return NULL;
key = make_canonical (fname, buf, buflen);
xfree (buf);
return key;
diff --git a/agent/query.c b/agent/query.c
index ee18a1483..a20e4fe7b 100644
--- a/agent/query.c
+++ b/agent/query.c
@@ -1,5 +1,5 @@
/* query.c - fork of the pinentry to query stuff from the user
- * Copyright (C) 2001 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -56,9 +56,15 @@ struct entry_parm_s {
+/* Unlock the pinentry so that another thread can start one and
+ disconnect that pinentry - we do this after the unlock so that a
+ stalled pinentry does not block other threads. Fixme: We should
+ have a timeout in Assuan for the disconnetc operation. */
static int
unlock_pinentry (int rc)
{
+ ASSUAN_CONTEXT ctx = entry_ctx;
+
#ifdef USE_GNU_PTH
if (!pth_mutex_release (&entry_lock))
{
@@ -67,6 +73,8 @@ unlock_pinentry (int rc)
rc = GNUPG_Internal_Error;
}
#endif
+ entry_ctx = NULL;
+ assuan_disconnect (ctx);
return rc;
}
@@ -75,7 +83,7 @@ unlock_pinentry (int rc)
pinentry - we will serialize _all_ pinentry calls.
*/
static int
-start_pinentry (void)
+start_pinentry (CTRL ctrl)
{
int rc;
const char *pgmname;
@@ -96,7 +104,7 @@ start_pinentry (void)
return 0;
if (opt.verbose)
- log_info ("no running PIN Entry - starting it\n");
+ log_info ("starting a new PIN Entry\n");
if (fflush (NULL))
{
@@ -111,12 +119,11 @@ start_pinentry (void)
else
pgmname++;
- /* FIXME: We must do this thread specific */
argv[0] = pgmname;
- if (opt.display && !opt.keep_display)
+ if (ctrl->display && !opt.keep_display)
{
argv[1] = "--display";
- argv[2] = opt.display;
+ argv[2] = ctrl->display;
argv[3] = NULL;
}
else
@@ -150,10 +157,10 @@ start_pinentry (void)
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (map_assuan_err (rc));
- if (opt.ttyname && !opt.keep_tty)
+ if (ctrl->ttyname)
{
char *optstr;
- if (asprintf (&optstr, "OPTION ttyname=%s", opt.ttyname) < 0 )
+ if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 )
return unlock_pinentry (GNUPG_Out_Of_Core);
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
@@ -161,30 +168,30 @@ start_pinentry (void)
if (rc)
return unlock_pinentry (map_assuan_err (rc));
}
- if (opt.ttytype && !opt.keep_tty)
+ if (ctrl->ttytype)
{
char *optstr;
- if (asprintf (&optstr, "OPTION ttytype=%s", opt.ttytype) < 0 )
+ if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 )
return unlock_pinentry (GNUPG_Out_Of_Core);
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
if (rc)
return unlock_pinentry (map_assuan_err (rc));
}
- if (opt.lc_ctype)
+ if (ctrl->lc_ctype)
{
char *optstr;
- if (asprintf (&optstr, "OPTION lc-ctype=%s", opt.lc_ctype) < 0 )
+ if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
return unlock_pinentry (GNUPG_Out_Of_Core);
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
if (rc)
return unlock_pinentry (map_assuan_err (rc));
}
- if (opt.lc_messages)
+ if (ctrl->lc_messages)
{
char *optstr;
- if (asprintf (&optstr, "OPTION lc-messages=%s", opt.lc_messages) < 0 )
+ if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
return unlock_pinentry (GNUPG_Out_Of_Core);
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
@@ -230,7 +237,8 @@ all_digitsp( const char *s)
number here and repeat it as long as we have invalid formed
numbers. */
int
-agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo)
+agent_askpin (CTRL ctrl,
+ const char *desc_text, struct pin_entry_info_s *pininfo)
{
int rc;
char line[ASSUAN_LINELENGTH];
@@ -252,7 +260,7 @@ agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo)
is_pin = desc_text && strstr (desc_text, "PIN");
- rc = start_pinentry ();
+ rc = start_pinentry (ctrl);
if (rc)
return rc;
@@ -335,7 +343,8 @@ agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo)
passphrase is returned in RETPASS as an hex encoded string to be
freed by the caller */
int
-agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
+agent_get_passphrase (CTRL ctrl,
+ char **retpass, const char *desc, const char *prompt,
const char *errtext)
{
@@ -349,7 +358,7 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
if (opt.batch)
return GNUPG_Bad_Passphrase;
- rc = start_pinentry ();
+ rc = start_pinentry (ctrl);
if (rc)
return rc;
@@ -417,12 +426,13 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
confirmed it, GNUPG_Not_Confirmed for what the text says or an
other error. */
int
-agent_get_confirmation (const char *desc, const char *ok, const char *cancel)
+agent_get_confirmation (CTRL ctrl,
+ const char *desc, const char *ok, const char *cancel)
{
int rc;
char line[ASSUAN_LINELENGTH];
- rc = start_pinentry ();
+ rc = start_pinentry (ctrl);
if (rc)
return rc;
diff --git a/agent/simple-pwquery.c b/agent/simple-pwquery.c
index 5bb08afec..afdc4e2a4 100644
--- a/agent/simple-pwquery.c
+++ b/agent/simple-pwquery.c
@@ -177,9 +177,10 @@ agent_send_all_options (int fd)
return rc;
}
- if (ttyname (1))
- dft_ttyname = ttyname (1);
- if (dft_ttyname)
+ dft_ttyname = getenv ("GPG_TTY");
+ if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
+ dft_ttyname = ttyname (0);
+ if (dft_ttyname && *dft_ttyname)
{
if ((rc=agent_send_option (fd, "ttyname", dft_ttyname)))
return rc;
diff --git a/agent/trustlist.c b/agent/trustlist.c
index b6545f7de..9fc4623c6 100644
--- a/agent/trustlist.c
+++ b/agent/trustlist.c
@@ -228,7 +228,7 @@ agent_listtrusted (void *assuan_context)
whether this is actual wants he want to do.
*/
int
-agent_marktrusted (const char *name, const char *fpr, int flag)
+agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag)
{
int rc;
static char key[41];
@@ -254,7 +254,7 @@ agent_marktrusted (const char *name, const char *fpr, int flag)
"has the fingerprint:%%0A"
" %s", name, fpr) < 0 )
return GNUPG_Out_Of_Core;
- rc = agent_get_confirmation (desc, "Correct", "No");
+ rc = agent_get_confirmation (ctrl, desc, "Correct", "No");
free (desc);
if (rc)
return rc;
@@ -265,7 +265,7 @@ agent_marktrusted (const char *name, const char *fpr, int flag)
"to correctly certify user certificates?",
name) < 0 )
return GNUPG_Out_Of_Core;
- rc = agent_get_confirmation (desc, "Yes", "No");
+ rc = agent_get_confirmation (ctrl, desc, "Yes", "No");
free (desc);
if (rc)
return rc;