common: Remove two JNLIB_ macros (jnlib merge).
[gnupg.git] / common / asshelp.c
1 /* asshelp.c - Helper functions for Assuan
2  * Copyright (C) 2002, 2004, 2007, 2009, 2010 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * This file is free software; you can redistribute it and/or modify
7  * it under the terms of either
8  *
9  *   - the GNU Lesser General Public License as published by the Free
10  *     Software Foundation; either version 3 of the License, or (at
11  *     your option) any later version.
12  *
13  * or
14  *
15  *   - the GNU General Public License as published by the Free
16  *     Software Foundation; either version 2 of the License, or (at
17  *     your option) any later version.
18  *
19  * or both in parallel, as here.
20  *
21  * This file is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, see <http://www.gnu.org/licenses/>.
28  */
29
30 #include <config.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <errno.h>
36 #ifdef HAVE_LOCALE_H
37 #include <locale.h>
38 #endif
39
40 #include "i18n.h"
41 #include "util.h"
42 #include "exechelp.h"
43 #include "sysutils.h"
44 #include "status.h"
45 #include "asshelp.h"
46
47 /* The type we use for lock_agent_spawning.  */
48 #ifdef HAVE_W32_SYSTEM
49 # define lock_spawn_t HANDLE
50 #else
51 # define lock_spawn_t dotlock_t
52 #endif
53
54 /* The time we wait until the agent or the dirmngr are ready for
55    operation after we started them before giving up.  */
56 #ifdef HAVE_W32CE_SYSTEM
57 # define SECS_TO_WAIT_FOR_AGENT 30
58 # define SECS_TO_WAIT_FOR_DIRMNGR 30
59 #else
60 # define SECS_TO_WAIT_FOR_AGENT 5
61 # define SECS_TO_WAIT_FOR_DIRMNGR 5
62 #endif
63
64 /* A bitfield that specifies the assuan categories to log.  This is
65    identical to the default log handler of libassuan.  We need to do
66    it ourselves because we use a custom log handler and want to use
67    the same assuan variables to select the categories to log. */
68 static int log_cats;
69 #define TEST_LOG_CAT(x) (!! (log_cats & (1 << (x - 1))))
70
71
72 static int
73 my_libassuan_log_handler (assuan_context_t ctx, void *hook,
74                           unsigned int cat, const char *msg)
75 {
76   unsigned int dbgval;
77
78   (void)ctx;
79
80   if (! TEST_LOG_CAT (cat))
81     return 0;
82
83   dbgval = hook? *(unsigned int*)hook : 0;
84   if (!(dbgval & 1024))
85     return 0; /* Assuan debugging is not enabled.  */
86
87   if (msg)
88     log_string (JNLIB_LOG_DEBUG, msg);
89
90   return 1;
91 }
92
93
94 /* Setup libassuan to use our own logging functions.  Should be used
95    early at startup.  */
96 void
97 setup_libassuan_logging (unsigned int *debug_var_address)
98 {
99   char *flagstr;
100
101   flagstr = getenv ("ASSUAN_DEBUG");
102   if (flagstr)
103     log_cats = atoi (flagstr);
104   else /* Default to log the control channel.  */
105     log_cats = (1 << (ASSUAN_LOG_CONTROL - 1));
106   assuan_set_log_cb (my_libassuan_log_handler, debug_var_address);
107 }
108
109 /* Change the Libassuan log categories to those given by NEWCATS.
110    NEWCATS is 0 the default category of ASSUAN_LOG_CONTROL is
111    selected.  Note, that setup_libassuan_logging overrides the values
112    given here.  */
113 void
114 set_libassuan_log_cats (unsigned int newcats)
115 {
116   if (newcats)
117     log_cats = newcats;
118   else /* Default to log the control channel.  */
119     log_cats = (1 << (ASSUAN_LOG_CONTROL - 1));
120 }
121
122
123
124 static gpg_error_t
125 send_one_option (assuan_context_t ctx, gpg_err_source_t errsource,
126                  const char *name, const char *value, int use_putenv)
127 {
128   gpg_error_t err;
129   char *optstr;
130
131   (void)errsource;
132
133   if (!value || !*value)
134     err = 0;  /* Avoid sending empty strings.  */
135   else if (asprintf (&optstr, "OPTION %s%s=%s",
136                      use_putenv? "putenv=":"", name, value) < 0)
137     err = gpg_error_from_syserror ();
138   else
139     {
140       err = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL);
141       xfree (optstr);
142     }
143
144   return err;
145 }
146
147
148 /* Send the assuan commands pertaining to the pinentry environment.  The
149    OPT_* arguments are optional and may be used to override the
150    defaults taken from the current locale. */
151 gpg_error_t
152 send_pinentry_environment (assuan_context_t ctx,
153                            gpg_err_source_t errsource,
154                            const char *opt_lc_ctype,
155                            const char *opt_lc_messages,
156                            session_env_t session_env)
157
158 {
159   gpg_error_t err = 0;
160 #if defined(HAVE_SETLOCALE)
161   char *old_lc = NULL;
162 #endif
163   char *dft_lc = NULL;
164   const char *dft_ttyname;
165   int iterator;
166   const char *name, *assname, *value;
167   int is_default;
168
169   iterator = 0;
170   while ((name = session_env_list_stdenvnames (&iterator, &assname)))
171     {
172       value = session_env_getenv_or_default (session_env, name, NULL);
173       if (!value)
174         continue;
175
176       if (assname)
177         err = send_one_option (ctx, errsource, assname, value, 0);
178       else
179         {
180           err = send_one_option (ctx, errsource, name, value, 1);
181           if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
182             err = 0;  /* Server too old; can't pass the new envvars.  */
183         }
184       if (err)
185         return err;
186     }
187
188
189   dft_ttyname = session_env_getenv_or_default (session_env, "GPG_TTY",
190                                                &is_default);
191   if (dft_ttyname && !is_default)
192     dft_ttyname = NULL;  /* We need the default value.  */
193
194   /* Send the value for LC_CTYPE.  */
195 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
196   old_lc = setlocale (LC_CTYPE, NULL);
197   if (old_lc)
198     {
199       old_lc = xtrystrdup (old_lc);
200       if (!old_lc)
201         return gpg_error_from_syserror ();
202     }
203   dft_lc = setlocale (LC_CTYPE, "");
204 #endif
205   if (opt_lc_ctype || (dft_ttyname && dft_lc))
206     {
207       err = send_one_option (ctx, errsource, "lc-ctype",
208                              opt_lc_ctype ? opt_lc_ctype : dft_lc, 0);
209     }
210 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
211   if (old_lc)
212     {
213       setlocale (LC_CTYPE, old_lc);
214       xfree (old_lc);
215     }
216 #endif
217   if (err)
218     return err;
219
220   /* Send the value for LC_MESSAGES.  */
221 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
222   old_lc = setlocale (LC_MESSAGES, NULL);
223   if (old_lc)
224     {
225       old_lc = xtrystrdup (old_lc);
226       if (!old_lc)
227         return gpg_error_from_syserror ();
228     }
229   dft_lc = setlocale (LC_MESSAGES, "");
230 #endif
231   if (opt_lc_messages || (dft_ttyname && dft_lc))
232     {
233       err = send_one_option (ctx, errsource, "lc-messages",
234                              opt_lc_messages ? opt_lc_messages : dft_lc, 0);
235     }
236 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
237   if (old_lc)
238     {
239       setlocale (LC_MESSAGES, old_lc);
240       xfree (old_lc);
241     }
242 #endif
243   if (err)
244     return err;
245
246   return 0;
247 }
248
249
250 /* Lock a spawning process.  The caller needs to provide the address
251    of a variable to store the lock information and the name or the
252    process.  */
253 static gpg_error_t
254 lock_spawning (lock_spawn_t *lock, const char *homedir, const char *name,
255                int verbose)
256 {
257 #ifdef HAVE_W32_SYSTEM
258   int waitrc;
259   int timeout = (!strcmp (name, "agent")
260                  ? SECS_TO_WAIT_FOR_AGENT
261                  : SECS_TO_WAIT_FOR_DIRMNGR);
262
263   (void)homedir; /* Not required. */
264
265   *lock = CreateMutexW
266     (NULL, FALSE,
267      !strcmp (name, "agent")?   L"spawn_"GNUPG_NAME"_agent_sentinel":
268      !strcmp (name, "dirmngr")? L"spawn_"GNUPG_NAME"_dirmngr_sentinel":
269      /*                    */   L"spawn_"GNUPG_NAME"_unknown_sentinel");
270   if (!*lock)
271     {
272       log_error ("failed to create the spawn_%s mutex: %s\n",
273                  name, w32_strerror (-1));
274       return gpg_error (GPG_ERR_GENERAL);
275     }
276
277  retry:
278   waitrc = WaitForSingleObject (*lock, 1000);
279   if (waitrc == WAIT_OBJECT_0)
280     return 0;
281
282   if (waitrc == WAIT_TIMEOUT && timeout)
283     {
284       timeout--;
285       if (verbose)
286         log_info ("another process is trying to start the %s ... (%ds)\n",
287                   name, timeout);
288       goto retry;
289     }
290   if (waitrc == WAIT_TIMEOUT)
291     log_info ("error waiting for the spawn_%s mutex: timeout\n", name);
292   else
293     log_info ("error waiting for the spawn_%s mutex: (code=%d) %s\n",
294               name, waitrc, w32_strerror (-1));
295   return gpg_error (GPG_ERR_GENERAL);
296 #else /*!HAVE_W32_SYSTEM*/
297   char *fname;
298
299   (void)verbose;
300
301   *lock = NULL;
302
303   fname = make_absfilename_try
304     (homedir,
305      !strcmp (name, "agent")?   "gnupg_spawn_agent_sentinel":
306      !strcmp (name, "dirmngr")? "gnupg_spawn_dirmngr_sentinel":
307      /*                    */   "gnupg_spawn_unknown_sentinel",
308      NULL);
309   if (!fname)
310     return gpg_error_from_syserror ();
311
312   *lock = dotlock_create (fname, 0);
313   xfree (fname);
314   if (!*lock)
315     return gpg_error_from_syserror ();
316
317   /* FIXME: We should use a timeout of 5000 here - however
318      make_dotlock does not yet support values other than -1 and 0.  */
319   if (dotlock_take (*lock, -1))
320     return gpg_error_from_syserror ();
321
322   return 0;
323 #endif /*!HAVE_W32_SYSTEM*/
324 }
325
326
327 /* Unlock the spawning process.  */
328 static void
329 unlock_spawning (lock_spawn_t *lock, const char *name)
330 {
331   if (*lock)
332     {
333 #ifdef HAVE_W32_SYSTEM
334       if (!ReleaseMutex (*lock))
335         log_error ("failed to release the spawn_%s mutex: %s\n",
336                    name, w32_strerror (-1));
337       CloseHandle (*lock);
338 #else /*!HAVE_W32_SYSTEM*/
339       (void)name;
340       dotlock_destroy (*lock);
341 #endif /*!HAVE_W32_SYSTEM*/
342       *lock = NULL;
343     }
344 }
345
346 /* Try to connect to the agent via socket or start it if it is not
347    running and AUTOSTART is set.  Handle the server's initial
348    greeting.  Returns a new assuan context at R_CTX or an error
349    code. */
350 gpg_error_t
351 start_new_gpg_agent (assuan_context_t *r_ctx,
352                      gpg_err_source_t errsource,
353                      const char *homedir,
354                      const char *agent_program,
355                      const char *opt_lc_ctype,
356                      const char *opt_lc_messages,
357                      session_env_t session_env,
358                      int autostart, int verbose, int debug,
359                      gpg_error_t (*status_cb)(ctrl_t, int, ...),
360                      ctrl_t status_cb_arg)
361 {
362   gpg_error_t err;
363   assuan_context_t ctx;
364   int did_success_msg = 0;
365   char *sockname;
366   const char *argv[6];
367
368   *r_ctx = NULL;
369
370   err = assuan_new (&ctx);
371   if (err)
372     {
373       log_error ("error allocating assuan context: %s\n", gpg_strerror (err));
374       return err;
375     }
376
377   sockname = make_absfilename (homedir, GPG_AGENT_SOCK_NAME, NULL);
378   err = assuan_socket_connect (ctx, sockname, 0, 0);
379   if (err && autostart)
380     {
381       char *abs_homedir;
382       lock_spawn_t lock;
383       char *program = NULL;
384       const char *program_arg = NULL;
385       char *p;
386       const char *s;
387       int i;
388
389       /* With no success start a new server.  */
390       if (!agent_program || !*agent_program)
391         agent_program = gnupg_module_name (GNUPG_MODULE_NAME_AGENT);
392       else if ((s=strchr (agent_program, '|')) && s[1] == '-' && s[2]=='-')
393         {
394           /* Hack to insert an additional option on the command line.  */
395           program = xtrystrdup (agent_program);
396           if (!program)
397             {
398               gpg_error_t tmperr = gpg_err_make (errsource,
399                                                  gpg_err_code_from_syserror ());
400               xfree (sockname);
401               assuan_release (ctx);
402               return tmperr;
403             }
404           p = strchr (program, '|');
405           *p++ = 0;
406           program_arg = p;
407         }
408
409       if (verbose)
410         log_info (_("no running gpg-agent - starting '%s'\n"),
411                   agent_program);
412
413       if (status_cb)
414         status_cb (status_cb_arg, STATUS_PROGRESS,
415                    "starting_agent ? 0 0", NULL);
416
417       /* We better pass an absolute home directory to the agent just
418          in case gpg-agent does not convert the passed name to an
419          absolute one (which it should do).  */
420       abs_homedir = make_absfilename_try (homedir, NULL);
421       if (!abs_homedir)
422         {
423           gpg_error_t tmperr = gpg_err_make (errsource,
424                                              gpg_err_code_from_syserror ());
425           log_error ("error building filename: %s\n",gpg_strerror (tmperr));
426           xfree (sockname);
427           assuan_release (ctx);
428           xfree (program);
429           return tmperr;
430         }
431
432       if (fflush (NULL))
433         {
434           gpg_error_t tmperr = gpg_err_make (errsource,
435                                              gpg_err_code_from_syserror ());
436           log_error ("error flushing pending output: %s\n",
437                      strerror (errno));
438           xfree (sockname);
439           assuan_release (ctx);
440           xfree (abs_homedir);
441           xfree (program);
442           return tmperr;
443         }
444
445       /* If the agent has been configured for use with a standard
446          socket, an environment variable is not required and thus
447          we we can savely start the agent here.  */
448       i = 0;
449       argv[i++] = "--homedir";
450       argv[i++] = abs_homedir;
451       argv[i++] = "--use-standard-socket";
452       if (program_arg)
453         argv[i++] = program_arg;
454       argv[i++] = "--daemon";
455       argv[i++] = NULL;
456
457       if (!(err = lock_spawning (&lock, homedir, "agent", verbose))
458           && assuan_socket_connect (ctx, sockname, 0, 0))
459         {
460           err = gnupg_spawn_process_detached (program? program : agent_program,
461                                               argv, NULL);
462           if (err)
463             log_error ("failed to start agent '%s': %s\n",
464                        agent_program, gpg_strerror (err));
465           else
466             {
467               for (i=0; i < SECS_TO_WAIT_FOR_AGENT; i++)
468                 {
469                   if (verbose)
470                     log_info (_("waiting for the agent to come up ... (%ds)\n"),
471                               SECS_TO_WAIT_FOR_AGENT - i);
472                   gnupg_sleep (1);
473                   err = assuan_socket_connect (ctx, sockname, 0, 0);
474                   if (!err)
475                     {
476                       if (verbose)
477                         {
478                           log_info (_("connection to agent established\n"));
479                           did_success_msg = 1;
480                         }
481                       break;
482                     }
483                 }
484             }
485         }
486
487       unlock_spawning (&lock, "agent");
488       xfree (abs_homedir);
489       xfree (program);
490     }
491   xfree (sockname);
492   if (err)
493     {
494       if (autostart || gpg_err_code (err) != GPG_ERR_ASS_CONNECT_FAILED)
495         log_error ("can't connect to the agent: %s\n", gpg_strerror (err));
496       assuan_release (ctx);
497       return gpg_err_make (errsource, GPG_ERR_NO_AGENT);
498     }
499
500   if (debug && !did_success_msg)
501     log_debug (_("connection to agent established\n"));
502
503   err = assuan_transact (ctx, "RESET",
504                          NULL, NULL, NULL, NULL, NULL, NULL);
505   if (!err)
506     {
507       err = send_pinentry_environment (ctx, errsource,
508                                        opt_lc_ctype, opt_lc_messages,
509                                        session_env);
510       if (gpg_err_code (err) == GPG_ERR_FORBIDDEN
511           && gpg_err_source (err) == GPG_ERR_SOURCE_GPGAGENT)
512         {
513           /* Check whether we are in restricted mode.  */
514           if (!assuan_transact (ctx, "GETINFO restricted",
515                                 NULL, NULL, NULL, NULL, NULL, NULL))
516             {
517               if (verbose)
518                 log_info (_("connection to agent is in restricted mode\n"));
519               err = 0;
520             }
521         }
522     }
523   if (err)
524     {
525       assuan_release (ctx);
526       return err;
527     }
528
529   *r_ctx = ctx;
530   return 0;
531 }
532
533
534 /* Try to connect to the dirmngr via a socket.  On platforms
535    supporting it, start it up if needed and if AUTOSTART is true.
536    Returns a new assuan context at R_CTX or an error code. */
537 gpg_error_t
538 start_new_dirmngr (assuan_context_t *r_ctx,
539                    gpg_err_source_t errsource,
540                    const char *homedir,
541                    const char *dirmngr_program,
542                    int autostart,
543                    int verbose, int debug,
544                    gpg_error_t (*status_cb)(ctrl_t, int, ...),
545                    ctrl_t status_cb_arg)
546 {
547   gpg_error_t err;
548   assuan_context_t ctx;
549   const char *sockname;
550   int did_success_msg = 0;
551
552   *r_ctx = NULL;
553
554   err = assuan_new (&ctx);
555   if (err)
556     {
557       log_error ("error allocating assuan context: %s\n", gpg_strerror (err));
558       return err;
559     }
560
561   sockname = dirmngr_user_socket_name ();
562   if (sockname)
563     {
564       /* First try the local socket name and only if that fails try
565          the system socket.  */
566       err = assuan_socket_connect (ctx, sockname, 0, 0);
567       if (err)
568         sockname = dirmngr_sys_socket_name ();
569     }
570   else
571     sockname = dirmngr_sys_socket_name ();
572
573   err = assuan_socket_connect (ctx, sockname, 0, 0);
574
575 #ifdef USE_DIRMNGR_AUTO_START
576   if (err && autostart)
577     {
578       lock_spawn_t lock;
579       const char *argv[4];
580       int try_system_daemon = 0;
581       char *abs_homedir;
582
583       /* No connection: Try start a new Dirmngr.  On Windows this will
584          fail because the Dirmngr is expected to be a system service.
585          However on WinCE we don't distinguish users and thus we can
586          start it.  */
587
588       /* We prefer to start it as a user daemon.  */
589       sockname = dirmngr_user_socket_name ();
590       if (!sockname)
591         {
592           sockname = dirmngr_sys_socket_name ();
593           try_system_daemon = 1;
594         }
595
596       if (!dirmngr_program || !*dirmngr_program)
597         dirmngr_program = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR);
598
599       if (verbose)
600         log_info (_("no running Dirmngr - starting '%s'\n"),
601                   dirmngr_program);
602
603       if (status_cb)
604         status_cb (status_cb_arg, STATUS_PROGRESS,
605                    "starting_dirmngr ? 0 0", NULL);
606
607       abs_homedir = make_absfilename (homedir, NULL);
608       if (!abs_homedir)
609         {
610           gpg_error_t tmperr = gpg_err_make (errsource,
611                                              gpg_err_code_from_syserror ());
612           log_error ("error building filename: %s\n",gpg_strerror (tmperr));
613           assuan_release (ctx);
614           return tmperr;
615         }
616
617       if (fflush (NULL))
618         {
619           gpg_error_t tmperr = gpg_err_make (errsource,
620                                              gpg_err_code_from_syserror ());
621           log_error ("error flushing pending output: %s\n",
622                      strerror (errno));
623           assuan_release (ctx);
624           return tmperr;
625         }
626
627       argv[0] = "--daemon";
628       if (try_system_daemon)
629         argv[1] = NULL;
630       else
631         { /* Try starting as user daemon - dirmngr does this if the
632              home directory is given on the command line.  */
633           argv[1] = "--homedir";
634           argv[2] = abs_homedir;
635           argv[3] = NULL;
636         }
637
638       /* On the use of HOMEDIR for locking: Under Windows HOMEDIR is
639          not used thus it does not matter.  Under Unix we should
640          TRY_SYSTEM_DAEMON should never be true because
641          dirmngr_user_socket_name() won't return NULL.  */
642
643       if (!(err = lock_spawning (&lock, homedir, "dirmngr", verbose))
644           && assuan_socket_connect (ctx, sockname, 0, 0))
645         {
646           err = gnupg_spawn_process_detached (dirmngr_program, argv, NULL);
647           if (err)
648             log_error ("failed to start the dirmngr '%s': %s\n",
649                        dirmngr_program, gpg_strerror (err));
650           else
651             {
652               int i;
653
654               for (i=0; i < SECS_TO_WAIT_FOR_DIRMNGR; i++)
655                 {
656                   if (verbose)
657                     log_info (_("waiting for the dirmngr "
658                                 "to come up ... (%ds)\n"),
659                               SECS_TO_WAIT_FOR_DIRMNGR - i);
660                   gnupg_sleep (1);
661                   err = assuan_socket_connect (ctx, sockname, 0, 0);
662                   if (!err)
663                     {
664                       if (verbose)
665                         {
666                           log_info (_("connection to the dirmngr"
667                                       " established\n"));
668                           did_success_msg = 1;
669                         }
670                       break;
671                     }
672                 }
673             }
674         }
675
676       unlock_spawning (&lock, "dirmngr");
677       xfree (abs_homedir);
678     }
679 #else
680   (void)homedir;
681   (void)dirmngr_program;
682   (void)verbose;
683   (void)status_cb;
684   (void)status_cb_arg;
685 #endif /*USE_DIRMNGR_AUTO_START*/
686
687   if (err)
688     {
689       if (autostart || gpg_err_code (err) != GPG_ERR_ASS_CONNECT_FAILED)
690         log_error ("connecting dirmngr at '%s' failed: %s\n",
691                    sockname, gpg_strerror (err));
692       assuan_release (ctx);
693       return gpg_err_make (errsource, GPG_ERR_NO_DIRMNGR);
694     }
695
696   if (debug && !did_success_msg)
697     log_debug (_("connection to the dirmngr established\n"));
698
699   *r_ctx = ctx;
700   return 0;
701 }