diff options
author | Patrick Monnerat <patrick@monnerat.net> | 2021-12-06 11:13:28 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2021-12-11 12:54:50 +0100 |
commit | b40e4c0d4715f3c30ea1032589847ef4e431642e (patch) | |
tree | a4199e60c0d45bf20ca81d39259b1cdfba6a5862 | |
parent | 254f7bd78a1ab248329def2cbbbc983e7f6d2495 (diff) | |
download | curl-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.c | 271 |
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 |