Imported Upstream version 7.53.1
[platform/upstream/curl.git] / lib / ldap.c
index f27fa90..979ce7d 100644 (file)
@@ -5,11 +5,11 @@
  *                | (__| |_| |  _ <| |___
  *                 \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.haxx.se/docs/copyright.html.
  *
  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  * copies of the Software, and permit persons to whom the Software is
@@ -35,7 +35,7 @@
  * OpenLDAP library versions, USE_OPENLDAP shall not be defined.
  */
 
-#ifdef CURL_LDAP_WIN            /* Use Windows LDAP implementation. */
+#ifdef USE_WIN32_LDAP           /* Use Windows LDAP implementation. */
 # include <winldap.h>
 # ifndef LDAP_VENDOR_NAME
 #  error Your Platform SDK is NOT sufficient for LDAP support! \
 # endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */
 #endif
 
+/* These are macros in both <wincrypt.h> (in above <winldap.h>) and typedefs
+ * in BoringSSL's <openssl/x509.h>
+ */
+#ifdef HAVE_BORINGSSL
+# undef X509_NAME
+# undef X509_CERT_PAIR
+# undef X509_EXTENSIONS
+#endif
+
 #include "urldata.h"
 #include <curl/curl.h>
 #include "sendf.h"
 #include "escape.h"
 #include "progress.h"
 #include "transfer.h"
-#include "strequal.h"
+#include "strcase.h"
 #include "strtok.h"
 #include "curl_ldap.h"
-#include "curl_memory.h"
 #include "curl_multibyte.h"
 #include "curl_base64.h"
-#include "rawstr.h"
 #include "connect.h"
-
-#define _MPRINTF_REPLACE /* use our functions only */
-#include <curl/mprintf.h>
-
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
 #include "memdebug.h"
 
 #ifndef HAVE_LDAP_URL_PARSE
@@ -81,7 +87,7 @@
 typedef struct {
   char   *lud_host;
   int     lud_port;
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
   TCHAR  *lud_dn;
   TCHAR **lud_attrs;
 #else
@@ -89,7 +95,7 @@ typedef struct {
   char  **lud_attrs;
 #endif
   int     lud_scope;
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
   TCHAR  *lud_filter;
 #else
   char   *lud_filter;
@@ -103,9 +109,9 @@ typedef struct {
 #undef LDAPURLDesc
 #define LDAPURLDesc             CURL_LDAPURLDesc
 
-static int  _ldap_url_parse (const struct connectdata *conn,
-                             LDAPURLDesc **ludp);
-static void _ldap_free_urldesc (LDAPURLDesc *ludp);
+static int  _ldap_url_parse(const struct connectdata *conn,
+                            LDAPURLDesc **ludp);
+static void _ldap_free_urldesc(LDAPURLDesc *ludp);
 
 #undef ldap_free_urldesc
 #define ldap_free_urldesc       _ldap_free_urldesc
@@ -113,11 +119,11 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp);
 
 #ifdef DEBUG_LDAP
   #define LDAP_TRACE(x)   do { \
-                            _ldap_trace ("%u: ", __LINE__); \
+                            _ldap_trace("%u: ", __LINE__); \
                             _ldap_trace x; \
                           } WHILE_FALSE
 
-  static void _ldap_trace (const char *fmt, ...);
+  static void _ldap_trace(const char *fmt, ...);
 #else
   #define LDAP_TRACE(x)   Curl_nop_stmt
 #endif
@@ -185,16 +191,16 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
   LDAPMessage *ldapmsg = NULL;
   LDAPMessage *entryIterator;
   int num = 0;
-  struct SessionHandle *data=conn->data;
+  struct Curl_easy *data=conn->data;
   int ldap_proto = LDAP_VERSION3;
   int ldap_ssl = 0;
   char *val_b64 = NULL;
   size_t val_b64_sz = 0;
   curl_off_t dlsize = 0;
 #ifdef LDAP_OPT_NETWORK_TIMEOUT
-  struct timeval ldap_timeout = {10,0}; /* 10 sec connection/search timeout */
+  struct timeval ldap_timeout = {10, 0}; /* 10 sec connection/search timeout */
 #endif
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
   TCHAR *host = NULL;
   TCHAR *user = NULL;
   TCHAR *passwd = NULL;
@@ -220,13 +226,13 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
     goto quit;
   }
 
-  /* Get the URL scheme ( either ldap or ldaps ) */
+  /* Get the URL scheme (either ldap or ldaps) */
   if(conn->given->flags & PROTOPT_SSL)
     ldap_ssl = 1;
   infof(data, "LDAP local: trying to establish %s connection\n",
           ldap_ssl ? "encrypted" : "cleartext");
 
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
   host = Curl_convert_UTF8_to_tchar(conn->host.name);
   if(!host) {
     result = CURLE_OUT_OF_MEMORY;
@@ -259,13 +265,13 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
 
   if(ldap_ssl) {
 #ifdef HAVE_LDAP_SSL
-#ifdef CURL_LDAP_WIN
+#ifdef USE_WIN32_LDAP
     /* Win32 LDAP SDK doesn't support insecure mode without CA! */
     server = ldap_sslinit(host, (int)conn->port, 1);
     ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
 #else
     int ldap_option;
-    char* ldap_ca = data->set.str[STRING_SSL_CAFILE];
+    char *ldap_ca = conn->ssl_config.CAfile;
 #if defined(CURL_HAS_NOVELL_LDAPSDK)
     rc = ldapssl_client_init(NULL, NULL);
     if(rc != LDAP_SUCCESS) {
@@ -273,11 +279,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       result = CURLE_SSL_CERTPROBLEM;
       goto quit;
     }
-    if(data->set.ssl.verifypeer) {
+    if(conn->ssl_config.verifypeer) {
       /* Novell SDK supports DER or BASE64 files. */
       int cert_type = LDAPSSL_CERT_FILETYPE_B64;
-      if((data->set.str[STRING_CERT_TYPE]) &&
-         (Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "DER")))
+      if((data->set.ssl.cert_type) &&
+         (strcasecompare(data->set.ssl.cert_type, "DER")))
         cert_type = LDAPSSL_CERT_FILETYPE_DER;
       if(!ldap_ca) {
         failf(data, "LDAP local: ERROR %s CA cert not set!",
@@ -315,10 +321,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       goto quit;
     }
 #elif defined(LDAP_OPT_X_TLS)
-    if(data->set.ssl.verifypeer) {
+    if(conn->ssl_config.verifypeer) {
       /* OpenLDAP SDK supports BASE64 files. */
-      if((data->set.str[STRING_CERT_TYPE]) &&
-         (!Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "PEM"))) {
+      if((data->set.ssl.cert_type) &&
+         (!strcasecompare(data->set.ssl.cert_type, "PEM"))) {
         failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
         result = CURLE_SSL_CERTPROBLEM;
         goto quit;
@@ -392,7 +398,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       goto quit;
     }
   }
-#ifdef CURL_LDAP_WIN
+#ifdef USE_WIN32_LDAP
   ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
 #endif
 
@@ -421,7 +427,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       entryIterator;
       entryIterator = ldap_next_entry(server, entryIterator), num++) {
     BerElement *ber = NULL;
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
     TCHAR *attribute;
 #else
     char  *attribute;       /*! suspicious that this isn't 'const' */
@@ -432,7 +438,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
     {
       char *name;
       size_t name_len;
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
       TCHAR *dn = ldap_get_dn(server, entryIterator);
       name = Curl_convert_tchar_to_UTF8(dn);
       if(!name) {
@@ -449,7 +455,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
 
       result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
       if(result) {
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
         Curl_unicodefree(name);
 #endif
         ldap_memfree(dn);
@@ -460,7 +466,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *) name,
                                  name_len);
       if(result) {
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
         Curl_unicodefree(name);
 #endif
         ldap_memfree(dn);
@@ -470,7 +476,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
 
       result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
       if(result) {
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
         Curl_unicodefree(name);
 #endif
         ldap_memfree(dn);
@@ -480,7 +486,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
 
       dlsize += name_len + 5;
 
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
       Curl_unicodefree(name);
 #endif
       ldap_memfree(dn);
@@ -492,7 +498,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
         attribute = ldap_next_attribute(server, entryIterator, ber)) {
       BerValue **vals;
       size_t attr_len;
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
       char *attr = Curl_convert_tchar_to_UTF8(attribute);
       if(!attr) {
         if(ber)
@@ -513,7 +519,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
           result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
           if(result) {
             ldap_value_free_len(vals);
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
             Curl_unicodefree(attr);
 #endif
             ldap_memfree(attribute);
@@ -527,7 +533,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
                                      (char *) attr, attr_len);
           if(result) {
             ldap_value_free_len(vals);
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
             Curl_unicodefree(attr);
 #endif
             ldap_memfree(attribute);
@@ -540,7 +546,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
           result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
           if(result) {
             ldap_value_free_len(vals);
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
             Curl_unicodefree(attr);
 #endif
             ldap_memfree(attribute);
@@ -562,7 +568,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
                                         &val_b64_sz);
             if(result) {
               ldap_value_free_len(vals);
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
               Curl_unicodefree(attr);
 #endif
               ldap_memfree(attribute);
@@ -578,7 +584,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
               free(val_b64);
               if(result) {
                 ldap_value_free_len(vals);
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
                 Curl_unicodefree(attr);
 #endif
                 ldap_memfree(attribute);
@@ -596,7 +602,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
                                        vals[i]->bv_len);
             if(result) {
               ldap_value_free_len(vals);
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
               Curl_unicodefree(attr);
 #endif
               ldap_memfree(attribute);
@@ -612,7 +618,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
           result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
           if(result) {
             ldap_value_free_len(vals);
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
             Curl_unicodefree(attr);
 #endif
             ldap_memfree(attribute);
@@ -630,7 +636,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       }
 
       /* Free the attribute as we are done with it */
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
       Curl_unicodefree(attr);
 #endif
       ldap_memfree(attribute);
@@ -649,7 +655,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
 quit:
   if(ldapmsg) {
     ldap_msgfree(ldapmsg);
-    LDAP_TRACE (("Received %d entries\n", num));
+    LDAP_TRACE(("Received %d entries\n", num));
   }
   if(rc == LDAP_SIZELIMIT_EXCEEDED)
     infof(data, "There are more than %d entries\n", num);
@@ -662,7 +668,7 @@ quit:
     ldapssl_client_deinit();
 #endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
 
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
   Curl_unicodefree(passwd);
   Curl_unicodefree(user);
   Curl_unicodefree(host);
@@ -676,7 +682,7 @@ quit:
 }
 
 #ifdef DEBUG_LDAP
-static void _ldap_trace (const char *fmt, ...)
+static void _ldap_trace(const char *fmt, ...)
 {
   static int do_trace = -1;
   va_list args;
@@ -688,9 +694,9 @@ static void _ldap_trace (const char *fmt, ...)
   if(!do_trace)
     return;
 
-  va_start (args, fmt);
-  vfprintf (stderr, fmt, args);
-  va_end (args);
+  va_start(args, fmt);
+  vfprintf(stderr, fmt, args);
+  va_end(args);
 }
 #endif
 
@@ -699,18 +705,18 @@ static void _ldap_trace (const char *fmt, ...)
 /*
  * Return scope-value for a scope-string.
  */
-static int str2scope (const char *p)
+static int str2scope(const char *p)
 {
-  if(strequal(p, "one"))
-     return LDAP_SCOPE_ONELEVEL;
-  if(strequal(p, "onetree"))
-     return LDAP_SCOPE_ONELEVEL;
-  if(strequal(p, "base"))
-     return LDAP_SCOPE_BASE;
-  if(strequal(p, "sub"))
-     return LDAP_SCOPE_SUBTREE;
-  if(strequal( p, "subtree"))
-     return LDAP_SCOPE_SUBTREE;
+  if(strcasecompare(p, "one"))
+    return LDAP_SCOPE_ONELEVEL;
+  if(strcasecompare(p, "onetree"))
+    return LDAP_SCOPE_ONELEVEL;
+  if(strcasecompare(p, "base"))
+    return LDAP_SCOPE_BASE;
+  if(strcasecompare(p, "sub"))
+    return LDAP_SCOPE_SUBTREE;
+  if(strcasecompare(p, "subtree"))
+    return LDAP_SCOPE_SUBTREE;
   return (-1);
 }
 
@@ -760,7 +766,7 @@ static bool split_str(char *str, char ***out, size_t *count)
  *
  * Defined in RFC4516 section 2.
  */
-static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
+static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 {
   int rc = LDAP_SUCCESS;
   char *path;
@@ -769,9 +775,9 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
   size_t i;
 
   if(!conn->data ||
-      !conn->data->state.path ||
-      conn->data->state.path[0] != '/' ||
-      !checkprefix("LDAP", conn->data->change.url))
+     !conn->data->state.path ||
+     conn->data->state.path[0] != '/' ||
+     !checkprefix("LDAP", conn->data->change.url))
     return LDAP_INVALID_SYNTAX;
 
   ludp->lud_scope = LDAP_SCOPE_BASE;
@@ -791,18 +797,19 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
   if(*p) {
     char *dn = p;
     char *unescaped;
+    CURLcode result;
 
-    LDAP_TRACE (("DN '%s'\n", dn));
+    LDAP_TRACE(("DN '%s'\n", dn));
 
     /* Unescape the DN */
-    unescaped = curl_easy_unescape(conn->data, dn, 0, NULL);
-    if(!unescaped) {
+    result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE);
+    if(result) {
       rc = LDAP_NO_MEMORY;
 
       goto quit;
     }
 
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
     /* Convert the unescaped string to a tchar */
     ludp->lud_dn = Curl_convert_UTF8_to_tchar(unescaped);
 
@@ -840,13 +847,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
     }
 
     /* Allocate our array (+1 for the NULL entry) */
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
     ludp->lud_attrs = calloc(count + 1, sizeof(TCHAR *));
 #else
     ludp->lud_attrs = calloc(count + 1, sizeof(char *));
 #endif
     if(!ludp->lud_attrs) {
-      Curl_safefree(attributes);
+      free(attributes);
 
       rc = LDAP_NO_MEMORY;
 
@@ -855,20 +862,22 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
 
     for(i = 0; i < count; i++) {
       char *unescaped;
+      CURLcode result;
 
-      LDAP_TRACE (("attr[%d] '%s'\n", i, attributes[i]));
+      LDAP_TRACE(("attr[%d] '%s'\n", i, attributes[i]));
 
       /* Unescape the attribute */
-      unescaped = curl_easy_unescape(conn->data, attributes[i], 0, NULL);
-      if(!unescaped) {
-        Curl_safefree(attributes);
+      result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
+                              FALSE);
+      if(result) {
+        free(attributes);
 
         rc = LDAP_NO_MEMORY;
 
         goto quit;
       }
 
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
       /* Convert the unescaped string to a tchar */
       ludp->lud_attrs[i] = Curl_convert_UTF8_to_tchar(unescaped);
 
@@ -876,7 +885,7 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
       Curl_unicodefree(unescaped);
 
       if(!ludp->lud_attrs[i]) {
-        Curl_safefree(attributes);
+        free(attributes);
 
         rc = LDAP_NO_MEMORY;
 
@@ -889,7 +898,7 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
       ludp->lud_attrs_dups++;
     }
 
-    Curl_safefree(attributes);
+    free(attributes);
   }
 
   p = q;
@@ -908,7 +917,7 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
 
       goto quit;
     }
-    LDAP_TRACE (("scope %d\n", ludp->lud_scope));
+    LDAP_TRACE(("scope %d\n", ludp->lud_scope));
   }
 
   p = q;
@@ -923,18 +932,19 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
   if(*p) {
     char *filter = p;
     char *unescaped;
+    CURLcode result;
 
-    LDAP_TRACE (("filter '%s'\n", filter));
+    LDAP_TRACE(("filter '%s'\n", filter));
 
     /* Unescape the filter */
-    unescaped = curl_easy_unescape(conn->data, filter, 0, NULL);
-    if(!unescaped) {
+    result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE);
+    if(result) {
       rc = LDAP_NO_MEMORY;
 
       goto quit;
     }
 
-#if defined(CURL_LDAP_WIN)
+#if defined(USE_WIN32_LDAP)
     /* Convert the unescaped string to a tchar */
     ludp->lud_filter = Curl_convert_UTF8_to_tchar(unescaped);
 
@@ -959,13 +969,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
   }
 
 quit:
-  Curl_safefree(path);
+  free(path);
 
   return rc;
 }
 
-static int _ldap_url_parse (const struct connectdata *conn,
-                            LDAPURLDesc **ludpp)
+static int _ldap_url_parse(const struct connectdata *conn,
+                           LDAPURLDesc **ludpp)
 {
   LDAPURLDesc *ludp = calloc(1, sizeof(*ludp));
   int rc;
@@ -974,7 +984,7 @@ static int _ldap_url_parse (const struct connectdata *conn,
   if(!ludp)
      return LDAP_NO_MEMORY;
 
-  rc = _ldap_url_parse2 (conn, ludp);
+  rc = _ldap_url_parse2(conn, ludp);
   if(rc != LDAP_SUCCESS) {
     _ldap_free_urldesc(ludp);
     ludp = NULL;
@@ -983,18 +993,15 @@ static int _ldap_url_parse (const struct connectdata *conn,
   return (rc);
 }
 
-static void _ldap_free_urldesc (LDAPURLDesc *ludp)
+static void _ldap_free_urldesc(LDAPURLDesc *ludp)
 {
   size_t i;
 
   if(!ludp)
     return;
 
-  if(ludp->lud_dn)
-    free(ludp->lud_dn);
-
-  if(ludp->lud_filter)
-    free(ludp->lud_filter);
+  free(ludp->lud_dn);
+  free(ludp->lud_filter);
 
   if(ludp->lud_attrs) {
     for(i = 0; i < ludp->lud_attrs_dups; i++)
@@ -1002,7 +1009,7 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp)
     free(ludp->lud_attrs);
   }
 
-  free (ludp);
+  free(ludp);
 }
 #endif  /* !HAVE_LDAP_URL_PARSE */
 #endif  /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */