build: Require latest released libraries
[gnupg.git] / dirmngr / ks-engine-ldap.c
index 68a1bb7..ad2110e 100644 (file)
 #include "ks-engine.h"
 #include "ldap-parse-uri.h"
 
-#ifdef __riscos__
-# include "util.h"
-#endif
-
 #ifndef HAVE_TIMEGM
 time_t timegm(struct tm *tm);
 #endif
@@ -220,7 +216,7 @@ ldap_to_gpg_err (LDAP *ld)
 #else
   /* We should never get here since the LDAP library should always
      have either ldap_get_option or ld_errno, but just in case... */
-  return GPG_ERR_GENERAL;
+  return GPG_ERR_INTERNAL;
 #endif
 }
 \f
@@ -265,7 +261,7 @@ tm2ldaptime (struct tm *tm)
   tmp.tm_year += 1900;
   tmp.tm_mon ++;
 
-  sprintf (buf, "%04d%02d%02d%02d%02d%02dZ",
+  snprintf (buf, sizeof buf, "%04d%02d%02d%02d%02d%02dZ",
           tmp.tm_year,
           tmp.tm_mon,
           tmp.tm_mday,
@@ -310,7 +306,9 @@ ks_ldap_help (ctrl_t ctrl, parsed_uri_t uri)
     "Supported methods: search, get, put\n";
   gpg_error_t err;
 
-  if (strcmp (uri->scheme, "ldap") == 0
+  if(!uri)
+    err = ks_print_help (ctrl, "  ldap");
+  else if (strcmp (uri->scheme, "ldap") == 0
       || strcmp (uri->scheme, "ldaps") == 0
       || strcmp (uri->scheme, "ldapi") == 0)
     err = ks_print_help (ctrl, data);
@@ -333,6 +331,7 @@ keyspec_to_ldap_filter (const char *keyspec, char **filter, int only_exact)
   /* XXX: Should we include disabled / revoke options?  */
   KEYDB_SEARCH_DESC desc;
   char *f = NULL;
+  char *freeme = NULL;
 
   gpg_error_t err = classify_user_id (keyspec, &desc, 1);
   if (err)
@@ -342,31 +341,31 @@ keyspec_to_ldap_filter (const char *keyspec, char **filter, int only_exact)
     {
     case KEYDB_SEARCH_MODE_EXACT:
       f = xasprintf ("(pgpUserID=%s)",
-                    ldap_escape_filter (desc.u.name));
+                    (freeme = ldap_escape_filter (desc.u.name)));
       break;
 
     case KEYDB_SEARCH_MODE_SUBSTR:
       if (! only_exact)
        f = xasprintf ("(pgpUserID=*%s*)",
-                      ldap_escape_filter (desc.u.name));
+                      (freeme = ldap_escape_filter (desc.u.name)));
       break;
 
     case KEYDB_SEARCH_MODE_MAIL:
       if (! only_exact)
        f = xasprintf ("(pgpUserID=*<%s>*)",
-                      ldap_escape_filter (desc.u.name));
+                      (freeme = ldap_escape_filter (desc.u.name)));
       break;
 
     case KEYDB_SEARCH_MODE_MAILSUB:
       if (! only_exact)
        f = xasprintf ("(pgpUserID=*<*%s*>*)",
-                      ldap_escape_filter (desc.u.name));
+                      (freeme = ldap_escape_filter (desc.u.name)));
       break;
 
     case KEYDB_SEARCH_MODE_MAILEND:
       if (! only_exact)
        f = xasprintf ("(pgpUserID=*<*%s>*)",
-                      ldap_escape_filter (desc.u.name));
+                      (freeme = ldap_escape_filter (desc.u.name)));
       break;
 
     case KEYDB_SEARCH_MODE_SHORT_KID:
@@ -392,6 +391,8 @@ keyspec_to_ldap_filter (const char *keyspec, char **filter, int only_exact)
       break;
     }
 
