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