[git] GnuPG - branch, master, updated. post-nuke-of-trailing-ws-42-gf8c5395

by Werner Koch cvs at cvs.gnupg.org
Tue Apr 12 18:49:25 CEST 2011


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  f8c5395fbd24b9811807d7601e22b38af9f5126c (commit)
       via  a9edbfb3a316e8c1bfa0373c39ad69a1e1c29080 (commit)
       via  944bf8f5b550bdbab292e7fadd0016b341c7bef9 (commit)
       via  893b455a3da5b5af2214657ead0a4994102c2714 (commit)
       via  f1e9f510ec70f2bb64f1b61b2b040d8d3103af32 (commit)
       via  4206a2bd486f02072c8ba2731f4fade46c2a5581 (commit)
      from  b9bcc77d6ca13463c2e4bede91fc1782795f1eae (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 f8c5395fbd24b9811807d7601e22b38af9f5126c
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Apr 12 18:20:46 2011 +0200

    Use macros for the 120 and 900s cache TTLs.

diff --git a/agent/ChangeLog b/agent/ChangeLog
index d4cea79..21cd0c4 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,15 +1,18 @@
-2011-04-10  Ben Kibbey <bjk at luxsci.net>
+2011-04-12  Werner Koch  <wk at g10code.com>
 
-	* command.c: (cmd_passwd): Add option --preset.
+	* agent.h (CACHE_TTL_NONCE, CACHE_TTL_OPT_PRESET): New.
+	* command.c (cmd_passwd, cmd_import_key): Use new macros.
+	* genkey.c (agent_genkey): Ditto.
 
 2011-04-10  Ben Kibbey <bjk at luxsci.net>
 
-	* command.c: (cmd_genkey): Add option --preset.
-	* genkey.c: (agent_genkey): Add parameter preset.
+	* command.c (cmd_passwd): Add option --preset.
+	* command.c (cmd_genkey): Add option --preset.
+	* genkey.c (agent_genkey): Add parameter preset.
 
 2011-04-06  Ben Kibbey <bjk at luxsci.net>
 
-	* command.c: (do_one_keyinfo): Add protection type field.
+	* command.c (do_one_keyinfo): Add protection type field.
 
 2011-03-10  Werner Koch  <wk at g10code.com>
 
diff --git a/agent/agent.h b/agent/agent.h
index d5aaec8..20a617f 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -217,6 +217,12 @@ typedef enum
   }
 cache_mode_t;
 
+/* The TTL is seconds used for adding a new nonce mode cache item.  */
+#define CACHE_TTL_NONCE 120
+
+/* The TTL in seconds used by the --preset option of some commands.  */
+#define CACHE_TTL_OPT_PRESET 900
+
 
 /* The type of a function to lookup a TTL by a keygrip.  */
 typedef int (*lookup_ttl_t)(const char *hexgrip);
diff --git a/agent/command.c b/agent/command.c
index 8655c99..e5243ed 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -1411,7 +1411,7 @@ cmd_learn (assuan_context_t ctx, char *line)
 
 
 static const char hlp_passwd[] =
-  "PASSWD [--cache-nonce=<c>] [--passwd-nonce=<s>] [--preset] <hexstring_with_keygrip>\n"
+  "PASSWD [--cache-nonce=<c>] [--passwd-nonce=<s>] [--preset] <hexkeygrip>\n"
   "\n"
   "Change the passphrase/PIN for the key identified by keygrip in LINE. When\n"
   "--preset is used then the new passphrase will be added to the cache.\n";
@@ -1501,7 +1501,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
             }
           if (cache_nonce
               && !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
-                                   passphrase, 120 /*seconds*/))
+                                   passphrase, CACHE_TTL_NONCE))
             {
               assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
               xfree (ctrl->server_local->last_cache_nonce);
@@ -1521,7 +1521,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
                 }
               if (passwd_nonce
                   && !agent_put_cache (passwd_nonce, CACHE_MODE_NONCE,
-                                       newpass, 120 /*seconds*/))
+                                       newpass, CACHE_TTL_NONCE))
                 {
                   assuan_write_status (ctx, "PASSWD_NONCE", passwd_nonce);
                   xfree (ctrl->server_local->last_passwd_nonce);
@@ -1532,7 +1532,8 @@ cmd_passwd (assuan_context_t ctx, char *line)
 		{
 		  char hexgrip[40+1];
 		  bin2hex(grip, 20, hexgrip);
-		  err = agent_put_cache (hexgrip, CACHE_MODE_ANY, newpass, 900);
+		  err = agent_put_cache (hexgrip, CACHE_MODE_ANY, newpass,
+                                         CACHE_TTL_OPT_PRESET);
 		}
             }
         }
@@ -1844,7 +1845,7 @@ cmd_import_key (assuan_context_t ctx, char *line)
             }
           if (cache_nonce
               && !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
-                                   passphrase, 120 /*seconds*/))
+                                   passphrase, CACHE_TTL_NONCE))
             assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
         }
     }
diff --git a/agent/genkey.c b/agent/genkey.c
index 95e0a64..30e698f 100644
--- a/agent/genkey.c
+++ b/agent/genkey.c
@@ -432,7 +432,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
       if (cache_nonce
           && !no_protection
           && !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
-                               passphrase, 900 /*seconds*/))
+                               passphrase, CACHE_TTL_OPT_PRESET))
         agent_write_status (ctrl, "CACHE_NONCE", cache_nonce, NULL);
       if (preset && !no_protection)
 	{
@@ -441,7 +441,8 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
 	  if (gcry_pk_get_keygrip (s_private, grip))
 	    {
 	      bin2hex(grip, 20, hexgrip);
-	      rc = agent_put_cache (hexgrip, CACHE_MODE_ANY, passphrase, 900);
+	      rc = agent_put_cache (hexgrip, CACHE_MODE_ANY, passphrase,
+                                    CACHE_TTL_OPT_PRESET);
 	    }
 	}
     }

