[git] GnuPG - branch, master, updated. gnupg-2.1.10-98-g2aa42ba

by Werner Koch cvs at cvs.gnupg.org
Fri Jan 8 10:38:16 CET 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  2aa42baaf3dd7c3ae613ae0c61760a17c8adfcd0 (commit)
       via  4d7ac43ff71fdadfd2e04621f74840a82fbe788a (commit)
      from  496643291e1e346434e9c98405c5a370957eb7d3 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 2aa42baaf3dd7c3ae613ae0c61760a17c8adfcd0
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Jan 8 10:33:19 2016 +0100

    Print warnings if old daemon versions are used.
    
    * common/status.h (STATUS_WARNING): New.
    * g10/call-agent.c (warn_version_mismatch): New.
    (start_agent): Call warn function.
    * g10/call-dirmngr.c: Include status.h.
    (warn_version_mismatch): New.
    (create_context): Call warn function.
    * sm/call-agent.c (warn_version_mismatch): New.
    (start_agent): Call warn function.
    (gpgsm_agent_learn): Call warn function.
    * sm/call-dirmngr.c (warn_version_mismatch): New.
    (prepare_dirmngr): Call warn function.
    --
    
    We have seen too often bug reports which are due to still running old
    versions of the daemons.  To catch this problematic use we now print
    warning messages and also provide the warning via the status
    interface.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/common/status.h b/common/status.h
index 509e044..e50827f 100644
--- a/common/status.h
+++ b/common/status.h
@@ -141,6 +141,7 @@ enum
     STATUS_PLAINTEXT_FOLLOWS,   /* Used by g13-syshelp  */
 
     STATUS_ERROR,
+    STATUS_WARNING,
     STATUS_SUCCESS,
     STATUS_FAILURE,
 
diff --git a/doc/DETAILS b/doc/DETAILS
index 7c3e67c..69c2e5b 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -840,7 +840,12 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
     should not contain spaces.  The error code is a either a string
     commencing with a letter or such a string prefixed with a
     numerical error code and an underscore; e.g.: "151011327_EOF".
-
+*** WARNING <location> <error code> [<text>]
+    This is a generic warning status message, it might be followed by
+    error location specific data. <error code> and <location>
+    should not contain spaces.  The error code is a either a string
+    commencing with a letter or such a string prefixed with a
+    numerical error code and an underscore; e.g.: "151011327_EOF".
 *** SUCCESS [<location>]
     Postive confirmation that an operation succeeded.  It is used
     similar to ISO-C's EXIT_SUCCESS.  <location> is optional but if
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 3600579..83fabcc 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -253,6 +253,40 @@ check_hijacking (assuan_context_t ctx)
 
 
 
+/* Print a warning if the server's version number is less than our
+   version number.  Returns an error code on a connection problem.  */
+static gpg_error_t
+warn_version_mismatch (assuan_context_t ctx, const char *servername, int mode)
+{
+  gpg_error_t err;
+  char *serverversion;
+  const char *myversion = strusage (13);
+
+  err = get_assuan_server_version (ctx, mode, &serverversion);
+  if (err)
+    log_error (_("error getting version from '%s': %s\n"),
+               servername, gpg_strerror (err));
+  else if (!compare_version_strings (serverversion, myversion))
+    {
+      char *warn;
+
+      warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"),
+                           servername, serverversion, myversion);
+      if (!warn)
+        err = gpg_error_from_syserror ();
+      else
+        {
+          log_info (_("WARNING: %s\n"), warn);
+          write_status_strings (STATUS_WARNING, "server_version_mismatch 0",
+                                " ", warn, NULL);
+          xfree (warn);
+        }
+    }
+  xfree (serverversion);
+  return err;
+}
+
+
 /* Try to connect to the agent via socket or fork it off and work by
    pipes.  Handle the server's initial greeting */
 static int
@@ -286,7 +320,8 @@ start_agent (ctrl_t ctrl, int for_card)
               log_info (_("no gpg-agent running in this session\n"));
             }
         }
