summaryrefslogtreecommitdiff
path: root/src/engine-gpg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine-gpg.c')
-rw-r--r--src/engine-gpg.c211
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
};