Renamed the lock functions.
[gnupg.git] / g13 / 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 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <time.h>
26 #include <assert.h>
27 #include <pth.h>
28
29 #include "g13.h"
30 #include <assuan.h>
31 #include "i18n.h"
32 #include "call-gpg.h"
33 #include "utils.h"
34 #include "../common/exechelp.h"
35
36
37 \f
38 /* Fire up a new GPG.  Handle the server's initial greeting.  Returns
39    0 on success and stores the assuan context at R_CTX.  */
40 static gpg_error_t
41 start_gpg (ctrl_t ctrl, int input_fd, int output_fd, assuan_context_t *r_ctx)
42 {
43   gpg_error_t err;
44   assuan_context_t ctx = NULL;
45   const char *pgmname;
46   const char *argv[10];
47   int no_close_list[5];
48   int i;
49   char line[ASSUAN_LINELENGTH];
50
51   (void)ctrl;
52
53   *r_ctx = NULL;
54
55   err = assuan_new (&ctx);
56   if (err)
57     {
58       log_error ("can't allocate assuan context: %s\n", gpg_strerror (err));
59       return err;
60     }
61
62   /* The first time we are used, intialize the gpg_program variable.  */
63   if ( !opt.gpg_program || !*opt.gpg_program )
64     opt.gpg_program = gnupg_module_name (GNUPG_MODULE_NAME_GPG);
65
66   if (opt.verbose)
67     log_info (_("no running gpg - starting `%s'\n"), opt.gpg_program);
68
69   /* Compute argv[0].  */
70   if ( !(pgmname = strrchr (opt.gpg_program, '/')))
71     pgmname = opt.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   i = 0;
83   argv[i++] = pgmname;
84   argv[i++] = "--server";
85   if ((opt.debug & 1024))
86     argv[i++] = "--debug=1024";
87   argv[i++] = "-z";
88   argv[i++] = "0";
89   argv[i++] = "--trust-model";
90   argv[i++] = "always";
91   argv[i++] = NULL;
92
93   i = 0;
94   if (log_get_fd () != -1)
95     no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ());
96   no_close_list[i++] = assuan_fd_from_posix_fd (fileno (stderr));
97   if (input_fd != -1)
98     no_close_list[i++] = assuan_fd_from_posix_fd (input_fd);
99   if (output_fd != -1)
100     no_close_list[i++] = assuan_fd_from_posix_fd (output_fd);
101   no_close_list[i] = -1;
102
103   /* Connect to GPG and perform initial handshaking.  */
104   err = assuan_pipe_connect (ctx, opt.gpg_program, argv, no_close_list,
105                              NULL, NULL, 0);
106   if (err)
107     {
108       assuan_release (ctx);
109       log_error ("can't connect to GPG: %s\n", gpg_strerror (err));
110       return gpg_error (GPG_ERR_NO_ENGINE);
111     }
112
113   if (input_fd != -1)
114     {
115       snprintf (line, sizeof line, "INPUT FD=%d", input_fd);
116       err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
117       if (err)
118         {
119           assuan_release (ctx);
120           log_error ("error sending INPUT command: %s\n", gpg_strerror (err));
121           return err;
122         }
123     }
124
125   if (output_fd != -1)
126     {
127       snprintf (line, sizeof line, "OUTPUT FD=%d", output_fd);
128       err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
129       if (err)
130         {
131           assuan_release (ctx);
132           log_error ("error sending OUTPUT command: %s\n", gpg_strerror (err));
133           return err;
134         }
135     }
136
137   *r_ctx = ctx;
138
139   if (DBG_ASSUAN)
140     log_debug ("connection to GPG established\n");
141   return 0;
142 }
143
144
145 /* Release the assuan context created by start_gpg.  */
146 static void
147 release_gpg (assuan_context_t ctx)
148 {
149   assuan_release (ctx);
150 }
151
152
153 \f
154 /* The data passed to the writer_thread.  */
155 struct writer_thread_parms
156 {
157   int fd;
158   const void *data;
159   size_t datalen;
160   gpg_error_t *err_addr;
161 };
162
163
164 /* The thread started by start_writer.  */
165 static void *
166 writer_thread (void *arg)
167 {
168   struct writer_thread_parms *parm = arg;
169   const char *buffer = parm->data;
170   size_t length = parm->datalen;
171
172   while (length)
173     {
174       ssize_t nwritten;
175
176       nwritten = pth_write (parm->fd, buffer, length < 4096? length:4096);
177       if (nwritten < 0)
178         {
179           if (errno == EINTR)
180             continue;
181           *parm->err_addr = gpg_error_from_syserror ();
182           break; /* Write error.  */
183         }
184       length -= nwritten;
185       buffer += nwritten;
186     }
187
188   if (close (parm->fd))
189     log_error ("closing writer fd %d failed: %s\n", parm->fd, strerror (errno));
190   xfree (parm);
191   return NULL;
192 }
193
194
195 /* Fire up a thread to send (DATA,DATALEN) to the file descriptor FD.
196    On success the thread receives the ownership over FD.  The thread
197    ID is stored at R_TID.  WRITER_ERR is the address of an gpg_error_t
198    variable to receive a possible write error after the thread has
199    finished.  */
200 static gpg_error_t
201 start_writer (int fd, const void *data, size_t datalen,
202               pth_t *r_tid, gpg_error_t *err_addr)
203 {
204   gpg_error_t err;
205   struct writer_thread_parms *parm;
206   pth_attr_t tattr;
207   pth_t tid;
208
209   *r_tid = NULL;
210   *err_addr = 0;
211
212   parm = xtrymalloc (sizeof *parm);
213   if (!parm)
214     return gpg_error_from_syserror ();
215   parm->fd = fd;
216   parm->data = data;
217   parm->datalen = datalen;
218   parm->err_addr = err_addr;
219
220   tattr = pth_attr_new ();
221   pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
222   pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 64*1024);
223   pth_attr_set (tattr, PTH_ATTR_NAME, "fd-writer");
224
225   tid = pth_spawn (tattr, writer_thread, parm);
226   if (!tid)
227     {
228       err = gpg_error_from_syserror ();
229       log_error ("error spawning writer thread: %s\n", gpg_strerror (err));
230     }
231   else
232     {
233       err = 0;
234       *r_tid = tid;
235     }
236   pth_attr_destroy (tattr);
237
238   return err;
239 }
240
241
242 \f
243 /* The data passed to the reader_thread.  */
244 struct reader_thread_parms
245 {
246   int fd;
247   membuf_t *mb;
248   gpg_error_t *err_addr;
249 };
250
251
252 /* The thread started by start_reader.  */
253 static void *
254 reader_thread (void *arg)
255 {
256   struct reader_thread_parms *parm = arg;
257   char buffer[4096];
258   int nread;
259
260   while ( (nread = pth_read (parm->fd, buffer, sizeof buffer)) )
261     {
262       if (nread < 0)
263         {
264           if (errno == EINTR)
265             continue;
266           *parm->err_addr = gpg_error_from_syserror ();
267           break;  /* Read error.  */
268         }
269
270       put_membuf (parm->mb, buffer, nread);
271     }
272
273   if (close (parm->fd))
274     log_error ("closing reader fd %d failed: %s\n", parm->fd, strerror (errno));
275   xfree (parm);
276   return NULL;
277 }
278
279
280 /* Fire up a thread to receive data from the file descriptor FD.  On
281    success the thread receives the ownership over FD.  The thread ID
282    is stored at R_TID.  After the thread has finished an error from
283    the thread will be stored at ERR_ADDR.  */
284 static gpg_error_t
285 start_reader (int fd, membuf_t *mb, pth_t *r_tid, gpg_error_t *err_addr)
286 {
287   gpg_error_t err;
288   struct reader_thread_parms *parm;
289   pth_attr_t tattr;
290   pth_t tid;
291
292   *r_tid = NULL;
293   *err_addr = 0;
294
295   parm = xtrymalloc (sizeof *parm);
296   if (!parm)
297     return gpg_error_from_syserror ();
298   parm->fd = fd;
299   parm->mb = mb;
300   parm->err_addr = err_addr;
301
302   tattr = pth_attr_new ();
303   pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
304   pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 64*1024);
305   pth_attr_set (tattr, PTH_ATTR_NAME, "fd-reader");
306
307   tid = pth_spawn (tattr, reader_thread, parm);
308   if (!tid)
309     {
310       err = gpg_error_from_syserror ();
311       log_error ("error spawning reader thread: %s\n", gpg_strerror (err));
312     }
313   else
314     {
315       err = 0;
316       *r_tid = tid;
317     }
318   pth_attr_destroy (tattr);
319
320   return err;
321 }
322
323
324
325 \f
326 /* Call GPG to encrypt a block of data.
327
328
329  */
330 gpg_error_t
331 gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen,
332                   strlist_t keys, void **r_ciph, size_t *r_ciphlen)
333 {
334   gpg_error_t err;
335   assuan_context_t ctx;
336   int outbound_fds[2] = { -1, -1 };
337   int inbound_fds[2]  = { -1, -1 };
338   pth_t writer_tid = NULL;
339   pth_t reader_tid = NULL;
340   gpg_error_t writer_err, reader_err;
341   membuf_t reader_mb;
342   char line[ASSUAN_LINELENGTH];
343   strlist_t sl;
344
345   *r_ciph = NULL;
346   *r_ciphlen = 0;
347
348   /* Init the memory buffer to receive the encrypted stuff.  */
349   init_membuf (&reader_mb, 4096);
350
351   /* Create two pipes.  */
352   err = gnupg_create_outbound_pipe (outbound_fds);
353   if (!err)
354     err = gnupg_create_inbound_pipe (inbound_fds);
355   if (err)
356     {
357       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
358       goto leave;
359     }
360
361   /* Start GPG and send the INPUT and OUTPUT commands.  */
362   err = start_gpg (ctrl, outbound_fds[0], inbound_fds[1], &ctx);
363   if (err)
364     goto leave;
365   close (outbound_fds[0]); outbound_fds[0] = -1;
366   close (inbound_fds[1]); inbound_fds[1] = -1;
367
368   /* Start a writer thread to feed the INPUT command of the server.  */
369   err = start_writer (outbound_fds[1], plain, plainlen,
370                       &writer_tid, &writer_err);
371   if (err)
372     return err;
373   outbound_fds[1] = -1;  /* The thread owns the FD now.  */
374
375   /* Start a reader thread to eat from the OUTPUT command of the
376      server.  */
377   err = start_reader (inbound_fds[0], &reader_mb,
378                       &reader_tid, &reader_err);
379   if (err)
380     return err;
381   outbound_fds[0] = -1;  /* The thread owns the FD now.  */
382
383   /* Run the encryption.  */
384   for (sl = keys; sl; sl = sl->next)
385     {
386       snprintf (line, sizeof line, "RECIPIENT -- %s", sl->d);
387       err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
388       if (err)
389         {
390           log_error ("the engine's RECIPIENT command failed: %s <%s>\n",
391                  gpg_strerror (err), gpg_strsource (err));
392           goto leave;
393         }
394     }
395
396   err = assuan_transact (ctx, "ENCRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
397   if (err)
398     {
399       log_error ("the engine's ENCRYPT command failed: %s <%s>\n",
400                  gpg_strerror (err), gpg_strsource (err));
401       goto leave;
402     }
403
404   /* Wait for reader and return the data.  */
405   if (!pth_join (reader_tid, NULL))
406     {
407       err = gpg_error_from_syserror ();
408       log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
409       goto leave;
410     }
411   reader_tid = NULL;
412   if (reader_err)
413     {
414       err = reader_err;
415       log_error ("read error in reader thread: %s\n", gpg_strerror (err));
416       goto leave;
417     }
418
419   /* Wait for the writer to catch  a writer error.  */
420   if (!pth_join (writer_tid, NULL))
421     {
422       err = gpg_error_from_syserror ();
423       log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
424       goto leave;
425     }
426   writer_tid = NULL;
427   if (writer_err)
428     {
429       err = writer_err;
430       log_error ("write error in writer thread: %s\n", gpg_strerror (err));
431       goto leave;
432     }
433
434   /* Return the data.  */
435   *r_ciph = get_membuf (&reader_mb, r_ciphlen);
436   if (!*r_ciph)
437     {
438       err = gpg_error_from_syserror ();
439       log_error ("error while storing the data in the reader thread: %s\n",
440                  gpg_strerror (err));
441       goto leave;
442     }
443
444  leave:
445   if (reader_tid)
446     {
447       pth_cancel (reader_tid);
448       pth_join (reader_tid, NULL);
449     }
450   if (writer_tid)
451     {
452       pth_cancel (writer_tid);
453       pth_join (writer_tid, NULL);
454     }
455   if (outbound_fds[0] != -1)
456     close (outbound_fds[0]);
457   if (outbound_fds[1] != -1)
458     close (outbound_fds[1]);
459   if (inbound_fds[0] != -1)
460     close (inbound_fds[0]);
461   if (inbound_fds[1] != -1)
462     close (inbound_fds[1]);
463   release_gpg (ctx);
464   xfree (get_membuf (&reader_mb, NULL));
465   return err;
466 }
467
468
469 \f
470 /* Call GPG to decrypt a block of data.
471
472
473  */
474 gpg_error_t
475 gpg_decrypt_blob (ctrl_t ctrl, const void *ciph, size_t ciphlen,
476                   void **r_plain, size_t *r_plainlen)
477 {
478   gpg_error_t err;
479   assuan_context_t ctx;
480   int outbound_fds[2] = { -1, -1 };
481   int inbound_fds[2]  = { -1, -1 };
482   pth_t writer_tid = NULL;
483   pth_t reader_tid = NULL;
484   gpg_error_t writer_err, reader_err;
485   membuf_t reader_mb;
486
487   *r_plain = NULL;
488   *r_plainlen = 0;
489
490   /* Init the memory buffer to receive the encrypted stuff.  */
491   init_membuf_secure (&reader_mb, 1024);
492
493   /* Create two pipes.  */
494   err = gnupg_create_outbound_pipe (outbound_fds);
495   if (!err)
496     err = gnupg_create_inbound_pipe (inbound_fds);
497   if (err)
498     {
499       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
500       goto leave;
501     }
502
503   /* Start GPG and send the INPUT and OUTPUT commands.  */
504   err = start_gpg (ctrl, outbound_fds[0], inbound_fds[1], &ctx);
505   if (err)
506     goto leave;
507   close (outbound_fds[0]); outbound_fds[0] = -1;
508   close (inbound_fds[1]); inbound_fds[1] = -1;
509
510   /* Start a writer thread to feed the INPUT command of the server.  */
511   err = start_writer (outbound_fds[1], ciph, ciphlen,
512                       &writer_tid, &writer_err);
513   if (err)
514     return err;
515   outbound_fds[1] = -1;  /* The thread owns the FD now.  */
516
517   /* Start a reader thread to eat from the OUTPUT command of the
518      server.  */
519   err = start_reader (inbound_fds[0], &reader_mb,
520                       &reader_tid, &reader_err);
521   if (err)
522     return err;
523   outbound_fds[0] = -1;  /* The thread owns the FD now.  */
524
525   /* Run the decryption.  */
526   err = assuan_transact (ctx, "DECRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
527   if (err)
528     {
529       log_error ("the engine's DECRYPT command failed: %s <%s>\n",
530                  gpg_strerror (err), gpg_strsource (err));
531       goto leave;
532     }
533
534   /* Wait for reader and return the data.  */
535   if (!pth_join (reader_tid, NULL))
536     {
537       err = gpg_error_from_syserror ();
538       log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
539       goto leave;
540     }
541   reader_tid = NULL;
542   if (reader_err)
543     {
544       err = reader_err;
545       log_error ("read error in reader thread: %s\n", gpg_strerror (err));
546       goto leave;
547     }
548
549   /* Wait for the writer to catch a writer error.  */
550   if (!pth_join (writer_tid, NULL))
551     {
552       err = gpg_error_from_syserror ();
553       log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
554       goto leave;
555     }
556   writer_tid = NULL;
557   if (writer_err)
558     {
559       err = writer_err;
560       log_error ("write error in writer thread: %s\n", gpg_strerror (err));
561       goto leave;
562     }
563
564   /* Return the data.  */
565   *r_plain = get_membuf (&reader_mb, r_plainlen);
566   if (!*r_plain)
567     {
568       err = gpg_error_from_syserror ();
569       log_error ("error while storing the data in the reader thread: %s\n",
570                  gpg_strerror (err));
571       goto leave;
572     }
573
574  leave:
575   if (reader_tid)
576     {
577       pth_cancel (reader_tid);
578       pth_join (reader_tid, NULL);
579     }
580   if (writer_tid)
581     {
582       pth_cancel (writer_tid);
583       pth_join (writer_tid, NULL);
584     }
585   if (outbound_fds[0] != -1)
586     close (outbound_fds[0]);
587   if (outbound_fds[1] != -1)
588     close (outbound_fds[1]);
589   if (inbound_fds[0] != -1)
590     close (inbound_fds[0]);
591   if (inbound_fds[1] != -1)
592     close (inbound_fds[1]);
593   release_gpg (ctx);
594   xfree (get_membuf (&reader_mb, NULL));
595   return err;
596 }