core: New global flag "require-gnupg".
authorWerner Koch <wk@gnupg.org>
Tue, 16 Aug 2016 16:53:42 +0000 (18:53 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 16 Aug 2016 16:53:42 +0000 (18:53 +0200)
* 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 <wk@gnupg.org>
NEWS
doc/gpgme.texi
src/engine.c
src/engine.h
src/gpgme.c
tests/run-keylist.c

diff --git a/NEWS b/NEWS
index e47ec91..ce16687 100644 (file)
--- 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.
index 8b0ec52..ac0fffa 100644 (file)
@@ -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
index a7c016f..f428034 100644 (file)
@@ -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;
+
+
 \f
 /* 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)
             {
index 238a21c..b713d96 100644 (file)
@@ -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);
index e0cd9b0..d59f808 100644 (file)
@@ -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"))
index fc0f066..cc4c354 100644 (file)
@@ -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)