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