-      else if (!rc)
+      else if (!rc
+               && !(rc = warn_version_mismatch (agent_ctx, GPG_AGENT_NAME, 0)))
         {
           /* Tell the agent that we support Pinentry notifications.
              No error checking so that it will work also with older
@@ -324,9 +359,12 @@ start_agent (ctrl_t ctrl, int for_card)
       struct agent_card_info_s info;
 
       memset (&info, 0, sizeof info);
-      rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
-                            NULL, NULL, NULL, NULL,
-                            learn_status_cb, &info);
+
+      rc = warn_version_mismatch (agent_ctx, SCDAEMON_NAME, 2);
+      if (!rc)
+        rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
+                              NULL, NULL, NULL, NULL,
+                              learn_status_cb, &info);
       if (rc)
         {
           switch (gpg_err_code (rc))
diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c
index b1c856d..360e127 100644
--- a/g10/call-dirmngr.c
+++ b/g10/call-dirmngr.c
@@ -38,6 +38,7 @@
 #include "i18n.h"
 #include "asshelp.h"
 #include "keyserver.h"
+#include "status.h"
 #include "call-dirmngr.h"
 
 
@@ -132,6 +133,40 @@ gpg_dirmngr_deinit_session_data (ctrl_t ctrl)
 }
 
 
+/* Print a warning if the server's version number is less than our
+   version number.  Returns an error code on a connection problem.  */
+static gpg_error_t
+warn_version_mismatch (assuan_context_t ctx, const char *servername)
+{
+  gpg_error_t err;
+  char *serverversion;
+  const char *myversion = strusage (13);
+
+  err = get_assuan_server_version (ctx, 0, &serverversion);
+  if (err)
+    log_error (_("error getting version from '%s': %s\n"),
+               servername, gpg_strerror (err));
+  else if (!compare_version_strings (serverversion, myversion))
+    {
+      char *warn;
+
+      warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"),
+                           servername, serverversion, myversion);
+      if (!warn)
+        err = gpg_error_from_syserror ();
+      else
+        {
+          log_info (_("WARNING: %s\n"), warn);
+          write_status_strings (STATUS_WARNING, "server_version_mismatch 0",
+                                " ", warn, NULL);
+          xfree (warn);
+        }
+    }
+  xfree (serverversion);
+  return err;
+}
+
+
 /* Try to connect to the Dirmngr via a socket or spawn it if possible.
    Handle the server's initial greeting and set global options.  */
 static gpg_error_t
@@ -157,7 +192,7 @@ create_context (ctrl_t ctrl, assuan_context_t *r_ctx)
           log_info (_("no dirmngr running in this session\n"));
         }
     }
-  else if (!err)
+  else if (!err && !(err = warn_version_mismatch (ctx, DIRMNGR_NAME)))
     {
       char *line;
 
diff --git a/sm/call-agent.c b/sm/call-agent.c
index b881fb8..c7d4c5a 100644
--- a/sm/call-agent.c
+++ b/sm/call-agent.c
@@ -76,6 +76,41 @@ struct import_key_parm_s
 
 
 

+/* Print a warning if the server's version number is less than our
+   version number.  Returns an error code on a connection problem.  */
+static gpg_error_t
+warn_version_mismatch (ctrl_t ctrl, assuan_context_t ctx,
+                       const char *servername, int mode)
+{
+  gpg_error_t err;
+  char *serverversion;
+  const char *myversion = strusage (13);
+
+  err = get_assuan_server_version (ctx, mode, &serverversion);
+  if (err)
+    log_error (_("error getting version from '%s': %s\n"),
+               servername, gpg_strerror (err));
+  else if (!compare_version_strings (serverversion, myversion))
+    {
+      char *warn;
+
+      warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"),
+                           servername, serverversion, myversion);
+      if (!warn)
+        err = gpg_error_from_syserror ();
+      else
+        {
+          log_info (_("WARNING: %s\n"), warn);
+          gpgsm_status2 (ctrl, STATUS_WARNING, "server_version_mismatch 0",
+                         warn, NULL);
+          xfree (warn);
+        }
+    }
+  xfree (serverversion);
+  return err;
+}
+
+
 /* Try to connect to the agent via socket or fork it off and work by
    pipes.  Handle the server's initial greeting */
 static int
@@ -108,7 +143,8 @@ start_agent (ctrl_t ctrl)
               log_info (_("no gpg-agent running in this session\n"));
             }
         }
-      else if (!rc)
+      else if (!rc && !(rc = warn_version_mismatch (ctrl, agent_ctx,
+                                                    GPG_AGENT_NAME, 0)))
         {
           /* Tell the agent that we support Pinentry notifications.  No
              error checking so that it will work also with older
@@ -919,6 +955,10 @@ gpgsm_agent_learn (ctrl_t ctrl)
   if (rc)
     return rc;
 
+  rc = warn_version_mismatch (ctrl, agent_ctx, SCDAEMON_NAME, 2);
+  if (rc)
+    return rc;
+
   init_membuf (&data, 4096);
   learn_parm.error = 0;
   learn_parm.ctrl = ctrl;
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
index 379d7e9..881c484 100644
--- a/sm/call-dirmngr.c
+++ b/sm/call-dirmngr.c
@@ -149,6 +149,41 @@ get_membuf (struct membuf *mb, size_t *len)
 }
 
 
+/* Print a warning if the server's version number is less than our
+   version number.  Returns an error code on a connection problem.  */
+static gpg_error_t
+warn_version_mismatch (ctrl_t ctrl, assuan_context_t ctx,
+                       const char *servername, int mode)
+{
+  gpg_error_t err;
+  char *serverversion;
+  const char *myversion = strusage (13);
+
+  err = get_assuan_server_version (ctx, mode, &serverversion);
+  if (err)
+    log_error (_("error getting version from '%s': %s\n"),
+               servername, gpg_strerror (err));
+  else if (!compare_version_strings (serverversion, myversion))
+    {
+      char *warn;
+
+      warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"),
+                           servername, serverversion, myversion);
+      if (!warn)
+        err = gpg_error_from_syserror ();
+      else
+        {
+          log_info (_("WARNING: %s\n"), warn);
+          gpgsm_status2 (ctrl, STATUS_WARNING, "server_version_mismatch 0",
+                         warn, NULL);
+          xfree (warn);
+        }
+    }
+  xfree (serverversion);
+  return err;
+}
+
+
 /* This function prepares the dirmngr for a new session.  The
    audit-events option is used so that other dirmngr clients won't get
    disturbed by such events.  */
