1 /* asshelp.c - Helper functions for Assuan
2 * Copyright (C) 2002, 2004, 2007, 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
38 send_one_option (assuan_context_t ctx
, gpg_err_source_t errsource
,
39 const char *name
, const char *value
, int use_putenv
)
46 if (!value
|| !*value
)
47 err
= 0; /* Avoid sending empty strings. */
48 else if (asprintf (&optstr
, "OPTION %s%s=%s",
49 use_putenv
? "putenv=":"", name
, value
) < 0)
50 err
= gpg_error_from_syserror ();
53 err
= assuan_transact (ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
61 /* Send the assuan commands pertaining to the pinentry environment. The
62 OPT_* arguments are optional and may be used to override the
63 defaults taken from the current locale. */
65 send_pinentry_environment (assuan_context_t ctx
,
66 gpg_err_source_t errsource
,
67 const char *opt_lc_ctype
,
68 const char *opt_lc_messages
,
69 session_env_t session_env
)
75 const char *dft_ttyname
;
77 const char *name
, *assname
, *value
;
81 while ((name
= session_env_list_stdenvnames (&iterator
, &assname
)))
83 value
= session_env_getenv_or_default (session_env
, name
, NULL
);
88 err
= send_one_option (ctx
, errsource
, assname
, value
, 0);
91 err
= send_one_option (ctx
, errsource
, name
, value
, 1);
92 if (gpg_err_code (err
) == GPG_ERR_UNKNOWN_OPTION
)
93 err
= 0; /* Server too old; can't pass the new envvars. */
100 dft_ttyname
= session_env_getenv_or_default (session_env
, "GPG_TTY",
102 if (dft_ttyname
&& !is_default
)
103 dft_ttyname
= NULL
; /* We need the default value. */
105 /* Send the value for LC_CTYPE. */
106 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
107 old_lc
= setlocale (LC_CTYPE
, NULL
);
110 old_lc
= xtrystrdup (old_lc
);
112 return gpg_error_from_syserror ();
114 dft_lc
= setlocale (LC_CTYPE
, "");
116 if (opt_lc_ctype
|| (dft_ttyname
&& dft_lc
))
118 err
= send_one_option (ctx
, errsource
, "lc-ctype",
119 opt_lc_ctype
? opt_lc_ctype
: dft_lc
, 0);
121 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
124 setlocale (LC_CTYPE
, old_lc
);
131 /* Send the value for LC_MESSAGES. */
132 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
133 old_lc
= setlocale (LC_MESSAGES
, NULL
);
136 old_lc
= xtrystrdup (old_lc
);
138 return gpg_error_from_syserror ();
140 dft_lc
= setlocale (LC_MESSAGES
, "");
142 if (opt_lc_messages
|| (dft_ttyname
&& dft_lc
))
144 err
= send_one_option (ctx
, errsource
, "lc-messages",
145 opt_lc_messages
? opt_lc_messages
: dft_lc
, 0);
147 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
150 setlocale (LC_MESSAGES
, old_lc
);
161 /* Try to connect to the agent via socket or fork it off and work by
162 pipes. Handle the server's initial greeting. Returns a new assuan
163 context at R_CTX or an error code. */
165 start_new_gpg_agent (assuan_context_t
*r_ctx
,
166 gpg_err_source_t errsource
,
168 const char *agent_program
,
169 const char *opt_lc_ctype
,
170 const char *opt_lc_messages
,
171 session_env_t session_env
,
172 int verbose
, int debug
,
173 gpg_error_t (*status_cb
)(ctrl_t
, int, ...),
174 ctrl_t status_cb_arg
)
176 /* If we ever failed to connect via a socket we will force the use
177 of the pipe based server for the lifetime of the process. */
178 static int force_pipe_server
= 0;
182 assuan_context_t ctx
;
186 rc
= assuan_new (&ctx
);
189 log_error ("error allocating assuan context: %s\n", gpg_strerror (rc
));
194 infostr
= force_pipe_server
? NULL
: getenv ("GPG_AGENT_INFO");
195 if (!infostr
|| !*infostr
)
199 /* First check whether we can connect at the standard
201 sockname
= make_filename (homedir
, "S.gpg-agent", NULL
);
202 rc
= assuan_socket_connect (ctx
, sockname
, 0);
206 /* With no success start a new server. */
208 log_info (_("no running gpg-agent - starting one\n"));
211 status_cb (status_cb_arg
, STATUS_PROGRESS
,
212 "starting_agent ? 0 0", NULL
);
216 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
217 log_error ("error flushing pending output: %s\n",
220 assuan_release (ctx
);
224 if (!agent_program
|| !*agent_program
)
225 agent_program
= gnupg_module_name (GNUPG_MODULE_NAME_AGENT
);
227 #ifdef HAVE_W32_SYSTEM
229 /* Under Windows we start the server in daemon mode. This
230 is because the default is to use the standard socket
231 and thus there is no need for the GPG_AGENT_INFO
232 envvar. This is possible as we don't have a real unix
233 domain socket but use a plain file and thus there is no
234 need to care about non-local file systems. */
237 argv
[0] = "--daemon";
238 argv
[1] = "--use-standard-socket";
241 rc
= gnupg_spawn_process_detached (agent_program
, argv
, NULL
);
243 log_debug ("failed to start agent `%s': %s\n",
244 agent_program
, gpg_strerror (rc
));
247 /* Give the agent some time to prepare itself. */
249 /* Now try again to connect the agent. */
250 rc
= assuan_socket_connect (ctx
, sockname
, 0);
253 #else /*!HAVE_W32_SYSTEM*/
257 int no_close_list
[3];
260 if ( !(pgmname
= strrchr (agent_program
, '/')))
261 pgmname
= agent_program
;
266 argv
[1] = "--server";
270 if (log_get_fd () != -1)
271 no_close_list
[i
++] = log_get_fd ();
272 no_close_list
[i
++] = fileno (stderr
);
273 no_close_list
[i
] = -1;
275 /* Connect to the agent and perform initial handshaking. */
276 rc
= assuan_pipe_connect (ctx
, agent_program
, argv
,
279 #endif /*!HAVE_W32_SYSTEM*/
288 infostr
= xstrdup (infostr
);
289 if ( !(p
= strchr (infostr
, PATHSEP_C
)) || p
== infostr
)
291 log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
293 force_pipe_server
= 1;
298 while (*p
&& *p
!= PATHSEP_C
)
300 prot
= *p
? atoi (p
+1) : 0;
303 log_error (_("gpg-agent protocol version %d is not supported\n"),
306 force_pipe_server
= 1;
310 rc
= assuan_socket_connect (ctx
, infostr
, pid
);
312 if (gpg_err_code (rc
) == GPG_ERR_ASS_CONNECT_FAILED
)
314 log_info (_("can't connect to the agent - trying fall back\n"));
315 force_pipe_server
= 1;
322 log_error ("can't connect to the agent: %s\n", gpg_strerror (rc
));
323 assuan_release (ctx
);
324 return gpg_error (GPG_ERR_NO_AGENT
);
328 log_debug ("connection to agent established\n");
330 rc
= assuan_transact (ctx
, "RESET",
331 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
333 rc
= send_pinentry_environment (ctx
, errsource
,
334 opt_lc_ctype
, opt_lc_messages
,
338 assuan_release (ctx
);