g10: Fix segfault on unsupported curve.
[gnupg.git] / g10 / keyserver.c
index 3a3bc40..e9ccb58 100644 (file)
@@ -1,6 +1,7 @@
 /* keyserver.c - generic keyserver code
  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
  *               2009, 2011, 2012 Free Software Foundation, Inc.
 /* keyserver.c - generic keyserver code
  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
  *               2009, 2011, 2012 Free Software Foundation, Inc.
+ * Copyright (C) 2014 Werner Koch
  *
  * This file is part of GnuPG.
  *
  *
  * This file is part of GnuPG.
  *
 #include "trustdb.h"
 #include "keyserver-internal.h"
 #include "util.h"
 #include "trustdb.h"
 #include "keyserver-internal.h"
 #include "util.h"
-#include "dns-cert.h"
-#include "pka.h"
-#ifdef USE_DNS_SRV
-#include "srv.h"
-#endif
 #include "membuf.h"
 #include "call-dirmngr.h"
 
 #include "membuf.h"
 #include "call-dirmngr.h"
 
@@ -90,13 +86,14 @@ static struct parse_options keyserver_opts[]=
   {
     /* some of these options are not real - just for the help
        message */
   {
     /* some of these options are not real - just for the help
        message */
-    {"max-cert-size",0,NULL,NULL},
+    {"max-cert-size",0,NULL,NULL},  /* MUST be the first in this array! */
+    {"http-proxy", KEYSERVER_HTTP_PROXY, NULL, /* MUST be the second!  */
+     N_("override proxy options set for dirmngr")},
+
     {"include-revoked",0,NULL,N_("include revoked keys in search results")},
     {"include-subkeys",0,NULL,N_("include subkeys when searching by key ID")},
     {"include-revoked",0,NULL,N_("include revoked keys in search results")},
     {"include-subkeys",0,NULL,N_("include subkeys when searching by key ID")},
-    {"use-temp-files",0,NULL,
-     N_("use temporary files to pass data to keyserver helpers")},
-    {"keep-temp-files",KEYSERVER_KEEP_TEMP_FILES,NULL,
-     N_("do not delete temporary files after using them")},
+    {"timeout", KEYSERVER_TIMEOUT, NULL,
+     N_("override timeout options set for dirmngr")},
     {"refresh-add-fake-v3-keyids",KEYSERVER_ADD_FAKE_V3,NULL,
      NULL},
     {"auto-key-retrieve",KEYSERVER_AUTO_KEY_RETRIEVE,NULL,
     {"refresh-add-fake-v3-keyids",KEYSERVER_ADD_FAKE_V3,NULL,
      NULL},
     {"auto-key-retrieve",KEYSERVER_AUTO_KEY_RETRIEVE,NULL,
@@ -110,9 +107,9 @@ static struct parse_options keyserver_opts[]=
 
 static gpg_error_t keyserver_get (ctrl_t ctrl,
                                   KEYDB_SEARCH_DESC *desc, int ndesc,
 
 static gpg_error_t keyserver_get (ctrl_t ctrl,
                                   KEYDB_SEARCH_DESC *desc, int ndesc,
-                                  struct keyserver_spec *keyserver);
-static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs,
-                                  struct keyserver_spec *keyserver);
+                                  struct keyserver_spec *override_keyserver,
+                                  unsigned char **r_fpr, size_t *r_fprlen);
+static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs);
 
 
 /* Reasonable guess.  The commonly used test key simon.josefsson.org
 
 
 /* Reasonable guess.  The commonly used test key simon.josefsson.org
@@ -121,27 +118,28 @@ static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs,
 
 static size_t max_cert_size=DEFAULT_MAX_CERT_SIZE;
 
 
 static size_t max_cert_size=DEFAULT_MAX_CERT_SIZE;
 
+
 static void
 static void
-add_canonical_option(char *option,strlist_t *list)
+warn_kshelper_option(char *option, int noisy)
 {
 {
-  char *arg=argsplit(option);
-
-  if(arg)
-    {
-      char *joined;
-
-      joined=xmalloc(strlen(option)+1+strlen(arg)+1);
-      /* Make a canonical name=value form with no spaces */
-      strcpy(joined,option);
-      strcat(joined,"=");
-      strcat(joined,arg);
-      append_to_strlist(list,joined);
-      xfree(joined);
-    }
-  else
-    append_to_strlist(list,option);
+  char *p;
+
+  if ((p=strchr (option, '=')))
+    *p = 0;
+
+  if (!strcmp (option, "ca-cert-file"))
+    log_info ("keyserver option '%s' is obsolete; please use "
+              "'%s' in dirmngr.conf\n",
+              "ca-cert-file", "hkp-cacert");
+  else if (!strcmp (option, "check-cert")
+           || !strcmp (option, "broken-http-proxy"))
+    log_info ("keyserver option '%s' is obsolete\n", option);
+  else if (noisy || opt.verbose)
+    log_info ("keyserver option '%s' is unknown\n", option);
 }
 
 }
 
