[git] GnuPG - branch, master, updated. gnupg-2.1.15-380-g52c10a2

by Werner Koch cvs at cvs.gnupg.org
Wed Nov 16 21:25:27 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  52c10a280af6ce06eb1732ff35b095f2b8d24b9f (commit)
       via  4839e6d002a8ad1f7d3260792c3c9641e258f342 (commit)
      from  c4506a3f15bba5d257cb4c6738800c5e00ecc9a2 (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 52c10a280af6ce06eb1732ff35b095f2b8d24b9f
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Nov 16 21:22:39 2016 +0100

    dirmngr: Add command to only load the swdb.
    
    * dirmngr/loadswdb.c: New.
    * dirmngr/Makefile.am (dirmngr_SOURCES): Add that file.
    * dirmngr/server.c: Remove includes cpparray.h and exectool.h.
    (cmd_loadswdb): New.
    (parse_version_number,parse_version_string): Remove.
    (my_mktmpdir, cmp_version): Remove.
    (fetch_into_tmpdir): Remove.
    (struct verify_swdb_parm_s): Remove.
    (verify_swdb_status_cb): Remove.
    (cmd_versioncheck): Remove.
    (register_commands): Register LOADSWDB.  Remove VERSIONCHECK.
    --
    
    This change is required to to the new design where gpgconf does the
    version check w/o network access and only dirmngr is responsible for
    getting the swdb.
    
    In the next installment the loading will be triggered as needed.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am
index bd70c8c..2a18a50 100644
--- a/dirmngr/Makefile.am
+++ b/dirmngr/Makefile.am
@@ -56,6 +56,7 @@ noinst_HEADERS = dirmngr.h crlcache.h crlfetch.h misc.h
 
 dirmngr_SOURCES = dirmngr.c dirmngr.h server.c crlcache.c crlfetch.c	\
 	certcache.c certcache.h \
+	loadswdb.c \
 	cdb.h cdblib.c misc.c dirmngr-err.h  \
 	ocsp.c ocsp.h validate.c validate.h  \
 	dns-stuff.c dns-stuff.h \
diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h
index 107059d..42b3b2b 100644
--- a/dirmngr/dirmngr.h
+++ b/dirmngr/dirmngr.h
@@ -206,5 +206,8 @@ gpg_error_t dirmngr_status_help (ctrl_t ctrl, const char *text);
 gpg_error_t dirmngr_tick (ctrl_t ctrl);
 
 
+/*-- loadswdb.c --*/
+gpg_error_t dirmngr_load_swdb (ctrl_t ctrl, int force);
+
 
 #endif /*DIRMNGR_H*/
diff --git a/dirmngr/loadswdb.c b/dirmngr/loadswdb.c
new file mode 100644
index 0000000..57a7e04
--- /dev/null
+++ b/dirmngr/loadswdb.c
@@ -0,0 +1,358 @@
+/* loadswdb.c - Load the swdb file from versions.gnupg.org
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dirmngr.h"
+#include "../common/ccparray.h"
+#include "../common/exectool.h"
+#include "misc.h"
+#include "ks-engine.h"
+
+
+/* Get the time from the current swdb file and store it at R_TIME.  If
+ * the file does not exist 0 is stored at R_TIME.  The function
+ * returns 0 on sucess or an error code.  */
+static gpg_error_t
+time_of_saved_swdb (const char *fname, time_t *r_time)
+{
+  gpg_error_t err;
+  estream_t fp = NULL;
+  char *line = NULL;
+  size_t length_of_line = 0;
+  size_t  maxlen;
+  ssize_t len;
+  char *fields[2];
+  time_t t = (time_t)(-1);
+
+  *r_time = 0;
+
+  fp = es_fopen (fname, "r");
+  err = fp? 0 : gpg_error_from_syserror ();
+  if (err)
+    {
+      if (gpg_err_code (err) == GPG_ERR_ENOENT)
+        err = 0; /* No file - assume time is the year of Unix.  */
+      goto leave;
+    }
+
+  /* Note that the parser uses the first occurance of a matching
+   * values and ignores possible duplicated values.  */
+  maxlen = 2048; /* Set limit.  */
+  while ((len = es_read_line (fp, &line, &length_of_line, &maxlen)) > 0)
+    {
+      if (!maxlen)
+        {
+          err = gpg_error (GPG_ERR_LINE_TOO_LONG);
+          goto leave;
+        }
+      /* Strip newline and carriage return, if present.  */
+      while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
+	line[--len] = '\0';
+
+      if (split_fields (line, fields, DIM (fields)) < DIM(fields))
+        continue; /* Skip empty lines and names w/o a value.  */
+      if (*fields[0] == '#')
+        continue; /* Skip comments.  */
+
+      /* Record the meta data.  */
+      if (!strcmp (fields[0], ".filedate"))
+        {
+          gnupg_isotime_t isot;
+          if (string2isotime (isot, fields[1])
+              && (t = isotime2epoch (isot)) != (time_t)(-1))
+            break;  /* Got the time - stop reading.  */
+        }
+    }
+  if (len < 0 || es_ferror (fp))
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+  if (t == (time_t)(-1))
+    {
+      err = gpg_error (GPG_ERR_INV_TIME);
+      goto leave;
+    }
+
+  *r_time = t;
+
+ leave:
+  if (err)
+    log_error (_("error reading '%s': %s\n"), fname, gpg_strerror (err));
+  xfree (line);
+  es_fclose (fp);
+  return err;
+}
+
+
+
+/* Read a file from URL and return it as an estream memory buffer at
+ * R_FP.  */
+static gpg_error_t
+fetch_file (ctrl_t ctrl, const char *url, estream_t *r_fp)
+{
+  gpg_error_t err;
+  estream_t fp = NULL;
+  estream_t httpfp = NULL;
+  size_t nread, nwritten;
+  char buffer[1024];
+
+  if ((err = ks_http_fetch (ctrl, url, &httpfp)))
+    goto leave;
+
+  /* We now read the data from the web server into a memory buffer.
+   * To avoid excessive memory use in case of a ill behaving server we
+   * put a 64 k size limit on the buffer.  As of today the actual size
+   * of the swdb.lst file is 3k.  */
+  fp = es_fopenmem (64*1024, "rw");
+  if (!fp)
+    {
+      err = gpg_error_from_syserror ();
+      log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
+      goto leave;
+    }
+
+  for (;;)
+    {
+      if (es_read (httpfp, buffer, sizeof buffer, &nread))
+        {
+          err = gpg_error_from_syserror ();
+          log_error ("error reading '%s': %s\n",
+                     es_fname_get (httpfp), gpg_strerror (err));
+          goto leave;
+        }
+
+      if (!nread)
+        break; /* Ready.  */
+      if (es_write (fp, buffer, nread, &nwritten))
+        {
+          err = gpg_error_from_syserror ();
+          log_error ("error writing '%s': %s\n",
+                     es_fname_get (fp), gpg_strerror (err));
+          goto leave;
+        }
+      else if (nread != nwritten)
+        {
+          err = gpg_error (GPG_ERR_EIO);
+          log_error ("error writing '%s': %s\n",
+                     es_fname_get (fp), "short write");
+          goto leave;
+        }
+    }
+
+  es_rewind (fp);
+  *r_fp = fp;
+  fp = NULL;
+
+ leave:
+  es_fclose (httpfp);
+  es_fclose (fp);
+  return err;
+}
+
+
+/* Communication object for verify_status_cb.  */
+struct verify_status_parm_s
+{
+  time_t sigtime;
+  int anyvalid;
+};
+
+static void
+verify_status_cb (void *opaque, const char *keyword, char *args)
+{
+  struct verify_status_parm_s *parm = opaque;
+
+  /* We care only about the first valid signature.  */
+  if (!strcmp (keyword, "VALIDSIG") && !parm->anyvalid)
+    {
+      char *fields[3];
+
+      parm->anyvalid = 1;
+      if (split_fields (args, fields, DIM (fields)) >= 3)
+        parm->sigtime = parse_timestamp (fields[2], NULL);
+    }
+}
+
+
+
+/* Load the swdb file into the current home directory.  Do this onlky
+ * when needed unless FORCE is set which will always get a new
+ * copy.  */
+gpg_error_t
+dirmngr_load_swdb (ctrl_t ctrl, int force)
+{
+  gpg_error_t err;
+  char *fname = NULL;      /* The swdb.lst file.  */
+  char *tmp_fname = NULL;  /* The temporary swdb.lst file.  */
+  char *keyfile_fname = NULL;
+  estream_t swdb = NULL;
+  estream_t swdb_sig = NULL;
+  ccparray_t ccp;
+  const char **argv = NULL;
+  struct verify_status_parm_s verify_status_parm = { (time_t)(-1), 0 };
+  estream_t outfp = NULL;
+  time_t now = gnupg_get_time ();
+  gnupg_isotime_t isotime;
+
+
+  fname = make_filename_try (gnupg_homedir (), "swdb.lst", NULL);
+  if (!fname)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+
+  /* Check whether there is a need to get an update.  */
+  if (!force)
+    {
+      time_t filetime;
+
+      err = time_of_saved_swdb (fname, &filetime);
+      if (err)
+        goto leave;
+      if (filetime >= now)
+        goto leave; /* Current or newer.  */
+      if (now - filetime < 3*86400)
+        goto leave; /* Not older than 3 days.  */
+    }
+
+  /* Create the filename of the file with the keys. */
+  keyfile_fname = make_filename_try (gnupg_datadir (), "distsigkey.gpg", NULL);
+  if (!keyfile_fname)
+    goto leave;
+
+  /* Fetch the swdb from the web.  */
+  err = fetch_file (ctrl, "https://versions.gnupg.org/swdb.lst", &swdb);
+  if (err)
+    goto leave;
+  err = fetch_file (ctrl, "https://versions.gnupg.org/swdb.lst.sig", &swdb_sig);
+  if (err)
+    goto leave;
+
+  /* Run gpgv.  */
+  ccparray_init (&ccp, 0);
+  ccparray_put (&ccp, "--enable-special-filenames");
+  ccparray_put (&ccp, "--status-fd=2");
+  ccparray_put (&ccp, "--keyring");
+  ccparray_put (&ccp, keyfile_fname);
+  ccparray_put (&ccp, "--");
+  ccparray_put (&ccp, "-&@INEXTRA@");
+  ccparray_put (&ccp, "-");
+  ccparray_put (&ccp, NULL);
+  argv = ccparray_get (&ccp, NULL);
+  if (!argv)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+
+  err = gnupg_exec_tool_stream (gnupg_module_name (GNUPG_MODULE_NAME_GPGV),
+                                argv, swdb, swdb_sig, NULL,
+                                verify_status_cb, &verify_status_parm);
+  if (!err && verify_status_parm.sigtime == (time_t)(-1))
+    err = gpg_error (verify_status_parm.anyvalid? GPG_ERR_BAD_SIGNATURE
+                     /**/                       : GPG_ERR_INV_TIME      );
+  if (err)
+    goto leave;
+
+  /* Create a file name for a temporary file in the home directory.
+   * We will later rename that file to the real name.  */
+  {
+    char *tmpstr;
+
+#ifdef HAVE_W32_SYSTEM
+    tmpstr = es_bsprintf ("tmp-%u-swdb", (unsigned int)getpid ());
+#else
+    tmpstr = es_bsprintf (".#%u.swdb", (unsigned int)getpid ());
+#endif
+    if (!tmpstr)
+      {
+        err = gpg_error_from_syserror ();
+        goto leave;
+      }
+    tmp_fname = make_filename_try (gnupg_homedir (), tmpstr, NULL);
+    xfree (tmpstr);
+    if (!tmp_fname)
+      {
+        err = gpg_error_from_syserror ();
+        goto leave;
+      }
+  }
+
+  outfp = es_fopen (tmp_fname, "w");
+  if (!outfp)
+    {
+      err = gpg_error_from_syserror ();
+      log_error (_("error creating '%s': %s\n"), tmp_fname, gpg_strerror (err));
+      goto leave;
+    }
+
+  epoch2isotime (isotime, verify_status_parm.sigtime);
+  es_fprintf (outfp, ".filedate %s\n", isotime);
+  epoch2isotime (isotime, now);
+  es_fprintf (outfp, ".verified %s\n", isotime);
+
+  if (es_fseek (swdb, 0, SEEK_SET))
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+
+  err = copy_stream (swdb, outfp);
+  if (err)
+    {
+      /* Well, it might also be a reading error, but that is pretty
+       * unlikely for a memory stream.  */
+      log_error (_("error writing '%s': %s\n"), tmp_fname, gpg_strerror (err));
+      goto leave;
+    }
+
+  if (es_fclose (outfp))
+    {
+      err = gpg_error_from_syserror ();
+      log_error (_("error writing '%s': %s\n"), tmp_fname, gpg_strerror (err));
+      goto leave;
+    }
+  outfp = NULL;
+
+  err = gnupg_rename_file (tmp_fname, fname, NULL);
+  if (err)
+    goto leave;
+  xfree (tmp_fname);
+  tmp_fname = NULL;
+
+
+ leave:
+  es_fclose (outfp);
+  if (tmp_fname)
+    gnupg_remove (tmp_fname);  /* This is a temporary file.  */
+  xfree (argv);
+  es_fclose (swdb_sig);
+  es_fclose (swdb);
+  xfree (keyfile_fname);
+  xfree (tmp_fname);
+  xfree (fname);
+  return err;
+}
diff --git a/dirmngr/server.c b/dirmngr/server.c
index 2122d54..5c78d64 100644
--- a/dirmngr/server.c
+++ b/dirmngr/server.c
@@ -54,8 +54,6 @@
 #include "mbox-util.h"
 #include "zb32.h"
 #include "server-help.h"
-#include "ccparray.h"
-#include "../common/exectool.h"
 
 /* To avoid DoS attacks we limit the size of a certificate to
    something reasonable.  The DoS was actually only an issue back when
@@ -2239,6 +2237,22 @@ cmd_ks_put (assuan_context_t ctx, char *line)
 }
 
 
+

+static const char hlp_loadswdb[] =
+  "LOADSWDB [--force]\n"
+  "\n"
+  "Load and verify the swdb.lst from the Net.";
+static gpg_error_t
+cmd_loadswdb (assuan_context_t ctx, char *line)
+{
+  ctrl_t ctrl = assuan_get_pointer (ctx);
+  gpg_error_t err;
+
+  err = dirmngr_load_swdb (ctrl, has_option (line, "--force"));
+
+  return leave_cmd (ctx, err);
+}
+
 
 

 static const char hlp_getinfo[] =
@@ -2343,388 +2357,6 @@ cmd_reloaddirmngr (assuan_context_t ctx, char *line)
 
 
 

-/* 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.  If MICRO is not given 0 is used instead.
- *
- * On success, the last component, the patch level, will be returned;
- * on 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.  */
-}
-
-
-/* Create temporary directory with mode 0700.  Returns a dynamically
- * allocated string with the filename of the directory.  */
-static char *
-my_mktmpdir (void)
-{
-  char *name, *p;
-
-  p = getenv ("TMPDIR");
-  if (!p || !*p)
-    p = "/tmp";
-  if (p[strlen (p) - 1] == '/')
-    name = strconcat (p, "gpg-XXXXXX", NULL);
-  else
-    name = strconcat (p, "/", "gpg-XXXXXX", NULL);
-  if (!name || !gnupg_mkdtemp (name))
-    {
-      int saveerr = errno;
-      log_error (_("can't create temporary directory '%s': %s\n"),
-                 name, strerror (saveerr));
-      gpg_err_set_errno (saveerr);
-      return NULL;
-    }
-
-  return name;
-}
-
-
-/* Sets result to -1 if version a is less than b, 0 if the versions are equal
- * and 1 otherwise. Patch levels are compared as strings.  */
-static gpg_error_t
-cmp_version (const char *a, const char *b, int *result)
-{
-  int a_major, b_major;
-  int a_minor, b_minor;
-  int a_micro, b_micro;
-  const char *a_patch, *b_patch;
-
-  if (!a || !b || !result)
-    return gpg_error (GPG_ERR_EINVAL);
-
-  a_patch = parse_version_string (a, &a_major, &a_minor, &a_micro);
-  b_patch = parse_version_string (b, &b_major, &b_minor, &b_micro);
-
-  if (!a_patch || !b_patch)
-    return gpg_error (GPG_ERR_EINVAL);
-
-  if (a_major == b_major)
-    {
-      if (a_minor == b_minor)
-        {
-          if (a_micro == b_micro)
-            *result = strcmp (a_patch, b_patch);
-          else
-            *result = a_micro - b_minor;
-        }
-      else
-        *result = a_minor - b_minor;
-    }
-  else
-    *result = a_major - b_major;
-
-  return 0;
-}
-
-
-static gpg_error_t
-fetch_into_tmpdir (ctrl_t ctrl, const char *url, estream_t *strm_out,
-                   char **path)
-{
-  gpg_error_t err;
-  char *filename = NULL;
-  char *dirname = NULL;
-  estream_t file = NULL;
-  estream_t strm = NULL;
-  size_t len, nwritten;
-  char buf[1024];
-
-  if (!strm_out || !path || !url)
-    {
-      err = gpg_error (GPG_ERR_INV_ARG);
-      goto leave;
-    }
-
-  dirname = my_mktmpdir ();
-  if (!dirname)
-    {
-      err = gpg_error_from_syserror ();
-      goto leave;
-    }
-
-  filename = strconcat (dirname, DIRSEP_S, "file", NULL);
-  if (!filename)
-    {
-      err = gpg_error_from_syserror ();
-      goto leave;
-    }
-
-  file = es_fopen (filename, "w+");
-  if (!file)
-    {
-      err = gpg_error_from_syserror ();
-      goto leave;
-    }
-
-  if ((err = ks_http_fetch (ctrl, url, &strm)))
-    goto leave;
-
-  for (;;)
-    {
-      if (es_read (strm, buf, sizeof buf, &len))
-        {
-          err = gpg_error_from_syserror ();
-          log_error ("error reading '%s': %s\n",
-                     es_fname_get (strm), gpg_strerror (err));
-          goto leave;
-        }
-
-      if (!len)
-        break;
-      if (es_write (file, buf, len, &nwritten))
-        {
-          err = gpg_error_from_syserror ();
-          log_error ("error writing '%s': %s\n", filename, gpg_strerror (err));
-          goto leave;
-        }
-      else if (len != nwritten)
-        {
-          err = gpg_error (GPG_ERR_EIO);
-          log_error ("error writing '%s': %s\n", filename, "short write");
-          goto leave;
-        }
-    }
-
-  es_rewind (file);
-  *strm_out = file;
-  file = NULL;
-
-  if (path)
-    {
-      *path = dirname;
-      dirname = NULL;
-    }
-
- leave:
-  es_fclose (file);
-  es_fclose (strm);
-  xfree (dirname);
-  xfree (filename);
-  return err;
-}
-
-
-struct verify_swdb_parm_s
-{
-  time_t sigtime;
-  int anyvalid;
-};
-
-static void
-verify_swdb_status_cb (void *opaque, const char *keyword, char *args)
-{
-  struct verify_swdb_parm_s *parm = opaque;
-
-  /* We care only about the first valid signature.  */
-  if (!strcmp (keyword, "VALIDSIG") && !parm->anyvalid)
-    {
-      char *fields[3];
-
-      parm->anyvalid = 1;
-      if (split_fields (args, fields, DIM (fields)) >= 3)
-        parm->sigtime = parse_timestamp (fields[2], NULL);
-    }
-}
-
-
-static const char hlp_versioncheck[] =
-  "VERSIONCHECK <name> <version>"
-  "\n"
-  "Checks the internet to find whenever a new program version is available."
-  "\n"
-  "<name> program name i.e. \"gnupg\"\n"
-  "<version> current version of the program i.e. \"2.0.2\"";
-static gpg_error_t
-cmd_versioncheck (assuan_context_t ctx, char *line)
-{
-  gpg_error_t err;
-
-  char *name;
-  char *version;
-  size_t name_len;
-  char *cmd_fields[2];
-
-  ctrl_t ctrl;
-  estream_t swdb = NULL;
-  estream_t swdb_sig = NULL;
-  char* swdb_dir = NULL;
-  char* swdb_sig_dir = NULL;
-  char* buf = NULL;
-  size_t len = 0;
-  ccparray_t ccp;
-  const char **argv = NULL;
-  char keyring_name[128];
-  char swdb_name[128];
-  char swdb_sig_name[128];
-
-  struct verify_swdb_parm_s verify_swdb_parm = { (time_t)(-1), 0 };
-
-
-  swdb_name[0] = 0;
-  swdb_sig_name[0] = 0;
-  ctrl = assuan_get_pointer (ctx);
-
-  if (split_fields (line, cmd_fields, 2) != 2)
-    {
-      err = set_error (GPG_ERR_ASS_PARAMETER,
-                       "No program name and/or version given");
-      goto out;
-    }
-
-  name = cmd_fields[0];
-  name_len = strlen (name);
-  version = cmd_fields[1];
-
-  if ((err = fetch_into_tmpdir (ctrl, "https://versions.gnupg.org/swdb.lst",
-                                &swdb, &swdb_dir)))
-    goto out;
-
-  snprintf (swdb_name, sizeof swdb_name, "%s%s%s", swdb_dir, DIRSEP_S, "file");
-
-  if ((err = fetch_into_tmpdir (ctrl, "https://versions.gnupg.org/swdb.lst.sig",
-                                &swdb_sig, &swdb_sig_dir)))
-    goto out;
-
-  snprintf (keyring_name, sizeof keyring_name, "%s%s%s", gnupg_datadir (),
-           DIRSEP_S, "distsigkey.gpg");
-  snprintf (swdb_sig_name, sizeof swdb_sig_name, "%s%s%s", swdb_sig_dir,
-           DIRSEP_S, "file");
-
-  ccparray_init (&ccp, 0);
-  ccparray_put (&ccp, "--status-fd=2");
-  ccparray_put (&ccp, "--keyring");
-  ccparray_put (&ccp, keyring_name);
-  ccparray_put (&ccp, "--");
-  ccparray_put (&ccp, swdb_sig_name);
-  ccparray_put (&ccp, "-");
-  ccparray_put (&ccp, NULL);
-  argv = ccparray_get (&ccp, NULL);
-  if (!argv)
-    {
-      err = gpg_error_from_syserror ();
-      goto out;
-    }
-
-  if ((err = gnupg_exec_tool_stream (gnupg_module_name (GNUPG_MODULE_NAME_GPGV),
-                                     argv, swdb, NULL, NULL,
-                                     verify_swdb_status_cb, &verify_swdb_parm)))
-    goto out;
-  if (verify_swdb_parm.sigtime == (time_t)(-1))
-    {
-      if (verify_swdb_parm.anyvalid)
-        err = gpg_error (GPG_ERR_BAD_SIGNATURE);
-      else
-        err = gpg_error (GPG_ERR_INV_TIME);
-      goto out;
-    }
-
-  {
-    gnupg_isotime_t tbuf;
-
-    epoch2isotime (tbuf, verify_swdb_parm.sigtime);
-    log_debug ("swdb created: %s\n", tbuf);
-  }
-
-  es_fseek (swdb, 0, SEEK_SET);
-
-  while (es_getline (&buf, &len, swdb) > 0)
-    {
-      if (len > name_len + 5 &&
-          strncmp (buf, name, name_len) == 0 &&
-          strncmp (buf + name_len, "_ver ", 5) == 0)
-        {
-          const char* this_ver_start = buf + name_len + 5;
-          char* this_ver_end = strchr (this_ver_start, '\n');
-          int cmp;
-
-          if (this_ver_end)
-            *this_ver_end = 0;
-
-          err = assuan_write_status (ctx, "LINE", buf);
-
-          err = cmp_version (this_ver_start, version, &cmp);
-          if (err > 0)
-            goto out;
-
-          if (cmp < 0)
-            err = assuan_send_data (ctx, "ROLLBACK", strlen ("ROLLBACK"));
-          else if (cmp == 0)
-            err = assuan_send_data (ctx, "CURRENT", strlen ("CURRENT"));
-          else
-            err = assuan_send_data (ctx, "UPDATE", strlen ("UPDATE"));
-
-          goto out;
-        }
-    }
-
-  err = assuan_send_data (ctx, "NOT_FOUND", strlen ("NOT_FOUND"));
-
- out:
-  es_fclose (swdb);
-  es_fclose (swdb_sig);
-  xfree (buf);
-
-  if (strlen (swdb_name) > 0)
-    remove (swdb_name);
-  if (swdb_dir)
-    rmdir (swdb_dir);
-  xfree (swdb_dir);
-
-  if (strlen (swdb_sig_name) > 0)
-    remove (swdb_sig_name);
-  if (swdb_sig_dir)
-    rmdir (swdb_sig_dir);
-  xfree (swdb_sig_dir);
-  xfree (argv);
-
-  return leave_cmd (ctx, err);
-}
-
-
-

 /* Tell the assuan library about our commands. */
 static int
 register_commands (assuan_context_t ctx)
