summaryrefslogtreecommitdiff
path: root/gnu/usr.sbin/sendmail/libsm/ldap.c
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2002-04-18 00:49:30 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2002-04-18 00:49:30 +0000
commit3001c6f5135796bf49346dd969e8445342d2251b (patch)
treed710aec0cc173e2b9a67ff56f56f47a1f3b32bc0 /gnu/usr.sbin/sendmail/libsm/ldap.c
parent7bc62683b217ae48e11df50f14c39728b723a832 (diff)
update to sendmail 8.12.3
Diffstat (limited to 'gnu/usr.sbin/sendmail/libsm/ldap.c')
-rw-r--r--gnu/usr.sbin/sendmail/libsm/ldap.c524
1 files changed, 386 insertions, 138 deletions
diff --git a/gnu/usr.sbin/sendmail/libsm/ldap.c b/gnu/usr.sbin/sendmail/libsm/ldap.c
index f1eaa76d2ae..c5c82554472 100644
--- a/gnu/usr.sbin/sendmail/libsm/ldap.c
+++ b/gnu/usr.sbin/sendmail/libsm/ldap.c
@@ -8,7 +8,7 @@
*/
#include <sm/gen.h>
-SM_RCSID("@(#)$Sendmail: ldap.c,v 1.18 2002/01/11 22:06:51 gshapiro Exp $")
+SM_RCSID("@(#)$Sendmail: ldap.c,v 1.44 2002/02/22 21:54:02 gshapiro Exp $")
#if LDAPMAP
# include <sys/types.h>
@@ -24,6 +24,9 @@ SM_RCSID("@(#)$Sendmail: ldap.c,v 1.18 2002/01/11 22:06:51 gshapiro Exp $")
# include <sm/errstring.h>
# include <sm/ldap.h>
# include <sm/string.h>
+# ifdef EX_OK
+# undef EX_OK /* for SVr4.2 SMP */
+# endif /* EX_OK */
# include <sm/sysexits.h>
SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap",
@@ -49,8 +52,14 @@ sm_ldap_clear(lmap)
if (lmap == NULL)
return;
- lmap->ldap_host = NULL;
+ lmap->ldap_target = NULL;
lmap->ldap_port = LDAP_PORT;
+#if _FFR_LDAP_URI
+ lmap->ldap_uri = false;
+#endif /* _FFR_LDAP_URI */
+# if _FFR_LDAP_SETVERSION
+ lmap->ldap_version = 0;
+# endif /* _FFR_LDAP_SETVERSION */
lmap->ldap_deref = LDAP_DEREF_NEVER;
lmap->ldap_timelimit = LDAP_NO_LIMIT;
lmap->ldap_sizelimit = LDAP_NO_LIMIT;
@@ -72,8 +81,8 @@ sm_ldap_clear(lmap)
lmap->ldap_filter = NULL;
lmap->ldap_attr[0] = NULL;
#if _FFR_LDAP_RECURSION
- lmap->ldap_attr_type[0] = LDAPMAP_ATTR_NORMAL;
- lmap->ldap_attr_final[0] = NULL;
+ lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE;
+ lmap->ldap_attr_needobjclass[0] = NULL;
#endif /* _FFR_LDAP_RECURSION */
lmap->ldap_res = NULL;
lmap->ldap_next = NULL;
@@ -132,11 +141,16 @@ sm_ldap_start(name, lmap)
if (sm_debug_active(&SmLDAPTrace, 9))
sm_dprintf("ldapmap_start(%s, %d)\n",
- lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host,
+ lmap->ldap_target == NULL ? "localhost" : lmap->ldap_target,
lmap->ldap_port);
# if USE_LDAP_INIT
- ld = ldap_init(lmap->ldap_host, lmap->ldap_port);
+# if _FFR_LDAP_URI
+ if (lmap->ldap_uri)
+ errno = ldap_initialize(&ld, lmap->ldap_target);
+ else
+# endif /* _FFR_LDAP_URI */
+ ld = ldap_init(lmap->ldap_target, lmap->ldap_port);
save_errno = errno;
# else /* USE_LDAP_INIT */
/*
@@ -146,7 +160,7 @@ sm_ldap_start(name, lmap)
*/
SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec);
- ld = ldap_open(lmap->ldap_host, lmap->ldap_port);
+ ld = ldap_open(lmap->ldap_target, lmap->ldap_port);
save_errno = errno;
/* clear the event if it has not sprung */
@@ -297,8 +311,8 @@ sm_ldap_search(lmap, key)
sm_dprintf("ldap search filter=%s\n", filter);
lmap->ldap_res = NULL;
- msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, lmap->ldap_scope,
- filter,
+ msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base,
+ lmap->ldap_scope, filter,
(lmap->ldap_attr[0] == NULL ? NULL :
lmap->ldap_attr),
lmap->ldap_attrsonly);
@@ -307,6 +321,66 @@ sm_ldap_search(lmap, key)
# if _FFR_LDAP_RECURSION
/*
+** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a
+** particular objectClass
+**
+** Parameters:
+** lmap -- pointer to SM_LDAP_STRUCT in use
+** entry -- current LDAP entry struct
+** ocvalue -- particular objectclass in question.
+** may be of form (fee|foo|fum) meaning
+** any entry can be part of either fee,
+** foo or fum objectclass
+**
+** Returns:
+** true if item has that objectClass
+*/
+
+static bool
+sm_ldap_has_objectclass(lmap, entry, ocvalue)
+ SM_LDAP_STRUCT *lmap;
+ LDAPMessage *entry;
+ char *ocvalue;
+{
+ char **vals = NULL;
+ int i;
+
+ if (ocvalue == NULL)
+ return false;
+
+ vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass");
+ if (vals == NULL)
+ return false;
+
+ for (i = 0; vals[i] != NULL; i++)
+ {
+ char *p;
+ char *q;
+
+ p = q = ocvalue;
+ while (*p != '\0')
+ {
+ while (*p != '\0' && *p != '|')
+ p++;
+
+ if ((p - q) == strlen(vals[i]) &&
+ sm_strncasecmp(vals[i], q, p - q) == 0)
+ {
+ ldap_value_free(vals);
+ return true;
+ }
+
+ while (*p == '|')
+ p++;
+ q = p;
+ }
+ }
+
+ ldap_value_free(vals);
+ return false;
+}
+
+/*
** SM_LDAP_RESULTS -- return results from an LDAP lookup in result
**
** Parameters:
@@ -322,7 +396,7 @@ sm_ldap_search(lmap, key)
** status (sysexit)
*/
-# define LDAPMAP_ERROR_CLEANUP() \
+# define SM_LDAP_ERROR_CLEANUP() \
{ \
if (lmap->ldap_res != NULL) \
{ \
@@ -332,58 +406,138 @@ sm_ldap_search(lmap, key)
(void) ldap_abandon(lmap->ldap_ld, msgid); \
}
-static int
-ldapmap_add_recurse(top, item, type, rpool)
+static SM_LDAP_RECURSE_ENTRY *
+sm_ldap_add_recurse(top, item, type, rpool)
SM_LDAP_RECURSE_LIST **top;
char *item;
int type;
SM_RPOOL_T *rpool;
{
- SM_LDAP_RECURSE_LIST *p;
- SM_LDAP_RECURSE_LIST *last;
+ int n;
+ int m;
+ int p;
+ int insertat;
+ int moveb;
+ int oldsizeb;
+ int rc;
+ SM_LDAP_RECURSE_ENTRY *newe;
+ SM_LDAP_RECURSE_ENTRY **olddata;
+
+ /*
+ ** This code will maintain a list of
+ ** SM_LDAP_RECURSE_ENTRY structures
+ ** in ascending order.
+ */
+
+ if (*top == NULL)
+ {
+ /* Allocate an initial SM_LDAP_RECURSE_LIST struct */
+ *top = sm_rpool_malloc_x(rpool, sizeof **top);
+ (*top)->lr_cnt = 0;
+ (*top)->lr_size = 0;
+ (*top)->lr_data = NULL;
+ }
- last = NULL;
- for (p = *top; p != NULL; p = p->lr_next)
+ if ((*top)->lr_cnt >= (*top)->lr_size)
{
- if (strcasecmp(item, p->lr_search) == 0 &&
- type == p->lr_type)
+ /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */
+ olddata = (*top)->lr_data;
+ if ((*top)->lr_size == 0)
{
- /* already on list */
- return 1;
+ oldsizeb = 0;
+ (*top)->lr_size = 256;
}
- last = p;
+ else
+ {
+ oldsizeb = (*top)->lr_size * sizeof *((*top)->lr_data);
+ (*top)->lr_size *= 2;
+ }
+ (*top)->lr_data = sm_rpool_malloc_x(rpool,
+ (*top)->lr_size * sizeof *((*top)->lr_data));
+ if (oldsizeb > 0)
+ memcpy((*top)->lr_data, olddata, oldsizeb);
}
- /* not on list, add it */
- p = sm_rpool_malloc_x(rpool, sizeof *p);
- p->lr_search = sm_rpool_strdup_x(rpool, item);
- p->lr_type = type;
- p->lr_next = NULL;
- if (last == NULL)
- *top = p;
+ /*
+ ** Binary search/insert item:type into list.
+ ** Return current entry pointer if already exists.
+ */
+
+ n = 0;
+ m = (*top)->lr_cnt - 1;
+ if (m < 0)
+ insertat = 0;
else
- last->lr_next = p;
- return 0;
+ insertat = -1;
+
+ while (insertat == -1)
+ {
+ p = (m + n) / 2;
+
+ rc = sm_strcasecmp(item, (*top)->lr_data[p]->lr_search);
+ if (rc == 0)
+ rc = type - (*top)->lr_data[p]->lr_type;
+
+ if (rc < 0)
+ m = p - 1;
+ else if (rc > 0)
+ n = p + 1;
+ else
+ return (*top)->lr_data[p];
+
+ if (m == -1)
+ insertat = 0;
+ else if (n >= (*top)->lr_cnt)
+ insertat = (*top)->lr_cnt;
+ else if (m < n)
+ insertat = m + 1;
+ }
+
+ /*
+ ** Not found in list, make room
+ ** at insert point and add it.
+ */
+
+ newe = sm_rpool_malloc_x(rpool, sizeof *newe);
+ if (newe != NULL)
+ {
+ moveb = ((*top)->lr_cnt - insertat) * sizeof *((*top)->lr_data);
+ if (moveb > 0)
+ memmove(&((*top)->lr_data[insertat + 1]),
+ &((*top)->lr_data[insertat]),
+ moveb);
+
+ newe->lr_search = sm_rpool_strdup_x(rpool, item);
+ newe->lr_type = type;
+ newe->lr_done = false;
+
+ ((*top)->lr_data)[insertat] = newe;
+ (*top)->lr_cnt++;
+ }
+ return newe;
}
int
-sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
+sm_ldap_results(lmap, msgid, flags, delim, rpool, result,
+ resultln, resultsz, recurse)
SM_LDAP_STRUCT *lmap;
int msgid;
int flags;
- char delim;
+ int delim;
SM_RPOOL_T *rpool;
char **result;
+ int *resultln;
+ int *resultsz;
SM_LDAP_RECURSE_LIST *recurse;
{
bool toplevel;
int i;
- int entries = 0;
int statp;
int vsize;
int ret;
int save_errno;
char *p;
+ SM_LDAP_RECURSE_ENTRY *rl;
/* Are we the top top level of the search? */
toplevel = (recurse == NULL);
@@ -397,20 +551,8 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
{
LDAPMessage *entry;
- if (bitset(SM_LDAP_SINGLEMATCH, flags))
- {
- entries += ldap_count_entries(lmap->ldap_ld,
- lmap->ldap_res);
- if (entries > 1)
- {
- LDAPMAP_ERROR_CLEANUP();
- errno = ENOENT;
- return EX_NOTFOUND;
- }
- }
-
/* If we don't want multiple values and we have one, break */
- if (delim == '\0' && *result != NULL)
+ if ((char) delim == '\0' && *result != NULL)
break;
/* Cycle through all entries */
@@ -438,23 +580,24 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
{
save_errno = sm_ldap_geterrno(lmap->ldap_ld);
save_errno += E_LDAPBASE;
- LDAPMAP_ERROR_CLEANUP();
+ SM_LDAP_ERROR_CLEANUP();
errno = save_errno;
return EX_OSERR;
}
- switch (ldapmap_add_recurse(&recurse, dn,
- LDAPMAP_ATTR_NORMAL,
- rpool))
+ rl = sm_ldap_add_recurse(&recurse, dn,
+ SM_LDAP_ATTR_DN,
+ rpool);
+
+ if (rl == NULL)
{
- case -1:
- /* error adding */
ldap_memfree(dn);
- LDAPMAP_ERROR_CLEANUP();
+ SM_LDAP_ERROR_CLEANUP();
errno = ENOMEM;
return EX_OSERR;
-
- case 1:
+ }
+ else if (rl->lr_done)
+ {
/* already on list, skip it */
ldap_memfree(dn);
continue;
@@ -479,27 +622,54 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
{
char *tmp, *vp_tmp;
int type;
+ char *needobjclass = NULL;
+ type = SM_LDAP_ATTR_NONE;
for (i = 0; lmap->ldap_attr[i] != NULL; i++)
{
if (sm_strcasecmp(lmap->ldap_attr[i],
attr) == 0)
{
type = lmap->ldap_attr_type[i];
+ needobjclass = lmap->ldap_attr_needobjclass[i];
break;
}
}
- if (lmap->ldap_attr[i] == NULL)
+
+ if (bitset(SM_LDAP_USE_ALLATTR, flags) &&
+ type == SM_LDAP_ATTR_NONE)
+ {
+ /* URL lookups specify attrs to use */
+ type = SM_LDAP_ATTR_NORMAL;
+ needobjclass = NULL;
+ }
+
+ if (type == SM_LDAP_ATTR_NONE)
{
/* attribute not requested */
-# if USING_NETSCAPE_LDAP
ldap_memfree(attr);
-# endif /* USING_NETSCAPE_LDAP */
- LDAPMAP_ERROR_CLEANUP();
+ SM_LDAP_ERROR_CLEANUP();
errno = EFAULT;
return EX_SOFTWARE;
}
+ /*
+ ** For recursion on a particular attribute,
+ ** we may need to see if this entry is
+ ** part of a particular objectclass.
+ ** Also, ignore objectClass attribute.
+ ** Otherwise we just ignore this attribute.
+ */
+
+ if (type == SM_LDAP_ATTR_OBJCLASS ||
+ (needobjclass != NULL &&
+ !sm_ldap_has_objectclass(lmap, entry,
+ needobjclass)))
+ {
+ ldap_memfree(attr);
+ continue;
+ }
+
if (lmap->ldap_attrsonly == LDAPMAP_FALSE)
{
vals = ldap_get_values(lmap->ldap_ld,
@@ -510,18 +680,14 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
save_errno = sm_ldap_geterrno(lmap->ldap_ld);
if (save_errno == LDAP_SUCCESS)
{
-# if USING_NETSCAPE_LDAP
ldap_memfree(attr);
-# endif /* USING_NETSCAPE_LDAP */
continue;
}
/* Must be an error */
save_errno += E_LDAPBASE;
-# if USING_NETSCAPE_LDAP
ldap_memfree(attr);
-# endif /* USING_NETSCAPE_LDAP */
- LDAPMAP_ERROR_CLEANUP();
+ SM_LDAP_ERROR_CLEANUP();
errno = save_errno;
return EX_TEMPFAIL;
}
@@ -548,10 +714,7 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
{
if (lmap->ldap_attrsonly == LDAPMAP_FALSE)
ldap_value_free(vals);
-
-# if USING_NETSCAPE_LDAP
ldap_memfree(attr);
-# endif /* USING_NETSCAPE_LDAP */
continue;
}
@@ -560,24 +723,36 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
** return first found.
*/
- if (delim == '\0')
+ if ((char) delim == '\0')
{
+ if (*result != NULL)
+ {
+ /* already have a value */
+ break;
+ }
+
+ if (bitset(SM_LDAP_SINGLEMATCH,
+ flags) &&
+ *result != NULL)
+ {
+ /* only wanted one match */
+ SM_LDAP_ERROR_CLEANUP();
+ errno = ENOENT;
+ return EX_NOTFOUND;
+ }
+
if (lmap->ldap_attrsonly == LDAPMAP_TRUE)
{
*result = sm_rpool_strdup_x(rpool,
attr);
-# if USING_NETSCAPE_LDAP
ldap_memfree(attr);
-# endif /* USING_NETSCAPE_LDAP */
break;
}
if (vals[0] == NULL)
{
ldap_value_free(vals);
-# if USING_NETSCAPE_LDAP
ldap_memfree(attr);
-# endif /* USING_NETSCAPE_LDAP */
continue;
}
@@ -596,9 +771,7 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
sm_strlcpy(*result, vals[0],
vsize);
ldap_value_free(vals);
-# if USING_NETSCAPE_LDAP
ldap_memfree(attr);
-# endif /* USING_NETSCAPE_LDAP */
break;
}
@@ -610,94 +783,137 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
attr);
else
{
+ if (bitset(SM_LDAP_SINGLEMATCH,
+ flags) &&
+ *result != NULL)
+ {
+ /* only wanted one match */
+ SM_LDAP_ERROR_CLEANUP();
+ errno = ENOENT;
+ return EX_NOTFOUND;
+ }
+
vsize = strlen(*result) +
strlen(attr) + 2;
tmp = sm_rpool_malloc_x(rpool,
vsize);
(void) sm_snprintf(tmp,
vsize, "%s%c%s",
- *result, delim,
+ *result, (char) delim,
attr);
*result = tmp;
}
-# if USING_NETSCAPE_LDAP
ldap_memfree(attr);
-# endif /* USING_NETSCAPE_LDAP */
continue;
}
/*
- ** If there is more than one,
- ** munge then into a map_coldelim
- ** separated string
+ ** If there is more than one, munge then
+ ** into a map_coldelim separated string.
+ ** If we are recursing we may have an entry
+ ** with no 'normal' values to put in the
+ ** string.
+ ** This is not an error.
*/
+ if (type == SM_LDAP_ATTR_NORMAL &&
+ bitset(SM_LDAP_SINGLEMATCH, flags) &&
+ *result != NULL)
+ {
+ /* only wanted one match */
+ SM_LDAP_ERROR_CLEANUP();
+ errno = ENOENT;
+ return EX_NOTFOUND;
+ }
+
vsize = 0;
for (i = 0; vals[i] != NULL; i++)
{
- if (type == LDAPMAP_ATTR_DN ||
- type == LDAPMAP_ATTR_FILTER ||
- type == LDAPMAP_ATTR_URL)
+ if (type == SM_LDAP_ATTR_DN ||
+ type == SM_LDAP_ATTR_FILTER ||
+ type == SM_LDAP_ATTR_URL)
{
- if (ldapmap_add_recurse(&recurse,
+ /* add to recursion */
+ if (sm_ldap_add_recurse(&recurse,
vals[i],
- type) < 0)
+ type,
+ rpool) == NULL)
{
- LDAPMAP_ERROR_CLEANUP();
+ SM_LDAP_ERROR_CLEANUP();
errno = ENOMEM;
return EX_OSERR;
}
- }
- if (type != LDAPMAP_ATTR_NORMAL)
- {
-# if USING_NETSCAPE_LDAP
- ldap_memfree(attr);
-# endif /* USING_NETSCAPE_LDAP */
continue;
}
+
vsize += strlen(vals[i]) + 1;
if (lmap->ldap_attrsep != '\0')
vsize += strlen(attr) + 1;
}
- vp_tmp = sm_rpool_malloc_x(rpool, vsize);
- *vp_tmp = '\0';
- p = vp_tmp;
- for (i = 0; vals[i] != NULL; i++)
+ /*
+ ** Create/Append to string any normal
+ ** attribute values. Otherwise, just free
+ ** memory and move on to the next
+ ** attribute in this entry.
+ */
+
+ if (type == SM_LDAP_ATTR_NORMAL && vsize > 0)
{
- if (lmap->ldap_attrsep != '\0')
+ char *pe;
+
+ /* Grow result string if needed */
+ if ((*resultln + vsize) >= *resultsz)
{
- p += sm_strlcpy(p, attr,
- vsize - (p - vp_tmp));
- *p++ = lmap->ldap_attrsep;
+ while ((*resultln + vsize) >= *resultsz)
+ {
+ if (*resultsz == 0)
+ *resultsz = 1024;
+ else
+ *resultsz *= 2;
+ }
+
+ vp_tmp = sm_rpool_malloc_x(rpool, *resultsz);
+ *vp_tmp = '\0';
+
+ if (*result != NULL)
+ sm_strlcpy(vp_tmp,
+ *result,
+ *resultsz);
+ *result = vp_tmp;
}
- p += sm_strlcpy(p, vals[i],
- vsize - (p - vp_tmp));
- if (p >= vp_tmp + vsize)
+
+ p = *result + *resultln;
+ pe = *result + *resultsz;
+
+ for (i = 0; vals[i] != NULL; i++)
{
- /* Internal error: buffer too small for LDAP values */
- LDAPMAP_ERROR_CLEANUP();
- errno = ENOMEM;
- return EX_OSERR;
+ if (*resultln > 0)
+ *p++ = (char) delim;
+
+ if (lmap->ldap_attrsep != '\0')
+ {
+ p += sm_strlcpy(p, attr,
+ pe - p);
+ if (p < pe)
+ *p++ = lmap->ldap_attrsep;
+ }
+
+ p += sm_strlcpy(p, vals[i],
+ pe - p);
+ *resultln = p - (*result);
+ if (p >= pe)
+ {
+ /* Internal error: buffer too small for LDAP values */
+ SM_LDAP_ERROR_CLEANUP();
+ errno = ENOMEM;
+ return EX_OSERR;
+ }
}
- if (vals[i + 1] != NULL)
- *p++ = delim;
}
ldap_value_free(vals);
-# if USING_NETSCAPE_LDAP
ldap_memfree(attr);
-# endif /* USING_NETSCAPE_LDAP */
- if (*result == NULL)
- {
- *result = vp_tmp;
- continue;
- }
- vsize = strlen(*result) + strlen(vp_tmp) + 2;
- tmp = sm_rpool_malloc_x(rpool, vsize);
- (void) sm_snprintf(tmp, vsize, "%s%c%s",
- *result, delim, vp_tmp);
- *result = tmp;
}
save_errno = sm_ldap_geterrno(lmap->ldap_ld);
@@ -715,13 +931,16 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
{
/* Must be an error */
save_errno += E_LDAPBASE;
- LDAPMAP_ERROR_CLEANUP();
+ SM_LDAP_ERROR_CLEANUP();
errno = save_errno;
return EX_TEMPFAIL;
}
+ /* mark this DN as done */
+ rl->lr_done = true;
+
/* We don't want multiple values and we have one */
- if (delim == '\0' && *result != NULL)
+ if ((char) delim == '\0' && *result != NULL)
break;
}
save_errno = sm_ldap_geterrno(lmap->ldap_ld);
@@ -730,7 +949,7 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
{
/* Must be an error */
save_errno += E_LDAPBASE;
- LDAPMAP_ERROR_CLEANUP();
+ SM_LDAP_ERROR_CLEANUP();
errno = save_errno;
return EX_TEMPFAIL;
}
@@ -754,13 +973,18 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
#endif /* LDAP_SERVER_DOWN */
case LDAP_TIMEOUT:
case LDAP_UNAVAILABLE:
- /* server disappeared, try reopen on next search */
+
+ /*
+ ** server disappeared,
+ ** try reopen on next search
+ */
+
statp = EX_RESTART;
break;
}
save_errno += E_LDAPBASE;
}
- LDAPMAP_ERROR_CLEANUP();
+ SM_LDAP_ERROR_CLEANUP();
errno = save_errno;
return statp;
}
@@ -773,7 +997,7 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
if (toplevel)
{
- SM_LDAP_RECURSE_LIST *rl;
+ int rlidx;
/*
** Spin through the built-up recurse list at the top
@@ -784,42 +1008,50 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
** will be expanded by the top level.
*/
- for (rl = recurse; rl != NULL; rl = rl->lr_next)
+ for (rlidx = 0; recurse != NULL && rlidx < recurse->lr_cnt; rlidx++)
{
+ int newflags;
int sid;
int status;
- if (rl->lr_type == LDAPMAP_ATTR_NORMAL)
+ rl = recurse->lr_data[rlidx];
+
+ newflags = flags;
+ if (rl->lr_done)
{
/* already expanded */
continue;
}
- else if (rl->lr_type == LDAPMAP_ATTR_DN)
+
+ if (rl->lr_type == SM_LDAP_ATTR_DN)
{
/* do DN search */
sid = ldap_search(lmap->ldap_ld,
rl->lr_search,
lmap->ldap_scope,
"(objectClass=*)",
- lmap->ldap_attr_final,
+ (lmap->ldap_attr[0] == NULL ?
+ NULL : lmap->ldap_attr),
lmap->ldap_attrsonly);
}
- else if (rl->lr_type == LDAPMAP_ATTR_FILTER)
+ else if (rl->lr_type == SM_LDAP_ATTR_FILTER)
{
/* do new search */
sid = ldap_search(lmap->ldap_ld,
lmap->ldap_base,
lmap->ldap_scope,
rl->lr_search,
- lmap->ldap_attr_final,
+ (lmap->ldap_attr[0] == NULL ?
+ NULL : lmap->ldap_attr),
lmap->ldap_attrsonly);
}
- else if (rl->lr_type == LDAPMAP_ATTR_URL)
+ else if (rl->lr_type == SM_LDAP_ATTR_URL)
{
/* do new URL search */
sid = ldap_url_search(lmap->ldap_ld,
rl->lr_search,
lmap->ldap_attrsonly);
+ newflags |= SM_LDAP_USE_ALLATTR;
}
else
{
@@ -840,7 +1072,12 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
#endif /* LDAP_SERVER_DOWN */
case LDAP_TIMEOUT:
case LDAP_UNAVAILABLE:
- /* server disappeared, try reopen on next search */
+
+ /*
+ ** server disappeared,
+ ** try reopen on next search
+ */
+
statp = EX_RESTART;
break;
}
@@ -848,8 +1085,9 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
return statp;
}
- status = sm_ldap_results(lmap, sid, flags, delim,
- rpool, result, recurse);
+ status = sm_ldap_results(lmap, sid, newflags, delim,
+ rpool, result, resultln,
+ resultsz, recurse);
save_errno = errno;
if (status != EX_OK && status != EX_NOTFOUND)
{
@@ -858,7 +1096,10 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse)
}
/* Mark as done */
- rl->lr_type = LDAPMAP_ATTR_NORMAL;
+ rl->lr_done = true;
+
+ /* Reset rlidx as new items may have been added */
+ rlidx = -1;
}
}
return statp;
@@ -907,6 +1148,13 @@ sm_ldap_setopts(ld, lmap)
SM_LDAP_STRUCT *lmap;
{
# if USE_LDAP_SET_OPTION
+# if _FFR_LDAP_SETVERSION
+ if (lmap->ldap_version != 0)
+ {
+ ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
+ &lmap->ldap_version);
+ }
+# endif /* _FFR_LDAP_SETVERSION */
ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref);
if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options))
ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON);