* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2015 */
+/* Copyright (c) University of Cambridge 1995 - 2016 */
/* See the file NOTICE for conditions of use and distribution. */
/* Many thanks to Stuart Lynne for contributing the original code for this
-driver. Further contibutions from Michael Haardt, Brian Candler, Barry
+driver. Further contributions from Michael Haardt, Brian Candler, Barry
Pederson, Peter Savitch and Christian Kellner. Particular thanks to Brian for
researching how to handle the different kinds of error. */
uschar *error2 = NULL; /* error message from the server */
uschar *matched = NULL; /* partially matched DN */
-int attr_count = 0;
+int attrs_requested = 0;
int error_yield = DEFER;
int msgid;
int rc, ldap_rc, ldap_parse_rc;
/* Count the attributes; we need this later to tell us how to format results */
for (attrp = USS ludp->lud_attrs; attrp != NULL && *attrp != NULL; attrp++)
- attr_count++;
+ attrs_requested++;
/* See if we can find a cached connection to this host. The port is not
relevant for ldapi. The host name pointer is set to NULL if no host was given
{
DEBUG(D_lookup) debug_printf("%sbinding with user=%s password=%s\n",
(lcp->bound)? "re-" : "", user, password);
- if (eldap_start_tls && !lcp->is_start_tls_called)
+ if (eldap_start_tls && !lcp->is_start_tls_called && !ldapi)
{
#if defined(LDAP_OPT_X_TLS) && !defined(LDAP_LIB_SOLARIS)
/* The Oracle LDAP libraries (LDAP_LIB_TYPE=SOLARIS) don't support this.
LDAP_RES_SEARCH_ENTRY)
{
LDAPMessage *e;
+ int valuecount; /* We can see an attr spread across several
+ entries. If B is derived from A and we request
+ A and the directory contains both, A and B,
+ then we get two entries, one for A and one for B.
+ Here we just count the values per entry */
- DEBUG(D_lookup) debug_printf("ldap_result loop\n");
+ DEBUG(D_lookup) debug_printf("LDAP result loop\n");
- for(e = ldap_first_entry(lcp->ld, result);
+ for(e = ldap_first_entry(lcp->ld, result), valuecount = 0;
e != NULL;
e = ldap_next_entry(lcp->ld, e))
{
/* Results for multiple entries values are separated by newlines. */
- if (data != NULL) data = string_cat(data, &size, &ptr, US"\n", 1);
+ if (data != NULL) data = string_catn(data, &size, &ptr, US"\n", 1);
/* Get the DN from the last result. */
{ /* condition, because of the else */
if (new_dn != NULL) /* below, that's for the first only */
{
- data = string_cat(data, &size, &ptr, new_dn, Ustrlen(new_dn));
+ data = string_cat(data, &size, &ptr, new_dn);
data[ptr] = 0;
attribute_found = TRUE;
}
/* Otherwise, loop through the entry, grabbing attribute values. If there's
only one attribute being retrieved, no attribute name is given, and the
- result is not quoted. Multiple values are separated by (comma, space).
+ result is not quoted. Multiple values are separated by (comma).
If more than one attribute is being retrieved, the data is given as a
- sequence of name=value pairs, with the value always in quotes. If there are
- multiple values, they are given within the quotes, comma separated. */
+ sequence of name=value pairs, separated by (space), with the value always in quotes.
+ If there are multiple values, they are given within the quotes, comma separated. */
else for (attr = US ldap_first_attribute(lcp->ld, e, &ber);
attr != NULL;
attr = US ldap_next_attribute(lcp->ld, e, ber))
{
+ DEBUG(D_lookup) debug_printf("LDAP attr loop\n");
+
+ /* In case of attrs_requested == 1 we just count the values, in all other cases
+ (0, >1) we count the values per attribute */
+ if (attrs_requested != 1) valuecount = 0;
+
if (attr[0] != 0)
{
/* Get array of values for this attribute. */
if ((firstval = values = USS ldap_get_values(lcp->ld, e, CS attr))
!= NULL)
{
- if (attr_count != 1)
+
+ if (attrs_requested != 1)
{
if (insert_space)
- data = string_cat(data, &size, &ptr, US" ", 1);
+ data = string_catn(data, &size, &ptr, US" ", 1);
else
insert_space = TRUE;
- data = string_cat(data, &size, &ptr, attr, Ustrlen(attr));
- data = string_cat(data, &size, &ptr, US"=\"", 2);
+ data = string_cat(data, &size, &ptr, attr);
+ data = string_catn(data, &size, &ptr, US"=\"", 2);
}
while (*values != NULL)
{
uschar *value = *values;
int len = Ustrlen(value);
+ ++valuecount;
+
+ DEBUG(D_lookup) debug_printf("LDAP value loop %s:%s\n", attr, value);
- DEBUG(D_lookup) debug_printf("LDAP attr loop %s:%s\n", attr, value);
+ /* In case we requested one attribute only but got several times
+ into that attr loop, we need to append the additional values.
+ (This may happen if you derive attributeTypes B and C from A and
+ then query for A.) In all other cases we detect the different
+ attribute and append only every non first value. */
- /* In case we requested one attribute only but got
- * several times into that attr loop, we need to append
- * the additional values. (This may happen if you derive
- * attributeTypes B and C from A and then query for A.)
- * In all other cases we detect the different attribute
- * and append only every non first value. */
- if ((attr_count == 1 && data) || (values != firstval))
- data = string_cat(data, &size, &ptr, US",", 1);
+ if (data && valuecount > 1)
+ data = string_catn(data, &size, &ptr, US",", 1);
/* For multiple attributes, the data is in quotes. We must escape
internal quotes, backslashes, newlines, and must double commas. */
- if (attr_count != 1)
+ if (attrs_requested != 1)
{
int j;
for (j = 0; j < len; j++)
{
if (value[j] == '\n')
- data = string_cat(data, &size, &ptr, US"\\n", 2);
+ data = string_catn(data, &size, &ptr, US"\\n", 2);
else if (value[j] == ',')
- data = string_cat(data, &size, &ptr, US",,", 2);
+ data = string_catn(data, &size, &ptr, US",,", 2);
else
{
if (value[j] == '\"' || value[j] == '\\')
- data = string_cat(data, &size, &ptr, US"\\", 1);
- data = string_cat(data, &size, &ptr, value+j, 1);
+ data = string_catn(data, &size, &ptr, US"\\", 1);
+ data = string_catn(data, &size, &ptr, value+j, 1);
}
}
}
{
int j;
for (j = 0; j < len; j++)
- {
if (value[j] == ',')
- data = string_cat(data, &size, &ptr, US",,", 2);
+ data = string_catn(data, &size, &ptr, US",,", 2);
else
- data = string_cat(data, &size, &ptr, value+j, 1);
- }
+ data = string_catn(data, &size, &ptr, value+j, 1);
}
/* Closing quote at the end of the data for a named attribute. */
- if (attr_count != 1)
- data = string_cat(data, &size, &ptr, US"\"", 1);
+ if (attrs_requested != 1)
+ data = string_catn(data, &size, &ptr, US"\"", 1);
/* Free the values */