1 /* rungpg.c - Gpg Engine.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 g10 Code GmbH
5 This file is part of GPGME.
7 GPGME is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
12 GPGME is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
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->fd_data_map)
178 for (i = 0; gpg->fd_data_map[i].data; i++)
180 if (gpg->fd_data_map[i].fd == fd)
182 if (gpg->fd_data_map[i].tag)
183 (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
184 gpg->fd_data_map[i].fd = -1;
187 if (gpg->fd_data_map[i].peer_fd == fd)
189 gpg->fd_data_map[i].peer_fd = -1;
196 /* If FRONT is true, push at the front of the list. Use this for
197 options added late in the process. */
199 _add_arg (engine_gpg_t gpg, const char *arg, int front, int *arg_locp)
201 struct arg_and_data_s *a;
206 a = malloc (sizeof *a + strlen (arg));
208 return gpg_error_from_errno (errno);
212 a->arg_locp = arg_locp;
214 strcpy (a->arg, arg);
217 a->next = gpg->arglist;
220 /* If this is the first argument, we need to update the tail
222 gpg->argtail = &a->next;
230 gpg->argtail = &a->next;
237 add_arg_ext (engine_gpg_t gpg, const char *arg, int front)
239 return _add_arg (gpg, arg, front, NULL);
244 add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp)
246 return _add_arg (gpg, arg, 0, locp);
251 add_arg (engine_gpg_t gpg, const char *arg)
253 return add_arg_ext (gpg, arg, 0);
258 add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
260 struct arg_and_data_s *a;
265 a = malloc (sizeof *a - 1);
267 return gpg_error_from_errno (errno);
270 a->inbound = inbound;
284 gpg->argtail = &a->next;
290 gpg_get_version (const char *file_name)
292 return _gpgme_get_program_version (file_name ? file_name
293 : _gpgme_get_gpg_path ());
298 gpg_get_req_version (void)
300 return NEED_GPG_VERSION;
305 free_argv (char **argv)
309 for (i = 0; argv[i]; i++)
316 free_fd_data_map (struct fd_data_map_s *fd_data_map)
323 for (i = 0; fd_data_map[i].data; i++)
325 if (fd_data_map[i].fd != -1)
326 _gpgme_io_close (fd_data_map[i].fd);
327 if (fd_data_map[i].peer_fd != -1)
328 _gpgme_io_close (fd_data_map[i].peer_fd);
329 /* Don't release data because this is only a reference. */
336 gpg_cancel (void *engine)
338 engine_gpg_t gpg = engine;
341 return gpg_error (GPG_ERR_INV_VALUE);
343 /* If gpg may be waiting for a cmd, close the cmd fd first. On
344 Windows, close operations block on the reader/writer thread. */
347 if (gpg->cmd.fd != -1)
348 _gpgme_io_close (gpg->cmd.fd);
349 else if (gpg->fd_data_map
350 && gpg->fd_data_map[gpg->cmd.idx].fd != -1)
351 _gpgme_io_close (gpg->fd_data_map[gpg->cmd.idx].fd);
354 if (gpg->status.fd[0] != -1)
355 _gpgme_io_close (gpg->status.fd[0]);
356 if (gpg->status.fd[1] != -1)
357 _gpgme_io_close (gpg->status.fd[1]);
358 if (gpg->colon.fd[0] != -1)
359 _gpgme_io_close (gpg->colon.fd[0]);
360 if (gpg->colon.fd[1] != -1)
361 _gpgme_io_close (gpg->colon.fd[1]);
362 if (gpg->fd_data_map)
364 free_fd_data_map (gpg->fd_data_map);
365 gpg->fd_data_map = NULL;
372 gpg_release (void *engine)
374 engine_gpg_t gpg = engine;
382 free (gpg->file_name);
384 if (gpg->lc_messages)
385 free (gpg->lc_messages);
387 free (gpg->lc_ctype);
391 struct arg_and_data_s *next = gpg->arglist->next;
398 if (gpg->status.buffer)
399 free (gpg->status.buffer);
400 if (gpg->colon.buffer)
401 free (gpg->colon.buffer);
403 free_argv (gpg->argv);
404 if (gpg->cmd.keyword)
405 free (gpg->cmd.keyword);
412 gpg_new (void **engine, const char *file_name, const char *home_dir)
415 gpgme_error_t rc = 0;
416 char *dft_display = NULL;
417 char dft_ttyname[64];
418 char *dft_ttytype = NULL;
420 gpg = calloc (1, sizeof *gpg);
422 return gpg_error_from_errno (errno);
426 gpg->file_name = strdup (file_name);
429 rc = gpg_error_from_errno (errno);
434 gpg->argtail = &gpg->arglist;
435 gpg->status.fd[0] = -1;
436 gpg->status.fd[1] = -1;
437 gpg->colon.fd[0] = -1;
438 gpg->colon.fd[1] = -1;
441 gpg->cmd.linked_data = NULL;
442 gpg->cmd.linked_idx = -1;
444 /* Allocate the read buffer for the status pipe. */
445 gpg->status.bufsize = 1024;
446 gpg->status.readpos = 0;
447 gpg->status.buffer = malloc (gpg->status.bufsize);
448 if (!gpg->status.buffer)
450 rc = gpg_error_from_errno (errno);
453 /* In any case we need a status pipe - create it right here and
454 don't handle it with our generic gpgme_data_t mechanism. */
455 if (_gpgme_io_pipe (gpg->status.fd, 1) == -1)
457 rc = gpg_error_from_errno (errno);
460 if (_gpgme_io_set_close_notify (gpg->status.fd[0],
461 close_notify_handler, gpg)
462 || _gpgme_io_set_close_notify (gpg->status.fd[1],
463 close_notify_handler, gpg))
465 rc = gpg_error (GPG_ERR_GENERAL);
472 rc = add_arg (gpg, "--homedir");
474 rc = add_arg (gpg, home_dir);
479 rc = add_arg (gpg, "--status-fd");
485 _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]);
486 rc = add_arg_with_locp (gpg, buf, &gpg->status.arg_loc);
491 rc = add_arg (gpg, "--no-tty");
493 rc = add_arg (gpg, "--charset");
495 rc = add_arg (gpg, "utf8");
497 rc = add_arg (gpg, "--enable-progress-filter");
501 rc = _gpgme_getenv ("DISPLAY", &dft_display);
506 rc = add_arg (gpg, "--display");
508 rc = add_arg (gpg, dft_display);
517 err = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
519 rc = gpg_error_from_errno (err);
524 rc = add_arg (gpg, "--ttyname");
526 rc = add_arg (gpg, dft_ttyname);
532 rc = _gpgme_getenv ("TERM", &dft_ttytype);
538 rc = add_arg (gpg, "--ttytype");
540 rc = add_arg (gpg, dft_ttytype);
560 gpg_set_locale (void *engine, int category, const char *value)
562 engine_gpg_t gpg = engine;
564 if (category == LC_CTYPE)
568 free (gpg->lc_ctype);
569 gpg->lc_ctype = NULL;
573 gpg->lc_ctype = strdup (value);
575 return gpg_error_from_syserror ();
579 else if (category == LC_MESSAGES)
581 if (gpg->lc_messages)
583 free (gpg->lc_messages);
584 gpg->lc_messages = NULL;
588 gpg->lc_messages = strdup (value);
589 if (!gpg->lc_messages)
590 return gpg_error_from_syserror ();
593 #endif /* LC_MESSAGES */
595 return gpg_error (GPG_ERR_INV_VALUE);
601 /* Note, that the status_handler is allowed to modifiy the args
604 gpg_set_status_handler (void *engine, engine_status_handler_t fnc,
607 engine_gpg_t gpg = engine;
609 gpg->status.fnc = fnc;
610 gpg->status.fnc_value = fnc_value;
613 /* Kludge to process --with-colon output. */
615 gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
618 engine_gpg_t gpg = engine;
620 gpg->colon.bufsize = 1024;
621 gpg->colon.readpos = 0;
622 gpg->colon.buffer = malloc (gpg->colon.bufsize);
623 if (!gpg->colon.buffer)
624 return gpg_error_from_errno (errno);
626 if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1)
628 int saved_errno = errno;
629 free (gpg->colon.buffer);
630 gpg->colon.buffer = NULL;
631 return gpg_error_from_errno (saved_errno);
633 if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg)
634 || _gpgme_io_set_close_notify (gpg->colon.fd[1],
635 close_notify_handler, gpg))
636 return gpg_error (GPG_ERR_GENERAL);
638 gpg->colon.fnc = fnc;
639 gpg->colon.fnc_value = fnc_value;
645 command_handler (void *opaque, int fd)
648 engine_gpg_t gpg = (engine_gpg_t) opaque;
651 assert (gpg->cmd.used);
652 assert (gpg->cmd.code);
653 assert (gpg->cmd.fnc);
655 err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd,
659 /* And sleep again until read_status will wake us up again. */
660 /* XXX We must check if there are any more fds active after removing
662 (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag);
663 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
664 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
669 /* We always need to send at least a newline character. */
671 _gpgme_io_write (fd, "\n", 1);
678 /* The Fnc will be called to get a value for one of the commands with
679 a key KEY. If the Code pssed to FNC is 0, the function may release
680 resources associated with the returned value from another call. To
681 match such a second call to a first call, the returned value from
682 the first call is passed as keyword. */
684 gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
685 void *fnc_value, gpgme_data_t linked_data)
687 engine_gpg_t gpg = engine;
690 rc = add_arg (gpg, "--command-fd");
694 /* This is a hack. We don't have a real data object. The only
695 thing that matters is that we use something unique, so we use the
696 address of the cmd structure in the gpg object. */
697 rc = add_data (gpg, (void *) &gpg->cmd, -2, 0);
702 gpg->cmd.cb_data = (void *) &gpg->cmd;
703 gpg->cmd.fnc_value = fnc_value;
704 gpg->cmd.linked_data = linked_data;
711 build_argv (engine_gpg_t gpg)
714 struct arg_and_data_s *a;
715 struct fd_data_map_s *fd_data_map;
716 size_t datac=0, argc=0;
718 int need_special = 0;
722 /* We don't want to use the agent with a malformed environment
723 variable. This is only a very basic test but sufficient to make
724 our life in the regression tests easier. */
725 err = _gpgme_getenv ("GPG_AGENT_INFO", &p);
728 use_agent = (p && strchr (p, ':'));
734 free_argv (gpg->argv);
737 if (gpg->fd_data_map)
739 free_fd_data_map (gpg->fd_data_map);
740 gpg->fd_data_map = NULL;
743 argc++; /* For argv[0]. */
744 for (a = gpg->arglist; a; a = a->next)
749 /*fprintf (stderr, "build_argv: data\n" );*/
751 if (a->dup_to == -1 && !a->print_fd)
756 /* fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
764 argc++; /* --batch */
765 argc += 1; /* --no-sk-comment */
767 argv = calloc (argc + 1, sizeof *argv);
769 return gpg_error_from_errno (errno);
770 fd_data_map = calloc (datac + 1, sizeof *fd_data_map);
773 int saved_errno = errno;
775 return gpg_error_from_errno (saved_errno);
779 argv[argc] = strdup ("gpg"); /* argv[0] */
782 int saved_errno = errno;
785 return gpg_error_from_errno (saved_errno);
790 argv[argc] = strdup ("--enable-special-filenames");
793 int saved_errno = errno;
796 return gpg_error_from_errno (saved_errno);
802 argv[argc] = strdup ("--use-agent");
805 int saved_errno = errno;
808 return gpg_error_from_errno (saved_errno);
814 argv[argc] = strdup ("--batch");
817 int saved_errno = errno;
820 return gpg_error_from_errno (saved_errno);
824 argv[argc] = strdup ("--no-sk-comment");
827 int saved_errno = errno;
830 return gpg_error_from_errno (saved_errno);
833 for (a = gpg->arglist; a; a = a->next)
836 *(a->arg_locp) = argc;
840 /* Create a pipe to pass it down to gpg. */
841 fd_data_map[datac].inbound = a->inbound;
847 if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0)
850 int saved_errno = errno;
853 return gpg_error (saved_errno);
855 if (_gpgme_io_set_close_notify (fds[0],
856 close_notify_handler, gpg)
857 || _gpgme_io_set_close_notify (fds[1],
858 close_notify_handler,
861 return gpg_error (GPG_ERR_GENERAL);
863 /* If the data_type is FD, we have to do a dup2 here. */
864 if (fd_data_map[datac].inbound)
866 fd_data_map[datac].fd = fds[0];
867 fd_data_map[datac].peer_fd = fds[1];
871 fd_data_map[datac].fd = fds[1];
872 fd_data_map[datac].peer_fd = fds[0];
876 /* Hack to get hands on the fd later. */
879 if (gpg->cmd.cb_data == a->data)
881 assert (gpg->cmd.idx == -1);
882 gpg->cmd.idx = datac;
884 else if (gpg->cmd.linked_data == a->data)
886 assert (gpg->cmd.linked_idx == -1);
887 gpg->cmd.linked_idx = datac;
891 fd_data_map[datac].data = a->data;
892 fd_data_map[datac].dup_to = a->dup_to;
899 argv[argc] = malloc (buflen);
902 int saved_errno = errno;
905 return gpg_error_from_errno (saved_errno);
916 _gpgme_io_fd2str (ptr, buflen, fd_data_map[datac].peer_fd);
917 fd_data_map[datac].arg_loc = argc;
924 argv[argc] = strdup (a->arg);
927 int saved_errno = errno;
930 return gpg_error_from_errno (saved_errno);
937 gpg->fd_data_map = fd_data_map;
943 add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
948 err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
952 /* FIXME Kludge around poll() problem. */
953 err = _gpgme_io_set_nonblocking (fd);
959 status_cmp (const void *ap, const void *bp)
961 const struct status_table_s *a = ap;
962 const struct status_table_s *b = bp;
964 return strcmp (a->name, b->name);
968 /* Handle the status output of GnuPG. This function does read entire
969 lines and passes them as C strings to the callback function (we can
970 use C Strings because the status output is always UTF-8 encoded).
971 Of course we have to buffer the lines to cope with long lines
972 e.g. with a large user ID. Note: We can optimize this to only cope
973 with status line code we know about and skip all other stuff
974 without buffering (i.e. without extending the buffer). */
976 read_status (engine_gpg_t gpg)
980 size_t bufsize = gpg->status.bufsize;
981 char *buffer = gpg->status.buffer;
982 size_t readpos = gpg->status.readpos;
985 if (bufsize - readpos < 256)
987 /* Need more room for the read. */
989 buffer = realloc (buffer, bufsize);
991 return gpg_error_from_errno (errno);
994 nread = _gpgme_io_read (gpg->status.fd[0],
995 buffer + readpos, bufsize-readpos);
997 return gpg_error_from_errno (errno);
1001 gpg->status.eof = 1;
1002 if (gpg->status.fnc)
1005 err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, "");
1014 for (p = buffer + readpos; nread; nread--, p++)
1018 /* (we require that the last line is terminated by a LF) */
1019 if (p > buffer && p[-1] == '\r')
1022 if (!strncmp (buffer, "[GNUPG:] ", 9)
1023 && buffer[9] >= 'A' && buffer[9] <= 'Z')
1025 struct status_table_s t, *r;
1028 rest = strchr (buffer + 9, ' ');
1030 rest = p; /* Set to an empty string. */
1035 /* (the status table has one extra element) */
1036 r = bsearch (&t, status_table, DIM(status_table) - 1,
1037 sizeof t, status_cmp);
1041 && (r->code == GPGME_STATUS_GET_BOOL
1042 || r->code == GPGME_STATUS_GET_LINE
1043 || r->code == GPGME_STATUS_GET_HIDDEN))
1045 gpg->cmd.code = r->code;
1046 if (gpg->cmd.keyword)
1047 free (gpg->cmd.keyword);
1048 gpg->cmd.keyword = strdup (rest);
1049 if (!gpg->cmd.keyword)
1050 return gpg_error_from_errno (errno);
1051 /* This should be the last thing we have
1052 received and the next thing will be that
1053 the command handler does its action. */
1055 TRACE0 (DEBUG_CTX, "gpgme:read_status", 0,
1056 "error: unexpected data");
1058 add_io_cb (gpg, gpg->cmd.fd, 0,
1059 command_handler, gpg,
1060 &gpg->fd_data_map[gpg->cmd.idx].tag);
1061 gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd;
1064 else if (gpg->status.fnc)
1067 err = gpg->status.fnc (gpg->status.fnc_value,
1073 if (r->code == GPGME_STATUS_END_STREAM)
1077 /* Before we can actually add the
1078 command fd, we might have to flush
1079 the linked output data pipe. */
1080 if (gpg->cmd.linked_idx != -1
1081 && gpg->fd_data_map[gpg->cmd.linked_idx].fd
1084 struct io_select_fd_s fds;
1086 gpg->fd_data_map[gpg->cmd.linked_idx].fd;
1093 _gpgme_io_select (&fds, 1, 1);
1095 _gpgme_data_inbound_handler
1096 (gpg->cmd.linked_data, fds.fd);
1098 while (fds.signaled);
1101 /* XXX We must check if there are any
1102 more fds active after removing this
1104 (*gpg->io_cbs.remove)
1105 (gpg->fd_data_map[gpg->cmd.idx].tag);
1106 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
1107 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
1112 /* To reuse the buffer for the next line we have to
1113 shift the remaining data to the buffer start and
1114 restart the loop Hmmm: We can optimize this function
1115 by looking forward in the buffer to see whether a
1116 second complete line is available and in this case
1117 avoid the memmove for this line. */
1120 memmove (buffer, p, nread);
1122 break; /* the for loop */
1129 /* Update the gpg object. */
1130 gpg->status.bufsize = bufsize;
1131 gpg->status.buffer = buffer;
1132 gpg->status.readpos = readpos;
1137 static gpgme_error_t
1138 status_handler (void *opaque, int fd)
1140 engine_gpg_t gpg = opaque;
1143 assert (fd == gpg->status.fd[0]);
1144 err = read_status (gpg);
1147 if (gpg->status.eof)
1148 _gpgme_io_close (fd);
1153 static gpgme_error_t
1154 read_colon_line (engine_gpg_t gpg)
1158 size_t bufsize = gpg->colon.bufsize;
1159 char *buffer = gpg->colon.buffer;
1160 size_t readpos = gpg->colon.readpos;
1163 if (bufsize - readpos < 256)
1165 /* Need more room for the read. */
1167 buffer = realloc (buffer, bufsize);
1169 return gpg_error_from_errno (errno);
1172 nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos);
1174 return gpg_error_from_errno (errno);
1179 assert (gpg->colon.fnc);
1180 gpg->colon.fnc (gpg->colon.fnc_value, NULL);
1186 for (p = buffer + readpos; nread; nread--, p++)
1190 /* (we require that the last line is terminated by a LF)
1191 and we skip empty lines. Note: we use UTF8 encoding
1192 and escaping of special characters. We require at
1193 least one colon to cope with some other printed
1196 if (*buffer && strchr (buffer, ':'))
1200 if (gpg->colon.preprocess_fnc)
1204 err = gpg->colon.preprocess_fnc (buffer, &line);
1209 assert (gpg->colon.fnc);
1210 gpg->colon.fnc (gpg->colon.fnc_value, line ? line : buffer);
1215 /* To reuse the buffer for the next line we have to
1216 shift the remaining data to the buffer start and
1217 restart the loop Hmmm: We can optimize this function
1218 by looking forward in the buffer to see whether a
1219 second complete line is available and in this case
1220 avoid the memmove for this line. */
1223 memmove (buffer, p, nread);
1225 break; /* The for loop. */
1232 /* Update the gpg object. */
1233 gpg->colon.bufsize = bufsize;
1234 gpg->colon.buffer = buffer;
1235 gpg->colon.readpos = readpos;
1240 /* This colonline handler thing is not the clean way to do it. It
1241 might be better to enhance the gpgme_data_t object to act as a wrapper
1242 for a callback. Same goes for the status thing. For now we use
1243 this thing here because it is easier to implement. */
1244 static gpgme_error_t
1245 colon_line_handler (void *opaque, int fd)
1247 engine_gpg_t gpg = opaque;
1248 gpgme_error_t rc = 0;
1250 assert (fd == gpg->colon.fd[0]);
1251 rc = read_colon_line (gpg);
1255 _gpgme_io_close (fd);
1260 static gpgme_error_t
1261 start (engine_gpg_t gpg)
1267 struct spawn_fd_item_s *fd_list;
1271 return gpg_error (GPG_ERR_INV_VALUE);
1273 if (!gpg->file_name && !_gpgme_get_gpg_path ())
1274 return gpg_error (GPG_ERR_INV_ENGINE);
1278 rc = add_arg_ext (gpg, gpg->lc_ctype, 1);
1280 rc = add_arg_ext (gpg, "--lc-ctype", 1);
1285 if (gpg->lc_messages)
1287 rc = add_arg_ext (gpg, gpg->lc_messages, 1);
1289 rc = add_arg_ext (gpg, "--lc-messages", 1);
1294 rc = build_argv (gpg);
1298 /* status_fd, colon_fd and end of list. */
1300 for (i = 0; gpg->fd_data_map[i].data; i++)
1302 fd_list = calloc (n, sizeof *fd_list);
1304 return gpg_error_from_errno (errno);
1306 /* Build the fd list for the child. */
1308 fd_list[n].fd = gpg->status.fd[1];
1309 fd_list[n].dup_to = -1;
1310 fd_list[n].arg_loc = gpg->status.arg_loc;
1314 fd_list[n].fd = gpg->colon.fd[1];
1315 fd_list[n].dup_to = 1;
1318 for (i = 0; gpg->fd_data_map[i].data; i++)
1320 fd_list[n].fd = gpg->fd_data_map[i].peer_fd;
1321 fd_list[n].dup_to = gpg->fd_data_map[i].dup_to;
1322 fd_list[n].arg_loc = gpg->fd_data_map[i].arg_loc;
1326 fd_list[n].dup_to = -1;
1328 status = _gpgme_io_spawn (gpg->file_name ? gpg->file_name :
1329 _gpgme_get_gpg_path (), gpg->argv, fd_list, &pid);
1330 saved_errno = errno;
1334 return gpg_error_from_errno (saved_errno);
1336 /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
1338 rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg,
1341 /* FIXME: kill the child */
1346 assert (gpg->colon.fd[0] != -1);
1347 rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg,
1350 /* FIXME: kill the child */
1354 for (i = 0; gpg->fd_data_map[i].data; i++)
1356 if (gpg->cmd.used && i == gpg->cmd.idx)
1358 /* Park the cmd fd. */
1359 gpg->cmd.fd = gpg->fd_data_map[i].fd;
1360 gpg->fd_data_map[i].fd = -1;
1364 rc = add_io_cb (gpg, gpg->fd_data_map[i].fd,
1365 gpg->fd_data_map[i].inbound,
1366 gpg->fd_data_map[i].inbound
1367 ? _gpgme_data_inbound_handler
1368 : _gpgme_data_outbound_handler,
1369 gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag);
1372 /* FIXME: kill the child */
1377 _gpgme_allow_set_foregound_window (pid);
1379 gpg_io_event (gpg, GPGME_EVENT_START, NULL);
1381 /* fixme: check what data we can release here */
1386 static gpgme_error_t
1387 gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
1389 engine_gpg_t gpg = engine;
1392 err = add_arg (gpg, "--decrypt");
1394 /* Tell the gpg object about the data. */
1396 err = add_arg (gpg, "--output");
1398 err = add_arg (gpg, "-");
1400 err = add_data (gpg, plain, 1, 1);
1402 err = add_arg (gpg, "--");
1404 err = add_data (gpg, ciph, -1, 0);
1411 static gpgme_error_t
1412 gpg_delete (void *engine, gpgme_key_t key, int allow_secret)
1414 engine_gpg_t gpg = engine;
1417 err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key"
1420 err = add_arg (gpg, "--");
1423 if (!key->subkeys || !key->subkeys->fpr)
1424 return gpg_error (GPG_ERR_INV_VALUE);
1426 err = add_arg (gpg, key->subkeys->fpr);
1435 static gpgme_error_t
1436 append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1438 gpgme_error_t err = 0;
1442 for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
1444 const char *s = key->subkeys ? key->subkeys->keyid : NULL;
1448 err = add_arg (gpg, "-u");
1450 err = add_arg (gpg, s);
1452 gpgme_key_unref (key);
1459 static gpgme_error_t
1460 append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1462 gpgme_error_t err = 0;
1463 gpgme_sig_notation_t notation;
1465 notation = gpgme_sig_notation_get (ctx);
1467 while (!err && notation)
1470 && !(notation->flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
1471 err = gpg_error (GPG_ERR_INV_VALUE);
1472 else if (notation->name)
1476 /* Maximum space needed is one byte for the "critical" flag,
1477 the name, one byte for '=', the value, and a terminating
1480 arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1);
1482 err = gpg_error_from_errno (errno);
1488 if (notation->critical)
1491 memcpy (argp, notation->name, notation->name_len);
1492 argp += notation->name_len;
1496 /* We know that notation->name is '\0' terminated. */
1497 strcpy (argp, notation->value);
1501 err = add_arg (gpg, "--sig-notation");
1503 err = add_arg (gpg, arg);
1510 /* This is a policy URL. */
1514 if (notation->critical)
1516 value = malloc (1 + notation->value_len + 1);
1518 err = gpg_error_from_errno (errno);
1522 /* We know that notation->value is '\0' terminated. */
1523 strcpy (&value[1], notation->value);
1527 value = notation->value;
1530 err = add_arg (gpg, "--sig-policy-url");
1532 err = add_arg (gpg, value);
1534 if (value != notation->value)
1538 notation = notation->next;
1544 static gpgme_error_t
1545 gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
1546 gpgme_ctx_t ctx /* FIXME */)
1548 engine_gpg_t gpg = engine;
1551 err = add_arg (gpg, "--with-colons");
1553 err = append_args_from_signers (gpg, ctx);
1555 err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
1557 err = add_data (gpg, out, 1, 1);
1559 err = add_arg (gpg, "--");
1560 if (!err && type == 0)
1562 const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1564 err = gpg_error (GPG_ERR_INV_VALUE);
1566 err = add_arg (gpg, s);
1575 static gpgme_error_t
1576 append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
1578 gpgme_error_t err = 0;
1583 if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
1584 err = gpg_error (GPG_ERR_INV_VALUE);
1586 err = add_arg (gpg, "-r");
1588 err = add_arg (gpg, recp[i]->subkeys->fpr);
1597 static gpgme_error_t
1598 gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
1599 gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
1601 engine_gpg_t gpg = engine;
1603 int symmetric = !recp;
1605 err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt");
1607 if (!err && use_armor)
1608 err = add_arg (gpg, "--armor");
1612 /* If we know that all recipients are valid (full or ultimate trust)
1613 we can suppress further checks. */
1614 if (!err && !symmetric && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1615 err = add_arg (gpg, "--always-trust");
1618 err = append_args_from_recipients (gpg, recp);
1621 /* Tell the gpg object about the data. */
1623 err = add_arg (gpg, "--output");
1625 err = add_arg (gpg, "-");
1627 err = add_data (gpg, ciph, 1, 1);
1628 if (gpgme_data_get_file_name (plain))
1631 err = add_arg (gpg, "--set-filename");
1633 err = add_arg (gpg, gpgme_data_get_file_name (plain));
1636 err = add_arg (gpg, "--");
1638 err = add_data (gpg, plain, -1, 0);
1647 static gpgme_error_t
1648 gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
1649 gpgme_encrypt_flags_t flags, gpgme_data_t plain,
1650 gpgme_data_t ciph, int use_armor,
1651 gpgme_ctx_t ctx /* FIXME */)
1653 engine_gpg_t gpg = engine;
1656 err = add_arg (gpg, "--encrypt");
1658 err = add_arg (gpg, "--sign");
1659 if (!err && use_armor)
1660 err = add_arg (gpg, "--armor");
1662 /* If we know that all recipients are valid (full or ultimate trust)
1663 we can suppress further checks. */
1664 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1665 err = add_arg (gpg, "--always-trust");
1668 err = append_args_from_recipients (gpg, recp);
1671 err = append_args_from_signers (gpg, ctx);
1673 err = append_args_from_sig_notations (gpg, ctx);
1675 /* Tell the gpg object about the data. */
1677 err = add_arg (gpg, "--output");
1679 err = add_arg (gpg, "-");
1681 err = add_data (gpg, ciph, 1, 1);
1682 if (gpgme_data_get_file_name (plain))
1685 err = add_arg (gpg, "--set-filename");
1687 err = add_arg (gpg, gpgme_data_get_file_name (plain));
1690 err = add_arg (gpg, "--");
1692 err = add_data (gpg, plain, -1, 0);
1701 static gpgme_error_t
1702 gpg_export (void *engine, const char *pattern, unsigned int reserved,
1703 gpgme_data_t keydata, int use_armor)
1705 engine_gpg_t gpg = engine;
1709 return gpg_error (GPG_ERR_INV_VALUE);
1711 err = add_arg (gpg, "--export");
1712 if (!err && use_armor)
1713 err = add_arg (gpg, "--armor");
1715 err = add_data (gpg, keydata, 1, 1);
1717 err = add_arg (gpg, "--");
1719 if (!err && pattern && *pattern)
1720 err = add_arg (gpg, pattern);
1729 static gpgme_error_t
1730 gpg_export_ext (void *engine, const char *pattern[], unsigned int reserved,
1731 gpgme_data_t keydata, int use_armor)
1733 engine_gpg_t gpg = engine;
1737 return gpg_error (GPG_ERR_INV_VALUE);
1739 err = add_arg (gpg, "--export");
1740 if (!err && use_armor)
1741 err = add_arg (gpg, "--armor");
1743 err = add_data (gpg, keydata, 1, 1);
1745 err = add_arg (gpg, "--");
1749 while (!err && *pattern && **pattern)
1750 err = add_arg (gpg, *(pattern++));
1760 static gpgme_error_t
1761 gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,
1762 gpgme_data_t pubkey, gpgme_data_t seckey)
1764 engine_gpg_t gpg = engine;
1768 return gpg_error (GPG_ERR_INV_VALUE);
1770 /* We need a special mechanism to get the fd of a pipe here, so that
1771 we can use this for the %pubring and %secring parameters. We
1772 don't have this yet, so we implement only the adding to the
1773 standard keyrings. */
1774 if (pubkey || seckey)
1775 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1777 err = add_arg (gpg, "--gen-key");
1778 if (!err && use_armor)
1779 err = add_arg (gpg, "--armor");
1781 err = add_arg (gpg, "--");
1783 err = add_data (gpg, help_data, -1, 0);
1792 static gpgme_error_t
1793 gpg_import (void *engine, gpgme_data_t keydata)
1795 engine_gpg_t gpg = engine;
1798 err = add_arg (gpg, "--import");
1800 err = add_arg (gpg, "--");
1802 err = add_data (gpg, keydata, -1, 0);
1811 /* The output for external keylistings in GnuPG is different from all
1812 the other key listings. We catch this here with a special
1813 preprocessor that reformats the colon handler lines. */
1814 static gpgme_error_t
1815 gpg_keylist_preprocess (char *line, char **r_line)
1819 RT_NONE, RT_INFO, RT_PUB, RT_UID
1822 #define NR_FIELDS 16
1823 char *field[NR_FIELDS];
1828 while (line && fields < NR_FIELDS)
1830 field[fields++] = line;
1831 line = strchr (line, ':');
1836 if (!strcmp (field[0], "info"))
1838 else if (!strcmp (field[0], "pub"))
1840 else if (!strcmp (field[0], "uid"))
1848 /* FIXME: Eventually, check the version number at least. */
1857 pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>
1859 as defined in 5.2. Machine Readable Indexes of the OpenPGP
1860 HTTP Keyserver Protocol (draft).
1863 pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>::::::::
1866 if (asprintf (r_line, "pub:o%s:%s:%s:%s:%s:%s::::::::",
1867 field[6], field[3], field[2], field[1],
1868 field[4], field[5]) < 0)
1869 return gpg_error_from_errno (errno);
1875 uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags>
1877 as defined in 5.2. Machine Readable Indexes of the OpenPGP
1878 HTTP Keyserver Protocol (draft).
1881 uid:o<flags>::::<creatdate>:<expdate>:::<c-coded uid>:
1885 /* The user ID is percent escaped, but we want c-coded.
1886 Because we have to replace each '%HL' by '\xHL', we need at
1887 most 4/3 th the number of bytes. But because we also need
1888 to escape the backslashes we allocate twice as much. */
1889 char *uid = malloc (2 * strlen (field[1]) + 1);
1894 return gpg_error_from_errno (errno);
1904 /* Copy the next two bytes unconditionally. */
1906 *(dst++) = *(src++);
1908 *(dst++) = *(src++);
1910 else if (*src == '\\')
1916 *(dst++) = *(src++);
1920 if (asprintf (r_line, "uid:o%s::::%s:%s:::%s:",
1921 field[4], field[2], field[3], uid) < 0)
1922 return gpg_error_from_errno (errno);
1927 /* Unknown record. */
1936 gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
1937 gpgme_keylist_mode_t mode)
1941 err = add_arg (gpg, "--with-colons");
1943 err = add_arg (gpg, "--fixed-list-mode");
1945 err = add_arg (gpg, "--with-fingerprint");
1947 err = add_arg (gpg, "--with-fingerprint");
1949 && (mode & GPGME_KEYLIST_MODE_SIGS)
1950 && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
1952 err = add_arg (gpg, "--list-options");
1954 err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
1958 if ( (mode & GPGME_KEYLIST_MODE_EXTERN) )
1961 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
1962 else if ( (mode & GPGME_KEYLIST_MODE_LOCAL))
1964 /* The local+extern mode is special. It works only with
1965 gpg >= 2.0.10. FIXME: We should check that we have
1966 such a version to that we can return a proper error
1967 code. The problem is that we don't know the context
1968 here and thus can't accesses the cached version
1969 number for the engine info structure. */
1970 err = add_arg (gpg, "--locate-keys");
1971 if ((mode & GPGME_KEYLIST_MODE_SIGS))
1972 err = add_arg (gpg, "--with-sig-check");
1976 err = add_arg (gpg, "--search-keys");
1977 gpg->colon.preprocess_fnc = gpg_keylist_preprocess;
1982 err = add_arg (gpg, secret_only ? "--list-secret-keys"
1983 : ((mode & GPGME_KEYLIST_MODE_SIGS)
1984 ? "--check-sigs" : "--list-keys"));
1988 err = add_arg (gpg, "--");
1994 static gpgme_error_t
1995 gpg_keylist (void *engine, const char *pattern, int secret_only,
1996 gpgme_keylist_mode_t mode)
1998 engine_gpg_t gpg = engine;
2001 err = gpg_keylist_build_options (gpg, secret_only, mode);
2003 if (!err && pattern && *pattern)
2004 err = add_arg (gpg, pattern);
2013 static gpgme_error_t
2014 gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
2015 int reserved, gpgme_keylist_mode_t mode)
2017 engine_gpg_t gpg = engine;
2021 return gpg_error (GPG_ERR_INV_VALUE);
2023 err = gpg_keylist_build_options (gpg, secret_only, mode);
2027 while (!err && *pattern && **pattern)
2028 err = add_arg (gpg, *(pattern++));
2038 static gpgme_error_t
2039 gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
2040 gpgme_sig_mode_t mode, int use_armor, int use_textmode,
2041 int include_certs, gpgme_ctx_t ctx /* FIXME */)
2043 engine_gpg_t gpg = engine;
2046 if (mode == GPGME_SIG_MODE_CLEAR)
2047 err = add_arg (gpg, "--clearsign");
2050 err = add_arg (gpg, "--sign");
2051 if (!err && mode == GPGME_SIG_MODE_DETACH)
2052 err = add_arg (gpg, "--detach");
2053 if (!err && use_armor)
2054 err = add_arg (gpg, "--armor");
2055 if (!err && use_textmode)
2056 err = add_arg (gpg, "--textmode");
2060 err = append_args_from_signers (gpg, ctx);
2062 err = append_args_from_sig_notations (gpg, ctx);
2064 if (gpgme_data_get_file_name (in))
2067 err = add_arg (gpg, "--set-filename");
2069 err = add_arg (gpg, gpgme_data_get_file_name (in));
2072 /* Tell the gpg object about the data. */
2074 err = add_arg (gpg, "--");
2076 err = add_data (gpg, in, -1, 0);
2078 err = add_data (gpg, out, 1, 1);
2086 static gpgme_error_t
2087 gpg_trustlist (void *engine, const char *pattern)
2089 engine_gpg_t gpg = engine;
2092 err = add_arg (gpg, "--with-colons");
2094 err = add_arg (gpg, "--list-trust-path");
2096 /* Tell the gpg object about the data. */
2098 err = add_arg (gpg, "--");
2100 err = add_arg (gpg, pattern);
2109 static gpgme_error_t
2110 gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
2111 gpgme_data_t plaintext)
2113 engine_gpg_t gpg = engine;
2114 gpgme_error_t err = 0;
2118 /* Normal or cleartext signature. */
2120 err = add_arg (gpg, "--output");
2122 err = add_arg (gpg, "-");
2124 err = add_arg (gpg, "--");
2126 err = add_data (gpg, sig, -1, 0);
2128 err = add_data (gpg, plaintext, 1, 1);
2132 err = add_arg (gpg, "--verify");
2134 err = add_arg (gpg, "--");
2136 err = add_data (gpg, sig, -1, 0);
2137 if (!err && signed_text)
2138 err = add_data (gpg, signed_text, -1, 0);
2149 gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
2151 engine_gpg_t gpg = engine;
2153 gpg->io_cbs = *io_cbs;
2157 struct engine_ops _gpgme_engine_ops_gpg =
2159 /* Static functions. */
2160 _gpgme_get_gpg_path,
2162 gpg_get_req_version,
2165 /* Member functions. */
2168 gpg_set_status_handler,
2169 gpg_set_command_handler,
2170 gpg_set_colon_line_handler,
2186 NULL, /* getauditlog */
2187 NULL, /* conf_load */
2188 NULL, /* conf_save */