1 /* engine-gpg.c - Gpg Engine.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4 2009, 2010, 2012, 2013 g10 Code GmbH
6 This file is part of GPGME.
8 GPGME is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 GPGME is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with this program; if not, see <https://www.gnu.org/licenses/>.
40 #include "context.h" /*temp hack until we have GpmeData methods to do I/O */
45 #include "mbox-util.h"
47 #include "engine-backend.h"
50 /* This type is used to build a list of gpg arguments and data
54 struct arg_and_data_s *next;
55 gpgme_data_t data; /* If this is not NULL, use arg below. */
56 int inbound; /* True if this is used for reading from gpg. */
58 int print_fd; /* Print the fd number and not the special form of it. */
59 int *arg_locp; /* Write back the argv idx of this argument when
60 building command line to this location. */
61 char arg[1]; /* Used if data above is not used. */
68 int inbound; /* true if this is used for reading from gpg */
70 int fd; /* the fd to use */
71 int peer_fd; /* the other side of the pipe */
72 int arg_loc; /* The index into the argv for translation purposes. */
77 /* NB.: R_LINE is allocated an gpgrt function and thus gpgrt_free
78 * shall be used to release it. This takes care of custom memory
79 * allocators and avoids problems on Windows with different runtimes
80 * used for libgpg-error/gpgrt and gpgme. */
81 typedef gpgme_error_t (*colon_preprocessor_t) (char *line, char **rline);
91 struct arg_and_data_s *arglist;
92 struct arg_and_data_s **argtail;
102 engine_status_handler_t fnc;
104 gpgme_status_cb_t mon_cb;
109 /* This is a kludge - see the comment at colon_line_handler. */
118 engine_colon_line_handler_t fnc; /* this indicate use of this structrue */
121 colon_preprocessor_t preprocess_fnc;
125 struct fd_data_map_s *fd_data_map;
127 /* stuff needed for interactive (command) mode */
133 int idx; /* Index in fd_data_map */
134 gpgme_status_code_t code; /* last code */
135 char *keyword; /* what has been requested (malloced) */
136 engine_command_handler_t fnc;
140 struct gpgme_io_cbs io_cbs;
141 gpgme_pinentry_mode_t pinentry_mode;
142 char request_origin[10];
143 char *auto_key_locate;
147 unsigned int no_symkey_cache : 1;
148 unsigned int offline : 1;
149 unsigned int ignore_mdc_error : 1;
152 /* NULL or the data object fed to --override_session_key-fd. */
153 gpgme_data_t override_session_key;
155 /* Memory data containing diagnostics (--logger-fd) of gpg */
156 gpgme_data_t diagnostics;
159 typedef struct engine_gpg *engine_gpg_t;
163 gpg_io_event (void *engine, gpgme_event_io_t type, void *type_data)
165 engine_gpg_t gpg = engine;
167 TRACE3 (DEBUG_ENGINE, "gpgme:gpg_io_event", gpg,
168 "event %p, type %d, type_data %p",
169 gpg->io_cbs.event, type, type_data);
170 if (gpg->io_cbs.event)
171 (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data);
176 close_notify_handler (int fd, void *opaque)
178 engine_gpg_t gpg = opaque;
181 if (gpg->status.fd[0] == fd)
184 (*gpg->io_cbs.remove) (gpg->status.tag);
185 gpg->status.fd[0] = -1;
187 else if (gpg->status.fd[1] == fd)
188 gpg->status.fd[1] = -1;
189 else if (gpg->colon.fd[0] == fd)
192 (*gpg->io_cbs.remove) (gpg->colon.tag);
193 gpg->colon.fd[0] = -1;
195 else if (gpg->colon.fd[1] == fd)
196 gpg->colon.fd[1] = -1;
197 else if (gpg->cmd.fd == fd)
199 else if (gpg->fd_data_map)
203 for (i = 0; gpg->fd_data_map[i].data; i++)
205 if (gpg->fd_data_map[i].fd == fd)
207 if (gpg->fd_data_map[i].tag)
208 (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
209 gpg->fd_data_map[i].fd = -1;
212 if (gpg->fd_data_map[i].peer_fd == fd)
214 gpg->fd_data_map[i].peer_fd = -1;
221 /* If FRONT is true, push at the front of the list. Use this for
222 options added late in the process. */
224 _add_arg (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen,
225 int front, int *arg_locp)
227 struct arg_and_data_s *a;
228 size_t prefixlen = prefix? strlen (prefix) : 0;
233 a = malloc (sizeof *a + prefixlen + arglen);
235 return gpg_error_from_syserror ();
239 a->arg_locp = arg_locp;
242 memcpy (a->arg, prefix, prefixlen);
243 memcpy (a->arg + prefixlen, arg, arglen);
244 a->arg[prefixlen + arglen] = 0;
247 a->next = gpg->arglist;
250 /* If this is the first argument, we need to update the tail
252 gpg->argtail = &a->next;
260 gpg->argtail = &a->next;
268 add_arg_ext (engine_gpg_t gpg, const char *arg, int front)
270 return _add_arg (gpg, NULL, arg, strlen (arg), front, NULL);
274 add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp)
276 return _add_arg (gpg, NULL, arg, strlen (arg), 0, locp);
280 add_arg (engine_gpg_t gpg, const char *arg)
282 return _add_arg (gpg, NULL, arg, strlen (arg), 0, NULL);
286 add_arg_pfx (engine_gpg_t gpg, const char *prefix, const char *arg)
288 return _add_arg (gpg, prefix, arg, strlen (arg), 0, NULL);
292 add_arg_len (engine_gpg_t gpg, const char *prefix,
293 const char *arg, size_t arglen)
295 return _add_arg (gpg, prefix, arg, arglen, 0, NULL);
300 add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
302 struct arg_and_data_s *a;
307 a = malloc (sizeof *a - 1);
309 return gpg_error_from_syserror ();
312 a->inbound = inbound;
326 gpg->argtail = &a->next;
331 /* Return true if the engine's version is at least VERSION. */
333 have_gpg_version (engine_gpg_t gpg, const char *version)
335 return _gpgme_compare_versions (gpg->version, version);
341 gpg_get_version (const char *file_name)
343 return _gpgme_get_program_version (file_name ? file_name
344 : _gpgme_get_default_gpg_name ());
349 gpg_get_req_version (void)
356 free_argv (char **argv)
360 for (i = 0; argv[i]; i++)
367 free_fd_data_map (struct fd_data_map_s *fd_data_map)
374 for (i = 0; fd_data_map[i].data; i++)
376 if (fd_data_map[i].fd != -1)
377 _gpgme_io_close (fd_data_map[i].fd);
378 if (fd_data_map[i].peer_fd != -1)
379 _gpgme_io_close (fd_data_map[i].peer_fd);
380 /* Don't release data because this is only a reference. */
387 gpg_cancel (void *engine)
389 engine_gpg_t gpg = engine;
392 return gpg_error (GPG_ERR_INV_VALUE);
394 /* If gpg may be waiting for a cmd, close the cmd fd first. On
395 Windows, close operations block on the reader/writer thread. */
398 if (gpg->cmd.fd != -1)
399 _gpgme_io_close (gpg->cmd.fd);
400 else if (gpg->fd_data_map
401 && gpg->fd_data_map[gpg->cmd.idx].fd != -1)
402 _gpgme_io_close (gpg->fd_data_map[gpg->cmd.idx].fd);
405 if (gpg->status.fd[0] != -1)
406 _gpgme_io_close (gpg->status.fd[0]);
407 if (gpg->status.fd[1] != -1)
408 _gpgme_io_close (gpg->status.fd[1]);
409 if (gpg->colon.fd[0] != -1)
410 _gpgme_io_close (gpg->colon.fd[0]);
411 if (gpg->colon.fd[1] != -1)
412 _gpgme_io_close (gpg->colon.fd[1]);
413 if (gpg->fd_data_map)
415 free_fd_data_map (gpg->fd_data_map);
416 gpg->fd_data_map = NULL;
423 gpg_release (void *engine)
425 engine_gpg_t gpg = engine;
433 free (gpg->file_name);
437 if (gpg->lc_messages)
438 free (gpg->lc_messages);
440 free (gpg->lc_ctype);
444 struct arg_and_data_s *next = gpg->arglist->next;
450 if (gpg->status.buffer)
451 free (gpg->status.buffer);
452 if (gpg->colon.buffer)
453 free (gpg->colon.buffer);
455 free_argv (gpg->argv);
456 if (gpg->cmd.keyword)
457 free (gpg->cmd.keyword);
458 free (gpg->auto_key_locate);
459 free (gpg->trust_model);
461 gpgme_data_release (gpg->override_session_key);
462 gpgme_data_release (gpg->diagnostics);
469 gpg_new (void **engine, const char *file_name, const char *home_dir,
473 gpgme_error_t rc = 0;
474 char *dft_display = NULL;
475 char dft_ttyname[64];
476 char *dft_ttytype = NULL;
477 char *env_tty = NULL;
479 gpg = calloc (1, sizeof *gpg);
481 return gpg_error_from_syserror ();
485 gpg->file_name = strdup (file_name);
488 rc = gpg_error_from_syserror ();
495 gpg->version = strdup (version);
498 rc = gpg_error_from_syserror ();
503 gpg->argtail = &gpg->arglist;
504 gpg->status.fd[0] = -1;
505 gpg->status.fd[1] = -1;
506 gpg->colon.fd[0] = -1;
507 gpg->colon.fd[1] = -1;
511 /* Allocate the read buffer for the status pipe. */
512 gpg->status.bufsize = 1024;
513 gpg->status.readpos = 0;
514 gpg->status.buffer = malloc (gpg->status.bufsize);
515 if (!gpg->status.buffer)
517 rc = gpg_error_from_syserror ();
520 /* In any case we need a status pipe - create it right here and
521 don't handle it with our generic gpgme_data_t mechanism. */
522 if (_gpgme_io_pipe (gpg->status.fd, 1) == -1)
524 rc = gpg_error_from_syserror ();
527 if (_gpgme_io_set_close_notify (gpg->status.fd[0],
528 close_notify_handler, gpg)
529 || _gpgme_io_set_close_notify (gpg->status.fd[1],
530 close_notify_handler, gpg))
532 rc = gpg_error (GPG_ERR_GENERAL);
539 rc = add_arg (gpg, "--homedir");
541 rc = add_arg (gpg, home_dir);
546 rc = add_arg (gpg, "--status-fd");
552 _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]);
553 rc = add_arg_with_locp (gpg, buf, &gpg->status.arg_loc);
558 rc = add_arg (gpg, "--no-tty");
560 rc = add_arg (gpg, "--charset");
562 rc = add_arg (gpg, "utf8");
564 rc = add_arg (gpg, "--enable-progress-filter");
565 if (!rc && have_gpg_version (gpg, "2.1.11"))
566 rc = add_arg (gpg, "--exit-on-status-write-error");
570 rc = _gpgme_getenv ("DISPLAY", &dft_display);
575 rc = add_arg (gpg, "--display");
577 rc = add_arg (gpg, dft_display);
584 rc = _gpgme_getenv ("GPG_TTY", &env_tty);
585 if (isatty (1) || env_tty || rc)
593 snprintf (dft_ttyname, sizeof (dft_ttyname), "%s", env_tty);
597 err = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
599 /* Even though isatty() returns 1, ttyname_r() may fail in many
600 ways, e.g., when /dev/pts is not accessible under chroot. */
605 rc = add_arg (gpg, "--ttyname");
607 rc = add_arg (gpg, dft_ttyname);
613 rc = _gpgme_getenv ("TERM", &dft_ttytype);
619 rc = add_arg (gpg, "--ttytype");
621 rc = add_arg (gpg, dft_ttytype);
631 rc = gpgme_data_new (&gpg->diagnostics);
635 rc = add_arg (gpg, "--logger-fd");
639 rc = add_data (gpg, gpg->diagnostics, -2, 1);
650 /* Copy flags from CTX into the engine object. */
652 gpg_set_engine_flags (void *engine, const gpgme_ctx_t ctx)
654 engine_gpg_t gpg = engine;
656 if (ctx->request_origin && have_gpg_version (gpg, "2.2.6"))
658 if (strlen (ctx->request_origin) + 1 > sizeof gpg->request_origin)
659 strcpy (gpg->request_origin, "xxx"); /* Too long - force error */
661 strcpy (gpg->request_origin, ctx->request_origin);
664 *gpg->request_origin = 0;
666 if (ctx->auto_key_locate && have_gpg_version (gpg, "2.1.18"))
668 if (gpg->auto_key_locate)
669 free (gpg->auto_key_locate);
670 gpg->auto_key_locate = _gpgme_strconcat ("--auto-key-locate=",
671 ctx->auto_key_locate, NULL);
674 if (ctx->trust_model && strlen (ctx->trust_model))
676 if (gpg->trust_model)
677 free (gpg->trust_model);
678 gpg->trust_model = _gpgme_strconcat ("--trust-model=",
679 ctx->trust_model, NULL);
682 gpg->flags.no_symkey_cache = (ctx->no_symkey_cache
683 && have_gpg_version (gpg, "2.2.7"));
684 gpg->flags.offline = (ctx->offline && have_gpg_version (gpg, "2.1.23"));
686 gpg->flags.ignore_mdc_error = !!ctx->ignore_mdc_error;
692 gpg_set_locale (void *engine, int category, const char *value)
694 engine_gpg_t gpg = engine;
699 else if (category == LC_CTYPE)
703 free (gpg->lc_ctype);
704 gpg->lc_ctype = NULL;
708 gpg->lc_ctype = strdup (value);
710 return gpg_error_from_syserror ();
715 else if (category == LC_MESSAGES)
717 if (gpg->lc_messages)
719 free (gpg->lc_messages);
720 gpg->lc_messages = NULL;
724 gpg->lc_messages = strdup (value);
725 if (!gpg->lc_messages)
726 return gpg_error_from_syserror ();
729 #endif /* LC_MESSAGES */
731 return gpg_error (GPG_ERR_INV_VALUE);
736 /* This sets a status callback for monitoring status lines before they
737 * are passed to a caller set handler. */
739 gpg_set_status_cb (void *engine, gpgme_status_cb_t cb, void *cb_value)
741 engine_gpg_t gpg = engine;
743 gpg->status.mon_cb = cb;
744 gpg->status.mon_cb_value = cb_value;
748 /* Note, that the status_handler is allowed to modify the args
751 gpg_set_status_handler (void *engine, engine_status_handler_t fnc,
754 engine_gpg_t gpg = engine;
756 gpg->status.fnc = fnc;
757 gpg->status.fnc_value = fnc_value;
760 /* Kludge to process --with-colon output. */
762 gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
765 engine_gpg_t gpg = engine;
767 gpg->colon.bufsize = 1024;
768 gpg->colon.readpos = 0;
769 gpg->colon.buffer = malloc (gpg->colon.bufsize);
770 if (!gpg->colon.buffer)
771 return gpg_error_from_syserror ();
773 if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1)
775 int saved_err = gpg_error_from_syserror ();
776 free (gpg->colon.buffer);
777 gpg->colon.buffer = NULL;
780 if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg)
781 || _gpgme_io_set_close_notify (gpg->colon.fd[1],
782 close_notify_handler, gpg))
783 return gpg_error (GPG_ERR_GENERAL);
785 gpg->colon.fnc = fnc;
786 gpg->colon.fnc_value = fnc_value;
792 command_handler (void *opaque, int fd)
794 struct io_cb_data *data = (struct io_cb_data *) opaque;
795 engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
798 assert (gpg->cmd.used);
799 assert (gpg->cmd.code);
800 assert (gpg->cmd.fnc);
802 err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd,
806 /* And sleep again until read_status will wake us up again. */
807 /* XXX We must check if there are any more fds active after removing
809 (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag);
810 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
811 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
816 /* We always need to send at least a newline character. */
818 _gpgme_io_write (fd, "\n", 1);
825 /* The FNC will be called to get a value for one of the commands with
826 * a key KEY. If the code passed to FNC is 0, the function may
827 * release resources associated with the returned value from another
828 * call. To match such a second call to a first call, the returned
829 * value from the first call is passed as keyword. */
831 gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
834 engine_gpg_t gpg = engine;
837 rc = add_arg (gpg, "--command-fd");
841 /* This is a hack. We don't have a real data object. The only
842 thing that matters is that we use something unique, so we use the
843 address of the cmd structure in the gpg object. */
844 rc = add_data (gpg, (void *) &gpg->cmd, -2, 0);
849 gpg->cmd.cb_data = (void *) &gpg->cmd;
850 gpg->cmd.fnc_value = fnc_value;
857 build_argv (engine_gpg_t gpg, const char *pgmname)
860 struct arg_and_data_s *a;
861 struct fd_data_map_s *fd_data_map;
862 size_t datac=0, argc=0;
864 int need_special = 0;
868 if (_gpgme_in_gpg_one_mode ())
870 /* In GnuPG-1 mode we don't want to use the agent with a
871 malformed environment variable. This is only a very basic
872 test but sufficient to make our life in the regression tests
873 easier. With GnuPG-2 the agent is anyway required and on
874 modern installations GPG_AGENT_INFO is optional. */
875 err = _gpgme_getenv ("GPG_AGENT_INFO", &p);
878 use_agent = (p && strchr (p, ':'));
885 free_argv (gpg->argv);
888 if (gpg->fd_data_map)
890 free_fd_data_map (gpg->fd_data_map);
891 gpg->fd_data_map = NULL;
894 argc++; /* For argv[0]. */
895 for (a = gpg->arglist; a; a = a->next)
900 /*fprintf (stderr, "build_argv: data\n" );*/
902 if (a->dup_to == -1 && !a->print_fd)
907 /* fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
914 if (gpg->pinentry_mode)
917 argc++; /* --batch */
918 argc += 4; /* --no-sk-comments, --request-origin, --no-symkey-cache */
919 /* --disable-dirmngr */
921 argv = calloc (argc + 1, sizeof *argv);
923 return gpg_error_from_syserror ();
924 fd_data_map = calloc (datac + 1, sizeof *fd_data_map);
927 int saved_err = gpg_error_from_syserror ();
933 argv[argc] = strdup (_gpgme_get_basename (pgmname)); /* argv[0] */
936 int saved_err = gpg_error_from_syserror ();
944 argv[argc] = strdup ("--enable-special-filenames");
947 int saved_err = gpg_error_from_syserror ();
956 argv[argc] = strdup ("--use-agent");
959 int saved_err = gpg_error_from_syserror ();
967 if (*gpg->request_origin)
969 argv[argc] = _gpgme_strconcat ("--request-origin=",
970 gpg->request_origin, NULL);
973 int saved_err = gpg_error_from_syserror ();
981 if (gpg->auto_key_locate)
983 argv[argc] = strdup (gpg->auto_key_locate);
986 int saved_err = gpg_error_from_syserror ();
994 if (gpg->trust_model)
996 argv[argc] = strdup (gpg->trust_model);
999 int saved_err = gpg_error_from_syserror ();
1007 if (gpg->flags.no_symkey_cache)
1009 argv[argc] = strdup ("--no-symkey-cache");
1012 int saved_err = gpg_error_from_syserror ();
1020 if (gpg->flags.ignore_mdc_error)
1022 argv[argc] = strdup ("--ignore-mdc-error");
1025 int saved_err = gpg_error_from_syserror ();
1033 if (gpg->flags.offline)
1035 argv[argc] = strdup ("--disable-dirmngr");
1038 int saved_err = gpg_error_from_syserror ();
1046 if (gpg->pinentry_mode && have_gpg_version (gpg, "2.1.0"))
1048 const char *s = NULL;
1049 switch (gpg->pinentry_mode)
1051 case GPGME_PINENTRY_MODE_DEFAULT: break;
1052 case GPGME_PINENTRY_MODE_ASK: s = "--pinentry-mode=ask"; break;
1053 case GPGME_PINENTRY_MODE_CANCEL: s = "--pinentry-mode=cancel"; break;
1054 case GPGME_PINENTRY_MODE_ERROR: s = "--pinentry-mode=error"; break;
1055 case GPGME_PINENTRY_MODE_LOOPBACK:s = "--pinentry-mode=loopback"; break;
1059 argv[argc] = strdup (s);
1062 int saved_err = gpg_error_from_syserror ();
1073 argv[argc] = strdup ("--batch");
1076 int saved_err = gpg_error_from_syserror ();
1083 argv[argc] = strdup ("--no-sk-comments");
1086 int saved_err = gpg_error_from_syserror ();
1092 for (a = gpg->arglist; a; a = a->next)
1095 *(a->arg_locp) = argc;
1099 /* Create a pipe to pass it down to gpg. */
1100 fd_data_map[datac].inbound = a->inbound;
1102 /* Create a pipe. */
1106 if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0)
1109 int saved_err = gpg_error_from_syserror ();
1114 if (_gpgme_io_set_close_notify (fds[0],
1115 close_notify_handler, gpg)
1116 || _gpgme_io_set_close_notify (fds[1],
1117 close_notify_handler,
1120 /* We leak fd_data_map and the fds. This is not easy
1121 to avoid and given that we reach this here only
1122 after a malloc failure for a small object, it is
1123 probably better not to do anything. */
1124 return gpg_error (GPG_ERR_GENERAL);
1126 /* If the data_type is FD, we have to do a dup2 here. */
1127 if (fd_data_map[datac].inbound)
1129 fd_data_map[datac].fd = fds[0];
1130 fd_data_map[datac].peer_fd = fds[1];
1134 fd_data_map[datac].fd = fds[1];
1135 fd_data_map[datac].peer_fd = fds[0];
1139 /* Hack to get hands on the fd later. */
1142 if (gpg->cmd.cb_data == a->data)
1144 assert (gpg->cmd.idx == -1);
1145 gpg->cmd.idx = datac;
1149 fd_data_map[datac].data = a->data;
1150 fd_data_map[datac].dup_to = a->dup_to;
1152 if (a->dup_to == -1)
1157 argv[argc] = malloc (buflen);
1160 int saved_err = gpg_error_from_syserror ();
1174 _gpgme_io_fd2str (ptr, buflen, fd_data_map[datac].peer_fd);
1175 fd_data_map[datac].arg_loc = argc;
1182 argv[argc] = strdup (a->arg);
1185 int saved_err = gpg_error_from_syserror ();
1195 gpg->fd_data_map = fd_data_map;
1200 static gpgme_error_t
1201 add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
1206 err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
1210 /* FIXME Kludge around poll() problem. */
1211 err = _gpgme_io_set_nonblocking (fd);
1216 /* Handle the status output of GnuPG. This function does read entire
1217 lines and passes them as C strings to the callback function (we can
1218 use C Strings because the status output is always UTF-8 encoded).
1219 Of course we have to buffer the lines to cope with long lines
1220 e.g. with a large user ID. Note: We can optimize this to only cope
1221 with status line code we know about and skip all other stuff
1222 without buffering (i.e. without extending the buffer). */
1223 static gpgme_error_t
1224 read_status (engine_gpg_t gpg)
1228 size_t bufsize = gpg->status.bufsize;
1229 char *buffer = gpg->status.buffer;
1230 size_t readpos = gpg->status.readpos;
1234 if (bufsize - readpos < 256)
1236 /* Need more room for the read. */
1238 buffer = realloc (buffer, bufsize);
1240 return gpg_error_from_syserror ();
1243 nread = _gpgme_io_read (gpg->status.fd[0],
1244 buffer + readpos, bufsize-readpos);
1246 return gpg_error_from_syserror ();
1251 gpg->status.eof = 1;
1252 if (gpg->status.mon_cb)
1253 err = gpg->status.mon_cb (gpg->status.mon_cb_value, "", "");
1254 if (gpg->status.fnc)
1256 char emptystring[1] = {0};
1257 err = gpg->status.fnc (gpg->status.fnc_value,
1258 GPGME_STATUS_EOF, emptystring);
1259 if (gpg_err_code (err) == GPG_ERR_FALSE)
1260 err = 0; /* Drop special error code. */
1268 for (p = buffer + readpos; nread; nread--, p++)
1272 /* (we require that the last line is terminated by a LF) */
1273 if (p > buffer && p[-1] == '\r')
1276 if (!strncmp (buffer, "[GNUPG:] ", 9)
1277 && buffer[9] >= 'A' && buffer[9] <= 'Z')
1280 gpgme_status_code_t r;
1282 rest = strchr (buffer + 9, ' ');
1284 rest = p; /* Set to an empty string. */
1288 r = _gpgme_parse_status (buffer + 9);
1289 if (gpg->status.mon_cb && r != GPGME_STATUS_PROGRESS)
1291 /* Note that we call the monitor even if we do
1292 * not know the status code (r < 0). */
1293 err = gpg->status.mon_cb (gpg->status.mon_cb_value,
1301 && (r == GPGME_STATUS_GET_BOOL
1302 || r == GPGME_STATUS_GET_LINE
1303 || r == GPGME_STATUS_GET_HIDDEN))
1306 if (gpg->cmd.keyword)
1307 free (gpg->cmd.keyword);
1308 gpg->cmd.keyword = strdup (rest);
1309 if (!gpg->cmd.keyword)
1310 return gpg_error_from_syserror ();
1311 /* This should be the last thing we have
1312 received and the next thing will be that
1313 the command handler does its action. */
1315 TRACE0 (DEBUG_CTX, "gpgme:read_status", 0,
1316 "error: unexpected data");
1318 add_io_cb (gpg, gpg->cmd.fd, 0,
1319 command_handler, gpg,
1320 &gpg->fd_data_map[gpg->cmd.idx].tag);
1321 gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd;
1324 else if (gpg->status.fnc)
1326 err = gpg->status.fnc (gpg->status.fnc_value,
1328 if (gpg_err_code (err) == GPG_ERR_FALSE)
1329 err = 0; /* Drop special error code. */
1335 /* To reuse the buffer for the next line we have to
1336 shift the remaining data to the buffer start and
1337 restart the loop Hmmm: We can optimize this function
1338 by looking forward in the buffer to see whether a
1339 second complete line is available and in this case
1340 avoid the memmove for this line. */
1343 memmove (buffer, p, nread);
1345 break; /* the for loop */
1352 /* Update the gpg object. */
1353 gpg->status.bufsize = bufsize;
1354 gpg->status.buffer = buffer;
1355 gpg->status.readpos = readpos;
1360 static gpgme_error_t
1361 status_handler (void *opaque, int fd)
1363 struct io_cb_data *data = (struct io_cb_data *) opaque;
1364 engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
1367 assert (fd == gpg->status.fd[0]);
1368 err = read_status (gpg);
1371 if (gpg->status.eof)
1372 _gpgme_io_close (fd);
1377 static gpgme_error_t
1378 read_colon_line (engine_gpg_t gpg)
1382 size_t bufsize = gpg->colon.bufsize;
1383 char *buffer = gpg->colon.buffer;
1384 size_t readpos = gpg->colon.readpos;
1387 if (bufsize - readpos < 256)
1389 /* Need more room for the read. */
1391 buffer = realloc (buffer, bufsize);
1393 return gpg_error_from_syserror ();
1396 nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos);
1398 return gpg_error_from_syserror ();
1403 assert (gpg->colon.fnc);
1404 gpg->colon.fnc (gpg->colon.fnc_value, NULL);
1410 for (p = buffer + readpos; nread; nread--, p++)
1414 /* (we require that the last line is terminated by a LF)
1415 and we skip empty lines. Note: we use UTF8 encoding
1416 and escaping of special characters. We require at
1417 least one colon to cope with some other printed
1420 if (*buffer && strchr (buffer, ':'))
1424 if (gpg->colon.preprocess_fnc)
1428 err = gpg->colon.preprocess_fnc (buffer, &line);
1433 assert (gpg->colon.fnc);
1441 endp = strchr (linep, '\n');
1444 gpg->colon.fnc (gpg->colon.fnc_value, linep);
1447 while (linep && *linep);
1452 gpg->colon.fnc (gpg->colon.fnc_value, buffer);
1455 /* To reuse the buffer for the next line we have to
1456 shift the remaining data to the buffer start and
1457 restart the loop Hmmm: We can optimize this function
1458 by looking forward in the buffer to see whether a
1459 second complete line is available and in this case
1460 avoid the memmove for this line. */
1463 memmove (buffer, p, nread);
1465 break; /* The for loop. */
1472 /* Update the gpg object. */
1473 gpg->colon.bufsize = bufsize;
1474 gpg->colon.buffer = buffer;
1475 gpg->colon.readpos = readpos;
1480 /* This colonline handler thing is not the clean way to do it. It
1481 might be better to enhance the gpgme_data_t object to act as a wrapper
1482 for a callback. Same goes for the status thing. For now we use
1483 this thing here because it is easier to implement. */
1484 static gpgme_error_t
1485 colon_line_handler (void *opaque, int fd)
1487 struct io_cb_data *data = (struct io_cb_data *) opaque;
1488 engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
1489 gpgme_error_t rc = 0;
1491 assert (fd == gpg->colon.fd[0]);
1492 rc = read_colon_line (gpg);
1496 _gpgme_io_close (fd);
1501 static gpgme_error_t
1502 start (engine_gpg_t gpg)
1507 struct spawn_fd_item_s *fd_list;
1509 const char *pgmname;
1512 return gpg_error (GPG_ERR_INV_VALUE);
1514 if (!gpg->file_name && !_gpgme_get_default_gpg_name ())
1515 return trace_gpg_error (GPG_ERR_INV_ENGINE);
1519 rc = add_arg_ext (gpg, gpg->lc_ctype, 1);
1521 rc = add_arg_ext (gpg, "--lc-ctype", 1);
1526 if (gpg->lc_messages)
1528 rc = add_arg_ext (gpg, gpg->lc_messages, 1);
1530 rc = add_arg_ext (gpg, "--lc-messages", 1);
1535 pgmname = gpg->file_name ? gpg->file_name : _gpgme_get_default_gpg_name ();
1536 rc = build_argv (gpg, pgmname);
1540 /* status_fd, colon_fd and end of list. */
1542 for (i = 0; gpg->fd_data_map[i].data; i++)
1544 fd_list = calloc (n, sizeof *fd_list);
1546 return gpg_error_from_syserror ();
1548 /* Build the fd list for the child. */
1550 fd_list[n].fd = gpg->status.fd[1];
1551 fd_list[n].dup_to = -1;
1552 fd_list[n].arg_loc = gpg->status.arg_loc;
1556 fd_list[n].fd = gpg->colon.fd[1];
1557 fd_list[n].dup_to = 1;
1560 for (i = 0; gpg->fd_data_map[i].data; i++)
1562 fd_list[n].fd = gpg->fd_data_map[i].peer_fd;
1563 fd_list[n].dup_to = gpg->fd_data_map[i].dup_to;
1564 fd_list[n].arg_loc = gpg->fd_data_map[i].arg_loc;
1568 fd_list[n].dup_to = -1;
1570 status = _gpgme_io_spawn (pgmname, gpg->argv,
1571 (IOSPAWN_FLAG_DETACHED |IOSPAWN_FLAG_ALLOW_SET_FG),
1572 fd_list, NULL, NULL, &pid);
1574 int saved_err = gpg_error_from_syserror ();
1580 /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
1582 rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg,
1585 /* FIXME: kill the child */
1590 assert (gpg->colon.fd[0] != -1);
1591 rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg,
1594 /* FIXME: kill the child */
1598 for (i = 0; gpg->fd_data_map[i].data; i++)
1600 if (gpg->cmd.used && i == gpg->cmd.idx)
1602 /* Park the cmd fd. */
1603 gpg->cmd.fd = gpg->fd_data_map[i].fd;
1604 gpg->fd_data_map[i].fd = -1;
1608 rc = add_io_cb (gpg, gpg->fd_data_map[i].fd,
1609 gpg->fd_data_map[i].inbound,
1610 gpg->fd_data_map[i].inbound
1611 ? _gpgme_data_inbound_handler
1612 : _gpgme_data_outbound_handler,
1613 gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag);
1616 /* FIXME: kill the child */
1621 gpg_io_event (gpg, GPGME_EVENT_START, NULL);
1623 /* fixme: check what data we can release here */
1628 /* Add the --input-size-hint option if requested. */
1629 static gpgme_error_t
1630 add_input_size_hint (engine_gpg_t gpg, gpgme_data_t data)
1633 gpgme_off_t value = _gpgme_data_get_size_hint (data);
1634 char numbuf[50]; /* Large enough for even 2^128 in base-10. */
1637 if (!value || !have_gpg_version (gpg, "2.1.15"))
1640 err = add_arg (gpg, "--input-size-hint");
1643 p = numbuf + sizeof numbuf;
1647 *--p = '0' + (value % 10);
1651 err = add_arg (gpg, p);
1657 static gpgme_error_t
1658 gpg_decrypt (void *engine,
1659 gpgme_decrypt_flags_t flags,
1660 gpgme_data_t ciph, gpgme_data_t plain,
1661 int export_session_key, const char *override_session_key,
1662 int auto_key_retrieve)
1664 engine_gpg_t gpg = engine;
1667 err = add_arg (gpg, "--decrypt");
1669 if (!err && (flags & GPGME_DECRYPT_UNWRAP))
1671 if (!have_gpg_version (gpg, "2.1.12"))
1672 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
1674 err = add_arg (gpg, "--unwrap");
1677 if (!err && export_session_key)
1678 err = add_arg (gpg, "--show-session-key");
1680 if (!err && auto_key_retrieve)
1681 err = add_arg (gpg, "--auto-key-retrieve");
1683 if (!err && override_session_key && *override_session_key)
1685 if (have_gpg_version (gpg, "2.1.16"))
1687 gpgme_data_release (gpg->override_session_key);
1688 TRACE2 (DEBUG_ENGINE, "override", gpg, "seskey='%s' len=%zu\n",
1689 override_session_key,
1690 strlen (override_session_key));
1692 err = gpgme_data_new_from_mem (&gpg->override_session_key,
1693 override_session_key,
1694 strlen (override_session_key), 1);
1697 /* We add --no-keyring because a keyring is not required
1698 * when we are overriding the session key. It would
1699 * work without that option but --no-keyring avoids that
1700 * gpg return a failure due to a missing key log_error()
1701 * diagnostic. --no-keyring is supported since 2.1.14. */
1702 err = add_arg (gpg, "--no-keyring");
1704 err = add_arg (gpg, "--override-session-key-fd");
1706 err = add_data (gpg, gpg->override_session_key, -2, 0);
1711 /* Using that option may leak the session key via ps(1). */
1712 err = add_arg (gpg, "--override-session-key");
1714 err = add_arg (gpg, override_session_key);
1718 /* Tell the gpg object about the data. */
1720 err = add_arg (gpg, "--output");
1722 err = add_arg (gpg, "-");
1724 err = add_data (gpg, plain, 1, 1);
1726 err = add_input_size_hint (gpg, ciph);
1728 err = add_arg (gpg, "--");
1730 err = add_data (gpg, ciph, -1, 0);
1737 static gpgme_error_t
1738 gpg_delete (void *engine, gpgme_key_t key, unsigned int flags)
1740 engine_gpg_t gpg = engine;
1741 gpgme_error_t err = 0;
1742 int allow_secret = flags & GPGME_DELETE_ALLOW_SECRET;
1743 int force = flags & GPGME_DELETE_FORCE;
1746 err = add_arg (gpg, "--yes");
1748 err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key"
1751 err = add_arg (gpg, "--");
1754 if (!key->subkeys || !key->subkeys->fpr)
1755 return gpg_error (GPG_ERR_INV_VALUE);
1757 err = add_arg (gpg, key->subkeys->fpr);
1766 static gpgme_error_t
1767 gpg_passwd (void *engine, gpgme_key_t key, unsigned int flags)
1769 engine_gpg_t gpg = engine;
1774 if (!key || !key->subkeys || !key->subkeys->fpr)
1775 return gpg_error (GPG_ERR_INV_CERT_OBJ);
1777 err = add_arg (gpg, "--passwd");
1779 err = add_arg (gpg, key->subkeys->fpr);
1786 static gpgme_error_t
1787 append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1789 gpgme_error_t err = 0;
1793 for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
1795 const char *s = key->subkeys ? key->subkeys->keyid : NULL;
1799 err = add_arg (gpg, "-u");
1801 err = add_arg (gpg, s);
1803 gpgme_key_unref (key);
1811 static gpgme_error_t
1812 append_args_from_sender (engine_gpg_t gpg, gpgme_ctx_t ctx)
1816 if (ctx->sender && have_gpg_version (gpg, "2.1.15"))
1818 err = add_arg (gpg, "--sender");
1820 err = add_arg (gpg, ctx->sender);
1828 static gpgme_error_t
1829 append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1831 gpgme_error_t err = 0;
1832 gpgme_sig_notation_t notation;
1834 notation = gpgme_sig_notation_get (ctx);
1836 while (!err && notation)
1839 && !(notation->flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
1840 err = gpg_error (GPG_ERR_INV_VALUE);
1841 else if (notation->name)
1845 /* Maximum space needed is one byte for the "critical" flag,
1846 the name, one byte for '=', the value, and a terminating
1849 arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1);
1851 err = gpg_error_from_syserror ();
1857 if (notation->critical)
1860 memcpy (argp, notation->name, notation->name_len);
1861 argp += notation->name_len;
1865 /* We know that notation->name is '\0' terminated. */
1866 strcpy (argp, notation->value);
1870 err = add_arg (gpg, "--sig-notation");
1872 err = add_arg (gpg, arg);
1879 /* This is a policy URL. */
1883 if (notation->critical)
1885 value = malloc (1 + notation->value_len + 1);
1887 err = gpg_error_from_syserror ();
1891 /* We know that notation->value is '\0' terminated. */
1892 strcpy (&value[1], notation->value);
1896 value = notation->value;
1899 err = add_arg (gpg, "--sig-policy-url");
1901 err = add_arg (gpg, value);
1903 if (value != notation->value)
1907 notation = notation->next;
1913 static gpgme_error_t
1914 gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
1915 gpgme_ctx_t ctx /* FIXME */)
1917 engine_gpg_t gpg = engine;
1920 err = add_arg (gpg, "--with-colons");
1922 err = append_args_from_signers (gpg, ctx);
1924 err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
1926 err = add_data (gpg, out, 1, 1);
1928 err = add_arg (gpg, "--");
1929 if (!err && type == 0)
1931 const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1933 err = gpg_error (GPG_ERR_INV_VALUE);
1935 err = add_arg (gpg, s);
1944 /* Add a single argument from a key to an -r option. */
1946 add_arg_recipient (engine_gpg_t gpg, gpgme_encrypt_flags_t flags,
1951 if ((flags & GPGME_ENCRYPT_WANT_ADDRESS))
1953 /* We have no way to figure out which mail address was
1954 * requested. FIXME: It would be possible to figure this out by
1955 * consulting the SENDER property of the context. */
1956 err = gpg_error (GPG_ERR_INV_USER_ID);
1959 err = add_arg (gpg, key->subkeys->fpr);
1965 /* Add a single argument from a USERID string to an -r option. */
1967 add_arg_recipient_string (engine_gpg_t gpg, gpgme_encrypt_flags_t flags,
1968 const char *userid, int useridlen)
1972 if ((flags & GPGME_ENCRYPT_WANT_ADDRESS))
1974 char *tmpstr, *mbox;
1976 tmpstr = malloc (useridlen + 1);
1978 err = gpg_error_from_syserror ();
1981 memcpy (tmpstr, userid, useridlen);
1982 tmpstr[useridlen] = 0;
1984 mbox = _gpgme_mailbox_from_userid (tmpstr);
1987 err = gpg_error_from_syserror ();
1988 if (gpg_err_code (err) == GPG_ERR_EINVAL)
1989 err = gpg_error (GPG_ERR_INV_USER_ID);
1992 err = add_arg (gpg, mbox);
1999 err = add_arg_len (gpg, NULL, userid, useridlen);
2005 static gpgme_error_t
2006 append_args_from_recipients (engine_gpg_t gpg, gpgme_encrypt_flags_t flags,
2009 gpgme_error_t err = 0;
2014 if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
2015 err = gpg_error (GPG_ERR_INV_VALUE);
2017 err = add_arg (gpg, "-r");
2019 err = add_arg_recipient (gpg, flags, recp[i]);
2028 /* Take recipients from the LF delimited STRING and add -r args. */
2030 append_args_from_recipients_string (engine_gpg_t gpg,
2031 gpgme_encrypt_flags_t flags,
2034 gpg_error_t err = 0;
2035 gpgme_encrypt_flags_t orig_flags = flags;
2045 /* Skip leading white space */
2046 while (*string == ' ' || *string == '\t')
2051 /* Look for the LF. */
2052 s = strchr (string, '\n');
2056 n = strlen (string);
2057 while (n && (string[n-1] == ' ' || string[n-1] == '\t'))
2060 if (!ignore && n == 2 && !memcmp (string, "--", 2))
2062 else if (!ignore && n == 8 && !memcmp (string, "--hidden", 8))
2064 else if (!ignore && n == 11 && !memcmp (string, "--no-hidden", 11))
2066 else if (!ignore && n == 6 && !memcmp (string, "--file", 6))
2069 /* Because the key is used as is we need to ignore this flag: */
2070 flags &= ~GPGME_ENCRYPT_WANT_ADDRESS;
2072 else if (!ignore && n == 9 && !memcmp (string, "--no-file", 9))
2077 else if (n) /* Not empty - use it. */
2079 err = add_arg (gpg, file? (hidden? "-F":"-f") : (hidden? "-R":"-r"));
2081 err = add_arg_recipient_string (gpg, flags, string, n);
2091 err = gpg_error (GPG_ERR_MISSING_KEY);
2096 static gpgme_error_t
2097 gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
2098 gpgme_encrypt_flags_t flags,
2099 gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
2101 engine_gpg_t gpg = engine;
2102 gpgme_error_t err = 0;
2104 if (recp || recpstring)
2105 err = add_arg (gpg, "--encrypt");
2107 if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || (!recp && !recpstring)))
2108 err = add_arg (gpg, "--symmetric");
2110 if (!err && use_armor)
2111 err = add_arg (gpg, "--armor");
2113 if (!err && (flags & GPGME_ENCRYPT_WRAP))
2115 /* gpg is current not able to detect already compressed
2116 * packets. Thus when using
2117 * gpg --unwrap -d | gpg --no-literal -e
2118 * the encryption would add an additional compression layer.
2119 * We better suppress that. */
2120 flags |= GPGME_ENCRYPT_NO_COMPRESS;
2121 err = add_arg (gpg, "--no-literal");
2124 if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
2125 err = add_arg (gpg, "--compress-algo=none");
2127 if (!err && (flags & GPGME_ENCRYPT_THROW_KEYIDS))
2128 err = add_arg (gpg, "--throw-keyids");
2130 if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
2131 && have_gpg_version (gpg, "2.1.14"))
2132 err = add_arg (gpg, "--mimemode");
2134 if (recp || recpstring)
2136 /* If we know that all recipients are valid (full or ultimate trust)
2137 we can suppress further checks. */
2138 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
2139 err = add_arg (gpg, "--always-trust");
2141 if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
2142 err = add_arg (gpg, "--no-encrypt-to");
2144 if (!err && !recp && recpstring)
2145 err = append_args_from_recipients_string (gpg, flags, recpstring);
2147 err = append_args_from_recipients (gpg, flags, recp);
2150 /* Tell the gpg object about the data. */
2152 err = add_arg (gpg, "--output");
2154 err = add_arg (gpg, "-");
2156 err = add_data (gpg, ciph, 1, 1);
2157 if (gpgme_data_get_file_name (plain))
2160 err = add_arg (gpg, "--set-filename");
2162 err = add_arg (gpg, gpgme_data_get_file_name (plain));
2165 err = add_input_size_hint (gpg, plain);
2167 err = add_arg (gpg, "--");
2169 err = add_data (gpg, plain, -1, 0);
2178 static gpgme_error_t
2179 gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
2180 const char *recpstring,
2181 gpgme_encrypt_flags_t flags, gpgme_data_t plain,
2182 gpgme_data_t ciph, int use_armor,
2183 gpgme_ctx_t ctx /* FIXME */)
2185 engine_gpg_t gpg = engine;
2186 gpgme_error_t err = 0;
2188 if (recp || recpstring)
2189 err = add_arg (gpg, "--encrypt");
2191 if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || (!recp && !recpstring)))
2192 err = add_arg (gpg, "--symmetric");
2195 err = add_arg (gpg, "--sign");
2196 if (!err && use_armor)
2197 err = add_arg (gpg, "--armor");
2199 if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
2200 err = add_arg (gpg, "--compress-algo=none");
2202 if (!err && (flags & GPGME_ENCRYPT_THROW_KEYIDS))
2203 err = add_arg (gpg, "--throw-keyids");
2205 if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
2206 && have_gpg_version (gpg, "2.1.14"))
2207 err = add_arg (gpg, "--mimemode");
2209 if (recp || recpstring)
2211 /* If we know that all recipients are valid (full or ultimate trust)
2212 we can suppress further checks. */
2213 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
2214 err = add_arg (gpg, "--always-trust");
2216 if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
2217 err = add_arg (gpg, "--no-encrypt-to");
2219 if (!err && !recp && recpstring)
2220 err = append_args_from_recipients_string (gpg, flags, recpstring);
2222 err = append_args_from_recipients (gpg, flags, recp);
2226 err = append_args_from_signers (gpg, ctx);
2229 err = append_args_from_sender (gpg, ctx);
2232 err = append_args_from_sig_notations (gpg, ctx);
2234 /* Tell the gpg object about the data. */
2236 err = add_arg (gpg, "--output");
2238 err = add_arg (gpg, "-");
2240 err = add_data (gpg, ciph, 1, 1);
2241 if (gpgme_data_get_file_name (plain))
2244 err = add_arg (gpg, "--set-filename");
2246 err = add_arg (gpg, gpgme_data_get_file_name (plain));
2249 err = add_input_size_hint (gpg, plain);
2251 err = add_arg (gpg, "--");
2253 err = add_data (gpg, plain, -1, 0);
2262 static gpgme_error_t
2263 export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
2264 gpgme_data_t keydata, int use_armor)
2266 gpgme_error_t err = 0;
2268 if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
2269 |GPGME_EXPORT_MODE_MINIMAL
2270 |GPGME_EXPORT_MODE_SECRET)))
2271 return gpg_error (GPG_ERR_NOT_SUPPORTED);
2273 if ((mode & GPGME_EXPORT_MODE_MINIMAL))
2275 if ((mode & GPGME_EXPORT_MODE_NOUID))
2276 err = add_arg (gpg, "--export-options=export-minimal,export-drop-uids");
2278 err = add_arg (gpg, "--export-options=export-minimal");
2280 else if ((mode & GPGME_EXPORT_MODE_NOUID))
2281 err = add_arg (gpg, "--export-options=export-drop-uids");
2285 else if ((mode & GPGME_EXPORT_MODE_EXTERN))
2287 err = add_arg (gpg, "--send-keys");
2288 if (!err && (mode & GPGME_EXPORT_MODE_NOUID))
2289 err = add_arg (gpg, "--keyserver-options=export-drop-uids");
2293 if ((mode & GPGME_EXPORT_MODE_SECRET))
2294 err = add_arg (gpg, "--export-secret-keys");
2296 err = add_arg (gpg, "--export");
2297 if (!err && use_armor)
2298 err = add_arg (gpg, "--armor");
2300 err = add_data (gpg, keydata, 1, 1);
2303 err = add_arg (gpg, "--");
2309 static gpgme_error_t
2310 gpg_export (void *engine, const char *pattern, gpgme_export_mode_t mode,
2311 gpgme_data_t keydata, int use_armor)
2313 engine_gpg_t gpg = engine;
2316 err = export_common (gpg, mode, keydata, use_armor);
2318 if (!err && pattern && *pattern)
2319 err = add_arg (gpg, pattern);
2328 static gpgme_error_t
2329 gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
2330 gpgme_data_t keydata, int use_armor)
2332 engine_gpg_t gpg = engine;
2335 err = export_common (gpg, mode, keydata, use_armor);
2339 while (!err && *pattern && **pattern)
2340 err = add_arg (gpg, *(pattern++));
2351 /* Helper to add algo, usage, and expire to the list of args. */
2352 static gpgme_error_t
2353 gpg_add_algo_usage_expire (engine_gpg_t gpg,
2355 unsigned long expires,
2360 /* This condition is only required to allow the use of gpg < 2.1.16 */
2362 || (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR
2363 | GPGME_CREATE_CERT | GPGME_CREATE_AUTH
2364 | GPGME_CREATE_NOEXPIRE))
2367 err = add_arg (gpg, algo? algo : "default");
2371 snprintf (tmpbuf, sizeof tmpbuf, "%s%s%s%s",
2372 (flags & GPGME_CREATE_SIGN)? " sign":"",
2373 (flags & GPGME_CREATE_ENCR)? " encr":"",
2374 (flags & GPGME_CREATE_CERT)? " cert":"",
2375 (flags & GPGME_CREATE_AUTH)? " auth":"");
2376 err = add_arg (gpg, *tmpbuf? tmpbuf : "default");
2380 if ((flags & GPGME_CREATE_NOEXPIRE))
2381 err = add_arg (gpg, "never");
2382 else if (expires == 0)
2383 err = add_arg (gpg, "-");
2387 snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires);
2388 err = add_arg (gpg, tmpbuf);
2399 static gpgme_error_t
2400 gpg_createkey_from_param (engine_gpg_t gpg,
2401 gpgme_data_t help_data, unsigned int extraflags)
2405 err = add_arg (gpg, "--gen-key");
2406 if (!err && (extraflags & GENKEY_EXTRAFLAG_ARMOR))
2407 err = add_arg (gpg, "--armor");
2409 err = add_arg (gpg, "--");
2411 err = add_data (gpg, help_data, -1, 0);
2418 static gpgme_error_t
2419 gpg_createkey (engine_gpg_t gpg,
2420 const char *userid, const char *algo,
2421 unsigned long expires,
2423 unsigned int extraflags)
2427 err = add_arg (gpg, "--quick-gen-key");
2428 if (!err && (extraflags & GENKEY_EXTRAFLAG_ARMOR))
2429 err = add_arg (gpg, "--armor");
2430 if (!err && (flags & GPGME_CREATE_NOPASSWD))
2432 err = add_arg (gpg, "--passphrase");
2434 err = add_arg (gpg, "");
2436 err = add_arg (gpg, "--batch");
2438 if (!err && (flags & GPGME_CREATE_FORCE))
2439 err = add_arg (gpg, "--yes");
2441 err = add_arg (gpg, "--");
2443 err = add_arg (gpg, userid);
2446 err = gpg_add_algo_usage_expire (gpg, algo, expires, flags);
2454 static gpgme_error_t
2455 gpg_addkey (engine_gpg_t gpg,
2457 unsigned long expires,
2460 unsigned int extraflags)
2464 if (!key || !key->fpr)
2465 return gpg_error (GPG_ERR_INV_ARG);
2467 err = add_arg (gpg, "--quick-addkey");
2468 if (!err && (extraflags & GENKEY_EXTRAFLAG_ARMOR))
2469 err = add_arg (gpg, "--armor");
2470 if (!err && (flags & GPGME_CREATE_NOPASSWD))
2472 err = add_arg (gpg, "--passphrase");
2474 err = add_arg (gpg, "");
2476 err = add_arg (gpg, "--batch");
2479 err = add_arg (gpg, "--");
2481 err = add_arg (gpg, key->fpr);
2484 err = gpg_add_algo_usage_expire (gpg, algo, expires, flags);
2492 static gpgme_error_t
2493 gpg_adduid (engine_gpg_t gpg,
2496 unsigned int extraflags)
2500 if (!key || !key->fpr || !userid)
2501 return gpg_error (GPG_ERR_INV_ARG);
2503 if ((extraflags & GENKEY_EXTRAFLAG_SETPRIMARY))
2505 if (!have_gpg_version (gpg, "2.1.20"))
2506 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2508 err = add_arg (gpg, "--quick-set-primary-uid");
2510 else if ((extraflags & GENKEY_EXTRAFLAG_REVOKE))
2511 err = add_arg (gpg, "--quick-revuid");
2513 err = add_arg (gpg, "--quick-adduid");
2516 err = add_arg (gpg, "--");
2518 err = add_arg (gpg, key->fpr);
2520 err = add_arg (gpg, userid);
2528 static gpgme_error_t
2529 gpg_genkey (void *engine,
2530 const char *userid, const char *algo,
2531 unsigned long reserved, unsigned long expires,
2532 gpgme_key_t key, unsigned int flags,
2533 gpgme_data_t help_data, unsigned int extraflags,
2534 gpgme_data_t pubkey, gpgme_data_t seckey)
2536 engine_gpg_t gpg = engine;
2542 return gpg_error (GPG_ERR_INV_VALUE);
2544 /* If HELP_DATA is given the use of the old interface
2545 * (gpgme_op_genkey) has been requested. The other modes are:
2547 * USERID && !KEY - Create a new keyblock.
2548 * !USERID && KEY - Add a new subkey to KEY (gpg >= 2.1.14)
2549 * USERID && KEY && !ALGO - Add a new user id to KEY (gpg >= 2.1.14).
2550 * or set a flag on a user id.
2554 /* We need a special mechanism to get the fd of a pipe here, so
2555 that we can use this for the %pubring and %secring
2556 parameters. We don't have this yet, so we implement only the
2557 adding to the standard keyrings. */
2558 if (pubkey || seckey)
2559 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2561 err = gpg_createkey_from_param (gpg, help_data, extraflags);
2563 else if (!have_gpg_version (gpg, "2.1.13"))
2564 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2565 else if (userid && !key)
2566 err = gpg_createkey (gpg, userid, algo, expires, flags, extraflags);
2567 else if (!userid && key)
2568 err = gpg_addkey (gpg, algo, expires, key, flags, extraflags);
2569 else if (userid && key && !algo)
2570 err = gpg_adduid (gpg, key, userid, extraflags);
2572 err = gpg_error (GPG_ERR_INV_VALUE);
2577 /* Return the next DELIM delimited string from DATA as a C-string.
2578 The caller needs to provide the address of a pointer variable which
2579 he has to set to NULL before the first call. After the last call
2580 to this function, this function needs to be called once more with
2581 DATA set to NULL so that the function can release its internal
2582 state. After that the pointer variable is free for use again.
2583 Note that we use a delimiter and thus a trailing delimiter is not
2584 required. DELIM may not be changed after the first call. */
2586 string_from_data (gpgme_data_t data, int delim,
2587 void **helpptr, gpgme_error_t *r_err)
2589 #define MYBUFLEN 2000 /* Fixme: We don't support URLs longer than that. */
2592 int nbytes; /* Length of the last returned string including
2594 int buflen; /* Valid length of BUF. */
2595 char buf[MYBUFLEN+1]; /* Buffer with one byte extra space. */
2615 self = malloc (sizeof *self);
2618 *r_err = gpg_error_from_syserror ();
2630 assert (self->nbytes <= self->buflen);
2631 memmove (self->buf, self->buf + self->nbytes, self->buflen - self->nbytes);
2632 self->buflen -= self->nbytes;
2637 /* Fixme: This is fairly infective scanning because we may scan
2638 the buffer several times. */
2639 p = memchr (self->buf, delim, self->buflen);
2643 self->nbytes = p - self->buf + 1;
2647 if ( !(MYBUFLEN - self->buflen) )
2649 /* Not enough space - URL too long. */
2650 *r_err = gpg_error (GPG_ERR_TOO_LARGE);
2654 nread = gpgme_data_read (data, self->buf + self->buflen,
2655 MYBUFLEN - self->buflen);
2658 *r_err = gpg_error_from_syserror ();
2661 self->buflen += nread;
2665 /* EOF reached. If we have anything in the buffer, append a Nul and
2670 self->buf[self->buflen] = 0; /* (we allocated one extra byte) */
2679 static gpgme_error_t
2680 gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
2682 engine_gpg_t gpg = engine;
2685 gpgme_data_encoding_t dataenc;
2687 if (keydata && keyarray)
2688 return gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */
2690 dataenc = gpgme_data_get_encoding (keydata);
2694 err = add_arg (gpg, "--recv-keys");
2696 err = add_arg (gpg, "--");
2697 for (idx=0; !err && keyarray[idx]; idx++)
2699 if (keyarray[idx]->protocol != GPGME_PROTOCOL_OpenPGP)
2701 else if (!keyarray[idx]->subkeys)
2703 else if (keyarray[idx]->subkeys->fpr && *keyarray[idx]->subkeys->fpr)
2704 err = add_arg (gpg, keyarray[idx]->subkeys->fpr);
2705 else if (*keyarray[idx]->subkeys->keyid)
2706 err = add_arg (gpg, keyarray[idx]->subkeys->keyid);
2709 else if (dataenc == GPGME_DATA_ENCODING_URL
2710 || dataenc == GPGME_DATA_ENCODING_URL0)
2715 int delim = (dataenc == GPGME_DATA_ENCODING_URL)? '\n': 0;
2717 /* FIXME: --fetch-keys is probably not correct because it can't
2718 grok all kinds of URLs. On Unix it should just work but on
2719 Windows we will build the command line and that may fail for
2720 some embedded control characters. It is anyway limited to
2721 the maximum size of the command line. We need another
2722 command which can take its input from a file. Maybe we
2723 should use an option to gpg to modify such commands (ala
2725 err = add_arg (gpg, "--fetch-keys");
2727 err = add_arg (gpg, "--");
2730 && (string = string_from_data (keydata, delim, &helpptr, &xerr)))
2731 err = add_arg (gpg, string);
2734 string_from_data (NULL, delim, &helpptr, &xerr);
2736 else if (dataenc == GPGME_DATA_ENCODING_URLESC)
2738 /* Already escaped URLs are not yet supported. */
2739 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2743 err = add_arg (gpg, "--import");
2745 err = add_arg (gpg, "--");
2747 err = add_data (gpg, keydata, -1, 0);
2757 /* The output for external keylistings in GnuPG is different from all
2758 the other key listings. We catch this here with a special
2759 preprocessor that reformats the colon handler lines. */
2760 static gpgme_error_t
2761 gpg_keylist_preprocess (char *line, char **r_line)
2765 RT_NONE, RT_INFO, RT_PUB, RT_UID
2768 #define NR_FIELDS 16
2769 char *field[NR_FIELDS];
2775 while (line && fields < NR_FIELDS)
2777 field[fields++] = line;
2778 line = strchr (line, ':');
2783 if (!strcmp (field[0], "info"))
2785 else if (!strcmp (field[0], "pub"))
2787 else if (!strcmp (field[0], "uid"))
2795 /* FIXME: Eventually, check the version number at least. */
2804 pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>
2806 as defined in 5.2. Machine Readable Indexes of the OpenPGP
2807 HTTP Keyserver Protocol (draft). Modern versions of the SKS
2808 keyserver return the fingerprint instead of the keyid. We
2809 detect this here and use the v4 fingerprint format to convert
2813 pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>::::::::
2816 n = strlen (field[1]);
2819 if (gpgrt_asprintf (r_line,
2820 "pub:o%s:%s:%s:%s:%s:%s::::::::\n"
2822 field[6], field[3], field[2], field[1] + n - 16,
2823 field[4], field[5], field[1]) < 0)
2824 return gpg_error_from_syserror ();
2828 if (gpgrt_asprintf (r_line,
2829 "pub:o%s:%s:%s:%s:%s:%s::::::::",
2830 field[6], field[3], field[2], field[1],
2831 field[4], field[5]) < 0)
2832 return gpg_error_from_syserror ();
2840 uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags>
2842 as defined in 5.2. Machine Readable Indexes of the OpenPGP
2843 HTTP Keyserver Protocol (draft).
2845 For an ldap keyserver the format is:
2846 uid:<escaped uid string>
2849 uid:o<flags>::::<creatdate>:<expdate>:::<c-coded uid>:
2853 /* The user ID is percent escaped, but we want c-coded.
2854 Because we have to replace each '%HL' by '\xHL', we need at
2855 most 4/3 th the number of bytes. But because we also need
2856 to escape the backslashes we allocate twice as much. */
2857 char *uid = malloc (2 * strlen (field[1]) + 1);
2862 return gpg_error_from_syserror ();
2872 /* Copy the next two bytes unconditionally. */
2874 *(dst++) = *(src++);
2876 *(dst++) = *(src++);
2878 else if (*src == '\\')
2885 *(dst++) = *(src++);
2891 if (gpgrt_asprintf (r_line, "uid:o::::::::%s:", uid) < 0)
2892 return gpg_error_from_syserror ();
2896 if (gpgrt_asprintf (r_line, "uid:o%s::::%s:%s:::%s:",
2897 field[4], field[2], field[3], uid) < 0)
2898 return gpg_error_from_syserror ();
2904 /* Unknown record. */
2913 gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
2914 gpgme_keylist_mode_t mode)
2918 err = add_arg (gpg, "--with-colons");
2920 /* Since gpg 2.1.15 fingerprints are always printed, thus there is
2921 * no more need to explicitly request them. */
2922 if (!have_gpg_version (gpg, "2.1.15"))
2925 err = add_arg (gpg, "--fixed-list-mode");
2927 err = add_arg (gpg, "--with-fingerprint");
2929 err = add_arg (gpg, "--with-fingerprint");
2932 if (!err && (mode & GPGME_KEYLIST_MODE_WITH_TOFU)
2933 && have_gpg_version (gpg, "2.1.16"))
2934 err = add_arg (gpg, "--with-tofu-info");
2936 if (!err && (mode & GPGME_KEYLIST_MODE_WITH_SECRET))
2937 err = add_arg (gpg, "--with-secret");
2940 && (mode & GPGME_KEYLIST_MODE_SIGS)
2941 && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
2943 err = add_arg (gpg, "--list-options");
2945 err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
2950 if ( (mode & GPGME_KEYLIST_MODE_EXTERN) )
2953 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2954 else if ( (mode & GPGME_KEYLIST_MODE_LOCAL))
2956 /* The local+extern mode is special. It works only with
2957 gpg >= 2.0.10. FIXME: We should check that we have
2958 such a version to that we can return a proper error
2959 code. The problem is that we don't know the context
2960 here and thus can't access the cached version number
2961 for the engine info structure. */
2962 err = add_arg (gpg, "--locate-keys");
2963 if ((mode & GPGME_KEYLIST_MODE_SIGS))
2964 err = add_arg (gpg, "--with-sig-check");
2968 err = add_arg (gpg, "--search-keys");
2969 gpg->colon.preprocess_fnc = gpg_keylist_preprocess;
2974 err = add_arg (gpg, secret_only ? "--list-secret-keys"
2975 : ((mode & GPGME_KEYLIST_MODE_SIGS)
2976 ? "--check-sigs" : "--list-keys"));
2981 err = add_arg (gpg, "--");
2987 static gpgme_error_t
2988 gpg_keylist (void *engine, const char *pattern, int secret_only,
2989 gpgme_keylist_mode_t mode, int engine_flags)
2991 engine_gpg_t gpg = engine;
2996 err = gpg_keylist_build_options (gpg, secret_only, mode);
2998 if (!err && pattern && *pattern)
2999 err = add_arg (gpg, pattern);
3008 static gpgme_error_t
3009 gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
3010 int reserved, gpgme_keylist_mode_t mode, int engine_flags)
3012 engine_gpg_t gpg = engine;
3018 return gpg_error (GPG_ERR_INV_VALUE);
3020 err = gpg_keylist_build_options (gpg, secret_only, mode);
3024 while (!err && *pattern && **pattern)
3025 err = add_arg (gpg, *(pattern++));
3035 static gpgme_error_t
3036 gpg_keylist_data (void *engine, gpgme_data_t data)
3038 engine_gpg_t gpg = engine;
3041 if (!have_gpg_version (gpg, "2.1.14"))
3042 return gpg_error (GPG_ERR_NOT_SUPPORTED);
3044 err = add_arg (gpg, "--with-colons");
3046 err = add_arg (gpg, "--with-fingerprint");
3048 err = add_arg (gpg, "--import-options");
3050 err = add_arg (gpg, "import-show");
3052 err = add_arg (gpg, "--dry-run");
3054 err = add_arg (gpg, "--import");
3056 err = add_arg (gpg, "--");
3058 err = add_data (gpg, data, -1, 0);
3067 static gpgme_error_t
3068 gpg_keysign (void *engine, gpgme_key_t key, const char *userid,
3069 unsigned long expire, unsigned int flags,
3072 engine_gpg_t gpg = engine;
3076 if (!key || !key->fpr)
3077 return gpg_error (GPG_ERR_INV_ARG);
3079 if (!have_gpg_version (gpg, "2.1.12"))
3080 return gpg_error (GPG_ERR_NOT_SUPPORTED);
3082 if ((flags & GPGME_KEYSIGN_LOCAL))
3083 err = add_arg (gpg, "--quick-lsign-key");
3085 err = add_arg (gpg, "--quick-sign-key");
3088 err = append_args_from_signers (gpg, ctx);
3090 /* If an expiration time has been given use that. If none has been
3091 * given the default from gpg.conf is used. To make sure not to set
3092 * an expiration time at all the flag GPGME_KEYSIGN_NOEXPIRE can be
3094 if (!err && (expire || (flags & GPGME_KEYSIGN_NOEXPIRE)))
3098 if ((flags & GPGME_KEYSIGN_NOEXPIRE))
3100 snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expire);
3101 err = add_arg (gpg, "--default-cert-expire");
3103 err = add_arg (gpg, tmpbuf);
3107 err = add_arg (gpg, "--");
3110 err = add_arg (gpg, key->fpr);
3113 if ((flags & GPGME_KEYSIGN_LFSEP))
3115 for (; !err && (s = strchr (userid, '\n')); userid = s + 1)
3117 err = add_arg_len (gpg, "=", userid, s - userid);
3118 if (!err && *userid)
3119 err = add_arg_pfx (gpg, "=", userid);
3122 err = add_arg_pfx (gpg, "=", userid);
3132 static gpgme_error_t
3133 gpg_tofu_policy (void *engine, gpgme_key_t key, gpgme_tofu_policy_t policy)
3135 engine_gpg_t gpg = engine;
3137 const char *policystr = NULL;
3139 if (!key || !key->fpr)
3140 return gpg_error (GPG_ERR_INV_ARG);
3144 case GPGME_TOFU_POLICY_NONE: break;
3145 case GPGME_TOFU_POLICY_AUTO: policystr = "auto"; break;
3146 case GPGME_TOFU_POLICY_GOOD: policystr = "good"; break;
3147 case GPGME_TOFU_POLICY_BAD: policystr = "bad"; break;
3148 case GPGME_TOFU_POLICY_ASK: policystr = "ask"; break;
3149 case GPGME_TOFU_POLICY_UNKNOWN: policystr = "unknown"; break;
3152 return gpg_error (GPG_ERR_INV_VALUE);
3154 if (!have_gpg_version (gpg, "2.1.10"))
3155 return gpg_error (GPG_ERR_NOT_SUPPORTED);
3157 err = add_arg (gpg, "--tofu-policy");
3159 err = add_arg (gpg, "--");
3161 err = add_arg (gpg, policystr);
3163 err = add_arg (gpg, key->fpr);
3172 static gpgme_error_t
3173 gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
3174 gpgme_sig_mode_t mode, int use_armor, int use_textmode,
3175 int include_certs, gpgme_ctx_t ctx /* FIXME */)
3177 engine_gpg_t gpg = engine;
3180 (void)include_certs;
3182 if (mode == GPGME_SIG_MODE_CLEAR)
3183 err = add_arg (gpg, "--clearsign");
3186 err = add_arg (gpg, "--sign");
3187 if (!err && mode == GPGME_SIG_MODE_DETACH)
3188 err = add_arg (gpg, "--detach");
3189 if (!err && use_armor)
3190 err = add_arg (gpg, "--armor");
3193 if (gpgme_data_get_encoding (in) == GPGME_DATA_ENCODING_MIME
3194 && have_gpg_version (gpg, "2.1.14"))
3195 err = add_arg (gpg, "--mimemode");
3196 else if (use_textmode)
3197 err = add_arg (gpg, "--textmode");
3202 err = append_args_from_signers (gpg, ctx);
3204 err = append_args_from_sender (gpg, ctx);
3206 err = append_args_from_sig_notations (gpg, ctx);
3208 if (gpgme_data_get_file_name (in))
3211 err = add_arg (gpg, "--set-filename");
3213 err = add_arg (gpg, gpgme_data_get_file_name (in));
3216 /* Tell the gpg object about the data. */
3218 err = add_input_size_hint (gpg, in);
3220 err = add_arg (gpg, "--");
3222 err = add_data (gpg, in, -1, 0);
3224 err = add_data (gpg, out, 1, 1);
3232 static gpgme_error_t
3233 gpg_trustlist (void *engine, const char *pattern)
3235 engine_gpg_t gpg = engine;
3238 err = add_arg (gpg, "--with-colons");
3240 err = add_arg (gpg, "--list-trust-path");
3242 /* Tell the gpg object about the data. */
3244 err = add_arg (gpg, "--");
3246 err = add_arg (gpg, pattern);
3255 static gpgme_error_t
3256 gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
3257 gpgme_data_t plaintext, gpgme_ctx_t ctx)
3259 engine_gpg_t gpg = engine;
3262 err = append_args_from_sender (gpg, ctx);
3263 if (!err && ctx->auto_key_retrieve)
3264 err = add_arg (gpg, "--auto-key-retrieve");
3270 /* Normal or cleartext signature. */
3271 err = add_arg (gpg, "--output");
3273 err = add_arg (gpg, "-");
3275 err = add_input_size_hint (gpg, sig);
3277 err = add_arg (gpg, "--");
3279 err = add_data (gpg, sig, -1, 0);
3281 err = add_data (gpg, plaintext, 1, 1);
3285 err = add_arg (gpg, "--verify");
3287 err = add_input_size_hint (gpg, signed_text);
3289 err = add_arg (gpg, "--");
3291 err = add_data (gpg, sig, -1, 0);
3292 if (!err && signed_text)
3293 err = add_data (gpg, signed_text, -1, 0);
3304 gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
3306 engine_gpg_t gpg = engine;
3308 gpg->io_cbs = *io_cbs;
3312 static gpgme_error_t
3313 gpg_set_pinentry_mode (void *engine, gpgme_pinentry_mode_t mode)
3315 engine_gpg_t gpg = engine;
3317 gpg->pinentry_mode = mode;
3322 static gpgme_error_t
3323 gpg_getauditlog (void *engine, gpgme_data_t output, unsigned int flags)
3325 engine_gpg_t gpg = engine;
3326 #define MYBUFLEN 4096
3329 int any_written = 0;
3331 if (!(flags & GPGME_AUDITLOG_DIAG))
3333 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
3336 if (!gpg || !output)
3338 return gpg_error (GPG_ERR_INV_VALUE);
3341 if (!gpg->diagnostics)
3343 return gpg_error (GPG_ERR_GENERAL);
3346 gpgme_data_rewind (gpg->diagnostics);
3348 while ((nread = gpgme_data_read (gpg->diagnostics, buf, MYBUFLEN)) > 0)
3351 if (gpgme_data_write (output, buf, nread) == -1)
3352 return gpg_error_from_syserror ();
3356 return gpg_error (GPG_ERR_NO_DATA);
3360 return gpg_error_from_syserror ();
3362 gpgme_data_rewind (output);
3369 struct engine_ops _gpgme_engine_ops_gpg =
3371 /* Static functions. */
3372 _gpgme_get_default_gpg_name,
3375 gpg_get_req_version,
3378 /* Member functions. */
3382 gpg_set_status_handler,
3383 gpg_set_command_handler,
3384 gpg_set_colon_line_handler,
3386 NULL, /* set_protocol */
3387 gpg_set_engine_flags, /* set_engine_flags */
3401 gpg_tofu_policy, /* tofu_policy */
3406 NULL, /* opassuan_transact */
3407 NULL, /* conf_load */
3408 NULL, /* conf_save */
3409 NULL, /* conf_dir */
3410 NULL, /* query_swdb */
3414 NULL, /* cancel_op */
3416 gpg_set_pinentry_mode,