gpgme_tool: Support GPG's new pinentry-mode.
* src/gpgme-tool.c (log_error): Do not always print the error source. (gt_set_pinentry_mode): New. (server_passphrase_cb): New. (cmd_pinentry_mode): New. (register_commands): Add cmd_pinentry_mode. (options): Add option --gpg-binary. (struct args): Add field gpg-binary. (parse_options, main): Implement that option.
This commit is contained in:
parent
61a0d92b67
commit
02a2cf0ccb
118
src/gpgme-tool.c
118
src/gpgme-tool.c
@ -1,5 +1,5 @@
|
|||||||
/* gpgme-tool.c - Assuan server exposing GnuPG Made Easy operations.
|
/* gpgme-tool.c - Assuan server exposing GnuPG Made Easy operations.
|
||||||
Copyright (C) 2009, 2010, 2012 g10 Code GmbH
|
Copyright (C) 2009, 2010, 2012, 2013 g10 Code GmbH
|
||||||
Copyright (C) 2001, 2003, 2009, 2011 Free Software Foundation, Inc.
|
Copyright (C) 2001, 2003, 2009, 2011 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GPGME.
|
This file is part of GPGME.
|
||||||
@ -645,8 +645,11 @@ log_error (int status, gpg_error_t errnum, const char *fmt, ...)
|
|||||||
vfprintf (log_stream, fmt, ap);
|
vfprintf (log_stream, fmt, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
if (errnum)
|
if (errnum)
|
||||||
fprintf (log_stream, ": %s <%s>", gpg_strerror (errnum),
|
{
|
||||||
gpg_strsource (errnum));
|
fprintf (log_stream, ": %s", gpg_strerror (errnum));
|
||||||
|
if (gpg_err_source (errnum) != GPG_ERR_SOURCE_GPGME)
|
||||||
|
fprintf (log_stream, " <%s>", gpg_strsource (errnum));
|
||||||
|
}
|
||||||
fprintf (log_stream, "\n");
|
fprintf (log_stream, "\n");
|
||||||
if (status)
|
if (status)
|
||||||
exit (status);
|
exit (status);
|
||||||
@ -1466,6 +1469,10 @@ typedef struct gpgme_tool *gpgme_tool_t;
|
|||||||
/* Forward declaration. */
|
/* Forward declaration. */
|
||||||
void gt_write_status (gpgme_tool_t gt,
|
void gt_write_status (gpgme_tool_t gt,
|
||||||
status_t status, ...) GT_GCC_A_SENTINEL(0);
|
status_t status, ...) GT_GCC_A_SENTINEL(0);
|
||||||
|
static gpg_error_t
|
||||||
|
server_passphrase_cb (void *opaque, const char *uid_hint, const char *info,
|
||||||
|
int was_bad, int fd);
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_gt_progress_cb (void *opaque, const char *what,
|
_gt_progress_cb (void *opaque, const char *what,
|
||||||
@ -1495,9 +1502,10 @@ _gt_gpgme_new (gpgme_tool_t gt, gpgme_ctx_t *ctx)
|
|||||||
void
|
void
|
||||||
gt_init (gpgme_tool_t gt)
|
gt_init (gpgme_tool_t gt)
|
||||||
{
|
{
|
||||||
memset (gt, '\0', sizeof (*gt));
|
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
|
|
||||||
|
memset (gt, '\0', sizeof (*gt));
|
||||||
|
|
||||||
err = _gt_gpgme_new (gt, >->ctx);
|
err = _gt_gpgme_new (gt, >->ctx);
|
||||||
if (err)
|
if (err)
|
||||||
log_error (1, err, "can't create gpgme context");
|
log_error (1, err, "can't create gpgme context");
|
||||||
@ -1776,6 +1784,19 @@ gt_get_sub_protocol (gpgme_tool_t gt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gpg_error_t
|
||||||
|
gt_set_pinentry_mode (gpgme_tool_t gt, gpgme_pinentry_mode_t mode, void *opaque)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
|
||||||
|
gpgme_set_passphrase_cb (gt->ctx, NULL, NULL);
|
||||||
|
err = gpgme_set_pinentry_mode (gt->ctx, mode);
|
||||||
|
if (!err && mode == GPGME_PINENTRY_MODE_LOOPBACK)
|
||||||
|
gpgme_set_passphrase_cb (gt->ctx, server_passphrase_cb, opaque);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
gt_set_armor (gpgme_tool_t gt, int armor)
|
gt_set_armor (gpgme_tool_t gt, int armor)
|
||||||
{
|
{
|
||||||
@ -2151,6 +2172,41 @@ server_write_data (void *hook, const void *buf, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpg_error_t
|
||||||
|
server_passphrase_cb (void *opaque, const char *uid_hint, const char *info,
|
||||||
|
int was_bad, int fd)
|
||||||
|
{
|
||||||
|
struct server *server = opaque;
|
||||||
|
gpg_error_t err;
|
||||||
|
unsigned char *buf = NULL;
|
||||||
|
size_t buflen = 0;
|
||||||
|
|
||||||
|
if (server && server->assuan_ctx)
|
||||||
|
{
|
||||||
|
if (uid_hint)
|
||||||
|
assuan_write_status (server->assuan_ctx, "USERID_HINT", uid_hint);
|
||||||
|
if (info)
|
||||||
|
assuan_write_status (server->assuan_ctx, "NEED_PASSPHRASE", info);
|
||||||
|
|
||||||
|
err = assuan_inquire (server->assuan_ctx, "PASSPHRASE",
|
||||||
|
&buf, &buflen, 100);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
err = gpg_error (GPG_ERR_NO_PASSPHRASE);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
/* We take care to always send a LF. */
|
||||||
|
if (gpgme_io_writen (fd, buf, buflen))
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
else if (!memchr (buf, '\n', buflen) && gpgme_io_writen (fd, "\n", 1))
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
}
|
||||||
|
free (buf);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Wrapper around assuan_command_parse_fd to also handle a
|
/* Wrapper around assuan_command_parse_fd to also handle a
|
||||||
"file=FILENAME" argument. On success either a filename is returned
|
"file=FILENAME" argument. On success either a filename is returned
|
||||||
at FILENAME or a file descriptor at RFD; the other one is set to
|
at FILENAME or a file descriptor at RFD; the other one is set to
|
||||||
@ -2367,6 +2423,39 @@ cmd_sub_protocol (assuan_context_t ctx, char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char hlp_pinentry_mode[] =
|
||||||
|
"PINENTRY_MODE <name>\n"
|
||||||
|
"\n"
|
||||||
|
"Set the pinentry mode to NAME. Allowedvalues for NAME are:\n"
|
||||||
|
" default - reset to the default of the engine,\n"
|
||||||
|
" ask - force the use of the pinentry,\n"
|
||||||
|
" cancel - emulate use of pinentry's cancel button,\n"
|
||||||
|
" error - return a pinentry error,\n"
|
||||||
|
" loopback - redirect pinentry queries to the caller.\n"
|
||||||
|
"Note that only recent versions of GPG support changing the pinentry mode.";
|
||||||
|
static gpg_error_t
|
||||||
|
cmd_pinentry_mode (assuan_context_t ctx, char *line)
|
||||||
|
{
|
||||||
|
struct server *server = assuan_get_pointer (ctx);
|
||||||
|
gpgme_pinentry_mode_t mode;
|
||||||
|
|
||||||
|
if (!line || !*line || !strcmp (line, "default"))
|
||||||
|
mode = GPGME_PINENTRY_MODE_DEFAULT;
|
||||||
|
else if (!strcmp (line, "ask"))
|
||||||
|
mode = GPGME_PINENTRY_MODE_ASK;
|
||||||
|
else if (!strcmp (line, "cancel"))
|
||||||
|
mode = GPGME_PINENTRY_MODE_CANCEL;
|
||||||
|
else if (!strcmp (line, "error"))
|
||||||
|
mode = GPGME_PINENTRY_MODE_ERROR;
|
||||||
|
else if (!strcmp (line, "loopback"))
|
||||||
|
mode = GPGME_PINENTRY_MODE_LOOPBACK;
|
||||||
|
else
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
return gt_set_pinentry_mode (server->gt, mode, server);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char hlp_armor[] =
|
static const char hlp_armor[] =
|
||||||
"ARMOR [true|false]\n"
|
"ARMOR [true|false]\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -3354,6 +3443,7 @@ register_commands (assuan_context_t ctx)
|
|||||||
{ "ENGINE", cmd_engine, hlp_engine },
|
{ "ENGINE", cmd_engine, hlp_engine },
|
||||||
{ "PROTOCOL", cmd_protocol, hlp_protocol },
|
{ "PROTOCOL", cmd_protocol, hlp_protocol },
|
||||||
{ "SUB_PROTOCOL", cmd_sub_protocol, hlp_sub_protocol },
|
{ "SUB_PROTOCOL", cmd_sub_protocol, hlp_sub_protocol },
|
||||||
|
{ "PINENTRY_MODE", cmd_pinentry_mode, hlp_pinentry_mode },
|
||||||
{ "ARMOR", cmd_armor, hlp_armor },
|
{ "ARMOR", cmd_armor, hlp_armor },
|
||||||
{ "TEXTMODE", cmd_textmode, hlp_textmode },
|
{ "TEXTMODE", cmd_textmode, hlp_textmode },
|
||||||
{ "INCLUDE_CERTS", cmd_include_certs, hlp_include_certs },
|
{ "INCLUDE_CERTS", cmd_include_certs, hlp_include_certs },
|
||||||
@ -3410,7 +3500,6 @@ register_commands (assuan_context_t ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: password callback can do INQUIRE. */
|
|
||||||
void
|
void
|
||||||
gpgme_server (gpgme_tool_t gt)
|
gpgme_server (gpgme_tool_t gt)
|
||||||
{
|
{
|
||||||
@ -3495,6 +3584,7 @@ static char args_doc[] = "COMMAND [OPTIONS...]";
|
|||||||
|
|
||||||
static struct argp_option options[] = {
|
static struct argp_option options[] = {
|
||||||
{ "server", 's', 0, 0, "Server mode" },
|
{ "server", 's', 0, 0, "Server mode" },
|
||||||
|
{ "gpg-binary", 501, "FILE", 0, "Use FILE for the GPG backend" },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3504,6 +3594,7 @@ static struct argp argp = { options, parse_options, args_doc, doc };
|
|||||||
struct args
|
struct args
|
||||||
{
|
{
|
||||||
enum { CMD_DEFAULT, CMD_SERVER } cmd;
|
enum { CMD_DEFAULT, CMD_SERVER } cmd;
|
||||||
|
const char *gpg_binary;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -3524,6 +3615,10 @@ parse_options (int key, char *arg, struct argp_state *state)
|
|||||||
case 's':
|
case 's':
|
||||||
args->cmd = CMD_SERVER;
|
args->cmd = CMD_SERVER;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 501:
|
||||||
|
args->gpg_binary = arg;
|
||||||
|
break;
|
||||||
#if 0
|
#if 0
|
||||||
case ARGP_KEY_ARG:
|
case ARGP_KEY_ARG:
|
||||||
if (state->arg_num >= 2)
|
if (state->arg_num >= 2)
|
||||||
@ -3548,6 +3643,7 @@ main (int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
struct args args;
|
struct args args;
|
||||||
struct gpgme_tool gt;
|
struct gpgme_tool gt;
|
||||||
|
gpg_error_t err;
|
||||||
|
|
||||||
#ifdef HAVE_SETLOCALE
|
#ifdef HAVE_SETLOCALE
|
||||||
setlocale (LC_ALL, "");
|
setlocale (LC_ALL, "");
|
||||||
@ -3565,6 +3661,18 @@ main (int argc, char *argv[])
|
|||||||
argp_parse (&argp, argc, argv, 0, 0, &args);
|
argp_parse (&argp, argc, argv, 0, 0, &args);
|
||||||
log_init ();
|
log_init ();
|
||||||
|
|
||||||
|
if (args.gpg_binary)
|
||||||
|
{
|
||||||
|
if (access (args.gpg_binary, X_OK))
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
else
|
||||||
|
err = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP,
|
||||||
|
args.gpg_binary, NULL);
|
||||||
|
if (err)
|
||||||
|
log_error (1, err, "error witching OpenPGP engine to '%s'",
|
||||||
|
args.gpg_binary);
|
||||||
|
}
|
||||||
|
|
||||||
gt_init (>);
|
gt_init (>);
|
||||||
|
|
||||||
switch (args.cmd)
|
switch (args.cmd)
|
||||||
|
@ -205,5 +205,8 @@ EXPORTS
|
|||||||
gpgme_set_global_flag @156
|
gpgme_set_global_flag @156
|
||||||
|
|
||||||
gpgme_io_writen @157
|
gpgme_io_writen @157
|
||||||
|
|
||||||
|
gpgme_set_pinentry_mode @158
|
||||||
|
|
||||||
; END
|
; END
|
||||||
|
|
||||||
|
@ -83,6 +83,8 @@ GPGME_1.1 {
|
|||||||
gpgme_set_global_flag;
|
gpgme_set_global_flag;
|
||||||
|
|
||||||
gpgme_io_writen;
|
gpgme_io_writen;
|
||||||
|
|
||||||
|
gpgme_set_pinentry_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user