From: Patrick Monnerat Date: Mon, 6 Dec 2021 10:13:28 +0000 (+0100) Subject: openldap: process search query response messages one by one X-Git-Tag: curl-7_81_0~73 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b40e4c0d4715f3c30ea1032589847ef4e431642e;p=thirdparty%2Fcurl.git 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 --- diff --git a/lib/openldap.c b/lib/openldap.c index 003d0f8e59..23bc38bc05 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; jreq.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