+
+/* Called from main to parse the args for --keyserver-options.  */
 int
 parse_keyserver_options(char *options)
 {
 int
 parse_keyserver_options(char *options)
 {
@@ -150,47 +148,24 @@ parse_keyserver_options(char *options)
   char *max_cert=NULL;
 
   keyserver_opts[0].value=&max_cert;
   char *max_cert=NULL;
 
   keyserver_opts[0].value=&max_cert;
+  keyserver_opts[1].value=&opt.keyserver_options.http_proxy;
 
   while((tok=optsep(&options)))
     {
       if(tok[0]=='\0')
        continue;
 
 
   while((tok=optsep(&options)))
     {
       if(tok[0]=='\0')
        continue;
 
-      /* For backwards compatibility.  1.2.x used honor-http-proxy and
-        there are a good number of documents published that recommend
-        it. */
-      if(ascii_strcasecmp(tok,"honor-http-proxy")==0)
-       tok="http-proxy";
-      else if(ascii_strcasecmp(tok,"no-honor-http-proxy")==0)
-       tok="no-http-proxy";
-
       /* We accept quite a few possible options here - some options to
         handle specially, the keyserver_options list, and import and
       /* We accept quite a few possible options here - some options to
         handle specially, the keyserver_options list, and import and
-        export options that pertain to keyserver operations.  Note
-        that you must use strncasecmp here as there might be an
-        =argument attached which will foil the use of strcasecmp. */
-
-#ifdef EXEC_TEMPFILE_ONLY
-      if(ascii_strncasecmp(tok,"use-temp-files",14)==0 ||
-             ascii_strncasecmp(tok,"no-use-temp-files",17)==0)
-       log_info(_("WARNING: keyserver option '%s' is not used"
-                  " on this platform\n"),tok);
-#else
-      if(ascii_strncasecmp(tok,"use-temp-files",14)==0)
-       opt.keyserver_options.options|=KEYSERVER_USE_TEMP_FILES;
-      else if(ascii_strncasecmp(tok,"no-use-temp-files",17)==0)
-       opt.keyserver_options.options&=~KEYSERVER_USE_TEMP_FILES;
-#endif
-      else if(!parse_options(tok,&opt.keyserver_options.options,
-                            keyserver_opts,0)
-        && !parse_import_options(tok,
-                                 &opt.keyserver_options.import_options,0)
-        && !parse_export_options(tok,
-                                 &opt.keyserver_options.export_options,0))
+        export options that pertain to keyserver operations.  */
+
+      if (!parse_options (tok,&opt.keyserver_options.options, keyserver_opts,0)
+          && !parse_import_options(tok,&opt.keyserver_options.import_options,0)
+          && !parse_export_options(tok,&opt.keyserver_options.export_options,0))
        {
        {
-         /* All of the standard options have failed, so the option is
-            destined for a keyserver plugin. */
-         add_canonical_option(tok,&opt.keyserver_options.other);
+         /* All of the standard options have failed, so the option was
+            destined for a keyserver plugin as used by GnuPG < 2.1 */
+         warn_kshelper_option (tok, 1);
        }
     }
 
        }
     }
 
@@ -205,6 +180,7 @@ parse_keyserver_options(char *options)
   return ret;
 }
 
   return ret;
 }
 
+
 void
 free_keyserver_spec(struct keyserver_spec *keyserver)
 {
 void
 free_keyserver_spec(struct keyserver_spec *keyserver)
 {
@@ -259,8 +235,7 @@ keyserver_match(struct keyserver_spec *spec)
    keyserver/ksutil.c for limited use in gpgkeys_ldap or the like. */
 
 keyserver_spec_t
    keyserver/ksutil.c for limited use in gpgkeys_ldap or the like. */
 
 keyserver_spec_t
-parse_keyserver_uri (const char *string,int require_scheme,
-                    const char *configname,unsigned int configlineno)
+parse_keyserver_uri (const char *string,int require_scheme)
 {
   int assume_hkp=0;
   struct keyserver_spec *keyserver;
 {
   int assume_hkp=0;
   struct keyserver_spec *keyserver;
@@ -283,7 +258,7 @@ parse_keyserver_uri (const char *string,int require_scheme,
       options++;
 
       while((tok=optsep(&options)))
       options++;
 
       while((tok=optsep(&options)))
-       add_canonical_option(tok,&keyserver->options);
+       warn_kshelper_option (tok, 0);
     }
 
   /* Get the scheme */
     }
 
   /* Get the scheme */
@@ -342,11 +317,8 @@ parse_keyserver_uri (const char *string,int require_scheme,
 
   if(ascii_strcasecmp(keyserver->scheme,"x-broken-hkp")==0)
     {
 
   if(ascii_strcasecmp(keyserver->scheme,"x-broken-hkp")==0)
     {
-      deprecated_warning(configname,configlineno,"x-broken-hkp",
-                        "--keyserver-options ","broken-http-proxy");
-      xfree(keyserver->scheme);
-      keyserver->scheme=xstrdup("hkp");
-      append_to_strlist(&opt.keyserver_options.other,"broken-http-proxy");
+      log_info ("keyserver option '%s' is obsolete\n",
+                "x-broken-hkp");
     }
   else if(ascii_strcasecmp(keyserver->scheme,"x-hkp")==0)
     {
     }
   else if(ascii_strcasecmp(keyserver->scheme,"x-hkp")==0)
     {
@@ -485,7 +457,7 @@ parse_preferred_keyserver(PKT_signature *sig)
 
       memcpy(dupe,p,plen);
       dupe[plen]='\0';
 
       memcpy(dupe,p,plen);
       dupe[plen]='\0';
-      spec=parse_keyserver_uri(dupe,1,NULL,0);
+      spec = parse_keyserver_uri (dupe, 1);
       xfree(dupe);
     }
 
       xfree(dupe);
     }
 
@@ -819,7 +791,7 @@ show_prompt (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int numdesc,
           }
         for (idx = 0; idx < numidx; idx++)
           selarray[idx] = desc[numarray[idx]-1];
           }
         for (idx = 0; idx < numidx; idx++)
           selarray[idx] = desc[numarray[idx]-1];
-        err = keyserver_get (ctrl, selarray, numidx, NULL);
+        err = keyserver_get (ctrl, selarray, numidx, NULL, NULL, NULL);
         xfree (selarray);
       }
     }
         xfree (selarray);
       }
     }
