diff options
-rw-r--r-- | docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3 | 14 | ||||
-rw-r--r-- | lib/openldap.c | 179 |
2 files changed, 107 insertions, 86 deletions
diff --git a/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3 b/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3 index 66b9f3719..628b438bd 100644 --- a/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3 +++ b/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3 @@ -30,15 +30,14 @@ CURLINFO_RESPONSE_CODE \- get the last response code CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RESPONSE_CODE, long *codep); .fi .SH DESCRIPTION -Pass a pointer to a long to receive the last received HTTP, FTP or SMTP -response code. This option was previously known as CURLINFO_HTTP_CODE in -libcurl 7.10.7 and earlier. The stored value will be zero if no server -response code has been received. Note that a proxy's CONNECT response should +Pass a pointer to a long to receive the last received HTTP, FTP, SMTP or +LDAP (openldap only) response code. This option was previously known as +CURLINFO_HTTP_CODE in libcurl 7.10.7 and earlier. +The stored value will be zero if no server response code has been received. +Note that a proxy's CONNECT response should be read with \fICURLINFO_HTTP_CONNECTCODE(3)\fP and not this. - -Support for SMTP responses added in 7.25.0. .SH PROTOCOLS -HTTP, FTP and SMTP +HTTP, FTP, SMTP and LDAP .SH EXAMPLE .nf CURL *curl = curl_easy_init(); @@ -55,6 +54,7 @@ if(curl) { .fi .SH AVAILABILITY Added in 7.10.8. CURLINFO_HTTP_CODE was added in 7.4.1. +Support for SMTP responses added in 7.25.0, for OpenLDAP in 7.81.0. .SH RETURN VALUE Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not. .SH "SEE ALSO" diff --git a/lib/openldap.c b/lib/openldap.c index f5483f478..0ffb6a36a 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -154,20 +154,6 @@ const struct Curl_handler Curl_handler_ldaps = { }; #endif -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" -}; - struct ldapconninfo { LDAP *ld; /* Openldap connection handle. */ Curl_recv *recv; /* For stacking SSL handler */ @@ -231,40 +217,66 @@ static CURLcode oldap_map_error(int rc, CURLcode result) return result; } -static CURLcode oldap_setup_connection(struct Curl_easy *data, - struct connectdata *conn) +static CURLcode oldap_url_parse(struct Curl_easy *data, LDAPURLDesc **ludp) { - struct ldapconninfo *li; - LDAPURLDesc *lud; - int rc, proto; - CURLcode status; + CURLcode result = CURLE_OK; + int rc = LDAP_URL_ERR_BADURL; + static const char * const 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" + }; - rc = ldap_url_parse(data->state.url, &lud); + *ludp = NULL; + if(!data->state.up.user && !data->state.up.password && + !data->state.up.options) + rc = ldap_url_parse(data->state.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; + + result = rc == LDAP_URL_ERR_MEM? CURLE_OUT_OF_MEMORY: CURLE_URL_MALFORMAT; + rc -= LDAP_URL_SUCCESS; + if((size_t) rc < sizeof(url_errs) / sizeof(url_errs[0])) msg = url_errs[rc]; - } failf(data, "LDAP local: %s", msg); - return status; } - proto = ldap_pvt_url_scheme2proto(lud->lud_scheme); - ldap_free_urldesc(lud); + return result; +} - li = calloc(1, sizeof(struct ldapconninfo)); - if(!li) - return CURLE_OUT_OF_MEMORY; - li->proto = proto; - conn->proto.ldapc = li; - connkeep(conn, "OpenLDAP default"); +static CURLcode oldap_setup_connection(struct Curl_easy *data, + struct connectdata *conn) +{ + CURLcode result; + LDAPURLDesc *lud; + struct ldapconninfo *li; - /* Clear the TLS upgraded flag */ - conn->bits.tls_upgraded = FALSE; + /* Early URL syntax check. */ + result = oldap_url_parse(data, &lud); + ldap_free_urldesc(lud); - return CURLE_OK; + if(!result) { + li = calloc(1, sizeof(struct ldapconninfo)); + if(!li) + result = CURLE_OUT_OF_MEMORY; + else { + li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme); + conn->proto.ldapc = li; + connkeep(conn, "OpenLDAP default"); + + /* Clear the TLS upgraded flag */ + conn->bits.tls_upgraded = FALSE; + } + } + + return result; } /* Starts LDAP simple bind. */ @@ -350,29 +362,31 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) { struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; - int rc, proto = LDAP_VERSION3; - char hosturl[1024]; - char *ptr; + static const int version = LDAP_VERSION3; + int rc; + char *hosturl; #ifdef CURL_OPENLDAP_DEBUG static int do_trace = -1; #endif (void)done; - strcpy(hosturl, "ldap"); - ptr = hosturl + 4; - if(conn->handler->flags & PROTOPT_SSL) - *ptr++ = 's'; - msnprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d", - conn->host.name, conn->remote_port); + hosturl = aprintf("ldap%s://%s:%d", + conn->handler->flags & PROTOPT_SSL? "s": "", + conn->host.name, conn->remote_port); + if(!hosturl) + return CURLE_OUT_OF_MEMORY; 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)); + free(hosturl); return CURLE_COULDNT_CONNECT; } + free(hosturl); + #ifdef CURL_OPENLDAP_DEBUG if(do_trace < 0) { const char *env = getenv("CURL_OPENLDAP_TRACE"); @@ -382,7 +396,11 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) ldap_set_option(li->ld, LDAP_OPT_DEBUG_LEVEL, &do_trace); #endif - ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); + /* Try version 3 first. */ + ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &version); + + /* Do not chase referrals. */ + ldap_set_option(li->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); #ifdef USE_SSL if(conn->handler->flags & PROTOPT_SSL) @@ -453,6 +471,10 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done) rc = ldap_parse_result(li->ld, msg, &code, NULL, NULL, NULL, NULL, 0); if(rc) code = rc; + else { + /* store the latest code for later retrieval */ + data->info.httpcode = code; + } /* If protocol version 3 is not supported, fallback to version 2. */ if(code == LDAP_PROTOCOL_ERROR && li->state != OLDAP_BINDV2 @@ -551,44 +573,40 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done) struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; struct ldapreqinfo *lr; - CURLcode status = CURLE_OK; - int rc = 0; - LDAPURLDesc *ludp = NULL; + CURLcode result; + int rc; + LDAPURLDesc *lud; int msgid; connkeep(conn, "OpenLDAP do"); infof(data, "LDAP local: %s", data->state.url); - rc = ldap_url_parse(data->state.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]; + result = oldap_url_parse(data, &lud); + if(!result) { + rc = ldap_search_ext(li->ld, lud->lud_dn, lud->lud_scope, + lud->lud_filter, lud->lud_attrs, 0, + NULL, NULL, NULL, 0, &msgid); + ldap_free_urldesc(lud); + if(rc != LDAP_SUCCESS) { + failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc)); + result = CURLE_LDAP_SEARCH_FAILED; + } + else { + lr = calloc(1, sizeof(struct ldapreqinfo)); + if(!lr) { + ldap_abandon_ext(li->ld, msgid, NULL, NULL); + result = CURLE_OUT_OF_MEMORY; + } + else { + lr->msgid = msgid; + data->req.p.ldap = lr; + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + *done = TRUE; + } } - failf(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(struct ldapreqinfo)); - if(!lr) - return CURLE_OUT_OF_MEMORY; - lr->msgid = msgid; - data->req.p.ldap = lr; - Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); - *done = TRUE; - return CURLE_OK; + return result; } static CURLcode oldap_done(struct Curl_easy *data, CURLcode res, @@ -653,7 +671,7 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf, int rc; LDAPMessage *msg = NULL; BerElement *ber = NULL; - struct timeval tv = {0, 1}; + struct timeval tv = {0, 0}; struct berval bv, *bvals; int binary = 0; CURLcode result = CURLE_AGAIN; @@ -689,6 +707,9 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf, break; } + /* store the latest code for later retrieval */ + data->info.httpcode = code; + switch(code) { case LDAP_SIZELIMIT_EXCEEDED: infof(data, "There are more than %d entries", lr->nument); |