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