@@ -834,7 +806,7 @@ show_prompt (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int numdesc,
    KS_SEARCH command.  If SPECIAL is 0, LINE is the actual data line
    received with all escaping removed and guaranteed to be exactly one
    line with stripped LF; an EOF is indicated by LINE passed as NULL.
    KS_SEARCH command.  If SPECIAL is 0, LINE is the actual data line
    received with all escaping removed and guaranteed to be exactly one
    line with stripped LF; an EOF is indicated by LINE passed as NULL.
-   If special is 1, the line conatins the source of the information
+   If special is 1, the line contains the source of the information
    (usually an URL).  LINE may be modified after return.  */
 static gpg_error_t
 search_line_handler (void *opaque, int special, char *line)
    (usually an URL).  LINE may be modified after return.  */
 static gpg_error_t
 search_line_handler (void *opaque, int special, char *line)
@@ -863,7 +835,7 @@ search_line_handler (void *opaque, int special, char *line)
   /* Print the received line.  */
   if (opt.with_colons && line)
     {
   /* Print the received line.  */
   if (opt.with_colons && line)
     {
-      log_debug ("%s\n",line);
+      es_printf ("%s\n", line);
     }
 
   /* Look for an info: line.  The only current info: values defined
     }
 
   /* Look for an info: line.  The only current info: values defined
@@ -1032,13 +1004,93 @@ keyserver_export (ctrl_t ctrl, strlist_t users)
 
   if(sl)
     {
 
   if(sl)
     {
-      rc = keyserver_put (ctrl, sl, opt.keyserver);
+      rc = keyserver_put (ctrl, sl);
       free_strlist(sl);
     }
 
   return rc;
 }
 
       free_strlist(sl);
     }
 
   return rc;
 }
 
+
+/* Structure to convey the arg to keyserver_retrieval_screener.  */
+struct ks_retrieval_screener_arg_s
+{
+  KEYDB_SEARCH_DESC *desc;
+  int ndesc;
+};
+
+
+/* Check whether a key matches the search description.  The function
+   returns 0 if the key shall be imported.  */
+static gpg_error_t
+keyserver_retrieval_screener (kbnode_t keyblock, void *opaque)
+{
+  struct ks_retrieval_screener_arg_s *arg = opaque;
+  KEYDB_SEARCH_DESC *desc = arg->desc;
+  int ndesc = arg->ndesc;
+  kbnode_t node;
+  PKT_public_key *pk;
+  int n;
+  u32 keyid[2];
+  byte fpr[MAX_FINGERPRINT_LEN];
+  size_t fpr_len = 0;
+
+  /* Secret keys are not expected from a keyserver.  We do not
+     care about secret subkeys because the import code takes care
+     of skipping them.  Not allowing an import of a public key
+     with a secret subkey would make it too easy to inhibit the
+     downloading of a public key.  Recall that keyservers do only
+     limited checks.  */
+  node = find_kbnode (keyblock, PKT_SECRET_KEY);
+  if (node)
+    return gpg_error (GPG_ERR_GENERAL);   /* Do not import. */
+
+  if (!ndesc)
+    return 0; /* Okay if no description given.  */
+
+  /* Loop over all key packets.  */
+  for (node = keyblock; node; node = node->next)
+    {
+      if (node->pkt->pkttype != PKT_PUBLIC_KEY
+          && node->pkt->pkttype != PKT_PUBLIC_SUBKEY)
+        continue;
+
+      pk = node->pkt->pkt.public_key;
+      fingerprint_from_pk (pk, fpr, &fpr_len);
+      keyid_from_pk (pk, keyid);
+
+      /* Compare requested and returned fingerprints if available. */
+      for (n = 0; n < ndesc; n++)
+        {
+          if (desc[n].mode == KEYDB_SEARCH_MODE_FPR20)
+            {
+              if (fpr_len == 20 && !memcmp (fpr, desc[n].u.fpr, 20))
+                return 0;
+            }
+          else if (desc[n].mode == KEYDB_SEARCH_MODE_FPR16)
+            {
+              if (fpr_len == 16 && !memcmp (fpr, desc[n].u.fpr, 16))
+                return 0;
+            }
+          else if (desc[n].mode == KEYDB_SEARCH_MODE_LONG_KID)
+            {
+              if (keyid[0] == desc[n].u.kid[0] && keyid[1] == desc[n].u.kid[1])
+                return 0;
+            }
+          else if (desc[n].mode == KEYDB_SEARCH_MODE_SHORT_KID)
+            {
+              if (keyid[1] == desc[n].u.kid[1])
+                return 0;
+            }
+          else /* No keyid or fingerprint - can't check.  */
+            return 0; /* allow import.  */
+        }
+    }
+
+  return gpg_error (GPG_ERR_GENERAL);
+}
+
+
 int
 keyserver_import (ctrl_t ctrl, strlist_t users)
 {
 int
 keyserver_import (ctrl_t ctrl, strlist_t users)
 {
@@ -1071,13 +1123,39 @@ keyserver_import (ctrl_t ctrl, strlist_t users)
     }
 
   if(count>0)
     }
 
   if(count>0)
-    rc=keyserver_get (ctrl, desc, count, NULL);
+    rc=keyserver_get (ctrl, desc, count, NULL, NULL, NULL);
 
   xfree(desc);
 
   return rc;
 }
 
 
   xfree(desc);
 
   return rc;
 }
 
+
+/* Return true if any keyserver has been configured. */
+int
+keyserver_any_configured (ctrl_t ctrl)
+{
+  return !gpg_dirmngr_ks_list (ctrl, NULL);
+}
+
+
+/* Import all keys that exactly match NAME */
+int
+keyserver_import_name (ctrl_t ctrl, const char *name,
+                       unsigned char **fpr, size_t *fprlen,
+                       struct keyserver_spec *keyserver)
+{
+  KEYDB_SEARCH_DESC desc;
+
+  memset (&desc, 0, sizeof desc);
+
+  desc.mode = KEYDB_SEARCH_MODE_EXACT;
+  desc.u.name = name;
+
+  return keyserver_get (ctrl, &desc, 1, keyserver, fpr, fprlen);
+}
+
+
 int
 keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
                         struct keyserver_spec *keyserver)
 int
 keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
                         struct keyserver_spec *keyserver)
@@ -1097,7 +1175,7 @@ keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
 
   /* TODO: Warn here if the fingerprint we got doesn't match the one
      we asked for? */
 
   /* TODO: Warn here if the fingerprint we got doesn't match the one
      we asked for? */
-  return keyserver_get (ctrl, &desc, 1, keyserver);
+  return keyserver_get (ctrl, &desc, 1, keyserver, NULL, NULL);
 }
 
 int
 }
 
 int
@@ -1112,24 +1190,33 @@ keyserver_import_keyid (ctrl_t ctrl,
   desc.u.kid[0]=keyid[0];
   desc.u.kid[1]=keyid[1];
 
   desc.u.kid[0]=keyid[0];
   desc.u.kid[1]=keyid[1];
 
-  return keyserver_get (ctrl, &desc,1, keyserver);
+  return keyserver_get (ctrl, &desc,1, keyserver, NULL, NULL);
 }
 
 /* code mostly stolen from do_export_stream */
 static int
 keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
 {
 }
 
 /* code mostly stolen from do_export_stream */
 static int
 keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
 {
-  int rc=0,ndesc,num=100;
-  KBNODE keyblock=NULL,node;
+  int rc = 0;
+  int num = 100;
+  kbnode_t keyblock = NULL;
+  kbnode_t node;
   KEYDB_HANDLE kdbhd;
   KEYDB_HANDLE kdbhd;
-  KEYDB_SEARCH_DESC *desc;
+  int ndesc;
+  KEYDB_SEARCH_DESC *desc = NULL;
   strlist_t sl;
 
   *count=0;
 
   *klist=xmalloc(sizeof(KEYDB_SEARCH_DESC)*num);
 
   strlist_t sl;
 
   *count=0;
 
   *klist=xmalloc(sizeof(KEYDB_SEARCH_DESC)*num);
 
-  kdbhd=keydb_new ();
+  kdbhd = keydb_new ();
+  if (!kdbhd)
+    {
+      rc = gpg_error_from_syserror ();
+      goto leave;
+    }
+  keydb_disable_caching (kdbhd);  /* We are looping the search.  */
 
   if(!users)
     {
 
   if(!users)
     {
@@ -1154,8 +1241,12 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
        }
     }
 
        }
     }
 
