diff options
author | Werner Koch <wk@gnupg.org> | 2009-07-07 12:02:41 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2009-07-07 12:02:41 +0200 |
commit | f6f5430e5014f90b685420447dffe89b220e2663 (patch) | |
tree | 0a8c28fc24f291bbc3a148f7240d1c49421f9077 /agent | |
parent | * debugging.texi (Common Problems): Add a note about corrupted (diff) | |
download | gnupg2-f6f5430e5014f90b685420447dffe89b220e2663.tar.xz gnupg2-f6f5430e5014f90b685420447dffe89b220e2663.zip |
Reworked passing of envars to Pinentry.
Diffstat (limited to 'agent')
-rw-r--r-- | agent/ChangeLog | 18 | ||||
-rw-r--r-- | agent/agent.h | 14 | ||||
-rw-r--r-- | agent/call-pinentry.c | 41 | ||||
-rw-r--r-- | agent/command-ssh.c | 44 | ||||
-rw-r--r-- | agent/command.c | 117 | ||||
-rw-r--r-- | agent/gpg-agent.c | 120 | ||||
-rw-r--r-- | agent/protect-tool.c | 2 |
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); |