Fix gpg-preset-passphrase bug.
[gnupg.git] / common / asshelp.c
1 /* asshelp.c - Helper functions for Assuan
2  * Copyright (C) 2002, 2004, 2007 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #ifdef HAVE_LOCALE_H
27 #include <locale.h>
28 #endif
29
30 #include "i18n.h"
31 #include "util.h"
32 #include "exechelp.h"
33 #include "sysutils.h"
34 #include "status.h" 
35 #include "asshelp.h"
36
37
38 static gpg_error_t
39 send_one_option (assuan_context_t ctx, gpg_err_source_t errsource,
40                  const char *name, const char *value)
41 {
42   gpg_error_t err;
43   char *optstr;
44
45   if (!value || !*value)
46     err = 0;  /* Avoid sending empty strings.  */
47   else if (asprintf (&optstr, "OPTION %s=%s", name, value ) < 0)
48     err = gpg_error_from_syserror ();
49   else
50     {
51       err = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL);
52       xfree (optstr);
53     }
54
55   return err;
56 }
57
58
59 /* Send the assuan commands pertaining to the pinentry environment.  The
60    OPT_* arguments are optional and may be used to override the
61    defaults taken from the current locale. */
62 gpg_error_t
63 send_pinentry_environment (assuan_context_t ctx,
64                            gpg_err_source_t errsource,
65                            const char *opt_display,
66                            const char *opt_ttyname,
67                            const char *opt_ttytype,
68                            const char *opt_lc_ctype,
69                            const char *opt_lc_messages,
70                            const char *opt_xauthority,
71                            const char *opt_pinentry_user_data)
72 {
73   gpg_error_t err = 0;
74   char *dft_display = NULL;
75   char *dft_ttyname = NULL;
76   char *dft_ttytype = NULL;
77   char *old_lc = NULL; 
78   char *dft_lc = NULL;
79   char *dft_xauthority = NULL;
80   char *dft_pinentry_user_data = NULL;
81
82   /* Send the DISPLAY variable.  */
83   dft_display = getenv ("DISPLAY");
84   if (opt_display || dft_display)
85     {
86       err = send_one_option (ctx, errsource, "display", 
87                              opt_display ? opt_display : dft_display);
88       if (err)
89         return err;
90     }
91
92   /* Send the name of the TTY.  */
93   if (!opt_ttyname)
94     {
95       dft_ttyname = getenv ("GPG_TTY");
96       if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
97         dft_ttyname = ttyname (0);
98     }
99   if (opt_ttyname || dft_ttyname)
100     {
101       err = send_one_option (ctx, errsource, "ttyname", 
102                              opt_ttyname ? opt_ttyname : dft_ttyname);
103       if (err)
104         return err;
105     }
106
107   /* Send the type of the TTY.  */
108   dft_ttytype = getenv ("TERM");
109   if (opt_ttytype || (dft_ttyname && dft_ttytype))
110     {
111       err = send_one_option (ctx, errsource, "ttytype", 
112                              opt_ttyname ? opt_ttytype : dft_ttytype);
113       if (err)
114         return err;
115     }
116
117   /* Send the value for LC_CTYPE.  */
118 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
119   old_lc = setlocale (LC_CTYPE, NULL);
120   if (old_lc)
121     {
122       old_lc = xtrystrdup (old_lc);
123       if (!old_lc)
124         return gpg_error_from_syserror ();
125     }
126   dft_lc = setlocale (LC_CTYPE, "");
127 #endif
128   if (opt_lc_ctype || (dft_ttyname && dft_lc))
129     {
130       err = send_one_option (ctx, errsource, "lc-ctype", 
131                              opt_lc_ctype ? opt_lc_ctype : dft_lc);
132     }
133 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
134   if (old_lc)
135     {
136       setlocale (LC_CTYPE, old_lc);
137       xfree (old_lc);
138     }
139 #endif
140   if (err)
141     return err;
142
143   /* Send the value for LC_MESSAGES.  */
144 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
145   old_lc = setlocale (LC_MESSAGES, NULL);
146   if (old_lc)
147     {
148       old_lc = xtrystrdup (old_lc);
149       if (!old_lc)
150         return gpg_error_from_syserror ();
151     }
152   dft_lc = setlocale (LC_MESSAGES, "");
153 #endif
154   if (opt_lc_messages || (dft_ttyname && dft_lc))
155     {
156       err = send_one_option (ctx, errsource, "lc-messages", 
157                              opt_lc_messages ? opt_lc_messages : dft_lc);
158     }
159 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
160   if (old_lc)
161     {
162       setlocale (LC_MESSAGES, old_lc);
163       xfree (old_lc);
164     }
165 #endif
166   if (err)
167     return err;
168
169   /* Send the XAUTHORITY variable.  */
170   dft_xauthority = getenv ("XAUTHORITY");
171   if (opt_xauthority || dft_xauthority)
172     {
173       err = send_one_option (ctx, errsource, "xauthority", 
174                              opt_xauthority ? opt_xauthority : dft_xauthority);
175       if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
176         err = 0;
177       if (err)
178         return err;
179     }
180
181   /* Send the PINENTRY_USER_DATA variable.  */
182   dft_pinentry_user_data = getenv ("PINENTRY_USER_DATA");
183   if (opt_pinentry_user_data || dft_pinentry_user_data)
184     {
185       err = send_one_option (ctx, errsource, "pinentry-user-data", 
186                              opt_pinentry_user_data ?
187                              opt_pinentry_user_data : dft_pinentry_user_data);
188       if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
189         err = 0;
190       if (err)
191         return err;
192     }
193
194   return 0;
195 }
196
197
198 /* Try to connect to the agent via socket or fork it off and work by
199    pipes.  Handle the server's initial greeting.  Returns a new assuan
200    context at R_CTX or an error code. */
201 gpg_error_t
202 start_new_gpg_agent (assuan_context_t *r_ctx,
203                      gpg_err_source_t errsource,
204                      const char *homedir,
205                      const char *agent_program,
206                      const char *opt_display,
207                      const char *opt_ttyname,
208                      const char *opt_ttytype,
209                      const char *opt_lc_ctype,
210                      const char *opt_lc_messages,
211                      const char *opt_xauthority,
212                      const char *opt_pinentry_user_data,
213                      int verbose, int debug,
214                      gpg_error_t (*status_cb)(ctrl_t, int, ...),
215                      ctrl_t status_cb_arg)
216 {
217   /* If we ever failed to connect via a socket we will force the use
218      of the pipe based server for the lifetime of the process.  */
219   static int force_pipe_server = 0;
220
221   gpg_error_t rc = 0;
222   char *infostr, *p;
223   assuan_context_t ctx;
224
225   *r_ctx = NULL;
226
227  restart:
228   infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO");
229   if (!infostr || !*infostr)
230     {
231       char *sockname;
232
233       /* First check whether we can connect at the standard
234          socket.  */
235       sockname = make_filename (homedir, "S.gpg-agent", NULL);
236       rc = assuan_socket_connect (&ctx, sockname, 0);
237
238       if (rc)
239         {
240           /* With no success start a new server.  */
241           if (verbose)
242             log_info (_("no running gpg-agent - starting one\n"));
243           
244           if (status_cb)
245             status_cb (status_cb_arg, STATUS_PROGRESS, 
246                        "starting_agent ? 0 0", NULL);
247           
248           if (fflush (NULL))
249             {
250               gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
251               log_error ("error flushing pending output: %s\n",
252                          strerror (errno));
253               xfree (sockname);
254               return tmperr;
255             }
256           
257           if (!agent_program || !*agent_program)
258             agent_program = gnupg_module_name (GNUPG_MODULE_NAME_AGENT);
259
260 #ifdef HAVE_W32_SYSTEM
261           {
262             /* Under Windows we start the server in daemon mode.  This
263                is because the default is to use the standard socket
264                and thus there is no need for the GPG_AGENT_INFO
265                envvar.  This is possible as we don't have a real unix
266                domain socket but use a plain file and thus there is no
267                need to care about non-local file systems. */
268             const char *argv[3];
269
270             argv[0] = "--daemon";
271             argv[1] = "--use-standard-socket"; 
272             argv[2] = NULL;  
273
274             rc = gnupg_spawn_process_detached (agent_program, argv, NULL);
275             if (rc)
276               log_debug ("failed to start agent `%s': %s\n",
277                          agent_program, gpg_strerror (rc));
278             else
279               {
280                 /* Give the agent some time to prepare itself. */
281                 gnupg_sleep (3);
282                 /* Now try again to connect the agent.  */
283                 rc = assuan_socket_connect (&ctx, sockname, 0);
284               }
285           }
286 #else /*!HAVE_W32_SYSTEM*/
287           {
288             const char *pgmname;
289             const char *argv[3];
290             int no_close_list[3];
291             int i;
292
293             if ( !(pgmname = strrchr (agent_program, '/')))
294               pgmname = agent_program;
295             else
296               pgmname++;
297             
298             argv[0] = pgmname;
299             argv[1] = "--server";
300             argv[2] = NULL;
301             
302             i=0;
303             if (log_get_fd () != -1)
304               no_close_list[i++] = log_get_fd ();
305             no_close_list[i++] = fileno (stderr);
306             no_close_list[i] = -1;
307             
308             /* Connect to the agent and perform initial handshaking. */
309             rc = assuan_pipe_connect (&ctx, agent_program, argv,
310                                       no_close_list);
311           }
312 #endif /*!HAVE_W32_SYSTEM*/
313         }
314       xfree (sockname);
315     }
316   else
317     {
318       int prot;
319       int pid;
320
321       infostr = xstrdup (infostr);
322       if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
323         {
324           log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
325           xfree (infostr);
326           force_pipe_server = 1;
327           goto restart;
328         }
329       *p++ = 0;
330       pid = atoi (p);
331       while (*p && *p != PATHSEP_C)
332         p++;
333       prot = *p? atoi (p+1) : 0;
334       if (prot != 1)
335         {
336           log_error (_("gpg-agent protocol version %d is not supported\n"),
337                      prot);
338           xfree (infostr);
339           force_pipe_server = 1;
340           goto restart;
341         }
342
343       rc = assuan_socket_connect (&ctx, infostr, pid);
344       xfree (infostr);
345       if (gpg_err_code (rc) == GPG_ERR_ASS_CONNECT_FAILED)
346         {
347           log_info (_("can't connect to the agent - trying fall back\n"));
348           force_pipe_server = 1;
349           goto restart;
350         }
351     }
352
353   if (rc)
354     {
355       log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
356       return gpg_error (GPG_ERR_NO_AGENT);
357     }
358
359   if (debug)
360     log_debug ("connection to agent established\n");
361
362   rc = assuan_transact (ctx, "RESET",
363                         NULL, NULL, NULL, NULL, NULL, NULL);
364   if (!rc)
365     rc = send_pinentry_environment (ctx, errsource,
366                                     opt_display, opt_ttyname, opt_ttytype,
367                                     opt_lc_ctype, opt_lc_messages,
368                                     opt_xauthority,
369                                     opt_pinentry_user_data);
370   if (rc)
371     {
372       assuan_disconnect (ctx);
373       return rc;
374     }
375
376   *r_ctx = ctx;
377   return 0;
378 }
379