@@ -158,6 +193,9 @@ prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
   struct keyserver_spec *server;
 
   if (!err)
+    err = warn_version_mismatch (ctrl, ctx, DIRMNGR_NAME, 0);
+
+  if (!err)
     {
       err = assuan_transact (ctx, "OPTION audit-events=1",
 			     NULL, NULL, NULL, NULL, NULL, NULL);

commit 4d7ac43ff71fdadfd2e04621f74840a82fbe788a
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Jan 8 08:58:21 2016 +0100

    common: New function compare_version_strings.
    
    * common/stringhelp.c (parse_version_number): New.
    (parse_version_string): New.
    (compare_version_strings): New.
    * common/t-stringhelp.c (test_compare_version_strings): New.
    (main): Call test.  Return ERRCOUNT instead of 0.
    --
    
    The code for that function is based on code from libgcrypt.  Similar
    code is in all GnuPG related libraries this function is
    a candidates for inclusion in libgpg-error.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/common/stringhelp.c b/common/stringhelp.c
index e8b990a..8b47a1c 100644
--- a/common/stringhelp.c
+++ b/common/stringhelp.c
@@ -1329,6 +1329,91 @@ strtokenize (const char *string, const char *delim)
 }
 
 
+

+/* Version number parsing.  */
+
+/* This function parses the first portion of the version number S and
+   stores it in *NUMBER.  On success, this function returns a pointer
+   into S starting with the first character, which is not part of the
+   initial number portion; on failure, NULL is returned.  */
+static const char*
+parse_version_number (const char *s, int *number)
+{
+  int val = 0;
+
+  if (*s == '0' && digitp (s+1))
+    return NULL;  /* Leading zeros are not allowed.  */
+  for (; digitp (s); s++)
+    {
+      val *= 10;
+      val += *s - '0';
+    }
+  *number = val;
+  return val < 0 ? NULL : s;
+}
+
+
+/* This function breaks up the complete string-representation of the
+   version number S, which is of the following struture: <major
+   number>.<minor number>.<micro number><patch level>.  The major,
+   minor and micro number components will be stored in *MAJOR, *MINOR
+   and *MICRO.
+
+   On success, the last component, the patch level, will be returned;
+   in failure, NULL will be returned.  */
+static const char *
+parse_version_string (const char *s, int *major, int *minor, int *micro)
+{
+  s = parse_version_number (s, major);
+  if (!s || *s != '.')
+    return NULL;
+  s++;
+  s = parse_version_number (s, minor);
+  if (!s)
+    return NULL;
+  if (*s == '.')
+    {
+      s++;
+      s = parse_version_number (s, micro);
+      if (!s)
+        return NULL;
+    }
+  else
+    *micro = 0;
+  return s;  /* Patchlevel.  */
+}
+
+
+/* Check that the version string MY_VERSION is greater or equal than
+   REQ_VERSION.  Returns true if the condition is satisfied or false
+   if not.  This works with 3 part and two part version strings; for a
+   two part version string the micor part is assumed to be 0.  */
+int
+compare_version_strings (const char *my_version, const char *req_version)
+{
+  int my_major, my_minor, my_micro;
+  int rq_major, rq_minor, rq_micro;
+
+  if (!my_version || !req_version)
+    return 0;
+
+  if (!parse_version_string (my_version, &my_major, &my_minor, &my_micro))
+    return 0;
+  if (!parse_version_string(req_version, &rq_major, &rq_minor, &rq_micro))
+    return 0;
+
+  if (my_major > rq_major
+      || (my_major == rq_major && my_minor > rq_minor)
+      || (my_major == rq_major && my_minor == rq_minor
+	  && my_micro >= rq_micro))
+    {
+      return 1;
+    }
+  return 0;
+}
+
+
+

 /* Format a string so that it fits within about TARGET_COLS columns.
    If IN_PLACE is 0, then TEXT is copied to a new buffer, which is
    returned.  Otherwise, TEXT is modified in place and returned.
diff --git a/common/stringhelp.h b/common/stringhelp.h
index c813662..d9225a3 100644
--- a/common/stringhelp.h
+++ b/common/stringhelp.h
@@ -148,6 +148,9 @@ char **strsplit (char *string, char delim, char replacement, int *count);
 /* Tokenize STRING using the set of delimiters in DELIM.  */
 char **strtokenize (const char *string, const char *delim);
 