commit a9edbfb3a316e8c1bfa0373c39ad69a1e1c29080
Author: Ben Kibbey <bjk at luxsci.net>
Date:   Sun Apr 10 16:06:18 2011 -0400

    Added PASSWD --preset.

diff --git a/agent/ChangeLog b/agent/ChangeLog
index 83ad651..d4cea79 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,5 +1,9 @@
 2011-04-10  Ben Kibbey <bjk at luxsci.net>
 
+	* command.c: (cmd_passwd): Add option --preset.
+
+2011-04-10  Ben Kibbey <bjk at luxsci.net>
+
 	* command.c: (cmd_genkey): Add option --preset.
 	* genkey.c: (agent_genkey): Add parameter preset.
 
diff --git a/agent/command.c b/agent/command.c
index 0121a20..8655c99 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -1411,9 +1411,10 @@ cmd_learn (assuan_context_t ctx, char *line)
 
 
 static const char hlp_passwd[] =
-  "PASSWD [--cache-nonce=<c>] [--passwd-nonce=<s>] <hexstring_with_keygrip>\n"
+  "PASSWD [--cache-nonce=<c>] [--passwd-nonce=<s>] [--preset] <hexstring_with_keygrip>\n"
   "\n"
-  "Change the passphrase/PIN for the key identified by keygrip in LINE.";
+  "Change the passphrase/PIN for the key identified by keygrip in LINE. When\n"
+  "--preset is used then the new passphrase will be added to the cache.\n";
 static gpg_error_t
 cmd_passwd (assuan_context_t ctx, char *line)
 {
@@ -1427,7 +1428,9 @@ cmd_passwd (assuan_context_t ctx, char *line)
   unsigned char *shadow_info = NULL;
   char *passphrase = NULL;
   char *pend;
+  int opt_preset;
 
+  opt_preset = has_option (line, "--preset");
   cache_nonce = option_value (line, "--cache-nonce");
   if (cache_nonce)
     {
@@ -1525,6 +1528,12 @@ cmd_passwd (assuan_context_t ctx, char *line)
                   ctrl->server_local->last_passwd_nonce = passwd_nonce;
                   passwd_nonce = NULL;
                 }
+	      if (opt_preset)
+		{
+		  char hexgrip[40+1];
+		  bin2hex(grip, 20, hexgrip);
+		  err = agent_put_cache (hexgrip, CACHE_MODE_ANY, newpass, 900);
+		}
             }
         }
       xfree (newpass);

commit 944bf8f5b550bdbab292e7fadd0016b341c7bef9
Author: Ben Kibbey <bjk at luxsci.net>
Date:   Sun Apr 10 09:37:18 2011 -0400

    Added GENKEY --preset to add the passphrase of the generated key to the cache.

diff --git a/agent/ChangeLog b/agent/ChangeLog
index b05c174..83ad651 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,3 +1,8 @@
+2011-04-10  Ben Kibbey <bjk at luxsci.net>
+
+	* command.c: (cmd_genkey): Add option --preset.
+	* genkey.c: (agent_genkey): Add parameter preset.
+
 2011-04-06  Ben Kibbey <bjk at luxsci.net>
 
 	* command.c: (do_one_keyinfo): Add protection type field.
diff --git a/agent/agent.h b/agent/agent.h
index 3e01897..d5aaec8 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -313,7 +313,7 @@ gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
                                       char **r_passphrase);
 int agent_genkey (ctrl_t ctrl, const char *cache_nonce,
                   const char *keyparam, size_t keyparmlen,
-                  int no_protection, membuf_t *outbuf);
+                  int no_protection, int preset, membuf_t *outbuf);
 gpg_error_t agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
                                      char **passphrase_addr);
 
diff --git a/agent/command.c b/agent/command.c
index d53ca5e..0121a20 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -831,7 +831,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
 
 
 static const char hlp_genkey[] =
-  "GENKEY [--no-protection] [<cache_nonce>]\n"
+  "GENKEY [--no-protection] [--preset] [<cache_nonce>]\n"
   "\n"
   "Generate a new key, store the secret part and return the public\n"
   "part.  Here is an example transaction:\n"
@@ -843,6 +843,9 @@ static const char hlp_genkey[] =
   "  S: D (public-key\n"
   "  S: D   (rsa (n 326487324683264) (e 10001)))\n"
   "  S: OK key created\n"
+  "\n"
+  "When the --preset option is used the passphrase for the generated\n"
+  "key will be added to the cache.\n"
   "\n";
 static gpg_error_t
 cmd_genkey (assuan_context_t ctx, char *line)
@@ -854,8 +857,10 @@ cmd_genkey (assuan_context_t ctx, char *line)
   size_t valuelen;
   membuf_t outbuf;
   char *cache_nonce = NULL;
+  int opt_preset;
   char *p;
 
+  opt_preset = has_option (line, "--preset");
   no_protection = has_option (line, "--no-protection");
   line = skip_options (line);
 
@@ -874,7 +879,7 @@ cmd_genkey (assuan_context_t ctx, char *line)
   init_membuf (&outbuf, 512);
 
   rc = agent_genkey (ctrl, cache_nonce, (char*)value, valuelen, no_protection,
-                     &outbuf);
+                     opt_preset, &outbuf);
   xfree (value);
   if (rc)
     clear_outbuf (&outbuf);
