From 61a0d92b679f248505f1bf16386bc41a5bf2ba1d Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 7 Feb 2013 20:59:16 +0100 Subject: [PATCH] Add public function gpgme_set_pinentry_mode. * src/gpgme.c (gpgme_set_pinentry_mode): New. * src/gpgme.h.in (gpgme_pinentry_t): New. (gpgme_set_pinentry_mode): New. * src/context.h (struct gpgme_context): Add field pinentry_mode. * src/engine-backend.h (struct engine_ops): Add field set_pinentry_mode. * src/engine-gpg.c (struct engine_gpg): Add field pinentry_mode. (build_argv): Implement pinentry_mode. (gpg_set_pinentry_mode): New. (_gpgme_engine_ops_gpg): Register gpg_set_pinentry_mode. -- Note that this new fucntion may only be used with gpg 2.1. --- NEWS | 8 ++++++++ src/context.h | 3 +++ src/engine-assuan.c | 4 +++- src/engine-backend.h | 3 +++ src/engine-g13.c | 2 ++ src/engine-gpg.c | 43 ++++++++++++++++++++++++++++++++++++++++++- src/engine-gpgconf.c | 5 ++++- src/engine-gpgsm.c | 3 ++- src/engine-uiserver.c | 2 ++ src/engine.c | 13 +++++++++++++ src/engine.h | 3 +++ src/gpgme.c | 31 +++++++++++++++++++++++++++++-- src/gpgme.h.in | 18 +++++++++++++++++- src/op-support.c | 9 +++++++++ 14 files changed, 140 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index b4b30869..7499b14f 100644 --- a/NEWS +++ b/NEWS @@ -3,7 +3,15 @@ Noteworthy changes in version 1.3.3 (unreleased) * Interface changes relative to the 1.3.1 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + gpgme_io_writen NEW. gpgme_set_global_flag NEW. + gpgme_set_pinentry_mode NEW. + gpgme_pinentry_mode_t NEW. + GPGME_PINENTRY_MODE_DEFAULT NEW. + GPGME_PINENTRY_MODE_ASK NEW. + GPGME_PINENTRY_MODE_CANCEL NEW. + GPGME_PINENTRY_MODE_ERROR NEW. + GPGME_PINENTRY_MODE_LOOPBACK NEW. Noteworthy changes in version 1.3.2 (2012-05-02) diff --git a/src/context.h b/src/context.h index d984324b..e9214368 100644 --- a/src/context.h +++ b/src/context.h @@ -101,6 +101,9 @@ struct gpgme_context /* Flags for keylist mode. */ gpgme_keylist_mode_t keylist_mode; + /* The current pinnetry mode. */ + gpgme_pinentry_mode_t pinentry_mode; + /* Number of certs to be included. */ unsigned int include_certs; diff --git a/src/engine-assuan.c b/src/engine-assuan.c index a3c9e92f..5ef30479 100644 --- a/src/engine-assuan.c +++ b/src/engine-assuan.c @@ -781,5 +781,7 @@ struct engine_ops _gpgme_engine_ops_assuan = llass_set_io_cbs, llass_io_event, llass_cancel, - llass_cancel_op + llass_cancel_op, + NULL, /* passwd */ + NULL /* set_pinentry_mode */ }; diff --git a/src/engine-backend.h b/src/engine-backend.h index 1adac92b..a4c0eb27 100644 --- a/src/engine-backend.h +++ b/src/engine-backend.h @@ -121,6 +121,9 @@ struct engine_ops /* Change the passphrase for KEY. */ gpgme_error_t (*passwd) (void *engine, gpgme_key_t key, unsigned int flags); + + /* Set the pinentry mode. */ + gpgme_error_t (*set_pinentry_mode) (void *engine, gpgme_pinentry_mode_t mode); }; diff --git a/src/engine-g13.c b/src/engine-g13.c index 9231a9ac..de0aac80 100644 --- a/src/engine-g13.c +++ b/src/engine-g13.c @@ -798,4 +798,6 @@ struct engine_ops _gpgme_engine_ops_g13 = g13_io_event, g13_cancel, g13_cancel_op, + NULL, /* passwd */ + NULL /* set_pinentry_mode */ }; diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 825a4503..3f025030 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -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; @@ -769,6 +770,8 @@ 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 */ @@ -818,6 +821,32 @@ build_argv (engine_gpg_t gpg) } 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"); @@ -2348,6 +2377,17 @@ 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 = { @@ -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 }; diff --git a/src/engine-gpgconf.c b/src/engine-gpgconf.c index 96c6b3db..fec0fc34 100644 --- a/src/engine-gpgconf.c +++ b/src/engine-gpgconf.c @@ -925,5 +925,8 @@ struct engine_ops _gpgme_engine_ops_gpgconf = gpgconf_conf_save, gpgconf_set_io_cbs, NULL, /* io_event */ - NULL /* cancel */ + NULL, /* cancel */ + NULL, /* cancel_op */ + NULL, /* passwd */ + NULL /* set_pinentry_mode */ }; diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c index c4272a42..79adde2c 100644 --- a/src/engine-gpgsm.c +++ b/src/engine-gpgsm.c @@ -1986,5 +1986,6 @@ struct engine_ops _gpgme_engine_ops_gpgsm = gpgsm_io_event, gpgsm_cancel, NULL, /* cancel_op */ - gpgsm_passwd + gpgsm_passwd, + NULL /* set_pinentry_mode */ }; diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c index 92aebbbc..abdd79ed 100644 --- a/src/engine-uiserver.c +++ b/src/engine-uiserver.c @@ -1339,4 +1339,6 @@ struct engine_ops _gpgme_engine_ops_uiserver = uiserver_io_event, uiserver_cancel, NULL /* cancel_op */ + NULL, /* passwd */ + NULL /* set_pinentry_mode */ }; diff --git a/src/engine.c b/src/engine.c index d74f186f..09f379c7 100644 --- a/src/engine.c +++ b/src/engine.c @@ -923,3 +923,16 @@ _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key, return (*engine->ops->passwd) (engine->engine, key, flags); } + +/* Set the pinentry mode for ENGINE to MODE. */ +gpgme_error_t +_gpgme_engine_set_pinentry_mode (engine_t engine, gpgme_pinentry_mode_t mode) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->set_pinentry_mode) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->set_pinentry_mode) (engine->engine, mode); +} diff --git a/src/engine.h b/src/engine.h index e8683076..a0287add 100644 --- a/src/engine.h +++ b/src/engine.h @@ -160,5 +160,8 @@ gpgme_error_t _gpgme_engine_cancel_op (engine_t engine); gpgme_error_t _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key, unsigned int flags); +gpgme_error_t _gpgme_engine_set_pinentry_mode (engine_t engine, + gpgme_pinentry_mode_t mode); + #endif /* ENGINE_H */ diff --git a/src/gpgme.c b/src/gpgme.c index 79895db2..76c13b16 100644 --- a/src/gpgme.c +++ b/src/gpgme.c @@ -53,8 +53,8 @@ DEFINE_STATIC_LOCK (result_ref_lock); /* Set the global flag NAME to VALUE. Return 0 on success. Note that - this function does use gpgme_error and thus a non-zero return value - merely means "error". Certain flags may be set before + this function does not use gpgme_error and thus a non-zero return + value merely means "error". Certain flags may be set before gpgme_check_version is called. See the manual for a description of supported flags. The caller must assure that this function is called only by one thread at a time. */ @@ -512,6 +512,33 @@ gpgme_get_keylist_mode (gpgme_ctx_t ctx) } +/* Set the pinentry mode for CTX to MODE. */ +gpgme_error_t +gpgme_set_pinentry_mode (gpgme_ctx_t ctx, gpgme_keylist_mode_t mode) +{ + TRACE1 (DEBUG_CTX, "gpgme_set_pinentry_mode", ctx, "pinentry_mode=%u", + (unsigned int)mode); + + if (!ctx) + return gpg_error (GPG_ERR_INV_VALUE); + + switch (mode) + { + case GPGME_PINENTRY_MODE_DEFAULT: + case GPGME_PINENTRY_MODE_ASK: + case GPGME_PINENTRY_MODE_CANCEL: + case GPGME_PINENTRY_MODE_ERROR: + case GPGME_PINENTRY_MODE_LOOPBACK: + break; + default: + return gpg_error (GPG_ERR_INV_VALUE); + } + + ctx->pinentry_mode = mode; + return 0; +} + + /* This function sets a callback function to be used to pass a passphrase to gpg. */ void diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 27ef195b..4ec2367b 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1,7 +1,7 @@ /* gpgme.h - Public interface to GnuPG Made Easy. -*- c -*- Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 - 2010, 2011, 2012 g10 Code GmbH + 2010, 2011, 2012, 2013 g10 Code GmbH This file is part of GPGME. @@ -353,6 +353,18 @@ gpgme_protocol_t; typedef unsigned int gpgme_keylist_mode_t; + +/* The pinentry modes. */ +typedef enum + { + GPGME_PINENTRY_MODE_DEFAULT = 0, + GPGME_PINENTRY_MODE_ASK = 1, + GPGME_PINENTRY_MODE_CANCEL = 2, + GPGME_PINENTRY_MODE_ERROR = 3, + GPGME_PINENTRY_MODE_LOOPBACK = 4 + } +gpgme_pinentry_mode_t; + /* The available export mode flags. */ #define GPGME_EXPORT_MODE_EXTERN 2 @@ -859,6 +871,10 @@ gpgme_error_t gpgme_set_keylist_mode (gpgme_ctx_t ctx, /* Get keylist mode in CTX. */ gpgme_keylist_mode_t gpgme_get_keylist_mode (gpgme_ctx_t ctx); +/* Set the pinentry mode for CTX to MODE. */ +gpgme_error_t gpgme_set_pinentry_mode (gpgme_ctx_t ctx, + gpgme_pinentry_mode_t mode); + /* Set the passphrase callback function in CTX to CB. HOOK_VALUE is passed as first argument to the passphrase callback function. */ void gpgme_set_passphrase_cb (gpgme_ctx_t ctx, diff --git a/src/op-support.c b/src/op-support.c index 6a0817ce..edd317d1 100644 --- a/src/op-support.c +++ b/src/op-support.c @@ -134,6 +134,15 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type) #endif if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED) err = 0; + + if (!err) + { + err = _gpgme_engine_set_pinentry_mode (ctx->engine, + ctx->pinentry_mode); + if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED) + err = 0; + } + if (err) { _gpgme_engine_release (ctx->engine);