From 2e056353b00d0944bdb2f8e948cc40a4dc0f3dfb Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Tue, 25 May 2010 00:44:42 +0200 Subject: LDAP: properly implemented as a curl_handler makes the LDAP code much cleaner, nicer and in general being a better libcurl citizen. If a new enough OpenLDAP version is detect, the new and shiny lib/openldap.c code is then used instead of the old cruft Code by Howard, minor cleanups by Daniel. --- lib/openldap.c | 576 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 576 insertions(+) create mode 100644 lib/openldap.c (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c new file mode 100644 index 000000000..0f10e0a2c --- /dev/null +++ b/lib/openldap.c @@ -0,0 +1,576 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, Howard Chu, + * + * 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. + * + * 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 + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "setup.h" + +#ifdef USE_OPENLDAP + +#include "urldata.h" +#include +#include "sendf.h" +#include +#include "sslgen.h" +#include "transfer.h" +#include "curl_base64.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include + +#include "memdebug.h" + +static CURLcode ldap_setup(struct connectdata *conn); +static CURLcode ldap_do(struct connectdata *conn, bool *done); +static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool); +static CURLcode ldap_connect(struct connectdata *conn, bool *done); +static CURLcode ldap_connecting(struct connectdata *conn, bool *done); +static CURLcode ldap_disconnect(struct connectdata *conn); + +static Curl_recv ldap_recv; + +/* + * LDAP protocol handler. + */ + +const struct Curl_handler Curl_handler_ldap = { + "LDAP", /* scheme */ + ldap_setup, /* setup_connection */ + ldap_do, /* do_it */ + ldap_done, /* done */ + ZERO_NULL, /* do_more */ + ldap_connect, /* connect_it */ + ldap_connecting, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* perform_getsock */ + ldap_disconnect, /* disconnect */ + PORT_LDAP, /* defport */ + PROT_LDAP /* protocol */ +}; + +/* + * LDAPS protocol handler. + */ + +const struct Curl_handler Curl_handler_ldaps = { + "LDAPS", /* scheme */ + ldap_setup, /* setup_connection */ + ldap_do, /* do_it */ + ldap_done, /* done */ + ZERO_NULL, /* do_more */ + ldap_connect, /* connect_it */ + ldap_connecting, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* perform_getsock */ + ldap_disconnect, /* disconnect */ + PORT_LDAPS, /* defport */ + PROT_LDAP | PROT_SSL /* protocol */ +}; + +static const char *url_errs[] = { + "success", + "out of memory", + "bad parameter", + "unrecognized scheme", + "unbalanced delimiter", + "bad URL", + "bad host or port", + "bad or missing attributes", + "bad or missing scope", + "bad or missing filter", + "bad or missing extensions" +}; + +typedef struct ldapconninfo { + LDAP *ld; + Curl_recv *recv; /* for stacking SSL handler */ + Curl_send *send; + int proto; + int msgid; + bool ssldone; + bool sslinst; + bool didbind; +} ldapconninfo; + +typedef struct ldapreqinfo { + int msgid; + int nument; +} ldapreqinfo; + +static CURLcode ldap_setup(struct connectdata *conn) +{ + ldapconninfo *li; + LDAPURLDesc *lud; + struct SessionHandle *data=conn->data; + int rc, proto; + CURLcode status; + + rc = ldap_url_parse(data->change.url, &lud); + if (rc != LDAP_URL_SUCCESS) { + const char *msg = "url parsing problem"; + status = CURLE_URL_MALFORMAT; + if (rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { + if (rc == LDAP_URL_ERR_MEM) + status = CURLE_OUT_OF_MEMORY; + msg = url_errs[rc]; + } + failf(conn->data, "LDAP local: %s", msg); + return status; + } + proto = ldap_pvt_url_scheme2proto(lud->lud_scheme); + ldap_free_urldesc(lud); + + li = calloc(1, sizeof(ldapconninfo)); + li->proto = proto; + conn->proto.generic = li; + /* TODO: + * - provide option to choose SASL Binds instead of Simple + */ + return CURLE_OK; +} + +static Sockbuf_IO ldapsb_tls; + +static CURLcode ldap_connect(struct connectdata *conn, bool *done) +{ + ldapconninfo *li = conn->proto.generic; + struct SessionHandle *data=conn->data; + int rc, proto = LDAP_VERSION3; + char hosturl[1024], *ptr; + + strcpy(hosturl, "ldap"); + ptr = hosturl+4; + if (conn->protocol & PROT_SSL) + *ptr++ = 's'; + snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d", + conn->host.name, conn->port); + + rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld); + if (rc) { + failf(data, "LDAP local: Cannot connect to %s, %s", + hosturl, ldap_err2string(rc)); + return CURLE_COULDNT_CONNECT; + } + + ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + + if (conn->protocol & PROT_SSL) { + CURLcode res; + if (data->state.used_interface == Curl_if_easy) { + res = Curl_ssl_connect(conn, FIRSTSOCKET); + if (res) + return res; + li->ssldone = TRUE; + } else { + res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); + if (res) + return res; + } + } + + if (data->state.used_interface == Curl_if_easy) + return ldap_connecting(conn, done); + + return CURLE_OK; +} + +static CURLcode ldap_connecting(struct connectdata *conn, bool *done) +{ + ldapconninfo *li = conn->proto.generic; + struct SessionHandle *data=conn->data; + LDAPMessage *result = NULL; + struct timeval tv = {0,1}, *tvp; + int rc, err; + char *info = NULL; + + if (conn->protocol & PROT_SSL) { + /* Is the SSL handshake complete yet? */ + if (!li->ssldone) { + CURLcode res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); + if (res || !li->ssldone) + return res; + } + /* Have we installed the libcurl SSL handlers into the sockbuf yet? */ + if (!li->sslinst) { + Sockbuf *sb; + ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); + ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn); + li->sslinst = TRUE; + li->recv = conn->recv[FIRSTSOCKET]; + li->send = conn->send[FIRSTSOCKET]; + } + } + + if (data->state.used_interface == Curl_if_easy) + tvp = NULL; /* let ldap_result block indefinitely */ + else + tvp = &tv; + +retry: + if (!li->didbind) { + char *binddn; + struct berval passwd; + + if (conn->bits.user_passwd) { + binddn = conn->user; + passwd.bv_val = conn->passwd; + passwd.bv_len = strlen(passwd.bv_val); + } else { + binddn = NULL; + passwd.bv_val = NULL; + passwd.bv_len = 0; + } + rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd, + NULL, NULL, &li->msgid); + if (rc) + return CURLE_LDAP_CANNOT_BIND; + li->didbind = TRUE; + if (tvp) + return CURLE_OK; + } + + rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, tvp, &result); + if (rc < 0) { + failf(data, "LDAP local: bind ldap_result %s", ldap_err2string(rc)); + return CURLE_LDAP_CANNOT_BIND; + } + if (rc == 0) { + /* timed out */ + return CURLE_OK; + } + rc = ldap_parse_result(li->ld, result, &err, NULL, &info, NULL, NULL, 1); + if (rc) { + failf(data, "LDAP local: bind ldap_parse_result %s", ldap_err2string(rc)); + return CURLE_LDAP_CANNOT_BIND; + } + /* Try to fallback to LDAPv2? */ + if (err == LDAP_PROTOCOL_ERROR) { + int proto; + ldap_get_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + if (proto == LDAP_VERSION3) { + ldap_memfree(info); + proto = LDAP_VERSION2; + ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + li->didbind = FALSE; + goto retry; + } + } + + if (err) { + failf(data, "LDAP remote: bind failed %s %s", ldap_err2string(rc), + info ? info : ""); + return CURLE_LOGIN_DENIED; + } + conn->recv[FIRSTSOCKET] = ldap_recv; + *done = TRUE; + return CURLE_OK; +} + +static CURLcode ldap_disconnect(struct connectdata *conn) +{ + ldapconninfo *li = conn->proto.generic; + + if (li) { + if (li->ld) { + ldap_unbind(li->ld); + li->ld = NULL; + } + conn->proto.generic = NULL; + free(li); + } + return CURLE_OK; +} + +static CURLcode ldap_do(struct connectdata *conn, bool *done) +{ + ldapconninfo *li = conn->proto.generic; + ldapreqinfo *lr; + CURLcode status = CURLE_OK; + int rc = 0; + LDAPURLDesc *ludp = NULL; + int msgid; + struct SessionHandle *data=conn->data; + + conn->bits.close = FALSE; + + infof(data, "LDAP local: %s\n", data->change.url); + + rc = ldap_url_parse(data->change.url, &ludp); + if (rc != LDAP_URL_SUCCESS) { + const char *msg = "url parsing problem"; + status = CURLE_URL_MALFORMAT; + if (rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { + if (rc == LDAP_URL_ERR_MEM) + status = CURLE_OUT_OF_MEMORY; + msg = url_errs[rc]; + } + failf(conn->data, "LDAP local: %s", msg); + return status; + } + + rc = ldap_search_ext(li->ld, ludp->lud_dn, ludp->lud_scope, + ludp->lud_filter, ludp->lud_attrs, 0, + NULL, NULL, NULL, 0, &msgid); + ldap_free_urldesc(ludp); + if (rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc)); + return CURLE_LDAP_SEARCH_FAILED; + } + lr = calloc(1,sizeof(ldapreqinfo)); + lr->msgid = msgid; + data->state.proto.generic = lr; + Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); + *done = TRUE; + return CURLE_OK; +} + +static CURLcode ldap_done(struct connectdata *conn, CURLcode res, + bool premature) +{ + ldapreqinfo *lr = conn->data->state.proto.generic; + (void)res; + (void)premature; + + if (lr) { + /* if there was a search in progress, abandon it */ + if (lr->msgid) { + ldapconninfo *li = conn->proto.generic; + ldap_abandon(li->ld, lr->msgid); + lr->msgid = 0; + } + conn->data->state.proto.generic = NULL; + free(lr); + } + return CURLE_OK; +} + +static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, + size_t len, CURLcode *err) +{ + ldapconninfo *li = conn->proto.generic; + struct SessionHandle *data=conn->data; + ldapreqinfo *lr = data->state.proto.generic; + int rc, ret; + LDAPMessage *result = NULL; + LDAPMessage *ent; + BerElement *ber = NULL; + struct timeval tv = {0,1}; + (void)len; + (void)buf; + (void)sockindex; + + rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &result); + if (rc < 0) { + failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc)); + *err = CURLE_RECV_ERROR; + return -1; + } + + *err = CURLE_AGAIN; + ret = -1; + + /* timed out */ + if (result == NULL) + return ret; + + for (ent = ldap_first_message(li->ld, result); ent; + ent = ldap_next_message(li->ld, ent)) { + struct berval bv, *bvals, **bvp = &bvals; + int binary = 0, msgtype; + + msgtype = ldap_msgtype(ent); + if (msgtype == LDAP_RES_SEARCH_RESULT) { + int code; + char *info = NULL; + rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0); + if (rc) { + failf(data, "LDAP local: search ldap_parse_result %s", ldap_err2string(rc)); + *err = CURLE_LDAP_SEARCH_FAILED; + } else if (code && code != LDAP_SIZELIMIT_EXCEEDED) { + failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc), + info ? info : ""); + *err = CURLE_LDAP_SEARCH_FAILED; + } else { + /* successful */ + if (code == LDAP_SIZELIMIT_EXCEEDED) + infof(data, "There are more than %d entries\n", lr->nument); + data->req.size = data->req.bytecount; + *err = CURLE_OK; + ret = 0; + } + lr->msgid = 0; + ldap_memfree(info); + break; + } else if (msgtype != LDAP_RES_SEARCH_ENTRY) { + continue; + } + + lr->nument++; + rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv); + Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); + Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); + Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); + data->req.bytecount += bv.bv_len + 5; + + for (rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp); + rc == LDAP_SUCCESS; + rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) { + int i; + + if (bv.bv_val == NULL) break; + + if (bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7)) + binary = 1; + + for (i=0; bvals[i].bv_val != NULL; i++) { + int binval = 0; + Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); + Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); + Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1); + data->req.bytecount += bv.bv_len + 2; + + if (!binary) { + /* check for leading or trailing whitespace */ + if (isspace(bvals[i].bv_val[0]) || + isspace(bvals[i].bv_val[bvals[i].bv_len-1])) { + binval = 1; + } else { + /* check for unprintable characters */ + unsigned int j; + for (j=0; jreq.bytecount += 2; + if(val_b64_sz > 0) { + Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz); + free(val_b64); + data->req.bytecount += val_b64_sz; + } + } else { + Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1); + Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val, + bvals[i].bv_len); + data->req.bytecount += bvals[i].bv_len + 1; + } + Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + data->req.bytecount++; + } + ber_memfree(bvals); + Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + data->req.bytecount++; + } + Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); + data->req.bytecount++; + ber_free(ber, 0); + } + ldap_msgfree(result); + return ret; +} + +static int +ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg) +{ + sbiod->sbiod_pvt = arg; + return 0; +} + +static int +ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod) +{ + sbiod->sbiod_pvt = NULL; + return 0; +} + +/* We don't need to do anything because libcurl does it already */ +static int +ldapsb_tls_close(Sockbuf_IO_Desc *sbiod) +{ + (void)sbiod; + return 0; +} + +static int +ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) +{ + (void)arg; + if (opt == LBER_SB_OPT_DATA_READY) { + struct connectdata *conn = sbiod->sbiod_pvt; + return Curl_ssl_data_pending(conn, FIRSTSOCKET); + } + return 0; +} + +static ber_slen_t +ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct connectdata *conn = sbiod->sbiod_pvt; + ldapconninfo *li = conn->proto.generic; + ber_slen_t ret; + CURLcode err = CURLE_RECV_ERROR; + + ret = li->recv(conn, FIRSTSOCKET, buf, len, &err); + if (ret < 0 && err == CURLE_AGAIN) { + SET_SOCKERRNO(EWOULDBLOCK); + } + return ret; +} + +static ber_slen_t +ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct connectdata *conn = sbiod->sbiod_pvt; + ldapconninfo *li = conn->proto.generic; + ber_slen_t ret; + CURLcode err = CURLE_SEND_ERROR; + + ret = li->send(conn, FIRSTSOCKET, buf, len, &err); + if (ret < 0 && err == CURLE_AGAIN) { + SET_SOCKERRNO(EWOULDBLOCK); + } + return ret; +} + +static Sockbuf_IO ldapsb_tls = +{ + ldapsb_tls_setup, + ldapsb_tls_remove, + ldapsb_tls_ctrl, + ldapsb_tls_read, + ldapsb_tls_write, + ldapsb_tls_close +}; + +#endif /* USE_OPENLDAP */ -- cgit v1.2.1 From c03cbb38ad27465a014f7abfe1438033071d2b6f Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 27 May 2010 22:37:00 +0200 Subject: openldap: fix compiler warnings --- lib/openldap.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 0f10e0a2c..237230215 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -37,6 +37,11 @@ #include "memdebug.h" +#ifndef _LDAP_PVT_H +extern int ldap_pvt_url_scheme2proto(const char *); +extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, LDAP **ld); +#endif + static CURLcode ldap_setup(struct connectdata *conn); static CURLcode ldap_do(struct connectdata *conn, bool *done); static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool); @@ -293,7 +298,7 @@ static CURLcode ldap_disconnect(struct connectdata *conn) if (li) { if (li->ld) { - ldap_unbind(li->ld); + ldap_unbind_ext(li->ld, NULL, NULL); li->ld = NULL; } conn->proto.generic = NULL; @@ -356,7 +361,7 @@ static CURLcode ldap_done(struct connectdata *conn, CURLcode res, /* if there was a search in progress, abandon it */ if (lr->msgid) { ldapconninfo *li = conn->proto.generic; - ldap_abandon(li->ld, lr->msgid); + ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL); lr->msgid = 0; } conn->data->state.proto.generic = NULL; -- cgit v1.2.1 From 123f80ae5401bb4d8ab8e8ccdb6fda4ac76b0767 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 28 May 2010 12:22:35 +0200 Subject: LDAP: make it build without SSL if no such support is available of course it also goes for the case where SSL is explicitly disabled --- lib/openldap.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 237230215..16bf7b8c8 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -72,6 +72,7 @@ const struct Curl_handler Curl_handler_ldap = { PROT_LDAP /* protocol */ }; +#ifdef USE_SSL /* * LDAPS protocol handler. */ @@ -92,6 +93,7 @@ const struct Curl_handler Curl_handler_ldaps = { PORT_LDAPS, /* defport */ PROT_LDAP | PROT_SSL /* protocol */ }; +#endif static const char *url_errs[] = { "success", @@ -155,7 +157,9 @@ static CURLcode ldap_setup(struct connectdata *conn) return CURLE_OK; } +#ifdef USE_SSL static Sockbuf_IO ldapsb_tls; +#endif static CURLcode ldap_connect(struct connectdata *conn, bool *done) { @@ -180,6 +184,7 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); +#ifdef USE_SSL if (conn->protocol & PROT_SSL) { CURLcode res; if (data->state.used_interface == Curl_if_easy) { @@ -193,6 +198,7 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) return res; } } +#endif if (data->state.used_interface == Curl_if_easy) return ldap_connecting(conn, done); @@ -209,6 +215,7 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done) int rc, err; char *info = NULL; +#ifdef USE_SSL if (conn->protocol & PROT_SSL) { /* Is the SSL handshake complete yet? */ if (!li->ssldone) { @@ -226,6 +233,7 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done) li->send = conn->send[FIRSTSOCKET]; } } +#endif if (data->state.used_interface == Curl_if_easy) tvp = NULL; /* let ldap_result block indefinitely */ @@ -505,6 +513,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, return ret; } +#ifdef USE_SSL static int ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg) { @@ -577,5 +586,6 @@ static Sockbuf_IO ldapsb_tls = ldapsb_tls_write, ldapsb_tls_close }; +#endif /* USE_SSL */ #endif /* USE_OPENLDAP */ -- cgit v1.2.1 From 89da5324457070cb4a7391c48c6c4f84ed7fe964 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 1 Jun 2010 17:25:03 +0200 Subject: fix ldap related compilation issues --- lib/openldap.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 16bf7b8c8..daba224ed 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -22,7 +22,18 @@ #include "setup.h" -#ifdef USE_OPENLDAP +#if !defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP) + +/* + * Notice that USE_OPENLDAP is only a source code selection switch. When + * libcurl is built with USE_OPENLDAP defined the libcurl source code that + * gets compiled is the code from openldap.c, otherwise the code that gets + * compiled is the code from ldap.c. + * + * When USE_OPENLDAP is defined a recent version of the OpenLDAP library + * might be required for compilation and runtime. In order to use ancient + * OpenLDAP library versions, USE_OPENLDAP shall not be defined. + */ #include "urldata.h" #include @@ -588,4 +599,4 @@ static Sockbuf_IO ldapsb_tls = }; #endif /* USE_SSL */ -#endif /* USE_OPENLDAP */ +#endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */ -- cgit v1.2.1 From 1c4538610b4e69b7a365c9db9421182496eef9bd Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 2 Jun 2010 11:23:30 +0200 Subject: openldap header inclusions fix --- lib/openldap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index daba224ed..05628ab8e 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -35,12 +35,15 @@ * OpenLDAP library versions, USE_OPENLDAP shall not be defined. */ +#include + #include "urldata.h" #include #include "sendf.h" -#include #include "sslgen.h" #include "transfer.h" +#include "curl_ldap.h" +#include "curl_memory.h" #include "curl_base64.h" #define _MPRINTF_REPLACE /* use our functions only */ -- cgit v1.2.1 From c59dba338ea2c71fa0422a8594928d3c1787469e Mon Sep 17 00:00:00 2001 From: Mauro Iorio Date: Sat, 18 Sep 2010 00:03:23 +0200 Subject: LDAP: Support for tunnelling queries through HTTP proxy As of curl-7.21.1 tunnelling ldap queries through HTTP Proxies is not supported. Actually 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=... " This fix 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. --- lib/openldap.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 05628ab8e..445d30167 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -165,6 +165,7 @@ static CURLcode ldap_setup(struct connectdata *conn) 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 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) 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; -- cgit v1.2.1 From fae19aed8de74e6b01544c314358ff702419ec7d Mon Sep 17 00:00:00 2001 From: Tor Arntsen Date: Sat, 18 Sep 2010 14:15:52 +0200 Subject: LDAP: Add missing declaration for 'result' --- lib/openldap.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 445d30167..5996876a9 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -178,6 +178,7 @@ static Sockbuf_IO ldapsb_tls; static CURLcode ldap_connect(struct connectdata *conn, bool *done) { + CURLcode result; ldapconninfo *li = conn->proto.generic; struct SessionHandle *data=conn->data; int rc, proto = LDAP_VERSION3; -- cgit v1.2.1 From 3208757c1af6e3a46bce786430d9dca2ea6f5e76 Mon Sep 17 00:00:00 2001 From: Tor Arntsen Date: Sat, 18 Sep 2010 14:16:49 +0200 Subject: LDAP: Use FALSE instead of bool_false when setting bits.close bool_false is the internal name used in the setup_once.h definition we fall back to for non-C99 non-stdbool systems, it's not the actual name to use in assignments (we use bool_false, bool_true there to avoid global namespace problems, see comment in setup_once.h). The correct C99 value to use is 'false', but let's use FALSE as used elsewhere when assigning to bits.close. FALSE is set equal to 'false' in setup_once.h when possible. This fixes a build problem on C99 targets. --- lib/openldap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 5996876a9..3382c7724 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -165,7 +165,7 @@ static CURLcode ldap_setup(struct connectdata *conn) li = calloc(1, sizeof(ldapconninfo)); li->proto = proto; conn->proto.generic = li; - conn->bits.close = bool_false; + conn->bits.close = FALSE; /* TODO: * - provide option to choose SASL Binds instead of Simple */ -- cgit v1.2.1 From 9de4b2664312f0e956305a3f6180f6c6eee10e06 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 18 Sep 2010 22:50:04 +0200 Subject: LDAP: moved variable declaration to avoid compiler warn If built without HTTP or proxy support it would cause a compiler warning due to the unused variable. I moved the declaration of it into the only scope it is used. --- lib/openldap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 3382c7724..4d5db4a51 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -178,7 +178,6 @@ static Sockbuf_IO ldapsb_tls; static CURLcode ldap_connect(struct connectdata *conn, bool *done) { - CURLcode result; ldapconninfo *li = conn->proto.generic; struct SessionHandle *data=conn->data; int rc, proto = LDAP_VERSION3; @@ -205,6 +204,7 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) /* for LDAP over HTTP proxy */ struct HTTP http_proxy; ldapconninfo *li_save; + CURLcode result; /* BLOCKING */ /* We want "seamless" LDAP operations through HTTP proxy tunnel */ -- cgit v1.2.1 From 6a07e704ca7f815c38bba0dc5277a8d729cfc75b Mon Sep 17 00:00:00 2001 From: Alfred Gebert Date: Fri, 5 Nov 2010 15:53:41 +0100 Subject: LDAP: detect non-binary attributes properly If the query result has a binary attribute, the binary attribute is base64 encoded. But all following non binary attributes are also base64 encoded which is wrong. This is a test (LDAP server is public). curl ldap://x500.bund.de:389/o=Bund,c=DE?userCertificate,certificateSerialNumber?sub ?cn=*Woehleke* --- lib/openldap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 4d5db4a51..ee4915f66 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -499,6 +499,8 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, if (bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7)) binary = 1; + else + binary = 0; for (i=0; bvals[i].bv_val != NULL; i++) { int binval = 0; -- cgit v1.2.1 From d212fe43af25b9d550cf7e84b24374a3ea120808 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Mon, 22 Nov 2010 23:59:59 +0100 Subject: openldap: use remote port in URL passed to ldap_init_fd() ... not the proxy port. It makes no difference unless a proxy is used. --- lib/openldap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index ee4915f66..6b059d10a 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -188,7 +188,7 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) if (conn->protocol & PROT_SSL) *ptr++ = 's'; snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d", - conn->host.name, conn->port); + conn->host.name, conn->remote_port); rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld); if (rc) { -- cgit v1.2.1 From c2ba8ca81f8d753a9ac3fdd94a1fb3ea53b64f84 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 26 Nov 2010 13:59:01 +0100 Subject: s/isspace/ISSPACE --- lib/openldap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 6b059d10a..e9dcfcc71 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -511,14 +511,14 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, if (!binary) { /* check for leading or trailing whitespace */ - if (isspace(bvals[i].bv_val[0]) || - isspace(bvals[i].bv_val[bvals[i].bv_len-1])) { + if (ISSPACE(bvals[i].bv_val[0]) || + ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1])) { binval = 1; } else { /* check for unprintable characters */ unsigned int j; for (j=0; j Date: Fri, 19 Nov 2010 13:43:20 +0100 Subject: url: provide dead_connection flag in Curl_handler::disconnect It helps to prevent a hangup with some FTP servers in case idle session timeout has exceeded. But it may be useful also for other protocols that send any quit message on disconnect. Currently used by FTP, POP3, IMAP and SMTP. --- lib/openldap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index e9dcfcc71..7010da6c2 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -61,7 +61,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done); static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool); static CURLcode ldap_connect(struct connectdata *conn, bool *done); static CURLcode ldap_connecting(struct connectdata *conn, bool *done); -static CURLcode ldap_disconnect(struct connectdata *conn); +static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection); static Curl_recv ldap_recv; @@ -344,9 +344,10 @@ retry: return CURLE_OK; } -static CURLcode ldap_disconnect(struct connectdata *conn) +static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection) { ldapconninfo *li = conn->proto.generic; + (void) dead_connection; if (li) { if (li->ld) { -- cgit v1.2.1 From 8831000bc07de463d277975a3ddfb6a31dcf14b4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 14 Mar 2011 22:22:22 +0100 Subject: protocol handler: added flags field The protocol handler struct got a 'flags' field for special information and characteristics of the given protocol. This now enables us to move away central protocol information such as CLOSEACTION and DUALCHANNEL from single defines in a central place, out to each protocol's definition. It also made us stop abusing the protocol field for other info than the protocol, and we could start cleaning up other protocol-specific things by adding flags bits to set in the handler struct. The "protocol" field connectdata struct was removed as well and the code now refers directly to the conn->handler->protocol field instead. To make things work properly, the code now always store a conn->given pointer that points out the original handler struct so that the code can learn details from the original protocol even if conn->handler is modified along the way - for example when switching to go over a HTTP proxy. --- lib/openldap.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 7010da6c2..386f796e5 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -83,7 +83,8 @@ const struct Curl_handler Curl_handler_ldap = { ZERO_NULL, /* perform_getsock */ ldap_disconnect, /* disconnect */ PORT_LDAP, /* defport */ - PROT_LDAP /* protocol */ + PROT_LDAP, /* protocol */ + PROTOPT_NONE /* flags */ }; #ifdef USE_SSL @@ -105,7 +106,8 @@ const struct Curl_handler Curl_handler_ldaps = { ZERO_NULL, /* perform_getsock */ ldap_disconnect, /* disconnect */ PORT_LDAPS, /* defport */ - PROT_LDAP | PROT_SSL /* protocol */ + PROT_LDAP, /* protocol */ + PROTOPT_SSL /* flags */ }; #endif @@ -185,7 +187,7 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) strcpy(hosturl, "ldap"); ptr = hosturl+4; - if (conn->protocol & PROT_SSL) + if (conn->handler->flags & PROTOPT_SSL) *ptr++ = 's'; snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d", conn->host.name, conn->remote_port); @@ -229,7 +231,7 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) #endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */ #ifdef USE_SSL - if (conn->protocol & PROT_SSL) { + if (conn->handler->flags & PROTOPT_SSL) { CURLcode res; if (data->state.used_interface == Curl_if_easy) { res = Curl_ssl_connect(conn, FIRSTSOCKET); @@ -260,7 +262,7 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done) char *info = NULL; #ifdef USE_SSL - if (conn->protocol & PROT_SSL) { + if (conn->handler->flags & PROTOPT_SSL) { /* Is the SSL handshake complete yet? */ if (!li->ssldone) { CURLcode res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); -- cgit v1.2.1 From 13b64d75589647f8d151e035bd2c5d340a1c37ee Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 14 Mar 2011 22:52:14 +0100 Subject: protocols: use CURLPROTO_ internally The PROT_* set of internal defines for the protocols is no longer used. We now use the same bits internally as we have defined in the public header using the CURLPROTO_ prefix. This is for simplicity and because the PROT_* prefix was already used duplicated internally for a set of KRB4 values. The PROTOPT_* defines were moved up to just below the struct definition within which they are used. --- lib/openldap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 386f796e5..ec723beb2 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -83,7 +83,7 @@ const struct Curl_handler Curl_handler_ldap = { ZERO_NULL, /* perform_getsock */ ldap_disconnect, /* disconnect */ PORT_LDAP, /* defport */ - PROT_LDAP, /* protocol */ + CURLPROTO_LDAP, /* protocol */ PROTOPT_NONE /* flags */ }; @@ -106,7 +106,7 @@ const struct Curl_handler Curl_handler_ldaps = { ZERO_NULL, /* perform_getsock */ ldap_disconnect, /* disconnect */ PORT_LDAPS, /* defport */ - PROT_LDAP, /* protocol */ + CURLPROTO_LDAP, /* protocol */ PROTOPT_SSL /* flags */ }; #endif -- cgit v1.2.1 From b8118dd49589f2ccfc7c3ef4ff4dacf994614333 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 16 Mar 2011 00:16:34 +0100 Subject: ldap_recv: check return code from ldap_get_dn_ber --- lib/openldap.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index ec723beb2..dd008800a 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -465,7 +465,8 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, char *info = NULL; rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0); if (rc) { - failf(data, "LDAP local: search ldap_parse_result %s", ldap_err2string(rc)); + failf(data, "LDAP local: search ldap_parse_result %s", + ldap_err2string(rc)); *err = CURLE_LDAP_SEARCH_FAILED; } else if (code && code != LDAP_SIZELIMIT_EXCEEDED) { failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc), @@ -488,6 +489,12 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, lr->nument++; rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv); + if(rc < 0) { + /* TODO: verify that this is really how this return code should be + handled */ + *err = CURLE_RECV_ERROR; + return -1; + } Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); -- cgit v1.2.1 From 02dbfa21921aded6bba292b99dd224fe450e7254 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 4 Apr 2011 16:24:37 +0200 Subject: http-proxy: move proxy code to http_proxy.c The new http_proxy.* files now host HTTP proxy specific code (500+ lines moved out from http.c), and as a consequence there is a macro introduced for the Curl_proxyCONNECT() function so that code can use it without actually supporting proxy (or HTTP) in builds. --- lib/openldap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index dd008800a..3cb796380 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -6,6 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010, Howard Chu, + * Copyright (C) 2011, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -45,6 +46,7 @@ #include "curl_ldap.h" #include "curl_memory.h" #include "curl_base64.h" +#include "http_proxy.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -201,7 +203,6 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) 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; @@ -228,7 +229,6 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) if(CURLE_OK != result) return result; } -#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */ #ifdef USE_SSL if (conn->handler->flags & PROTOPT_SSL) { -- cgit v1.2.1 From b903186fa0189ff241d756d25d07fdfe9885ae49 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Apr 2011 15:17:42 +0200 Subject: source cleanup: unify look, style and indent levels By the use of a the new lib/checksrc.pl script that checks that our basic source style rules are followed. --- lib/openldap.c | 138 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 73 insertions(+), 65 deletions(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 3cb796380..80dc284ac 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -55,7 +55,8 @@ #ifndef _LDAP_PVT_H extern int ldap_pvt_url_scheme2proto(const char *); -extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, LDAP **ld); +extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, + LDAP **ld); #endif static CURLcode ldap_setup(struct connectdata *conn); @@ -63,7 +64,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done); static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool); static CURLcode ldap_connect(struct connectdata *conn, bool *done); static CURLcode ldap_connecting(struct connectdata *conn, bool *done); -static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection); +static CURLcode ldap_disconnect(struct connectdata *conn, bool dead); static Curl_recv ldap_recv; @@ -152,11 +153,11 @@ static CURLcode ldap_setup(struct connectdata *conn) CURLcode status; rc = ldap_url_parse(data->change.url, &lud); - if (rc != LDAP_URL_SUCCESS) { + if(rc != LDAP_URL_SUCCESS) { const char *msg = "url parsing problem"; status = CURLE_URL_MALFORMAT; - if (rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { - if (rc == LDAP_URL_ERR_MEM) + if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { + if(rc == LDAP_URL_ERR_MEM) status = CURLE_OUT_OF_MEMORY; msg = url_errs[rc]; } @@ -189,13 +190,13 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) strcpy(hosturl, "ldap"); ptr = hosturl+4; - if (conn->handler->flags & PROTOPT_SSL) + if(conn->handler->flags & PROTOPT_SSL) *ptr++ = 's'; snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d", conn->host.name, conn->remote_port); rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld); - if (rc) { + if(rc) { failf(data, "LDAP local: Cannot connect to %s, %s", hosturl, ldap_err2string(rc)); return CURLE_COULDNT_CONNECT; @@ -231,22 +232,23 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) } #ifdef USE_SSL - if (conn->handler->flags & PROTOPT_SSL) { + if(conn->handler->flags & PROTOPT_SSL) { CURLcode res; - if (data->state.used_interface == Curl_if_easy) { + if(data->state.used_interface == Curl_if_easy) { res = Curl_ssl_connect(conn, FIRSTSOCKET); - if (res) + if(res) return res; li->ssldone = TRUE; - } else { + } + else { res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); - if (res) + if(res) return res; } } #endif - if (data->state.used_interface == Curl_if_easy) + if(data->state.used_interface == Curl_if_easy) return ldap_connecting(conn, done); return CURLE_OK; @@ -262,15 +264,16 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done) char *info = NULL; #ifdef USE_SSL - if (conn->handler->flags & PROTOPT_SSL) { + if(conn->handler->flags & PROTOPT_SSL) { /* Is the SSL handshake complete yet? */ - if (!li->ssldone) { - CURLcode res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); - if (res || !li->ssldone) + if(!li->ssldone) { + CURLcode res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, + &li->ssldone); + if(res || !li->ssldone) return res; } /* Have we installed the libcurl SSL handlers into the sockbuf yet? */ - if (!li->sslinst) { + if(!li->sslinst) { Sockbuf *sb; ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn); @@ -281,53 +284,54 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done) } #endif - if (data->state.used_interface == Curl_if_easy) + if(data->state.used_interface == Curl_if_easy) tvp = NULL; /* let ldap_result block indefinitely */ else tvp = &tv; retry: - if (!li->didbind) { + if(!li->didbind) { char *binddn; struct berval passwd; - if (conn->bits.user_passwd) { + if(conn->bits.user_passwd) { binddn = conn->user; passwd.bv_val = conn->passwd; passwd.bv_len = strlen(passwd.bv_val); - } else { + } + else { binddn = NULL; passwd.bv_val = NULL; passwd.bv_len = 0; } rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd, NULL, NULL, &li->msgid); - if (rc) + if(rc) return CURLE_LDAP_CANNOT_BIND; li->didbind = TRUE; - if (tvp) + if(tvp) return CURLE_OK; } rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, tvp, &result); - if (rc < 0) { + if(rc < 0) { failf(data, "LDAP local: bind ldap_result %s", ldap_err2string(rc)); return CURLE_LDAP_CANNOT_BIND; } - if (rc == 0) { + if(rc == 0) { /* timed out */ return CURLE_OK; } rc = ldap_parse_result(li->ld, result, &err, NULL, &info, NULL, NULL, 1); - if (rc) { + if(rc) { failf(data, "LDAP local: bind ldap_parse_result %s", ldap_err2string(rc)); return CURLE_LDAP_CANNOT_BIND; } /* Try to fallback to LDAPv2? */ - if (err == LDAP_PROTOCOL_ERROR) { + if(err == LDAP_PROTOCOL_ERROR) { int proto; ldap_get_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); - if (proto == LDAP_VERSION3) { + if(proto == LDAP_VERSION3) { ldap_memfree(info); proto = LDAP_VERSION2; ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); @@ -336,7 +340,7 @@ retry: } } - if (err) { + if(err) { failf(data, "LDAP remote: bind failed %s %s", ldap_err2string(rc), info ? info : ""); return CURLE_LOGIN_DENIED; @@ -351,8 +355,8 @@ static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection) ldapconninfo *li = conn->proto.generic; (void) dead_connection; - if (li) { - if (li->ld) { + if(li) { + if(li->ld) { ldap_unbind_ext(li->ld, NULL, NULL); li->ld = NULL; } @@ -377,11 +381,11 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done) infof(data, "LDAP local: %s\n", data->change.url); rc = ldap_url_parse(data->change.url, &ludp); - if (rc != LDAP_URL_SUCCESS) { + if(rc != LDAP_URL_SUCCESS) { const char *msg = "url parsing problem"; status = CURLE_URL_MALFORMAT; - if (rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { - if (rc == LDAP_URL_ERR_MEM) + if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { + if(rc == LDAP_URL_ERR_MEM) status = CURLE_OUT_OF_MEMORY; msg = url_errs[rc]; } @@ -393,7 +397,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done) ludp->lud_filter, ludp->lud_attrs, 0, NULL, NULL, NULL, 0, &msgid); ldap_free_urldesc(ludp); - if (rc != LDAP_SUCCESS) { + if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc)); return CURLE_LDAP_SEARCH_FAILED; } @@ -412,9 +416,9 @@ static CURLcode ldap_done(struct connectdata *conn, CURLcode res, (void)res; (void)premature; - if (lr) { + if(lr) { /* if there was a search in progress, abandon it */ - if (lr->msgid) { + if(lr->msgid) { ldapconninfo *li = conn->proto.generic; ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL); lr->msgid = 0; @@ -441,7 +445,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, (void)sockindex; rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &result); - if (rc < 0) { + if(rc < 0) { failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc)); *err = CURLE_RECV_ERROR; return -1; @@ -451,30 +455,32 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, ret = -1; /* timed out */ - if (result == NULL) + if(result == NULL) return ret; - for (ent = ldap_first_message(li->ld, result); ent; + for(ent = ldap_first_message(li->ld, result); ent; ent = ldap_next_message(li->ld, ent)) { struct berval bv, *bvals, **bvp = &bvals; int binary = 0, msgtype; msgtype = ldap_msgtype(ent); - if (msgtype == LDAP_RES_SEARCH_RESULT) { + if(msgtype == LDAP_RES_SEARCH_RESULT) { int code; char *info = NULL; rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0); - if (rc) { + if(rc) { failf(data, "LDAP local: search ldap_parse_result %s", ldap_err2string(rc)); *err = CURLE_LDAP_SEARCH_FAILED; - } else if (code && code != LDAP_SIZELIMIT_EXCEEDED) { + } + else if(code && code != LDAP_SIZELIMIT_EXCEEDED) { failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc), - info ? info : ""); + info ? info : ""); *err = CURLE_LDAP_SEARCH_FAILED; - } else { + } + else { /* successful */ - if (code == LDAP_SIZELIMIT_EXCEEDED) + if(code == LDAP_SIZELIMIT_EXCEEDED) infof(data, "There are more than %d entries\n", lr->nument); data->req.size = data->req.bytecount; *err = CURLE_OK; @@ -483,9 +489,9 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, lr->msgid = 0; ldap_memfree(info); break; - } else if (msgtype != LDAP_RES_SEARCH_ENTRY) { - continue; } + else if(msgtype != LDAP_RES_SEARCH_ENTRY) + continue; lr->nument++; rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv); @@ -500,41 +506,42 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); data->req.bytecount += bv.bv_len + 5; - for (rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp); + for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp); rc == LDAP_SUCCESS; rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) { int i; - if (bv.bv_val == NULL) break; + if(bv.bv_val == NULL) break; - if (bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7)) + if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7)) binary = 1; else binary = 0; - for (i=0; bvals[i].bv_val != NULL; i++) { + for(i=0; bvals[i].bv_val != NULL; i++) { int binval = 0; Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); + Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, + bv.bv_len); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1); data->req.bytecount += bv.bv_len + 2; - if (!binary) { + if(!binary) { /* check for leading or trailing whitespace */ - if (ISSPACE(bvals[i].bv_val[0]) || - ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1])) { + if(ISSPACE(bvals[i].bv_val[0]) || + ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1])) binval = 1; - } else { + else { /* check for unprintable characters */ unsigned int j; - for (j=0; jreq.bytecount += val_b64_sz; } - } else { + } + else { Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1); Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val, bvals[i].bv_len); @@ -596,7 +604,7 @@ static int ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) { (void)arg; - if (opt == LBER_SB_OPT_DATA_READY) { + if(opt == LBER_SB_OPT_DATA_READY) { struct connectdata *conn = sbiod->sbiod_pvt; return Curl_ssl_data_pending(conn, FIRSTSOCKET); } @@ -612,7 +620,7 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) CURLcode err = CURLE_RECV_ERROR; ret = li->recv(conn, FIRSTSOCKET, buf, len, &err); - if (ret < 0 && err == CURLE_AGAIN) { + if(ret < 0 && err == CURLE_AGAIN) { SET_SOCKERRNO(EWOULDBLOCK); } return ret; @@ -627,7 +635,7 @@ ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) CURLcode err = CURLE_SEND_ERROR; ret = li->send(conn, FIRSTSOCKET, buf, len, &err); - if (ret < 0 && err == CURLE_AGAIN) { + if(ret < 0 && err == CURLE_AGAIN) { SET_SOCKERRNO(EWOULDBLOCK); } return ret; -- cgit v1.2.1 From f0612f166a5fa51d09498baa19a327c5cf36941f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 5 May 2011 16:27:03 +0200 Subject: RTSP: convert protocol-specific checks to generic Add a 'readwrite' function to the protocol handler struct and use that for the extra readwrite functionality RTSP needs. --- lib/openldap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 80dc284ac..69523cb37 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -85,6 +85,7 @@ const struct Curl_handler Curl_handler_ldap = { ZERO_NULL, /* doing_getsock */ ZERO_NULL, /* perform_getsock */ ldap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ PORT_LDAP, /* defport */ CURLPROTO_LDAP, /* protocol */ PROTOPT_NONE /* flags */ @@ -108,6 +109,7 @@ const struct Curl_handler Curl_handler_ldaps = { ZERO_NULL, /* doing_getsock */ ZERO_NULL, /* perform_getsock */ ldap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ PORT_LDAPS, /* defport */ CURLPROTO_LDAP, /* protocol */ PROTOPT_SSL /* flags */ -- cgit v1.2.1 From fd00b382b2d33ef90c6f5c840a32b66c8ceb1662 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 24 Aug 2011 08:07:36 +0200 Subject: base64: fix Curl_base64_encode and Curl_base64_decode interfaces Previous interfaces for these libcurl internal functions did not allow to tell apart a legitimate zero size result from an error condition. These functions now return a CURLcode indicating function success or otherwise specific error. Output size is returned using a pointer argument. All usage of these two functions, and others closely related, has been adapted to the new interfaces. Relative error and OOM handling adapted or added where missing. Unit test 1302 also adapted. --- lib/openldap.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 69523cb37..070892524 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -544,12 +544,21 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, } } if(binary || binval) { - char *val_b64; + char *val_b64 = NULL; + size_t val_b64_sz = 0; /* Binary value, encode to base64. */ - size_t val_b64_sz = Curl_base64_encode(data, - bvals[i].bv_val, - bvals[i].bv_len, - &val_b64); + CURLcode error = Curl_base64_encode(data, + bvals[i].bv_val, + bvals[i].bv_len, + &val_b64, + &val_b64_sz); + if(error) { + ber_memfree(bvals); + ber_free(ber, 0); + ldap_msgfree(result); + *err = error; + return -1; + } Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2); data->req.bytecount += 2; if(val_b64_sz > 0) { -- cgit v1.2.1 From d7934b8bd49114cbb54f7401742f7fb088e2f796 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 21 Oct 2011 23:36:54 +0200 Subject: curl_multi_fdset: correct fdset with FTP PORT use After a PORT has been issued, and the multi handle would switch to the CURLM_STATE_DO_MORE state (which is unique for FTP), libcurl would return the wrong fdset to wait for when curl_multi_fdset() is called. The code would blindly assume that it was waiting for a connect of the second connection, while that isn't true immediately after the PORT command. Also, the function multi.c:domore_getsock() was highly FTP-centric and therefore ugly to keep in protocol-agnostic code. I solved this problem by introducing a new function pointer in the Curl_handler struct called domore_getsock() which is only called during the DOMORE state for protocols that set that pointer. The new ftp.c:ftp_domore_getsock() function now returns fdset info about the control connection's command/response handling while such a state is in use, and goes over to waiting for a writable second connection first once the commands are done. The original problem could be seen by running test 525 and checking the time stamps in the FTP server log. I can verify that this fix at least fixes this problem. Bug: http://curl.haxx.se/mail/lib-2011-10/0250.html Reported by: Gokhan Sengun --- lib/openldap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 070892524..e5a3369a1 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -83,6 +83,7 @@ const struct Curl_handler Curl_handler_ldap = { ZERO_NULL, /* doing */ ZERO_NULL, /* proto_getsock */ ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* perform_getsock */ ldap_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ @@ -107,6 +108,7 @@ const struct Curl_handler Curl_handler_ldaps = { ZERO_NULL, /* doing */ ZERO_NULL, /* proto_getsock */ ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* perform_getsock */ ldap_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ -- cgit v1.2.1 From 2cafb0e97c288d2e942a50e964e1604c692871db Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 18 Jan 2012 16:06:29 +0100 Subject: OpenLDAP: fix LDAP connection phase memory leak bug: http://curl.haxx.se/bug/view.cgi?id=3474308 --- lib/openldap.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index e5a3369a1..a26ff2e15 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010, Howard Chu, - * Copyright (C) 2011, Daniel Stenberg, , et al. + * Copyright (C) 2011 - 2012, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -336,7 +336,10 @@ retry: int proto; ldap_get_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); if(proto == LDAP_VERSION3) { - ldap_memfree(info); + if(info) { + ldap_memfree(info); + info = NULL; + } proto = LDAP_VERSION2; ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); li->didbind = FALSE; @@ -347,8 +350,13 @@ retry: if(err) { failf(data, "LDAP remote: bind failed %s %s", ldap_err2string(rc), info ? info : ""); + if(info) + ldap_memfree(info); return CURLE_LOGIN_DENIED; } + + if(info) + ldap_memfree(info); conn->recv[FIRSTSOCKET] = ldap_recv; *done = TRUE; return CURLE_OK; -- cgit v1.2.1 From 41b02378342322aa8e264260057502f4d7493239 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 8 Mar 2012 23:31:38 +0100 Subject: CONNECT: made generically not per-protocol Curl_protocol_connect() now does the tunneling through the HTTP proxy if requested instead of letting each protocol specific connection function do it. --- lib/openldap.c | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index a26ff2e15..3a6c7e341 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -208,33 +208,6 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done) ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { - /* for LDAP over HTTP proxy */ - struct HTTP http_proxy; - ldapconninfo *li_save; - CURLcode result; - - /* 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; - } - #ifdef USE_SSL if(conn->handler->flags & PROTOPT_SSL) { CURLcode res; -- cgit v1.2.1 From 2764bf2c5b4076f25e76dd8e64bf52f226ee7c5f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 9 Mar 2012 00:05:24 +0100 Subject: includes: remove inclusion of unused file http_proxy.h --- lib/openldap.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 3a6c7e341..3886d0889 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -46,7 +46,6 @@ #include "curl_ldap.h" #include "curl_memory.h" #include "curl_base64.h" -#include "http_proxy.h" #define _MPRINTF_REPLACE /* use our functions only */ #include -- cgit v1.2.1 From e3f5e04cf09b59a70866c0a08d5310e57492cf73 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 8 Jun 2012 20:56:22 +0200 Subject: openldap: OOM fixes when calloc fails, return error! (Detected by Fortify) Reported by: Robert B. Harris --- lib/openldap.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/openldap.c') diff --git a/lib/openldap.c b/lib/openldap.c index 3886d0889..9ccfa7fae 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -171,6 +171,8 @@ static CURLcode ldap_setup(struct connectdata *conn) ldap_free_urldesc(lud); li = calloc(1, sizeof(ldapconninfo)); + if(!li) + return CURLE_OUT_OF_MEMORY; li->proto = proto; conn->proto.generic = li; conn->bits.close = FALSE; @@ -386,6 +388,8 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done) return CURLE_LDAP_SEARCH_FAILED; } lr = calloc(1,sizeof(ldapreqinfo)); + if(!lr) + return CURLE_OUT_OF_MEMORY; lr->msgid = msgid; data->state.proto.generic = lr; Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); -- cgit v1.2.1