Fix comment of configure.
[gnupg.git] / dirmngr / ldap.c
index b71a0d3..adf8307 100644 (file)
 #include <unistd.h>
 #include <fcntl.h>
 #include <time.h>
-#include <pth.h>
+#include <npth.h>
 
 #include "dirmngr.h"
-#include "exechelp.h"
+#include "../common/exechelp.h"
 #include "crlfetch.h"
 #include "ldapserver.h"
 #include "misc.h"
 #include "ldap-wrapper.h"
+#include "../common/host2net.h"
 
 
 #define UNENCODED_URL_CHARS "abcdefghijklmnopqrstuvwxyz"   \
@@ -91,7 +92,7 @@ add_server_to_servers (const char *host, int port)
         return;
       }
 
-  log_info (_("adding `%s:%d' to the ldap server list\n"), host, port);
+  log_info (_("adding '%s:%d' to the ldap server list\n"), host, port);
   server = xtrycalloc (1, sizeof *s);
   if (!server)
     log_error (_("malloc failed: %s\n"), strerror (errno));
@@ -112,11 +113,11 @@ add_server_to_servers (const char *host, int port)
 /* Perform an LDAP query.  Returns an gpg error code or 0 on success.
    The function returns a new reader object at READER. */
 static gpg_error_t
-run_ldap_wrapper (ctrl_t ctrl, 
+run_ldap_wrapper (ctrl_t ctrl,
                   int ignore_timeout,
                   int multi_mode,
                   const char *proxy,
-                  const char *host, int port, 
+                  const char *host, int port,
                   const char *user, const char *pass,
                   const char *dn, const char *filter, const char *attr,
                   const char *url,
@@ -125,12 +126,12 @@ run_ldap_wrapper (ctrl_t ctrl,
   const char *argv[40];
   int argc;
   char portbuf[30], timeoutbuf[30];
-  
+
 
   *reader = NULL;
 
   argc = 0;
-  if (pass)  /* Note, that the password most be the first item.  */
+  if (pass)  /* Note, that the password must be the first item.  */
     {
       argv[argc++] = "--pass";
       argv[argc++] = pass;
@@ -186,7 +187,7 @@ run_ldap_wrapper (ctrl_t ctrl,
     }
   argv[argc++] = url? url : "ldap://";
   argv[argc] = NULL;
-    
+
   return ldap_wrapper (ctrl, reader, argv);
 }
 
@@ -216,7 +217,7 @@ url_fetch_ldap (ctrl_t ctrl, const char *url, const char *host, int port,
      will enlarge the list of servers to consult without a limit and
      all LDAP queries w/o a host are will then try each host in
      turn. */
-  if (!err && opt.add_new_ldapservers && !opt.ldap_proxy) 
+  if (!err && opt.add_new_ldapservers && !opt.ldap_proxy)
     {
       if (host)
         add_server_to_servers (host, port);
@@ -236,11 +237,11 @@ url_fetch_ldap (ctrl_t ctrl, const char *url, const char *host, int port,
   if (err && !(opt.ldap_proxy && opt.only_ldap_proxy))
     {
       struct ldapserver_iter iter;
-      
+
       if (DBG_LOOKUP)
         log_debug ("no hostname in URL or query failed; "
                    "trying all default hostnames\n");
-      
+
       for (ldapserver_iter_begin (&iter, ctrl);
           err && ! ldapserver_iter_end_p (&iter);
           ldapserver_iter_next (&iter))
@@ -362,26 +363,27 @@ parse_one_pattern (const char *pattern)
       break;
     case '*':
       pattern++;
+      /* fall through */
     default:                   /* Take as substring match. */
       {
        const char format[] = "(|(sn=*%s*)(|(cn=*%s*)(mail=*%s*)))";
-        
+
         if (*pattern)
           {
             result = xmalloc (sizeof *result
                               + strlen (format) + 3 * strlen (pattern));
             result->next = NULL;
-            result->flags = 0; 
+            result->flags = 0;
             sprintf (result->d, format, pattern, pattern, pattern);
           }
       }
       break;
     }
-  
+
   return result;
 }
 
-/* Take the string STRING and escape it accoring to the URL rules.
+/* Take the string STRING and escape it according to the URL rules.
    Retun a newly allocated string. */
 static char *
 escape4url (const char *string)
@@ -396,9 +398,9 @@ escape4url (const char *string)
   for (s=string,n=0; *s; s++)
     if (strchr (UNENCODED_URL_CHARS, *s))
       n++;
-    else 
+    else
       n += 3;
-  
+
   buf = malloc (n+1);
   if (!buf)
     return NULL;
@@ -406,7 +408,7 @@ escape4url (const char *string)
   for (s=string,p=buf; *s; s++)
     if (strchr (UNENCODED_URL_CHARS, *s))
       *p++ = *s;
-    else 
+    else
       {
         sprintf (p, "%%%02X", *(const unsigned char *)s);
         p += 3;
@@ -444,26 +446,16 @@ make_url (char **url, const char *dn, const char *filter)
       xfree (u_dn);
       return err;
     }
-  *url = malloc ( 8 + strlen (u_dn)
-                 + 1 + strlen (attrs)
-                 + 5 + strlen (u_filter) + 1 );
+
+  *url = strconcat ("ldap:///", u_dn, "?", attrs, "?sub?", u_filter, NULL);
   if (!*url)
-    {
-      err = gpg_error_from_errno (errno);
-      xfree (u_dn);
-      xfree (u_filter);
-      return err;
-    }
-  stpcpy (stpcpy (stpcpy (stpcpy (stpcpy (stpcpy (*url, "ldap:///"),
-                                          u_dn),
-                                  "?"),
-                          attrs),
-                  "?sub?"),
-          u_filter);
+    err = gpg_error_from_syserror ();
+  else
+    err = 0;
+
   xfree (u_dn);
   xfree (u_filter);
-  return 0;
+  return err;
 }
 
 
@@ -511,7 +503,7 @@ start_default_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
 }
 
 
-/* Prepare an LDAP query to return certificates maching PATTERNS using
+/* Prepare an LDAP query to return certificates matching PATTERNS using
    the SERVER.  This function returns an error code or 0 and a CONTEXT
    on success. */
 gpg_error_t
@@ -519,32 +511,54 @@ start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
                        strlist_t patterns, const ldap_server_t server)
 {
   gpg_error_t err;
-  const char *host;
+  char *proxy = NULL;
+  char *host = NULL;
   int port;
-  const char *user;
-  const char *pass;
+  char *user = NULL;
+  char *pass = NULL;
   const char *base;
-  const char *argv[50];
-  int argc;
+  char *argv[50];
+  int argc = 0;
+  int argc_malloced = 0;
   char portbuf[30], timeoutbuf[30];
 
-  
+
   *context = NULL;
+
+  if (opt.ldap_proxy && !(proxy = xtrystrdup (opt.ldap_proxy)))
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+
   if (server)
     {
-      host = server->host;
+      if (server->host && !(host = xtrystrdup (server->host)))
+        {
+          err = gpg_error_from_syserror ();
+          goto leave;
+        }
       port = server->port;
-      user = server->user;
-      pass = server->pass;
+      if (server->user && !(user = xtrystrdup (server->user)))
+        {
+          err = gpg_error_from_syserror ();
+          goto leave;
+        }
+      if (server->pass && !(pass = xtrystrdup (server->pass)))
+        {
+          err = gpg_error_from_syserror ();
+          goto leave;
+        }
       base = server->base;
+
     }
   else /* Use a default server. */
     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
+
   if (!base)
     base = "";
 
-  argc = 0;
   if (pass) /* Note: Must be the first item. */
     {
       argv[argc++] = "--pass";
@@ -556,14 +570,14 @@ start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
   argv[argc++] = "--multi";
   if (opt.ldaptimeout)
     {
-      sprintf (timeoutbuf, "%u", opt.ldaptimeout);
+      snprintf (timeoutbuf, sizeof timeoutbuf, "%u", opt.ldaptimeout);
       argv[argc++] = "--timeout";
       argv[argc++] = timeoutbuf;
     }
   if (opt.ldap_proxy)
     {
       argv[argc++] = "--proxy";
-      argv[argc++] = opt.ldap_proxy;
+      argv[argc++] = proxy;
     }
   if (host)
     {
@@ -572,7 +586,7 @@ start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
     }
   if (port)
     {
-      sprintf (portbuf, "%d", port);
+      snprintf (portbuf, sizeof portbuf, "%d", port);
       argv[argc++] = "--port";
       argv[argc++] = portbuf;
     }
@@ -582,13 +596,15 @@ start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
       argv[argc++] = user;
     }
 
+  /* All entries in argv from this index on are malloc'ed.  */
+  argc_malloced = argc;
 
   for (; patterns; patterns = patterns->next)
     {
       strlist_t sl;
       char *url;
 
-      if (argc >= sizeof argv -1)
+      if (argc >= DIM (argv) - 1)
         {
           /* Too many patterns.  It does not make sense to allow an
              arbitrary number of patters because the length of the
@@ -599,10 +615,10 @@ start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
       sl = parse_one_pattern (patterns->d);
       if (!sl)
         {
-          log_error (_("start_cert_fetch: invalid pattern `%s'\n"),
+          log_error (_("start_cert_fetch: invalid pattern '%s'\n"),
                      patterns->d);
-          /* fixme: cleanup argv.  */
-          return gpg_error (GPG_ERR_INV_USER_ID);
+          err = gpg_error (GPG_ERR_INV_USER_ID);
+          goto leave;
         }
       if ((sl->flags & 1))
         err = make_url (&url, sl->d, "objectClass=*");
@@ -610,19 +626,19 @@ start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
         err = make_url (&url, base, sl->d);
       free_strlist (sl);
       if (err)
-        {
-          /* fixme: cleanup argv. */
-          return err;
-        }
+        goto leave;
       argv[argc++] = url;
     }
   argv[argc] = NULL;
 
   *context = xtrycalloc (1, sizeof **context);
   if (!*context)
-    return gpg_error_from_errno (errno);
+    {
+      err = gpg_error_from_errno (errno);
+      goto leave;
+    }
 
-  err = ldap_wrapper (ctrl, &(*context)->reader, argv);
+  err = ldap_wrapper (ctrl, &(*context)->reader, (const char**)argv);
 
   if (err)
     {
@@ -630,6 +646,13 @@ start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
       *context = NULL;
     }
 
+ leave:
+  for (; argc_malloced < argc; argc_malloced++)
+    xfree (argv[argc_malloced]);
+  xfree (proxy);
+  xfree (host);
+  xfree (user);
+  xfree (pass);
   return err;
 }
 
@@ -640,7 +663,7 @@ read_buffer (ksba_reader_t reader, unsigned char *buffer, size_t count)
 {
   gpg_error_t err;
   size_t nread;
-  
+
   while (count)
     {
       err = ksba_reader_read (reader, buffer, count, &nread);
@@ -664,9 +687,9 @@ fetch_next_cert_ldap (cert_fetch_context_t context,
   gpg_error_t err;
   unsigned char hdr[5];
   char *p, *pend;
-  int n;
+  unsigned long n;
   int okay = 0;
-  int is_cms = 0;
+  /* int is_cms = 0; */
 
   *value = NULL;
   *valuelen = 0;
@@ -677,18 +700,18 @@ fetch_next_cert_ldap (cert_fetch_context_t context,
       err = read_buffer (context->reader, hdr, 5);
       if (err)
         break;
-      n = (hdr[1] << 24)|(hdr[2]<<16)|(hdr[3]<<8)|hdr[4];
+      n = buf32_to_ulong (hdr+1);
       if (*hdr == 'V' && okay)
         {
 #if 0  /* That code is not yet ready.  */
-       
+
           if (is_cms)
             {
               /* The certificate needs to be parsed from CMS data. */
               ksba_cms_t cms;
               ksba_stop_reason_t stopreason;
               int i;
-          
+
               err = ksba_cms_new (&cms);
               if (err)
                 goto leave;
@@ -700,7 +723,7 @@ fetch_next_cert_ldap (cert_fetch_context_t context,
                   goto leave;
                 }
 
-              do 
+              do
                 {
                   err = ksba_cms_parse (cms, &stopreason);
                   if (err)
@@ -714,12 +737,12 @@ fetch_next_cert_ldap (cert_fetch_context_t context,
                     log_error ("userSMIMECertificate is not "
                                "a certs-only message\n");
                 }
-              while (stopreason != KSBA_SR_READY);   
-      
+              while (stopreason != KSBA_SR_READY);
+
               for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
                 {
                   check_and_store (ctrl, stats, cert, 0);
-                  ksba_cert_release (cert); 
+                  ksba_cert_release (cert);
                   cert = NULL;
                 }
               if (!i)
@@ -733,7 +756,7 @@ fetch_next_cert_ldap (cert_fetch_context_t context,
               *value = xtrymalloc (n);
               if (!*value)
                 return gpg_error_from_errno (errno);
-              *valuelen = n; 
+              *valuelen = n;
               err = read_buffer (context->reader, *value, n);
               break; /* Ready or error.  */
             }
@@ -750,7 +773,7 @@ fetch_next_cert_ldap (cert_fetch_context_t context,
               if (!context->tmpbuf)
                 return gpg_error_from_errno (errno);
               context->tmpbufsize = n;
-            }  
+            }
           err = read_buffer (context->reader, context->tmpbuf, n);
           if (err)
             break;
@@ -758,34 +781,34 @@ fetch_next_cert_ldap (cert_fetch_context_t context,
             {
               p = context->tmpbuf;
               p[n] = 0; /*(we allocated one extra byte for this.)*/
-              is_cms = 0;
+              /* fixme: is_cms = 0; */
               if ( (pend = strchr (p, ';')) )
                 *pend = 0; /* Strip off the extension. */
               if (!ascii_strcasecmp (p, USERCERTIFICATE))
                 {
                   if (DBG_LOOKUP)
-                    log_debug ("fetch_next_cert_ldap: got attribute `%s'\n",
+                    log_debug ("fetch_next_cert_ldap: got attribute '%s'\n",
                                USERCERTIFICATE);
                   okay = 1;
                 }
               else if (!ascii_strcasecmp (p, CACERTIFICATE))
                 {
                   if (DBG_LOOKUP)
-                    log_debug ("fetch_next_cert_ldap: got attribute `%s'\n",
+                    log_debug ("fetch_next_cert_ldap: got attribute '%s'\n",
                                CACERTIFICATE);
                   okay = 1;
                 }
               else if (!ascii_strcasecmp (p, X509CACERT))
                 {
                   if (DBG_LOOKUP)
-                    log_debug ("fetch_next_cert_ldap: got attribute `%s'\n",
+                    log_debug ("fetch_next_cert_ldap: got attribute '%s'\n",
                                CACERTIFICATE);
                   okay = 1;
                 }
 /*               else if (!ascii_strcasecmp (p, USERSMIMECERTIFICATE)) */
 /*                 { */
 /*                   if (DBG_LOOKUP) */
-/*                     log_debug ("fetch_next_cert_ldap: got attribute `%s'\n", */
+/*                     log_debug ("fetch_next_cert_ldap: got attribute '%s'\n", */
 /*                                USERSMIMECERTIFICATE); */
 /*                   okay = 1; */
 /*                   is_cms = 1; */
@@ -793,7 +816,7 @@ fetch_next_cert_ldap (cert_fetch_context_t context,
               else
                 {
                   if (DBG_LOOKUP)
-                    log_debug ("fetch_next_cert_ldap: got attribute `%s'"
+                    log_debug ("fetch_next_cert_ldap: got attribute '%s'"
                                " -  ignored\n", p);
                   okay = 0;
                 }