1 /* asshelp.c - Helper functions for Assuan
2 * Copyright (C) 2002, 2004, 2007 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/>.
39 send_one_option (assuan_context_t ctx
, gpg_err_source_t errsource
,
40 const char *name
, const char *value
)
47 if (!value
|| !*value
)
48 err
= 0; /* Avoid sending empty strings. */
49 else if (asprintf (&optstr
, "OPTION %s=%s", 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_display
,
68 const char *opt_ttyname
,
69 const char *opt_ttytype
,
70 const char *opt_lc_ctype
,
71 const char *opt_lc_messages
,
72 const char *opt_xauthority
,
73 const char *opt_pinentry_user_data
)
76 char *dft_display
= NULL
;
77 char *dft_ttyname
= NULL
;
78 char *dft_ttytype
= NULL
;
81 char *dft_xauthority
= NULL
;
82 char *dft_pinentry_user_data
= NULL
;
84 /* Send the DISPLAY variable. */
85 dft_display
= getenv ("DISPLAY");
86 if (opt_display
|| dft_display
)
88 err
= send_one_option (ctx
, errsource
, "display",
89 opt_display
? opt_display
: dft_display
);
94 /* Send the name of the TTY. */
97 dft_ttyname
= getenv ("GPG_TTY");
98 if ((!dft_ttyname
|| !*dft_ttyname
) && ttyname (0))
99 dft_ttyname
= ttyname (0);
101 if (opt_ttyname
|| dft_ttyname
)
103 err
= send_one_option (ctx
, errsource
, "ttyname",
104 opt_ttyname
? opt_ttyname
: dft_ttyname
);
109 /* Send the type of the TTY. */
110 dft_ttytype
= getenv ("TERM");
111 if (opt_ttytype
|| (dft_ttyname
&& dft_ttytype
))
113 err
= send_one_option (ctx
, errsource
, "ttytype",
114 opt_ttyname
? opt_ttytype
: dft_ttytype
);
119 /* Send the value for LC_CTYPE. */
120 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
121 old_lc
= setlocale (LC_CTYPE
, NULL
);
124 old_lc
= xtrystrdup (old_lc
);
126 return gpg_error_from_syserror ();
128 dft_lc
= setlocale (LC_CTYPE
, "");
130 if (opt_lc_ctype
|| (dft_ttyname
&& dft_lc
))
132 err
= send_one_option (ctx
, errsource
, "lc-ctype",
133 opt_lc_ctype
? opt_lc_ctype
: dft_lc
);
135 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
138 setlocale (LC_CTYPE
, old_lc
);
145 /* Send the value for LC_MESSAGES. */
146 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
147 old_lc
= setlocale (LC_MESSAGES
, NULL
);
150 old_lc
= xtrystrdup (old_lc
);
152 return gpg_error_from_syserror ();
154 dft_lc
= setlocale (LC_MESSAGES
, "");
156 if (opt_lc_messages
|| (dft_ttyname
&& dft_lc
))
158 err
= send_one_option (ctx
, errsource
, "lc-messages",
159 opt_lc_messages
? opt_lc_messages
: dft_lc
);
161 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
164 setlocale (LC_MESSAGES
, old_lc
);
171 /* Send the XAUTHORITY variable. */
172 dft_xauthority
= getenv ("XAUTHORITY");
173 if (opt_xauthority
|| dft_xauthority
)
175 err
= send_one_option (ctx
, errsource
, "xauthority",
176 opt_xauthority
? opt_xauthority
: dft_xauthority
);
177 if (gpg_err_code (err
) == GPG_ERR_UNKNOWN_OPTION
)
183 /* Send the PINENTRY_USER_DATA variable. */
184 dft_pinentry_user_data
= getenv ("PINENTRY_USER_DATA");
185 if (opt_pinentry_user_data
|| dft_pinentry_user_data
)
187 err
= send_one_option (ctx
, errsource
, "pinentry-user-data",
188 opt_pinentry_user_data
?
189 opt_pinentry_user_data
: dft_pinentry_user_data
);
190 if (gpg_err_code (err
) == GPG_ERR_UNKNOWN_OPTION
)
200 /* Try to connect to the agent via socket or fork it off and work by
201 pipes. Handle the server's initial greeting. Returns a new assuan
202 context at R_CTX or an error code. */
204 start_new_gpg_agent (assuan_context_t
*r_ctx
,
205 gpg_err_source_t errsource
,
207 const char *agent_program
,
208 const char *opt_display
,
209 const char *opt_ttyname
,
210 const char *opt_ttytype
,
211 const char *opt_lc_ctype
,
212 const char *opt_lc_messages
,
213 const char *opt_xauthority
,
214 const char *opt_pinentry_user_data
,
215 int verbose
, int debug
,
216 gpg_error_t (*status_cb
)(ctrl_t
, int, ...),
217 ctrl_t status_cb_arg
)
219 /* If we ever failed to connect via a socket we will force the use
220 of the pipe based server for the lifetime of the process. */
221 static int force_pipe_server
= 0;
225 assuan_context_t ctx
;
230 infostr
= force_pipe_server
? NULL
: getenv ("GPG_AGENT_INFO");
231 if (!infostr
|| !*infostr
)
235 /* First check whether we can connect at the standard
237 sockname
= make_filename (homedir
, "S.gpg-agent", NULL
);
238 rc
= assuan_socket_connect (&ctx
, sockname
, 0);
242 /* With no success start a new server. */
244 log_info (_("no running gpg-agent - starting one\n"));
247 status_cb (status_cb_arg
, STATUS_PROGRESS
,
248 "starting_agent ? 0 0", NULL
);
252 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
253 log_error ("error flushing pending output: %s\n",
259 if (!agent_program
|| !*agent_program
)
260 agent_program
= gnupg_module_name (GNUPG_MODULE_NAME_AGENT
);
262 #ifdef HAVE_W32_SYSTEM
264 /* Under Windows we start the server in daemon mode. This
265 is because the default is to use the standard socket
266 and thus there is no need for the GPG_AGENT_INFO
267 envvar. This is possible as we don't have a real unix
268 domain socket but use a plain file and thus there is no
269 need to care about non-local file systems. */
272 argv
[0] = "--daemon";
273 argv
[1] = "--use-standard-socket";
276 rc
= gnupg_spawn_process_detached (agent_program
, argv
, NULL
);
278 log_debug ("failed to start agent `%s': %s\n",
279 agent_program
, gpg_strerror (rc
));
282 /* Give the agent some time to prepare itself. */
284 /* Now try again to connect the agent. */
285 rc
= assuan_socket_connect (&ctx
, sockname
, 0);
288 #else /*!HAVE_W32_SYSTEM*/
292 int no_close_list
[3];
295 if ( !(pgmname
= strrchr (agent_program
, '/')))
296 pgmname
= agent_program
;
301 argv
[1] = "--server";
305 if (log_get_fd () != -1)
306 no_close_list
[i
++] = log_get_fd ();
307 no_close_list
[i
++] = fileno (stderr
);
308 no_close_list
[i
] = -1;
310 /* Connect to the agent and perform initial handshaking. */
311 rc
= assuan_pipe_connect (&ctx
, agent_program
, argv
,
314 #endif /*!HAVE_W32_SYSTEM*/
323 infostr
= xstrdup (infostr
);
324 if ( !(p
= strchr (infostr
, PATHSEP_C
)) || p
== infostr
)
326 log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
328 force_pipe_server
= 1;
333 while (*p
&& *p
!= PATHSEP_C
)
335 prot
= *p
? atoi (p
+1) : 0;
338 log_error (_("gpg-agent protocol version %d is not supported\n"),
341 force_pipe_server
= 1;
345 rc
= assuan_socket_connect (&ctx
, infostr
, pid
);
347 if (gpg_err_code (rc
) == GPG_ERR_ASS_CONNECT_FAILED
)
349 log_info (_("can't connect to the agent - trying fall back\n"));
350 force_pipe_server
= 1;
357 log_error ("can't connect to the agent: %s\n", gpg_strerror (rc
));
358 return gpg_error (GPG_ERR_NO_AGENT
);
362 log_debug ("connection to agent established\n");
364 rc
= assuan_transact (ctx
, "RESET",
365 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
367 rc
= send_pinentry_environment (ctx
, errsource
,
368 opt_display
, opt_ttyname
, opt_ttytype
,
369 opt_lc_ctype
, opt_lc_messages
,
371 opt_pinentry_user_data
);
374 assuan_disconnect (ctx
);