# HG changeset patch
# User Mauro Iorio <mio@bit4id.com>
# Date 1284732726 -7200
# Node ID 7873bbe6509bc0cd2aa5779b55c8a1d715368fc2
# Parent  4d558e814291dc81ecb799c2de621fdc40d13ad5
[libcurl]: Support for tunnelling ldap queries through HTTP-Proxy

As of curl-7.21.1 tunnelling ldap queries through HTTP Proxies is not
supported. Acutally if --proxytunnel command-line option (or equivalent
CURLOPT_HTTPPROXYTUNNEL) is used for ldap queries like
ldap://ldap.my.server.com/... You are unable to successfully
execute the query. In facts ldap_*_bind is executed directly against the
ldap server and proxy is totally ignored. This is true for both openLDAP
and Microsoft LDAP API.

Step to reproduce the error:
Just launch "curl --proxytunnel --proxy 192.168.1.1:8080
ldap://ldap.my.server.com/dc=... "

The patch provided adds an invocation to Curl_proxyCONNECT against the
provided proxy address and on successful "CONNECT" it tunnels ldap
query to the final ldap server through the HTTP proxy.
As far as I know Microsoft LDAP APIs don't permit tunnelling in any
way so the patch provided is for OpenLDAP only.
The patch has been developed against OpenLDAP 2.4.23 and has been
tested with Microsoft ISA Server 2006 and works properly with basic,
digest and NTLM authentication.

diff --git a/lib/openldap.c b/lib/openldap.c
--- a/lib/openldap.c
+++ b/lib/openldap.c
@@ -165,6 +165,7 @@
   li = calloc(1, sizeof(ldapconninfo));
   li->proto = proto;
   conn->proto.generic = li;
+  conn->bits.close = bool_false;
   /* TODO:
    * - provide option to choose SASL Binds instead of Simple
    */
@@ -198,6 +199,34 @@
 
   ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
 
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY)
+  if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
+    /* for LDAP over HTTP proxy */
+    struct HTTP http_proxy;
+    ldapconninfo *li_save;
+
+    /* BLOCKING */
+    /* We want "seamless" LDAP operations through HTTP proxy tunnel */
+
+    /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member
+     * conn->proto.http; we want LDAP through HTTP and we have to change the
+     * member temporarily for connecting to the HTTP proxy. After
+     * Curl_proxyCONNECT we have to set back the member to the original struct
+     * LDAP pointer
+     */
+    li_save = data->state.proto.generic;
+    memset(&http_proxy, 0, sizeof(http_proxy));
+    data->state.proto.http = &http_proxy;
+    result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
+                               conn->host.name, conn->remote_port);
+
+    data->state.proto.generic = li_save;
+
+    if(CURLE_OK != result)
+      return result;
+  }
+#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */
+
 #ifdef USE_SSL
   if (conn->protocol & PROT_SSL) {
     CURLcode res;

