1 /* call-gpg.c - Communication with the GPG
2 * Copyright (C) 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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/>.
34 #include "../common/exechelp.h"
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. */
41 start_gpg (ctrl_t ctrl, int input_fd, int output_fd, assuan_context_t *r_ctx)
44 assuan_context_t ctx = NULL;
49 char line[ASSUAN_LINELENGTH];
55 err = assuan_new (&ctx);
58 log_error ("can't allocate assuan context: %s\n", gpg_strerror (err));
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);
67 log_info (_("no running gpg - starting '%s'\n"), opt.gpg_program);
69 /* Compute argv[0]. */
70 if ( !(pgmname = strrchr (opt.gpg_program, '/')))
71 pgmname = opt.gpg_program;
77 err = gpg_error_from_syserror ();
78 log_error ("error flushing pending output: %s\n", gpg_strerror (err));
84 argv[i++] = "--server";
85 if ((opt.debug & 1024))
86 argv[i++] = "--debug=1024";
89 argv[i++] = "--trust-model";
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));
98 no_close_list[i++] = assuan_fd_from_posix_fd (input_fd);
100 no_close_list[i++] = assuan_fd_from_posix_fd (output_fd);
101 no_close_list[i] = -1;
103 /* Connect to GPG and perform initial handshaking. */
104 err = assuan_pipe_connect (ctx, opt.gpg_program, argv, no_close_list,
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);
115 snprintf (line, sizeof line, "INPUT FD=%d", input_fd);
116 err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
119 assuan_release (ctx);
120 log_error ("error sending INPUT command: %s\n", gpg_strerror (err));
127 snprintf (line, sizeof line, "OUTPUT FD=%d", output_fd);
128 err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
131 assuan_release (ctx);
132 log_error ("error sending OUTPUT command: %s\n", gpg_strerror (err));
140 log_debug ("connection to GPG established\n");
145 /* Release the assuan context created by start_gpg. */
147 release_gpg (assuan_context_t ctx)
149 assuan_release (ctx);
154 /* The data passed to the writer_thread. */
155 struct writer_thread_parms
160 gpg_error_t *err_addr;
164 /* The thread started by start_writer. */
166 writer_thread_main (void *arg)
168 struct writer_thread_parms *parm = arg;
169 const char *buffer = parm->data;
170 size_t length = parm->datalen;
176 nwritten = npth_write (parm->fd, buffer, length < 4096? length:4096);
181 *parm->err_addr = gpg_error_from_syserror ();
182 break; /* Write error. */
188 if (close (parm->fd))
189 log_error ("closing writer fd %d failed: %s\n", parm->fd, strerror (errno));
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
201 start_writer (int fd, const void *data, size_t datalen,
202 npth_t *r_thread, gpg_error_t *err_addr)
205 struct writer_thread_parms *parm;
210 memset (r_thread, '\0', sizeof (*r_thread));
213 parm = xtrymalloc (sizeof *parm);
215 return gpg_error_from_syserror ();
218 parm->datalen = datalen;
219 parm->err_addr = err_addr;
221 npth_attr_init (&tattr);
222 npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
224 ret = npth_create (&thread, &tattr, writer_thread_main, parm);
227 err = gpg_error_from_errno (ret);
228 log_error ("error spawning writer thread: %s\n", gpg_strerror (err));
232 npth_setname_np (thread, "fd-writer");
236 npth_attr_destroy (&tattr);
243 /* The data passed to the reader_thread. */
244 struct reader_thread_parms
248 gpg_error_t *err_addr;
252 /* The thread started by start_reader. */
254 reader_thread_main (void *arg)
256 struct reader_thread_parms *parm = arg;
260 while ( (nread = npth_read (parm->fd, buffer, sizeof buffer)) )
266 *parm->err_addr = gpg_error_from_syserror ();
267 break; /* Read error. */
270 put_membuf (parm->mb, buffer, nread);
273 if (close (parm->fd))
274 log_error ("closing reader fd %d failed: %s\n", parm->fd, strerror (errno));
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. */
285 start_reader (int fd, membuf_t *mb, npth_t *r_thread, gpg_error_t *err_addr)
288 struct reader_thread_parms *parm;
293 memset (r_thread, '\0', sizeof (*r_thread));
296 parm = xtrymalloc (sizeof *parm);
298 return gpg_error_from_syserror ();
301 parm->err_addr = err_addr;
303 npth_attr_init (&tattr);
304 npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
306 ret = npth_create (&thread, &tattr, reader_thread_main, parm);
309 err = gpg_error_from_errno (ret);
310 log_error ("error spawning reader thread: %s\n", gpg_strerror (err));
314 npth_setname_np (thread, "fd-reader");
318 npth_attr_destroy (&tattr);
326 /* Call GPG to encrypt a block of data.
331 gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen,
332 strlist_t keys, void **r_ciph, size_t *r_ciphlen)
335 assuan_context_t ctx = NULL;
336 int outbound_fds[2] = { -1, -1 };
337 int inbound_fds[2] = { -1, -1 };
338 npth_t writer_thread = (npth_t)0;
339 npth_t reader_thread = (npth_t)0;
340 gpg_error_t writer_err, reader_err;
342 char line[ASSUAN_LINELENGTH];
349 /* Init the memory buffer to receive the encrypted stuff. */
350 init_membuf (&reader_mb, 4096);
352 /* Create two pipes. */
353 err = gnupg_create_outbound_pipe (outbound_fds);
355 err = gnupg_create_inbound_pipe (inbound_fds);
358 log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
362 /* Start GPG and send the INPUT and OUTPUT commands. */
363 err = start_gpg (ctrl, outbound_fds[0], inbound_fds[1], &ctx);
366 close (outbound_fds[0]); outbound_fds[0] = -1;
367 close (inbound_fds[1]); inbound_fds[1] = -1;
369 /* Start a writer thread to feed the INPUT command of the server. */
370 err = start_writer (outbound_fds[1], plain, plainlen,
371 &writer_thread, &writer_err);
374 outbound_fds[1] = -1; /* The thread owns the FD now. */
376 /* Start a reader thread to eat from the OUTPUT command of the
378 err = start_reader (inbound_fds[0], &reader_mb,
379 &reader_thread, &reader_err);
382 outbound_fds[0] = -1; /* The thread owns the FD now. */
384 /* Run the encryption. */
385 for (sl = keys; sl; sl = sl->next)
387 snprintf (line, sizeof line, "RECIPIENT -- %s", sl->d);
388 err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
391 log_error ("the engine's RECIPIENT command failed: %s <%s>\n",
392 gpg_strerror (err), gpg_strsource (err));
397 err = assuan_transact (ctx, "ENCRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
400 log_error ("the engine's ENCRYPT command failed: %s <%s>\n",
401 gpg_strerror (err), gpg_strsource (err));
405 /* Wait for reader and return the data. */
406 ret = npth_join (reader_thread, NULL);
409 err = gpg_error_from_errno (ret);
410 log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
413 /* FIXME: Not really valid, as npth_t is an opaque type. */
414 memset (&reader_thread, '\0', sizeof (reader_thread));
418 log_error ("read error in reader thread: %s\n", gpg_strerror (err));
422 /* Wait for the writer to catch a writer error. */
423 ret = npth_join (writer_thread, NULL);
426 err = gpg_error_from_errno (ret);
427 log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
430 memset (&writer_thread, '\0', sizeof (writer_thread));
434 log_error ("write error in writer thread: %s\n", gpg_strerror (err));
438 /* Return the data. */
439 *r_ciph = get_membuf (&reader_mb, r_ciphlen);
442 err = gpg_error_from_syserror ();
443 log_error ("error while storing the data in the reader thread: %s\n",
449 /* FIXME: Not valid, as npth_t is an opaque type. */
451 npth_detach (reader_thread);
453 npth_detach (writer_thread);
454 if (outbound_fds[0] != -1)
455 close (outbound_fds[0]);
456 if (outbound_fds[1] != -1)
457 close (outbound_fds[1]);
458 if (inbound_fds[0] != -1)
459 close (inbound_fds[0]);
460 if (inbound_fds[1] != -1)
461 close (inbound_fds[1]);
463 xfree (get_membuf (&reader_mb, NULL));
469 /* Call GPG to decrypt a block of data.
474 gpg_decrypt_blob (ctrl_t ctrl, const void *ciph, size_t ciphlen,
475 void **r_plain, size_t *r_plainlen)
478 assuan_context_t ctx = NULL;
479 int outbound_fds[2] = { -1, -1 };
480 int inbound_fds[2] = { -1, -1 };
481 npth_t writer_thread = (npth_t)0;
482 npth_t reader_thread = (npth_t)0;
483 gpg_error_t writer_err, reader_err;
490 /* Init the memory buffer to receive the encrypted stuff. */
491 init_membuf_secure (&reader_mb, 1024);
493 /* Create two pipes. */
494 err = gnupg_create_outbound_pipe (outbound_fds);
496 err = gnupg_create_inbound_pipe (inbound_fds);
499 log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
503 /* Start GPG and send the INPUT and OUTPUT commands. */
504 err = start_gpg (ctrl, outbound_fds[0], inbound_fds[1], &ctx);
507 close (outbound_fds[0]); outbound_fds[0] = -1;
508 close (inbound_fds[1]); inbound_fds[1] = -1;
510 /* Start a writer thread to feed the INPUT command of the server. */
511 err = start_writer (outbound_fds[1], ciph, ciphlen,
512 &writer_thread, &writer_err);
515 outbound_fds[1] = -1; /* The thread owns the FD now. */
517 /* Start a reader thread to eat from the OUTPUT command of the
519 err = start_reader (inbound_fds[0], &reader_mb,
520 &reader_thread, &reader_err);
523 outbound_fds[0] = -1; /* The thread owns the FD now. */
525 /* Run the decryption. */
526 err = assuan_transact (ctx, "DECRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
529 log_error ("the engine's DECRYPT command failed: %s <%s>\n",
530 gpg_strerror (err), gpg_strsource (err));
534 /* Wait for reader and return the data. */
535 ret = npth_join (reader_thread, NULL);
538 err = gpg_error_from_errno (ret);
539 log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
542 memset (&reader_thread, '\0', sizeof (reader_thread));
546 log_error ("read error in reader thread: %s\n", gpg_strerror (err));
550 /* Wait for the writer to catch a writer error. */
551 ret = npth_join (writer_thread, NULL);
554 err = gpg_error_from_errno (ret);
555 log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
558 memset (&writer_thread, '\0', sizeof (writer_thread));
562 log_error ("write error in writer thread: %s\n", gpg_strerror (err));
566 /* Return the data. */
567 *r_plain = get_membuf (&reader_mb, r_plainlen);
570 err = gpg_error_from_syserror ();
571 log_error ("error while storing the data in the reader thread: %s\n",
578 npth_detach (reader_thread);
580 npth_detach (writer_thread);
581 if (outbound_fds[0] != -1)
582 close (outbound_fds[0]);
583 if (outbound_fds[1] != -1)
584 close (outbound_fds[1]);
585 if (inbound_fds[0] != -1)
586 close (inbound_fds[0]);
587 if (inbound_fds[1] != -1)
588 close (inbound_fds[1]);
590 xfree (get_membuf (&reader_mb, NULL));