1 /* engine-gpg.c - Gpg Engine.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007,
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 <http://www.gnu.org/licenses/>.
37 #include "context.h" /*temp hack until we have GpmeData methods to do I/O */
42 #include "status-table.h"
43 #include "engine-backend.h"
46 /* This type is used to build a list of gpg arguments and data
50 struct arg_and_data_s *next;
51 gpgme_data_t data; /* If this is not NULL, use arg below. */
52 int inbound; /* True if this is used for reading from gpg. */
54 int print_fd; /* Print the fd number and not the special form of it. */
55 int *arg_locp; /* Write back the argv idx of this argument when
56 building command line to this location. */
57 char arg[1]; /* Used if data above is not used. */
64 int inbound; /* true if this is used for reading from gpg */
66 int fd; /* the fd to use */
67 int peer_fd; /* the other side of the pipe */
68 int arg_loc; /* The index into the argv for translation purposes. */
73 typedef gpgme_error_t (*colon_preprocessor_t) (char *line, char **rline);
82 struct arg_and_data_s *arglist;
83 struct arg_and_data_s **argtail;
93 engine_status_handler_t fnc;
98 /* This is a kludge - see the comment at colon_line_handler. */
107 engine_colon_line_handler_t fnc; /* this indicate use of this structrue */
110 colon_preprocessor_t preprocess_fnc;
114 struct fd_data_map_s *fd_data_map;
116 /* stuff needed for interactive (command) mode */
122 int idx; /* Index in fd_data_map */
123 gpgme_status_code_t code; /* last code */
124 char *keyword; /* what has been requested (malloced) */
125 engine_command_handler_t fnc;
127 /* The kludges never end. This is used to couple command handlers
128 with output data in edit key mode. */
129 gpgme_data_t linked_data;
133 struct gpgme_io_cbs io_cbs;
136 typedef struct engine_gpg *engine_gpg_t;
140 gpg_io_event (void *engine, gpgme_event_io_t type, void *type_data)
142 engine_gpg_t gpg = engine;
144 TRACE3 (DEBUG_ENGINE, "gpgme:gpg_io_event", gpg,
145 "event %p, type %d, type_data %p",
146 gpg->io_cbs.event, type, type_data);
147 if (gpg->io_cbs.event)
148 (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data);
153 close_notify_handler (int fd, void *opaque)
155 engine_gpg_t gpg = opaque;
158 if (gpg->status.fd[0] == fd)
161 (*gpg->io_cbs.remove) (gpg->status.tag);
162 gpg->status.fd[0] = -1;
164 else if (gpg->status.fd[1] == fd)
165 gpg->status.fd[1] = -1;
166 else if (gpg->colon.fd[0] == fd)
169 (*gpg->io_cbs.remove) (gpg->colon.tag);
170 gpg->colon.fd[0] = -1;
172 else if (gpg->colon.fd[1] == fd)
173 gpg->colon.fd[1] = -1;
174 else if (gpg->cmd.fd == fd)
176 else if (gpg->fd_data_map)
180 for (i = 0; gpg->fd_data_map[i].data; i++)
182 if (gpg->fd_data_map[i].fd == fd)
184 if (gpg->fd_data_map[i].tag)
185 (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
186 gpg->fd_data_map[i].fd = -1;
189 if (gpg->fd_data_map[i].peer_fd == fd)
191 gpg->fd_data_map[i].peer_fd = -1;
198 /* If FRONT is true, push at the front of the list. Use this for
199 options added late in the process. */
201 _add_arg (engine_gpg_t gpg, const char *arg, int front, int *arg_locp)
203 struct arg_and_data_s *a;
208 a = malloc (sizeof *a + strlen (arg));
210 return gpg_error_from_errno (errno);
214 a->arg_locp = arg_locp;
216 strcpy (a->arg, arg);
219 a->next = gpg->arglist;
222 /* If this is the first argument, we need to update the tail
224 gpg->argtail = &a->next;
232 gpg->argtail = &a->next;
239 add_arg_ext (engine_gpg_t gpg, const char *arg, int front)
241 return _add_arg (gpg, arg, front, NULL);
246 add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp)
248 return _add_arg (gpg, arg, 0, locp);
253 add_arg (engine_gpg_t gpg, const char *arg)
255 return add_arg_ext (gpg, arg, 0);
260 add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
262 struct arg_and_data_s *a;
267 a = malloc (sizeof *a - 1);
269 return gpg_error_from_errno (errno);
272 a->inbound = inbound;
286 gpg->argtail = &a->next;
292 gpg_get_version (const char *file_name)
294 return _gpgme_get_program_version (file_name ? file_name
295 : _gpgme_get_gpg_path ());
300 gpg_get_req_version (void)
302 return NEED_GPG_VERSION;
307 free_argv (char **argv)
311 for (i = 0; argv[i]; i++)
318 free_fd_data_map (struct fd_data_map_s *fd_data_map)
325 for (i = 0; fd_data_map[i].data; i++)
327 if (fd_data_map[i].fd != -1)
328 _gpgme_io_close (fd_data_map[i].fd);
329 if (fd_data_map[i].peer_fd != -1)
330 _gpgme_io_close (fd_data_map[i].peer_fd);
331 /* Don't release data because this is only a reference. */
338 gpg_cancel (void *engine)
340 engine_gpg_t gpg = engine;
343 return gpg_error (GPG_ERR_INV_VALUE);
345 /* If gpg may be waiting for a cmd, close the cmd fd first. On
346 Windows, close operations block on the reader/writer thread. */
349 if (gpg->cmd.fd != -1)
350 _gpgme_io_close (gpg->cmd.fd);
351 else if (gpg->fd_data_map
352 && gpg->fd_data_map[gpg->cmd.idx].fd != -1)
353 _gpgme_io_close (gpg->fd_data_map[gpg->cmd.idx].fd);
356 if (gpg->status.fd[0] != -1)
357 _gpgme_io_close (gpg->status.fd[0]);
358 if (gpg->status.fd[1] != -1)
359 _gpgme_io_close (gpg->status.fd[1]);
360 if (gpg->colon.fd[0] != -1)
361 _gpgme_io_close (gpg->colon.fd[0]);
362 if (gpg->colon.fd[1] != -1)
363 _gpgme_io_close (gpg->colon.fd[1]);
364 if (gpg->fd_data_map)
366 free_fd_data_map (gpg->fd_data_map);
367 gpg->fd_data_map = NULL;
374 gpg_release (void *engine)
376 engine_gpg_t gpg = engine;
384 free (gpg->file_name);
386 if (gpg->lc_messages)
387 free (gpg->lc_messages);
389 free (gpg->lc_ctype);
393 struct arg_and_data_s *next = gpg->arglist->next;
400 if (gpg->status.buffer)
401 free (gpg->status.buffer);
402 if (gpg->colon.buffer)
403 free (gpg->colon.buffer);
405 free_argv (gpg->argv);
406 if (gpg->cmd.keyword)
407 free (gpg->cmd.keyword);
414 gpg_new (void **engine, const char *file_name, const char *home_dir)
417 gpgme_error_t rc = 0;
418 char *dft_display = NULL;
419 char dft_ttyname[64];
420 char *dft_ttytype = NULL;
422 gpg = calloc (1, sizeof *gpg);
424 return gpg_error_from_errno (errno);
428 gpg->file_name = strdup (file_name);
431 rc = gpg_error_from_errno (errno);
436 gpg->argtail = &gpg->arglist;
437 gpg->status.fd[0] = -1;
438 gpg->status.fd[1] = -1;
439 gpg->colon.fd[0] = -1;
440 gpg->colon.fd[1] = -1;
443 gpg->cmd.linked_data = NULL;
444 gpg->cmd.linked_idx = -1;
446 /* Allocate the read buffer for the status pipe. */
447 gpg->status.bufsize = 1024;
448 gpg->status.readpos = 0;
449 gpg->status.buffer = malloc (gpg->status.bufsize);
450 if (!gpg->status.buffer)
452 rc = gpg_error_from_errno (errno);
455 /* In any case we need a status pipe - create it right here and
456 don't handle it with our generic gpgme_data_t mechanism. */
457 if (_gpgme_io_pipe (gpg->status.fd, 1) == -1)
459 rc = gpg_error_from_errno (errno);
462 if (_gpgme_io_set_close_notify (gpg->status.fd[0],
463 close_notify_handler, gpg)
464 || _gpgme_io_set_close_notify (gpg->status.fd[1],
465 close_notify_handler, gpg))
467 rc = gpg_error (GPG_ERR_GENERAL);
474 rc = add_arg (gpg, "--homedir");
476 rc = add_arg (gpg, home_dir);
481 rc = add_arg (gpg, "--status-fd");
487 _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]);
488 rc = add_arg_with_locp (gpg, buf, &gpg->status.arg_loc);
493 rc = add_arg (gpg, "--no-tty");
495 rc = add_arg (gpg, "--charset");
497 rc = add_arg (gpg, "utf8");
499 rc = add_arg (gpg, "--enable-progress-filter");
503 rc = _gpgme_getenv ("DISPLAY", &dft_display);
508 rc = add_arg (gpg, "--display");
510 rc = add_arg (gpg, dft_display);
519 err = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
521 rc = gpg_error_from_errno (err);
526 rc = add_arg (gpg, "--ttyname");
528 rc = add_arg (gpg, dft_ttyname);
534 rc = _gpgme_getenv ("TERM", &dft_ttytype);
540 rc = add_arg (gpg, "--ttytype");
542 rc = add_arg (gpg, dft_ttytype);
562 gpg_set_locale (void *engine, int category, const char *value)
564 engine_gpg_t gpg = engine;
566 if (category == LC_CTYPE)
570 free (gpg->lc_ctype);
571 gpg->lc_ctype = NULL;
575 gpg->lc_ctype = strdup (value);
577 return gpg_error_from_syserror ();
581 else if (category == LC_MESSAGES)
583 if (gpg->lc_messages)
585 free (gpg->lc_messages);
586 gpg->lc_messages = NULL;
590 gpg->lc_messages = strdup (value);
591 if (!gpg->lc_messages)
592 return gpg_error_from_syserror ();
595 #endif /* LC_MESSAGES */
597 return gpg_error (GPG_ERR_INV_VALUE);
603 /* Note, that the status_handler is allowed to modifiy the args
606 gpg_set_status_handler (void *engine, engine_status_handler_t fnc,
609 engine_gpg_t gpg = engine;
611 gpg->status.fnc = fnc;
612 gpg->status.fnc_value = fnc_value;
615 /* Kludge to process --with-colon output. */
617 gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
620 engine_gpg_t gpg = engine;
622 gpg->colon.bufsize = 1024;
623 gpg->colon.readpos = 0;
624 gpg->colon.buffer = malloc (gpg->colon.bufsize);
625 if (!gpg->colon.buffer)
626 return gpg_error_from_errno (errno);
628 if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1)
630 int saved_errno = errno;
631 free (gpg->colon.buffer);
632 gpg->colon.buffer = NULL;
633 return gpg_error_from_errno (saved_errno);
635 if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg)
636 || _gpgme_io_set_close_notify (gpg->colon.fd[1],
637 close_notify_handler, gpg))
638 return gpg_error (GPG_ERR_GENERAL);
640 gpg->colon.fnc = fnc;
641 gpg->colon.fnc_value = fnc_value;
647 command_handler (void *opaque, int fd)
650 engine_gpg_t gpg = (engine_gpg_t) opaque;
653 assert (gpg->cmd.used);
654 assert (gpg->cmd.code);
655 assert (gpg->cmd.fnc);
657 err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd,
661 /* And sleep again until read_status will wake us up again. */
662 /* XXX We must check if there are any more fds active after removing
664 (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag);
665 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
666 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
671 /* We always need to send at least a newline character. */
673 _gpgme_io_write (fd, "\n", 1);
680 /* The Fnc will be called to get a value for one of the commands with
681 a key KEY. If the Code passed to FNC is 0, the function may release
682 resources associated with the returned value from another call. To
683 match such a second call to a first call, the returned value from
684 the first call is passed as keyword. */
686 gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
687 void *fnc_value, gpgme_data_t linked_data)
689 engine_gpg_t gpg = engine;
692 rc = add_arg (gpg, "--command-fd");
696 /* This is a hack. We don't have a real data object. The only
697 thing that matters is that we use something unique, so we use the
698 address of the cmd structure in the gpg object. */
699 rc = add_data (gpg, (void *) &gpg->cmd, -2, 0);
704 gpg->cmd.cb_data = (void *) &gpg->cmd;
705 gpg->cmd.fnc_value = fnc_value;
706 gpg->cmd.linked_data = linked_data;
713 build_argv (engine_gpg_t gpg)
716 struct arg_and_data_s *a;
717 struct fd_data_map_s *fd_data_map;
718 size_t datac=0, argc=0;
720 int need_special = 0;
724 /* We don't want to use the agent with a malformed environment
725 variable. This is only a very basic test but sufficient to make
726 our life in the regression tests easier. */
727 err = _gpgme_getenv ("GPG_AGENT_INFO", &p);
730 use_agent = (p && strchr (p, ':'));
736 free_argv (gpg->argv);
739 if (gpg->fd_data_map)
741 free_fd_data_map (gpg->fd_data_map);
742 gpg->fd_data_map = NULL;
745 argc++; /* For argv[0]. */
746 for (a = gpg->arglist; a; a = a->next)
751 /*fprintf (stderr, "build_argv: data\n" );*/
753 if (a->dup_to == -1 && !a->print_fd)
758 /* fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
766 argc++; /* --batch */
767 argc += 1; /* --no-sk-comment */
769 argv = calloc (argc + 1, sizeof *argv);
771 return gpg_error_from_errno (errno);
772 fd_data_map = calloc (datac + 1, sizeof *fd_data_map);
775 int saved_errno = errno;
777 return gpg_error_from_errno (saved_errno);
781 argv[argc] = strdup ("gpg"); /* argv[0] */
784 int saved_errno = errno;
787 return gpg_error_from_errno (saved_errno);
792 argv[argc] = strdup ("--enable-special-filenames");
795 int saved_errno = errno;
798 return gpg_error_from_errno (saved_errno);
804 argv[argc] = strdup ("--use-agent");
807 int saved_errno = errno;
810 return gpg_error_from_errno (saved_errno);
816 argv[argc] = strdup ("--batch");
819 int saved_errno = errno;
822 return gpg_error_from_errno (saved_errno);
826 argv[argc] = strdup ("--no-sk-comment");
829 int saved_errno = errno;
832 return gpg_error_from_errno (saved_errno);
835 for (a = gpg->arglist; a; a = a->next)
838 *(a->arg_locp) = argc;
842 /* Create a pipe to pass it down to gpg. */
843 fd_data_map[datac].inbound = a->inbound;
849 if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0)
852 int saved_errno = errno;
855 return gpg_error (saved_errno);
857 if (_gpgme_io_set_close_notify (fds[0],
858 close_notify_handler, gpg)
859 || _gpgme_io_set_close_notify (fds[1],
860 close_notify_handler,
863 return gpg_error (GPG_ERR_GENERAL);
865 /* If the data_type is FD, we have to do a dup2 here. */
866 if (fd_data_map[datac].inbound)
868 fd_data_map[datac].fd = fds[0];
869 fd_data_map[datac].peer_fd = fds[1];
873 fd_data_map[datac].fd = fds[1];
874 fd_data_map[datac].peer_fd = fds[0];
878 /* Hack to get hands on the fd later. */
881 if (gpg->cmd.cb_data == a->data)
883 assert (gpg->cmd.idx == -1);
884 gpg->cmd.idx = datac;
886 else if (gpg->cmd.linked_data == a->data)
888 assert (gpg->cmd.linked_idx == -1);
889 gpg->cmd.linked_idx = datac;
893 fd_data_map[datac].data = a->data;
894 fd_data_map[datac].dup_to = a->dup_to;
901 argv[argc] = malloc (buflen);
904 int saved_errno = errno;
907 return gpg_error_from_errno (saved_errno);
918 _gpgme_io_fd2str (ptr, buflen, fd_data_map[datac].peer_fd);
919 fd_data_map[datac].arg_loc = argc;
926 argv[argc] = strdup (a->arg);
929 int saved_errno = errno;
932 return gpg_error_from_errno (saved_errno);
939 gpg->fd_data_map = fd_data_map;
945 add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
950 err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
954 /* FIXME Kludge around poll() problem. */
955 err = _gpgme_io_set_nonblocking (fd);
961 status_cmp (const void *ap, const void *bp)
963 const struct status_table_s *a = ap;
964 const struct status_table_s *b = bp;
966 return strcmp (a->name, b->name);
970 /* Handle the status output of GnuPG. This function does read entire
971 lines and passes them as C strings to the callback function (we can
972 use C Strings because the status output is always UTF-8 encoded).
973 Of course we have to buffer the lines to cope with long lines
974 e.g. with a large user ID. Note: We can optimize this to only cope
975 with status line code we know about and skip all other stuff
976 without buffering (i.e. without extending the buffer). */
978 read_status (engine_gpg_t gpg)
982 size_t bufsize = gpg->status.bufsize;
983 char *buffer = gpg->status.buffer;
984 size_t readpos = gpg->status.readpos;
987 if (bufsize - readpos < 256)
989 /* Need more room for the read. */
991 buffer = realloc (buffer, bufsize);
993 return gpg_error_from_errno (errno);
996 nread = _gpgme_io_read (gpg->status.fd[0],
997 buffer + readpos, bufsize-readpos);
999 return gpg_error_from_errno (errno);
1003 gpg->status.eof = 1;
1004 if (gpg->status.fnc)
1007 err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, "");
1016 for (p = buffer + readpos; nread; nread--, p++)
1020 /* (we require that the last line is terminated by a LF) */
1021 if (p > buffer && p[-1] == '\r')
1024 if (!strncmp (buffer, "[GNUPG:] ", 9)
1025 && buffer[9] >= 'A' && buffer[9] <= 'Z')
1027 struct status_table_s t, *r;
1030 rest = strchr (buffer + 9, ' ');
1032 rest = p; /* Set to an empty string. */
1037 /* (the status table has one extra element) */
1038 r = bsearch (&t, status_table, DIM(status_table) - 1,
1039 sizeof t, status_cmp);
1043 && (r->code == GPGME_STATUS_GET_BOOL
1044 || r->code == GPGME_STATUS_GET_LINE
1045 || r->code == GPGME_STATUS_GET_HIDDEN))
1047 gpg->cmd.code = r->code;
1048 if (gpg->cmd.keyword)
1049 free (gpg->cmd.keyword);
1050 gpg->cmd.keyword = strdup (rest);
1051 if (!gpg->cmd.keyword)
1052 return gpg_error_from_errno (errno);
1053 /* This should be the last thing we have
1054 received and the next thing will be that
1055 the command handler does its action. */
1057 TRACE0 (DEBUG_CTX, "gpgme:read_status", 0,
1058 "error: unexpected data");
1060 add_io_cb (gpg, gpg->cmd.fd, 0,
1061 command_handler, gpg,
1062 &gpg->fd_data_map[gpg->cmd.idx].tag);
1063 gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd;
1066 else if (gpg->status.fnc)
1069 err = gpg->status.fnc (gpg->status.fnc_value,
1075 if (r->code == GPGME_STATUS_END_STREAM)
1079 /* Before we can actually add the
1080 command fd, we might have to flush
1081 the linked output data pipe. */
1082 if (gpg->cmd.linked_idx != -1
1083 && gpg->fd_data_map[gpg->cmd.linked_idx].fd
1086 struct io_select_fd_s fds;
1088 gpg->fd_data_map[gpg->cmd.linked_idx].fd;
1095 _gpgme_io_select (&fds, 1, 1);
1097 _gpgme_data_inbound_handler
1098 (gpg->cmd.linked_data, fds.fd);
1100 while (fds.signaled);
1103 /* XXX We must check if there are any
1104 more fds active after removing this
1106 (*gpg->io_cbs.remove)
1107 (gpg->fd_data_map[gpg->cmd.idx].tag);
1108 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
1109 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
1114 /* To reuse the buffer for the next line we have to
1115 shift the remaining data to the buffer start and
1116 restart the loop Hmmm: We can optimize this function
1117 by looking forward in the buffer to see whether a
1118 second complete line is available and in this case
1119 avoid the memmove for this line. */
1122 memmove (buffer, p, nread);
1124 break; /* the for loop */
1131 /* Update the gpg object. */
1132 gpg->status.bufsize = bufsize;
1133 gpg->status.buffer = buffer;
1134 gpg->status.readpos = readpos;
1139 static gpgme_error_t
1140 status_handler (void *opaque, int fd)
1142 engine_gpg_t gpg = opaque;
1145 assert (fd == gpg->status.fd[0]);
1146 err = read_status (gpg);
1149 if (gpg->status.eof)
1150 _gpgme_io_close (fd);
1155 static gpgme_error_t
1156 read_colon_line (engine_gpg_t gpg)
1160 size_t bufsize = gpg->colon.bufsize;
1161 char *buffer = gpg->colon.buffer;
1162 size_t readpos = gpg->colon.readpos;
1165 if (bufsize - readpos < 256)
1167 /* Need more room for the read. */
1169 buffer = realloc (buffer, bufsize);
1171 return gpg_error_from_errno (errno);
1174 nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos);
1176 return gpg_error_from_errno (errno);
1181 assert (gpg->colon.fnc);
1182 gpg->colon.fnc (gpg->colon.fnc_value, NULL);
1188 for (p = buffer + readpos; nread; nread--, p++)
1192 /* (we require that the last line is terminated by a LF)
1193 and we skip empty lines. Note: we use UTF8 encoding
1194 and escaping of special characters. We require at
1195 least one colon to cope with some other printed
1198 if (*buffer && strchr (buffer, ':'))
1202 if (gpg->colon.preprocess_fnc)
1206 err = gpg->colon.preprocess_fnc (buffer, &line);
1211 assert (gpg->colon.fnc);
1212 gpg->colon.fnc (gpg->colon.fnc_value, line ? line : buffer);
1217 /* To reuse the buffer for the next line we have to
1218 shift the remaining data to the buffer start and
1219 restart the loop Hmmm: We can optimize this function
1220 by looking forward in the buffer to see whether a
1221 second complete line is available and in this case
1222 avoid the memmove for this line. */
1225 memmove (buffer, p, nread);
1227 break; /* The for loop. */
1234 /* Update the gpg object. */
1235 gpg->colon.bufsize = bufsize;
1236 gpg->colon.buffer = buffer;
1237 gpg->colon.readpos = readpos;
1242 /* This colonline handler thing is not the clean way to do it. It
1243 might be better to enhance the gpgme_data_t object to act as a wrapper
1244 for a callback. Same goes for the status thing. For now we use
1245 this thing here because it is easier to implement. */
1246 static gpgme_error_t
1247 colon_line_handler (void *opaque, int fd)
1249 engine_gpg_t gpg = opaque;
1250 gpgme_error_t rc = 0;
1252 assert (fd == gpg->colon.fd[0]);
1253 rc = read_colon_line (gpg);
1257 _gpgme_io_close (fd);
1262 static gpgme_error_t
1263 start (engine_gpg_t gpg)
1269 struct spawn_fd_item_s *fd_list;
1273 return gpg_error (GPG_ERR_INV_VALUE);
1275 if (!gpg->file_name && !_gpgme_get_gpg_path ())
1276 return gpg_error (GPG_ERR_INV_ENGINE);
1280 rc = add_arg_ext (gpg, gpg->lc_ctype, 1);
1282 rc = add_arg_ext (gpg, "--lc-ctype", 1);
1287 if (gpg->lc_messages)
1289 rc = add_arg_ext (gpg, gpg->lc_messages, 1);
1291 rc = add_arg_ext (gpg, "--lc-messages", 1);
1296 rc = build_argv (gpg);
1300 /* status_fd, colon_fd and end of list. */
1302 for (i = 0; gpg->fd_data_map[i].data; i++)
1304 fd_list = calloc (n, sizeof *fd_list);
1306 return gpg_error_from_errno (errno);
1308 /* Build the fd list for the child. */
1310 fd_list[n].fd = gpg->status.fd[1];
1311 fd_list[n].dup_to = -1;
1312 fd_list[n].arg_loc = gpg->status.arg_loc;
1316 fd_list[n].fd = gpg->colon.fd[1];
1317 fd_list[n].dup_to = 1;
1320 for (i = 0; gpg->fd_data_map[i].data; i++)
1322 fd_list[n].fd = gpg->fd_data_map[i].peer_fd;
1323 fd_list[n].dup_to = gpg->fd_data_map[i].dup_to;
1324 fd_list[n].arg_loc = gpg->fd_data_map[i].arg_loc;
1328 fd_list[n].dup_to = -1;
1330 status = _gpgme_io_spawn (gpg->file_name ? gpg->file_name :
1331 _gpgme_get_gpg_path (), gpg->argv,
1332 IOSPAWN_FLAG_ALLOW_SET_FG,
1334 saved_errno = errno;
1338 return gpg_error_from_errno (saved_errno);
1340 /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
1342 rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg,
1345 /* FIXME: kill the child */
1350 assert (gpg->colon.fd[0] != -1);
1351 rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg,
1354 /* FIXME: kill the child */
1358 for (i = 0; gpg->fd_data_map[i].data; i++)
1360 if (gpg->cmd.used && i == gpg->cmd.idx)
1362 /* Park the cmd fd. */
1363 gpg->cmd.fd = gpg->fd_data_map[i].fd;
1364 gpg->fd_data_map[i].fd = -1;
1368 rc = add_io_cb (gpg, gpg->fd_data_map[i].fd,
1369 gpg->fd_data_map[i].inbound,
1370 gpg->fd_data_map[i].inbound
1371 ? _gpgme_data_inbound_handler
1372 : _gpgme_data_outbound_handler,
1373 gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag);
1376 /* FIXME: kill the child */
1381 gpg_io_event (gpg, GPGME_EVENT_START, NULL);
1383 /* fixme: check what data we can release here */
1388 static gpgme_error_t
1389 gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
1391 engine_gpg_t gpg = engine;
1394 err = add_arg (gpg, "--decrypt");
1396 /* Tell the gpg object about the data. */
1398 err = add_arg (gpg, "--output");
1400 err = add_arg (gpg, "-");
1402 err = add_data (gpg, plain, 1, 1);
1404 err = add_arg (gpg, "--");
1406 err = add_data (gpg, ciph, -1, 0);
1413 static gpgme_error_t
1414 gpg_delete (void *engine, gpgme_key_t key, int allow_secret)
1416 engine_gpg_t gpg = engine;
1419 err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key"
1422 err = add_arg (gpg, "--");
1425 if (!key->subkeys || !key->subkeys->fpr)
1426 return gpg_error (GPG_ERR_INV_VALUE);
1428 err = add_arg (gpg, key->subkeys->fpr);
1437 static gpgme_error_t
1438 append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1440 gpgme_error_t err = 0;
1444 for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
1446 const char *s = key->subkeys ? key->subkeys->keyid : NULL;
1450 err = add_arg (gpg, "-u");
1452 err = add_arg (gpg, s);
1454 gpgme_key_unref (key);
1461 static gpgme_error_t
1462 append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1464 gpgme_error_t err = 0;
1465 gpgme_sig_notation_t notation;
1467 notation = gpgme_sig_notation_get (ctx);
1469 while (!err && notation)
1472 && !(notation->flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
1473 err = gpg_error (GPG_ERR_INV_VALUE);
1474 else if (notation->name)
1478 /* Maximum space needed is one byte for the "critical" flag,
1479 the name, one byte for '=', the value, and a terminating
1482 arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1);
1484 err = gpg_error_from_errno (errno);
1490 if (notation->critical)
1493 memcpy (argp, notation->name, notation->name_len);
1494 argp += notation->name_len;
1498 /* We know that notation->name is '\0' terminated. */
1499 strcpy (argp, notation->value);
1503 err = add_arg (gpg, "--sig-notation");
1505 err = add_arg (gpg, arg);
1512 /* This is a policy URL. */
1516 if (notation->critical)
1518 value = malloc (1 + notation->value_len + 1);
1520 err = gpg_error_from_errno (errno);
1524 /* We know that notation->value is '\0' terminated. */
1525 strcpy (&value[1], notation->value);
1529 value = notation->value;
1532 err = add_arg (gpg, "--sig-policy-url");
1534 err = add_arg (gpg, value);
1536 if (value != notation->value)
1540 notation = notation->next;
1546 static gpgme_error_t
1547 gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
1548 gpgme_ctx_t ctx /* FIXME */)
1550 engine_gpg_t gpg = engine;
1553 err = add_arg (gpg, "--with-colons");
1555 err = append_args_from_signers (gpg, ctx);
1557 err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
1559 err = add_data (gpg, out, 1, 1);
1561 err = add_arg (gpg, "--");
1562 if (!err && type == 0)
1564 const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1566 err = gpg_error (GPG_ERR_INV_VALUE);
1568 err = add_arg (gpg, s);
1577 static gpgme_error_t
1578 append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
1580 gpgme_error_t err = 0;
1585 if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
1586 err = gpg_error (GPG_ERR_INV_VALUE);
1588 err = add_arg (gpg, "-r");
1590 err = add_arg (gpg, recp[i]->subkeys->fpr);
1599 static gpgme_error_t
1600 gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
1601 gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
1603 engine_gpg_t gpg = engine;
1605 int symmetric = !recp;
1607 err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt");
1609 if (!err && use_armor)
1610 err = add_arg (gpg, "--armor");
1614 /* If we know that all recipients are valid (full or ultimate trust)
1615 we can suppress further checks. */
1616 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1617 err = add_arg (gpg, "--always-trust");
1619 if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
1620 err = add_arg (gpg, "--no-encrypt-to");
1623 err = append_args_from_recipients (gpg, recp);
1626 /* Tell the gpg object about the data. */
1628 err = add_arg (gpg, "--output");
1630 err = add_arg (gpg, "-");
1632 err = add_data (gpg, ciph, 1, 1);
1633 if (gpgme_data_get_file_name (plain))
1636 err = add_arg (gpg, "--set-filename");
1638 err = add_arg (gpg, gpgme_data_get_file_name (plain));
1641 err = add_arg (gpg, "--");
1643 err = add_data (gpg, plain, -1, 0);
1652 static gpgme_error_t
1653 gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
1654 gpgme_encrypt_flags_t flags, gpgme_data_t plain,
1655 gpgme_data_t ciph, int use_armor,
1656 gpgme_ctx_t ctx /* FIXME */)
1658 engine_gpg_t gpg = engine;
1661 err = add_arg (gpg, "--encrypt");
1663 err = add_arg (gpg, "--sign");
1664 if (!err && use_armor)
1665 err = add_arg (gpg, "--armor");
1667 /* If we know that all recipients are valid (full or ultimate trust)
1668 we can suppress further checks. */
1669 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1670 err = add_arg (gpg, "--always-trust");
1673 err = append_args_from_recipients (gpg, recp);
1676 err = append_args_from_signers (gpg, ctx);
1678 err = append_args_from_sig_notations (gpg, ctx);
1680 /* Tell the gpg object about the data. */
1682 err = add_arg (gpg, "--output");
1684 err = add_arg (gpg, "-");
1686 err = add_data (gpg, ciph, 1, 1);
1687 if (gpgme_data_get_file_name (plain))
1690 err = add_arg (gpg, "--set-filename");
1692 err = add_arg (gpg, gpgme_data_get_file_name (plain));
1695 err = add_arg (gpg, "--");
1697 err = add_data (gpg, plain, -1, 0);
1706 static gpgme_error_t
1707 export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
1708 gpgme_data_t keydata, int use_armor)
1712 if ((mode & ~GPGME_EXPORT_MODE_EXTERN))
1713 return gpg_error (GPG_ERR_NOT_SUPPORTED);
1715 if ((mode & GPGME_EXPORT_MODE_EXTERN))
1717 err = add_arg (gpg, "--send-keys");
1721 err = add_arg (gpg, "--export");
1722 if (!err && use_armor)
1723 err = add_arg (gpg, "--armor");
1725 err = add_data (gpg, keydata, 1, 1);
1728 err = add_arg (gpg, "--");
1734 static gpgme_error_t
1735 gpg_export (void *engine, const char *pattern, gpgme_export_mode_t mode,
1736 gpgme_data_t keydata, int use_armor)
1738 engine_gpg_t gpg = engine;
1741 err = export_common (gpg, mode, keydata, use_armor);
1743 if (!err && pattern && *pattern)
1744 err = add_arg (gpg, pattern);
1753 static gpgme_error_t
1754 gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
1755 gpgme_data_t keydata, int use_armor)
1757 engine_gpg_t gpg = engine;
1760 err = export_common (gpg, mode, keydata, use_armor);
1764 while (!err && *pattern && **pattern)
1765 err = add_arg (gpg, *(pattern++));
1775 static gpgme_error_t
1776 gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,
1777 gpgme_data_t pubkey, gpgme_data_t seckey)
1779 engine_gpg_t gpg = engine;
1783 return gpg_error (GPG_ERR_INV_VALUE);
1785 /* We need a special mechanism to get the fd of a pipe here, so that
1786 we can use this for the %pubring and %secring parameters. We
1787 don't have this yet, so we implement only the adding to the
1788 standard keyrings. */
1789 if (pubkey || seckey)
1790 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1792 err = add_arg (gpg, "--gen-key");
1793 if (!err && use_armor)
1794 err = add_arg (gpg, "--armor");
1796 err = add_arg (gpg, "--");
1798 err = add_data (gpg, help_data, -1, 0);
1807 static gpgme_error_t
1808 gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
1810 engine_gpg_t gpg = engine;
1814 if (keydata && keyarray)
1815 gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */
1819 err = add_arg (gpg, "--recv-keys");
1821 err = add_arg (gpg, "--");
1822 for (idx=0; !err && keyarray[idx]; idx++)
1824 if (keyarray[idx]->protocol != GPGME_PROTOCOL_OpenPGP)
1826 else if (!keyarray[idx]->subkeys)
1828 else if (keyarray[idx]->subkeys->fpr && *keyarray[idx]->subkeys->fpr)
1829 err = add_arg (gpg, keyarray[idx]->subkeys->fpr);
1830 else if (*keyarray[idx]->subkeys->keyid)
1831 err = add_arg (gpg, keyarray[idx]->subkeys->keyid);
1836 err = add_arg (gpg, "--import");
1838 err = add_arg (gpg, "--");
1840 err = add_data (gpg, keydata, -1, 0);
1850 /* The output for external keylistings in GnuPG is different from all
1851 the other key listings. We catch this here with a special
1852 preprocessor that reformats the colon handler lines. */
1853 static gpgme_error_t
1854 gpg_keylist_preprocess (char *line, char **r_line)
1858 RT_NONE, RT_INFO, RT_PUB, RT_UID
1861 #define NR_FIELDS 16
1862 char *field[NR_FIELDS];
1867 while (line && fields < NR_FIELDS)
1869 field[fields++] = line;
1870 line = strchr (line, ':');
1875 if (!strcmp (field[0], "info"))
1877 else if (!strcmp (field[0], "pub"))
1879 else if (!strcmp (field[0], "uid"))
1887 /* FIXME: Eventually, check the version number at least. */
1896 pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>
1898 as defined in 5.2. Machine Readable Indexes of the OpenPGP
1899 HTTP Keyserver Protocol (draft).
1902 pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>::::::::
1905 if (asprintf (r_line, "pub:o%s:%s:%s:%s:%s:%s::::::::",
1906 field[6], field[3], field[2], field[1],
1907 field[4], field[5]) < 0)
1908 return gpg_error_from_errno (errno);
1914 uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags>
1916 as defined in 5.2. Machine Readable Indexes of the OpenPGP
1917 HTTP Keyserver Protocol (draft).
1920 uid:o<flags>::::<creatdate>:<expdate>:::<c-coded uid>:
1924 /* The user ID is percent escaped, but we want c-coded.
1925 Because we have to replace each '%HL' by '\xHL', we need at
1926 most 4/3 th the number of bytes. But because we also need
1927 to escape the backslashes we allocate twice as much. */
1928 char *uid = malloc (2 * strlen (field[1]) + 1);
1933 return gpg_error_from_errno (errno);
1943 /* Copy the next two bytes unconditionally. */
1945 *(dst++) = *(src++);
1947 *(dst++) = *(src++);
1949 else if (*src == '\\')
1955 *(dst++) = *(src++);
1959 if (asprintf (r_line, "uid:o%s::::%s:%s:::%s:",
1960 field[4], field[2], field[3], uid) < 0)
1961 return gpg_error_from_errno (errno);
1966 /* Unknown record. */
1975 gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
1976 gpgme_keylist_mode_t mode)
1980 err = add_arg (gpg, "--with-colons");
1982 err = add_arg (gpg, "--fixed-list-mode");
1984 err = add_arg (gpg, "--with-fingerprint");
1986 err = add_arg (gpg, "--with-fingerprint");
1988 && (mode & GPGME_KEYLIST_MODE_SIGS)
1989 && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
1991 err = add_arg (gpg, "--list-options");
1993 err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
1997 if ( (mode & GPGME_KEYLIST_MODE_EXTERN) )
2000 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2001 else if ( (mode & GPGME_KEYLIST_MODE_LOCAL))
2003 /* The local+extern mode is special. It works only with
2004 gpg >= 2.0.10. FIXME: We should check that we have
2005 such a version to that we can return a proper error
2006 code. The problem is that we don't know the context
2007 here and thus can't accesses the cached version
2008 number for the engine info structure. */
2009 err = add_arg (gpg, "--locate-keys");
2010 if ((mode & GPGME_KEYLIST_MODE_SIGS))
2011 err = add_arg (gpg, "--with-sig-check");
2015 err = add_arg (gpg, "--search-keys");
2016 gpg->colon.preprocess_fnc = gpg_keylist_preprocess;
2021 err = add_arg (gpg, secret_only ? "--list-secret-keys"
2022 : ((mode & GPGME_KEYLIST_MODE_SIGS)
2023 ? "--check-sigs" : "--list-keys"));
2027 err = add_arg (gpg, "--");
2033 static gpgme_error_t
2034 gpg_keylist (void *engine, const char *pattern, int secret_only,
2035 gpgme_keylist_mode_t mode)
2037 engine_gpg_t gpg = engine;
2040 err = gpg_keylist_build_options (gpg, secret_only, mode);
2042 if (!err && pattern && *pattern)
2043 err = add_arg (gpg, pattern);
2052 static gpgme_error_t
2053 gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
2054 int reserved, gpgme_keylist_mode_t mode)
2056 engine_gpg_t gpg = engine;
2060 return gpg_error (GPG_ERR_INV_VALUE);
2062 err = gpg_keylist_build_options (gpg, secret_only, mode);
2066 while (!err && *pattern && **pattern)
2067 err = add_arg (gpg, *(pattern++));
2077 static gpgme_error_t
2078 gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
2079 gpgme_sig_mode_t mode, int use_armor, int use_textmode,
2080 int include_certs, gpgme_ctx_t ctx /* FIXME */)
2082 engine_gpg_t gpg = engine;
2085 if (mode == GPGME_SIG_MODE_CLEAR)
2086 err = add_arg (gpg, "--clearsign");
2089 err = add_arg (gpg, "--sign");
2090 if (!err && mode == GPGME_SIG_MODE_DETACH)
2091 err = add_arg (gpg, "--detach");
2092 if (!err && use_armor)
2093 err = add_arg (gpg, "--armor");
2094 if (!err && use_textmode)
2095 err = add_arg (gpg, "--textmode");
2099 err = append_args_from_signers (gpg, ctx);
2101 err = append_args_from_sig_notations (gpg, ctx);
2103 if (gpgme_data_get_file_name (in))
2106 err = add_arg (gpg, "--set-filename");
2108 err = add_arg (gpg, gpgme_data_get_file_name (in));
2111 /* Tell the gpg object about the data. */
2113 err = add_arg (gpg, "--");
2115 err = add_data (gpg, in, -1, 0);
2117 err = add_data (gpg, out, 1, 1);
2125 static gpgme_error_t
2126 gpg_trustlist (void *engine, const char *pattern)
2128 engine_gpg_t gpg = engine;
2131 err = add_arg (gpg, "--with-colons");
2133 err = add_arg (gpg, "--list-trust-path");
2135 /* Tell the gpg object about the data. */
2137 err = add_arg (gpg, "--");
2139 err = add_arg (gpg, pattern);
2148 static gpgme_error_t
2149 gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
2150 gpgme_data_t plaintext)
2152 engine_gpg_t gpg = engine;
2153 gpgme_error_t err = 0;
2157 /* Normal or cleartext signature. */
2159 err = add_arg (gpg, "--output");
2161 err = add_arg (gpg, "-");
2163 err = add_arg (gpg, "--");
2165 err = add_data (gpg, sig, -1, 0);
2167 err = add_data (gpg, plaintext, 1, 1);
2171 err = add_arg (gpg, "--verify");
2173 err = add_arg (gpg, "--");
2175 err = add_data (gpg, sig, -1, 0);
2176 if (!err && signed_text)
2177 err = add_data (gpg, signed_text, -1, 0);
2188 gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
2190 engine_gpg_t gpg = engine;
2192 gpg->io_cbs = *io_cbs;
2196 struct engine_ops _gpgme_engine_ops_gpg =
2198 /* Static functions. */
2199 _gpgme_get_gpg_path,
2202 gpg_get_req_version,
2205 /* Member functions. */
2208 gpg_set_status_handler,
2209 gpg_set_command_handler,
2210 gpg_set_colon_line_handler,
2226 NULL, /* getauditlog */
2227 NULL, /* opassuan_transact */
2228 NULL, /* conf_load */
2229 NULL, /* conf_save */