chiark / gitweb /
dirmngr: New option --no-use-tor and internal changes.
[gnupg2.git] / common / exectool.c
1 /* exectool.c - Utility functions to execute a helper tool
2  * Copyright (C) 2015 Werner Koch
3  * Copyright (C) 2016 g10 Code GmbH
4  *
5  * This file is part of GnuPG.
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of either
9  *
10  *   - the GNU Lesser General Public License as published by the Free
11  *     Software Foundation; either version 3 of the License, or (at
12  *     your option) any later version.
13  *
14  * or
15  *
16  *   - the GNU General Public License as published by the Free
17  *     Software Foundation; either version 2 of the License, or (at
18  *     your option) any later version.
19  *
20  * or both in parallel, as here.
21  *
22  * This file is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, see <https://www.gnu.org/licenses/>.
29  */
30
31 #include <config.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdarg.h>
36 #include <errno.h>
37 #include <assert.h>
38 #include <gpg-error.h>
39
40 #include <assuan.h>
41 #include "i18n.h"
42 #include "logging.h"
43 #include "membuf.h"
44 #include "mischelp.h"
45 #include "exechelp.h"
46 #include "sysutils.h"
47 #include "util.h"
48 #include "exectool.h"
49
50 typedef struct
51 {
52   const char *pgmname;
53   exec_tool_status_cb_t status_cb;
54   void *status_cb_value;
55   int cont;
56   size_t used;
57   size_t buffer_size;
58   char *buffer;
59 } read_and_log_buffer_t;
60
61
62 static inline gpg_error_t
63 my_error_from_syserror (void)
64 {
65   return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
66 }
67
68
69 static void
70 read_and_log_stderr (read_and_log_buffer_t *state, es_poll_t *fderr)
71 {
72   gpg_error_t err;
73   int c;
74
75   if (!fderr)
76     {
77       /* Flush internal buffer.  */
78       if (state->used)
79         {
80           const char *pname;
81           int len;
82
83           state->buffer[state->used] = 0;
84           state->used = 0;
85
86           pname = strrchr (state->pgmname, '/');
87           if (pname && pname != state->pgmname && pname[1])
88             pname++;
89           else
90             pname = state->pgmname;
91           len = strlen (pname);
92
93           if (state->status_cb
94               && !strncmp (state->buffer, "[GNUPG:] ", 9)
95               && state->buffer[9] >= 'A' && state->buffer[9] <= 'Z')
96             {
97               char *rest;
98
99               rest = strchr (state->buffer + 9, ' ');
100               if (!rest)
101                 {
102                   /* Set REST to an empty string.  */
103                   rest = state->buffer + strlen (state->buffer);
104                 }
105               else
106                 {
107                   *rest++ = 0;
108                   trim_spaces (rest);
109                 }
110               state->status_cb (state->status_cb_value,
111                                 state->buffer + 9, rest);
112             }
113           else if (!state->cont
114               && !strncmp (state->buffer, pname, len)
115               && strlen (state->buffer) > strlen (pname)
116               && state->buffer[len] == ':' )
117             {
118               /* PGMNAME plus colon is identical to the start of
119                  the output: print only the output.  */
120               log_info ("%s\n", state->buffer);
121             }
122           else
123             log_info ("%s%c %s\n",
124                       pname, state->cont? '+':':', state->buffer);
125         }
126       state->cont = 0;
127       return;
128     }
129   for (;;)
130     {
131       c = es_fgetc (fderr->stream);
132       if (c == EOF)
133         {
134           if (es_feof (fderr->stream))
135             {
136               fderr->ignore = 1; /* Not anymore needed.  */
137             }
138           else if (es_ferror (fderr->stream))
139             {
140               err = my_error_from_syserror ();
141               log_error ("error reading stderr of '%s': %s\n",
142                          state->pgmname, gpg_strerror (err));
143               fderr->ignore = 1; /* Disable.  */
144             }
145
146           break;
147         }
148       else if (c == '\n')
149         {
150           read_and_log_stderr (state, NULL);
151         }
152       else
153         {
154           if (state->used >= state->buffer_size - 1)
155             {
156               if (state->status_cb)
157                 {
158                   /* A status callback requires that we have a full
159                    * line.  Thus we need to enlarget the buffer in
160                    * this case.  */
161                   char *newbuffer;
162                   size_t newsize = state->buffer_size + 256;
163
164                   newbuffer = xtrymalloc (newsize);
165                   if (!newbuffer)
166                     {
167                       log_error ("error allocating memory for status cb: %s\n",
168                                  gpg_strerror (my_error_from_syserror ()));
169                       /* We better disable the status CB in this case.  */
170                       state->status_cb = NULL;
171                       read_and_log_stderr (state, NULL);
172                       state->cont = 1;
173                     }
174                   else
175                     {
176                       memcpy (newbuffer, state->buffer, state->used);
177                       xfree (state->buffer);
178                       state->buffer = newbuffer;
179                       state->buffer_size = newsize;
180                     }
181                 }
182               else
183                 {
184                   read_and_log_stderr (state, NULL);
185                   state->cont = 1;
186                 }
187             }
188           state->buffer[state->used++] = c;
189         }
190     }
191 }
192
193 \f
194
195 /* A buffer to copy from one stream to another.  */
196 struct copy_buffer
197 {
198   char buffer[4096];
199   char *writep;
200   size_t nread;
201 };
202
203
204 /* Initialize a copy buffer.  */
205 static void
206 copy_buffer_init (struct copy_buffer *c)
207 {
208   c->writep = c->buffer;
209   c->nread = 0;
210 }
211
212
213 /* Securely wipe a copy buffer.  */
214 static void
215 copy_buffer_shred (struct copy_buffer *c)
216 {
217   if (c == NULL)
218     return;
219   wipememory (c->buffer, sizeof c->buffer);
220   c->writep = NULL;
221   c->nread = ~0U;
222 }
223
224
225 /* Copy data from SOURCE to SINK using copy buffer C.  */
226 static gpg_error_t
227 copy_buffer_do_copy (struct copy_buffer *c, estream_t source, estream_t sink)
228 {
229   gpg_error_t err;
230   size_t nwritten = 0;
231
232   if (c->nread == 0)
233     {
234       c->writep = c->buffer;
235       if (es_read (source, c->buffer, sizeof c->buffer, &c->nread))
236         {
237           err = my_error_from_syserror ();
238           if (gpg_err_code (err) == GPG_ERR_EAGAIN)
239             return 0;   /* We will just retry next time.  */
240
241           return err;
242         }
243
244       log_assert (c->nread <= sizeof c->buffer);
245     }
246
247   if (c->nread == 0)
248     return 0;   /* Done copying.  */
249
250   nwritten = 0;
251   if (sink && es_write (sink, c->writep, c->nread, &nwritten))
252     err = my_error_from_syserror ();
253   else
254     err = 0;
255
256   log_assert (nwritten <= c->nread);
257   c->writep += nwritten;
258   c->nread -= nwritten;
259   log_assert (c->writep - c->buffer <= sizeof c->buffer);
260
261   if (err)
262     {
263       if (gpg_err_code (err) == GPG_ERR_EAGAIN)
264         return 0;       /* We will just retry next time.  */
265
266       return err;
267     }
268
269   if (sink && es_fflush (sink) && errno != EAGAIN)
270     err = my_error_from_syserror ();
271
272   return err;
273 }
274
275
276 /* Flush the remaining data to SINK.  */
277 static gpg_error_t
278 copy_buffer_flush (struct copy_buffer *c, estream_t sink)
279 {
280   gpg_error_t err = 0;
281   size_t nwritten = 0;
282
283   if (es_write (sink, c->writep, c->nread, &nwritten))
284     err = my_error_from_syserror ();
285
286   log_assert (nwritten <= c->nread);
287   c->writep += nwritten;
288   c->nread -= nwritten;
289   log_assert (c->writep - c->buffer <= sizeof c->buffer);
290
291   if (err)
292     return err;
293
294   if (es_fflush (sink))
295     err = my_error_from_syserror ();
296
297   return err;
298 }
299
300 \f
301
302 /* Run the program PGMNAME with the command line arguments given in
303  * the NULL terminates array ARGV.  If INPUT is not NULL it will be
304  * fed to stdin of the process.  stderr is logged using log_info and
305  * the process' stdout is written to OUTPUT.  If OUTPUT is NULL the
306  * output is discarded.  If INEXTRA is given, an additional input
307  * stream will be passed to the child; to tell the child about this
308  * ARGV is scanned and the first occurrence of an argument
309  * "-&@INEXTRA@" is replaced by the concatenation of "-&" and the
310  * child's file descriptor of the pipe created for the INEXTRA stream.
311  *
312  * On error a diagnostic is printed and an error code returned.  */
313 gpg_error_t
314 gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
315                         estream_t input, estream_t inextra,
316                         estream_t output,
317                         exec_tool_status_cb_t status_cb,
318                         void *status_cb_value)
319 {
320   gpg_error_t err;
321   pid_t pid = (pid_t) -1;
322   estream_t infp = NULL;
323   estream_t extrafp = NULL;
324   estream_t outfp = NULL, errfp = NULL;
325   es_poll_t fds[4];
326   int exceptclose[2];
327   int extrapipe[2] = {-1, -1};
328   char extrafdbuf[20];
329   const char *argsave = NULL;
330   int argsaveidx;
331   int count;
332   read_and_log_buffer_t fderrstate;
333   struct copy_buffer *cpbuf_in = NULL, *cpbuf_out = NULL, *cpbuf_extra = NULL;
334
335   memset (fds, 0, sizeof fds);
336   memset (&fderrstate, 0, sizeof fderrstate);
337
338   cpbuf_in = xtrymalloc (sizeof *cpbuf_in);
339   if (cpbuf_in == NULL)
340     {
341       err = my_error_from_syserror ();
342       goto leave;
343     }
344   copy_buffer_init (cpbuf_in);
345
346   cpbuf_out = xtrymalloc (sizeof *cpbuf_out);
347   if (cpbuf_out == NULL)
348     {
349       err = my_error_from_syserror ();
350       goto leave;
351     }
352   copy_buffer_init (cpbuf_out);
353
354   cpbuf_extra = xtrymalloc (sizeof *cpbuf_extra);
355   if (cpbuf_extra == NULL)
356     {
357       err = my_error_from_syserror ();
358       goto leave;
359     }
360   copy_buffer_init (cpbuf_extra);
361
362   fderrstate.pgmname = pgmname;
363   fderrstate.status_cb = status_cb;
364   fderrstate.status_cb_value = status_cb_value;
365   fderrstate.buffer_size = 256;
366   fderrstate.buffer = xtrymalloc (fderrstate.buffer_size);
367   if (!fderrstate.buffer)
368     {
369       err = my_error_from_syserror ();
370       goto leave;
371     }
372
373   if (inextra)
374     {
375       err = gnupg_create_outbound_pipe (extrapipe, &extrafp, 1);
376       if (err)
377         {
378           log_error ("error running outbound pipe for extra fp: %s\n",
379                      gpg_strerror (err));
380           goto leave;
381         }
382       exceptclose[0] = extrapipe[0]; /* Do not close in child. */
383       exceptclose[1] = -1;
384       /* Now find the argument marker and replace by the pipe's fd.
385          Yeah, that is an ugly non-thread safe hack but it safes us to
386          create a copy of the array.  */
387       snprintf (extrafdbuf, sizeof extrafdbuf, "-&%d", extrapipe[0]);
388       for (argsaveidx=0; argv[argsaveidx]; argsaveidx++)
389         if (!strcmp (argv[argsaveidx], "-&@INEXTRA@"))
390           {
391             argsave = argv[argsaveidx];
392             argv[argsaveidx] = extrafdbuf;
393             break;
394           }
395     }
396   else
397     exceptclose[0] = -1;
398
399   err = gnupg_spawn_process (pgmname, argv,
400                              exceptclose, NULL, GNUPG_SPAWN_NONBLOCK,
401                              input? &infp : NULL,
402                              &outfp, &errfp, &pid);
403   if (extrapipe[0] != -1)
404     close (extrapipe[0]);
405   if (argsave)
406     argv[argsaveidx] = argsave;
407   if (err)
408     {
409       log_error ("error running '%s': %s\n", pgmname, gpg_strerror (err));
410       goto leave;
411     }
412
413   fds[0].stream = infp;
414   fds[0].want_write = 1;
415   if (!input)
416     fds[0].ignore = 1;
417   fds[1].stream = outfp;
418   fds[1].want_read = 1;
419   fds[2].stream = errfp;
420   fds[2].want_read = 1;
421   fds[3].stream = extrafp;
422   fds[3].want_write = 1;
423   if (!inextra)
424     fds[3].ignore = 1;
425
426   /* Now read as long as we have something to poll.  We continue
427      reading even after EOF or error on stdout so that we get the
428      other error messages or remaining outut.  */
429   while (! (fds[1].ignore && fds[2].ignore))
430     {
431       count = es_poll (fds, DIM(fds), -1);
432       if (count == -1)
433         {
434           err = my_error_from_syserror ();
435           log_error ("error polling '%s': %s\n", pgmname, gpg_strerror (err));
436           goto leave;
437         }
438       if (!count)
439         {
440           log_debug ("unexpected timeout while polling '%s'\n", pgmname);
441           break;
442         }
443
444       if (fds[0].got_write)
445         {
446           err = copy_buffer_do_copy (cpbuf_in, input, fds[0].stream);
447           if (err)
448             {
449               log_error ("error feeding data to '%s': %s\n",
450                          pgmname, gpg_strerror (err));
451               goto leave;
452             }
453
454           if (es_feof (input))
455             {
456               err = copy_buffer_flush (cpbuf_in, fds[0].stream);
457               if (gpg_err_code (err) == GPG_ERR_EAGAIN)
458                 continue;       /* Retry next time.  */
459               if (err)
460                 {
461                   log_error ("error feeding data to '%s': %s\n",
462                              pgmname, gpg_strerror (err));
463                   goto leave;
464                 }
465
466               fds[0].ignore = 1; /* ready.  */
467               es_fclose (infp); infp = NULL;
468             }
469         }
470
471       if (fds[3].got_write)
472         {
473           log_assert (inextra);
474           err = copy_buffer_do_copy (cpbuf_extra, inextra, fds[3].stream);
475           if (err)
476             {
477               log_error ("error feeding data to '%s': %s\n",
478                          pgmname, gpg_strerror (err));
479               goto leave;
480             }
481
482           if (es_feof (inextra))
483             {
484               err = copy_buffer_flush (cpbuf_extra, fds[3].stream);
485               if (gpg_err_code (err) == GPG_ERR_EAGAIN)
486                 continue;       /* Retry next time.  */
487               if (err)
488                 {
489                   log_error ("error feeding data to '%s': %s\n",
490                              pgmname, gpg_strerror (err));
491                   goto leave;
492                 }
493
494               fds[3].ignore = 1; /* ready.  */
495               es_fclose (extrafp); extrafp = NULL;
496             }
497         }
498
499       if (fds[1].got_read)
500         {
501           err = copy_buffer_do_copy (cpbuf_out, fds[1].stream, output);
502           if (err)
503             {
504               log_error ("error reading data from '%s': %s\n",
505                          pgmname, gpg_strerror (err));
506               goto leave;
507             }
508
509           if (es_feof (fds[1].stream))
510             {
511               err = copy_buffer_flush (cpbuf_out, output);
512               if (err)
513                 {
514                   log_error ("error reading data from '%s': %s\n",
515                              pgmname, gpg_strerror (err));
516                   goto leave;
517                 }
518
519               fds[1].ignore = 1; /* ready.  */
520             }
521         }
522
523       if (fds[2].got_read)
524         read_and_log_stderr (&fderrstate, fds + 2);
525     }
526
527   read_and_log_stderr (&fderrstate, NULL); /* Flush.  */
528   es_fclose (infp); infp = NULL;
529   es_fclose (extrafp); extrafp = NULL;
530   es_fclose (outfp); outfp = NULL;
531   es_fclose (errfp); errfp = NULL;
532
533   err = gnupg_wait_process (pgmname, pid, 1, NULL);
534   pid = (pid_t)(-1);
535
536  leave:
537   if (err && pid != (pid_t) -1)
538     gnupg_kill_process (pid);
539
540   es_fclose (infp);
541   es_fclose (extrafp);
542   es_fclose (outfp);
543   es_fclose (errfp);
544   if (pid != (pid_t)(-1))
545     gnupg_wait_process (pgmname, pid, 1, NULL);
546   gnupg_release_process (pid);
547
548   copy_buffer_shred (cpbuf_in);
549   xfree (cpbuf_in);
550   copy_buffer_shred (cpbuf_out);
551   xfree (cpbuf_out);
552   copy_buffer_shred (cpbuf_extra);
553   xfree (cpbuf_extra);
554   xfree (fderrstate.buffer);
555   return err;
556 }
557
558
559 /* A dummy free function to pass to 'es_mopen'.  */
560 static void
561 nop_free (void *ptr)
562 {
563   (void) ptr;
564 }
565
566 /* Run the program PGMNAME with the command line arguments given in
567    the NULL terminates array ARGV.  If INPUT_STRING is not NULL it
568    will be fed to stdin of the process.  stderr is logged using
569    log_info and the process' stdout is returned in a newly malloced
570    buffer RESULT with the length stored at RESULTLEN if not given as
571    NULL.  A hidden Nul is appended to the output.  On error NULL is
572    stored at RESULT, a diagnostic is printed, and an error code
573    returned.  */
574 gpg_error_t
575 gnupg_exec_tool (const char *pgmname, const char *argv[],
576                  const char *input_string,
577                  char **result, size_t *resultlen)
578 {
579   gpg_error_t err;
580   estream_t input = NULL;
581   estream_t output;
582   size_t len;
583   size_t nread;
584
585   *result = NULL;
586   if (resultlen)
587     *resultlen = 0;
588
589   if (input_string)
590     {
591       len = strlen (input_string);
592       input = es_mopen ((char *) input_string, len, len,
593                         0 /* don't grow */, NULL, nop_free, "rb");
594       if (! input)
595         return my_error_from_syserror ();
596     }
597
598   output = es_fopenmem (0, "wb");
599   if (! output)
600     {
601       err = my_error_from_syserror ();
602       goto leave;
603     }
604
605   err = gnupg_exec_tool_stream (pgmname, argv, input, NULL, output, NULL, NULL);
606   if (err)
607     goto leave;
608
609   len = es_ftello (output);
610   err = es_fseek (output, 0, SEEK_SET);
611   if (err)
612     goto leave;
613
614   *result = xtrymalloc (len + 1);
615   if (!*result)
616     {
617       err = my_error_from_syserror ();
618       goto leave;
619     }
620
621   if (len)
622     {
623       if (es_read (output, *result, len, &nread))
624         {
625           err = my_error_from_syserror ();
626           goto leave;
627         }
628       if (nread != len)
629         log_fatal ("%s: short read from memstream\n", __func__);
630     }
631   (*result)[len] = 0;
632
633   if (resultlen)
634     *resultlen = len;
635
636  leave:
637   es_fclose (input);
638   es_fclose (output);
639   if (err)
640     {
641       xfree (*result);
642       *result = NULL;
643     }
644   return err;
645 }