From 8c09dd9989bcd434a8cb5997770cb8414b96bd5c Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 16 Aug 2016 18:53:42 +0200 Subject: [PATCH] core: New global flag "require-gnupg". * src/gpgme.c (gpgme_set_global_flag): Add flag. * src/engine.c (engine_minimal_version): New variable. (_gpgme_set_engine_minimal_version): New function. (gpgme_get_engine_info): Check that flag. * tests/run-keylist.c (main): New option --require-gnupg. Signed-off-by: Werner Koch --- NEWS | 2 ++ doc/gpgme.texi | 16 +++++++++++----- src/engine.c | 35 +++++++++++++++++++++++++++++++++++ src/engine.h | 2 ++ src/gpgme.c | 2 ++ tests/run-keylist.c | 10 +++++++++- 6 files changed, 61 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index e47ec91a..ce166874 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_] * Bindings for Python 3 are now included. + * New global flag "require-gnupg" to set a minimal gnupg version. + * Interface changes relative to the 1.6.0 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gpgme_pubkey_algo_string NEW. diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 8b0ec528..ac0fffab 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -678,12 +678,12 @@ as early as possible --- even before @code{gpgme_check_version}. The features are identified by the following values for @var{name}: @table @code -@item "debug" +@item debug To enable debugging use the string ``debug'' for @var{name} and @var{value} identical to the value used with the environment variable @code{GPGME_DEBUG}. -@item "disable-gpgconf" +@item disable-gpgconf Using this feature with any @var{value} disables the detection of the gpgconf program and thus forces GPGME to fallback into the simple OpenPGP only mode. It may be used to force the use of GnuPG-1 on @@ -691,8 +691,8 @@ systems which have both GPG versions installed. Note that in general the use of @code{gpgme_set_engine_info} is a better way to select a specific engine version. -@item "gpgconf-name" -@itemx "gpg-name" +@item gpgconf-name +@itemx gpg-name Set the name of the gpgconf respective gpg binary. The defaults are @code{GNU/GnuPG/gpgconf} and @code{GNU/GnuPG/gpg}. Under Unix the leading directory part is ignored. Under Windows the leading @@ -700,7 +700,13 @@ directory part is used as the default installation directory; the @code{.exe} suffix is added by GPGME. Use forward slashed even under Windows. -@item "w32-inst-dir" +@item require-gnupg +Set the mimimum version of the required GnuPG engine. If that version +is not met, GPGME fails early instead of trying to use the existant +version. The given version must be a string with major, minor, and +micro number. Example: "2.1.0". + +@item w32-inst-dir On Windows GPGME needs to know its installation directory to find its spawn helper. This is in general no problem because a DLL has this information. Some applications however link statically to GPGME and diff --git a/src/engine.c b/src/engine.c index a7c016f0..f428034d 100644 --- a/src/engine.c +++ b/src/engine.c @@ -63,6 +63,10 @@ static struct engine_ops *engine_ops[] = static gpgme_engine_info_t engine_info; DEFINE_STATIC_LOCK (engine_info_lock); +/* If non-NULL, the minimal version required for all engines. */ +static char *engine_minimal_version; + + /* Get the file name of the engine for PROTOCOL. */ static const char * @@ -178,6 +182,26 @@ _gpgme_engine_info_release (gpgme_engine_info_t info) } +/* This is an internal function to set a mimimal required version. + * This function must only be called by gpgme_set_global_flag. + * Returns 0 on success. */ +int +_gpgme_set_engine_minimal_version (const char *value) +{ + free (engine_minimal_version); + if (value) + { + engine_minimal_version = strdup (value); + return !engine_minimal_version; + } + else + { + engine_minimal_version = NULL; + return 0; + } +} + + /* Get the information about the configured and installed engines. A pointer to the first engine in the statically allocated linked list is returned in *INFO. If an error occurs, it is returned. The @@ -229,6 +253,17 @@ gpgme_get_engine_info (gpgme_engine_info_t *info) if (!*lastp && !err) err = gpg_error_from_syserror (); + /* Check against the optional minimal engine version. */ + if (!err && version && engine_minimal_version + && !_gpgme_compare_versions (version, engine_minimal_version)) + { +#if GPG_ERROR_VERSION_NUMBER < 0x011900 /* 1.25 */ + err = gpg_error (GPG_ERR_NO_ENGINE); +#else + err = gpg_error (GPG_ERR_ENGINE_TOO_OLD); +#endif + } + /* Now set the dummy version for pseudo engines. */ if (!err && !version) { diff --git a/src/engine.h b/src/engine.h index 238a21c0..b713d961 100644 --- a/src/engine.h +++ b/src/engine.h @@ -38,6 +38,8 @@ typedef gpgme_error_t (*engine_command_handler_t) (void *priv, typedef gpgme_error_t (*engine_assuan_result_cb_t) (void *priv, gpgme_error_t result); +/* Helper for gpgme_set_global_flag. */ +int _gpgme_set_engine_minimal_version (const char *value); /* Get a deep copy of the engine info and return it in INFO. */ gpgme_error_t _gpgme_engine_info_copy (gpgme_engine_info_t *r_info); diff --git a/src/gpgme.c b/src/gpgme.c index e0cd9b05..d59f8080 100644 --- a/src/gpgme.c +++ b/src/gpgme.c @@ -71,6 +71,8 @@ gpgme_set_global_flag (const char *name, const char *value) _gpgme_dirinfo_disable_gpgconf (); return 0; } + else if (!strcmp (name, "require-gnupg")) + return _gpgme_set_engine_minimal_version (value); else if (!strcmp (name, "gpgconf-name")) return _gpgme_set_default_gpgconf_name (value); else if (!strcmp (name, "gpg-name")) diff --git a/tests/run-keylist.c b/tests/run-keylist.c index fc0f0660..cc4c3545 100644 --- a/tests/run-keylist.c +++ b/tests/run-keylist.c @@ -54,6 +54,7 @@ show_usage (int ex) " --validate use GPGME_KEYLIST_MODE_VALIDATE\n" " --import import all keys\n" " --offline use offline mode\n" + " --require-gnupg required at least the given GnuPG version\n" , stderr); exit (ex); } @@ -149,9 +150,16 @@ main (int argc, char **argv) offline = 1; argc--; argv++; } + else if (!strcmp (*argv, "--require-gnupg")) + { + argc--; argv++; + if (!argc) + show_usage (1); + gpgme_set_global_flag ("require-gnupg", *argv); + argc--; argv++; + } else if (!strncmp (*argv, "--", 2)) show_usage (1); - } if (argc > 1)