diff options
Diffstat (limited to 'src/engine-gpg.c')
-rw-r--r-- | src/engine-gpg.c | 211 |
1 files changed, 126 insertions, 85 deletions
diff --git a/src/engine-gpg.c b/src/engine-gpg.c index cbb456e..3f02503 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -2,19 +2,19 @@ Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2012 g10 Code GmbH - + This file is part of GPGME. - + GPGME is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + GPGME is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. */ @@ -87,7 +87,7 @@ struct engine_gpg struct { - int fd[2]; + int fd[2]; int arg_loc; size_t bufsize; char *buffer; @@ -101,7 +101,7 @@ struct engine_gpg /* This is a kludge - see the comment at colon_line_handler. */ struct { - int fd[2]; + int fd[2]; int arg_loc; size_t bufsize; char *buffer; @@ -113,7 +113,7 @@ struct engine_gpg colon_preprocessor_t preprocess_fnc; } colon; - char **argv; + char **argv; struct fd_data_map_s *fd_data_map; /* stuff needed for interactive (command) mode */ @@ -125,7 +125,7 @@ struct engine_gpg int idx; /* Index in fd_data_map */ gpgme_status_code_t code; /* last code */ char *keyword; /* what has been requested (malloced) */ - engine_command_handler_t fnc; + engine_command_handler_t fnc; void *fnc_value; /* The kludges never end. This is used to couple command handlers with output data in edit key mode. */ @@ -134,6 +134,7 @@ struct engine_gpg } cmd; struct gpgme_io_cbs io_cbs; + gpgme_pinentry_mode_t pinentry_mode; }; typedef struct engine_gpg *engine_gpg_t; @@ -210,7 +211,7 @@ _add_arg (engine_gpg_t gpg, const char *arg, int front, int *arg_locp) a = malloc (sizeof *a + strlen (arg)); if (!a) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); a->data = NULL; a->dup_to = -1; @@ -269,7 +270,7 @@ add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound) a = malloc (sizeof *a - 1); if (!a) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); a->next = NULL; a->data = data; a->inbound = inbound; @@ -424,14 +425,14 @@ gpg_new (void **engine, const char *file_name, const char *home_dir) gpg = calloc (1, sizeof *gpg); if (!gpg) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); if (file_name) { gpg->file_name = strdup (file_name); if (!gpg->file_name) { - rc = gpg_error_from_errno (errno); + rc = gpg_error_from_syserror (); goto leave; } } @@ -452,14 +453,14 @@ gpg_new (void **engine, const char *file_name, const char *home_dir) gpg->status.buffer = malloc (gpg->status.bufsize); if (!gpg->status.buffer) { - rc = gpg_error_from_errno (errno); + rc = gpg_error_from_syserror (); goto leave; } /* In any case we need a status pipe - create it right here and don't handle it with our generic gpgme_data_t mechanism. */ if (_gpgme_io_pipe (gpg->status.fd, 1) == -1) { - rc = gpg_error_from_errno (errno); + rc = gpg_error_from_syserror (); goto leave; } if (_gpgme_io_set_close_notify (gpg->status.fd[0], @@ -537,7 +538,7 @@ gpg_new (void **engine, const char *file_name, const char *home_dir) rc = _gpgme_getenv ("TERM", &dft_ttytype); if (rc) goto leave; - + if (dft_ttytype) { rc = add_arg (gpg, "--ttytype"); @@ -630,14 +631,14 @@ gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc, gpg->colon.readpos = 0; gpg->colon.buffer = malloc (gpg->colon.bufsize); if (!gpg->colon.buffer) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); - if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1) + if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1) { - int saved_errno = errno; + int saved_err = gpg_error_from_syserror (); free (gpg->colon.buffer); gpg->colon.buffer = NULL; - return gpg_error_from_errno (saved_errno); + return saved_err; } if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg) || _gpgme_io_set_close_notify (gpg->colon.fd[1], @@ -722,7 +723,7 @@ build_argv (engine_gpg_t gpg) gpgme_error_t err; struct arg_and_data_s *a; struct fd_data_map_s *fd_data_map; - size_t datac=0, argc=0; + size_t datac=0, argc=0; char **argv; int need_special = 0; int use_agent = 0; @@ -769,29 +770,31 @@ build_argv (engine_gpg_t gpg) argc++; if (use_agent) argc++; + if (gpg->pinentry_mode) + argc++; if (!gpg->cmd.used) argc++; /* --batch */ argc += 1; /* --no-sk-comment */ argv = calloc (argc + 1, sizeof *argv); if (!argv) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); fd_data_map = calloc (datac + 1, sizeof *fd_data_map); if (!fd_data_map) { - int saved_errno = errno; + int saved_err = gpg_error_from_syserror (); free_argv (argv); - return gpg_error_from_errno (saved_errno); + return saved_err; } argc = datac = 0; argv[argc] = strdup ("gpg"); /* argv[0] */ if (!argv[argc]) { - int saved_errno = errno; + int saved_err = gpg_error_from_syserror (); free (fd_data_map); free_argv (argv); - return gpg_error_from_errno (saved_errno); + return saved_err; } argc++; if (need_special) @@ -799,10 +802,10 @@ build_argv (engine_gpg_t gpg) argv[argc] = strdup ("--enable-special-filenames"); if (!argv[argc]) { - int saved_errno = errno; + int saved_err = gpg_error_from_syserror (); free (fd_data_map); free_argv (argv); - return gpg_error_from_errno (saved_errno); + return saved_err; } argc++; } @@ -811,32 +814,58 @@ build_argv (engine_gpg_t gpg) argv[argc] = strdup ("--use-agent"); if (!argv[argc]) { - int saved_errno = errno; + int saved_err = gpg_error_from_syserror (); free (fd_data_map); free_argv (argv); - return gpg_error_from_errno (saved_errno); + return saved_err; } argc++; } + + if (gpg->pinentry_mode) + { + const char *s = NULL; + switch (gpg->pinentry_mode) + { + case GPGME_PINENTRY_MODE_DEFAULT: break; + case GPGME_PINENTRY_MODE_ASK: s = "--pinentry-mode=ask"; break; + case GPGME_PINENTRY_MODE_CANCEL: s = "--pinentry-mode=cancel"; break; + case GPGME_PINENTRY_MODE_ERROR: s = "--pinentry-mode=error"; break; + case GPGME_PINENTRY_MODE_LOOPBACK:s = "--pinentry-mode=loopback"; break; + } + if (s) + { + argv[argc] = strdup (s); + if (!argv[argc]) + { + int saved_err = gpg_error_from_syserror (); + free (fd_data_map); + free_argv (argv); + return saved_err; + } + argc++; + } + } + if (!gpg->cmd.used) { argv[argc] = strdup ("--batch"); if (!argv[argc]) { - int saved_errno = errno; + int saved_err = gpg_error_from_syserror (); free (fd_data_map); free_argv (argv); - return gpg_error_from_errno (saved_errno); + return saved_err; } argc++; } argv[argc] = strdup ("--no-sk-comment"); if (!argv[argc]) { - int saved_errno = errno; + int saved_err = gpg_error_from_syserror (); free (fd_data_map); free_argv (argv); - return gpg_error_from_errno (saved_errno); + return saved_err; } argc++; for (a = gpg->arglist; a; a = a->next) @@ -850,9 +879,9 @@ build_argv (engine_gpg_t gpg) fd_data_map[datac].inbound = a->inbound; /* Create a pipe. */ - { + { int fds[2]; - + if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0) == -1) { @@ -908,10 +937,10 @@ build_argv (engine_gpg_t gpg) argv[argc] = malloc (buflen); if (!argv[argc]) { - int saved_errno = errno; + int saved_err = gpg_error_from_syserror (); free (fd_data_map); free_argv (argv); - return gpg_error_from_errno (saved_errno); + return saved_err; } ptr = argv[argc]; @@ -933,10 +962,10 @@ build_argv (engine_gpg_t gpg) argv[argc] = strdup (a->arg); if (!argv[argc]) { - int saved_errno = errno; + int saved_err = gpg_error_from_syserror (); free (fd_data_map); free_argv (argv); - return gpg_error_from_errno (saved_errno); + return saved_err; } argc++; } @@ -976,24 +1005,24 @@ read_status (engine_gpg_t gpg) { char *p; int nread; - size_t bufsize = gpg->status.bufsize; + size_t bufsize = gpg->status.bufsize; char *buffer = gpg->status.buffer; - size_t readpos = gpg->status.readpos; + size_t readpos = gpg->status.readpos; assert (buffer); if (bufsize - readpos < 256) - { + { /* Need more room for the read. */ bufsize += 1024; buffer = realloc (buffer, bufsize); if (!buffer) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); } nread = _gpgme_io_read (gpg->status.fd[0], buffer + readpos, bufsize-readpos); if (nread == -1) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); if (!nread) { @@ -1029,7 +1058,7 @@ read_status (engine_gpg_t gpg) rest = p; /* Set to an empty string. */ else *rest++ = 0; - + r = _gpgme_parse_status (buffer + 9); if (r >= 0) { @@ -1043,7 +1072,7 @@ read_status (engine_gpg_t gpg) free (gpg->cmd.keyword); gpg->cmd.keyword = strdup (rest); if (!gpg->cmd.keyword) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); /* This should be the last thing we have received and the next thing will be that the command handler does its action. */ @@ -1060,12 +1089,12 @@ read_status (engine_gpg_t gpg) else if (gpg->status.fnc) { gpgme_error_t err; - err = gpg->status.fnc (gpg->status.fnc_value, + err = gpg->status.fnc (gpg->status.fnc_value, r, rest); if (err) return err; } - + if (r == GPGME_STATUS_END_STREAM) { if (gpg->cmd.used) @@ -1120,7 +1149,7 @@ read_status (engine_gpg_t gpg) else readpos++; } - } + } /* Update the gpg object. */ gpg->status.bufsize = bufsize; @@ -1152,23 +1181,23 @@ read_colon_line (engine_gpg_t gpg) { char *p; int nread; - size_t bufsize = gpg->colon.bufsize; + size_t bufsize = gpg->colon.bufsize; char *buffer = gpg->colon.buffer; - size_t readpos = gpg->colon.readpos; + size_t readpos = gpg->colon.readpos; assert (buffer); if (bufsize - readpos < 256) - { + { /* Need more room for the read. */ bufsize += 1024; buffer = realloc (buffer, bufsize); - if (!buffer) - return gpg_error_from_errno (errno); + if (!buffer) + return gpg_error_from_syserror (); } nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos); if (nread == -1) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); if (!nread) { @@ -1208,7 +1237,7 @@ read_colon_line (engine_gpg_t gpg) if (line) free (line); } - + /* To reuse the buffer for the next line we have to shift the remaining data to the buffer start and restart the loop Hmmm: We can optimize this function @@ -1224,7 +1253,7 @@ read_colon_line (engine_gpg_t gpg) else readpos++; } - } + } /* Update the gpg object. */ gpg->colon.bufsize = bufsize; @@ -1259,7 +1288,6 @@ static gpgme_error_t start (engine_gpg_t gpg) { gpgme_error_t rc; - int saved_errno; int i, n; int status; struct spawn_fd_item_s *fd_list; @@ -1269,7 +1297,7 @@ start (engine_gpg_t gpg) return gpg_error (GPG_ERR_INV_VALUE); if (!gpg->file_name && !_gpgme_get_gpg_path ()) - return gpg_error (GPG_ERR_INV_ENGINE); + return trace_gpg_error (GPG_ERR_INV_ENGINE); if (gpg->lc_ctype) { @@ -1295,11 +1323,11 @@ start (engine_gpg_t gpg) /* status_fd, colon_fd and end of list. */ n = 3; - for (i = 0; gpg->fd_data_map[i].data; i++) + for (i = 0; gpg->fd_data_map[i].data; i++) n++; fd_list = calloc (n, sizeof *fd_list); if (! fd_list) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); /* Build the fd list for the child. */ n = 0; @@ -1309,7 +1337,7 @@ start (engine_gpg_t gpg) n++; if (gpg->colon.fnc) { - fd_list[n].fd = gpg->colon.fd[1]; + fd_list[n].fd = gpg->colon.fd[1]; fd_list[n].dup_to = 1; n++; } @@ -1327,11 +1355,12 @@ start (engine_gpg_t gpg) _gpgme_get_gpg_path (), gpg->argv, IOSPAWN_FLAG_ALLOW_SET_FG, fd_list, NULL, NULL, &pid); - saved_errno = errno; - - free (fd_list); - if (status == -1) - return gpg_error_from_errno (saved_errno); + { + int saved_err = gpg_error_from_syserror (); + free (fd_list); + if (status == -1) + return saved_err; + } /*_gpgme_register_term_handler ( closure, closure_value, pid );*/ @@ -1367,7 +1396,7 @@ start (engine_gpg_t gpg) ? _gpgme_data_inbound_handler : _gpgme_data_outbound_handler, gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag); - + if (rc) /* FIXME: kill the child */ return rc; @@ -1375,7 +1404,7 @@ start (engine_gpg_t gpg) } gpg_io_event (gpg, GPGME_EVENT_START, NULL); - + /* fixme: check what data we can release here */ return 0; } @@ -1495,7 +1524,7 @@ append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */) arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1); if (!arg) - err = gpg_error_from_errno (errno); + err = gpg_error_from_syserror (); if (!err) { @@ -1531,7 +1560,7 @@ append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */) { value = malloc (1 + notation->value_len + 1); if (!value) - err = gpg_error_from_errno (errno); + err = gpg_error_from_syserror (); else { value[0] = '!'; @@ -1605,7 +1634,7 @@ append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[]) if (err) break; i++; - } + } return err; } @@ -1832,7 +1861,7 @@ gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor, Note that we use a delimiter and thus a trailing delimiter is not required. DELIM may not be changed after the first call. */ static const char * -string_from_data (gpgme_data_t data, int delim, +string_from_data (gpgme_data_t data, int delim, void **helpptr, gpgme_error_t *r_err) { #define MYBUFLEN 2000 /* Fixme: We don't support URLs longer than that. */ @@ -1900,7 +1929,7 @@ string_from_data (gpgme_data_t data, int delim, return NULL; } - nread = gpgme_data_read (data, self->buf + self->buflen, + nread = gpgme_data_read (data, self->buf + self->buflen, MYBUFLEN - self->buflen); if (nread < 0) { @@ -2034,7 +2063,7 @@ gpg_keylist_preprocess (char *line, char **r_line) rectype = RT_PUB; else if (!strcmp (field[0], "uid")) rectype = RT_UID; - else + else rectype = RT_NONE; switch (rectype) @@ -2052,7 +2081,7 @@ gpg_keylist_preprocess (char *line, char **r_line) pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags> as defined in 5.2. Machine Readable Indexes of the OpenPGP - HTTP Keyserver Protocol (draft). + HTTP Keyserver Protocol (draft). We want: pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>:::::::: @@ -2061,7 +2090,7 @@ gpg_keylist_preprocess (char *line, char **r_line) if (asprintf (r_line, "pub:o%s:%s:%s:%s:%s:%s::::::::", field[6], field[3], field[2], field[1], field[4], field[5]) < 0) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); return 0; case RT_UID: @@ -2070,7 +2099,7 @@ gpg_keylist_preprocess (char *line, char **r_line) uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags> as defined in 5.2. Machine Readable Indexes of the OpenPGP - HTTP Keyserver Protocol (draft). + HTTP Keyserver Protocol (draft). We want: uid:o<flags>::::<creatdate>:<expdate>:::<c-coded uid>: @@ -2086,7 +2115,7 @@ gpg_keylist_preprocess (char *line, char **r_line) char *dst; if (! uid) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); src = field[1]; dst = uid; while (*src) @@ -2114,7 +2143,7 @@ gpg_keylist_preprocess (char *line, char **r_line) if (asprintf (r_line, "uid:o%s::::%s:%s:::%s:", field[4], field[2], field[3], uid) < 0) - return gpg_error_from_errno (errno); + return gpg_error_from_syserror (); } return 0; @@ -2181,10 +2210,10 @@ gpg_keylist_build_options (engine_gpg_t gpg, int secret_only, } if (!err) err = add_arg (gpg, "--"); - + return err; } - + static gpgme_error_t gpg_keylist (void *engine, const char *pattern, int secret_only, @@ -2287,7 +2316,7 @@ gpg_trustlist (void *engine, const char *pattern) err = add_arg (gpg, "--with-colons"); if (!err) err = add_arg (gpg, "--list-trust-path"); - + /* Tell the gpg object about the data. */ if (!err) err = add_arg (gpg, "--"); @@ -2348,12 +2377,23 @@ gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs) gpg->io_cbs = *io_cbs; } + +static gpgme_error_t +gpg_set_pinentry_mode (void *engine, gpgme_pinentry_mode_t mode) +{ + engine_gpg_t gpg = engine; + + gpg->pinentry_mode = mode; + return 0; +} + + struct engine_ops _gpgme_engine_ops_gpg = { /* Static functions. */ _gpgme_get_gpg_path, - NULL, + NULL, gpg_get_version, gpg_get_req_version, gpg_new, @@ -2389,5 +2429,6 @@ struct engine_ops _gpgme_engine_ops_gpg = gpg_io_event, gpg_cancel, NULL, /* cancel_op */ - gpg_passwd + gpg_passwd, + gpg_set_pinentry_mode }; |