diff --git a/agent/genkey.c b/agent/genkey.c
index f70526d..95e0a64 100644
--- a/agent/genkey.c
+++ b/agent/genkey.c
@@ -357,7 +357,7 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
 int
 agent_genkey (ctrl_t ctrl, const char *cache_nonce,
               const char *keyparam, size_t keyparamlen, int no_protection,
-              membuf_t *outbuf)
+              int preset, membuf_t *outbuf)
 {
   gcry_sexp_t s_keyparam, s_key, s_private, s_public;
   char *passphrase;
@@ -434,6 +434,16 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
           && !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
                                passphrase, 900 /*seconds*/))
         agent_write_status (ctrl, "CACHE_NONCE", cache_nonce, NULL);
+      if (preset && !no_protection)
+	{
+	  unsigned char grip[20];
+	  char hexgrip[40+1];
+	  if (gcry_pk_get_keygrip (s_private, grip))
+	    {
+	      bin2hex(grip, 20, hexgrip);
+	      rc = agent_put_cache (hexgrip, CACHE_MODE_ANY, passphrase, 900);
+	    }
+	}
     }
   xfree (passphrase);
   passphrase = NULL;

commit 893b455a3da5b5af2214657ead0a4994102c2714
Author: Ben Kibbey <bjk at luxsci.net>
Date:   Wed Apr 6 19:23:05 2011 -0400

    Added KEYINFO field to show the protection type of a key. This differs from the second field which shows the location of the key.

diff --git a/agent/ChangeLog b/agent/ChangeLog
index 5f14306..b05c174 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,3 +1,7 @@
+2011-04-06  Ben Kibbey <bjk at luxsci.net>
+
+	* command.c: (do_one_keyinfo): Add protection type field.
+
 2011-03-10  Werner Koch  <wk at g10code.com>
 
 	* protect.c (hash_passphrase): Use the new gcry_kdf_derive.
diff --git a/agent/command.c b/agent/command.c
index 9df72aa..d53ca5e 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -938,7 +938,7 @@ static const char hlp_keyinfo[] =
   "available keys are returned.  The information is returned as a\n"
   "status line unless --data was specified, with this format:\n"
   "\n"
-  "  KEYINFO <keygrip> <type> <serialno> <idstr> <cached>\n"
+  "  KEYINFO <keygrip> <type> <serialno> <idstr> <cached> <protection>\n"
   "\n"
   "KEYGRIP is the keygrip.\n"
   "\n"
@@ -957,6 +957,11 @@ static const char hlp_keyinfo[] =
   "CACHED is 1 if the passphrase for the key was found in the key cache.\n"
   "       If not, a '-' is used instead.\n"
   "\n"
+  "PROTECTION describes the key protection type:\n"
+  "    'P' - The key is protected with a passphrase,\n"
+  "    'C' - The key is not protected,\n"
+  "    '-' - Unknown protection.\n"
+  "\n"
   "More information may be added in the future.";
 static gpg_error_t
 do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
@@ -970,6 +975,7 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
   char *idstr = NULL;
   const char *keytypestr;
   const char *cached;
+  const char *protectionstr;
   char *pw;
 
   err = agent_key_info_from_file (ctrl, grip, &keytype, &shadow_info);
@@ -979,13 +985,17 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
   /* Reformat the grip so that we use uppercase as good style. */
   bin2hex (grip, 20, hexgrip);
 
-  if (keytype == PRIVATE_KEY_CLEAR
-      || keytype == PRIVATE_KEY_PROTECTED)
-    keytypestr = "D";
-  else if (keytype == PRIVATE_KEY_SHADOWED)
-    keytypestr = "T";
-  else
-    keytypestr = "-";
+  switch (keytype)
+    {
+    case PRIVATE_KEY_CLEAR: protectionstr = "C"; keytypestr = "D";
+      break;
+    case PRIVATE_KEY_PROTECTED: protectionstr = "P"; keytypestr = "D";
+      break;
+    case PRIVATE_KEY_SHADOWED: protectionstr = "-"; keytypestr = "T";
+      break;
+    default: protectionstr = "-"; keytypestr = "-";
+      break;
+    }
 
   /* Here we have a little race by doing the cache check separately
      from the retrieval function.  Given that the cache flag is only a
@@ -1008,15 +1018,16 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
                               serialno? serialno : "-",
                               idstr? idstr : "-",
                               cached,
+			      protectionstr,
                               NULL);
   else
     {
       char *string;
 
-      string = xtryasprintf ("%s %s %s %s %s\n",
+      string = xtryasprintf ("%s %s %s %s %s %s\n",
                              hexgrip, keytypestr,
                              serialno? serialno : "-",
-                             idstr? idstr : "-", cached);
+                             idstr? idstr : "-", cached, protectionstr);
       if (!string)
         err = gpg_error_from_syserror ();
       else

commit f1e9f510ec70f2bb64f1b61b2b040d8d3103af32
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Apr 12 16:30:08 2011 +0200

    Add code for explicit selection of pooled A records.
    
    To better cope with round robin pooled A records like keys.gnupg.net
    we need to keep some information on unresponsive hosts etc.  What we
    do now is to resolve the hostnames, remember them and select a random
    one.  If a host is dead it will be marked and a different one
    selected.  This is intended to solve the problem of long timeouts due
    to unresponsive hosts.
    
    The code is not yet finished but selection works.

diff --git a/common/ChangeLog b/common/ChangeLog
index 6253867..ba7794e 100644
--- a/common/ChangeLog
+++ b/common/ChangeLog
@@ -1,3 +1,7 @@
+2011-04-01  Werner Koch  <wk at g10code.com>
+
+	* sysutils.c (get_uint_nonce): New.
+
 2011-03-03  Werner Koch  <wk at g10code.com>
 
 	* estream.c (struct estream_list): Rename to estream_list_s and
diff --git a/common/sysutils.c b/common/sysutils.c
index a94d1fc..648e70f 100644
--- a/common/sysutils.c
+++ b/common/sysutils.c
@@ -150,6 +150,17 @@ get_session_marker (size_t *rlen)
   return marker;
 }
 
+/* Return a random number in an unsigned int. */
+unsigned int
+get_uint_nonce (void)
+{
+  unsigned int value;
+
+  gcry_create_nonce (&value, sizeof value);
+  return value;
+}
+
+
 
 #if 0 /* not yet needed - Note that this will require inclusion of
          cmacros.am in Makefile.am */
