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/>.
41 #include "context.h" /*temp hack until we have GpmeData methods to do I/O */
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;
138 /* The kludges never end. This is used to couple command handlers
139 with output data in edit key mode. */
140 gpgme_data_t linked_data;
144 struct gpgme_io_cbs io_cbs;
145 gpgme_pinentry_mode_t pinentry_mode;
147 /* NULL or the data object fed to --override_session_key-fd. */
148 gpgme_data_t override_session_key;
151 typedef struct engine_gpg *engine_gpg_t;
155 gpg_io_event (void *engine, gpgme_event_io_t type, void *type_data)
157 engine_gpg_t gpg = engine;
159 TRACE3 (DEBUG_ENGINE, "gpgme:gpg_io_event", gpg,
160 "event %p, type %d, type_data %p",
161 gpg->io_cbs.event, type, type_data);
162 if (gpg->io_cbs.event)
163 (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data);
168 close_notify_handler (int fd, void *opaque)
170 engine_gpg_t gpg = opaque;
173 if (gpg->status.fd[0] == fd)
176 (*gpg->io_cbs.remove) (gpg->status.tag);
177 gpg->status.fd[0] = -1;
179 else if (gpg->status.fd[1] == fd)
180 gpg->status.fd[1] = -1;
181 else if (gpg->colon.fd[0] == fd)
184 (*gpg->io_cbs.remove) (gpg->colon.tag);
185 gpg->colon.fd[0] = -1;
187 else if (gpg->colon.fd[1] == fd)
188 gpg->colon.fd[1] = -1;
189 else if (gpg->cmd.fd == fd)
191 else if (gpg->fd_data_map)
195 for (i = 0; gpg->fd_data_map[i].data; i++)
197 if (gpg->fd_data_map[i].fd == fd)
199 if (gpg->fd_data_map[i].tag)
200 (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
201 gpg->fd_data_map[i].fd = -1;
204 if (gpg->fd_data_map[i].peer_fd == fd)
206 gpg->fd_data_map[i].peer_fd = -1;
213 /* If FRONT is true, push at the front of the list. Use this for
214 options added late in the process. */
216 _add_arg (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen,
217 int front, int *arg_locp)
219 struct arg_and_data_s *a;
220 size_t prefixlen = prefix? strlen (prefix) : 0;
225 a = malloc (sizeof *a + prefixlen + arglen);
227 return gpg_error_from_syserror ();
231 a->arg_locp = arg_locp;
234 memcpy (a->arg, prefix, prefixlen);
235 memcpy (a->arg + prefixlen, arg, arglen);
236 a->arg[prefixlen + arglen] = 0;
239 a->next = gpg->arglist;
242 /* If this is the first argument, we need to update the tail
244 gpg->argtail = &a->next;
252 gpg->argtail = &a->next;
260 add_arg_ext (engine_gpg_t gpg, const char *arg, int front)
262 return _add_arg (gpg, NULL, arg, strlen (arg), front, NULL);
266 add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp)
268 return _add_arg (gpg, NULL, arg, strlen (arg), 0, locp);
272 add_arg (engine_gpg_t gpg, const char *arg)
274 return _add_arg (gpg, NULL, arg, strlen (arg), 0, NULL);
278 add_arg_pfx (engine_gpg_t gpg, const char *prefix, const char *arg)
280 return _add_arg (gpg, prefix, arg, strlen (arg), 0, NULL);
284 add_arg_len (engine_gpg_t gpg, const char *prefix,
285 const char *arg, size_t arglen)
287 return _add_arg (gpg, prefix, arg, arglen, 0, NULL);
292 add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
294 struct arg_and_data_s *a;
299 a = malloc (sizeof *a - 1);
301 return gpg_error_from_syserror ();
304 a->inbound = inbound;
318 gpg->argtail = &a->next;
323 /* Return true if the engine's version is at least VERSION. */
325 have_gpg_version (engine_gpg_t gpg, const char *version)
327 return _gpgme_compare_versions (gpg->version, version);
333 gpg_get_version (const char *file_name)
335 return _gpgme_get_program_version (file_name ? file_name
336 : _gpgme_get_default_gpg_name ());
341 gpg_get_req_version (void)
348 free_argv (char **argv)
352 for (i = 0; argv[i]; i++)
359 free_fd_data_map (struct fd_data_map_s *fd_data_map)
366 for (i = 0; fd_data_map[i].data; i++)
368 if (fd_data_map[i].fd != -1)
369 _gpgme_io_close (fd_data_map[i].fd);
370 if (fd_data_map[i].peer_fd != -1)
371 _gpgme_io_close (fd_data_map[i].peer_fd);
372 /* Don't release data because this is only a reference. */
379 gpg_cancel (void *engine)
381 engine_gpg_t gpg = engine;
384 return gpg_error (GPG_ERR_INV_VALUE);
386 /* If gpg may be waiting for a cmd, close the cmd fd first. On
387 Windows, close operations block on the reader/writer thread. */
390 if (gpg->cmd.fd != -1)
391 _gpgme_io_close (gpg->cmd.fd);
392 else if (gpg->fd_data_map
393 && gpg->fd_data_map[gpg->cmd.idx].fd != -1)
394 _gpgme_io_close (gpg->fd_data_map[gpg->cmd.idx].fd);
397 if (gpg->status.fd[0] != -1)
398 _gpgme_io_close (gpg->status.fd[0]);
399 if (gpg->status.fd[1] != -1)
400 _gpgme_io_close (gpg->status.fd[1]);
401 if (gpg->colon.fd[0] != -1)
402 _gpgme_io_close (gpg->colon.fd[0]);
403 if (gpg->colon.fd[1] != -1)
404 _gpgme_io_close (gpg->colon.fd[1]);
405 if (gpg->fd_data_map)
407 free_fd_data_map (gpg->fd_data_map);
408 gpg->fd_data_map = NULL;
415 gpg_release (void *engine)
417 engine_gpg_t gpg = engine;
425 free (gpg->file_name);
429 if (gpg->lc_messages)
430 free (gpg->lc_messages);
432 free (gpg->lc_ctype);
436 struct arg_and_data_s *next = gpg->arglist->next;
442 if (gpg->status.buffer)
443 free (gpg->status.buffer);
444 if (gpg->colon.buffer)
445 free (gpg->colon.buffer);
447 free_argv (gpg->argv);
448 if (gpg->cmd.keyword)
449 free (gpg->cmd.keyword);
451 gpgme_data_release (gpg->override_session_key);
458 gpg_new (void **engine, const char *file_name, const char *home_dir,
462 gpgme_error_t rc = 0;
463 char *dft_display = NULL;
464 char dft_ttyname[64];
465 char *dft_ttytype = NULL;
466 char *env_tty = NULL;
468 gpg = calloc (1, sizeof *gpg);
470 return gpg_error_from_syserror ();
474 gpg->file_name = strdup (file_name);
477 rc = gpg_error_from_syserror ();
484 gpg->version = strdup (version);
487 rc = gpg_error_from_syserror ();
492 gpg->argtail = &gpg->arglist;
493 gpg->status.fd[0] = -1;
494 gpg->status.fd[1] = -1;
495 gpg->colon.fd[0] = -1;
496 gpg->colon.fd[1] = -1;
499 gpg->cmd.linked_data = NULL;
500 gpg->cmd.linked_idx = -1;
502 /* Allocate the read buffer for the status pipe. */
503 gpg->status.bufsize = 1024;
504 gpg->status.readpos = 0;
505 gpg->status.buffer = malloc (gpg->status.bufsize);
506 if (!gpg->status.buffer)
508 rc = gpg_error_from_syserror ();
511 /* In any case we need a status pipe - create it right here and
512 don't handle it with our generic gpgme_data_t mechanism. */
513 if (_gpgme_io_pipe (gpg->status.fd, 1) == -1)
515 rc = gpg_error_from_syserror ();
518 if (_gpgme_io_set_close_notify (gpg->status.fd[0],
519 close_notify_handler, gpg)
520 || _gpgme_io_set_close_notify (gpg->status.fd[1],
521 close_notify_handler, gpg))
523 rc = gpg_error (GPG_ERR_GENERAL);
530 rc = add_arg (gpg, "--homedir");
532 rc = add_arg (gpg, home_dir);
537 rc = add_arg (gpg, "--status-fd");
543 _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]);
544 rc = add_arg_with_locp (gpg, buf, &gpg->status.arg_loc);
549 rc = add_arg (gpg, "--no-tty");
551 rc = add_arg (gpg, "--charset");
553 rc = add_arg (gpg, "utf8");
555 rc = add_arg (gpg, "--enable-progress-filter");
556 if (!rc && have_gpg_version (gpg, "2.1.11"))
557 rc = add_arg (gpg, "--exit-on-status-write-error");
561 rc = _gpgme_getenv ("DISPLAY", &dft_display);
566 rc = add_arg (gpg, "--display");
568 rc = add_arg (gpg, dft_display);
575 rc = _gpgme_getenv ("GPG_TTY", &env_tty);
576 if (isatty (1) || env_tty || rc)
584 snprintf (dft_ttyname, sizeof (dft_ttyname), "%s", env_tty);
588 err = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
590 /* Even though isatty() returns 1, ttyname_r() may fail in many
591 ways, e.g., when /dev/pts is not accessible under chroot. */
596 rc = add_arg (gpg, "--ttyname");
598 rc = add_arg (gpg, dft_ttyname);
604 rc = _gpgme_getenv ("TERM", &dft_ttytype);
610 rc = add_arg (gpg, "--ttytype");
612 rc = add_arg (gpg, dft_ttytype);
632 gpg_set_locale (void *engine, int category, const char *value)
634 engine_gpg_t gpg = engine;
639 else if (category == LC_CTYPE)
643 free (gpg->lc_ctype);
644 gpg->lc_ctype = NULL;
648 gpg->lc_ctype = strdup (value);
650 return gpg_error_from_syserror ();
655 else if (category == LC_MESSAGES)
657 if (gpg->lc_messages)
659 free (gpg->lc_messages);
660 gpg->lc_messages = NULL;
664 gpg->lc_messages = strdup (value);
665 if (!gpg->lc_messages)
666 return gpg_error_from_syserror ();
669 #endif /* LC_MESSAGES */
671 return gpg_error (GPG_ERR_INV_VALUE);
676 /* This sets a status callback for monitoring status lines before they
677 * are passed to a caller set handler. */
679 gpg_set_status_cb (void *engine, gpgme_status_cb_t cb, void *cb_value)
681 engine_gpg_t gpg = engine;
683 gpg->status.mon_cb = cb;
684 gpg->status.mon_cb_value = cb_value;
688 /* Note, that the status_handler is allowed to modifiy the args
691 gpg_set_status_handler (void *engine, engine_status_handler_t fnc,
694 engine_gpg_t gpg = engine;
696 gpg->status.fnc = fnc;
697 gpg->status.fnc_value = fnc_value;
700 /* Kludge to process --with-colon output. */
702 gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
705 engine_gpg_t gpg = engine;
707 gpg->colon.bufsize = 1024;
708 gpg->colon.readpos = 0;
709 gpg->colon.buffer = malloc (gpg->colon.bufsize);
710 if (!gpg->colon.buffer)
711 return gpg_error_from_syserror ();
713 if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1)
715 int saved_err = gpg_error_from_syserror ();
716 free (gpg->colon.buffer);
717 gpg->colon.buffer = NULL;
720 if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg)
721 || _gpgme_io_set_close_notify (gpg->colon.fd[1],
722 close_notify_handler, gpg))
723 return gpg_error (GPG_ERR_GENERAL);
725 gpg->colon.fnc = fnc;
726 gpg->colon.fnc_value = fnc_value;
732 command_handler (void *opaque, int fd)
734 struct io_cb_data *data = (struct io_cb_data *) opaque;
735 engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
738 assert (gpg->cmd.used);
739 assert (gpg->cmd.code);
740 assert (gpg->cmd.fnc);
742 err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd,
746 /* And sleep again until read_status will wake us up again. */
747 /* XXX We must check if there are any more fds active after removing
749 (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag);
750 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
751 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
756 /* We always need to send at least a newline character. */
758 _gpgme_io_write (fd, "\n", 1);
765 /* The Fnc will be called to get a value for one of the commands with
766 a key KEY. If the Code passed to FNC is 0, the function may release
767 resources associated with the returned value from another call. To
768 match such a second call to a first call, the returned value from
769 the first call is passed as keyword. */
771 gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
772 void *fnc_value, gpgme_data_t linked_data)
774 engine_gpg_t gpg = engine;
777 rc = add_arg (gpg, "--command-fd");
781 /* This is a hack. We don't have a real data object. The only
782 thing that matters is that we use something unique, so we use the
783 address of the cmd structure in the gpg object. */
784 rc = add_data (gpg, (void *) &gpg->cmd, -2, 0);
789 gpg->cmd.cb_data = (void *) &gpg->cmd;
790 gpg->cmd.fnc_value = fnc_value;
791 gpg->cmd.linked_data = linked_data;
798 build_argv (engine_gpg_t gpg, const char *pgmname)
801 struct arg_and_data_s *a;
802 struct fd_data_map_s *fd_data_map;
803 size_t datac=0, argc=0;
805 int need_special = 0;
809 if (_gpgme_in_gpg_one_mode ())
811 /* In GnuPG-1 mode we don't want to use the agent with a
812 malformed environment variable. This is only a very basic
813 test but sufficient to make our life in the regression tests
814 easier. With GnuPG-2 the agent is anyway required and on
815 modern installations GPG_AGENT_INFO is optional. */
816 err = _gpgme_getenv ("GPG_AGENT_INFO", &p);
819 use_agent = (p && strchr (p, ':'));
826 free_argv (gpg->argv);
829 if (gpg->fd_data_map)
831 free_fd_data_map (gpg->fd_data_map);
832 gpg->fd_data_map = NULL;
835 argc++; /* For argv[0]. */
836 for (a = gpg->arglist; a; a = a->next)
841 /*fprintf (stderr, "build_argv: data\n" );*/
843 if (a->dup_to == -1 && !a->print_fd)
848 /* fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
855 if (gpg->pinentry_mode)
858 argc++; /* --batch */
859 argc += 1; /* --no-sk-comments */
861 argv = calloc (argc + 1, sizeof *argv);
863 return gpg_error_from_syserror ();
864 fd_data_map = calloc (datac + 1, sizeof *fd_data_map);
867 int saved_err = gpg_error_from_syserror ();
873 argv[argc] = strdup (_gpgme_get_basename (pgmname)); /* argv[0] */
876 int saved_err = gpg_error_from_syserror ();
884 argv[argc] = strdup ("--enable-special-filenames");
887 int saved_err = gpg_error_from_syserror ();
896 argv[argc] = strdup ("--use-agent");
899 int saved_err = gpg_error_from_syserror ();
907 if (gpg->pinentry_mode && have_gpg_version (gpg, "2.1.0"))
909 const char *s = NULL;
910 switch (gpg->pinentry_mode)
912 case GPGME_PINENTRY_MODE_DEFAULT: break;
913 case GPGME_PINENTRY_MODE_ASK: s = "--pinentry-mode=ask"; break;
914 case GPGME_PINENTRY_MODE_CANCEL: s = "--pinentry-mode=cancel"; break;
915 case GPGME_PINENTRY_MODE_ERROR: s = "--pinentry-mode=error"; break;
916 case GPGME_PINENTRY_MODE_LOOPBACK:s = "--pinentry-mode=loopback"; break;
920 argv[argc] = strdup (s);
923 int saved_err = gpg_error_from_syserror ();
934 argv[argc] = strdup ("--batch");
937 int saved_err = gpg_error_from_syserror ();
944 argv[argc] = strdup ("--no-sk-comments");
947 int saved_err = gpg_error_from_syserror ();
953 for (a = gpg->arglist; a; a = a->next)
956 *(a->arg_locp) = argc;
960 /* Create a pipe to pass it down to gpg. */
961 fd_data_map[datac].inbound = a->inbound;
967 if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0)
970 int saved_errno = errno;
973 return gpg_error (saved_errno);
975 if (_gpgme_io_set_close_notify (fds[0],
976 close_notify_handler, gpg)
977 || _gpgme_io_set_close_notify (fds[1],
978 close_notify_handler,
981 /* We leak fd_data_map and the fds. This is not easy
982 to avoid and given that we reach this here only
983 after a malloc failure for a small object, it is
984 probably better not to do anything. */
985 return gpg_error (GPG_ERR_GENERAL);
987 /* If the data_type is FD, we have to do a dup2 here. */
988 if (fd_data_map[datac].inbound)
990 fd_data_map[datac].fd = fds[0];
991 fd_data_map[datac].peer_fd = fds[1];
995 fd_data_map[datac].fd = fds[1];
996 fd_data_map[datac].peer_fd = fds[0];
1000 /* Hack to get hands on the fd later. */
1003 if (gpg->cmd.cb_data == a->data)
1005 assert (gpg->cmd.idx == -1);
1006 gpg->cmd.idx = datac;
1008 else if (gpg->cmd.linked_data == a->data)
1010 assert (gpg->cmd.linked_idx == -1);
1011 gpg->cmd.linked_idx = datac;
1015 fd_data_map[datac].data = a->data;
1016 fd_data_map[datac].dup_to = a->dup_to;
1018 if (a->dup_to == -1)
1023 argv[argc] = malloc (buflen);
1026 int saved_err = gpg_error_from_syserror ();
1040 _gpgme_io_fd2str (ptr, buflen, fd_data_map[datac].peer_fd);
1041 fd_data_map[datac].arg_loc = argc;
1048 argv[argc] = strdup (a->arg);
1051 int saved_err = gpg_error_from_syserror ();
1061 gpg->fd_data_map = fd_data_map;
1066 static gpgme_error_t
1067 add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
1072 err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
1076 /* FIXME Kludge around poll() problem. */
1077 err = _gpgme_io_set_nonblocking (fd);
1082 /* Handle the status output of GnuPG. This function does read entire
1083 lines and passes them as C strings to the callback function (we can
1084 use C Strings because the status output is always UTF-8 encoded).
1085 Of course we have to buffer the lines to cope with long lines
1086 e.g. with a large user ID. Note: We can optimize this to only cope
1087 with status line code we know about and skip all other stuff
1088 without buffering (i.e. without extending the buffer). */
1089 static gpgme_error_t
1090 read_status (engine_gpg_t gpg)
1094 size_t bufsize = gpg->status.bufsize;
1095 char *buffer = gpg->status.buffer;
1096 size_t readpos = gpg->status.readpos;
1100 if (bufsize - readpos < 256)
1102 /* Need more room for the read. */
1104 buffer = realloc (buffer, bufsize);
1106 return gpg_error_from_syserror ();
1109 nread = _gpgme_io_read (gpg->status.fd[0],
1110 buffer + readpos, bufsize-readpos);
1112 return gpg_error_from_syserror ();
1117 gpg->status.eof = 1;
1118 if (gpg->status.mon_cb)
1119 err = gpg->status.mon_cb (gpg->status.mon_cb_value, "", "");
1120 if (gpg->status.fnc)
1122 char emptystring[1] = {0};
1123 err = gpg->status.fnc (gpg->status.fnc_value,
1124 GPGME_STATUS_EOF, emptystring);
1125 if (gpg_err_code (err) == GPG_ERR_FALSE)
1126 err = 0; /* Drop special error code. */
1134 for (p = buffer + readpos; nread; nread--, p++)
1138 /* (we require that the last line is terminated by a LF) */
1139 if (p > buffer && p[-1] == '\r')
1142 if (!strncmp (buffer, "[GNUPG:] ", 9)
1143 && buffer[9] >= 'A' && buffer[9] <= 'Z')
1146 gpgme_status_code_t r;
1148 rest = strchr (buffer + 9, ' ');
1150 rest = p; /* Set to an empty string. */
1154 r = _gpgme_parse_status (buffer + 9);
1155 if (gpg->status.mon_cb && r != GPGME_STATUS_PROGRESS)
1157 /* Note that we call the monitor even if we do
1158 * not know the status code (r < 0). */
1159 err = gpg->status.mon_cb (gpg->status.mon_cb_value,
1167 && (r == GPGME_STATUS_GET_BOOL
1168 || r == GPGME_STATUS_GET_LINE
1169 || r == GPGME_STATUS_GET_HIDDEN))
1172 if (gpg->cmd.keyword)
1173 free (gpg->cmd.keyword);
1174 gpg->cmd.keyword = strdup (rest);
1175 if (!gpg->cmd.keyword)
1176 return gpg_error_from_syserror ();
1177 /* This should be the last thing we have
1178 received and the next thing will be that
1179 the command handler does its action. */
1181 TRACE0 (DEBUG_CTX, "gpgme:read_status", 0,
1182 "error: unexpected data");
1184 add_io_cb (gpg, gpg->cmd.fd, 0,
1185 command_handler, gpg,
1186 &gpg->fd_data_map[gpg->cmd.idx].tag);
1187 gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd;
1190 else if (gpg->status.fnc)
1192 err = gpg->status.fnc (gpg->status.fnc_value,
1194 if (gpg_err_code (err) == GPG_ERR_FALSE)
1195 err = 0; /* Drop special error code. */
1200 if (r == GPGME_STATUS_END_STREAM)
1204 /* Before we can actually add the
1205 command fd, we might have to flush
1206 the linked output data pipe. */
1207 if (gpg->cmd.linked_idx != -1
1208 && gpg->fd_data_map[gpg->cmd.linked_idx].fd
1211 struct io_select_fd_s fds;
1213 gpg->fd_data_map[gpg->cmd.linked_idx].fd;
1220 _gpgme_io_select (&fds, 1, 1);
1222 _gpgme_data_inbound_handler
1223 (gpg->cmd.linked_data, fds.fd);
1225 while (fds.signaled);
1228 /* XXX We must check if there are any
1229 more fds active after removing this
1231 (*gpg->io_cbs.remove)
1232 (gpg->fd_data_map[gpg->cmd.idx].tag);
1233 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
1234 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
1239 /* To reuse the buffer for the next line we have to
1240 shift the remaining data to the buffer start and
1241 restart the loop Hmmm: We can optimize this function
1242 by looking forward in the buffer to see whether a
1243 second complete line is available and in this case
1244 avoid the memmove for this line. */
1247 memmove (buffer, p, nread);
1249 break; /* the for loop */
1256 /* Update the gpg object. */
1257 gpg->status.bufsize = bufsize;
1258 gpg->status.buffer = buffer;
1259 gpg->status.readpos = readpos;
1264 static gpgme_error_t
1265 status_handler (void *opaque, int fd)
1267 struct io_cb_data *data = (struct io_cb_data *) opaque;
1268 engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
1271 assert (fd == gpg->status.fd[0]);
1272 err = read_status (gpg);
1275 if (gpg->status.eof)
1276 _gpgme_io_close (fd);
1281 static gpgme_error_t
1282 read_colon_line (engine_gpg_t gpg)
1286 size_t bufsize = gpg->colon.bufsize;
1287 char *buffer = gpg->colon.buffer;
1288 size_t readpos = gpg->colon.readpos;
1291 if (bufsize - readpos < 256)
1293 /* Need more room for the read. */
1295 buffer = realloc (buffer, bufsize);
1297 return gpg_error_from_syserror ();
1300 nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos);
1302 return gpg_error_from_syserror ();
1307 assert (gpg->colon.fnc);
1308 gpg->colon.fnc (gpg->colon.fnc_value, NULL);
1314 for (p = buffer + readpos; nread; nread--, p++)
1318 /* (we require that the last line is terminated by a LF)
1319 and we skip empty lines. Note: we use UTF8 encoding
1320 and escaping of special characters. We require at
1321 least one colon to cope with some other printed
1324 if (*buffer && strchr (buffer, ':'))
1328 if (gpg->colon.preprocess_fnc)
1332 err = gpg->colon.preprocess_fnc (buffer, &line);
1337 assert (gpg->colon.fnc);
1345 endp = strchr (linep, '\n');
1348 gpg->colon.fnc (gpg->colon.fnc_value, linep);
1351 while (linep && *linep);
1356 gpg->colon.fnc (gpg->colon.fnc_value, buffer);
1359 /* To reuse the buffer for the next line we have to
1360 shift the remaining data to the buffer start and
1361 restart the loop Hmmm: We can optimize this function
1362 by looking forward in the buffer to see whether a
1363 second complete line is available and in this case
1364 avoid the memmove for this line. */
1367 memmove (buffer, p, nread);
1369 break; /* The for loop. */
1376 /* Update the gpg object. */
1377 gpg->colon.bufsize = bufsize;
1378 gpg->colon.buffer = buffer;
1379 gpg->colon.readpos = readpos;
1384 /* This colonline handler thing is not the clean way to do it. It
1385 might be better to enhance the gpgme_data_t object to act as a wrapper
1386 for a callback. Same goes for the status thing. For now we use
1387 this thing here because it is easier to implement. */
1388 static gpgme_error_t
1389 colon_line_handler (void *opaque, int fd)
1391 struct io_cb_data *data = (struct io_cb_data *) opaque;
1392 engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
1393 gpgme_error_t rc = 0;
1395 assert (fd == gpg->colon.fd[0]);
1396 rc = read_colon_line (gpg);
1400 _gpgme_io_close (fd);
1405 static gpgme_error_t
1406 start (engine_gpg_t gpg)
1411 struct spawn_fd_item_s *fd_list;
1413 const char *pgmname;
1416 return gpg_error (GPG_ERR_INV_VALUE);
1418 if (!gpg->file_name && !_gpgme_get_default_gpg_name ())
1419 return trace_gpg_error (GPG_ERR_INV_ENGINE);
1423 rc = add_arg_ext (gpg, gpg->lc_ctype, 1);
1425 rc = add_arg_ext (gpg, "--lc-ctype", 1);
1430 if (gpg->lc_messages)
1432 rc = add_arg_ext (gpg, gpg->lc_messages, 1);
1434 rc = add_arg_ext (gpg, "--lc-messages", 1);
1439 pgmname = gpg->file_name ? gpg->file_name : _gpgme_get_default_gpg_name ();
1440 rc = build_argv (gpg, pgmname);
1444 /* status_fd, colon_fd and end of list. */
1446 for (i = 0; gpg->fd_data_map[i].data; i++)
1448 fd_list = calloc (n, sizeof *fd_list);
1450 return gpg_error_from_syserror ();
1452 /* Build the fd list for the child. */
1454 fd_list[n].fd = gpg->status.fd[1];
1455 fd_list[n].dup_to = -1;
1456 fd_list[n].arg_loc = gpg->status.arg_loc;
1460 fd_list[n].fd = gpg->colon.fd[1];
1461 fd_list[n].dup_to = 1;
1464 for (i = 0; gpg->fd_data_map[i].data; i++)
1466 fd_list[n].fd = gpg->fd_data_map[i].peer_fd;
1467 fd_list[n].dup_to = gpg->fd_data_map[i].dup_to;
1468 fd_list[n].arg_loc = gpg->fd_data_map[i].arg_loc;
1472 fd_list[n].dup_to = -1;
1474 status = _gpgme_io_spawn (pgmname, gpg->argv,
1475 (IOSPAWN_FLAG_DETACHED |IOSPAWN_FLAG_ALLOW_SET_FG),
1476 fd_list, NULL, NULL, &pid);
1478 int saved_err = gpg_error_from_syserror ();
1484 /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
1486 rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg,
1489 /* FIXME: kill the child */
1494 assert (gpg->colon.fd[0] != -1);
1495 rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg,
1498 /* FIXME: kill the child */
1502 for (i = 0; gpg->fd_data_map[i].data; i++)
1504 if (gpg->cmd.used && i == gpg->cmd.idx)
1506 /* Park the cmd fd. */
1507 gpg->cmd.fd = gpg->fd_data_map[i].fd;
1508 gpg->fd_data_map[i].fd = -1;
1512 rc = add_io_cb (gpg, gpg->fd_data_map[i].fd,
1513 gpg->fd_data_map[i].inbound,
1514 gpg->fd_data_map[i].inbound
1515 ? _gpgme_data_inbound_handler
1516 : _gpgme_data_outbound_handler,
1517 gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag);
1520 /* FIXME: kill the child */
1525 gpg_io_event (gpg, GPGME_EVENT_START, NULL);
1527 /* fixme: check what data we can release here */
1532 /* Add the --input-size-hint option if requested. */
1533 static gpgme_error_t
1534 add_input_size_hint (engine_gpg_t gpg, gpgme_data_t data)
1537 gpgme_off_t value = _gpgme_data_get_size_hint (data);
1538 char numbuf[50]; /* Large enough for even 2^128 in base-10. */
1541 if (!value || !have_gpg_version (gpg, "2.1.15"))
1544 err = add_arg (gpg, "--input-size-hint");
1547 p = numbuf + sizeof numbuf;
1551 *--p = '0' + (value % 10);
1555 err = add_arg (gpg, p);
1561 static gpgme_error_t
1562 gpg_decrypt (void *engine,
1563 gpgme_decrypt_flags_t flags,
1564 gpgme_data_t ciph, gpgme_data_t plain,
1565 int export_session_key, const char *override_session_key)
1567 engine_gpg_t gpg = engine;
1570 err = add_arg (gpg, "--decrypt");
1572 if (!err && (flags & GPGME_DECRYPT_UNWRAP))
1574 if (!have_gpg_version (gpg, "2.1.12"))
1575 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
1577 err = add_arg (gpg, "--unwrap");
1580 if (!err && export_session_key)
1581 err = add_arg (gpg, "--show-session-key");
1583 if (!err && override_session_key && *override_session_key)
1585 if (have_gpg_version (gpg, "2.1.16"))
1587 gpgme_data_release (gpg->override_session_key);
1588 TRACE2 (DEBUG_ENGINE, "override", gpg, "seskey='%s' len=%zu\n",
1589 override_session_key,
1590 strlen (override_session_key));
1592 err = gpgme_data_new_from_mem (&gpg->override_session_key,
1593 override_session_key,
1594 strlen (override_session_key), 1);
1597 err = add_arg (gpg, "--override-session-key-fd");
1599 err = add_data (gpg, gpg->override_session_key, -2, 0);
1604 /* Using that option may leak the session key via ps(1). */
1605 err = add_arg (gpg, "--override-session-key");
1607 err = add_arg (gpg, override_session_key);
1611 /* Tell the gpg object about the data. */
1613 err = add_arg (gpg, "--output");
1615 err = add_arg (gpg, "-");
1617 err = add_data (gpg, plain, 1, 1);
1619 err = add_input_size_hint (gpg, ciph);
1621 err = add_arg (gpg, "--");
1623 err = add_data (gpg, ciph, -1, 0);
1630 static gpgme_error_t
1631 gpg_delete (void *engine, gpgme_key_t key, unsigned int flags)
1633 engine_gpg_t gpg = engine;
1634 gpgme_error_t err = 0;
1635 int allow_secret = flags & GPGME_DELETE_ALLOW_SECRET;
1636 int force = flags & GPGME_DELETE_FORCE;
1639 err = add_arg (gpg, "--yes");
1641 err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key"
1644 err = add_arg (gpg, "--");
1647 if (!key->subkeys || !key->subkeys->fpr)
1648 return gpg_error (GPG_ERR_INV_VALUE);
1650 err = add_arg (gpg, key->subkeys->fpr);
1659 static gpgme_error_t
1660 gpg_passwd (void *engine, gpgme_key_t key, unsigned int flags)
1662 engine_gpg_t gpg = engine;
1667 if (!key || !key->subkeys || !key->subkeys->fpr)
1668 return gpg_error (GPG_ERR_INV_CERT_OBJ);
1670 err = add_arg (gpg, "--passwd");
1672 err = add_arg (gpg, key->subkeys->fpr);
1679 static gpgme_error_t
1680 append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1682 gpgme_error_t err = 0;
1686 for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
1688 const char *s = key->subkeys ? key->subkeys->keyid : NULL;
1692 err = add_arg (gpg, "-u");
1694 err = add_arg (gpg, s);
1696 gpgme_key_unref (key);
1704 static gpgme_error_t
1705 append_args_from_sender (engine_gpg_t gpg, gpgme_ctx_t ctx)
1709 if (ctx->sender && have_gpg_version (gpg, "2.1.15"))
1711 err = add_arg (gpg, "--sender");
1713 err = add_arg (gpg, ctx->sender);
1721 static gpgme_error_t
1722 append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1724 gpgme_error_t err = 0;
1725 gpgme_sig_notation_t notation;
1727 notation = gpgme_sig_notation_get (ctx);
1729 while (!err && notation)
1732 && !(notation->flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
1733 err = gpg_error (GPG_ERR_INV_VALUE);
1734 else if (notation->name)
1738 /* Maximum space needed is one byte for the "critical" flag,
1739 the name, one byte for '=', the value, and a terminating
1742 arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1);
1744 err = gpg_error_from_syserror ();
1750 if (notation->critical)
1753 memcpy (argp, notation->name, notation->name_len);
1754 argp += notation->name_len;
1758 /* We know that notation->name is '\0' terminated. */
1759 strcpy (argp, notation->value);
1763 err = add_arg (gpg, "--sig-notation");
1765 err = add_arg (gpg, arg);
1772 /* This is a policy URL. */
1776 if (notation->critical)
1778 value = malloc (1 + notation->value_len + 1);
1780 err = gpg_error_from_syserror ();
1784 /* We know that notation->value is '\0' terminated. */
1785 strcpy (&value[1], notation->value);
1789 value = notation->value;
1792 err = add_arg (gpg, "--sig-policy-url");
1794 err = add_arg (gpg, value);
1796 if (value != notation->value)
1800 notation = notation->next;
1806 static gpgme_error_t
1807 gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
1808 gpgme_ctx_t ctx /* FIXME */)
1810 engine_gpg_t gpg = engine;
1813 err = add_arg (gpg, "--with-colons");
1815 err = append_args_from_signers (gpg, ctx);
1817 err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
1819 err = add_data (gpg, out, 1, 1);
1821 err = add_arg (gpg, "--");
1822 if (!err && type == 0)
1824 const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1826 err = gpg_error (GPG_ERR_INV_VALUE);
1828 err = add_arg (gpg, s);
1837 static gpgme_error_t
1838 append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
1840 gpgme_error_t err = 0;
1845 if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
1846 err = gpg_error (GPG_ERR_INV_VALUE);
1848 err = add_arg (gpg, "-r");
1850 err = add_arg (gpg, recp[i]->subkeys->fpr);
1859 static gpgme_error_t
1860 gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
1861 gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
1863 engine_gpg_t gpg = engine;
1864 gpgme_error_t err = 0;
1867 err = add_arg (gpg, "--encrypt");
1869 if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp))
1870 err = add_arg (gpg, "--symmetric");
1872 if (!err && use_armor)
1873 err = add_arg (gpg, "--armor");
1875 if (!err && (flags & GPGME_ENCRYPT_WRAP))
1877 /* gpg is current not able to detect already compressed
1878 * packets. Thus when using
1879 * gpg --unwrap -d | gpg --no-literal -e
1880 * the encryption would add an additional compression layer.
1881 * We better suppress that. */
1882 flags |= GPGME_ENCRYPT_NO_COMPRESS;
1883 err = add_arg (gpg, "--no-literal");
1886 if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
1887 err = add_arg (gpg, "--compress-algo=none");
1889 if (!err && (flags & GPGME_ENCRYPT_THROW_KEYIDS))
1890 err = add_arg (gpg, "--throw-keyids");
1892 if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
1893 && have_gpg_version (gpg, "2.1.14"))
1894 err = add_arg (gpg, "--mimemode");
1898 /* If we know that all recipients are valid (full or ultimate trust)
1899 we can suppress further checks. */
1900 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1901 err = add_arg (gpg, "--always-trust");
1903 if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
1904 err = add_arg (gpg, "--no-encrypt-to");
1907 err = append_args_from_recipients (gpg, recp);
1910 /* Tell the gpg object about the data. */
1912 err = add_arg (gpg, "--output");
1914 err = add_arg (gpg, "-");
1916 err = add_data (gpg, ciph, 1, 1);
1917 if (gpgme_data_get_file_name (plain))
1920 err = add_arg (gpg, "--set-filename");
1922 err = add_arg (gpg, gpgme_data_get_file_name (plain));
1925 err = add_input_size_hint (gpg, plain);
1927 err = add_arg (gpg, "--");
1929 err = add_data (gpg, plain, -1, 0);
1938 static gpgme_error_t
1939 gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
1940 gpgme_encrypt_flags_t flags, gpgme_data_t plain,
1941 gpgme_data_t ciph, int use_armor,
1942 gpgme_ctx_t ctx /* FIXME */)
1944 engine_gpg_t gpg = engine;
1945 gpgme_error_t err = 0;
1948 err = add_arg (gpg, "--encrypt");
1950 if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp))
1951 err = add_arg (gpg, "--symmetric");
1954 err = add_arg (gpg, "--sign");
1955 if (!err && use_armor)
1956 err = add_arg (gpg, "--armor");
1958 if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
1959 err = add_arg (gpg, "--compress-algo=none");
1961 if (!err && (flags & GPGME_ENCRYPT_THROW_KEYIDS))
1962 err = add_arg (gpg, "--throw-keyids");
1964 if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
1965 && have_gpg_version (gpg, "2.1.14"))
1966 err = add_arg (gpg, "--mimemode");
1970 /* If we know that all recipients are valid (full or ultimate trust)
1971 we can suppress further checks. */
1972 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1973 err = add_arg (gpg, "--always-trust");
1975 if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
1976 err = add_arg (gpg, "--no-encrypt-to");
1979 err = append_args_from_recipients (gpg, recp);
1983 err = append_args_from_signers (gpg, ctx);
1986 err = append_args_from_sender (gpg, ctx);
1989 err = append_args_from_sig_notations (gpg, ctx);
1991 /* Tell the gpg object about the data. */
1993 err = add_arg (gpg, "--output");
1995 err = add_arg (gpg, "-");
1997 err = add_data (gpg, ciph, 1, 1);
1998 if (gpgme_data_get_file_name (plain))
2001 err = add_arg (gpg, "--set-filename");
2003 err = add_arg (gpg, gpgme_data_get_file_name (plain));
2006 err = add_input_size_hint (gpg, plain);
2008 err = add_arg (gpg, "--");
2010 err = add_data (gpg, plain, -1, 0);
2019 static gpgme_error_t
2020 export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
2021 gpgme_data_t keydata, int use_armor)
2023 gpgme_error_t err = 0;
2025 if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
2026 |GPGME_EXPORT_MODE_MINIMAL
2027 |GPGME_EXPORT_MODE_SECRET)))
2028 return gpg_error (GPG_ERR_NOT_SUPPORTED);
2030 if ((mode & GPGME_EXPORT_MODE_MINIMAL))
2031 err = add_arg (gpg, "--export-options=export-minimal");
2035 else if ((mode & GPGME_EXPORT_MODE_EXTERN))
2037 err = add_arg (gpg, "--send-keys");
2041 if ((mode & GPGME_EXPORT_MODE_SECRET))
2042 err = add_arg (gpg, "--export-secret-keys");
2044 err = add_arg (gpg, "--export");
2045 if (!err && use_armor)
2046 err = add_arg (gpg, "--armor");
2048 err = add_data (gpg, keydata, 1, 1);
2051 err = add_arg (gpg, "--");
2057 static gpgme_error_t
2058 gpg_export (void *engine, const char *pattern, gpgme_export_mode_t mode,
2059 gpgme_data_t keydata, int use_armor)
2061 engine_gpg_t gpg = engine;
2064 err = export_common (gpg, mode, keydata, use_armor);
2066 if (!err && pattern && *pattern)
2067 err = add_arg (gpg, pattern);
2076 static gpgme_error_t
2077 gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
2078 gpgme_data_t keydata, int use_armor)
2080 engine_gpg_t gpg = engine;
2083 err = export_common (gpg, mode, keydata, use_armor);
2087 while (!err && *pattern && **pattern)
2088 err = add_arg (gpg, *(pattern++));
2099 /* Helper to add algo, usage, and expire to the list of args. */
2100 static gpgme_error_t
2101 gpg_add_algo_usage_expire (engine_gpg_t gpg,
2103 unsigned long expires,
2108 /* This condition is only required to allow the use of gpg < 2.1.16 */
2110 || (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR
2111 | GPGME_CREATE_CERT | GPGME_CREATE_AUTH
2112 | GPGME_CREATE_NOEXPIRE))
2115 err = add_arg (gpg, algo? algo : "default");
2119 snprintf (tmpbuf, sizeof tmpbuf, "%s%s%s%s",
2120 (flags & GPGME_CREATE_SIGN)? " sign":"",
2121 (flags & GPGME_CREATE_ENCR)? " encr":"",
2122 (flags & GPGME_CREATE_CERT)? " cert":"",
2123 (flags & GPGME_CREATE_AUTH)? " auth":"");
2124 err = add_arg (gpg, *tmpbuf? tmpbuf : "default");
2128 if ((flags & GPGME_CREATE_NOEXPIRE))
2129 err = add_arg (gpg, "never");
2130 else if (expires == 0)
2131 err = add_arg (gpg, "-");
2135 snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires);
2136 err = add_arg (gpg, tmpbuf);
2147 static gpgme_error_t
2148 gpg_createkey_from_param (engine_gpg_t gpg,
2149 gpgme_data_t help_data, unsigned int extraflags)
2153 err = add_arg (gpg, "--gen-key");
2154 if (!err && (extraflags & GENKEY_EXTRAFLAG_ARMOR))
2155 err = add_arg (gpg, "--armor");
2157 err = add_arg (gpg, "--");
2159 err = add_data (gpg, help_data, -1, 0);
2166 static gpgme_error_t
2167 gpg_createkey (engine_gpg_t gpg,
2168 const char *userid, const char *algo,
2169 unsigned long expires,
2171 unsigned int extraflags)
2175 err = add_arg (gpg, "--quick-gen-key");
2176 if (!err && (extraflags & GENKEY_EXTRAFLAG_ARMOR))
2177 err = add_arg (gpg, "--armor");
2178 if (!err && (flags & GPGME_CREATE_NOPASSWD))
2180 err = add_arg (gpg, "--passphrase");
2182 err = add_arg (gpg, "");
2184 err = add_arg (gpg, "--batch");
2186 if (!err && (flags & GPGME_CREATE_FORCE))
2187 err = add_arg (gpg, "--yes");
2189 err = add_arg (gpg, "--");
2191 err = add_arg (gpg, userid);
2194 err = gpg_add_algo_usage_expire (gpg, algo, expires, flags);
2202 static gpgme_error_t
2203 gpg_addkey (engine_gpg_t gpg,
2205 unsigned long expires,
2208 unsigned int extraflags)
2212 if (!key || !key->fpr)
2213 return gpg_error (GPG_ERR_INV_ARG);
2215 err = add_arg (gpg, "--quick-addkey");
2216 if (!err && (extraflags & GENKEY_EXTRAFLAG_ARMOR))
2217 err = add_arg (gpg, "--armor");
2218 if (!err && (flags & GPGME_CREATE_NOPASSWD))
2220 err = add_arg (gpg, "--passphrase");
2222 err = add_arg (gpg, "");
2224 err = add_arg (gpg, "--batch");
2227 err = add_arg (gpg, "--");
2229 err = add_arg (gpg, key->fpr);
2232 err = gpg_add_algo_usage_expire (gpg, algo, expires, flags);
2240 static gpgme_error_t
2241 gpg_adduid (engine_gpg_t gpg,
2244 unsigned int extraflags)
2248 if (!key || !key->fpr || !userid)
2249 return gpg_error (GPG_ERR_INV_ARG);
2251 if ((extraflags & GENKEY_EXTRAFLAG_SETPRIMARY))
2253 if (!have_gpg_version (gpg, "2.1.20"))
2254 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2256 err = add_arg (gpg, "--quick-set-primary-uid");
2258 else if ((extraflags & GENKEY_EXTRAFLAG_REVOKE))
2259 err = add_arg (gpg, "--quick-revuid");
2261 err = add_arg (gpg, "--quick-adduid");
2264 err = add_arg (gpg, "--");
2266 err = add_arg (gpg, key->fpr);
2268 err = add_arg (gpg, userid);
2276 static gpgme_error_t
2277 gpg_genkey (void *engine,
2278 const char *userid, const char *algo,
2279 unsigned long reserved, unsigned long expires,
2280 gpgme_key_t key, unsigned int flags,
2281 gpgme_data_t help_data, unsigned int extraflags,
2282 gpgme_data_t pubkey, gpgme_data_t seckey)
2284 engine_gpg_t gpg = engine;
2290 return gpg_error (GPG_ERR_INV_VALUE);
2292 /* If HELP_DATA is given the use of the old interface
2293 * (gpgme_op_genkey) has been requested. The other modes are:
2295 * USERID && !KEY - Create a new keyblock.
2296 * !USERID && KEY - Add a new subkey to KEY (gpg >= 2.1.14)
2297 * USERID && KEY && !ALGO - Add a new user id to KEY (gpg >= 2.1.14).
2298 * or set a flag on a user id.
2302 /* We need a special mechanism to get the fd of a pipe here, so
2303 that we can use this for the %pubring and %secring
2304 parameters. We don't have this yet, so we implement only the
2305 adding to the standard keyrings. */
2306 if (pubkey || seckey)
2307 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2309 err = gpg_createkey_from_param (gpg, help_data, extraflags);
2311 else if (!have_gpg_version (gpg, "2.1.13"))
2312 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2313 else if (userid && !key)
2314 err = gpg_createkey (gpg, userid, algo, expires, flags, extraflags);
2315 else if (!userid && key)
2316 err = gpg_addkey (gpg, algo, expires, key, flags, extraflags);
2317 else if (userid && key && !algo)
2318 err = gpg_adduid (gpg, key, userid, extraflags);
2320 err = gpg_error (GPG_ERR_INV_VALUE);
2325 /* Return the next DELIM delimited string from DATA as a C-string.
2326 The caller needs to provide the address of a pointer variable which
2327 he has to set to NULL before the first call. After the last call
2328 to this function, this function needs to be called once more with
2329 DATA set to NULL so that the function can release its internal
2330 state. After that the pointer variable is free for use again.
2331 Note that we use a delimiter and thus a trailing delimiter is not
2332 required. DELIM may not be changed after the first call. */
2334 string_from_data (gpgme_data_t data, int delim,
2335 void **helpptr, gpgme_error_t *r_err)
2337 #define MYBUFLEN 2000 /* Fixme: We don't support URLs longer than that. */
2340 int nbytes; /* Length of the last returned string including
2342 int buflen; /* Valid length of BUF. */
2343 char buf[MYBUFLEN+1]; /* Buffer with one byte extra space. */
2363 self = malloc (sizeof *self);
2366 *r_err = gpg_error_from_syserror ();
2378 assert (self->nbytes <= self->buflen);
2379 memmove (self->buf, self->buf + self->nbytes, self->buflen - self->nbytes);
2380 self->buflen -= self->nbytes;
2385 /* Fixme: This is fairly infective scanning because we may scan
2386 the buffer several times. */
2387 p = memchr (self->buf, delim, self->buflen);
2391 self->nbytes = p - self->buf + 1;
2395 if ( !(MYBUFLEN - self->buflen) )
2397 /* Not enough space - URL too long. */
2398 *r_err = gpg_error (GPG_ERR_TOO_LARGE);
2402 nread = gpgme_data_read (data, self->buf + self->buflen,
2403 MYBUFLEN - self->buflen);
2406 *r_err = gpg_error_from_syserror ();
2409 self->buflen += nread;
2413 /* EOF reached. If we have anything in the buffer, append a Nul and
2418 self->buf[self->buflen] = 0; /* (we allocated one extra byte) */
2427 static gpgme_error_t
2428 gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
2430 engine_gpg_t gpg = engine;
2433 gpgme_data_encoding_t dataenc;
2435 if (keydata && keyarray)
2436 return gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */
2438 dataenc = gpgme_data_get_encoding (keydata);
2442 err = add_arg (gpg, "--recv-keys");
2444 err = add_arg (gpg, "--");
2445 for (idx=0; !err && keyarray[idx]; idx++)
2447 if (keyarray[idx]->protocol != GPGME_PROTOCOL_OpenPGP)
2449 else if (!keyarray[idx]->subkeys)
2451 else if (keyarray[idx]->subkeys->fpr && *keyarray[idx]->subkeys->fpr)
2452 err = add_arg (gpg, keyarray[idx]->subkeys->fpr);
2453 else if (*keyarray[idx]->subkeys->keyid)
2454 err = add_arg (gpg, keyarray[idx]->subkeys->keyid);
2457 else if (dataenc == GPGME_DATA_ENCODING_URL
2458 || dataenc == GPGME_DATA_ENCODING_URL0)
2463 int delim = (dataenc == GPGME_DATA_ENCODING_URL)? '\n': 0;
2465 /* FIXME: --fetch-keys is probably not correct because it can't
2466 grok all kinds of URLs. On Unix it should just work but on
2467 Windows we will build the command line and that may fail for
2468 some embedded control characters. It is anyway limited to
2469 the maximum size of the command line. We need another
2470 command which can take its input from a file. Maybe we
2471 should use an option to gpg to modify such commands (ala
2473 err = add_arg (gpg, "--fetch-keys");
2475 err = add_arg (gpg, "--");
2478 && (string = string_from_data (keydata, delim, &helpptr, &xerr)))
2479 err = add_arg (gpg, string);
2482 string_from_data (NULL, delim, &helpptr, &xerr);
2484 else if (dataenc == GPGME_DATA_ENCODING_URLESC)
2486 /* Already escaped URLs are not yet supported. */
2487 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2491 err = add_arg (gpg, "--import");
2493 err = add_arg (gpg, "--");
2495 err = add_data (gpg, keydata, -1, 0);
2505 /* The output for external keylistings in GnuPG is different from all
2506 the other key listings. We catch this here with a special
2507 preprocessor that reformats the colon handler lines. */
2508 static gpgme_error_t
2509 gpg_keylist_preprocess (char *line, char **r_line)
2513 RT_NONE, RT_INFO, RT_PUB, RT_UID
2516 #define NR_FIELDS 16
2517 char *field[NR_FIELDS];
2523 while (line && fields < NR_FIELDS)
2525 field[fields++] = line;
2526 line = strchr (line, ':');
2531 if (!strcmp (field[0], "info"))
2533 else if (!strcmp (field[0], "pub"))
2535 else if (!strcmp (field[0], "uid"))
2543 /* FIXME: Eventually, check the version number at least. */
2552 pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>
2554 as defined in 5.2. Machine Readable Indexes of the OpenPGP
2555 HTTP Keyserver Protocol (draft). Modern versions of the SKS
2556 keyserver return the fingerprint instead of the keyid. We
2557 detect this here and use the v4 fingerprint format to convert
2561 pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>::::::::
2564 n = strlen (field[1]);
2567 if (gpgrt_asprintf (r_line,
2568 "pub:o%s:%s:%s:%s:%s:%s::::::::\n"
2570 field[6], field[3], field[2], field[1] + n - 16,
2571 field[4], field[5], field[1]) < 0)
2572 return gpg_error_from_syserror ();
2576 if (gpgrt_asprintf (r_line,
2577 "pub:o%s:%s:%s:%s:%s:%s::::::::",
2578 field[6], field[3], field[2], field[1],
2579 field[4], field[5]) < 0)
2580 return gpg_error_from_syserror ();
2588 uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags>
2590 as defined in 5.2. Machine Readable Indexes of the OpenPGP
2591 HTTP Keyserver Protocol (draft).
2594 uid:o<flags>::::<creatdate>:<expdate>:::<c-coded uid>:
2598 /* The user ID is percent escaped, but we want c-coded.
2599 Because we have to replace each '%HL' by '\xHL', we need at
2600 most 4/3 th the number of bytes. But because we also need
2601 to escape the backslashes we allocate twice as much. */
2602 char *uid = malloc (2 * strlen (field[1]) + 1);
2607 return gpg_error_from_syserror ();
2617 /* Copy the next two bytes unconditionally. */
2619 *(dst++) = *(src++);
2621 *(dst++) = *(src++);
2623 else if (*src == '\\')
2630 *(dst++) = *(src++);
2634 if (gpgrt_asprintf (r_line, "uid:o%s::::%s:%s:::%s:",
2635 field[4], field[2], field[3], uid) < 0)
2636 return gpg_error_from_syserror ();
2641 /* Unknown record. */
2650 gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
2651 gpgme_keylist_mode_t mode)
2655 err = add_arg (gpg, "--with-colons");
2657 /* Since gpg 2.1.15 fingerprints are always printed, thus there is
2658 * no more need to explicitly request them. */
2659 if (!have_gpg_version (gpg, "2.1.15"))
2662 err = add_arg (gpg, "--fixed-list-mode");
2664 err = add_arg (gpg, "--with-fingerprint");
2666 err = add_arg (gpg, "--with-fingerprint");
2669 if (!err && (mode & GPGME_KEYLIST_MODE_WITH_TOFU)
2670 && have_gpg_version (gpg, "2.1.16"))
2671 err = add_arg (gpg, "--with-tofu-info");
2673 if (!err && (mode & GPGME_KEYLIST_MODE_WITH_SECRET))
2674 err = add_arg (gpg, "--with-secret");
2677 && (mode & GPGME_KEYLIST_MODE_SIGS)
2678 && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
2680 err = add_arg (gpg, "--list-options");
2682 err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
2687 if ( (mode & GPGME_KEYLIST_MODE_EXTERN) )
2690 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2691 else if ( (mode & GPGME_KEYLIST_MODE_LOCAL))
2693 /* The local+extern mode is special. It works only with
2694 gpg >= 2.0.10. FIXME: We should check that we have
2695 such a version to that we can return a proper error
2696 code. The problem is that we don't know the context
2697 here and thus can't access the cached version number
2698 for the engine info structure. */
2699 err = add_arg (gpg, "--locate-keys");
2700 if ((mode & GPGME_KEYLIST_MODE_SIGS))
2701 err = add_arg (gpg, "--with-sig-check");
2705 err = add_arg (gpg, "--search-keys");
2706 gpg->colon.preprocess_fnc = gpg_keylist_preprocess;
2711 err = add_arg (gpg, secret_only ? "--list-secret-keys"
2712 : ((mode & GPGME_KEYLIST_MODE_SIGS)
2713 ? "--check-sigs" : "--list-keys"));
2718 err = add_arg (gpg, "--");
2724 static gpgme_error_t
2725 gpg_keylist (void *engine, const char *pattern, int secret_only,
2726 gpgme_keylist_mode_t mode, int engine_flags)
2728 engine_gpg_t gpg = engine;
2733 err = gpg_keylist_build_options (gpg, secret_only, mode);
2735 if (!err && pattern && *pattern)
2736 err = add_arg (gpg, pattern);
2745 static gpgme_error_t
2746 gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
2747 int reserved, gpgme_keylist_mode_t mode, int engine_flags)
2749 engine_gpg_t gpg = engine;
2755 return gpg_error (GPG_ERR_INV_VALUE);
2757 err = gpg_keylist_build_options (gpg, secret_only, mode);
2761 while (!err && *pattern && **pattern)
2762 err = add_arg (gpg, *(pattern++));
2772 static gpgme_error_t
2773 gpg_keylist_data (void *engine, gpgme_data_t data)
2775 engine_gpg_t gpg = engine;
2778 if (!have_gpg_version (gpg, "2.1.14"))
2779 return gpg_error (GPG_ERR_NOT_SUPPORTED);
2781 err = add_arg (gpg, "--with-colons");
2783 err = add_arg (gpg, "--with-fingerprint");
2785 err = add_arg (gpg, "--import-options");
2787 err = add_arg (gpg, "import-show");
2789 err = add_arg (gpg, "--dry-run");
2791 err = add_arg (gpg, "--import");
2793 err = add_arg (gpg, "--");
2795 err = add_data (gpg, data, -1, 0);
2804 static gpgme_error_t
2805 gpg_keysign (void *engine, gpgme_key_t key, const char *userid,
2806 unsigned long expire, unsigned int flags,
2809 engine_gpg_t gpg = engine;
2813 if (!key || !key->fpr)
2814 return gpg_error (GPG_ERR_INV_ARG);
2816 if (!have_gpg_version (gpg, "2.1.12"))
2817 return gpg_error (GPG_ERR_NOT_SUPPORTED);
2819 if ((flags & GPGME_KEYSIGN_LOCAL))
2820 err = add_arg (gpg, "--quick-lsign-key");
2822 err = add_arg (gpg, "--quick-sign-key");
2825 err = append_args_from_signers (gpg, ctx);
2827 /* If an expiration time has been given use that. If none has been
2828 * given the default from gpg.conf is used. To make sure not to set
2829 * an expiration time at all the flag GPGME_KEYSIGN_NOEXPIRE can be
2831 if (!err && (expire || (flags & GPGME_KEYSIGN_NOEXPIRE)))
2835 if ((flags & GPGME_KEYSIGN_NOEXPIRE))
2837 snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expire);
2838 err = add_arg (gpg, "--default-cert-expire");
2840 err = add_arg (gpg, tmpbuf);
2844 err = add_arg (gpg, "--");
2847 err = add_arg (gpg, key->fpr);
2850 if ((flags & GPGME_KEYSIGN_LFSEP))
2852 for (; !err && (s = strchr (userid, '\n')); userid = s + 1)
2854 err = add_arg_len (gpg, "=", userid, s - userid);
2855 if (!err && *userid)
2856 err = add_arg_pfx (gpg, "=", userid);
2859 err = add_arg_pfx (gpg, "=", userid);
2869 static gpgme_error_t
2870 gpg_tofu_policy (void *engine, gpgme_key_t key, gpgme_tofu_policy_t policy)
2872 engine_gpg_t gpg = engine;
2874 const char *policystr = NULL;
2876 if (!key || !key->fpr)
2877 return gpg_error (GPG_ERR_INV_ARG);
2881 case GPGME_TOFU_POLICY_NONE: break;
2882 case GPGME_TOFU_POLICY_AUTO: policystr = "auto"; break;
2883 case GPGME_TOFU_POLICY_GOOD: policystr = "good"; break;
2884 case GPGME_TOFU_POLICY_BAD: policystr = "bad"; break;
2885 case GPGME_TOFU_POLICY_ASK: policystr = "ask"; break;
2886 case GPGME_TOFU_POLICY_UNKNOWN: policystr = "unknown"; break;
2889 return gpg_error (GPG_ERR_INV_VALUE);
2891 if (!have_gpg_version (gpg, "2.1.10"))
2892 return gpg_error (GPG_ERR_NOT_SUPPORTED);
2894 err = add_arg (gpg, "--tofu-policy");
2896 err = add_arg (gpg, "--");
2898 err = add_arg (gpg, policystr);
2900 err = add_arg (gpg, key->fpr);
2909 static gpgme_error_t
2910 gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
2911 gpgme_sig_mode_t mode, int use_armor, int use_textmode,
2912 int include_certs, gpgme_ctx_t ctx /* FIXME */)
2914 engine_gpg_t gpg = engine;
2917 (void)include_certs;
2919 if (mode == GPGME_SIG_MODE_CLEAR)
2920 err = add_arg (gpg, "--clearsign");
2923 err = add_arg (gpg, "--sign");
2924 if (!err && mode == GPGME_SIG_MODE_DETACH)
2925 err = add_arg (gpg, "--detach");
2926 if (!err && use_armor)
2927 err = add_arg (gpg, "--armor");
2930 if (gpgme_data_get_encoding (in) == GPGME_DATA_ENCODING_MIME
2931 && have_gpg_version (gpg, "2.1.14"))
2932 err = add_arg (gpg, "--mimemode");
2933 else if (use_textmode)
2934 err = add_arg (gpg, "--textmode");
2939 err = append_args_from_signers (gpg, ctx);
2941 err = append_args_from_sender (gpg, ctx);
2943 err = append_args_from_sig_notations (gpg, ctx);
2945 if (gpgme_data_get_file_name (in))
2948 err = add_arg (gpg, "--set-filename");
2950 err = add_arg (gpg, gpgme_data_get_file_name (in));
2953 /* Tell the gpg object about the data. */
2955 err = add_input_size_hint (gpg, in);
2957 err = add_arg (gpg, "--");
2959 err = add_data (gpg, in, -1, 0);
2961 err = add_data (gpg, out, 1, 1);
2969 static gpgme_error_t
2970 gpg_trustlist (void *engine, const char *pattern)
2972 engine_gpg_t gpg = engine;
2975 err = add_arg (gpg, "--with-colons");
2977 err = add_arg (gpg, "--list-trust-path");
2979 /* Tell the gpg object about the data. */
2981 err = add_arg (gpg, "--");
2983 err = add_arg (gpg, pattern);
2992 static gpgme_error_t
2993 gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
2994 gpgme_data_t plaintext, gpgme_ctx_t ctx)
2996 engine_gpg_t gpg = engine;
2999 err = append_args_from_sender (gpg, ctx);
3004 /* Normal or cleartext signature. */
3005 err = add_arg (gpg, "--output");
3007 err = add_arg (gpg, "-");
3009 err = add_input_size_hint (gpg, sig);
3011 err = add_arg (gpg, "--");
3013 err = add_data (gpg, sig, -1, 0);
3015 err = add_data (gpg, plaintext, 1, 1);
3019 err = add_arg (gpg, "--verify");
3021 err = add_input_size_hint (gpg, signed_text);
3023 err = add_arg (gpg, "--");
3025 err = add_data (gpg, sig, -1, 0);
3026 if (!err && signed_text)
3027 err = add_data (gpg, signed_text, -1, 0);
3038 gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
3040 engine_gpg_t gpg = engine;
3042 gpg->io_cbs = *io_cbs;
3046 static gpgme_error_t
3047 gpg_set_pinentry_mode (void *engine, gpgme_pinentry_mode_t mode)
3049 engine_gpg_t gpg = engine;
3051 gpg->pinentry_mode = mode;
3057 struct engine_ops _gpgme_engine_ops_gpg =
3059 /* Static functions. */
3060 _gpgme_get_default_gpg_name,
3063 gpg_get_req_version,
3066 /* Member functions. */
3070 gpg_set_status_handler,
3071 gpg_set_command_handler,
3072 gpg_set_colon_line_handler,
3074 NULL, /* set_protocol */
3088 gpg_tofu_policy, /* tofu_policy */
3092 NULL, /* getauditlog */
3093 NULL, /* opassuan_transact */
3094 NULL, /* conf_load */
3095 NULL, /* conf_save */
3096 NULL, /* conf_dir */
3097 NULL, /* query_swdb */
3101 NULL, /* cancel_op */
3103 gpg_set_pinentry_mode,