+  xfree (freeme);
+
   if (! f)
     {
       log_error ("Unsupported search mode.\n");
@@ -402,6 +403,8 @@ keyspec_to_ldap_filter (const char *keyspec, char **filter, int only_exact)
 
   return 0;
 }
+
+
 \f
 /* Connect to an LDAP server and interrogate it.
 
@@ -430,16 +433,16 @@ keyspec_to_ldap_filter (const char *keyspec, char **filter, int only_exact)
 
    If this function successfully interrogated the server, it returns
    0.  If there was an LDAP error, it returns the LDAP error code.  If
-   an error occured, *basednp, etc., are undefined (and don't need to
+   an error occurred, *basednp, etc., are undefined (and don't need to
    be freed.)
 
-   If no LDAP error occured, you still need to check that *basednp is
+   If no LDAP error occurred, you still need to check that *basednp is
    valid.  If it is NULL, then the server does not appear to be an
-   OpenPGP Keyserver.  In this case, you also do not need to free
+   OpenPGP Keyserver.  In this case, you also do not need to xfree
    *pgpkeyattrp.  */
 static int
-ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
-             char **basednp, char **pgpkeyattrp, int *real_ldapp)
+my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
+                 char **basednp, char **pgpkeyattrp, int *real_ldapp)
 {
   int err = 0;
 
@@ -454,7 +457,7 @@ ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
   char *pgpkeyattr = "pgpKey";
   int real_ldap = 0;
 
-  log_debug ("ldap_connect(%s:%d/%s????%s%s%s%s%s)\n",
+  log_debug ("my_ldap_connect(%s:%d/%s????%s%s%s%s%s)\n",
             uri->host, uri->port,
             uri->path ?: "",
             uri->auth ? "bindname=" : "", uri->auth ?: "",
@@ -476,9 +479,9 @@ ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
   ldap_conn = ldap_init (uri->host, uri->port);
   if (! ldap_conn)
     {
+      err = gpg_err_code_from_syserror ();
       log_error ("Failed to open connection to LDAP server (%s://%s:%d)\n",
                 uri->scheme, uri->host, uri->port);
-      err = gpg_err_code_from_errno (errno);
       goto out;
     }
 
@@ -516,7 +519,7 @@ ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
       /* XXX: We need an option to determine whether to abort if the
         certificate is bad or not.  Right now we conservatively
         default to checking the certificate and aborting.  */
-      int check_cert = LDAP_OPT_X_TLS_HARD; // LDAP_OPT_X_TLS_NEVER
+      int check_cert = LDAP_OPT_X_TLS_HARD; /* LDAP_OPT_X_TLS_NEVER */
 
       err = ldap_set_option (ldap_conn,
                             LDAP_OPT_X_TLS_REQUIRE_CERT, &check_cert);
@@ -587,10 +590,13 @@ ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
                  char **vals;
                  LDAPMessage *si_res;
 
-                 char *object = xasprintf ("cn=pgpServerInfo,%s", context[i]);
-                 err = ldap_search_s (ldap_conn, object, LDAP_SCOPE_BASE,
-                                      "(objectClass=*)", attr2, 0, &si_res);
-                 free (object);
+                  {
+                    char *object = xasprintf ("cn=pgpServerInfo,%s",
+                                              context[i]);
+                    err = ldap_search_s (ldap_conn, object, LDAP_SCOPE_BASE,
+                                         "(objectClass=*)", attr2, 0, &si_res);
+                    xfree (object);
+                  }
 
                  if (err == LDAP_SUCCESS)
                    {
@@ -598,7 +604,7 @@ ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
                                              "pgpBaseKeySpaceDN");
                      if (vals)
                        {
-                         basedn = strdup (vals[0]);
+                         basedn = xtrystrdup (vals[0]);
                          ldap_value_free (vals);
                        }
 
@@ -649,7 +655,7 @@ ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
              vals = ldap_get_values (ldap_conn, si_res, "baseKeySpaceDN");
              if (vals)
                {
-                 basedn = strdup (vals[0]);
+                 basedn = xtrystrdup (vals[0]);
                  ldap_value_free (vals);
                }
 
@@ -830,6 +836,13 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
 
   (void) ctrl;
 
+  if (opt.use_tor)
+    {
+      /* For now we do not support LDAP over Tor.  */
+      log_error (_("LDAP access not possible due to Tor mode\n"));
+      return gpg_error (GPG_ERR_NOT_SUPPORTED);
+    }
+
   /* Before connecting to the server, make sure we have a sane
      keyspec.  If not, there is no need to establish a network
      connection.  */
@@ -838,7 +851,7 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
     return (err);
 
   /* Make sure we are talking to an OpenPGP LDAP server.  */
-  ldap_err = ldap_connect (uri, &ldap_conn, &basedn, &pgpkeyattr, NULL);
+  ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, &pgpkeyattr, NULL);
   if (ldap_err || !basedn)
     {
       if (ldap_err)
@@ -1006,6 +1019,13 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
 
   (void) ctrl;
 
+  if (opt.use_tor)
+    {
+      /* For now we do not support LDAP over Tor.  */
+      log_error (_("LDAP access not possible due to Tor mode\n"));
+      return gpg_error (GPG_ERR_NOT_SUPPORTED);
+    }
+
   /* Before connecting to the server, make sure we have a sane
      keyspec.  If not, there is no need to establish a network
      connection.  */
@@ -1017,7 +1037,7 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
     }
 
   /* Make sure we are talking to an OpenPGP LDAP server.  */
-  ldap_err = ldap_connect (uri, &ldap_conn, &basedn, NULL, NULL);
+  ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, NULL, NULL);
   if (ldap_err || !basedn)
     {
       if (ldap_err)
@@ -1029,6 +1049,11 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
 
   /* Even if we have no results, we want to return a stream.  */
   fp = es_fopenmem(0, "rw");
+  if (!fp)
+    {
+      err = gpg_error_from_syserror ();
+      goto out;
+    }
 
   {
     char **vals;
@@ -1053,7 +1078,7 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
     xfree (filter);
     filter = NULL;
 
-    if (err != LDAP_SUCCESS && err != LDAP_SIZELIMIT_EXCEEDED)
+    if (ldap_err != LDAP_SUCCESS && ldap_err != LDAP_SIZELIMIT_EXCEEDED)
       {
        err = ldap_err_to_gpg_err (ldap_err);
 
@@ -1077,7 +1102,7 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
          }
       }
 
-    if (err == LDAP_SIZELIMIT_EXCEEDED)
+    if (ldap_err == LDAP_SIZELIMIT_EXCEEDED)
       {
        if (count == 1)
          log_error ("gpgkeys: search results exceeded server limit."
@@ -1114,118 +1139,117 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
 
                es_fprintf (fp, "pub:%s:",certid[0]);
 
-                 vals = ldap_get_values (ldap_conn, each, "pgpkeytype");
-                 if (vals)
-                   {
-                     /* The LDAP server doesn't exactly handle this
-                        well. */
-                     if (strcasecmp (vals[0], "RSA") == 0)
-                       es_fputs ("1", fp);
-                     else if (strcasecmp (vals[0], "DSS/DH") == 0)
-                       es_fputs ("17", fp);
-                     ldap_value_free (vals);
-                   }
-
-                 es_fputc (':', fp);
-
-                 vals = ldap_get_values (ldap_conn, each, "pgpkeysize");
-                 if (vals)
-                   {
-                     /* Not sure why, but some keys are listed with a
-                        key size of 0.  Treat that like an
-                        unknown. */
-                     if (atoi (vals[0]) > 0)
-                       es_fprintf (fp, "%d", atoi (vals[0]));
-                     ldap_value_free (vals);
-                   }
-
-                 es_fputc (':', fp);
-
-                 /* YYYYMMDDHHmmssZ */
-
-                 vals = ldap_get_values (ldap_conn, each, "pgpkeycreatetime");
-                 if(vals && strlen (vals[0]) == 15)
-                   {
-                     es_fprintf (fp, "%u",
-                                 (unsigned int) ldap2epochtime(vals[0]));
-                     ldap_value_free (vals);
-                   }
-
-                 es_fputc (':', fp);
-
-                 vals = ldap_get_values (ldap_conn, each, "pgpkeyexpiretime");
-                 if (vals && strlen (vals[0]) == 15)
-                   {
-                     es_fprintf (fp, "%u",
-                                 (unsigned int) ldap2epochtime (vals[0]));
-                     ldap_value_free (vals);
-                   }
-
-                 es_fputc (':', fp);
-
-                 vals = ldap_get_values (ldap_conn, each, "pgprevoked");
-                 if (vals)
-                   {
-                     if (atoi (vals[0]) == 1)
-                       es_fprintf (fp, "r");
-                     ldap_value_free (vals);
-                   }
-
-                 vals = ldap_get_values (ldap_conn, each, "pgpdisabled");
-                 if (vals)
-                   {
-                     if (atoi (vals[0]) ==1)
-                       es_fprintf (fp, "d");
-                     ldap_value_free (vals);
-                   }
+               vals = ldap_get_values (ldap_conn, each, "pgpkeytype");
+               if (vals)
+                 {
+                   /* The LDAP server doesn't exactly handle this
+                      well. */
+                   if (strcasecmp (vals[0], "RSA") == 0)
+                     es_fputs ("1", fp);
+                   else if (strcasecmp (vals[0], "DSS/DH") == 0)
+                     es_fputs ("17", fp);
+                   ldap_value_free (vals);
+                 }
+
+               es_fputc (':', fp);
+
+               vals = ldap_get_values (ldap_conn, each, "pgpkeysize");
+               if (vals)
+                 {
+                   /* Not sure why, but some keys are listed with a
+                      key size of 0.  Treat that like an unknown. */
+                   if (atoi (vals[0]) > 0)
+                     es_fprintf (fp, "%d", atoi (vals[0]));
+                   ldap_value_free (vals);
+                 }
+
+               es_fputc (':', fp);
+
+               /* YYYYMMDDHHmmssZ */
+
+               vals = ldap_get_values (ldap_conn, each, "pgpkeycreatetime");
+               if(vals && strlen (vals[0]) == 15)
+                 {
+                   es_fprintf (fp, "%u",
+                               (unsigned int) ldap2epochtime(vals[0]));
+                   ldap_value_free (vals);
+                 }
+
+               es_fputc (':', fp);
+
+               vals = ldap_get_values (ldap_conn, each, "pgpkeyexpiretime");
+               if (vals && strlen (vals[0]) == 15)
+                 {
+                   es_fprintf (fp, "%u",
+                               (unsigned int) ldap2epochtime (vals[0]));
+                   ldap_value_free (vals);
+                 }
+
+               es_fputc (':', fp);
+
+               vals = ldap_get_values (ldap_conn, each, "pgprevoked");
+               if (vals)
+                 {
+                   if (atoi (vals[0]) == 1)
+                     es_fprintf (fp, "r");
+                   ldap_value_free (vals);
+                 }
+
+               vals = ldap_get_values (ldap_conn, each, "pgpdisabled");
+               if (vals)
+                 {
+                   if (atoi (vals[0]) ==1)
+                     es_fprintf (fp, "d");
+                   ldap_value_free (vals);
+                 }
 
 #if 0
-                 /* This is not yet specified in the keyserver
-                    protocol, but may be someday. */
-                 es_fputc (':', fp);
-
-                 vals = ldap_get_values (ldap_conn, each, "modifytimestamp");
-                 if(vals && strlen (vals[0]) == 15)
-                   {
-                     es_fprintf (fp, "%u",
-                                 (unsigned int) ldap2epochtime (vals[0]));
-                     ldap_value_free (vals);
-                   }
+               /* This is not yet specified in the keyserver
+                  protocol, but may be someday. */
+               es_fputc (':', fp);
+
+               vals = ldap_get_values (ldap_conn, each, "modifytimestamp");
+               if(vals && strlen (vals[0]) == 15)
+                 {
+                   es_fprintf (fp, "%u",
+                               (unsigned int) ldap2epochtime (vals[0]));
+                   ldap_value_free (vals);
+                 }
 #endif
 
-                 es_fprintf (fp, "\n");
-
-                 /* Now print all the uids that have this certid */
-                 for (uids = ldap_first_entry (ldap_conn, res);
-                      uids;
-                      uids = ldap_next_entry (ldap_conn, uids))
-                   {
-                     vals = ldap_get_values (ldap_conn, uids, "pgpcertid");
-                     if (! vals)
-                       continue;
-
-                     if (strcasecmp (certid[0], vals[0]) == 0)
-                       {
-                         char **uidvals;
-
-                         es_fprintf (fp, "uid:");
-
-                         uidvals = ldap_get_values (ldap_conn,
-                                                    uids, "pgpuserid");
-                         if (uidvals)
-                           {
-                             /* Need to escape any colons */
-                             char *quoted = percent_escape (uidvals[0], NULL);
-                             es_fputs (quoted, fp);
-                             xfree (quoted);
-                             ldap_value_free (uidvals);
-                           }
-
-                         es_fprintf (fp, "\n");
-                       }
-
-                     ldap_value_free(vals);
-                   }
+               es_fprintf (fp, "\n");
+
+               /* Now print all the uids that have this certid */
+               for (uids = ldap_first_entry (ldap_conn, res);
+                    uids;
+                    uids = ldap_next_entry (ldap_conn, uids))
+                 {
+                   vals = ldap_get_values (ldap_conn, uids, "pgpcertid");
+                   if (! vals)
+                     continue;
+
+                   if (strcasecmp (certid[0], vals[0]) == 0)
+                     {
+                       char **uidvals;
+
+                       es_fprintf (fp, "uid:");
+
+                       uidvals = ldap_get_values (ldap_conn,
+                                                  uids, "pgpuserid");
+                       if (uidvals)
+                         {
+                           /* Need to escape any colons */
+                           char *quoted = percent_escape (uidvals[0], NULL);
+                           es_fputs (quoted, fp);
+                           xfree (quoted);
+                           ldap_value_free (uidvals);
+                         }
+
+                       es_fprintf (fp, "\n");
+                     }
+
+                   ldap_value_free(vals);
+                 }
              }
 
              ldap_value_free (certid);
@@ -1262,6 +1286,8 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
 
   return err;
 }
+
+
 \f
 /* A modlist describes a set of changes to an LDAP entry.  (An entry
    consists of 1 or more attributes.  Attributes are <name, value>
@@ -1361,8 +1387,6 @@ modlist_add (LDAPMod ***modlistp, char *attr, const char *value)
     {
       modlist[nummods]->mod_values = xmalloc (sizeof(char *) * 2);
 
-      /* XXX: Is this the right thing?  Can a UTF8-encoded user ID
-        have embedded nulls? */
       modlist[nummods]->mod_values[0] = xstrdup (value);
       modlist[nummods]->mod_values[1] = NULL;
     }
@@ -1394,7 +1418,7 @@ modlist_lookup (LDAPMod **modlist, const char *attr)
 
 /* Dump a modlist to a file.  This is useful for debugging.  */
 static estream_t modlist_dump (LDAPMod **modlist, estream_t output)
-  __attribute__ ((used));
+  GPGRT_ATTR_USED;
 
 static estream_t
 modlist_dump (LDAPMod **modlist, estream_t output)
@@ -1402,9 +1426,12 @@ modlist_dump (LDAPMod **modlist, estream_t output)
   LDAPMod **m;
 
   int opened = 0;
+
   if (! output)
     {
       output = es_fopenmem (0, "rw");
+      if (!output)
+        return NULL;
       opened = 1;
     }
 
@@ -1429,29 +1456,22 @@ modlist_dump (LDAPMod **modlist, estream_t output)
 
          for ((ptr = (*m)->mod_values), (i = 1); ptr && *ptr; ptr++, i ++)
            {
-             /* At most about 10 lines.  */
+             /* Assuming terminals are about 80 characters wide,
+                display at most most about 10 lines of debugging
+                output.  If we do trim the buffer, append '...' to
+                the end.  */
              const int max_len = 10 * 70;
              size_t value_len = strlen (*ptr);
-             char buffer[max_len + 4];
-             char *temp;
-             int elided = 0;
-             if (value_len > max_len)
-               {
-                 temp = buffer;
-                 memcpy (temp, *ptr, max_len);
-                 temp[max_len] = temp[max_len + 1] = temp[max_len + 2] = '.';
-                 temp[max_len + 3] = 0;
-                 elided = 1;
-               }
-             else
-               temp = *ptr;
+             int elide = value_len > max_len;
 
              if (multi)
                es_fprintf (output, "    %d. ", i);
-             es_fprintf (output, "`%s'", temp);
-             if (elided)
-               es_fprintf (output, " (%zd bytes elided)",
+             es_fprintf (output, "`%.*s", max_len, *ptr);
+             if (elide)
+               es_fprintf (output, "...' (%zd bytes elided)",
                            value_len - max_len);
+             else
+               es_fprintf (output, "'");
              es_fprintf (output, "\n");
            }
        }
@@ -1488,14 +1508,14 @@ modlist_free (LDAPMod **modlist)
       if (mod->mod_values)
        {
          for (ptr = mod->mod_values; *ptr; ptr++)
-           free (*ptr);
+           xfree (*ptr);
 
-         free (mod->mod_values);
+         xfree (mod->mod_values);
        }
 
-      free (mod);
+      xfree (mod);
     }
