[git] GnuPG - branch, master, updated. gnupg-2.2.1-79-g65038e6

by Werner Koch cvs at cvs.gnupg.org
Mon Nov 13 16:57:25 CET 2017


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  65038e6852185c20413d8f6602218ee636413b77 (commit)
      from  5d83eb9226c0ce608ec284d8c9bc22ce84a00c25 (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 65038e6852185c20413d8f6602218ee636413b77
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Nov 13 16:09:32 2017 +0100

    dirmngr: Keep track of domains used for WKD queries
    
    * dirmngr/domaininfo.c: New file.
    * dirmngr/Makefile.am (dirmngr_SOURCES): Add file.
    * dirmngr/server.c (cmd_wkd_get): Check whether the domain is already
    known and tell domaininfo about the results.
    --
    
    This adds a registry for domain information to eventually avoid
    useless queries for domains which do not support WKD.  The missing
    part is a background task to check whether a queried domain supports
    WKD at all and to expire old entries.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am
index b404165..421a325 100644
--- a/dirmngr/Makefile.am
+++ b/dirmngr/Makefile.am
@@ -16,6 +16,8 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, see <https://www.gnu.org/licenses/>.
+#
+# SPDX-License-Identifier: GPL-3.0+
 
 ## Process this file with automake to produce Makefile.in
 
@@ -57,6 +59,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 \
+	domaininfo.c \
 	loadswdb.c \
 	cdb.h cdblib.c misc.c dirmngr-err.h  \
 	ocsp.c ocsp.h validate.c validate.h  \
diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
index 5317c21..2b64655 100644
--- a/dirmngr/dirmngr.c
+++ b/dirmngr/dirmngr.c
@@ -17,6 +17,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0+
  */
 
 #include <config.h>
@@ -1871,6 +1873,7 @@ handle_signal (int signo)
 
     case SIGUSR1:
       cert_cache_print_stats ();
+      domaininfo_print_stats ();
       break;
 
     case SIGUSR2:
diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h
index 1f660de..b08e4fe 100644
--- a/dirmngr/dirmngr.h
+++ b/dirmngr/dirmngr.h
@@ -17,6 +17,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0+
  */
 
 #ifndef DIRMNGR_H
@@ -248,4 +250,14 @@ gpg_error_t gnupg_http_tls_verify_cb (void *opaque,
 gpg_error_t dirmngr_load_swdb (ctrl_t ctrl, int force);
 
 
+/*-- domaininfo.c --*/
+void domaininfo_print_stats (void);
+int  domaininfo_is_wkd_not_supported (const char *domain);
+void domaininfo_set_no_name (const char *domain);
+void domaininfo_set_wkd_supported (const char *domain);
+void domaininfo_set_wkd_not_supported (const char *domain);
+void domaininfo_set_wkd_not_found (const char *domain);
+
+
+
 #endif /*DIRMNGR_H*/
diff --git a/dirmngr/domaininfo.c b/dirmngr/domaininfo.c
new file mode 100644
index 0000000..393db8c
--- /dev/null
+++ b/dirmngr/domaininfo.c
@@ -0,0 +1,244 @@
+/* domaininfo.c - Gather statistics about accessed domains
+ * Copyright (C) 2017 Werner Koch
+ *
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0+
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dirmngr.h"
+
+
+#define NO_OF_DOMAINBUCKETS 103
+
+/* Object to keep track of a domain name.  */
+struct domaininfo_s
+{
+  struct domaininfo_s *next;
+  unsigned int no_name:1;            /* Domain name not found.            */
+  unsigned int wkd_not_found:1;      /* A WKD query failed.               */
+  unsigned int wkd_supported:1;      /* One WKD entry was found.          */
+  unsigned int wkd_not_supported:1;  /* Definitely does not support WKD.  */
+  char name[1];
+};
+typedef struct domaininfo_s *domaininfo_t;
+
+/* And the hashed array.  */
+static domaininfo_t domainbuckets[NO_OF_DOMAINBUCKETS];
+
+
+/* The hash function we use.  Must not call a system function.  */
+static inline u32
+hash_domain (const char *domain)
+{
+  const unsigned char *s = (const unsigned char*)domain;
+  u32 hashval = 0;
+  u32 carry;
+
+  for (; *s; s++)
+    {
+      if (*s == '.')
+        continue;
+      hashval = (hashval << 4) + *s;
+      if ((carry = (hashval & 0xf0000000)))
+        {
+          hashval ^= (carry >> 24);
+          hashval ^= carry;
+        }
+    }
+
+  return hashval % NO_OF_DOMAINBUCKETS;
+}
+
+
+void
+domaininfo_print_stats (void)
+{
+  int bidx;
+  domaininfo_t di;
+  int count, no_name, wkd_not_found, wkd_supported, wkd_not_supported;
+
+  for (bidx = 0; bidx < NO_OF_DOMAINBUCKETS; bidx++)
+    {
+      count = no_name = wkd_not_found = wkd_supported = wkd_not_supported = 0;
+      for (di = domainbuckets[bidx]; di; di = di->next)
+        {
+          count++;
+          if (di->no_name)
+            no_name++;
+          if (di->wkd_not_found)
+            wkd_not_found++;
+          if (di->wkd_supported)
+            wkd_supported++;
+          if (di->wkd_not_supported)
+            wkd_not_supported++;
+        }
+      if (count)
+        log_info ("domaininfo: chain %3d length=%d nn=%d nf=%d s=%d ns=%d\n",
+                  bidx, count, no_name,
+                  wkd_not_found, wkd_supported, wkd_not_supported);
+    }
+}
+
+
+/* Return true if DOMAIN definitely does not support WKD.  Noet that
+ * DOMAIN is expected to be lowercase.  */
+int
+domaininfo_is_wkd_not_supported (const char *domain)
+{
+  domaininfo_t di;
+
+  for (di = domainbuckets[hash_domain (domain)]; di; di = di->next)
+    if (!strcmp (di->name, domain))
+      return !!di->wkd_not_supported;
+
+  return 0;  /* We don't know.  */
+}
+
+
+/* Core update function.  DOMAIN is expected to be lowercase.
+ * CALLBACK is called to update the existing or the newly inserted
+ * item.  */
+static void
+insert_or_update (const char *domain,
+                  void (*callback)(domaininfo_t di, int insert_mode))
+{
+  domaininfo_t di;
+  domaininfo_t di_new;
+  u32 hash;
+
+  hash = hash_domain (domain);
+  for (di = domainbuckets[hash]; di; di = di->next)
+    if (!strcmp (di->name, domain))
+      {
+        callback (di, 0);  /* Update */
+        return;
+      }
+
+  di_new = xtrycalloc (1, sizeof *di + strlen (domain));
+  if (!di_new)
+    return;  /* Out of core - we ignore this.  */
+
+  /* Need to do another lookup because the malloc is a system call and
+   * thus the hash array may have been changed by another thread.  */
+  for (di = domainbuckets[hash]; di; di = di->next)
+    if (!strcmp (di->name, domain))
+      {
+        callback (di, 0);  /* Update */
+        xfree (di_new);
+        return;
+      }
+
+  callback (di_new, 1);  /* Insert */
+  di = di_new;
+  di->next = domainbuckets[hash];
+  domainbuckets[hash] = di;
+}
+
+
+/* Helper for domaininfo_set_no_name.  */
+static void
+set_no_name_cb (domaininfo_t di, int insert_mode)
+{
+  (void)insert_mode;
+
+  di->no_name = 1;
+  /* Obviously the domain is in this case also not supported.  */
+  di->wkd_not_supported = 1;
+
+  /* The next should already be 0 but we clear it anyway in the case
+   * of a temporary DNS failure.  */
+  di->wkd_supported = 0;
+}
+
+
+/* Mark DOMAIN as not existent.  */
+void
+domaininfo_set_no_name (const char *domain)
+{
+  insert_or_update (domain, set_no_name_cb);
+}
+
+
+/* Helper for domaininfo_set_wkd_supported.  */
+static void
+set_wkd_supported_cb (domaininfo_t di, int insert_mode)
+{
+  (void)insert_mode;
+
+  di->wkd_supported = 1;
+  /* The next will already be set unless the domain enabled WKD in the
+   * meantime.  Thus we need to clear it.  */
+  di->wkd_not_supported = 0;
+}
+
+
+/* Mark DOMAIN as supporting WKD.  */
+void
+domaininfo_set_wkd_supported (const char *domain)
+{
+  insert_or_update (domain, set_wkd_supported_cb);
+}
+
+
+/* Helper for domaininfo_set_wkd_not_supported.  */
+static void
+set_wkd_not_supported_cb (domaininfo_t di, int insert_mode)
+{
+  (void)insert_mode;
+
+  di->wkd_not_supported = 1;
+  di->wkd_supported = 0;
+}
+
+
+/* Mark DOMAIN as not supporting WKD queries (e.g. no policy file).  */
+void
+domaininfo_set_wkd_not_supported (const char *domain)
+{
+  insert_or_update (domain, set_wkd_not_supported_cb);
+}
+
+
+
+/* Helper for domaininfo_set_wkd_not_found.  */
+static void
+set_wkd_not_found_cb (domaininfo_t di, int insert_mode)
+{
+  /* Set the not found flag but there is no need to do this if we
+   * already know that the domain either does not support WKD or we
+   * know that it supports WKD.  */
+  if (insert_mode)
+    di->wkd_not_found = 1;
+  else if (!di->wkd_not_supported && !di->wkd_supported)
+    di->wkd_not_found = 1;
+
+  /* Better clear this flag in case we had a DNS failure in the
+   * past.  */
+  di->no_name = 0;
+}
+
+
+/* Update a counter for DOMAIN to keep track of failed WKD queries.  */
+void
+domaininfo_set_wkd_not_found (const char *domain)
+{
+  insert_or_update (domain, set_wkd_not_found_cb);
+}
diff --git a/dirmngr/server.c b/dirmngr/server.c
index 7ed6cde..18a5f72 100644
--- a/dirmngr/server.c
+++ b/dirmngr/server.c
@@ -18,6 +18,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0+
  */
 
 #include <config.h>
@@ -833,11 +835,13 @@ cmd_wkd_get (assuan_context_t ctx, char *line)
   char *mbox = NULL;
   char *domainbuf = NULL;
   char *domain;     /* Points to mbox or domainbuf.  */
+  char *domain_orig;/* Points to mbox.  */
   char sha1buf[20];
   char *uri = NULL;
   char *encodedhash = NULL;
   int opt_submission_addr;
   int opt_policy_flags;
+  int is_wkd_query;   /* True if this is a real WKD query.  */
   int no_log = 0;
   char portstr[20] = { 0 };
 
@@ -846,6 +850,7 @@ cmd_wkd_get (assuan_context_t ctx, char *line)
   if (has_option (line, "--quick"))
     ctrl->timeout = opt.connect_quick_timeout;
   line = skip_options (line);
+  is_wkd_query = !(opt_policy_flags || opt_submission_addr);
 
   mbox = mailbox_from_userid (line);
   if (!mbox || !(domain = strchr (mbox, '@')))
@@ -854,6 +859,18 @@ cmd_wkd_get (assuan_context_t ctx, char *line)
       goto leave;
     }
   *domain++ = 0;
+  domain_orig = domain;
+
+  /* First check whether we already know that the domain does not
+   * support WKD.  */
+  if (is_wkd_query)
+    {
+      if (domaininfo_is_wkd_not_supported (domain_orig))
+        {
+          err = gpg_error (GPG_ERR_NO_DATA);
+          goto leave;
+        }
+    }
 
   /* Check for SRV records.  */
   if (1)
@@ -962,6 +979,29 @@ cmd_wkd_get (assuan_context_t ctx, char *line)
         err = ks_action_fetch (ctrl, uri, outfp);
         es_fclose (outfp);
         ctrl->server_local->inhibit_data_logging = 0;
+        /* Register the result under the domain name of MBOX. */
+        switch (gpg_err_code (err))
+          {
+          case 0:
+            domaininfo_set_wkd_supported (domain_orig);
+            break;
+
+          case GPG_ERR_NO_NAME:
+            /* There is no such domain.  */
+            domaininfo_set_no_name (domain_orig);
+            break;
+
+          case GPG_ERR_NO_DATA:
+            if (is_wkd_query) /* Mark that - we will latter do a check.  */
+              domaininfo_set_wkd_not_found (domain_orig);
+            else if (opt_policy_flags) /* No policy file - no support.  */
+              domaininfo_set_wkd_not_supported (domain_orig);
+            break;
+
+          default:
+            /* Don't register other errors.  */
+            break;
+          }
       }
   }
 

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

Summary of changes:
 dirmngr/Makefile.am  |   3 +
 dirmngr/dirmngr.c    |   3 +
 dirmngr/dirmngr.h    |  12 +++
 dirmngr/domaininfo.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++
 dirmngr/server.c     |  40 +++++++++
 5 files changed, 302 insertions(+)
 create mode 100644 dirmngr/domaininfo.c


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




More information about the Gnupg-commits mailing list