diff --git a/common/sysutils.h b/common/sysutils.h
index a2f74f9..3559b34 100644
--- a/common/sysutils.h
+++ b/common/sysutils.h
@@ -41,6 +41,7 @@ void trap_unaligned (void);
 int  disable_core_dumps (void);
 int  enable_core_dumps (void);
 const unsigned char *get_session_marker (size_t *rlen);
+unsigned int get_uint_nonce (void);
 /*int check_permissions (const char *path,int extension,int checkonly);*/
 void gnupg_sleep (unsigned int seconds);
 int translate_sys2libc_fd (gnupg_fd_t fd, int for_write);
diff --git a/dirmngr/ChangeLog b/dirmngr/ChangeLog
index bb40fe1..f7ac887 100644
--- a/dirmngr/ChangeLog
+++ b/dirmngr/ChangeLog
@@ -1,3 +1,13 @@
+2011-04-12  Werner Koch  <wk at g10code.com>
+
+	* ks-engine-hkp.c (ks_hkp_search, ks_hkp_get, ks_hkp_put): Factor
+	code out to ..
+	(make_host_part): new.
+	(hostinfo_s): New.
+	(create_new_hostinfo, find_hostinfo, sort_hostpool)
+	(select_random_host, map_host, mark_host_dead)
+	(ks_hkp_print_hosttable): New.
+
 2011-02-23  Werner Koch  <wk at g10code.com>
 
 	* certcache.c (get_cert_bysubject): Take care of a NULL argument.
diff --git a/dirmngr/ks-action.c b/dirmngr/ks-action.c
index 1f876d0..14de4d6 100644
--- a/dirmngr/ks-action.c
+++ b/dirmngr/ks-action.c
@@ -76,7 +76,7 @@ ks_action_help (ctrl_t ctrl, const char *url)
         return err;
     }
 
-  /* Call all engines to geive them a chance to print a help sting.  */
+  /* Call all engines to give them a chance to print a help sting.  */
   err = ks_hkp_help (ctrl, parsed_uri);
   if (!err)
     err = ks_http_help (ctrl, parsed_uri);
diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
index 5ad61fd..0dd9a64 100644
--- a/dirmngr/ks-engine-hkp.c
+++ b/dirmngr/ks-engine-hkp.c
@@ -17,12 +17,20 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#warning fixme Windows part not yet done
 #include <config.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#ifdef HAVE_W32_SYSTEM
+# include <windows.h>
+#else /*!HAVE_W32_SYSTEM*/
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netdb.h>
+#endif /*!HAVE_W32_SYSTEM*/
 
 #include "dirmngr.h"
 #include "misc.h"
@@ -36,6 +44,359 @@
 /* How many redirections do we allow.  */
 #define MAX_REDIRECTS 2
 
+/* Objects used to maintain information about hosts.  */
+struct hostinfo_s;
+typedef struct hostinfo_s *hostinfo_t;
+struct hostinfo_s
+{
+  time_t lastfail;   /* Time we tried to connect and failed.  */
+  time_t lastused;   /* Time of last use.  */
+  int *pool;         /* A -1 terminated array with indices into
+                        HOSTTABLE or NULL if NAME is not a pool
+                        name.  */
+  int poolidx;       /* Index into POOL with the used host.  */
+  unsigned int v4:1; /* Host supports AF_INET.  */
+  unsigned int v6:1; /* Host supports AF_INET6.  */
+  unsigned int dead:1; /* Host is currently unresponsive.  */
+  char name[1];      /* The hostname.  */
+};
+
+
+/* An array of hostinfo_t for all hosts requested by the caller or
+   resolved from a pool name and its allocated size.*/
+static hostinfo_t *hosttable;
+static int hosttable_size;
+
+/* The number of host slots we initally allocate for HOSTTABLE.  */
+#define INITIAL_HOSTTABLE_SIZE 10
+
+
+/* Create a new hostinfo object, fill in NAME and put it into
+   HOSTTABLE.  Return the index into hosttable on success or -1 on
+   error. */
+static int
+create_new_hostinfo (const char *name)
+{
+  hostinfo_t hi, *newtable;
+  int newsize;
+  int idx, rc;
+
+  hi = xtrymalloc (sizeof *hi + strlen (name));
+  if (!hi)
+    return -1;
+  strcpy (hi->name, name);
+  hi->pool = NULL;
+  hi->poolidx = -1;
+  hi->lastused = (time_t)(-1);
+  hi->lastfail = (time_t)(-1);
+  hi->v4 = 0;
+  hi->v6 = 0;
+
+  /* Add it to the hosttable. */
+  for (idx=0; idx < hosttable_size; idx++)
+    if (!hosttable[idx])
+      {
+        hosttable[idx] = hi;
+        return idx;
+      }
+  /* Need to extend the hosttable.  */
+  newsize = hosttable_size + INITIAL_HOSTTABLE_SIZE;
+  newtable = xtryrealloc (hosttable, newsize * sizeof *hosttable);
+  if (!newtable)
+    {
+      xfree (hi);
+      return -1;
+    }
+  hosttable = newtable;
+  idx = hosttable_size;
+  hosttable_size = newsize;
+  rc = idx;
+  hosttable[idx++] = hi;
+  while (idx < hosttable_size)
+    hosttable[idx++] = NULL;
+
+  return rc;
+}
+
+
+/* Find the host NAME in our table.  Return the index into the
+   hosttable or -1 if not found.  */
+static int
+find_hostinfo (const char *name)
+{
+  int idx;
+
+  for (idx=0; idx < hosttable_size; idx++)
+    if (hosttable[idx] && !ascii_strcasecmp (hosttable[idx]->name, name))
+      return idx;
+  return -1;
+}
+
+
+static int
+sort_hostpool (const void *xa, const void *xb)
+{
+  int a = *(int *)xa;
+  int b = *(int *)xb;
+
+  assert (a >= 0 && a < hosttable_size);
+  assert (b >= 0 && b < hosttable_size);
+  assert (hosttable[a]);
+  assert (hosttable[b]);
+
+  return ascii_strcasecmp (hosttable[a]->name, hosttable[b]->name);
+}
+
+
+/* Select a random host.  Consult TABLE which indices into the global
+   hosttable.  Returns index into TABLE or -1 if no host could be
+   selected.  */
+static int
+select_random_host (int *table)
+{
+  int *tbl;
+  size_t tblsize;
+  int pidx, idx;
+
+  /* We create a new table so that we select only from currently alive
+     hosts.  */
+  for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
+    if (hosttable[pidx] && !hosttable[pidx]->dead)
+      tblsize++;
+  if (!tblsize)
+    return -1; /* No hosts.  */
+
+  tbl = xtrymalloc (tblsize * sizeof *tbl);
+  if (!tbl)
+    return -1;
+  for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
+    if (hosttable[pidx] && !hosttable[pidx]->dead)
+      tbl[tblsize++] = pidx;
+
+  if (tblsize == 1)  /* Save a get_uint_nonce.  */
+    pidx = tbl[0];
+  else
+    pidx = get_uint_nonce () % tblsize;
+
+  xfree (tbl);
+  return pidx;
+}
+
+
+/* Map the host name NAME to the actual to be used host name.  This
+   allows us to manage round robin DNS names.  We use our own strategy
+   to choose one of the hosts.  For example we skip those hosts which
+   failed for some time and we stick to one host for a time
+   independent of DNS retry times.  */
+static char *
+map_host (const char *name)
+{
+  hostinfo_t hi;
+  int idx;
+
+  /* No hostname means localhost.  */
+  if (!name || !*name)
+    return xtrystrdup ("localhost");
+
+  /* See whether the host is in our table.  */
+  idx = find_hostinfo (name);
+  if (idx == -1)
+    {
+      /* We never saw this host.  Allocate a new entry.  */
+      struct addrinfo hints, *aibuf, *ai;
+      int *reftbl;
+      size_t reftblsize;
+      int refidx;
+
+      reftblsize = 100;
+      reftbl = xmalloc (reftblsize * sizeof *reftbl);
+      if (!reftbl)
+        return NULL;
+      refidx = 0;
+
+      idx = create_new_hostinfo (name);
+      if (idx == -1)
+        {
+          xfree (reftbl);
+          return NULL;
+        }
+      hi = hosttable[idx];
+
+      /* Find all A records for this entry and put them into the pool
+         list - if any.  */
+      memset (&hints, 0, sizeof (hints));
+      hints.ai_socktype = SOCK_STREAM;
+      if (!getaddrinfo (name, NULL, &hints, &aibuf))
+        {
+          for (ai = aibuf; ai; ai = ai->ai_next)
+            {
+              char tmphost[NI_MAXHOST];
+              int tmpidx;
+              int ec;
+              int i;
+
+              if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+                continue;
+
+              log_printhex ("getaddrinfo returned", ai->ai_addr,ai->ai_addrlen);
+              if ((ec=getnameinfo (ai->ai_addr, ai->ai_addrlen,
+                                   tmphost, sizeof tmphost,
+                                   NULL, 0, NI_NAMEREQD)))
+                log_info ("getnameinfo failed while checking `%s': %s\n",
+                          name, gai_strerror (ec));
+              else if (refidx+1 >= reftblsize)
+                {
+                  log_error ("getnameinfo returned for `%s': `%s'"
+                            " [index table full - ignored]\n", name, tmphost);
+                }
+              else
+                {
+
+                  if ((tmpidx = find_hostinfo (tmphost)) != -1)
+                    {
+                      log_info ("getnameinfo returned for `%s': `%s'"
+                                " [already known]\n", name, tmphost);
+                      if (ai->ai_family == AF_INET)
+                        hosttable[tmpidx]->v4 = 1;
+                      if (ai->ai_family == AF_INET6)
+                        hosttable[tmpidx]->v6 = 1;
+
+                      for (i=0; i < refidx; i++)
+                        if (reftbl[i] == tmpidx)
+                      break;
+                      if (!(i < refidx) && tmpidx != idx)
+                        reftbl[refidx++] = tmpidx;
+                    }
+                  else
+                    {
+                      log_info ("getnameinfo returned for `%s': `%s'\n",
+                                name, tmphost);
+                      /* Create a new entry.  */
+                      tmpidx = create_new_hostinfo (tmphost);
+                      if (tmpidx == -1)
+                        log_error ("map_host for `%s' problem: %s - `%s'"
+                                   " [ignored]\n",
+                                   name, strerror (errno), tmphost);
+                      else
+                        {
+                          if (ai->ai_family == AF_INET)
+                        hosttable[tmpidx]->v4 = 1;
+                          if (ai->ai_family == AF_INET6)
+                            hosttable[tmpidx]->v6 = 1;
+
+                          for (i=0; i < refidx; i++)
+                            if (reftbl[i] == tmpidx)
+                              break;
+                          if (!(i < refidx) && tmpidx != idx)
+                            reftbl[refidx++] = tmpidx;
+                        }
+                    }
+                }
+            }
+        }
+      reftbl[refidx] = -1;
+      if (refidx)
+        {
+          assert (!hi->pool);
+          hi->pool = xtryrealloc (reftbl, (refidx+1) * sizeof *reftbl);
+          if (!hi->pool)
+            {
+              log_error ("shrinking index table in map_host failed: %s\n",
+                         strerror (errno));
+              xfree (reftbl);
+            }
+          qsort (reftbl, refidx, sizeof *reftbl, sort_hostpool);
+        }
+      else
+        xfree (reftbl);
+    }
+
+  hi = hosttable[idx];
+  if (hi->pool)
+    {
+      /* If the currently selected host is now marked dead, force a
+         re-selection .  */
+      if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
+          && hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
+        hi->poolidx = -1;
+
+      /* Select a host if needed.  */
+      if (hi->poolidx == -1)
+        {
+          hi->poolidx = select_random_host (hi->pool);
+          if (hi->poolidx == -1)
+            {
+              log_error ("no alive host found in pool `%s'\n", name);
+              return NULL;
+            }
+        }
+
+      assert (hi->poolidx >= 0 && hi->poolidx < hosttable_size);
+      hi = hosttable[hi->poolidx];
+      assert (hi);
+    }
+
+  if (hi->dead)
+    {
+      log_error ("host `%s' marked as dead\n", hi->name);
+      return NULL;
+    }
+
+  return xtrystrdup (hi->name);
+}
+
+
+/* Mark the host NAME as dead.  */
+static void
+mark_host_dead (const char *name)
+{
+  hostinfo_t hi;
+  int idx;
+
+  if (!name || !*name || !strcmp (name, "localhost"))
+    return;
+
+  idx = find_hostinfo (name);
+  if (idx == -1)
+    return;
+  hi = hosttable[idx];
+  log_info ("marking host `%s' as dead%s\n", hi->name, hi->dead? " (again)":"");
+  hi->dead = 1;
+}
+
+
+/* Debug function to print the entire hosttable.  */
+void
+ks_hkp_print_hosttable (void)
+{
+  int idx, idx2;
+  hostinfo_t hi;
+
+  for (idx=0; idx < hosttable_size; idx++)
+    if ((hi=hosttable[idx]))
+      {
+        log_info ("hosttable %3d %s %s %s %s\n",
+                  idx, hi->v4? "4":" ", hi->v6? "6":" ",
+                  hi->dead? "d":" ", hi->name);
+        if (hi->pool)
+          {
+            log_info ("          -->");
+            for (idx2=0; hi->pool[idx2] != -1; idx2++)
+              {
+                log_printf (" %d", hi->pool[idx2]);
+                if (hi->poolidx == idx2)
+                  log_printf ("*");
+              }
+            log_printf ("\n");
+            /* for (idx2=0; hi->pool[idx2] != -1; idx2++) */
+            /*   log_info ("              (%s)\n", */
+            /*              hosttable[hi->pool[idx2]]->name); */
+          }
+      }
+}
+
+
+
 /* Print a help output for the schemata supported by this module. */
 gpg_error_t
 ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
@@ -57,6 +418,44 @@ ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
 }
 
 
+/* Build the remote part or the URL from SCHEME, HOST and an optional
+   PORT.  Returns an allocated string or NULL on failure and sets
+   ERRNO.  */
+static char *
+make_host_part (const char *scheme, const char *host, unsigned short port)
+{
+  char portstr[10];
+  char *hostname;
+  char *hostport;
+
+  /* Map scheme and port.  */
+  if (!strcmp (scheme, "hkps") || !strcmp (scheme,"https"))
+    {
+      scheme = "https";
+      strcpy (portstr, "443");
+    }
+  else /* HKP or HTTP.  */
+    {
+      scheme = "http";
+      strcpy (portstr, "11371");
+    }
+  if (port)
+    snprintf (portstr, sizeof portstr, "%hu", port);
+  else
+    {
+      /*fixme_do_srv_lookup ()*/
+    }
+
+  hostname = map_host (host);
+  if (!hostname)
+    return NULL;
+
+  hostport = strconcat (scheme, "://", hostname, ":", portstr, NULL);
+  xfree (hostname);
+  return hostport;
+}
+
+
 /* Send an HTTP request.  On success returns an estream object at
    R_FP.  HOSTPORTSTR is only used for diagnostics.  If POST_CB is not
    NULL a post request is used and that callback is called to allow
@@ -73,6 +472,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
   char *request_buffer = NULL;
 
   *r_fp = NULL;
+  return gpg_error (GPG_ERR_NOT_SUPPORTED);
  once_more:
   err = http_open (&http,
                    post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
@@ -244,8 +644,6 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
   gpg_error_t err;
   KEYDB_SEARCH_DESC desc;
   char fprbuf[2+40+1];
-  const char *scheme;
-  char portstr[10];
   char *hostport = NULL;
   char *request = NULL;
   estream_t fp = NULL;
@@ -289,29 +687,11 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
       return gpg_error (GPG_ERR_INV_USER_ID);
     }
 
-  /* Map scheme and port.  */
-  if (!strcmp (uri->scheme,"hkps") || !strcmp (uri->scheme,"https"))
-    {
-      scheme = "https";
-      strcpy (portstr, "443");
-    }
-  else /* HKP or HTTP.  */
-    {
-      scheme = "http";
-      strcpy (portstr, "11371");
-    }
-  if (uri->port)
-    snprintf (portstr, sizeof portstr, "%hu", uri->port);
-  else
-    {} /*fixme_do_srv_lookup ()*/
-
   /* Build the request string.  */
   {
     char *searchkey;
 
-    hostport = strconcat (scheme, "://",
-                          *uri->host? uri->host: "localhost",
-                          ":", portstr, NULL);
+    hostport = make_host_part (uri->scheme, uri->host, uri->port);
     if (!hostport)
       {
         err = gpg_error_from_syserror ();
@@ -382,8 +762,6 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
   gpg_error_t err;
   KEYDB_SEARCH_DESC desc;
   char kidbuf[8+1];
-  const char *scheme;
-  char portstr[10];
   char *hostport = NULL;
   char *request = NULL;
   estream_t fp = NULL;
@@ -416,43 +794,23 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
       return gpg_error (GPG_ERR_INV_USER_ID);
     }
 
-  /* Map scheme and port.  */
-  if (!strcmp (uri->scheme,"hkps") || !strcmp (uri->scheme,"https"))
+  /* Build the request string.  */
+  hostport = make_host_part (uri->scheme, uri->host, uri->port);
+  if (!hostport)
     {
-      scheme = "https";
-      strcpy (portstr, "443");
+      err = gpg_error_from_syserror ();
+      goto leave;
     }
-  else /* HKP or HTTP.  */
+
+  request = strconcat (hostport,
+                       "/pks/lookup?op=get&options=mr&search=0x",
+                       kidbuf,
+                       NULL);
+  if (!request)
     {
-      scheme = "http";
-      strcpy (portstr, "11371");
+      err = gpg_error_from_syserror ();
+      goto leave;
     }
-  if (uri->port)
-    snprintf (portstr, sizeof portstr, "%hu", uri->port);
-  else
-    {} /*fixme_do_srv_lookup ()*/
-
-  /* Build the request string.  */
-  {
-    hostport = strconcat (scheme, "://",
-                          *uri->host? uri->host: "localhost",
-                          ":", portstr, NULL);
-    if (!hostport)
-      {
-        err = gpg_error_from_syserror ();
-        goto leave;
-      }
-
-    request = strconcat (hostport,
-                         "/pks/lookup?op=get&options=mr&search=0x",
-                         kidbuf,
-                         NULL);
-    if (!request)
-      {
-        err = gpg_error_from_syserror ();
-        goto leave;
-      }
-  }
 
   /* Send the request.  */
   err = send_request (ctrl, request, hostport, NULL, NULL, &fp);
@@ -507,8 +865,6 @@ gpg_error_t
 ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
 {
   gpg_error_t err;
-  const char *scheme;
-  char portstr[10];
   char *hostport = NULL;
   char *request = NULL;
   estream_t fp = NULL;
@@ -517,22 +873,6 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
 
   parm.datastring = NULL;
 
-  /* Map scheme and port.  */
-  if (!strcmp (uri->scheme,"hkps") || !strcmp (uri->scheme,"https"))
-    {
-      scheme = "https";
-      strcpy (portstr, "443");
-    }
-  else /* HKP or HTTP.  */
-    {
-      scheme = "http";
-      strcpy (portstr, "11371");
-    }
-  if (uri->port)
-    snprintf (portstr, sizeof portstr, "%hu", uri->port);
-  else
-    {} /*fixme_do_srv_lookup ()*/
-
   err = armor_data (&armored, data, datalen);
   if (err)
     goto leave;
@@ -547,9 +887,7 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
   armored = NULL;
 
   /* Build the request string.  */
-  hostport = strconcat (scheme, "://",
-                        *uri->host? uri->host: "localhost",
-                        ":", portstr, NULL);
+  hostport = make_host_part (uri->scheme, uri->host, uri->port);
   if (!hostport)
     {
       err = gpg_error_from_syserror ();
diff --git a/dirmngr/ks-engine.h b/dirmngr/ks-engine.h
index 8b55144..cda31a7 100644
--- a/dirmngr/ks-engine.h
+++ b/dirmngr/ks-engine.h
@@ -27,6 +27,7 @@
 gpg_error_t ks_print_help (ctrl_t ctrl, const char *text);
 
 /*-- ks-engine-hkp.c --*/
+void ks_hkp_print_hosttable (void);
 gpg_error_t ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri);
 gpg_error_t ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
                            estream_t *r_fp);
diff --git a/dirmngr/server.c b/dirmngr/server.c
index 1a244c8..76d36c1 100644
--- a/dirmngr/server.c
+++ b/dirmngr/server.c
@@ -42,6 +42,7 @@
 #include "misc.h"
 #include "ldap-wrapper.h"
 #include "ks-action.h"
+#include "ks-engine.h"  /* (ks_hkp_print_hosttable) */
 
 /* To avoid DoS attacks we limit the size of a certificate to
    something reasonable. */
@@ -1374,12 +1375,13 @@ cmd_keyserver (assuan_context_t ctx, char *line)
 {
   ctrl_t ctrl = assuan_get_pointer (ctx);
   gpg_error_t err;
-  int clear_flag, add_flag, help_flag;
+  int clear_flag, add_flag, help_flag, host_flag;
   uri_item_t item = NULL; /* gcc 4.4.5 is not able to detect that it
                              is always initialized.  */
 
   clear_flag = has_option (line, "--clear");
   help_flag = has_option (line, "--help");
+  host_flag = has_option (line, "--print-hosttable");
   line = skip_options (line);
   add_flag = !!*line;
 
@@ -1389,6 +1391,13 @@ cmd_keyserver (assuan_context_t ctx, char *line)
       goto leave;
     }
 
+  if (host_flag)
+    {
+      ks_hkp_print_hosttable ();
+      err = 0;
+      goto leave;
+    }
+
   if (add_flag)
     {
       item = xtrymalloc (sizeof *item + strlen (line));

commit 4206a2bd486f02072c8ba2731f4fade46c2a5581
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Mar 23 10:07:59 2011 +0100

    Detect premature EOF while parsing corrupted key packets.
    
    This helps in the case of an unknown key algorithm with a corrupted
    packet which claims a longer packet length.  This used to allocate the
    announced packet length and then tried to fill it up without detecting
    an EOF, thus taking quite some time.  IT is easy to fix, thus we do
    it.  However, there are many other ways to force gpg to use large
    amount of resources; thus as before it is strongly suggested that the
    sysadm uses ulimit do assign suitable resource limits to the gpg
    process.  Suggested by Timo Schulz.

diff --git a/g10/ChangeLog b/g10/ChangeLog
index f9edf57..ed958c5 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,8 @@
+2011-03-23  Werner Koch  <wk at g10code.com>
+
+	* parse-packet.c (read_rest): Drop unsed PARTIAL arg.  Rewrite to
+	detect premature EOF.  Suggested by Timo Schulz.
+
 2011-03-10  Werner Koch  <wk at g10code.com>
 
 	* passphrase.c (hash_passphrase): Remove.
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index fc11e9d..1171443 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -49,7 +49,7 @@ static int copy_packet (IOBUF inp, IOBUF out, int pkttype,
 			unsigned long pktlen, int partial);
 static void skip_packet (IOBUF inp, int pkttype,
 			 unsigned long pktlen, int partial);
-static void *read_rest (IOBUF inp, size_t pktlen, int partial);
+static void *read_rest (IOBUF inp, size_t pktlen);
 static int parse_marker (IOBUF inp, int pkttype, unsigned long pktlen);
 static int parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
 			    PACKET * packet);
@@ -720,24 +720,35 @@ skip_packet (IOBUF inp, int pkttype, unsigned long pktlen, int partial)
 }
 
 
