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 <https://www.gnu.org/licenses/>.
40 static GPGRT_INLINE gpg_error_t
41 my_error_from_syserror (void)
43 return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
46 static GPGRT_INLINE gpg_error_t
47 my_error_from_errno (int e)
49 return gpg_err_make (default_errsource, gpg_err_code_from_errno (e));
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. */
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)
60 assuan_context_t ctx = NULL;
63 assuan_fd_t no_close_list[5];
65 char line[ASSUAN_LINELENGTH];
71 err = assuan_new (&ctx);
74 log_error ("can't allocate assuan context: %s\n", gpg_strerror (err));
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);
82 /* Compute argv[0]. */
83 if ( !(pgmname = strrchr (gpg_program, '/')))
84 pgmname = gpg_program;
90 err = my_error_from_syserror ();
91 log_error ("error flushing pending output: %s\n", gpg_strerror (err));
95 argv = xtrycalloc (strlist_length (gpg_arguments) + 3, sizeof *argv);
98 err = my_error_from_syserror ();
103 argv[i++] = "--server";
104 for (; gpg_arguments; gpg_arguments = gpg_arguments->next)
105 argv[i++] = gpg_arguments->d;
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));
113 no_close_list[i++] = assuan_fd_from_posix_fd (input_fd);
115 no_close_list[i++] = assuan_fd_from_posix_fd (output_fd);
116 no_close_list[i] = ASSUAN_INVALID_FD;
118 /* Connect to GPG and perform initial handshaking. */
119 err = assuan_pipe_connect (ctx, gpg_program, argv, no_close_list,
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);
130 snprintf (line, sizeof line, "INPUT FD=%d", input_fd);
131 err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
134 assuan_release (ctx);
135 log_error ("error sending INPUT command: %s\n", gpg_strerror (err));
142 snprintf (line, sizeof line, "OUTPUT FD=%d", output_fd);
143 err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
146 assuan_release (ctx);
147 log_error ("error sending OUTPUT command: %s\n", gpg_strerror (err));
157 /* Release the assuan context created by start_gpg. */
159 release_gpg (assuan_context_t ctx)
161 assuan_release (ctx);
166 /* The data passed to the writer_thread. */
167 struct writer_thread_parms
173 gpg_error_t *err_addr;
177 /* The thread started by start_writer. */
179 writer_thread_main (void *arg)
182 struct writer_thread_parms *parm = arg;
190 err = es_read (parm->stream, buffer, sizeof _buffer, &length);
193 log_error ("reading stream failed: %s\n", gpg_strerror (err));
199 buffer = (char *) parm->data;
200 length = parm->datalen;
207 nwritten = npth_write (parm->fd, buffer, length < 4096? length:4096);
212 err = my_error_from_syserror ();
213 break; /* Write error. */
221 err = es_read (parm->stream, buffer, sizeof _buffer, &length);
224 log_error ("reading stream failed: %s\n",
238 *parm->err_addr = err;
239 if (close (parm->fd))
240 log_error ("closing writer fd %d failed: %s\n", parm->fd, strerror (errno));
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
252 start_writer (int fd, const void *data, size_t datalen, estream_t stream,
253 npth_t *r_thread, gpg_error_t *err_addr)
256 struct writer_thread_parms *parm;
261 memset (r_thread, '\0', sizeof (*r_thread));
264 parm = xtrymalloc (sizeof *parm);
266 return my_error_from_syserror ();
269 parm->datalen = datalen;
270 parm->stream = stream;
271 parm->err_addr = err_addr;
273 npth_attr_init (&tattr);
274 npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
276 ret = npth_create (&thread, &tattr, writer_thread_main, parm);
279 err = my_error_from_errno (ret);
280 log_error ("error spawning writer thread: %s\n", gpg_strerror (err));
284 npth_setname_np (thread, "fd-writer");
288 npth_attr_destroy (&tattr);
295 /* The data passed to the reader_thread. */
296 struct reader_thread_parms
301 gpg_error_t *err_addr;
305 /* The thread started by start_reader. */
307 reader_thread_main (void *arg)
310 struct reader_thread_parms *parm = arg;
314 while ( (nread = npth_read (parm->fd, buffer, sizeof buffer)) )
320 err = my_error_from_syserror ();
321 break; /* Read error. */
326 const char *p = buffer;
330 err = es_write (parm->stream, p, nread, &nwritten);
333 log_error ("writing stream failed: %s\n",
342 put_membuf (parm->mb, buffer, nread);
346 *parm->err_addr = err;
347 if (close (parm->fd))
348 log_error ("closing reader fd %d failed: %s\n", parm->fd, strerror (errno));
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. */
359 start_reader (int fd, membuf_t *mb, estream_t stream,
360 npth_t *r_thread, gpg_error_t *err_addr)
363 struct reader_thread_parms *parm;
368 memset (r_thread, '\0', sizeof (*r_thread));
371 parm = xtrymalloc (sizeof *parm);
373 return my_error_from_syserror ();
376 parm->stream = stream;
377 parm->err_addr = err_addr;
379 npth_attr_init (&tattr);
380 npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
382 ret = npth_create (&thread, &tattr, reader_thread_main, parm);
385 err = my_error_from_errno (ret);
386 log_error ("error spawning reader thread: %s\n", gpg_strerror (err));
390 npth_setname_np (thread, "fd-reader");
394 npth_attr_destroy (&tattr);
402 /* Call GPG to encrypt a block of data.
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,
414 estream_t cipher_stream)
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];
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));
432 /* Create two pipes. */
433 err = gnupg_create_outbound_pipe (outbound_fds, NULL, 0);
435 err = gnupg_create_inbound_pipe (inbound_fds, NULL, 0);
438 log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
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);
447 close (outbound_fds[0]); outbound_fds[0] = -1;
448 close (inbound_fds[1]); inbound_fds[1] = -1;
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);
455 outbound_fds[1] = -1; /* The thread owns the FD now. */
457 /* Start a reader thread to eat from the OUTPUT command of the
459 err = start_reader (inbound_fds[0], reader_mb, cipher_stream,
460 &reader_thread, &reader_err);
463 outbound_fds[0] = -1; /* The thread owns the FD now. */
465 /* Run the encryption. */
466 for (sl = keys; sl; sl = sl->next)
468 snprintf (line, sizeof line, "RECIPIENT -- %s", sl->d);
469 err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
472 log_error ("the engine's RECIPIENT command failed: %s <%s>\n",
473 gpg_strerror (err), gpg_strsource (err));
478 err = assuan_transact (ctx, "ENCRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
481 log_error ("the engine's ENCRYPT command failed: %s <%s>\n",
482 gpg_strerror (err), gpg_strsource (err));
486 /* Wait for reader and return the data. */
487 ret = npth_join (reader_thread, NULL);
490 err = my_error_from_errno (ret);
491 log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
494 /* FIXME: Not really valid, as npth_t is an opaque type. */
495 memset (&reader_thread, '\0', sizeof (reader_thread));
499 log_error ("read error in reader thread: %s\n", gpg_strerror (err));
503 /* Wait for the writer to catch a writer error. */
504 ret = npth_join (writer_thread, NULL);
507 err = my_error_from_errno (ret);
508 log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
511 memset (&writer_thread, '\0', sizeof (writer_thread));
515 log_error ("write error in writer thread: %s\n", gpg_strerror (err));
520 /* FIXME: Not valid, as npth_t is an opaque type. */
522 npth_detach (reader_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]);
538 gpg_encrypt_blob (ctrl_t ctrl,
539 const char *gpg_program,
540 strlist_t gpg_arguments,
541 const void *plain, size_t plainlen,
543 void **r_ciph, size_t *r_ciphlen)
551 /* Init the memory buffer to receive the encrypted stuff. */
552 init_membuf (&reader_mb, 4096);
554 err = _gpg_encrypt (ctrl, gpg_program, gpg_arguments,
555 plain, plainlen, NULL,
561 /* Return the data. */
562 *r_ciph = get_membuf (&reader_mb, r_ciphlen);
565 err = my_error_from_syserror ();
566 log_error ("error while storing the data in the reader thread: %s\n",
571 xfree (get_membuf (&reader_mb, NULL));
576 gpg_encrypt_stream (ctrl_t ctrl,
577 const char *gpg_program,
578 strlist_t gpg_arguments,
579 estream_t plain_stream,
581 estream_t cipher_stream)
583 return _gpg_encrypt (ctrl, gpg_program, gpg_arguments,
584 NULL, 0, plain_stream,
586 NULL, cipher_stream);
589 /* Call GPG to decrypt a block of data.
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,
600 estream_t plain_stream)
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;
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));
616 /* Create two pipes. */
617 err = gnupg_create_outbound_pipe (outbound_fds, NULL, 0);
619 err = gnupg_create_inbound_pipe (inbound_fds, NULL, 0);
622 log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
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);
631 close (outbound_fds[0]); outbound_fds[0] = -1;
632 close (inbound_fds[1]); inbound_fds[1] = -1;
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);
639 outbound_fds[1] = -1; /* The thread owns the FD now. */
641 /* Start a reader thread to eat from the OUTPUT command of the
643 err = start_reader (inbound_fds[0], reader_mb, plain_stream,
644 &reader_thread, &reader_err);
647 outbound_fds[0] = -1; /* The thread owns the FD now. */
649 /* Run the decryption. */
650 err = assuan_transact (ctx, "DECRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
653 log_error ("the engine's DECRYPT command failed: %s <%s>\n",
654 gpg_strerror (err), gpg_strsource (err));
658 /* Wait for reader and return the data. */
659 ret = npth_join (reader_thread, NULL);
662 err = my_error_from_errno (ret);
663 log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
666 memset (&reader_thread, '\0', sizeof (reader_thread));
670 log_error ("read error in reader thread: %s\n", gpg_strerror (err));
674 /* Wait for the writer to catch a writer error. */
675 ret = npth_join (writer_thread, NULL);
678 err = my_error_from_errno (ret);
679 log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
682 memset (&writer_thread, '\0', sizeof (writer_thread));
686 log_error ("write error in writer thread: %s\n", gpg_strerror (err));
692 npth_detach (reader_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]);
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)
720 /* Init the memory buffer to receive the encrypted stuff. */
721 init_membuf_secure (&reader_mb, 1024);
723 err = _gpg_decrypt (ctrl, gpg_program, gpg_arguments,
729 /* Return the data. */
730 *r_plain = get_membuf (&reader_mb, r_plainlen);
733 err = my_error_from_syserror ();
734 log_error ("error while storing the data in the reader thread: %s\n",
739 xfree (get_membuf (&reader_mb, NULL));
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)
750 return _gpg_decrypt (ctrl, gpg_program, gpg_arguments,
751 NULL, 0, cipher_stream,