chiark / gitweb /
dirmngr: Drop useless housekeeping.
[gnupg2.git] / common / call-gpg.c
1 /* call-gpg.c - Communication with the GPG
2  * Copyright (C) 2009 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 <https://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21
22 #include <assert.h>
23 #include <assuan.h>
24 #include <errno.h>
25 #include <npth.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <time.h>
30
31 #include "call-gpg.h"
32 #include "exechelp.h"
33 #include "i18n.h"
34 #include "logging.h"
35 #include "membuf.h"
36 #include "strlist.h"
37 #include "util.h"
38
39
40 static GPGRT_INLINE gpg_error_t
41 my_error_from_syserror (void)
42 {
43   return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
44 }
45
46 static GPGRT_INLINE gpg_error_t
47 my_error_from_errno (int e)
48 {
49   return gpg_err_make (default_errsource, gpg_err_code_from_errno (e));
50 }
51
52 \f
53 /* Fire up a new GPG.  Handle the server's initial greeting.  Returns
54    0 on success and stores the assuan context at R_CTX.  */
55 static gpg_error_t
56 start_gpg (ctrl_t ctrl, const char *gpg_program, strlist_t gpg_arguments,
57            int input_fd, int output_fd, assuan_context_t *r_ctx)
58 {
59   gpg_error_t err;
60   assuan_context_t ctx = NULL;
61   const char *pgmname;
62   const char **argv;
63   assuan_fd_t no_close_list[5];
64   int i;
65   char line[ASSUAN_LINELENGTH];
66
67   (void)ctrl;
68
69   *r_ctx = NULL;
70
71   err = assuan_new (&ctx);
72   if (err)
73     {
74       log_error ("can't allocate assuan context: %s\n", gpg_strerror (err));
75       return err;
76     }
77
78   /* The first time we are used, intialize the gpg_program variable.  */
79   if ( !gpg_program || !*gpg_program )
80     gpg_program = gnupg_module_name (GNUPG_MODULE_NAME_GPG);
81
82   /* Compute argv[0].  */
83   if ( !(pgmname = strrchr (gpg_program, '/')))
84     pgmname = gpg_program;
85   else
86     pgmname++;
87
88   if (fflush (NULL))
89     {
90       err = my_error_from_syserror ();
91       log_error ("error flushing pending output: %s\n", gpg_strerror (err));
92       return err;
93     }
94
95   argv = xtrycalloc (strlist_length (gpg_arguments) + 3, sizeof *argv);
96   if (argv == NULL)
97     {
98       err = my_error_from_syserror ();
99       return err;
100     }
101   i = 0;
102   argv[i++] = pgmname;
103   argv[i++] = "--server";
104   for (; gpg_arguments; gpg_arguments = gpg_arguments->next)
105     argv[i++] = gpg_arguments->d;
106   argv[i++] = NULL;
107
108   i = 0;
109   if (log_get_fd () != -1)
110     no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ());
111   no_close_list[i++] = assuan_fd_from_posix_fd (fileno (stderr));
112   if (input_fd != -1)
113     no_close_list[i++] = assuan_fd_from_posix_fd (input_fd);
114   if (output_fd != -1)
115     no_close_list[i++] = assuan_fd_from_posix_fd (output_fd);
116   no_close_list[i] = ASSUAN_INVALID_FD;
117
118   /* Connect to GPG and perform initial handshaking.  */
119   err = assuan_pipe_connect (ctx, gpg_program, argv, no_close_list,
120                              NULL, NULL, 0);
121   if (err)
122     {
123       assuan_release (ctx);
124       log_error ("can't connect to GPG: %s\n", gpg_strerror (err));
125       return gpg_error (GPG_ERR_NO_ENGINE);
126     }
127
128   if (input_fd != -1)
129     {
130       snprintf (line, sizeof line, "INPUT FD=%d", input_fd);
131       err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
132       if (err)
133         {
134           assuan_release (ctx);
135           log_error ("error sending INPUT command: %s\n", gpg_strerror (err));
136           return err;
137         }
138     }
139
140   if (output_fd != -1)
141     {
142       snprintf (line, sizeof line, "OUTPUT FD=%d", output_fd);
143       err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
144       if (err)
145         {
146           assuan_release (ctx);
147           log_error ("error sending OUTPUT command: %s\n", gpg_strerror (err));
148           return err;
149         }
150     }
151
152   *r_ctx = ctx;
153   return 0;
154 }
155
156
157 /* Release the assuan context created by start_gpg.  */
158 static void
159 release_gpg (assuan_context_t ctx)
160 {
161   assuan_release (ctx);
162 }
163
164
165 \f
166 /* The data passed to the writer_thread.  */
167 struct writer_thread_parms
168 {
169   int fd;
170   const void *data;
171   size_t datalen;
172   estream_t stream;
173   gpg_error_t *err_addr;
174 };
175
176
177 /* The thread started by start_writer.  */
178 static void *
179 writer_thread_main (void *arg)
180 {
181   gpg_error_t err = 0;
182   struct writer_thread_parms *parm = arg;
183   char _buffer[4096];
184   char *buffer;
185   size_t length;
186
187   if (parm->stream)
188     {
189       buffer = _buffer;
190       err = es_read (parm->stream, buffer, sizeof _buffer, &length);
191       if (err)
192         {
193           log_error ("reading stream failed: %s\n", gpg_strerror (err));
194           goto leave;
195         }
196     }
197   else
198     {
199       buffer = (char *) parm->data;
200       length = parm->datalen;
201     }
202
203   while (length)
204     {
205       ssize_t nwritten;
206
207       nwritten = npth_write (parm->fd, buffer, length < 4096? length:4096);
208       if (nwritten < 0)
209         {
210           if (errno == EINTR)
211             continue;
212           err = my_error_from_syserror ();
213           break; /* Write error.  */
214         }
215       length -= nwritten;
216
217       if (parm->stream)
218         {
219           if (length == 0)
220             {
221               err = es_read (parm->stream, buffer, sizeof _buffer, &length);
222               if (err)
223                 {
224                   log_error ("reading stream failed: %s\n",
225                              gpg_strerror (err));
226                   break;
227                 }
228               if (length == 0)
229                 /* We're done.  */
230                 break;
231             }
232         }
233       else
234         buffer += nwritten;
235     }
236
237  leave:
238   *parm->err_addr = err;
239   if (close (parm->fd))
240     log_error ("closing writer fd %d failed: %s\n", parm->fd, strerror (errno));
241   xfree (parm);
242   return NULL;
243 }
244
245
246 /* Fire up a thread to send (DATA,DATALEN) to the file descriptor FD.
247    On success the thread receives the ownership over FD.  The thread
248    ID is stored at R_TID.  WRITER_ERR is the address of an gpg_error_t
249    variable to receive a possible write error after the thread has
250    finished.  */
251 static gpg_error_t
252 start_writer (int fd, const void *data, size_t datalen, estream_t stream,
253               npth_t *r_thread, gpg_error_t *err_addr)
254 {
255   gpg_error_t err;
256   struct writer_thread_parms *parm;
257   npth_attr_t tattr;
258   npth_t thread;
259   int ret;
260
261   memset (r_thread, '\0', sizeof (*r_thread));
262   *err_addr = 0;
263
264   parm = xtrymalloc (sizeof *parm);
265   if (!parm)
266     return my_error_from_syserror ();
267   parm->fd = fd;
268   parm->data = data;
269   parm->datalen = datalen;
270   parm->stream = stream;
271   parm->err_addr = err_addr;
272
273   npth_attr_init (&tattr);
274   npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
275
276   ret = npth_create (&thread, &tattr, writer_thread_main, parm);
277   if (ret)
278     {
279       err = my_error_from_errno (ret);
280       log_error ("error spawning writer thread: %s\n", gpg_strerror (err));
281     }
282   else
283     {
284       npth_setname_np (thread, "fd-writer");
285       err = 0;
286       *r_thread = thread;
287     }
288   npth_attr_destroy (&tattr);
289
290   return err;
291 }
292
293
294 \f
295 /* The data passed to the reader_thread.  */
296 struct reader_thread_parms
297 {
298   int fd;
299   membuf_t *mb;
300   estream_t stream;
301   gpg_error_t *err_addr;
302 };
303
304
305 /* The thread started by start_reader.  */
306 static void *
307 reader_thread_main (void *arg)
308 {
309   gpg_error_t err = 0;
310   struct reader_thread_parms *parm = arg;
311   char buffer[4096];
312   int nread;
313
314   while ( (nread = npth_read (parm->fd, buffer, sizeof buffer)) )
315     {
316       if (nread < 0)
317         {
318           if (errno == EINTR)
319             continue;
320           err = my_error_from_syserror ();
321           break;  /* Read error.  */
322         }
323
324       if (parm->stream)
325         {
326           const char *p = buffer;
327           size_t nwritten;
328           while (nread)
329             {
330               err = es_write (parm->stream, p, nread, &nwritten);
331               if (err)
332                 {
333                   log_error ("writing stream failed: %s\n",
334                              gpg_strerror (err));
335                   goto leave;
336                 }
337               nread -= nwritten;
338               p += nwritten;
339             }
340         }
341       else
342         put_membuf (parm->mb, buffer, nread);
343     }
344
345  leave:
346   *parm->err_addr = err;
347   if (close (parm->fd))
348     log_error ("closing reader fd %d failed: %s\n", parm->fd, strerror (errno));
349   xfree (parm);
350   return NULL;
351 }
352
353
354 /* Fire up a thread to receive data from the file descriptor FD.  On
355    success the thread receives the ownership over FD.  The thread ID
356    is stored at R_TID.  After the thread has finished an error from
357    the thread will be stored at ERR_ADDR.  */
358 static gpg_error_t
359 start_reader (int fd, membuf_t *mb, estream_t stream,
360               npth_t *r_thread, gpg_error_t *err_addr)
361 {
362   gpg_error_t err;
363   struct reader_thread_parms *parm;
364   npth_attr_t tattr;
365   npth_t thread;
366   int ret;
367
368   memset (r_thread, '\0', sizeof (*r_thread));
369   *err_addr = 0;
370
371   parm = xtrymalloc (sizeof *parm);
372   if (!parm)
373     return my_error_from_syserror ();
374   parm->fd = fd;
375   parm->mb = mb;
376   parm->stream = stream;
377   parm->err_addr = err_addr;
378
379   npth_attr_init (&tattr);
380   npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
381
382   ret = npth_create (&thread, &tattr, reader_thread_main, parm);
383   if (ret)
384     {
385       err = my_error_from_errno (ret);
386       log_error ("error spawning reader thread: %s\n", gpg_strerror (err));
387     }
388   else
389     {
390       npth_setname_np (thread, "fd-reader");
391       err = 0;
392       *r_thread = thread;
393     }
394   npth_attr_destroy (&tattr);
395
396   return err;
397 }
398
399
400
401 \f
402 /* Call GPG to encrypt a block of data.
403
404
405  */
406 static gpg_error_t
407 _gpg_encrypt (ctrl_t ctrl,
408               const char *gpg_program,
409               strlist_t gpg_arguments,
410               const void *plain, size_t plainlen,
411               estream_t plain_stream,
412               strlist_t keys,
413               membuf_t *reader_mb,
414               estream_t cipher_stream)
415 {
416   gpg_error_t err;
417   assuan_context_t ctx = NULL;
418   int outbound_fds[2] = { -1, -1 };
419   int inbound_fds[2]  = { -1, -1 };
420   npth_t writer_thread = (npth_t)0;
421   npth_t reader_thread = (npth_t)0;
422   gpg_error_t writer_err, reader_err;
423   char line[ASSUAN_LINELENGTH];
424   strlist_t sl;
425   int ret;
426
427   /* Make sure that either the stream interface xor the buffer
428      interface is used.  */
429   assert ((plain == NULL) != (plain_stream == NULL));
430   assert ((reader_mb == NULL) != (cipher_stream == NULL));
431
432   /* Create two pipes.  */
433   err = gnupg_create_outbound_pipe (outbound_fds, NULL, 0);
434   if (!err)
435     err = gnupg_create_inbound_pipe (inbound_fds, NULL, 0);
436   if (err)
437     {
438       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
439       goto leave;
440     }
441
442   /* Start GPG and send the INPUT and OUTPUT commands.  */
443   err = start_gpg (ctrl, gpg_program, gpg_arguments,
444                    outbound_fds[0], inbound_fds[1], &ctx);
445   if (err)
446     goto leave;
447   close (outbound_fds[0]); outbound_fds[0] = -1;
448   close (inbound_fds[1]); inbound_fds[1] = -1;
449
450   /* Start a writer thread to feed the INPUT command of the server.  */
451   err = start_writer (outbound_fds[1], plain, plainlen, plain_stream,
452                       &writer_thread, &writer_err);
453   if (err)
454     return err;
455   outbound_fds[1] = -1;  /* The thread owns the FD now.  */
456
457   /* Start a reader thread to eat from the OUTPUT command of the
458      server.  */
459   err = start_reader (inbound_fds[0], reader_mb, cipher_stream,
460                       &reader_thread, &reader_err);
461   if (err)
462     return err;
463   outbound_fds[0] = -1;  /* The thread owns the FD now.  */
464
465   /* Run the encryption.  */
466   for (sl = keys; sl; sl = sl->next)
467     {
468       snprintf (line, sizeof line, "RECIPIENT -- %s", sl->d);
469       err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
470       if (err)
471         {
472           log_error ("the engine's RECIPIENT command failed: %s <%s>\n",
473                  gpg_strerror (err), gpg_strsource (err));
474           goto leave;
475         }
476     }
477
478   err = assuan_transact (ctx, "ENCRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
479   if (err)
480     {
481       log_error ("the engine's ENCRYPT command failed: %s <%s>\n",
482                  gpg_strerror (err), gpg_strsource (err));
483       goto leave;
484     }
485
486   /* Wait for reader and return the data.  */
487   ret = npth_join (reader_thread, NULL);
488   if (ret)
489     {
490       err = my_error_from_errno (ret);
491       log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
492       goto leave;
493     }
494   /* FIXME: Not really valid, as npth_t is an opaque type.  */
495   memset (&reader_thread, '\0', sizeof (reader_thread));
496   if (reader_err)
497     {
498       err = reader_err;
499       log_error ("read error in reader thread: %s\n", gpg_strerror (err));
500       goto leave;
501     }
502
503   /* Wait for the writer to catch  a writer error.  */
504   ret = npth_join (writer_thread, NULL);
505   if (ret)
506     {
507       err = my_error_from_errno (ret);
508       log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
509       goto leave;
510     }
511   memset (&writer_thread, '\0', sizeof (writer_thread));
512   if (writer_err)
513     {
514       err = writer_err;
515       log_error ("write error in writer thread: %s\n", gpg_strerror (err));
516       goto leave;
517     }
518
519  leave:
520   /* FIXME: Not valid, as npth_t is an opaque type.  */
521   if (reader_thread)
522     npth_detach (reader_thread);
523   if (writer_thread)
524     npth_detach (writer_thread);
525   if (outbound_fds[0] != -1)
526     close (outbound_fds[0]);
527   if (outbound_fds[1] != -1)
528     close (outbound_fds[1]);
529   if (inbound_fds[0] != -1)
530     close (inbound_fds[0]);
531   if (inbound_fds[1] != -1)
532     close (inbound_fds[1]);
533   release_gpg (ctx);
534   return err;
535 }
536
537 gpg_error_t
538 gpg_encrypt_blob (ctrl_t ctrl,
539                   const char *gpg_program,
540                   strlist_t gpg_arguments,
541                   const void *plain, size_t plainlen,
542                   strlist_t keys,
543                   void **r_ciph, size_t *r_ciphlen)
544 {
545   gpg_error_t err;
546   membuf_t reader_mb;
547
548   *r_ciph = NULL;
549   *r_ciphlen = 0;
550
551   /* Init the memory buffer to receive the encrypted stuff.  */
552   init_membuf (&reader_mb, 4096);
553
554   err = _gpg_encrypt (ctrl, gpg_program, gpg_arguments,
555                       plain, plainlen, NULL,
556                       keys,
557                       &reader_mb, NULL);
558
559   if (! err)
560     {
561       /* Return the data.  */
562       *r_ciph = get_membuf (&reader_mb, r_ciphlen);
563       if (!*r_ciph)
564         {
565           err = my_error_from_syserror ();
566           log_error ("error while storing the data in the reader thread: %s\n",
567                      gpg_strerror (err));
568         }
569     }
570
571   xfree (get_membuf (&reader_mb, NULL));
572   return err;
573 }
574
575 gpg_error_t
576 gpg_encrypt_stream (ctrl_t ctrl,
577                     const char *gpg_program,
578                     strlist_t gpg_arguments,
579                     estream_t plain_stream,
580                     strlist_t keys,
581                     estream_t cipher_stream)
582 {
583   return _gpg_encrypt (ctrl, gpg_program, gpg_arguments,
584                        NULL, 0, plain_stream,
585                        keys,
586                        NULL, cipher_stream);
587 }
588 \f
589 /* Call GPG to decrypt a block of data.
590
591
592  */
593 static gpg_error_t
594 _gpg_decrypt (ctrl_t ctrl,
595               const char *gpg_program,
596               strlist_t gpg_arguments,
597               const void *ciph, size_t ciphlen,
598               estream_t cipher_stream,
599               membuf_t *reader_mb,
600               estream_t plain_stream)
601 {
602   gpg_error_t err;
603   assuan_context_t ctx = NULL;
604   int outbound_fds[2] = { -1, -1 };
605   int inbound_fds[2]  = { -1, -1 };
606   npth_t writer_thread = (npth_t)0;
607   npth_t reader_thread = (npth_t)0;
608   gpg_error_t writer_err, reader_err;
609   int ret;
610
611   /* Make sure that either the stream interface xor the buffer
612      interface is used.  */
613   assert ((ciph == NULL) != (cipher_stream == NULL));
614   assert ((reader_mb == NULL) != (plain_stream == NULL));
615
616   /* Create two pipes.  */
617   err = gnupg_create_outbound_pipe (outbound_fds, NULL, 0);
618   if (!err)
619     err = gnupg_create_inbound_pipe (inbound_fds, NULL, 0);
620   if (err)
621     {
622       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
623       goto leave;
624     }
625
626   /* Start GPG and send the INPUT and OUTPUT commands.  */
627   err = start_gpg (ctrl, gpg_program, gpg_arguments,
628                    outbound_fds[0], inbound_fds[1], &ctx);
629   if (err)
630     goto leave;
631   close (outbound_fds[0]); outbound_fds[0] = -1;
632   close (inbound_fds[1]); inbound_fds[1] = -1;
633
634   /* Start a writer thread to feed the INPUT command of the server.  */
635   err = start_writer (outbound_fds[1], ciph, ciphlen, cipher_stream,
636                       &writer_thread, &writer_err);
637   if (err)
638     return err;
639   outbound_fds[1] = -1;  /* The thread owns the FD now.  */
640
641   /* Start a reader thread to eat from the OUTPUT command of the
642      server.  */
643   err = start_reader (inbound_fds[0], reader_mb, plain_stream,
644                       &reader_thread, &reader_err);
645   if (err)
646     return err;
647   outbound_fds[0] = -1;  /* The thread owns the FD now.  */
648
649   /* Run the decryption.  */
650   err = assuan_transact (ctx, "DECRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
651   if (err)
652     {
653       log_error ("the engine's DECRYPT command failed: %s <%s>\n",
654                  gpg_strerror (err), gpg_strsource (err));
655       goto leave;
656     }
657
658   /* Wait for reader and return the data.  */
659   ret = npth_join (reader_thread, NULL);
660   if (ret)
661     {
662       err = my_error_from_errno (ret);
663       log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
664       goto leave;
665     }
666   memset (&reader_thread, '\0', sizeof (reader_thread));
667   if (reader_err)
668     {
669       err = reader_err;
670       log_error ("read error in reader thread: %s\n", gpg_strerror (err));
671       goto leave;
672     }
673
674   /* Wait for the writer to catch a writer error.  */
675   ret = npth_join (writer_thread, NULL);
676   if (ret)
677     {
678       err = my_error_from_errno (ret);
679       log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
680       goto leave;
681     }
682   memset (&writer_thread, '\0', sizeof (writer_thread));
683   if (writer_err)
684     {
685       err = writer_err;
686       log_error ("write error in writer thread: %s\n", gpg_strerror (err));
687       goto leave;
688     }
689
690  leave:
691   if (reader_thread)
692     npth_detach (reader_thread);
693   if (writer_thread)
694     npth_detach (writer_thread);
695   if (outbound_fds[0] != -1)
696     close (outbound_fds[0]);
697   if (outbound_fds[1] != -1)
698     close (outbound_fds[1]);
699   if (inbound_fds[0] != -1)
700     close (inbound_fds[0]);
701   if (inbound_fds[1] != -1)
702     close (inbound_fds[1]);
703   release_gpg (ctx);
704   return err;
705 }
706
707 gpg_error_t
708 gpg_decrypt_blob (ctrl_t ctrl,
709                   const char *gpg_program,
710                   strlist_t gpg_arguments,
711                   const void *ciph, size_t ciphlen,
712                   void **r_plain, size_t *r_plainlen)
713 {
714   gpg_error_t err;
715   membuf_t reader_mb;
716
717   *r_plain = NULL;
718   *r_plainlen = 0;
719
720   /* Init the memory buffer to receive the encrypted stuff.  */
721   init_membuf_secure (&reader_mb, 1024);
722
723   err = _gpg_decrypt (ctrl, gpg_program, gpg_arguments,
724                       ciph, ciphlen, NULL,
725                       &reader_mb, NULL);
726
727   if (! err)
728     {
729       /* Return the data.  */
730       *r_plain = get_membuf (&reader_mb, r_plainlen);
731       if (!*r_plain)
732         {
733           err = my_error_from_syserror ();
734           log_error ("error while storing the data in the reader thread: %s\n",
735                      gpg_strerror (err));
736         }
737     }
738
739   xfree (get_membuf (&reader_mb, NULL));
740   return err;
741 }
742
743 gpg_error_t
744 gpg_decrypt_stream (ctrl_t ctrl,
745                     const char *gpg_program,
746                     strlist_t gpg_arguments,
747                     estream_t cipher_stream,
748                     estream_t plain_stream)
749 {
750   return _gpg_decrypt (ctrl, gpg_program, gpg_arguments,
751                        NULL, 0, cipher_stream,
752                        NULL, plain_stream);
753 }