diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2002-04-18 00:49:30 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2002-04-18 00:49:30 +0000 |
commit | 3001c6f5135796bf49346dd969e8445342d2251b (patch) | |
tree | d710aec0cc173e2b9a67ff56f56f47a1f3b32bc0 /gnu/usr.sbin/sendmail/libsm/ldap.c | |
parent | 7bc62683b217ae48e11df50f14c39728b723a832 (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.c | 524 |
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); |