-  while (!(rc = keydb_search (kdbhd, desc, ndesc, NULL)))
+  for (;;)
     {
     {
+      rc = keydb_search (kdbhd, desc, ndesc, NULL);
+      if (rc)
+        break;  /* ready.  */
+
       if (!users)
        desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
 
       if (!users)
        desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
 
@@ -1163,7 +1254,7 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
       rc = keydb_get_keyblock (kdbhd, &keyblock );
       if( rc )
        {
       rc = keydb_get_keyblock (kdbhd, &keyblock );
       if( rc )
        {
-         log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
+          log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) );
          goto leave;
        }
 
          goto leave;
        }
 
@@ -1262,7 +1353,10 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
 
  leave:
   if(rc)
 
  leave:
   if(rc)
-    xfree(*klist);
+    {
+      xfree(*klist);
+      *klist = NULL;
+    }
   xfree(desc);
   keydb_release(kdbhd);
   release_kbnode(keyblock);
   xfree(desc);
   keydb_release(kdbhd);
   release_kbnode(keyblock);
@@ -1273,10 +1367,12 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
 /* Note this is different than the original HKP refresh.  It allows
    usernames to refresh only part of the keyring. */
 
 /* Note this is different than the original HKP refresh.  It allows
    usernames to refresh only part of the keyring. */
 