@@ -2751,9 +2383,9 @@ register_commands (assuan_context_t ctx)
     { "KS_FETCH",   cmd_ks_fetch,   hlp_ks_fetch },
     { "KS_PUT",     cmd_ks_put,     hlp_ks_put },
     { "GETINFO",    cmd_getinfo,    hlp_getinfo },
+    { "LOADSWDB",   cmd_loadswdb,   hlp_loadswdb },
     { "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr },
     { "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr },
-    { "VERSIONCHECK",cmd_versioncheck,hlp_versioncheck },
     { NULL, NULL }
   };
   int i, j, rc;

commit 4839e6d002a8ad1f7d3260792c3c9641e258f342
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Nov 16 21:17:47 2016 +0100

    scd,dirmngr: Keep the standard fds when daemonizing.
    
    * dirmngr/dirmngr.c (main): Before calling setsid do not close the
    standard fds but connect them to /dev/null.
    * scd/scdaemon.c (main): Ditto.  Noet that the old test for a log
    stream was even reverted.
    
    --
    
    Note that this was fixed for gpg-agent 10 years ago on 2006-11-09.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
index 254c543..db5079c 100644
--- a/dirmngr/dirmngr.c
+++ b/dirmngr/dirmngr.c
@@ -1209,8 +1209,18 @@ main (int argc, char **argv)
           for (i=0; i <= 2; i++)
             {
               if (!log_test_fd (i) && i != fd )
-                close (i);
+                {
+                  if ( !close (i)
+                       && open ("/dev/null", i? O_WRONLY : O_RDONLY) == -1)
+                    {
+                      log_error ("failed to open '%s': %s\n",
+                                 "/dev/null", strerror (errno));
+                      cleanup ();
+                      dirmngr_exit (1);
+                    }
+                }
             }
+
           if (setsid() == -1)
             {
               log_error ("setsid() failed: %s\n", strerror(errno) );
diff --git a/scd/scdaemon.c b/scd/scdaemon.c
index acc5b47..064cae9 100644
--- a/scd/scdaemon.c
+++ b/scd/scdaemon.c
@@ -871,9 +871,19 @@ main (int argc, char **argv )
           /* Close stdin, stdout and stderr unless it is the log stream. */
           for (i=0; i <= 2; i++)
             {
-              if ( log_test_fd (i) && i != fd)
-                close (i);
+              if (!log_test_fd (i) && i != fd )
+                {
+                  if ( !close (i)
+                       && open ("/dev/null", i? O_WRONLY : O_RDONLY) == -1)
+                    {
+                      log_error ("failed to open '%s': %s\n",
+                                 "/dev/null", strerror (errno));
+                      cleanup ();
+                      exit (1);
+                    }
+                }
             }
+
           if (setsid() == -1)
             {
               log_error ("setsid() failed: %s\n", strerror(errno) );

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

Summary of changes:
 dirmngr/Makefile.am |   1 +
 dirmngr/dirmngr.c   |  12 +-
 dirmngr/dirmngr.h   |   3 +
 dirmngr/loadswdb.c  | 358 ++++++++++++++++++++++++++++++++++++++++++++++
 dirmngr/server.c    | 402 +++-------------------------------------------------
 scd/scdaemon.c      |  14 +-
 6 files changed, 402 insertions(+), 388 deletions(-)
 create mode 100644 dirmngr/loadswdb.c


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




More information about the Gnupg-commits mailing list