summaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2009-07-07 12:02:41 +0200
committerWerner Koch <wk@gnupg.org>2009-07-07 12:02:41 +0200
commitf6f5430e5014f90b685420447dffe89b220e2663 (patch)
tree0a8c28fc24f291bbc3a148f7240d1c49421f9077 /agent
parent* debugging.texi (Common Problems): Add a note about corrupted (diff)
downloadgnupg2-f6f5430e5014f90b685420447dffe89b220e2663.tar.xz
gnupg2-f6f5430e5014f90b685420447dffe89b220e2663.zip
Reworked passing of envars to Pinentry.
Diffstat (limited to 'agent')
-rw-r--r--agent/ChangeLog18
-rw-r--r--agent/agent.h14
-rw-r--r--agent/call-pinentry.c41
-rw-r--r--agent/command-ssh.c44
-rw-r--r--agent/command.c117
-rw-r--r--agent/gpg-agent.c120
-rw-r--r--agent/protect-tool.c2
7 files changed, 211 insertions, 145 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog
index 4829ff2d4..d0c1a7f45 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,3 +1,21 @@
+2009-07-06 Werner Koch <wk@g10code.com>
+
+ * agent.h: Include session-env.h.
+ (opt): Replace most of the startup_xxx fields by a session_env_t.
+ (struct server_control_s): Likewise.
+ * gpg-agent.c (main): Rewrite setting of the startup fields.
+ (handle_connections, main): Allocate SESSION_ENV.
+ (agent_init_default_ctrl, agent_deinit_default_ctrl): Change
+ accordingly.
+ * command.c (option_handler): Ditto.
+ (cmd_updatestartuptty): Change accordingly. Protect old values
+ from out of core failures.
+ * command-ssh.c (start_command_handler_ssh): Ditto.
+ (start_command_handler_ssh): Replace strdup by xtrystrdup.
+ * call-pinentry.c (atfork_cb): Pass new envrinmnet variables.
+ (start_pinentry): Use session_env stuff.
+ * protect-tool.c (main): Adjust call to gnupg_prepare_get_passphrase.
+
2009-06-24 Werner Koch <wk@g10code.com>
* genkey.c (agent_protect_and_store): Return RC and not 0.
diff --git a/agent/agent.h b/agent/agent.h
index 323c1c123..c7d8e02dd 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -33,6 +33,7 @@
#include "../common/util.h"
#include "../common/membuf.h"
#include "../common/sysutils.h" /* (gnupg_fd_t) */
+#include "../common/session-env.h"
/* To convey some special hash algorithms we use algorithm numbers
reserved for application use. */
@@ -56,13 +57,9 @@ struct
/* Environment setting gathered at program start or changed using the
Assuan command UPDATESTARTUPTTY. */
- char *startup_display;
- char *startup_ttyname;
- char *startup_ttytype;
+ session_env_t startup_env;
char *startup_lc_ctype;
char *startup_lc_messages;
- char *startup_xauthority;
- char *startup_pinentry_user_data;
const char *pinentry_program; /* Filename of the program to start as
@@ -142,13 +139,10 @@ struct server_control_s
/* Private data of the SCdaemon (call-scd.c). */
struct scd_local_s *scd_local;
- char *display;
- char *ttyname;
- char *ttytype;
+ session_env_t session_env;
char *lc_ctype;
char *lc_messages;
- char *xauthority;
- char *pinentry_user_data;
+
struct {
int algo;
unsigned char value[MAX_DIGEST_LEN];
diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c
index b956ef463..5e9685f61 100644
--- a/agent/call-pinentry.c
+++ b/agent/call-pinentry.c
@@ -172,14 +172,30 @@ atfork_cb (void *opaque, int where)
if (!where)
{
+ int iterator = 0;
+ const char *name, *assname, *value;
+
gcry_control (GCRYCTL_TERM_SECMEM);
- if (ctrl->xauthority)
- setenv ("XAUTHORITY", ctrl->xauthority, 1);
- if (ctrl->pinentry_user_data)
- setenv ("PINENTRY_USER_DATA", ctrl->pinentry_user_data, 1 );
+
+ while ((name = session_env_list_stdenvnames (&iterator, &assname)))
+ {
+ /* For all new envvars (!ASSNAME) and the two medium old
+ ones which do have an assuan name but are conveyed using
+ environment variables, update the environment of the
+ forked process. */
+ if (!assname
+ || !strcmp (name, "XAUTHORITY")
+ || !strcmp (name, "PINENTRY_USER_DATA"))
+ {
+ value = session_env_getenv (ctrl->session_env, name);
+ if (value)
+ setenv (name, value, 1);
+ }
+ }
}
}
+
static int
getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
{
@@ -214,6 +230,7 @@ start_pinentry (ctrl_t ctrl)
pth_event_t evt;
const char *tmpstr;
unsigned long pinentry_pid;
+ const char *value;
evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
if (!pth_mutex_acquire (&entry_lock, 0, evt))
@@ -273,10 +290,11 @@ start_pinentry (ctrl_t ctrl)
argv[0] = pgmname;
#endif /*__APPLE__*/
- if (ctrl->display && !opt.keep_display)
+ if (!opt.keep_display
+ && (value = session_env_getenv (ctrl->session_env, "DISPLAY")))
{
argv[1] = "--display";
- argv[2] = ctrl->display;
+ argv[2] = value;
argv[3] = NULL;
}
else
@@ -313,10 +331,12 @@ start_pinentry (ctrl_t ctrl)
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
- if (ctrl->ttyname)
+
+ value = session_env_getenv (ctrl->session_env, "GPG_TTY");
+ if (value)
{
char *optstr;
- if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 )
+ if (asprintf (&optstr, "OPTION ttyname=%s", value) < 0 )
return unlock_pinentry (out_of_core ());
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
@@ -324,10 +344,11 @@ start_pinentry (ctrl_t ctrl)
if (rc)
return unlock_pinentry (rc);
}
- if (ctrl->ttytype)
+ value = session_env_getenv (ctrl->session_env, "TERM");
+ if (value)
{
char *optstr;
- if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 )
+ if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 )
return unlock_pinentry (out_of_core ());
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index 76f310a33..12fe60a15 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -2906,27 +2906,39 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
void
start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
{
- estream_t stream_sock;
- gpg_error_t err;
+ estream_t stream_sock = NULL;
+ gpg_error_t err = 0;
int ret;
/* Because the ssh protocol does not send us information about the
the current TTY setting, we resort here to use those from startup
or those explictly set. */
- if (!ctrl->display && opt.startup_display)
- ctrl->display = strdup (opt.startup_display);
- if (!ctrl->ttyname && opt.startup_ttyname)
- ctrl->ttyname = strdup (opt.startup_ttyname);
- if (!ctrl->ttytype && opt.startup_ttytype)
- ctrl->ttytype = strdup (opt.startup_ttytype);
- if (!ctrl->lc_ctype && opt.startup_lc_ctype)
- ctrl->lc_ctype = strdup (opt.startup_lc_ctype);
- if (!ctrl->lc_messages && opt.startup_lc_messages)
- ctrl->lc_messages = strdup (opt.startup_lc_messages);
- if (!ctrl->xauthority && opt.startup_xauthority)
- ctrl->xauthority = strdup (opt.startup_xauthority);
- if (!ctrl->pinentry_user_data && opt.startup_pinentry_user_data)
- ctrl->pinentry_user_data = strdup (opt.startup_pinentry_user_data);
+ {
+ static const char *names[] =
+ {"GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL};
+ int idx;
+ const char *value;
+
+ for (idx=0; !err && names[idx]; idx++)
+ if (!session_env_getenv (ctrl->session_env, names[idx])
+ && (value = session_env_getenv (opt.startup_env, names[idx])))
+ err = session_env_setenv (ctrl->session_env, names[idx], value);
+
+ if (!err && !ctrl->lc_ctype && opt.startup_lc_ctype)
+ if (!(ctrl->lc_ctype = xtrystrdup (opt.startup_lc_ctype)))
+ err = gpg_error_from_syserror ();
+
+ if (!err && !ctrl->lc_messages && opt.startup_lc_messages)
+ if (!(ctrl->lc_messages = xtrystrdup (opt.startup_lc_messages)))
+ err = gpg_error_from_syserror ();
+
+ if (err)
+ {
+ log_error ("error setting default session environment: %s\n",
+ gpg_strerror (err));
+ goto out;
+ }
+ }
/* Create stream from socket. */
diff --git a/agent/command.c b/agent/command.c
index 9238a2219..e3de085dd 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -1520,33 +1520,53 @@ cmd_putval (assuan_context_t ctx, char *line)
static int
cmd_updatestartuptty (assuan_context_t ctx, char *line)
{
+ static const char *names[] =
+ { "GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL };
ctrl_t ctrl = assuan_get_pointer (ctx);
-
+ gpg_error_t err = 0;
+ session_env_t se;
+ int idx;
+ char *lc_ctype = NULL;
+ char *lc_messages = NULL;
+
(void)line;
- xfree (opt.startup_display); opt.startup_display = NULL;
- xfree (opt.startup_ttyname); opt.startup_ttyname = NULL;
- xfree (opt.startup_ttytype); opt.startup_ttytype = NULL;
- xfree (opt.startup_lc_ctype); opt.startup_lc_ctype = NULL;
- xfree (opt.startup_lc_messages); opt.startup_lc_messages = NULL;
- xfree (opt.startup_xauthority); opt.startup_xauthority = NULL;
-
- if (ctrl->display)
- opt.startup_display = xtrystrdup (ctrl->display);
- if (ctrl->ttyname)
- opt.startup_ttyname = xtrystrdup (ctrl->ttyname);
- if (ctrl->ttytype)
- opt.startup_ttytype = xtrystrdup (ctrl->ttytype);
- if (ctrl->lc_ctype)
- opt.startup_lc_ctype = xtrystrdup (ctrl->lc_ctype);
- if (ctrl->lc_messages)
- opt.startup_lc_messages = xtrystrdup (ctrl->lc_messages);
- if (ctrl->xauthority)
- opt.startup_xauthority = xtrystrdup (ctrl->xauthority);
- if (ctrl->pinentry_user_data)
- opt.startup_pinentry_user_data = xtrystrdup (ctrl->pinentry_user_data);
+ se = session_env_new ();
+ if (!se)
+ err = gpg_error_from_syserror ();
- return 0;
+ for (idx=0; !err && names[idx]; idx++)
+ {
+ const char *value = session_env_getenv (ctrl->session_env, names[idx]);
+ if (value)
+ err = session_env_setenv (se, names[idx], value);
+ }
+
+ if (!err && ctrl->lc_ctype)
+ if (!(lc_ctype = xtrystrdup (ctrl->lc_ctype)))
+ err = gpg_error_from_syserror ();
+
+ if (!err && ctrl->lc_messages)
+ if (!(lc_messages = xtrystrdup (ctrl->lc_messages)))
+ err = gpg_error_from_syserror ();
+
+ if (err)
+ {
+ session_env_release (se);
+ xfree (lc_ctype);
+ xfree (lc_messages);
+ }
+ else
+ {
+ session_env_release (opt.startup_env);
+ opt.startup_env = se;
+ xfree (opt.startup_lc_ctype);
+ opt.startup_lc_ctype = lc_ctype;
+ xfree (opt.startup_lc_messages);
+ opt.startup_lc_messages = lc_messages;
+ }
+
+ return err;
}
@@ -1680,36 +1700,31 @@ static int
option_handler (assuan_context_t ctx, const char *key, const char *value)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
+ gpg_error_t err = 0;
- if (!strcmp (key, "display"))
+ if (!strcmp (key, "putenv"))
{
- if (ctrl->display)
- xfree (ctrl->display);
- ctrl->display = xtrystrdup (value);
- if (!ctrl->display)
- return out_of_core ();
+ /* Change the session's environment to be used for the
+ Pinentry. Valid values are:
+ <NAME> Delete envvar NAME
+ <KEY>= Set envvar NAME to the empty string
+ <KEY>=<VALUE> Set envvar NAME to VALUE
+ */
+ err = session_env_putenv (ctrl->session_env, value);
+ }
+ else if (!strcmp (key, "display"))
+ {
+ err = session_env_setenv (ctrl->session_env, "DISPLAY", value);
}
else if (!strcmp (key, "ttyname"))
{
if (!opt.keep_tty)
- {
- if (ctrl->ttyname)
- xfree (ctrl->ttyname);
- ctrl->ttyname = xtrystrdup (value);
- if (!ctrl->ttyname)
- return out_of_core ();
- }
+ err = session_env_setenv (ctrl->session_env, "GPG_TTY", value);
}
else if (!strcmp (key, "ttytype"))
{
if (!opt.keep_tty)
- {
- if (ctrl->ttytype)
- xfree (ctrl->ttytype);
- ctrl->ttytype = xtrystrdup (value);
- if (!ctrl->ttytype)
- return out_of_core ();
- }
+ err = session_env_setenv (ctrl->session_env, "TERM", value);
}
else if (!strcmp (key, "lc-ctype"))
{
@@ -1729,28 +1744,20 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
}
else if (!strcmp (key, "xauthority"))
{
- if (ctrl->xauthority)
- xfree (ctrl->xauthority);
- ctrl->xauthority = xtrystrdup (value);
- if (!ctrl->xauthority)
- return out_of_core ();
+ err = session_env_setenv (ctrl->session_env, "XAUTHORITY", value);
}
else if (!strcmp (key, "pinentry-user-data"))
{
- if (ctrl->pinentry_user_data)
- xfree (ctrl->pinentry_user_data);
- ctrl->pinentry_user_data = xtrystrdup (value);
- if (!ctrl->pinentry_user_data)
- return out_of_core ();
+ err = session_env_setenv (ctrl->session_env, "PINENTRY_USER_DATA", value);
}
else if (!strcmp (key, "use-cache-for-signing"))
ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
else if (!strcmp (key, "allow-pinentry-notify"))
ctrl->server_local->allow_pinentry_notify = 1;
else
- return gpg_error (GPG_ERR_UNKNOWN_OPTION);
+ err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
- return 0;
+ return err;
}
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index eccf44539..31d79d508 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -609,28 +609,40 @@ main (int argc, char **argv )
opt.homedir = default_homedir ();
/* Record some of the original environment strings. */
- opt.startup_display = getenv ("DISPLAY");
- if (opt.startup_display)
- opt.startup_display = xstrdup (opt.startup_display);
- opt.startup_ttyname = ttyname (0);
- if (opt.startup_ttyname)
- opt.startup_ttyname = xstrdup (opt.startup_ttyname);
- opt.startup_ttytype = getenv ("TERM");
- if (opt.startup_ttytype)
- opt.startup_ttytype = xstrdup (opt.startup_ttytype);
- /* Fixme: Better use the locale function here. */
- opt.startup_lc_ctype = getenv ("LC_CTYPE");
- if (opt.startup_lc_ctype)
- opt.startup_lc_ctype = xstrdup (opt.startup_lc_ctype);
- opt.startup_lc_messages = getenv ("LC_MESSAGES");
- if (opt.startup_lc_messages)
- opt.startup_lc_messages = xstrdup (opt.startup_lc_messages);
- opt.startup_xauthority = getenv ("XAUTHORITY");
- if (opt.startup_xauthority)
- opt.startup_xauthority = xstrdup (opt.startup_xauthority);
- opt.startup_pinentry_user_data = getenv ("PINENTRY_USER_DATA");
- if (opt.startup_pinentry_user_data)
- opt.startup_pinentry_user_data = xstrdup (opt.startup_pinentry_user_data);
+ {
+ const char *s;
+ int idx;
+ static const char *names[] =
+ { "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL };
+
+ err = 0;
+ opt.startup_env = session_env_new ();
+ if (!opt.startup_env)
+ err = gpg_error_from_syserror ();
+ for (idx=0; !err && names[idx]; idx++)
+ {
+ s = getenv (names[idx]);
+ if (s)
+ err = session_env_setenv (opt.startup_env, names[idx], s);
+ }
+ if (!err)
+ {
+ s = ttyname (0);
+ if (s)
+ err = session_env_setenv (opt.startup_env, "GPG_TTY", s);
+ }
+ if (err)
+ log_fatal ("error recording startup environment: %s\n",
+ gpg_strerror (err));
+
+ /* Fixme: Better use the locale function here. */
+ opt.startup_lc_ctype = getenv ("LC_CTYPE");
+ if (opt.startup_lc_ctype)
+ opt.startup_lc_ctype = xstrdup (opt.startup_lc_ctype);
+ opt.startup_lc_messages = getenv ("LC_MESSAGES");
+ if (opt.startup_lc_messages)
+ opt.startup_lc_messages = xstrdup (opt.startup_lc_messages);
+ }
/* Check whether we have a config file on the commandline */
orig_argc = argc;
@@ -924,6 +936,14 @@ main (int argc, char **argv )
strerror (errno) );
agent_exit (1);
}
+ ctrl->session_env = session_env_new ();
+ if (!ctrl->session_env)
+ {
+ log_error ("error allocating session environment block: %s\n",
+ strerror (errno) );
+ xfree (ctrl);
+ agent_exit (1);
+ }
agent_init_default_ctrl (ctrl);
start_command_handler (ctrl, GNUPG_INVALID_FD, GNUPG_INVALID_FD);
agent_deinit_default_ctrl (ctrl);
@@ -1218,63 +1238,43 @@ agent_exit (int rc)
exit (rc);
}
+
static void
agent_init_default_ctrl (ctrl_t 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)
- xfree (ctrl->display);
- ctrl->display = default_display? xtrystrdup (default_display) : NULL;
-
- if (ctrl->ttyname)
- xfree (ctrl->ttyname);
- ctrl->ttyname = default_ttyname? xtrystrdup (default_ttyname) : NULL;
-
- if (ctrl->ttytype)
- xfree (ctrl->ttytype);
- ctrl->ttytype = default_ttytype? xtrystrdup (default_ttytype) : NULL;
-
+ session_env_setenv (ctrl->session_env, "DISPLAY", default_display);
+ session_env_setenv (ctrl->session_env, "GPG_TTY", default_ttyname);
+ session_env_setenv (ctrl->session_env, "TERM", default_ttytype);
+ session_env_setenv (ctrl->session_env, "XAUTHORITY", default_xauthority);
+ session_env_setenv (ctrl->session_env, "PINENTRY_USER_DATA", NULL);
+
if (ctrl->lc_ctype)
xfree (ctrl->lc_ctype);
ctrl->lc_ctype = default_lc_ctype? xtrystrdup (default_lc_ctype) : NULL;
-
+
if (ctrl->lc_messages)
xfree (ctrl->lc_messages);
ctrl->lc_messages = default_lc_messages? xtrystrdup (default_lc_messages)
/**/ : NULL;
- if (ctrl->xauthority)
- xfree (ctrl->xauthority);
- ctrl->xauthority = default_xauthority? xtrystrdup (default_xauthority)
- /**/: NULL;
-
- if (ctrl->pinentry_user_data)
- xfree (ctrl->pinentry_user_data);
- ctrl->pinentry_user_data = NULL;
}
static void
agent_deinit_default_ctrl (ctrl_t ctrl)
{
- if (ctrl->display)
- xfree (ctrl->display);
- if (ctrl->ttyname)
- xfree (ctrl->ttyname);
- if (ctrl->ttytype)
- xfree (ctrl->ttytype);
+ session_env_release (ctrl->session_env);
+
if (ctrl->lc_ctype)
xfree (ctrl->lc_ctype);
if (ctrl->lc_messages)
xfree (ctrl->lc_messages);
- if (ctrl->xauthority)
- xfree (ctrl->xauthority);
- if (ctrl->pinentry_user_data)
- xfree (ctrl->pinentry_user_data);
}
+
/* Reread parts of the configuration. Note, that this function is
obviously not thread-safe and should only be called from the PTH
signal handler.
@@ -1961,6 +1961,13 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
strerror (errno) );
assuan_sock_close (fd);
}
+ else if ( !(ctrl->session_env = session_env_new ()) )
+ {
+ log_error ("error allocating session environment block: %s\n",
+ strerror (errno) );
+ xfree (ctrl);
+ assuan_sock_close (fd);
+ }
else
{
char threadname[50];
@@ -1999,6 +2006,13 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
strerror (errno) );
assuan_sock_close (fd);
}
+ else if ( !(ctrl->session_env = session_env_new ()) )
+ {
+ log_error ("error allocating session environment block: %s\n",
+ strerror (errno) );
+ xfree (ctrl);
+ assuan_sock_close (fd);
+ }
else
{
char threadname[50];
diff --git a/agent/protect-tool.c b/agent/protect-tool.c
index 0e48124d8..27f4f9d0a 100644
--- a/agent/protect-tool.c
+++ b/agent/protect-tool.c
@@ -1086,7 +1086,7 @@ main (int argc, char **argv )
opt.verbose,
opt_homedir,
opt_agent_program,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
if (opt_prompt)
opt_prompt = percent_plus_unescape (opt_prompt, 0);