-int
+gpg_error_t
 keyserver_refresh (ctrl_t ctrl, strlist_t users)
 {
 keyserver_refresh (ctrl_t ctrl, strlist_t users)
 {
-  int rc,count,numdesc,fakev3=0;
+  gpg_error_t err;
+  int count, numdesc;
+  int fakev3 = 0;
   KEYDB_SEARCH_DESC *desc;
   unsigned int options=opt.keyserver_options.import_options;
 
   KEYDB_SEARCH_DESC *desc;
   unsigned int options=opt.keyserver_options.import_options;
 
@@ -1291,15 +1387,20 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
   opt.keyserver_options.import_options|=IMPORT_FAST;
 
   /* If refresh_add_fake_v3_keyids is on and it's a HKP or MAILTO
   opt.keyserver_options.import_options|=IMPORT_FAST;
 
   /* If refresh_add_fake_v3_keyids is on and it's a HKP or MAILTO
-     scheme, then enable fake v3 keyid generation. */
+     scheme, then enable fake v3 keyid generation.  Note that this
+     works only with a keyserver configured. gpg.conf
+     (i.e. opt.keyserver); however that method of configuring a
+     keyserver is deprecated and in any case it is questionable
+     whether we should keep on supporting these ancient and broken
+     keyservers.  */
   if((opt.keyserver_options.options&KEYSERVER_ADD_FAKE_V3) && opt.keyserver
      && (ascii_strcasecmp(opt.keyserver->scheme,"hkp")==0 ||
         ascii_strcasecmp(opt.keyserver->scheme,"mailto")==0))
     fakev3=1;
 
   if((opt.keyserver_options.options&KEYSERVER_ADD_FAKE_V3) && opt.keyserver
      && (ascii_strcasecmp(opt.keyserver->scheme,"hkp")==0 ||
         ascii_strcasecmp(opt.keyserver->scheme,"mailto")==0))
     fakev3=1;
 
-  rc=keyidlist(users,&desc,&numdesc,fakev3);
-  if(rc)
-    return rc;
+  err = keyidlist (users, &desc, &numdesc, fakev3);
+  if (err)
+    return err;
 
   count=numdesc;
   if(count>0)
 
   count=numdesc;
   if(count>0)
@@ -1313,14 +1414,17 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
            {
              struct keyserver_spec *keyserver=desc[i].skipfncvalue;
 
            {
              struct keyserver_spec *keyserver=desc[i].skipfncvalue;
 
+              if (!opt.quiet)
+                log_info (_("refreshing %d key from %s\n"), 1, keyserver->uri);
+
              /* We use the keyserver structure we parsed out before.
                 Note that a preferred keyserver without a scheme://
                 will be interpreted as hkp:// */
              /* We use the keyserver structure we parsed out before.
                 Note that a preferred keyserver without a scheme://
                 will be interpreted as hkp:// */
-             rc = keyserver_get (ctrl, &desc[i], 1, keyserver);
-             if(rc)
+             err = keyserver_get (ctrl, &desc[i], 1, keyserver, NULL, NULL);
+             if (err)
                log_info(_("WARNING: unable to refresh key %s"
                           " via %s: %s\n"),keystr_from_desc(&desc[i]),
                log_info(_("WARNING: unable to refresh key %s"
                           " via %s: %s\n"),keystr_from_desc(&desc[i]),
-                        keyserver->uri,g10_errstr(rc));
+                        keyserver->uri,gpg_strerror (err));
              else
                {
                  /* We got it, so mark it as NONE so we don't try and
              else
                {
                  /* We got it, so mark it as NONE so we don't try and
@@ -1337,16 +1441,21 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
 
   if(count>0)
     {
 
   if(count>0)
     {
-      if(opt.keyserver)
-       {
-         if(count==1)
-           log_info(_("refreshing 1 key from %s\n"),opt.keyserver->uri);
-         else
-           log_info(_("refreshing %d keys from %s\n"),
-                    count,opt.keyserver->uri);
-       }
+      char *tmpuri;
+
+      err = gpg_dirmngr_ks_list (ctrl, &tmpuri);
+      if (!err)
+        {
+          if (!opt.quiet)
+            {
+              log_info (ngettext("refreshing %d key from %s\n",
+                                 "refreshing %d keys from %s\n",
+                                 count), count, tmpuri);
+            }
+          xfree (tmpuri);
 
 
-      rc=keyserver_get (ctrl, desc, numdesc, NULL);
+          err = keyserver_get (ctrl, desc, numdesc, NULL, NULL, NULL);
+        }
     }
 
   xfree(desc);
     }
 
   xfree(desc);
@@ -1358,7 +1467,7 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
   if(!(opt.keyserver_options.import_options&IMPORT_FAST))
     check_or_update_trustdb ();
 
   if(!(opt.keyserver_options.import_options&IMPORT_FAST))
     check_or_update_trustdb ();
 
-  return rc;
+  return err;
 }
 
 
 }
 
 
@@ -1376,21 +1485,15 @@ keyserver_search (ctrl_t ctrl, strlist_t tokens)
   if (!tokens)
     return 0;  /* Return success if no patterns are given.  */
 
   if (!tokens)
     return 0;  /* Return success if no patterns are given.  */
 
-  if (!opt.keyserver)
-    {
-      log_error (_("no keyserver known (use option --keyserver)\n"));
-      return gpg_error (GPG_ERR_NO_KEYSERVER);
-    }
-
   /* Write global options */
 
   /* for(temp=opt.keyserver_options.other;temp;temp=temp->next) */
   /* Write global options */
 
   /* for(temp=opt.keyserver_options.other;temp;temp=temp->next) */
-  /*   fprintf(spawn->tochild,"OPTION %s\n",temp->d); */
+  /*   es_fprintf(spawn->tochild,"OPTION %s\n",temp->d); */
 
   /* Write per-keyserver options */
 
   /* for(temp=keyserver->options;temp;temp=temp->next) */
 
   /* Write per-keyserver options */
 
   /* for(temp=keyserver->options;temp;temp=temp->next) */
-  /*   fprintf(spawn->tochild,"OPTION %s\n",temp->d); */
+  /*   es_fprintf(spawn->tochild,"OPTION %s\n",temp->d); */
 
   {
     membuf_t mb;
 
   {
     membuf_t mb;
@@ -1467,23 +1570,16 @@ keyserver_search (ctrl_t ctrl, strlist_t tokens)
   return err;
 }
 
   return err;
 }
 
-
-
-/* Called using:
-
-import_name:
-  rc = keyserver_work (ctrl, KS_GETNAME, list, NULL,
-                       0, fpr, fpr_len, keyserver);
-
-import_ldap:
-  rc = keyserver_work (ctrl, KS_GETNAME, list, NULL,
-                       0, fpr, fpr_len, keyserver);
-
- */
-
+/* Helper for keyserver_get.  Here we only receive a chunk of the
+   description to be processed in one batch.  This is required due to
+   the limited number of patterns the dirmngr interface (KS_GET) can
+   grok and to limit the amount of temporary required memory.  */
 static gpg_error_t
 static gpg_error_t
-keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
-               struct keyserver_spec *keyserver)
+keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
+                     int *r_ndesc_used,
+                     import_stats_t stats_handle,
+                     struct keyserver_spec *override_keyserver,
+                     unsigned char **r_fpr, size_t *r_fprlen)
 
 {
   gpg_error_t err = 0;
 
 {
   gpg_error_t err = 0;
@@ -1491,12 +1587,26 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
   int idx, npat;
   estream_t datastream;
   char *source = NULL;
   int idx, npat;
   estream_t datastream;
   char *source = NULL;
+  size_t linelen;  /* Estimated linelen for KS_GET.  */
+  size_t n;
+
+#define MAX_KS_GET_LINELEN 950  /* Somewhat lower than the real limit.  */
+
+  *r_ndesc_used = 0;
 
   /* Create an array filled with a search pattern for each key.  The
      array is delimited by a NULL entry.  */
   pattern = xtrycalloc (ndesc+1, sizeof *pattern);
   if (!pattern)
     return gpg_error_from_syserror ();
 
   /* Create an array filled with a search pattern for each key.  The
      array is delimited by a NULL entry.  */
   pattern = xtrycalloc (ndesc+1, sizeof *pattern);
   if (!pattern)
     return gpg_error_from_syserror ();
+
+  /* Note that we break the loop as soon as our estimation of the to
+     be used line length reaches the limit.  But we do this only if we
+     have processed at leas one search requests so that an overlong
+     single request will be rejected only later by gpg_dirmngr_ks_get
+     but we are sure that R_NDESC_USED has been updated.  This avoids
+     a possible indefinite loop.  */
+  linelen = 9; /* "KS_GET --" */
   for (npat=idx=0; idx < ndesc; idx++)
     {
       int quiet = 0;
   for (npat=idx=0; idx < ndesc; idx++)
     {
       int quiet = 0;
@@ -1504,7 +1614,12 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
       if (desc[idx].mode == KEYDB_SEARCH_MODE_FPR20
           || desc[idx].mode == KEYDB_SEARCH_MODE_FPR16)
         {
       if (desc[idx].mode == KEYDB_SEARCH_MODE_FPR20
           || desc[idx].mode == KEYDB_SEARCH_MODE_FPR16)
         {
-          pattern[npat] = xtrymalloc (2+2*20+1);
+          n = 1+2+2*20;
+          if (idx && linelen + n > MAX_KS_GET_LINELEN)
+            break; /* Declare end of this chunk.  */
+          linelen += n;
+
+          pattern[npat] = xtrymalloc (n);
           if (!pattern[npat])
             err = gpg_error_from_syserror ();
           else
           if (!pattern[npat])
             err = gpg_error_from_syserror ();
           else
@@ -1518,6 +1633,11 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
         }
       else if(desc[idx].mode == KEYDB_SEARCH_MODE_LONG_KID)
         {
         }
       else if(desc[idx].mode == KEYDB_SEARCH_MODE_LONG_KID)
         {
+          n = 1+2+16;
+          if (idx && linelen + n > MAX_KS_GET_LINELEN)
+            break; /* Declare end of this chunk.  */
+          linelen += n;
+
           pattern[npat] = xtryasprintf ("0x%08lX%08lX",
                                         (ulong)desc[idx].u.kid[0],
                                         (ulong)desc[idx].u.kid[1]);
           pattern[npat] = xtryasprintf ("0x%08lX%08lX",
                                         (ulong)desc[idx].u.kid[0],
                                         (ulong)desc[idx].u.kid[1]);
@@ -1528,6 +1648,11 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
         }
       else if(desc[idx].mode == KEYDB_SEARCH_MODE_SHORT_KID)
         {
         }
       else if(desc[idx].mode == KEYDB_SEARCH_MODE_SHORT_KID)
         {
+          n = 1+2+8;
+          if (idx && linelen + n > MAX_KS_GET_LINELEN)
+            break; /* Declare end of this chunk.  */
+          linelen += n;
+
           pattern[npat] = xtryasprintf ("0x%08lX", (ulong)desc[idx].u.kid[1]);
           if (!pattern[npat])
             err = gpg_error_from_syserror ();
           pattern[npat] = xtryasprintf ("0x%08lX", (ulong)desc[idx].u.kid[1]);
           if (!pattern[npat])
             err = gpg_error_from_syserror ();
@@ -1536,10 +1661,18 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
         }
       else if(desc[idx].mode == KEYDB_SEARCH_MODE_EXACT)
         {
         }
       else if(desc[idx].mode == KEYDB_SEARCH_MODE_EXACT)
         {
-          /* FIXME: We don't need this.  It is used as a dummy by
-             keyserver_fetch which passes an entire URL.  Better use a
-             separate function here. */
-          pattern[npat] = xtrystrdup ("0x0000000000000000");
+          /* The Dirmngr also uses classify_user_id to detect the type
+             of the search string.  By adding the '=' prefix we force
+             Dirmngr's KS_GET to consider this an exact search string.
+             (In gpg 1.4 and gpg 2.0 the keyserver helpers used the
+             KS_GETNAME command to indicate this.)  */
+
+          n = 1+1+strlen (desc[idx].u.name);
+          if (idx && linelen + n > MAX_KS_GET_LINELEN)
+            break; /* Declare end of this chunk.  */
+          linelen += n;
+
+          pattern[npat] = strconcat ("=", desc[idx].u.name, NULL);
           if (!pattern[npat])
             err = gpg_error_from_syserror ();
           else
           if (!pattern[npat])
             err = gpg_error_from_syserror ();
           else
@@ -1561,31 +1694,33 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
           return err;
         }
 
           return err;
         }
 
-      if (!quiet && keyserver)
+      if (!quiet && override_keyserver)
         {
         {
-          if (keyserver->host)
+          if (override_keyserver->host)
             log_info (_("requesting key %s from %s server %s\n"),
                       keystr_from_desc (&desc[idx]),
             log_info (_("requesting key %s from %s server %s\n"),
                       keystr_from_desc (&desc[idx]),
-                      keyserver->scheme, keyserver->host);
+                      override_keyserver->scheme, override_keyserver->host);
           else
             log_info (_("requesting key %s from %s\n"),
           else
             log_info (_("requesting key %s from %s\n"),
-                      keystr_from_desc (&desc[idx]), keyserver->uri);
+                      keystr_from_desc (&desc[idx]), override_keyserver->uri);
         }
     }
 
         }
     }
 
+  /* Remember now many of search items were considered.  Note that
+     this is different from NPAT.  */
+  *r_ndesc_used = idx;
 
 
-  err = gpg_dirmngr_ks_get (ctrl, pattern, &datastream, &source);
+  err = gpg_dirmngr_ks_get (ctrl, pattern, override_keyserver,
+                            &datastream, &source);
   for (idx=0; idx < npat; idx++)
     xfree (pattern[idx]);
   xfree (pattern);
   for (idx=0; idx < npat; idx++)
     xfree (pattern[idx]);
   xfree (pattern);
-  if (opt.verbose)
+  if (opt.verbose && source)
     log_info ("data source: %s\n", source);
 
   if (!err)
     {
     log_info ("data source: %s\n", source);
 
   if (!err)
     {
-      void *stats_handle;
-
-      stats_handle = import_new_stats_handle();
+      struct ks_retrieval_screener_arg_s screenerarg;
 
       /* FIXME: Check whether this comment should be moved to dirmngr.
 
 
       /* FIXME: Check whether this comment should be moved to dirmngr.
 
@@ -1599,11 +1734,13 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
          never accept or send them but we better protect against rogue
          keyservers. */
 
          never accept or send them but we better protect against rogue
          keyservers. */
 
-      import_keys_es_stream (ctrl, datastream, stats_handle, NULL, NULL,
+      screenerarg.desc = desc;
+      screenerarg.ndesc = *r_ndesc_used;
+      import_keys_es_stream (ctrl, datastream, stats_handle,
+                             r_fpr, r_fprlen,
                              (opt.keyserver_options.import_options
                              (opt.keyserver_options.import_options
-                              | IMPORT_NO_SECKEY));
-      import_print_stats (stats_handle);
-      import_release_stats_handle (stats_handle);
+                              | IMPORT_NO_SECKEY),
+                             keyserver_retrieval_screener, &screenerarg);
     }
   es_fclose (datastream);
   xfree (source);
     }
   es_fclose (datastream);
   xfree (source);
@@ -1612,21 +1749,59 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
 }
 
 
 }
 
 
-/* Send all keys specified by KEYSPECS to the KEYSERVERS.  */
+/* Retrieve a key from a keyserver.  The search pattern are in
+   (DESC,NDESC).  Allowed search modes are keyid, fingerprint, and
+   exact searches.  OVERRIDE_KEYSERVER gives an optional override
+   keyserver. If (R_FPR,R_FPRLEN) are not NULL, they may return the
+   fingerprint of a single imported key.  */
 static gpg_error_t
 static gpg_error_t
-keyserver_put (ctrl_t ctrl, strlist_t keyspecs,
-               struct keyserver_spec *keyserver)
+keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
+               struct keyserver_spec *override_keyserver,
+               unsigned char **r_fpr, size_t *r_fprlen)
+{
+  gpg_error_t err;
+  import_stats_t stats_handle;
+  int ndesc_used;
+  int any_good = 0;
+
+  stats_handle = import_new_stats_handle();
+
+  for (;;)
+    {
+      err = keyserver_get_chunk (ctrl, desc, ndesc, &ndesc_used, stats_handle,
+                                 override_keyserver, r_fpr, r_fprlen);
+      if (!err)
+        any_good = 1;
+      if (err || ndesc_used >= ndesc)
+        break; /* Error or all processed.  */
+      /* Prepare for the next chunk.  */
+      desc += ndesc_used;
+      ndesc -= ndesc_used;
+    }
+
+  if (any_good)
+    import_print_stats (stats_handle);
+
+  import_release_stats_handle (stats_handle);
+  return err;
+}
+
+
+/* Send all keys specified by KEYSPECS to the configured keyserver.  */
+static gpg_error_t
+keyserver_put (ctrl_t ctrl, strlist_t keyspecs)
 
 {
   gpg_error_t err;
   strlist_t kspec;
 
 {
   gpg_error_t err;
   strlist_t kspec;
+  char *ksurl;
 
   if (!keyspecs)
     return 0;  /* Return success if the list is empty.  */
 
 
   if (!keyspecs)
     return 0;  /* Return success if the list is empty.  */
 
-  if (!opt.keyserver)
+  if (gpg_dirmngr_ks_list (ctrl, &ksurl))
     {
     {
-      log_error (_("no keyserver known (use option --keyserver)\n"));
+      log_error (_("no keyserver known\n"));
       return gpg_error (GPG_ERR_NO_KEYSERVER);
     }
 
       return gpg_error (GPG_ERR_NO_KEYSERVER);
     }
 
@@ -1638,35 +1813,35 @@ keyserver_put (ctrl_t ctrl, strlist_t keyspecs,
 
       err = export_pubkey_buffer (ctrl, kspec->d,
                                   opt.keyserver_options.export_options,
 
       err = export_pubkey_buffer (ctrl, kspec->d,
                                   opt.keyserver_options.export_options,
+                                  NULL,
                                   &keyblock, &data, &datalen);
       if (err)
         log_error (_("skipped \"%s\": %s\n"), kspec->d, gpg_strerror (err));
       else
         {
                                   &keyblock, &data, &datalen);
       if (err)
         log_error (_("skipped \"%s\": %s\n"), kspec->d, gpg_strerror (err));
       else
         {
-          if (keyserver->host)
-            log_info (_("sending key %s to %s server %s\n"),
-                      keystr (keyblock->pkt->pkt.public_key->keyid),
-                      keyserver->scheme, keyserver->host);
-          else
-            log_info (_("sending key %s to %s\n"),
-                      keystr (keyblock->pkt->pkt.public_key->keyid),
-                      keyserver->uri);
+          log_info (_("sending key %s to %s\n"),
+                    keystr (keyblock->pkt->pkt.public_key->keyid),
+                    ksurl?ksurl:"[?]");
 
           err = gpg_dirmngr_ks_put (ctrl, data, datalen, keyblock);
           release_kbnode (keyblock);
           xfree (data);
           if (err)
 
           err = gpg_dirmngr_ks_put (ctrl, data, datalen, keyblock);
           release_kbnode (keyblock);
           xfree (data);
           if (err)
-            log_error (_("keyserver send failed: %s\n"), gpg_strerror (err));
+            {
+              write_status_error ("keyserver_send", err);
+              log_error (_("keyserver send failed: %s\n"), gpg_strerror (err));
+            }
         }
     }
 
         }
     }
 
+  xfree (ksurl);
 
   return err;
 
 }
 
 
 
   return err;
 
 }
 
 
-/* Loop over all URLs in STRLIST and fetch the key that URL.  Note
+/* Loop over all URLs in STRLIST and fetch the key at that URL.  Note
    that the fetch operation ignores the configured key servers and
    instead directly retrieves the keys.  */
 int
    that the fetch operation ignores the configured key servers and
    instead directly retrieves the keys.  */
 int
@@ -1690,11 +1865,12 @@ keyserver_fetch (ctrl_t ctrl, strlist_t urilist)
       err = gpg_dirmngr_ks_fetch (ctrl, sl->d, &datastream);
       if (!err)
         {
       err = gpg_dirmngr_ks_fetch (ctrl, sl->d, &datastream);
       if (!err)
         {
-          void *stats_handle;
+          import_stats_t stats_handle;
 
           stats_handle = import_new_stats_handle();
           import_keys_es_stream (ctrl, datastream, stats_handle, NULL, NULL,
 
           stats_handle = import_new_stats_handle();
           import_keys_es_stream (ctrl, datastream, stats_handle, NULL, NULL,
-                                 opt.keyserver_options.import_options);
+                                 opt.keyserver_options.import_options,
+                                 NULL, NULL);
 
           import_print_stats (stats_handle);
           import_release_stats_handle (stats_handle);
 
           import_print_stats (stats_handle);
           import_release_stats_handle (stats_handle);
@@ -1716,35 +1892,40 @@ keyserver_fetch (ctrl_t ctrl, strlist_t urilist)
 }
 
 
 }
 
 
-/* Import key in a CERT or pointed to by a CERT */
+/* Import key in a CERT or pointed to by a CERT.  In DANE_MODE fetch
+   the certificate using the DANE method.  */
 int
 int
-keyserver_import_cert (ctrl_t ctrl,
-                       const char *name,unsigned char **fpr,size_t *fpr_len)
+keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode,
+                       unsigned char **fpr,size_t *fpr_len)
 {
   gpg_error_t err;
 {
   gpg_error_t err;
-  char *domain,*look,*url;
+  char *look,*url;
   estream_t key;
 
   estream_t key;
 
+  look = xstrdup(name);
 
 
-  look=xstrdup(name);
-
-  domain=strrchr(look,'@');
-  if(domain)
-    *domain='.';
+  if (!dane_mode)
+    {
+      char *domain = strrchr (look,'@');
+      if (domain)
+        *domain='.';
+    }
 
 
-  err = get_dns_cert (look, &key, fpr, fpr_len, &url);
+  err = gpg_dirmngr_dns_cert (ctrl, look, dane_mode? NULL : "*",
+                              &key, fpr, fpr_len, &url);
   if (err)
     ;
   else if (key)
     {
       int armor_status=opt.no_armor;
 
   if (err)
     ;
   else if (key)
     {
       int armor_status=opt.no_armor;
 
-      /* CERTs are always in binary format */
+      /* CERTs and DANE records are always in binary format */
       opt.no_armor=1;
 
       err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
                                    (opt.keyserver_options.import_options
       opt.no_armor=1;
 
       err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
                                    (opt.keyserver_options.import_options
-                                    | IMPORT_NO_SECKEY));
+                                    | IMPORT_NO_SECKEY),
+                                   NULL, NULL);
 
       opt.no_armor=armor_status;
 
 
       opt.no_armor=armor_status;
 
@@ -1760,22 +1941,22 @@ keyserver_import_cert (ctrl_t ctrl,
        {
          struct keyserver_spec *spec;
 
        {
          struct keyserver_spec *spec;
 
-         spec=parse_keyserver_uri(url,1,NULL,0);
+         spec = parse_keyserver_uri (url, 1);
          if(spec)
            {
              err = keyserver_import_fprint (ctrl, *fpr,*fpr_len,spec);
              free_keyserver_spec(spec);
            }
        }
          if(spec)
            {
              err = keyserver_import_fprint (ctrl, *fpr,*fpr_len,spec);
              free_keyserver_spec(spec);
            }
        }
-      else if(opt.keyserver)
+      else if (keyserver_any_configured (ctrl))
        {
          /* If only a fingerprint is provided, try and fetch it from
        {
          /* If only a fingerprint is provided, try and fetch it from
-            our --keyserver */
+            the configured keyserver. */
 
          err = keyserver_import_fprint (ctrl, *fpr,*fpr_len,opt.keyserver);
        }
       else
 
          err = keyserver_import_fprint (ctrl, *fpr,*fpr_len,opt.keyserver);
        }
       else
-       log_info(_("no keyserver known (use option --keyserver)\n"));
+       log_info(_("no keyserver known\n"));
 
       /* Give a better string here? "CERT fingerprint for \"%s\"
         found, but no keyserver" " known (use option
 
       /* Give a better string here? "CERT fingerprint for \"%s\"
         found, but no keyserver" " known (use option
@@ -1791,64 +1972,49 @@ keyserver_import_cert (ctrl_t ctrl,
 
 /* Import key pointed to by a PKA record. Return the requested
    fingerprint in fpr. */
 
 /* Import key pointed to by a PKA record. Return the requested
    fingerprint in fpr. */
-int
-keyserver_import_pka (ctrl_t ctrl,
-                      const char *name,unsigned char **fpr,size_t *fpr_len)
+gpg_error_t
+keyserver_import_pka (ctrl_t ctrl, const char *name,
+                      unsigned char **fpr, size_t *fpr_len)
 {
 {
-  char *uri;
-  int rc = G10ERR_NO_PUBKEY;
-
-  *fpr = xmalloc (20);
-  *fpr_len = 20;
+  gpg_error_t err;
+  char *url;
 
 
-  uri = get_pka_info (name, *fpr);
-  if (uri && *uri)
+  err = gpg_dirmngr_get_pka (ctrl, name, fpr, fpr_len, &url);
+  if (url && *url && fpr && fpr_len)
     {
     {
-      /* An URI is available.  Lookup the key. */
+      /* An URL is available.  Lookup the key. */
       struct keyserver_spec *spec;
       struct keyserver_spec *spec;
-      spec = parse_keyserver_uri (uri, 1, NULL, 0);
+      spec = parse_keyserver_uri (url, 1);
       if (spec)
        {
       if (spec)
        {
-         rc = keyserver_import_fprint (ctrl, *fpr, 20, spec);
+         err = keyserver_import_fprint (ctrl, *fpr, *fpr_len, spec);
          free_keyserver_spec (spec);
        }
          free_keyserver_spec (spec);
        }
-      xfree (uri);
     }
     }
+  xfree (url);
 
 
-  if (rc)
+  if (err)
     {
       xfree(*fpr);
       *fpr = NULL;
     {
       xfree(*fpr);
       *fpr = NULL;
+      *fpr_len = 0;
     }
 
     }
 
-  return rc;
+  return err;
 }
 
 }
 
-/* Import all keys that match name */
-int
-keyserver_import_name (ctrl_t ctrl, const char *name,
-                       unsigned char **fpr, size_t *fpr_len,
-                       struct keyserver_spec *keyserver)
-{
-  strlist_t list=NULL;
-  int rc;
-
-  append_to_strlist(&list,name);
-
-  rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);  /* FIXME */
-       /* keyserver_work (ctrl, KS_GETNAME, list, NULL, */
-       /*                 0, fpr, fpr_len, keyserver); */
-
-  free_strlist(list);
-
-  return rc;
-}
 
 /* Import a key by name using LDAP */
 int
 keyserver_import_ldap (ctrl_t ctrl,
 
 /* Import a key by name using LDAP */
 int
 keyserver_import_ldap (ctrl_t ctrl,
-                       const char *name,unsigned char **fpr,size_t *fpr_len)
+                       const char *name, unsigned char **fpr, size_t *fprlen)
 {
 {
+  (void)ctrl;
+  (void)name;
+  (void)fpr;
+  (void)fprlen;
+  return gpg_error (GPG_ERR_NOT_IMPLEMENTED); /*FIXME*/
+#if 0
   char *domain;
   struct keyserver_spec *keyserver;
   strlist_t list=NULL;
   char *domain;
   struct keyserver_spec *keyserver;
   strlist_t list=NULL;
@@ -1862,7 +2028,7 @@ keyserver_import_ldap (ctrl_t ctrl,
   /* Parse out the domain */
   domain=strrchr(name,'@');
   if(!domain)
   /* Parse out the domain */
   domain=strrchr(name,'@');
   if(!domain)
-    return G10ERR_GENERAL;
+    return GPG_ERR_GENERAL;
 
   domain++;
 
 
   domain++;
 
@@ -1874,6 +2040,7 @@ keyserver_import_ldap (ctrl_t ctrl,
 #ifdef USE_DNS_SRV
   snprintf(srvname,MAXDNAME,"_pgpkey-ldap._tcp.%s",domain);
 
 #ifdef USE_DNS_SRV
   snprintf(srvname,MAXDNAME,"_pgpkey-ldap._tcp.%s",domain);
 
+  FIXME("network related - move to dirmngr or drop the code");
   srvcount=getsrv(srvname,&srvlist);
 
   for(i=0;i<srvcount;i++)
   srvcount=getsrv(srvname,&srvlist);
 
   for(i=0;i<srvcount;i++)
@@ -1919,4 +2086,5 @@ keyserver_import_ldap (ctrl_t ctrl,
   free_keyserver_spec(keyserver);
 
   return rc;
   free_keyserver_spec(keyserver);
 
   return rc;
+#endif
 }
 }