+/* Read PKTLEN bytes form INP and return them in a newly allocated
+   buffer.  In case of an error NULL is returned and a error messages
+   printed.  */
 static void *
-read_rest (IOBUF inp, size_t pktlen, int partial)
+read_rest (IOBUF inp, size_t pktlen)
 {
-  byte *p;
-  int i;
+  int c;
+  byte *buf, *p;
 
-  if (partial)
+  buf = xtrymalloc (pktlen);
+  if (!buf)
     {
-      log_error ("read_rest: can't store stream data\n");
-      p = NULL;
+      gpg_error_t err = gpg_error_from_syserror ();
+      log_error ("error reading rest of packet: %s\n", gpg_strerror (err));
+      return NULL;
     }
-  else
+  for (p = buf; pktlen; pktlen--)
     {
-      p = xmalloc (pktlen);
-      for (i = 0; pktlen; pktlen--, i++)
-	p[i] = iobuf_get (inp);
+      c = iobuf_get (inp);
+      if (c == -1)
+        {
+          log_error ("premature eof while reading rest of packet\n");
+          xfree (buf);
+          return NULL;
+        }
+      *p++ = c;
     }
-  return p;
+
+  return buf;
 }
 
 
@@ -1749,8 +1760,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
       else
 	{
 	  sig->data[0] =
-	    gcry_mpi_set_opaque (NULL, read_rest (inp, pktlen, 0),
-				 pktlen * 8);
+	    gcry_mpi_set_opaque (NULL, read_rest (inp, pktlen), pktlen * 8);
 	  pktlen = 0;
 	}
     }
