summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Monnerat <patrick@monnerat.net>2021-12-06 11:13:28 +0100
committerDaniel Stenberg <daniel@haxx.se>2021-12-11 12:54:50 +0100
commitb40e4c0d4715f3c30ea1032589847ef4e431642e (patch)
treea4199e60c0d45bf20ca81d39259b1cdfba6a5862
parent254f7bd78a1ab248329def2cbbbc983e7f6d2495 (diff)
downloadcurl-b40e4c0d4715f3c30ea1032589847ef4e431642e.tar.gz
openldap: process search query response messages one by one
Upon receiving large result sets, this reduces memory consumption and allows starting to output results while the transfer is still in progress. Closes #8101
-rw-r--r--lib/openldap.c271
1 files changed, 114 insertions, 157 deletions
diff --git a/lib/openldap.c b/lib/openldap.c
index 003d0f8e5..23bc38bc0 100644
--- a/lib/openldap.c
+++ b/lib/openldap.c
@@ -620,95 +620,85 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
struct ldapreqinfo *lr = data->req.p.ldap;
- int rc, ret;
+ int rc;
LDAPMessage *msg = NULL;
- LDAPMessage *ent;
BerElement *ber = NULL;
struct timeval tv = {0, 1};
+ struct berval bv, *bvals;
+ int binary = 0;
+ CURLcode result = CURLE_AGAIN;
+ int code;
+ char *info = NULL;
(void)len;
(void)buf;
(void)sockindex;
- rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &msg);
+ rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_ONE, &tv, &msg);
if(rc < 0) {
failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc));
- *err = CURLE_RECV_ERROR;
- return -1;
+ result = CURLE_RECV_ERROR;
}
- *err = CURLE_AGAIN;
- ret = -1;
+ *err = result;
- /* timed out */
+ /* error or timed out */
if(!msg)
- return ret;
-
- for(ent = ldap_first_message(li->ld, msg); ent;
- ent = ldap_next_message(li->ld, ent)) {
- struct berval bv, *bvals;
- int binary = 0, msgtype;
- CURLcode writeerr;
-
- 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", lr->nument);
- data->req.size = data->req.bytecount;
- *err = CURLE_OK;
- ret = 0;
- }
- lr->msgid = 0;
- ldap_memfree(info);
+ return -1;
+
+ result = CURLE_OK;
+
+ switch(ldap_msgtype(msg)) {
+ case LDAP_RES_SEARCH_RESULT:
+ lr->msgid = 0;
+ rc = ldap_parse_result(li->ld, msg, &code, NULL, &info, NULL, NULL, 0);
+ if(rc) {
+ failf(data, "LDAP local: search ldap_parse_result %s",
+ ldap_err2string(rc));
+ result = CURLE_LDAP_SEARCH_FAILED;
break;
}
- else if(msgtype != LDAP_RES_SEARCH_ENTRY)
- continue;
+ switch(code) {
+ case LDAP_SIZELIMIT_EXCEEDED:
+ infof(data, "There are more than %d entries", lr->nument);
+ /* FALLTHROUGH */
+ case LDAP_SUCCESS:
+ data->req.size = data->req.bytecount;
+ break;
+ default:
+ failf(data, "LDAP remote: search failed %s %s", ldap_err2string(code),
+ info ? info : "");
+ result = CURLE_LDAP_SEARCH_FAILED;
+ break;
+ }
+ if(info)
+ ldap_memfree(info);
+ break;
+ case LDAP_RES_SEARCH_ENTRY:
lr->nument++;
- rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
+ rc = ldap_get_dn_ber(li->ld, msg, &ber, &bv);
if(rc < 0) {
- *err = CURLE_RECV_ERROR;
- return -1;
- }
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
- if(writeerr) {
- *err = writeerr;
- return -1;
+ result = CURLE_RECV_ERROR;
+ break;
}
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
+ if(result)
+ break;
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
- bv.bv_len);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ bv.bv_len);
+ if(result)
+ break;
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
+ if(result)
+ break;
data->req.bytecount += bv.bv_len + 5;
- for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals);
+ for(rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals);
rc == LDAP_SUCCESS;
- rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) {
+ rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals)) {
int i;
if(!bv.bv_val)
@@ -720,57 +710,45 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
binary = 0;
if(!bvals) {
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
- bv.bv_len);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":\n", 2);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
+ if(result)
+ break;
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ bv.bv_len);
+ if(result)
+ break;
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":\n", 2);
+ if(result)
+ break;
data->req.bytecount += bv.bv_len + 3;
continue;
}
for(i = 0; bvals[i].bv_val != NULL; i++) {
int binval = 0;
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
-
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
- bv.bv_len);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
-
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":", 1);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
+ if(result)
+ break;
+
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ bv.bv_len);
+ if(result)
+ break;
+
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":", 1);
+ if(result)
+ break;
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]))
+ ISSPACE(bvals[i].bv_val[bvals[i].bv_len - 1]))
binval = 1;
else {
/* check for unprintable characters */
unsigned int j;
- for(j = 0; j<bvals[i].bv_len; j++)
+ for(j = 0; j < bvals[i].bv_len; j++)
if(!ISPRINT(bvals[i].bv_val[j])) {
binval = 1;
break;
@@ -780,80 +758,59 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
if(binary || binval) {
char *val_b64 = NULL;
size_t val_b64_sz = 0;
+
/* Binary value, encode to base64. */
- 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(msg);
- *err = error;
- return -1;
- }
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY,
+ result = Curl_base64_encode(data, bvals[i].bv_val, bvals[i].bv_len,
+ &val_b64, &val_b64_sz);
+ if(!result)
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)": ", 2);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
-
- data->req.bytecount += 2;
- if(val_b64_sz > 0) {
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, val_b64,
- val_b64_sz);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
- free(val_b64);
- data->req.bytecount += val_b64_sz;
- }
+ if(!result && val_b64_sz > 0)
+ result = Curl_client_write(data, CLIENTWRITE_BODY, val_b64,
+ val_b64_sz);
+ free(val_b64);
+ data->req.bytecount += val_b64_sz + 2;
}
else {
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)" ", 1);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)" ", 1);
+ if(result)
+ break;
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, bvals[i].bv_val,
- bvals[i].bv_len);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ result = Curl_client_write(data, CLIENTWRITE_BODY, bvals[i].bv_val,
+ bvals[i].bv_len);
+ if(result)
+ break;
data->req.bytecount += bvals[i].bv_len + 1;
}
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
+ if(result)
+ break;
data->req.bytecount++;
}
+
ber_memfree(bvals);
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+
+ if(!result)
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
+ if(result)
+ break;
data->req.bytecount++;
}
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
- data->req.bytecount++;
+
ber_free(ber, 0);
+
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
+ if(!result)
+ result = CURLE_AGAIN;
+ data->req.bytecount++;
+ break;
}
+
ldap_msgfree(msg);
- return ret;
+ *err = result;
+ return result? -1: 0;
}
#ifdef USE_SSL