-  free (modlist);
+  xfree (modlist);
 }
 
 /* Append two onto the end of one.  Two is not freed, but its pointers
@@ -1541,8 +1561,8 @@ modlists_join (LDAPMod ***one, LDAPMod **two)
 static void
 uncescape (char *str)
 {
-  int r = 0;
-  int w = 0;
+  size_t r = 0;
+  size_t w = 0;
 
   char *first = strchr (str, '\\');
   if (! first)
@@ -1554,14 +1574,13 @@ uncescape (char *str)
 
   while (str[r])
     {
-      /* XXX: What to do about bad escapes?  */
+      /* XXX: What to do about bad escapes?
+         XXX: hextobyte already checks the string thus the hexdigitp
+         could be removed. */
       if (str[r] == '\\' && str[r + 1] == 'x'
-         && (('0' <= str[r + 2] && str[r + 2] <= '9')
-             || ('a' <= str[r + 2] && str[r + 2] <= 'f')
-             || ('A' <= str[r + 2] && str[r + 2] <= 'F'))
-         && (('0' <= str[r + 3] && str[r + 3] <= '9')
-             || ('a' <= str[r + 3] && str[r + 3] <= 'f')
-             || ('A' <= str[r + 3] && str[r + 3] <= 'F')))
+          && str[r+2] && str[r+3]
+         && hexdigitp (str + r + 2)
+         && hexdigitp (str + r + 3))
        {
          int x = hextobyte (&str[r + 2]);
          assert (0 <= x && x <= 0xff);
@@ -1585,8 +1604,6 @@ uncescape (char *str)
 static void
 extract_attributes (LDAPMod ***modlist, char *line)
 {
-  int i;
-
   int field_count;
   char **fields;
 
@@ -1595,12 +1612,11 @@ extract_attributes (LDAPMod ***modlist, char *line)
   int is_pub, is_sub, is_uid, is_sig;
 
   /* Remove trailing whitespace */
-  for (i = strlen (line) - 1; i >= 0 && ascii_isspace (line[i]); i--)
-    line[i] = '\0';
+  trim_trailing_spaces (line);
 
   fields = strsplit (line, ':', '\0', &field_count);
   if (field_count == 1)
-    /* We only have a single field.  There is definately nothing to
+    /* We only have a single field.  There is definitely nothing to
        do.  */
     goto out;
 
@@ -1633,7 +1649,8 @@ extract_attributes (LDAPMod ***modlist, char *line)
 
   if (is_pub)
     {
-      int disabled = 0, revoked = 0;
+      int disabled = 0;
+      int revoked = 0;
       char *flags;
       for (flags = fields[1]; *flags; flags ++)
        switch (*flags)
@@ -1673,7 +1690,7 @@ extract_attributes (LDAPMod ***modlist, char *line)
          char padded[6];
          if (val < 99999 && val > 0)
            {
-             sprintf (padded, "%05u", val);
+             snprintf (padded, sizeof padded, "%05u", val);
              size = padded;
            }
        }
@@ -1747,12 +1764,13 @@ extract_attributes (LDAPMod ***modlist, char *line)
             Check that first and then if it fails, then try
             parse_timestamp.  */
 
-         if (strptime (create_time, "%Y-%m-%d", &tm))
+         if (!isodate_human_to_tm (create_time, &tm))
            create_time = tm2ldaptime (&tm);
          else if ((t = parse_timestamp (create_time, &end)) != (time_t) -1
                   && *end == '\0')
            {
-             if (! gmtime_r (&t, &tm))
+
+             if (!gnupg_gmtime (&t, &tm))
                create_time = NULL;
              else
                create_time = tm2ldaptime (&tm);
@@ -1794,12 +1812,12 @@ extract_attributes (LDAPMod ***modlist, char *line)
             Check that first and then if it fails, then try
             parse_timestamp.  */
 
-         if (strptime (expire_time, "%Y-%m-%d", &tm))
+         if (!isodate_human_to_tm (expire_time, &tm))
            expire_time = tm2ldaptime (&tm);
          else if ((t = parse_timestamp (expire_time, &end)) != (time_t) -1
                   && *end == '\0')
            {
-             if (! gmtime_r (&t, &tm))
+             if (!gnupg_gmtime (&t, &tm))
                expire_time = NULL;
              else
                expire_time = tm2ldaptime (&tm);
@@ -1877,7 +1895,15 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
   /* Elide a warning.  */
   (void) ctrl;
 
-  ldap_err = ldap_connect (uri, &ldap_conn, &basedn, &pgpkeyattr, &real_ldap);
+  if (opt.use_tor)
+    {
+      /* For now we do not support LDAP over Tor.  */
+      log_error (_("LDAP access not possible due to Tor mode\n"));
+      return gpg_error (GPG_ERR_NOT_SUPPORTED);
+    }
+
+  ldap_err = my_ldap_connect (uri,
+                              &ldap_conn, &basedn, &pgpkeyattr, &real_ldap);
   if (ldap_err || !basedn)
     {
       if (ldap_err)
@@ -1960,7 +1986,7 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
        /* The last line is not \n terminated!  Make a copy so we can
           add a NUL terminator.  */
        {
-         temp = alloca (infolen + 1);
+         temp = xmalloc (infolen + 1);
          memcpy (temp, info, infolen);
          info = temp;
          newline = (char *) info + infolen;
@@ -1977,7 +2003,10 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
       if (! temp)
        assert ((char *) info + infolen - 1 == infoend);
       else
-       assert (infolen == -1);
+       {
+         assert (infolen == -1);
+         xfree (temp);
+       }
     }
 
   modlist_add (&addlist, "objectClass", "pgpKeyInfo");
@@ -1994,8 +2023,11 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
   if (dump)
     {
       estream_t input = modlist_dump (modlist, NULL);
-      copy_stream (input, dump);
-      es_fclose (input);
+      if (input)
+        {
+          copy_stream (input, dump);
+          es_fclose (input);
+        }
     }
 
   /* Going on the assumption that modify operations are more frequent