+/* Return True if MYVERSION is greater or equal than REQ_VERSION.  */
+int compare_version_strings (const char *my_version, const char *req_version);
+
 /* Format a string so that it fits within about TARGET_COLS columns.  */
 char *format_text (char *text, int in_place, int target_cols, int max_cols);
 
diff --git a/common/t-stringhelp.c b/common/t-stringhelp.c
index af79cb5..b4a41ac 100644
--- a/common/t-stringhelp.c
+++ b/common/t-stringhelp.c
@@ -705,6 +705,7 @@ stresc (char *s)
   return p;
 }
 
+
 static void
 test_format_text (void)
 {
@@ -813,6 +814,65 @@ test_format_text (void)
     fail(0);
 }
 
+
+static void
+test_compare_version_strings (void)
+{
+  struct { const char *a; const char *b; int okay; } tests[] = {
+    { "1.0.0",   "1.0.0", 1 },
+    { "1.0.0-",  "1.0.0", 1 },
+    { "1.0.0-1", "1.0.0", 1 },
+    { "1.0.0.1", "1.0.0", 1 },
+    { "1.0.0",   "1.0.1", 0 },
+    { "1.0.0-",  "1.0.1", 0 },
+    { "1.0.0-1", "1.0.1", 0 },
+    { "1.0.0.1", "1.0.1", 0 },
+    { "1.0.0",   "1.1.0", 0 },
+    { "1.0.0-",  "1.1.0", 0 },
+    { "1.0.0-1", "1.1.0", 0 },
+    { "1.0.0.1", "1.1.0", 0 },
+
+    { "1.0.0",   "1.0.0-", 1 },
+    { "1.0.0",   "1.0.0-1", 1 },
+    { "1.0.0",   "1.0.0.1", 1 },
+    { "1.1.0",   "1.0.0", 1 },
+    { "1.1.1",   "1.1.0", 1 },
+    { "1.1.2",   "1.1.2", 1 },
+    { "1.1.2",   "1.0.2", 1 },
+    { "1.1.2",   "0.0.2", 1 },
+    { "1.1.2",   "1.1.3", 0 },
+
+    { "0.99.1",  "0.9.9", 1 },
+    { "0.9.1",   "0.91.0", 0 },
+
+    { "1.5.3",   "1.5",  1 },
+    { "1.5.0",   "1.5",  1 },
+    { "1.4.99",  "1.5",  0 },
+    { "1.5",     "1.4.99",  1 },
+    { "1.5",     "1.5.0",  1 },
+    { "1.5",     "1.5.1",  0 },
+
+    { "1.5.3-x17",   "1.5-23",  1 },
+
+    { "1.5.3a",   "1.5.3",  1 },
+    { "1.5.3a",   "1.5.3b",  1 },
+
+    { NULL, NULL, 0 }
+  };
+  int idx;
+  int res;
+
+  for (idx=0; idx < DIM(tests); idx++)
+    {
+      res = compare_version_strings (tests[idx].a, tests[idx].b);
+      /* printf ("test %d: '%s'  '%s'  %d  ->  %d\n", */
+      /*         idx, tests[idx].a, tests[idx].b, tests[idx].okay, res); */
+      if (res != tests[idx].okay)
+        fail (idx);
+    }
+}
+
+
 int
 main (int argc, char **argv)
 {
@@ -827,8 +887,9 @@ main (int argc, char **argv)
   test_make_absfilename_try ();
   test_strsplit ();
   test_strtokenize ();
+  test_compare_version_strings ();
   test_format_text ();
 
   xfree (home_buffer);
-  return 0;
+  return !!errcount;
 }

-----------------------------------------------------------------------

Summary of changes:
 common/status.h       |  1 +
 common/stringhelp.c   | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++
 common/stringhelp.h   |  3 ++
 common/t-stringhelp.c | 63 +++++++++++++++++++++++++++++++++++++-
 doc/DETAILS           |  7 ++++-
 g10/call-agent.c      | 46 +++++++++++++++++++++++++---
 g10/call-dirmngr.c    | 37 +++++++++++++++++++++-
 sm/call-agent.c       | 42 ++++++++++++++++++++++++-
 sm/call-dirmngr.c     | 38 +++++++++++++++++++++++
 9 files changed, 314 insertions(+), 8 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list