@@ -1982,8 +1992,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
     {
       /* Unknown algorithm - put data into an opaque MPI.  */
       pk->pkey[0] = gcry_mpi_set_opaque (NULL,
-                                         read_rest (inp, pktlen, 0),
-                                         pktlen * 8);
+                                         read_rest (inp, pktlen), pktlen * 8);
       pktlen = 0;
       goto leave;
     }
@@ -2227,7 +2236,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
 	   * up to the end of the packet into the first SKEY
 	   * element.  */
 	  pk->pkey[npkey] = gcry_mpi_set_opaque (NULL,
-						 read_rest (inp, pktlen, 0),
+						 read_rest (inp, pktlen),
 						 pktlen * 8);
 	  pktlen = 0;
 	  if (list_mode)

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

Summary of changes:
 agent/ChangeLog         |   16 ++
 agent/agent.h           |    8 +-
 agent/command.c         |   60 ++++--
 agent/genkey.c          |   15 ++-
 common/ChangeLog        |    4 +
 common/sysutils.c       |   11 +
 common/sysutils.h       |    1 +
 dirmngr/ChangeLog       |   10 +
 dirmngr/ks-action.c     |    2 +-
 dirmngr/ks-engine-hkp.c |  492 +++++++++++++++++++++++++++++++++++++++--------
 dirmngr/ks-engine.h     |    1 +
 dirmngr/server.c        |   11 +-
 g10/ChangeLog           |    5 +
 g10/parse-packet.c      |   43 +++--
 14 files changed, 563 insertions(+), 116 deletions(-)


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




More information about the Gnupg-commits mailing list