I did this
I am using curl_easy_setopt and curl_easy_perform to query a jpegPhoto attribute from an LDAP server. My code is equivalent to this CLI command:
curl "ldap://ldap.example.com/uid=jdoe,ou=people,dc=example,dc=com?jpegPhoto?base"
On Linux with the OpenLDAP backend, this query returns an LDIF text response, with the jpegPhoto value as base64.
DN: uid=jdoe,ou=people,dc=example,dc=com
jpegPhoto:: /9j/4AAQSkZJRgABAQEASABIAAD//gBbUGh<more base64 here>
On Windows with the WinLDAP backend, it returns the attribute value as raw binary data.
DN: uid=jdoe,ou=people,dc=example,dc=com
jpegPhoto: <raw binary data here>
The above is what the callback I set with CURLOPT_WRITEFUNCTION receives. When using ther CLI instead, it stops with a warning as it detects raw binary.
DN: uid=jdoe,ou=people,dc=example,dc=com
jpegPhoto: Warning: Binary output can mess up your terminal. Use "--output -" to tell curl to output it to your terminal anyway,
Warning: or consider "--output <FILE>" to save to a file.
LDIF is a pure ASCII format, that uses spaces, tabs and newlines as delimiters. Curl chose to return the response as LDIF, but with the WinLDAP backend this LDIF response is malformed due to the injection of raw binary data. It makes the response unparseable.
Looking at the code, I see that lib/openldap.c is the OpenLDAP backend, and lib/ldap.c is the WinLDAP backend, and their logic to encode the values as base64 diverge.
|
binary = bv.bv_len > 7 && |
|
curl_strnequal(bv.bv_val + bv.bv_len - 7, ";binary", 7); |
|
|
|
for(i = 0; bvals[i].bv_val != NULL; i++) { |
|
bool binval = FALSE; |
|
|
|
result = client_write(data, STRCONST("\t"), bv.bv_val, bv.bv_len, |
|
STRCONST(":")); |
|
if(result) |
|
break; |
|
|
|
if(!binary) { |
|
/* check for leading or trailing whitespace */ |
|
if(bvals[i].bv_len && |
|
(ISBLANK(bvals[i].bv_val[0]) || |
|
ISBLANK(bvals[i].bv_val[bvals[i].bv_len - 1]))) |
|
binval = TRUE; |
|
else { |
|
/* check for unprintable characters */ |
|
unsigned int j; |
|
for(j = 0; j < bvals[i].bv_len; j++) |
|
if(!ISPRINT(bvals[i].bv_val[j])) { |
|
binval = TRUE; |
|
break; |
|
} |
|
} |
|
} |
|
if(binary || binval) { |
|
char *val_b64 = NULL; |
|
size_t val_b64_sz = 0; |
|
|
|
/* Binary value, encode to base64. */ |
|
if(bvals[i].bv_len) |
|
result = curlx_base64_encode((uint8_t *)bvals[i].bv_val, |
|
bvals[i].bv_len, |
|
&val_b64, &val_b64_sz); |
|
if((attr_len > 7) && |
|
curl_strequal(";binary", attr + (attr_len - 7))) { |
|
/* Binary attribute, encode to base64. */ |
|
if(vals[i]->bv_len) { |
|
result = curlx_base64_encode((uint8_t *)vals[i]->bv_val, |
|
vals[i]->bv_len, |
|
&val_b64, &val_b64_sz); |
Both check for the ;binary option, but only the OpenLDAP backend checks for leading and trailing whitespaces and for unprintable characters.
The ldap.c code should use the same logic than openldap.c (and possibly using shared code).
I don't know any workaround. I tried adding the ;binary option to the attribute in the query to force the base64 encoding, but it returns no result. It seems this option is reserved for certificate attributes only.
I expected the following
I expect LDAP responses to be in a valid LDIF format.
curl/libcurl version
curl 8.19.0
operating system
Windows 11 Pro
I did this
I am using
curl_easy_setoptandcurl_easy_performto query a jpegPhoto attribute from an LDAP server. My code is equivalent to this CLI command:curl "ldap://ldap.example.com/uid=jdoe,ou=people,dc=example,dc=com?jpegPhoto?base"On Linux with the OpenLDAP backend, this query returns an LDIF text response, with the jpegPhoto value as base64.
On Windows with the WinLDAP backend, it returns the attribute value as raw binary data.
The above is what the callback I set with
CURLOPT_WRITEFUNCTIONreceives. When using ther CLI instead, it stops with a warning as it detects raw binary.LDIF is a pure ASCII format, that uses spaces, tabs and newlines as delimiters. Curl chose to return the response as LDIF, but with the WinLDAP backend this LDIF response is malformed due to the injection of raw binary data. It makes the response unparseable.
Looking at the code, I see that
lib/openldap.cis the OpenLDAP backend, andlib/ldap.cis the WinLDAP backend, and their logic to encode the values as base64 diverge.curl/lib/openldap.c
Lines 1177 to 1212 in feb609f
curl/lib/ldap.c
Lines 516 to 522 in feb609f
Both check for the ;binary option, but only the OpenLDAP backend checks for leading and trailing whitespaces and for unprintable characters.
The ldap.c code should use the same logic than openldap.c (and possibly using shared code).
I don't know any workaround. I tried adding the ;binary option to the attribute in the query to force the base64 encoding, but it returns no result. It seems this option is reserved for certificate attributes only.
I expected the following
I expect LDAP responses to be in a valid LDIF format.
curl/libcurl version
curl 8.19.0
operating system
Windows 11 Pro