xref: /freebsd/contrib/sendmail/libsm/ldap.c (revision ffb836234b94e17739bac88bfd7f51f5ae49e3bc)
140266059SGregory Neil Shapiro /*
2ffb83623SGregory Neil Shapiro  * Copyright (c) 2001-2007 Sendmail, Inc. and its suppliers.
340266059SGregory Neil Shapiro  *      All rights reserved.
440266059SGregory Neil Shapiro  *
540266059SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
640266059SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
740266059SGregory Neil Shapiro  * the sendmail distribution.
840266059SGregory Neil Shapiro  */
940266059SGregory Neil Shapiro 
10d0cef73dSGregory Neil Shapiro /* some "deprecated" calls are used, e.g., ldap_get_values() */
11d0cef73dSGregory Neil Shapiro #define LDAP_DEPRECATED	1
12d0cef73dSGregory Neil Shapiro 
1340266059SGregory Neil Shapiro #include <sm/gen.h>
14ffb83623SGregory Neil Shapiro SM_RCSID("@(#)$Id: ldap.c,v 1.80 2007/10/12 00:19:44 ca Exp $")
1540266059SGregory Neil Shapiro 
1640266059SGregory Neil Shapiro #if LDAPMAP
1740266059SGregory Neil Shapiro # include <sys/types.h>
1840266059SGregory Neil Shapiro # include <errno.h>
1940266059SGregory Neil Shapiro # include <setjmp.h>
2040266059SGregory Neil Shapiro # include <stdlib.h>
2140266059SGregory Neil Shapiro # include <unistd.h>
2240266059SGregory Neil Shapiro 
2340266059SGregory Neil Shapiro # include <sm/bitops.h>
2440266059SGregory Neil Shapiro # include <sm/clock.h>
2540266059SGregory Neil Shapiro # include <sm/conf.h>
2640266059SGregory Neil Shapiro # include <sm/debug.h>
2740266059SGregory Neil Shapiro # include <sm/errstring.h>
2840266059SGregory Neil Shapiro # include <sm/ldap.h>
2940266059SGregory Neil Shapiro # include <sm/string.h>
30605302a5SGregory Neil Shapiro #  ifdef EX_OK
31605302a5SGregory Neil Shapiro #   undef EX_OK			/* for SVr4.2 SMP */
32605302a5SGregory Neil Shapiro #  endif /* EX_OK */
3340266059SGregory Neil Shapiro # include <sm/sysexits.h>
3440266059SGregory Neil Shapiro 
3540266059SGregory Neil Shapiro SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap",
3640266059SGregory Neil Shapiro 	"@(#)$Debug: sm_trace_ldap - trace LDAP operations $");
3740266059SGregory Neil Shapiro 
3840266059SGregory Neil Shapiro static void	ldaptimeout __P((int));
39b6bacd31SGregory Neil Shapiro static bool	sm_ldap_has_objectclass __P((SM_LDAP_STRUCT *, LDAPMessage *, char *));
40b6bacd31SGregory Neil Shapiro static SM_LDAP_RECURSE_ENTRY *sm_ldap_add_recurse __P((SM_LDAP_RECURSE_LIST **, char *, int, SM_RPOOL_T *));
4140266059SGregory Neil Shapiro 
4240266059SGregory Neil Shapiro /*
4340266059SGregory Neil Shapiro **  SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT
4440266059SGregory Neil Shapiro **
4540266059SGregory Neil Shapiro **	Parameters:
4640266059SGregory Neil Shapiro **		lmap -- pointer to SM_LDAP_STRUCT to clear
4740266059SGregory Neil Shapiro **
4840266059SGregory Neil Shapiro **	Returns:
4940266059SGregory Neil Shapiro **		None.
5040266059SGregory Neil Shapiro **
5140266059SGregory Neil Shapiro */
5240266059SGregory Neil Shapiro 
534e4196cbSGregory Neil Shapiro #if _FFR_LDAP_VERSION
544e4196cbSGregory Neil Shapiro # if defined(LDAP_VERSION_MAX) && _FFR_LDAP_VERSION > LDAP_VERSION_MAX
554e4196cbSGregory Neil Shapiro     ERROR FFR_LDAP_VERSION > _LDAP_VERSION_MAX
564e4196cbSGregory Neil Shapiro # endif /* defined(LDAP_VERSION_MAX) && _FFR_LDAP_VERSION > LDAP_VERSION_MAX */
574e4196cbSGregory Neil Shapiro # if defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN
584e4196cbSGregory Neil Shapiro     ERROR FFR_LDAP_VERSION < _LDAP_VERSION_MIN
594e4196cbSGregory Neil Shapiro # endif /* defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN */
604e4196cbSGregory Neil Shapiro # define SM_LDAP_VERSION_DEFAULT	_FFR_LDAP_VERSION
614e4196cbSGregory Neil Shapiro #else /* _FFR_LDAP_VERSION */
624e4196cbSGregory Neil Shapiro # define SM_LDAP_VERSION_DEFAULT	0
634e4196cbSGregory Neil Shapiro #endif /* _FFR_LDAP_VERSION */
644e4196cbSGregory Neil Shapiro 
6540266059SGregory Neil Shapiro void
6640266059SGregory Neil Shapiro sm_ldap_clear(lmap)
6740266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
6840266059SGregory Neil Shapiro {
6940266059SGregory Neil Shapiro 	if (lmap == NULL)
7040266059SGregory Neil Shapiro 		return;
7140266059SGregory Neil Shapiro 
72e92d3f3fSGregory Neil Shapiro 	lmap->ldap_host = NULL;
7340266059SGregory Neil Shapiro 	lmap->ldap_port = LDAP_PORT;
74e92d3f3fSGregory Neil Shapiro 	lmap->ldap_uri = NULL;
754e4196cbSGregory Neil Shapiro 	lmap->ldap_version = SM_LDAP_VERSION_DEFAULT;
7640266059SGregory Neil Shapiro 	lmap->ldap_deref = LDAP_DEREF_NEVER;
7740266059SGregory Neil Shapiro 	lmap->ldap_timelimit = LDAP_NO_LIMIT;
7840266059SGregory Neil Shapiro 	lmap->ldap_sizelimit = LDAP_NO_LIMIT;
7940266059SGregory Neil Shapiro # ifdef LDAP_REFERRALS
8040266059SGregory Neil Shapiro 	lmap->ldap_options = LDAP_OPT_REFERRALS;
8140266059SGregory Neil Shapiro # else /* LDAP_REFERRALS */
8240266059SGregory Neil Shapiro 	lmap->ldap_options = 0;
8340266059SGregory Neil Shapiro # endif /* LDAP_REFERRALS */
8440266059SGregory Neil Shapiro 	lmap->ldap_attrsep = '\0';
8540266059SGregory Neil Shapiro 	lmap->ldap_binddn = NULL;
8640266059SGregory Neil Shapiro 	lmap->ldap_secret = NULL;
8740266059SGregory Neil Shapiro 	lmap->ldap_method = LDAP_AUTH_SIMPLE;
8840266059SGregory Neil Shapiro 	lmap->ldap_base = NULL;
8940266059SGregory Neil Shapiro 	lmap->ldap_scope = LDAP_SCOPE_SUBTREE;
9040266059SGregory Neil Shapiro 	lmap->ldap_attrsonly = LDAPMAP_FALSE;
9140266059SGregory Neil Shapiro 	lmap->ldap_timeout.tv_sec = 0;
9240266059SGregory Neil Shapiro 	lmap->ldap_timeout.tv_usec = 0;
9340266059SGregory Neil Shapiro 	lmap->ldap_ld = NULL;
9440266059SGregory Neil Shapiro 	lmap->ldap_filter = NULL;
9540266059SGregory Neil Shapiro 	lmap->ldap_attr[0] = NULL;
96605302a5SGregory Neil Shapiro 	lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE;
97605302a5SGregory Neil Shapiro 	lmap->ldap_attr_needobjclass[0] = NULL;
9840266059SGregory Neil Shapiro 	lmap->ldap_res = NULL;
9940266059SGregory Neil Shapiro 	lmap->ldap_next = NULL;
10040266059SGregory Neil Shapiro 	lmap->ldap_pid = 0;
101d0cef73dSGregory Neil Shapiro 	lmap->ldap_multi_args = false;
10240266059SGregory Neil Shapiro }
10340266059SGregory Neil Shapiro 
10440266059SGregory Neil Shapiro /*
10540266059SGregory Neil Shapiro **  SM_LDAP_START -- actually connect to an LDAP server
10640266059SGregory Neil Shapiro **
10740266059SGregory Neil Shapiro **	Parameters:
10840266059SGregory Neil Shapiro **		name -- name of map for debug output.
10940266059SGregory Neil Shapiro **		lmap -- the LDAP map being opened.
11040266059SGregory Neil Shapiro **
11140266059SGregory Neil Shapiro **	Returns:
11240266059SGregory Neil Shapiro **		true if connection is successful, false otherwise.
11340266059SGregory Neil Shapiro **
11440266059SGregory Neil Shapiro **	Side Effects:
11540266059SGregory Neil Shapiro **		Populates lmap->ldap_ld.
11640266059SGregory Neil Shapiro */
11740266059SGregory Neil Shapiro 
11840266059SGregory Neil Shapiro static jmp_buf	LDAPTimeout;
11940266059SGregory Neil Shapiro 
12040266059SGregory Neil Shapiro #define SM_LDAP_SETTIMEOUT(to)						\
12140266059SGregory Neil Shapiro do									\
12240266059SGregory Neil Shapiro {									\
12340266059SGregory Neil Shapiro 	if (to != 0)							\
12440266059SGregory Neil Shapiro 	{								\
12540266059SGregory Neil Shapiro 		if (setjmp(LDAPTimeout) != 0)				\
12640266059SGregory Neil Shapiro 		{							\
12740266059SGregory Neil Shapiro 			errno = ETIMEDOUT;				\
12840266059SGregory Neil Shapiro 			return false;					\
12940266059SGregory Neil Shapiro 		}							\
13040266059SGregory Neil Shapiro 		ev = sm_setevent(to, ldaptimeout, 0);			\
13140266059SGregory Neil Shapiro 	}								\
13240266059SGregory Neil Shapiro } while (0)
13340266059SGregory Neil Shapiro 
13440266059SGregory Neil Shapiro #define SM_LDAP_CLEARTIMEOUT()						\
13540266059SGregory Neil Shapiro do									\
13640266059SGregory Neil Shapiro {									\
13740266059SGregory Neil Shapiro 	if (ev != NULL)							\
13840266059SGregory Neil Shapiro 		sm_clrevent(ev);					\
13940266059SGregory Neil Shapiro } while (0)
14040266059SGregory Neil Shapiro 
14140266059SGregory Neil Shapiro bool
14240266059SGregory Neil Shapiro sm_ldap_start(name, lmap)
14340266059SGregory Neil Shapiro 	char *name;
14440266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
14540266059SGregory Neil Shapiro {
14640266059SGregory Neil Shapiro 	int bind_result;
147b6bacd31SGregory Neil Shapiro 	int save_errno = 0;
148e92d3f3fSGregory Neil Shapiro 	char *id;
14940266059SGregory Neil Shapiro 	SM_EVENT *ev = NULL;
150e92d3f3fSGregory Neil Shapiro 	LDAP *ld = NULL;
15140266059SGregory Neil Shapiro 
15240266059SGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 2))
15340266059SGregory Neil Shapiro 		sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name);
15440266059SGregory Neil Shapiro 
155e92d3f3fSGregory Neil Shapiro 	if (lmap->ldap_host != NULL)
156e92d3f3fSGregory Neil Shapiro 		id = lmap->ldap_host;
157e92d3f3fSGregory Neil Shapiro 	else if (lmap->ldap_uri != NULL)
158e92d3f3fSGregory Neil Shapiro 		id = lmap->ldap_uri;
159605302a5SGregory Neil Shapiro 	else
160e92d3f3fSGregory Neil Shapiro 		id = "localhost";
161e92d3f3fSGregory Neil Shapiro 
162e92d3f3fSGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 9))
163e92d3f3fSGregory Neil Shapiro 	{
164e92d3f3fSGregory Neil Shapiro 		/* Don't print a port number for LDAP URIs */
165e92d3f3fSGregory Neil Shapiro 		if (lmap->ldap_uri != NULL)
166e92d3f3fSGregory Neil Shapiro 			sm_dprintf("ldapmap_start(%s)\n", id);
167e92d3f3fSGregory Neil Shapiro 		else
168e92d3f3fSGregory Neil Shapiro 			sm_dprintf("ldapmap_start(%s, %d)\n", id,
169e92d3f3fSGregory Neil Shapiro 				   lmap->ldap_port);
170e92d3f3fSGregory Neil Shapiro 	}
171e92d3f3fSGregory Neil Shapiro 
172e92d3f3fSGregory Neil Shapiro 	if (lmap->ldap_uri != NULL)
173e92d3f3fSGregory Neil Shapiro 	{
174e92d3f3fSGregory Neil Shapiro #if SM_CONF_LDAP_INITIALIZE
175e92d3f3fSGregory Neil Shapiro 		/* LDAP server supports URIs so use them directly */
176e92d3f3fSGregory Neil Shapiro 		save_errno = ldap_initialize(&ld, lmap->ldap_uri);
177e92d3f3fSGregory Neil Shapiro #else /* SM_CONF_LDAP_INITIALIZE */
178e92d3f3fSGregory Neil Shapiro 		int err;
179e92d3f3fSGregory Neil Shapiro 		LDAPURLDesc *ludp = NULL;
180e92d3f3fSGregory Neil Shapiro 
181e92d3f3fSGregory Neil Shapiro 		/* Blast apart URL and use the ldap_init/ldap_open below */
182e92d3f3fSGregory Neil Shapiro 		err = ldap_url_parse(lmap->ldap_uri, &ludp);
183e92d3f3fSGregory Neil Shapiro 		if (err != 0)
184e92d3f3fSGregory Neil Shapiro 		{
185e92d3f3fSGregory Neil Shapiro 			errno = err + E_LDAPURLBASE;
186e92d3f3fSGregory Neil Shapiro 			return false;
187e92d3f3fSGregory Neil Shapiro 		}
188e92d3f3fSGregory Neil Shapiro 		lmap->ldap_host = sm_strdup_x(ludp->lud_host);
189e92d3f3fSGregory Neil Shapiro 		if (lmap->ldap_host == NULL)
190e92d3f3fSGregory Neil Shapiro 		{
191e92d3f3fSGregory Neil Shapiro 			save_errno = errno;
192e92d3f3fSGregory Neil Shapiro 			ldap_free_urldesc(ludp);
193e92d3f3fSGregory Neil Shapiro 			errno = save_errno;
194e92d3f3fSGregory Neil Shapiro 			return false;
195e92d3f3fSGregory Neil Shapiro 		}
196e92d3f3fSGregory Neil Shapiro 		lmap->ldap_port = ludp->lud_port;
197e92d3f3fSGregory Neil Shapiro 		ldap_free_urldesc(ludp);
198e92d3f3fSGregory Neil Shapiro #endif /* SM_CONF_LDAP_INITIALIZE */
199e92d3f3fSGregory Neil Shapiro 	}
200e92d3f3fSGregory Neil Shapiro 
201e92d3f3fSGregory Neil Shapiro 	if (ld == NULL)
202e92d3f3fSGregory Neil Shapiro 	{
203e92d3f3fSGregory Neil Shapiro # if USE_LDAP_INIT
204e92d3f3fSGregory Neil Shapiro 		ld = ldap_init(lmap->ldap_host, lmap->ldap_port);
20540266059SGregory Neil Shapiro 		save_errno = errno;
20640266059SGregory Neil Shapiro # else /* USE_LDAP_INIT */
20740266059SGregory Neil Shapiro 		/*
20840266059SGregory Neil Shapiro 		**  If using ldap_open(), the actual connection to the server
20940266059SGregory Neil Shapiro 		**  happens now so we need the timeout here.  For ldap_init(),
21040266059SGregory Neil Shapiro 		**  the connection happens at bind time.
21140266059SGregory Neil Shapiro 		*/
21240266059SGregory Neil Shapiro 
21340266059SGregory Neil Shapiro 		SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec);
214e92d3f3fSGregory Neil Shapiro 		ld = ldap_open(lmap->ldap_host, lmap->ldap_port);
21540266059SGregory Neil Shapiro 		save_errno = errno;
21640266059SGregory Neil Shapiro 
21740266059SGregory Neil Shapiro 		/* clear the event if it has not sprung */
21840266059SGregory Neil Shapiro 		SM_LDAP_CLEARTIMEOUT();
21940266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */
220e92d3f3fSGregory Neil Shapiro 	}
22140266059SGregory Neil Shapiro 
22240266059SGregory Neil Shapiro 	errno = save_errno;
22340266059SGregory Neil Shapiro 	if (ld == NULL)
22440266059SGregory Neil Shapiro 		return false;
22540266059SGregory Neil Shapiro 
22640266059SGregory Neil Shapiro 	sm_ldap_setopts(ld, lmap);
22740266059SGregory Neil Shapiro 
22840266059SGregory Neil Shapiro # if USE_LDAP_INIT
22940266059SGregory Neil Shapiro 	/*
23040266059SGregory Neil Shapiro 	**  If using ldap_init(), the actual connection to the server
23140266059SGregory Neil Shapiro 	**  happens at ldap_bind_s() so we need the timeout here.
23240266059SGregory Neil Shapiro 	*/
23340266059SGregory Neil Shapiro 
23440266059SGregory Neil Shapiro 	SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec);
23540266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */
23640266059SGregory Neil Shapiro 
23740266059SGregory Neil Shapiro # ifdef LDAP_AUTH_KRBV4
23840266059SGregory Neil Shapiro 	if (lmap->ldap_method == LDAP_AUTH_KRBV4 &&
23940266059SGregory Neil Shapiro 	    lmap->ldap_secret != NULL)
24040266059SGregory Neil Shapiro 	{
24140266059SGregory Neil Shapiro 		/*
24240266059SGregory Neil Shapiro 		**  Need to put ticket in environment here instead of
24340266059SGregory Neil Shapiro 		**  during parseargs as there may be different tickets
24440266059SGregory Neil Shapiro 		**  for different LDAP connections.
24540266059SGregory Neil Shapiro 		*/
24640266059SGregory Neil Shapiro 
24740266059SGregory Neil Shapiro 		(void) putenv(lmap->ldap_secret);
24840266059SGregory Neil Shapiro 	}
24940266059SGregory Neil Shapiro # endif /* LDAP_AUTH_KRBV4 */
25040266059SGregory Neil Shapiro 
25140266059SGregory Neil Shapiro 	bind_result = ldap_bind_s(ld, lmap->ldap_binddn,
25240266059SGregory Neil Shapiro 				  lmap->ldap_secret, lmap->ldap_method);
25340266059SGregory Neil Shapiro 
25440266059SGregory Neil Shapiro # if USE_LDAP_INIT
25540266059SGregory Neil Shapiro 	/* clear the event if it has not sprung */
25640266059SGregory Neil Shapiro 	SM_LDAP_CLEARTIMEOUT();
25740266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */
25840266059SGregory Neil Shapiro 
25940266059SGregory Neil Shapiro 	if (bind_result != LDAP_SUCCESS)
26040266059SGregory Neil Shapiro 	{
26140266059SGregory Neil Shapiro 		errno = bind_result + E_LDAPBASE;
26240266059SGregory Neil Shapiro 		return false;
26340266059SGregory Neil Shapiro 	}
26440266059SGregory Neil Shapiro 
26540266059SGregory Neil Shapiro 	/* Save PID to make sure only this PID closes the LDAP connection */
26640266059SGregory Neil Shapiro 	lmap->ldap_pid = getpid();
26740266059SGregory Neil Shapiro 	lmap->ldap_ld = ld;
26840266059SGregory Neil Shapiro 	return true;
26940266059SGregory Neil Shapiro }
27040266059SGregory Neil Shapiro 
27140266059SGregory Neil Shapiro /* ARGSUSED */
27240266059SGregory Neil Shapiro static void
27340266059SGregory Neil Shapiro ldaptimeout(unused)
27440266059SGregory Neil Shapiro 	int unused;
27540266059SGregory Neil Shapiro {
27640266059SGregory Neil Shapiro 	/*
27740266059SGregory Neil Shapiro 	**  NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
27840266059SGregory Neil Shapiro 	**	ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
27940266059SGregory Neil Shapiro 	**	DOING.
28040266059SGregory Neil Shapiro 	*/
28140266059SGregory Neil Shapiro 
28240266059SGregory Neil Shapiro 	errno = ETIMEDOUT;
28340266059SGregory Neil Shapiro 	longjmp(LDAPTimeout, 1);
28440266059SGregory Neil Shapiro }
28540266059SGregory Neil Shapiro 
28640266059SGregory Neil Shapiro /*
287d0cef73dSGregory Neil Shapiro **  SM_LDAP_SEARCH_M -- initiate multi-key LDAP search
28840266059SGregory Neil Shapiro **
28940266059SGregory Neil Shapiro **	Initiate an LDAP search, return the msgid.
29040266059SGregory Neil Shapiro **	The calling function must collect the results.
29140266059SGregory Neil Shapiro **
29240266059SGregory Neil Shapiro **	Parameters:
29340266059SGregory Neil Shapiro **		lmap -- LDAP map information
294d0cef73dSGregory Neil Shapiro **		argv -- key vector of substitutions in LDAP filter
295d0cef73dSGregory Neil Shapiro **		        NOTE: argv must have SM_LDAP_ARGS elements to prevent
296d0cef73dSGregory Neil Shapiro **			      out of bound array references
29740266059SGregory Neil Shapiro **
29840266059SGregory Neil Shapiro **	Returns:
299d0cef73dSGregory Neil Shapiro **		<0 on failure (SM_LDAP_ERR*), msgid on success
30040266059SGregory Neil Shapiro **
30140266059SGregory Neil Shapiro */
30240266059SGregory Neil Shapiro 
30340266059SGregory Neil Shapiro int
304d0cef73dSGregory Neil Shapiro sm_ldap_search_m(lmap, argv)
30540266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
306d0cef73dSGregory Neil Shapiro 	char **argv;
30740266059SGregory Neil Shapiro {
30840266059SGregory Neil Shapiro 	int msgid;
30940266059SGregory Neil Shapiro 	char *fp, *p, *q;
31040266059SGregory Neil Shapiro 	char filter[LDAPMAP_MAX_FILTER + 1];
31140266059SGregory Neil Shapiro 
312d0cef73dSGregory Neil Shapiro 	SM_REQUIRE(lmap != NULL);
313d0cef73dSGregory Neil Shapiro 	SM_REQUIRE(argv != NULL);
314d0cef73dSGregory Neil Shapiro 	SM_REQUIRE(argv[0] != NULL);
315d0cef73dSGregory Neil Shapiro 
31640266059SGregory Neil Shapiro 	memset(filter, '\0', sizeof filter);
31740266059SGregory Neil Shapiro 	fp = filter;
31840266059SGregory Neil Shapiro 	p = lmap->ldap_filter;
31940266059SGregory Neil Shapiro 	while ((q = strchr(p, '%')) != NULL)
32040266059SGregory Neil Shapiro 	{
321d0cef73dSGregory Neil Shapiro 		char *key;
322d0cef73dSGregory Neil Shapiro 
323d0cef73dSGregory Neil Shapiro 		if (lmap->ldap_multi_args)
324d0cef73dSGregory Neil Shapiro 		{
325d0cef73dSGregory Neil Shapiro #if SM_LDAP_ARGS < 10
326d0cef73dSGregory Neil Shapiro # ERROR _SM_LDAP_ARGS must be 10
327d0cef73dSGregory Neil Shapiro #endif /* SM_LDAP_ARGS < 10 */
328d0cef73dSGregory Neil Shapiro 			if (q[1] == 's')
329d0cef73dSGregory Neil Shapiro 				key = argv[0];
330d0cef73dSGregory Neil Shapiro 			else if (q[1] >= '0' && q[1] <= '9')
331d0cef73dSGregory Neil Shapiro 			{
332d0cef73dSGregory Neil Shapiro 				key = argv[q[1] - '0'];
333d0cef73dSGregory Neil Shapiro 				if (key == NULL)
334d0cef73dSGregory Neil Shapiro 				{
335d0cef73dSGregory Neil Shapiro # if SM_LDAP_ERROR_ON_MISSING_ARGS
336d0cef73dSGregory Neil Shapiro 					return SM_LDAP_ERR_ARG_MISS;
337d0cef73dSGregory Neil Shapiro # else /* SM_LDAP_ERROR_ON_MISSING_ARGS */
338d0cef73dSGregory Neil Shapiro 					key = "";
339d0cef73dSGregory Neil Shapiro # endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */
340d0cef73dSGregory Neil Shapiro 				}
341d0cef73dSGregory Neil Shapiro 			}
342d0cef73dSGregory Neil Shapiro 			else
343d0cef73dSGregory Neil Shapiro 				key = NULL;
344d0cef73dSGregory Neil Shapiro 		}
345d0cef73dSGregory Neil Shapiro 		else
346d0cef73dSGregory Neil Shapiro 			key = argv[0];
347d0cef73dSGregory Neil Shapiro 
34840266059SGregory Neil Shapiro 		if (q[1] == 's')
34940266059SGregory Neil Shapiro 		{
35040266059SGregory Neil Shapiro 			(void) sm_snprintf(fp, SPACELEFT(filter, fp),
35140266059SGregory Neil Shapiro 					   "%.*s%s", (int) (q - p), p, key);
35240266059SGregory Neil Shapiro 			fp += strlen(fp);
35340266059SGregory Neil Shapiro 			p = q + 2;
35440266059SGregory Neil Shapiro 		}
355d0cef73dSGregory Neil Shapiro 		else if (q[1] == '0' ||
356d0cef73dSGregory Neil Shapiro 			 (lmap->ldap_multi_args && q[1] >= '0' && q[1] <= '9'))
35740266059SGregory Neil Shapiro 		{
35840266059SGregory Neil Shapiro 			char *k = key;
35940266059SGregory Neil Shapiro 
36040266059SGregory Neil Shapiro 			(void) sm_snprintf(fp, SPACELEFT(filter, fp),
36140266059SGregory Neil Shapiro 					   "%.*s", (int) (q - p), p);
36240266059SGregory Neil Shapiro 			fp += strlen(fp);
36340266059SGregory Neil Shapiro 			p = q + 2;
36440266059SGregory Neil Shapiro 
36540266059SGregory Neil Shapiro 			/* Properly escape LDAP special characters */
36640266059SGregory Neil Shapiro 			while (SPACELEFT(filter, fp) > 0 &&
36740266059SGregory Neil Shapiro 			       *k != '\0')
36840266059SGregory Neil Shapiro 			{
36940266059SGregory Neil Shapiro 				if (*k == '*' || *k == '(' ||
37040266059SGregory Neil Shapiro 				    *k == ')' || *k == '\\')
37140266059SGregory Neil Shapiro 				{
37240266059SGregory Neil Shapiro 					(void) sm_strlcat(fp,
37340266059SGregory Neil Shapiro 						       (*k == '*' ? "\\2A" :
37440266059SGregory Neil Shapiro 							(*k == '(' ? "\\28" :
37540266059SGregory Neil Shapiro 							 (*k == ')' ? "\\29" :
37640266059SGregory Neil Shapiro 							  (*k == '\\' ? "\\5C" :
37740266059SGregory Neil Shapiro 							   "\00")))),
37840266059SGregory Neil Shapiro 						SPACELEFT(filter, fp));
37940266059SGregory Neil Shapiro 					fp += strlen(fp);
38040266059SGregory Neil Shapiro 					k++;
38140266059SGregory Neil Shapiro 				}
38240266059SGregory Neil Shapiro 				else
38340266059SGregory Neil Shapiro 					*fp++ = *k++;
38440266059SGregory Neil Shapiro 			}
38540266059SGregory Neil Shapiro 		}
38640266059SGregory Neil Shapiro 		else
38740266059SGregory Neil Shapiro 		{
38840266059SGregory Neil Shapiro 			(void) sm_snprintf(fp, SPACELEFT(filter, fp),
38940266059SGregory Neil Shapiro 				"%.*s", (int) (q - p + 1), p);
39040266059SGregory Neil Shapiro 			p = q + (q[1] == '%' ? 2 : 1);
39140266059SGregory Neil Shapiro 			fp += strlen(fp);
39240266059SGregory Neil Shapiro 		}
39340266059SGregory Neil Shapiro 	}
39440266059SGregory Neil Shapiro 	(void) sm_strlcpy(fp, p, SPACELEFT(filter, fp));
39540266059SGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 20))
39640266059SGregory Neil Shapiro 		sm_dprintf("ldap search filter=%s\n", filter);
39740266059SGregory Neil Shapiro 
39840266059SGregory Neil Shapiro 	lmap->ldap_res = NULL;
399605302a5SGregory Neil Shapiro 	msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base,
400605302a5SGregory Neil Shapiro 			    lmap->ldap_scope, filter,
40140266059SGregory Neil Shapiro 			    (lmap->ldap_attr[0] == NULL ? NULL :
40240266059SGregory Neil Shapiro 			     lmap->ldap_attr),
40340266059SGregory Neil Shapiro 			    lmap->ldap_attrsonly);
40440266059SGregory Neil Shapiro 	return msgid;
40540266059SGregory Neil Shapiro }
40640266059SGregory Neil Shapiro 
40740266059SGregory Neil Shapiro /*
408d0cef73dSGregory Neil Shapiro **  SM_LDAP_SEARCH -- initiate LDAP search
409d0cef73dSGregory Neil Shapiro **
410d0cef73dSGregory Neil Shapiro **	Initiate an LDAP search, return the msgid.
411d0cef73dSGregory Neil Shapiro **	The calling function must collect the results.
412d0cef73dSGregory Neil Shapiro **	Note this is just a wrapper into sm_ldap_search_m()
413d0cef73dSGregory Neil Shapiro **
414d0cef73dSGregory Neil Shapiro **	Parameters:
415d0cef73dSGregory Neil Shapiro **		lmap -- LDAP map information
416d0cef73dSGregory Neil Shapiro **		key -- key to substitute in LDAP filter
417d0cef73dSGregory Neil Shapiro **
418d0cef73dSGregory Neil Shapiro **	Returns:
419d0cef73dSGregory Neil Shapiro **		<0 on failure, msgid on success
420d0cef73dSGregory Neil Shapiro **
421d0cef73dSGregory Neil Shapiro */
422d0cef73dSGregory Neil Shapiro 
423d0cef73dSGregory Neil Shapiro int
424d0cef73dSGregory Neil Shapiro sm_ldap_search(lmap, key)
425d0cef73dSGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
426d0cef73dSGregory Neil Shapiro 	char *key;
427d0cef73dSGregory Neil Shapiro {
428d0cef73dSGregory Neil Shapiro 	char *argv[SM_LDAP_ARGS];
429d0cef73dSGregory Neil Shapiro 
430d0cef73dSGregory Neil Shapiro 	memset(argv, '\0', sizeof argv);
431d0cef73dSGregory Neil Shapiro 	argv[0] = key;
432d0cef73dSGregory Neil Shapiro 	return sm_ldap_search_m(lmap, argv);
433d0cef73dSGregory Neil Shapiro }
434d0cef73dSGregory Neil Shapiro 
435d0cef73dSGregory Neil Shapiro /*
436605302a5SGregory Neil Shapiro **  SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a
437605302a5SGregory Neil Shapiro **			       particular objectClass
438605302a5SGregory Neil Shapiro **
439605302a5SGregory Neil Shapiro **	Parameters:
440605302a5SGregory Neil Shapiro **		lmap -- pointer to SM_LDAP_STRUCT in use
441605302a5SGregory Neil Shapiro **		entry -- current LDAP entry struct
442605302a5SGregory Neil Shapiro **		ocvalue -- particular objectclass in question.
443605302a5SGregory Neil Shapiro **			   may be of form (fee|foo|fum) meaning
444605302a5SGregory Neil Shapiro **			   any entry can be part of either fee,
445605302a5SGregory Neil Shapiro **			   foo or fum objectclass
446605302a5SGregory Neil Shapiro **
447605302a5SGregory Neil Shapiro **	Returns:
448605302a5SGregory Neil Shapiro **		true if item has that objectClass
449605302a5SGregory Neil Shapiro */
450605302a5SGregory Neil Shapiro 
451605302a5SGregory Neil Shapiro static bool
452605302a5SGregory Neil Shapiro sm_ldap_has_objectclass(lmap, entry, ocvalue)
453605302a5SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
454605302a5SGregory Neil Shapiro 	LDAPMessage *entry;
455605302a5SGregory Neil Shapiro 	char *ocvalue;
456605302a5SGregory Neil Shapiro {
457605302a5SGregory Neil Shapiro 	char **vals = NULL;
458605302a5SGregory Neil Shapiro 	int i;
459605302a5SGregory Neil Shapiro 
460605302a5SGregory Neil Shapiro 	if (ocvalue == NULL)
461605302a5SGregory Neil Shapiro 		return false;
462605302a5SGregory Neil Shapiro 
463605302a5SGregory Neil Shapiro 	vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass");
464605302a5SGregory Neil Shapiro 	if (vals == NULL)
465605302a5SGregory Neil Shapiro 		return false;
466605302a5SGregory Neil Shapiro 
467605302a5SGregory Neil Shapiro 	for (i = 0; vals[i] != NULL; i++)
468605302a5SGregory Neil Shapiro 	{
469605302a5SGregory Neil Shapiro 		char *p;
470605302a5SGregory Neil Shapiro 		char *q;
471605302a5SGregory Neil Shapiro 
472605302a5SGregory Neil Shapiro 		p = q = ocvalue;
473605302a5SGregory Neil Shapiro 		while (*p != '\0')
474605302a5SGregory Neil Shapiro 		{
475605302a5SGregory Neil Shapiro 			while (*p != '\0' && *p != '|')
476605302a5SGregory Neil Shapiro 				p++;
477605302a5SGregory Neil Shapiro 
478605302a5SGregory Neil Shapiro 			if ((p - q) == strlen(vals[i]) &&
479605302a5SGregory Neil Shapiro 			    sm_strncasecmp(vals[i], q, p - q) == 0)
480605302a5SGregory Neil Shapiro 			{
481605302a5SGregory Neil Shapiro 				ldap_value_free(vals);
482605302a5SGregory Neil Shapiro 				return true;
483605302a5SGregory Neil Shapiro 			}
484605302a5SGregory Neil Shapiro 
485605302a5SGregory Neil Shapiro 			while (*p == '|')
486605302a5SGregory Neil Shapiro 				p++;
487605302a5SGregory Neil Shapiro 			q = p;
488605302a5SGregory Neil Shapiro 		}
489605302a5SGregory Neil Shapiro 	}
490605302a5SGregory Neil Shapiro 
491605302a5SGregory Neil Shapiro 	ldap_value_free(vals);
492605302a5SGregory Neil Shapiro 	return false;
493605302a5SGregory Neil Shapiro }
494605302a5SGregory Neil Shapiro 
495605302a5SGregory Neil Shapiro /*
49640266059SGregory Neil Shapiro **  SM_LDAP_RESULTS -- return results from an LDAP lookup in result
49740266059SGregory Neil Shapiro **
49840266059SGregory Neil Shapiro **	Parameters:
49940266059SGregory Neil Shapiro **		lmap -- pointer to SM_LDAP_STRUCT in use
50040266059SGregory Neil Shapiro **		msgid -- msgid returned by sm_ldap_search()
50140266059SGregory Neil Shapiro **		flags -- flags for the lookup
50240266059SGregory Neil Shapiro **		delim -- delimiter for result concatenation
50340266059SGregory Neil Shapiro **		rpool -- memory pool for storage
50440266059SGregory Neil Shapiro **		result -- return string
50540266059SGregory Neil Shapiro **		recurse -- recursion list
50640266059SGregory Neil Shapiro **
50740266059SGregory Neil Shapiro **	Returns:
50840266059SGregory Neil Shapiro **		status (sysexit)
50940266059SGregory Neil Shapiro */
51040266059SGregory Neil Shapiro 
511605302a5SGregory Neil Shapiro # define SM_LDAP_ERROR_CLEANUP()				\
51240266059SGregory Neil Shapiro {								\
51340266059SGregory Neil Shapiro 	if (lmap->ldap_res != NULL)				\
51440266059SGregory Neil Shapiro 	{							\
51540266059SGregory Neil Shapiro 		ldap_msgfree(lmap->ldap_res);			\
51640266059SGregory Neil Shapiro 		lmap->ldap_res = NULL;				\
51740266059SGregory Neil Shapiro 	}							\
51840266059SGregory Neil Shapiro 	(void) ldap_abandon(lmap->ldap_ld, msgid);		\
51940266059SGregory Neil Shapiro }
52040266059SGregory Neil Shapiro 
521605302a5SGregory Neil Shapiro static SM_LDAP_RECURSE_ENTRY *
522605302a5SGregory Neil Shapiro sm_ldap_add_recurse(top, item, type, rpool)
52340266059SGregory Neil Shapiro 	SM_LDAP_RECURSE_LIST **top;
52440266059SGregory Neil Shapiro 	char *item;
52540266059SGregory Neil Shapiro 	int type;
52640266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
52740266059SGregory Neil Shapiro {
528605302a5SGregory Neil Shapiro 	int n;
529605302a5SGregory Neil Shapiro 	int m;
530605302a5SGregory Neil Shapiro 	int p;
531605302a5SGregory Neil Shapiro 	int insertat;
532605302a5SGregory Neil Shapiro 	int moveb;
533605302a5SGregory Neil Shapiro 	int oldsizeb;
534605302a5SGregory Neil Shapiro 	int rc;
535605302a5SGregory Neil Shapiro 	SM_LDAP_RECURSE_ENTRY *newe;
536605302a5SGregory Neil Shapiro 	SM_LDAP_RECURSE_ENTRY **olddata;
53740266059SGregory Neil Shapiro 
538605302a5SGregory Neil Shapiro 	/*
539605302a5SGregory Neil Shapiro 	**  This code will maintain a list of
540605302a5SGregory Neil Shapiro 	**  SM_LDAP_RECURSE_ENTRY structures
541605302a5SGregory Neil Shapiro 	**  in ascending order.
542605302a5SGregory Neil Shapiro 	*/
543605302a5SGregory Neil Shapiro 
544605302a5SGregory Neil Shapiro 	if (*top == NULL)
54540266059SGregory Neil Shapiro 	{
546605302a5SGregory Neil Shapiro 		/* Allocate an initial SM_LDAP_RECURSE_LIST struct */
547605302a5SGregory Neil Shapiro 		*top = sm_rpool_malloc_x(rpool, sizeof **top);
548d0cef73dSGregory Neil Shapiro 		(*top)->lrl_cnt = 0;
549d0cef73dSGregory Neil Shapiro 		(*top)->lrl_size = 0;
550d0cef73dSGregory Neil Shapiro 		(*top)->lrl_data = NULL;
55140266059SGregory Neil Shapiro 	}
55240266059SGregory Neil Shapiro 
553d0cef73dSGregory Neil Shapiro 	if ((*top)->lrl_cnt >= (*top)->lrl_size)
554605302a5SGregory Neil Shapiro 	{
555605302a5SGregory Neil Shapiro 		/* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */
556d0cef73dSGregory Neil Shapiro 		olddata = (*top)->lrl_data;
557d0cef73dSGregory Neil Shapiro 		if ((*top)->lrl_size == 0)
558605302a5SGregory Neil Shapiro 		{
559605302a5SGregory Neil Shapiro 			oldsizeb = 0;
560d0cef73dSGregory Neil Shapiro 			(*top)->lrl_size = 256;
561605302a5SGregory Neil Shapiro 		}
56240266059SGregory Neil Shapiro 		else
563605302a5SGregory Neil Shapiro 		{
564d0cef73dSGregory Neil Shapiro 			oldsizeb = (*top)->lrl_size * sizeof *((*top)->lrl_data);
565d0cef73dSGregory Neil Shapiro 			(*top)->lrl_size *= 2;
566605302a5SGregory Neil Shapiro 		}
567d0cef73dSGregory Neil Shapiro 		(*top)->lrl_data = sm_rpool_malloc_x(rpool,
568d0cef73dSGregory Neil Shapiro 						    (*top)->lrl_size * sizeof *((*top)->lrl_data));
569605302a5SGregory Neil Shapiro 		if (oldsizeb > 0)
570d0cef73dSGregory Neil Shapiro 			memcpy((*top)->lrl_data, olddata, oldsizeb);
571605302a5SGregory Neil Shapiro 	}
572605302a5SGregory Neil Shapiro 
573605302a5SGregory Neil Shapiro 	/*
574605302a5SGregory Neil Shapiro 	**  Binary search/insert item:type into list.
575605302a5SGregory Neil Shapiro 	**  Return current entry pointer if already exists.
576605302a5SGregory Neil Shapiro 	*/
577605302a5SGregory Neil Shapiro 
578605302a5SGregory Neil Shapiro 	n = 0;
579d0cef73dSGregory Neil Shapiro 	m = (*top)->lrl_cnt - 1;
580605302a5SGregory Neil Shapiro 	if (m < 0)
581605302a5SGregory Neil Shapiro 		insertat = 0;
582605302a5SGregory Neil Shapiro 	else
583605302a5SGregory Neil Shapiro 		insertat = -1;
584605302a5SGregory Neil Shapiro 
585605302a5SGregory Neil Shapiro 	while (insertat == -1)
586605302a5SGregory Neil Shapiro 	{
587605302a5SGregory Neil Shapiro 		p = (m + n) / 2;
588605302a5SGregory Neil Shapiro 
589d0cef73dSGregory Neil Shapiro 		rc = sm_strcasecmp(item, (*top)->lrl_data[p]->lr_search);
590605302a5SGregory Neil Shapiro 		if (rc == 0)
591d0cef73dSGregory Neil Shapiro 			rc = type - (*top)->lrl_data[p]->lr_type;
592605302a5SGregory Neil Shapiro 
593605302a5SGregory Neil Shapiro 		if (rc < 0)
594605302a5SGregory Neil Shapiro 			m = p - 1;
595605302a5SGregory Neil Shapiro 		else if (rc > 0)
596605302a5SGregory Neil Shapiro 			n = p + 1;
597605302a5SGregory Neil Shapiro 		else
598d0cef73dSGregory Neil Shapiro 			return (*top)->lrl_data[p];
599605302a5SGregory Neil Shapiro 
600605302a5SGregory Neil Shapiro 		if (m == -1)
601605302a5SGregory Neil Shapiro 			insertat = 0;
602d0cef73dSGregory Neil Shapiro 		else if (n >= (*top)->lrl_cnt)
603d0cef73dSGregory Neil Shapiro 			insertat = (*top)->lrl_cnt;
604605302a5SGregory Neil Shapiro 		else if (m < n)
605605302a5SGregory Neil Shapiro 			insertat = m + 1;
606605302a5SGregory Neil Shapiro 	}
607605302a5SGregory Neil Shapiro 
608605302a5SGregory Neil Shapiro 	/*
609605302a5SGregory Neil Shapiro 	** Not found in list, make room
610605302a5SGregory Neil Shapiro 	** at insert point and add it.
611605302a5SGregory Neil Shapiro 	*/
612605302a5SGregory Neil Shapiro 
613605302a5SGregory Neil Shapiro 	newe = sm_rpool_malloc_x(rpool, sizeof *newe);
614605302a5SGregory Neil Shapiro 	if (newe != NULL)
615605302a5SGregory Neil Shapiro 	{
616d0cef73dSGregory Neil Shapiro 		moveb = ((*top)->lrl_cnt - insertat) * sizeof *((*top)->lrl_data);
617605302a5SGregory Neil Shapiro 		if (moveb > 0)
618d0cef73dSGregory Neil Shapiro 			memmove(&((*top)->lrl_data[insertat + 1]),
619d0cef73dSGregory Neil Shapiro 				&((*top)->lrl_data[insertat]),
620605302a5SGregory Neil Shapiro 				moveb);
621605302a5SGregory Neil Shapiro 
622605302a5SGregory Neil Shapiro 		newe->lr_search = sm_rpool_strdup_x(rpool, item);
623605302a5SGregory Neil Shapiro 		newe->lr_type = type;
624e92d3f3fSGregory Neil Shapiro 		newe->lr_ludp = NULL;
625e92d3f3fSGregory Neil Shapiro 		newe->lr_attrs = NULL;
626605302a5SGregory Neil Shapiro 		newe->lr_done = false;
627605302a5SGregory Neil Shapiro 
628d0cef73dSGregory Neil Shapiro 		((*top)->lrl_data)[insertat] = newe;
629d0cef73dSGregory Neil Shapiro 		(*top)->lrl_cnt++;
630605302a5SGregory Neil Shapiro 	}
631605302a5SGregory Neil Shapiro 	return newe;
63240266059SGregory Neil Shapiro }
63340266059SGregory Neil Shapiro 
63440266059SGregory Neil Shapiro int
635605302a5SGregory Neil Shapiro sm_ldap_results(lmap, msgid, flags, delim, rpool, result,
636605302a5SGregory Neil Shapiro 		resultln, resultsz, recurse)
63740266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
63840266059SGregory Neil Shapiro 	int msgid;
63940266059SGregory Neil Shapiro 	int flags;
640605302a5SGregory Neil Shapiro 	int delim;
64140266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
64240266059SGregory Neil Shapiro 	char **result;
643605302a5SGregory Neil Shapiro 	int *resultln;
644605302a5SGregory Neil Shapiro 	int *resultsz;
64540266059SGregory Neil Shapiro 	SM_LDAP_RECURSE_LIST *recurse;
64640266059SGregory Neil Shapiro {
64740266059SGregory Neil Shapiro 	bool toplevel;
64840266059SGregory Neil Shapiro 	int i;
64940266059SGregory Neil Shapiro 	int statp;
65040266059SGregory Neil Shapiro 	int vsize;
65140266059SGregory Neil Shapiro 	int ret;
65240266059SGregory Neil Shapiro 	int save_errno;
65340266059SGregory Neil Shapiro 	char *p;
654605302a5SGregory Neil Shapiro 	SM_LDAP_RECURSE_ENTRY *rl;
65540266059SGregory Neil Shapiro 
65640266059SGregory Neil Shapiro 	/* Are we the top top level of the search? */
65740266059SGregory Neil Shapiro 	toplevel = (recurse == NULL);
65840266059SGregory Neil Shapiro 
65940266059SGregory Neil Shapiro 	/* Get results */
66040266059SGregory Neil Shapiro 	statp = EX_NOTFOUND;
66140266059SGregory Neil Shapiro 	while ((ret = ldap_result(lmap->ldap_ld, msgid, 0,
66240266059SGregory Neil Shapiro 				  (lmap->ldap_timeout.tv_sec == 0 ? NULL :
66340266059SGregory Neil Shapiro 				   &(lmap->ldap_timeout)),
66440266059SGregory Neil Shapiro 				  &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY)
66540266059SGregory Neil Shapiro 	{
66640266059SGregory Neil Shapiro 		LDAPMessage *entry;
66740266059SGregory Neil Shapiro 
66840266059SGregory Neil Shapiro 		/* If we don't want multiple values and we have one, break */
66913d88268SGregory Neil Shapiro 		if ((char) delim == '\0' &&
67013d88268SGregory Neil Shapiro 		    !bitset(SM_LDAP_SINGLEMATCH, flags) &&
67113d88268SGregory Neil Shapiro 		    *result != NULL)
67240266059SGregory Neil Shapiro 			break;
67340266059SGregory Neil Shapiro 
67440266059SGregory Neil Shapiro 		/* Cycle through all entries */
67540266059SGregory Neil Shapiro 		for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res);
67640266059SGregory Neil Shapiro 		     entry != NULL;
67740266059SGregory Neil Shapiro 		     entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res))
67840266059SGregory Neil Shapiro 		{
67940266059SGregory Neil Shapiro 			BerElement *ber;
68040266059SGregory Neil Shapiro 			char *attr;
68140266059SGregory Neil Shapiro 			char **vals = NULL;
68240266059SGregory Neil Shapiro 			char *dn;
68340266059SGregory Neil Shapiro 
68440266059SGregory Neil Shapiro 			/*
68540266059SGregory Neil Shapiro 			**  If matching only and found an entry,
68640266059SGregory Neil Shapiro 			**  no need to spin through attributes
68740266059SGregory Neil Shapiro 			*/
68840266059SGregory Neil Shapiro 
689323f6dcbSGregory Neil Shapiro 			if (bitset(SM_LDAP_MATCHONLY, flags))
690323f6dcbSGregory Neil Shapiro 			{
691323f6dcbSGregory Neil Shapiro 				statp = EX_OK;
69240266059SGregory Neil Shapiro 				continue;
693323f6dcbSGregory Neil Shapiro 			}
69440266059SGregory Neil Shapiro 
6954e4196cbSGregory Neil Shapiro #if _FFR_LDAP_SINGLEDN
6964e4196cbSGregory Neil Shapiro 			if (bitset(SM_LDAP_SINGLEDN, flags) && *result != NULL)
6974e4196cbSGregory Neil Shapiro 			{
6984e4196cbSGregory Neil Shapiro 				/* only wanted one match */
6994e4196cbSGregory Neil Shapiro 				SM_LDAP_ERROR_CLEANUP();
7004e4196cbSGregory Neil Shapiro 				errno = ENOENT;
7014e4196cbSGregory Neil Shapiro 				return EX_NOTFOUND;
7024e4196cbSGregory Neil Shapiro 			}
7034e4196cbSGregory Neil Shapiro #endif /* _FFR_LDAP_SINGLEDN */
7044e4196cbSGregory Neil Shapiro 
70540266059SGregory Neil Shapiro 			/* record completed DN's to prevent loops */
70640266059SGregory Neil Shapiro 			dn = ldap_get_dn(lmap->ldap_ld, entry);
70740266059SGregory Neil Shapiro 			if (dn == NULL)
70840266059SGregory Neil Shapiro 			{
70940266059SGregory Neil Shapiro 				save_errno = sm_ldap_geterrno(lmap->ldap_ld);
71040266059SGregory Neil Shapiro 				save_errno += E_LDAPBASE;
711605302a5SGregory Neil Shapiro 				SM_LDAP_ERROR_CLEANUP();
71240266059SGregory Neil Shapiro 				errno = save_errno;
713a7ec597cSGregory Neil Shapiro 				return EX_TEMPFAIL;
71440266059SGregory Neil Shapiro 			}
71540266059SGregory Neil Shapiro 
716605302a5SGregory Neil Shapiro 			rl = sm_ldap_add_recurse(&recurse, dn,
717605302a5SGregory Neil Shapiro 						 SM_LDAP_ATTR_DN,
718605302a5SGregory Neil Shapiro 						 rpool);
719605302a5SGregory Neil Shapiro 
720605302a5SGregory Neil Shapiro 			if (rl == NULL)
72140266059SGregory Neil Shapiro 			{
72240266059SGregory Neil Shapiro 				ldap_memfree(dn);
723605302a5SGregory Neil Shapiro 				SM_LDAP_ERROR_CLEANUP();
72440266059SGregory Neil Shapiro 				errno = ENOMEM;
72540266059SGregory Neil Shapiro 				return EX_OSERR;
726605302a5SGregory Neil Shapiro 			}
727605302a5SGregory Neil Shapiro 			else if (rl->lr_done)
728605302a5SGregory Neil Shapiro 			{
72940266059SGregory Neil Shapiro 				/* already on list, skip it */
73040266059SGregory Neil Shapiro 				ldap_memfree(dn);
73140266059SGregory Neil Shapiro 				continue;
73240266059SGregory Neil Shapiro 			}
73340266059SGregory Neil Shapiro 			ldap_memfree(dn);
73440266059SGregory Neil Shapiro 
73540266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT)
73640266059SGregory Neil Shapiro 			/*
73740266059SGregory Neil Shapiro 			**  Reset value to prevent lingering
73840266059SGregory Neil Shapiro 			**  LDAP_DECODING_ERROR due to
73940266059SGregory Neil Shapiro 			**  OpenLDAP 1.X's hack (see below)
74040266059SGregory Neil Shapiro 			*/
74140266059SGregory Neil Shapiro 
74240266059SGregory Neil Shapiro 			lmap->ldap_ld->ld_errno = LDAP_SUCCESS;
74340266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */
74440266059SGregory Neil Shapiro 
74540266059SGregory Neil Shapiro 			for (attr = ldap_first_attribute(lmap->ldap_ld, entry,
74640266059SGregory Neil Shapiro 							 &ber);
74740266059SGregory Neil Shapiro 			     attr != NULL;
74840266059SGregory Neil Shapiro 			     attr = ldap_next_attribute(lmap->ldap_ld, entry,
74940266059SGregory Neil Shapiro 							ber))
75040266059SGregory Neil Shapiro 			{
75140266059SGregory Neil Shapiro 				char *tmp, *vp_tmp;
75240266059SGregory Neil Shapiro 				int type;
753605302a5SGregory Neil Shapiro 				char *needobjclass = NULL;
75440266059SGregory Neil Shapiro 
755605302a5SGregory Neil Shapiro 				type = SM_LDAP_ATTR_NONE;
75640266059SGregory Neil Shapiro 				for (i = 0; lmap->ldap_attr[i] != NULL; i++)
75740266059SGregory Neil Shapiro 				{
75840266059SGregory Neil Shapiro 					if (sm_strcasecmp(lmap->ldap_attr[i],
75940266059SGregory Neil Shapiro 							  attr) == 0)
76040266059SGregory Neil Shapiro 					{
76140266059SGregory Neil Shapiro 						type = lmap->ldap_attr_type[i];
762605302a5SGregory Neil Shapiro 						needobjclass = lmap->ldap_attr_needobjclass[i];
76340266059SGregory Neil Shapiro 						break;
76440266059SGregory Neil Shapiro 					}
76540266059SGregory Neil Shapiro 				}
766605302a5SGregory Neil Shapiro 
767605302a5SGregory Neil Shapiro 				if (bitset(SM_LDAP_USE_ALLATTR, flags) &&
768605302a5SGregory Neil Shapiro 				    type == SM_LDAP_ATTR_NONE)
769605302a5SGregory Neil Shapiro 				{
770605302a5SGregory Neil Shapiro 					/* URL lookups specify attrs to use */
771605302a5SGregory Neil Shapiro 					type = SM_LDAP_ATTR_NORMAL;
772605302a5SGregory Neil Shapiro 					needobjclass = NULL;
773605302a5SGregory Neil Shapiro 				}
774605302a5SGregory Neil Shapiro 
775605302a5SGregory Neil Shapiro 				if (type == SM_LDAP_ATTR_NONE)
77640266059SGregory Neil Shapiro 				{
77740266059SGregory Neil Shapiro 					/* attribute not requested */
77840266059SGregory Neil Shapiro 					ldap_memfree(attr);
779605302a5SGregory Neil Shapiro 					SM_LDAP_ERROR_CLEANUP();
78040266059SGregory Neil Shapiro 					errno = EFAULT;
78140266059SGregory Neil Shapiro 					return EX_SOFTWARE;
78240266059SGregory Neil Shapiro 				}
78340266059SGregory Neil Shapiro 
784605302a5SGregory Neil Shapiro 				/*
785605302a5SGregory Neil Shapiro 				**  For recursion on a particular attribute,
786605302a5SGregory Neil Shapiro 				**  we may need to see if this entry is
787605302a5SGregory Neil Shapiro 				**  part of a particular objectclass.
788605302a5SGregory Neil Shapiro 				**  Also, ignore objectClass attribute.
789605302a5SGregory Neil Shapiro 				**  Otherwise we just ignore this attribute.
790605302a5SGregory Neil Shapiro 				*/
791605302a5SGregory Neil Shapiro 
792605302a5SGregory Neil Shapiro 				if (type == SM_LDAP_ATTR_OBJCLASS ||
793605302a5SGregory Neil Shapiro 				    (needobjclass != NULL &&
794605302a5SGregory Neil Shapiro 				     !sm_ldap_has_objectclass(lmap, entry,
795605302a5SGregory Neil Shapiro 							      needobjclass)))
796605302a5SGregory Neil Shapiro 				{
797605302a5SGregory Neil Shapiro 					ldap_memfree(attr);
798605302a5SGregory Neil Shapiro 					continue;
799605302a5SGregory Neil Shapiro 				}
800605302a5SGregory Neil Shapiro 
80140266059SGregory Neil Shapiro 				if (lmap->ldap_attrsonly == LDAPMAP_FALSE)
80240266059SGregory Neil Shapiro 				{
80340266059SGregory Neil Shapiro 					vals = ldap_get_values(lmap->ldap_ld,
80440266059SGregory Neil Shapiro 							       entry,
80540266059SGregory Neil Shapiro 							       attr);
80640266059SGregory Neil Shapiro 					if (vals == NULL)
80740266059SGregory Neil Shapiro 					{
80840266059SGregory Neil Shapiro 						save_errno = sm_ldap_geterrno(lmap->ldap_ld);
80940266059SGregory Neil Shapiro 						if (save_errno == LDAP_SUCCESS)
81040266059SGregory Neil Shapiro 						{
81140266059SGregory Neil Shapiro 							ldap_memfree(attr);
81240266059SGregory Neil Shapiro 							continue;
81340266059SGregory Neil Shapiro 						}
81440266059SGregory Neil Shapiro 
81540266059SGregory Neil Shapiro 						/* Must be an error */
81640266059SGregory Neil Shapiro 						save_errno += E_LDAPBASE;
81740266059SGregory Neil Shapiro 						ldap_memfree(attr);
818605302a5SGregory Neil Shapiro 						SM_LDAP_ERROR_CLEANUP();
81940266059SGregory Neil Shapiro 						errno = save_errno;
82040266059SGregory Neil Shapiro 						return EX_TEMPFAIL;
82140266059SGregory Neil Shapiro 					}
82240266059SGregory Neil Shapiro 				}
82340266059SGregory Neil Shapiro 
82440266059SGregory Neil Shapiro 				statp = EX_OK;
82540266059SGregory Neil Shapiro 
82640266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT)
82740266059SGregory Neil Shapiro 				/*
82840266059SGregory Neil Shapiro 				**  Reset value to prevent lingering
82940266059SGregory Neil Shapiro 				**  LDAP_DECODING_ERROR due to
83040266059SGregory Neil Shapiro 				**  OpenLDAP 1.X's hack (see below)
83140266059SGregory Neil Shapiro 				*/
83240266059SGregory Neil Shapiro 
83340266059SGregory Neil Shapiro 				lmap->ldap_ld->ld_errno = LDAP_SUCCESS;
83440266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */
83540266059SGregory Neil Shapiro 
83640266059SGregory Neil Shapiro 				/*
83740266059SGregory Neil Shapiro 				**  If matching only,
83840266059SGregory Neil Shapiro 				**  no need to spin through entries
83940266059SGregory Neil Shapiro 				*/
84040266059SGregory Neil Shapiro 
84140266059SGregory Neil Shapiro 				if (bitset(SM_LDAP_MATCHONLY, flags))
84240266059SGregory Neil Shapiro 				{
84340266059SGregory Neil Shapiro 					if (lmap->ldap_attrsonly == LDAPMAP_FALSE)
84440266059SGregory Neil Shapiro 						ldap_value_free(vals);
84540266059SGregory Neil Shapiro 					ldap_memfree(attr);
84640266059SGregory Neil Shapiro 					continue;
84740266059SGregory Neil Shapiro 				}
84840266059SGregory Neil Shapiro 
84940266059SGregory Neil Shapiro 				/*
85040266059SGregory Neil Shapiro 				**  If we don't want multiple values,
85140266059SGregory Neil Shapiro 				**  return first found.
85240266059SGregory Neil Shapiro 				*/
85340266059SGregory Neil Shapiro 
854605302a5SGregory Neil Shapiro 				if ((char) delim == '\0')
85540266059SGregory Neil Shapiro 				{
856605302a5SGregory Neil Shapiro 					if (*result != NULL)
857605302a5SGregory Neil Shapiro 					{
858605302a5SGregory Neil Shapiro 						/* already have a value */
859605302a5SGregory Neil Shapiro 						if (bitset(SM_LDAP_SINGLEMATCH,
86013d88268SGregory Neil Shapiro 							   flags))
861605302a5SGregory Neil Shapiro 						{
862605302a5SGregory Neil Shapiro 							/* only wanted one match */
863605302a5SGregory Neil Shapiro 							SM_LDAP_ERROR_CLEANUP();
864605302a5SGregory Neil Shapiro 							errno = ENOENT;
865605302a5SGregory Neil Shapiro 							return EX_NOTFOUND;
866605302a5SGregory Neil Shapiro 						}
86713d88268SGregory Neil Shapiro 						break;
86813d88268SGregory Neil Shapiro 					}
869605302a5SGregory Neil Shapiro 
87040266059SGregory Neil Shapiro 					if (lmap->ldap_attrsonly == LDAPMAP_TRUE)
87140266059SGregory Neil Shapiro 					{
87240266059SGregory Neil Shapiro 						*result = sm_rpool_strdup_x(rpool,
87340266059SGregory Neil Shapiro 									    attr);
87440266059SGregory Neil Shapiro 						ldap_memfree(attr);
87540266059SGregory Neil Shapiro 						break;
87640266059SGregory Neil Shapiro 					}
87740266059SGregory Neil Shapiro 
87840266059SGregory Neil Shapiro 					if (vals[0] == NULL)
87940266059SGregory Neil Shapiro 					{
88040266059SGregory Neil Shapiro 						ldap_value_free(vals);
88140266059SGregory Neil Shapiro 						ldap_memfree(attr);
88240266059SGregory Neil Shapiro 						continue;
88340266059SGregory Neil Shapiro 					}
88440266059SGregory Neil Shapiro 
88540266059SGregory Neil Shapiro 					vsize = strlen(vals[0]) + 1;
88640266059SGregory Neil Shapiro 					if (lmap->ldap_attrsep != '\0')
88740266059SGregory Neil Shapiro 						vsize += strlen(attr) + 1;
88840266059SGregory Neil Shapiro 					*result = sm_rpool_malloc_x(rpool,
88940266059SGregory Neil Shapiro 								    vsize);
89040266059SGregory Neil Shapiro 					if (lmap->ldap_attrsep != '\0')
89140266059SGregory Neil Shapiro 						sm_snprintf(*result, vsize,
89240266059SGregory Neil Shapiro 							    "%s%c%s",
89340266059SGregory Neil Shapiro 							    attr,
89440266059SGregory Neil Shapiro 							    lmap->ldap_attrsep,
89540266059SGregory Neil Shapiro 							    vals[0]);
89640266059SGregory Neil Shapiro 					else
89740266059SGregory Neil Shapiro 						sm_strlcpy(*result, vals[0],
89840266059SGregory Neil Shapiro 							   vsize);
89940266059SGregory Neil Shapiro 					ldap_value_free(vals);
90040266059SGregory Neil Shapiro 					ldap_memfree(attr);
90140266059SGregory Neil Shapiro 					break;
90240266059SGregory Neil Shapiro 				}
90340266059SGregory Neil Shapiro 
90440266059SGregory Neil Shapiro 				/* attributes only */
90540266059SGregory Neil Shapiro 				if (lmap->ldap_attrsonly == LDAPMAP_TRUE)
90640266059SGregory Neil Shapiro 				{
90740266059SGregory Neil Shapiro 					if (*result == NULL)
90840266059SGregory Neil Shapiro 						*result = sm_rpool_strdup_x(rpool,
90940266059SGregory Neil Shapiro 									    attr);
91040266059SGregory Neil Shapiro 					else
91140266059SGregory Neil Shapiro 					{
912605302a5SGregory Neil Shapiro 						if (bitset(SM_LDAP_SINGLEMATCH,
913605302a5SGregory Neil Shapiro 							   flags) &&
914605302a5SGregory Neil Shapiro 						    *result != NULL)
915605302a5SGregory Neil Shapiro 						{
916605302a5SGregory Neil Shapiro 							/* only wanted one match */
917605302a5SGregory Neil Shapiro 							SM_LDAP_ERROR_CLEANUP();
918605302a5SGregory Neil Shapiro 							errno = ENOENT;
919605302a5SGregory Neil Shapiro 							return EX_NOTFOUND;
920605302a5SGregory Neil Shapiro 						}
921605302a5SGregory Neil Shapiro 
92240266059SGregory Neil Shapiro 						vsize = strlen(*result) +
92340266059SGregory Neil Shapiro 							strlen(attr) + 2;
92440266059SGregory Neil Shapiro 						tmp = sm_rpool_malloc_x(rpool,
92540266059SGregory Neil Shapiro 									vsize);
92640266059SGregory Neil Shapiro 						(void) sm_snprintf(tmp,
92740266059SGregory Neil Shapiro 							vsize, "%s%c%s",
928605302a5SGregory Neil Shapiro 							*result, (char) delim,
92940266059SGregory Neil Shapiro 							attr);
93040266059SGregory Neil Shapiro 						*result = tmp;
93140266059SGregory Neil Shapiro 					}
93240266059SGregory Neil Shapiro 					ldap_memfree(attr);
93340266059SGregory Neil Shapiro 					continue;
93440266059SGregory Neil Shapiro 				}
93540266059SGregory Neil Shapiro 
93640266059SGregory Neil Shapiro 				/*
937605302a5SGregory Neil Shapiro 				**  If there is more than one, munge then
938605302a5SGregory Neil Shapiro 				**  into a map_coldelim separated string.
939605302a5SGregory Neil Shapiro 				**  If we are recursing we may have an entry
940605302a5SGregory Neil Shapiro 				**  with no 'normal' values to put in the
941605302a5SGregory Neil Shapiro 				**  string.
942605302a5SGregory Neil Shapiro 				**  This is not an error.
94340266059SGregory Neil Shapiro 				*/
94440266059SGregory Neil Shapiro 
945605302a5SGregory Neil Shapiro 				if (type == SM_LDAP_ATTR_NORMAL &&
946605302a5SGregory Neil Shapiro 				    bitset(SM_LDAP_SINGLEMATCH, flags) &&
947605302a5SGregory Neil Shapiro 				    *result != NULL)
948605302a5SGregory Neil Shapiro 				{
949605302a5SGregory Neil Shapiro 					/* only wanted one match */
950605302a5SGregory Neil Shapiro 					SM_LDAP_ERROR_CLEANUP();
951605302a5SGregory Neil Shapiro 					errno = ENOENT;
952605302a5SGregory Neil Shapiro 					return EX_NOTFOUND;
953605302a5SGregory Neil Shapiro 				}
954605302a5SGregory Neil Shapiro 
95540266059SGregory Neil Shapiro 				vsize = 0;
95640266059SGregory Neil Shapiro 				for (i = 0; vals[i] != NULL; i++)
95740266059SGregory Neil Shapiro 				{
958605302a5SGregory Neil Shapiro 					if (type == SM_LDAP_ATTR_DN ||
959605302a5SGregory Neil Shapiro 					    type == SM_LDAP_ATTR_FILTER ||
960605302a5SGregory Neil Shapiro 					    type == SM_LDAP_ATTR_URL)
96140266059SGregory Neil Shapiro 					{
962605302a5SGregory Neil Shapiro 						/* add to recursion */
963605302a5SGregory Neil Shapiro 						if (sm_ldap_add_recurse(&recurse,
96440266059SGregory Neil Shapiro 									vals[i],
965605302a5SGregory Neil Shapiro 									type,
966605302a5SGregory Neil Shapiro 									rpool) == NULL)
96740266059SGregory Neil Shapiro 						{
968605302a5SGregory Neil Shapiro 							SM_LDAP_ERROR_CLEANUP();
96940266059SGregory Neil Shapiro 							errno = ENOMEM;
97040266059SGregory Neil Shapiro 							return EX_OSERR;
97140266059SGregory Neil Shapiro 						}
97240266059SGregory Neil Shapiro 						continue;
97340266059SGregory Neil Shapiro 					}
974605302a5SGregory Neil Shapiro 
97540266059SGregory Neil Shapiro 					vsize += strlen(vals[i]) + 1;
97640266059SGregory Neil Shapiro 					if (lmap->ldap_attrsep != '\0')
97740266059SGregory Neil Shapiro 						vsize += strlen(attr) + 1;
97840266059SGregory Neil Shapiro 				}
979605302a5SGregory Neil Shapiro 
980605302a5SGregory Neil Shapiro 				/*
981605302a5SGregory Neil Shapiro 				**  Create/Append to string any normal
982605302a5SGregory Neil Shapiro 				**  attribute values.  Otherwise, just free
983605302a5SGregory Neil Shapiro 				**  memory and move on to the next
984605302a5SGregory Neil Shapiro 				**  attribute in this entry.
985605302a5SGregory Neil Shapiro 				*/
986605302a5SGregory Neil Shapiro 
987605302a5SGregory Neil Shapiro 				if (type == SM_LDAP_ATTR_NORMAL && vsize > 0)
988605302a5SGregory Neil Shapiro 				{
989605302a5SGregory Neil Shapiro 					char *pe;
990605302a5SGregory Neil Shapiro 
991605302a5SGregory Neil Shapiro 					/* Grow result string if needed */
992605302a5SGregory Neil Shapiro 					if ((*resultln + vsize) >= *resultsz)
993605302a5SGregory Neil Shapiro 					{
994605302a5SGregory Neil Shapiro 						while ((*resultln + vsize) >= *resultsz)
995605302a5SGregory Neil Shapiro 						{
996605302a5SGregory Neil Shapiro 							if (*resultsz == 0)
997605302a5SGregory Neil Shapiro 								*resultsz = 1024;
998605302a5SGregory Neil Shapiro 							else
999605302a5SGregory Neil Shapiro 								*resultsz *= 2;
1000605302a5SGregory Neil Shapiro 						}
1001605302a5SGregory Neil Shapiro 
1002605302a5SGregory Neil Shapiro 						vp_tmp = sm_rpool_malloc_x(rpool, *resultsz);
100340266059SGregory Neil Shapiro 						*vp_tmp = '\0';
100440266059SGregory Neil Shapiro 
1005605302a5SGregory Neil Shapiro 						if (*result != NULL)
1006605302a5SGregory Neil Shapiro 							sm_strlcpy(vp_tmp,
1007605302a5SGregory Neil Shapiro 								   *result,
1008605302a5SGregory Neil Shapiro 								   *resultsz);
1009605302a5SGregory Neil Shapiro 						*result = vp_tmp;
1010605302a5SGregory Neil Shapiro 					}
1011605302a5SGregory Neil Shapiro 
1012605302a5SGregory Neil Shapiro 					p = *result + *resultln;
1013605302a5SGregory Neil Shapiro 					pe = *result + *resultsz;
1014605302a5SGregory Neil Shapiro 
101540266059SGregory Neil Shapiro 					for (i = 0; vals[i] != NULL; i++)
101640266059SGregory Neil Shapiro 					{
1017959366dcSGregory Neil Shapiro 						if (*resultln > 0 &&
1018959366dcSGregory Neil Shapiro 						    p < pe)
1019605302a5SGregory Neil Shapiro 							*p++ = (char) delim;
1020605302a5SGregory Neil Shapiro 
102140266059SGregory Neil Shapiro 						if (lmap->ldap_attrsep != '\0')
102240266059SGregory Neil Shapiro 						{
102340266059SGregory Neil Shapiro 							p += sm_strlcpy(p, attr,
1024605302a5SGregory Neil Shapiro 									pe - p);
1025605302a5SGregory Neil Shapiro 							if (p < pe)
102640266059SGregory Neil Shapiro 								*p++ = lmap->ldap_attrsep;
102740266059SGregory Neil Shapiro 						}
1028605302a5SGregory Neil Shapiro 
102940266059SGregory Neil Shapiro 						p += sm_strlcpy(p, vals[i],
1030605302a5SGregory Neil Shapiro 								pe - p);
1031605302a5SGregory Neil Shapiro 						*resultln = p - (*result);
1032605302a5SGregory Neil Shapiro 						if (p >= pe)
103340266059SGregory Neil Shapiro 						{
103440266059SGregory Neil Shapiro 							/* Internal error: buffer too small for LDAP values */
1035605302a5SGregory Neil Shapiro 							SM_LDAP_ERROR_CLEANUP();
103640266059SGregory Neil Shapiro 							errno = ENOMEM;
103740266059SGregory Neil Shapiro 							return EX_OSERR;
103840266059SGregory Neil Shapiro 						}
1039605302a5SGregory Neil Shapiro 					}
104040266059SGregory Neil Shapiro 				}
104140266059SGregory Neil Shapiro 
104240266059SGregory Neil Shapiro 				ldap_value_free(vals);
104340266059SGregory Neil Shapiro 				ldap_memfree(attr);
104440266059SGregory Neil Shapiro 			}
104540266059SGregory Neil Shapiro 			save_errno = sm_ldap_geterrno(lmap->ldap_ld);
104640266059SGregory Neil Shapiro 
104740266059SGregory Neil Shapiro 			/*
104840266059SGregory Neil Shapiro 			**  We check save_errno != LDAP_DECODING_ERROR since
104940266059SGregory Neil Shapiro 			**  OpenLDAP 1.X has a very ugly *undocumented*
105040266059SGregory Neil Shapiro 			**  hack of returning this error code from
105140266059SGregory Neil Shapiro 			**  ldap_next_attribute() if the library freed the
105240266059SGregory Neil Shapiro 			**  ber attribute.  See:
105340266059SGregory Neil Shapiro 			**  http://www.openldap.org/lists/openldap-devel/9901/msg00064.html
105440266059SGregory Neil Shapiro 			*/
105540266059SGregory Neil Shapiro 
105640266059SGregory Neil Shapiro 			if (save_errno != LDAP_SUCCESS &&
105740266059SGregory Neil Shapiro 			    save_errno != LDAP_DECODING_ERROR)
105840266059SGregory Neil Shapiro 			{
105940266059SGregory Neil Shapiro 				/* Must be an error */
106040266059SGregory Neil Shapiro 				save_errno += E_LDAPBASE;
1061605302a5SGregory Neil Shapiro 				SM_LDAP_ERROR_CLEANUP();
106240266059SGregory Neil Shapiro 				errno = save_errno;
106340266059SGregory Neil Shapiro 				return EX_TEMPFAIL;
106440266059SGregory Neil Shapiro 			}
106540266059SGregory Neil Shapiro 
1066605302a5SGregory Neil Shapiro 			/* mark this DN as done */
1067605302a5SGregory Neil Shapiro 			rl->lr_done = true;
1068e92d3f3fSGregory Neil Shapiro 			if (rl->lr_ludp != NULL)
1069e92d3f3fSGregory Neil Shapiro 			{
1070e92d3f3fSGregory Neil Shapiro 				ldap_free_urldesc(rl->lr_ludp);
1071e92d3f3fSGregory Neil Shapiro 				rl->lr_ludp = NULL;
1072e92d3f3fSGregory Neil Shapiro 			}
1073e92d3f3fSGregory Neil Shapiro 			if (rl->lr_attrs != NULL)
1074e92d3f3fSGregory Neil Shapiro 			{
1075e92d3f3fSGregory Neil Shapiro 				free(rl->lr_attrs);
1076e92d3f3fSGregory Neil Shapiro 				rl->lr_attrs = NULL;
1077e92d3f3fSGregory Neil Shapiro 			}
1078605302a5SGregory Neil Shapiro 
107940266059SGregory Neil Shapiro 			/* We don't want multiple values and we have one */
108013d88268SGregory Neil Shapiro 			if ((char) delim == '\0' &&
108113d88268SGregory Neil Shapiro 			    !bitset(SM_LDAP_SINGLEMATCH, flags) &&
108213d88268SGregory Neil Shapiro 			    *result != NULL)
108340266059SGregory Neil Shapiro 				break;
108440266059SGregory Neil Shapiro 		}
108540266059SGregory Neil Shapiro 		save_errno = sm_ldap_geterrno(lmap->ldap_ld);
108640266059SGregory Neil Shapiro 		if (save_errno != LDAP_SUCCESS &&
108740266059SGregory Neil Shapiro 		    save_errno != LDAP_DECODING_ERROR)
108840266059SGregory Neil Shapiro 		{
108940266059SGregory Neil Shapiro 			/* Must be an error */
109040266059SGregory Neil Shapiro 			save_errno += E_LDAPBASE;
1091605302a5SGregory Neil Shapiro 			SM_LDAP_ERROR_CLEANUP();
109240266059SGregory Neil Shapiro 			errno = save_errno;
109340266059SGregory Neil Shapiro 			return EX_TEMPFAIL;
109440266059SGregory Neil Shapiro 		}
109540266059SGregory Neil Shapiro 		ldap_msgfree(lmap->ldap_res);
109640266059SGregory Neil Shapiro 		lmap->ldap_res = NULL;
109740266059SGregory Neil Shapiro 	}
109840266059SGregory Neil Shapiro 
109940266059SGregory Neil Shapiro 	if (ret == 0)
110040266059SGregory Neil Shapiro 		save_errno = ETIMEDOUT;
110140266059SGregory Neil Shapiro 	else
110240266059SGregory Neil Shapiro 		save_errno = sm_ldap_geterrno(lmap->ldap_ld);
110340266059SGregory Neil Shapiro 	if (save_errno != LDAP_SUCCESS)
110440266059SGregory Neil Shapiro 	{
110540266059SGregory Neil Shapiro 		statp = EX_TEMPFAIL;
110640266059SGregory Neil Shapiro 		switch (save_errno)
110740266059SGregory Neil Shapiro 		{
110840266059SGregory Neil Shapiro #ifdef LDAP_SERVER_DOWN
110940266059SGregory Neil Shapiro 		  case LDAP_SERVER_DOWN:
111040266059SGregory Neil Shapiro #endif /* LDAP_SERVER_DOWN */
111140266059SGregory Neil Shapiro 		  case LDAP_TIMEOUT:
1112ffb83623SGregory Neil Shapiro 		  case ETIMEDOUT:
111340266059SGregory Neil Shapiro 		  case LDAP_UNAVAILABLE:
1114605302a5SGregory Neil Shapiro 
1115605302a5SGregory Neil Shapiro 			/*
1116605302a5SGregory Neil Shapiro 			**  server disappeared,
1117605302a5SGregory Neil Shapiro 			**  try reopen on next search
1118605302a5SGregory Neil Shapiro 			*/
1119605302a5SGregory Neil Shapiro 
112040266059SGregory Neil Shapiro 			statp = EX_RESTART;
112140266059SGregory Neil Shapiro 			break;
112240266059SGregory Neil Shapiro 		}
1123ffb83623SGregory Neil Shapiro 		if (ret != 0)
112440266059SGregory Neil Shapiro 			save_errno += E_LDAPBASE;
1125605302a5SGregory Neil Shapiro 		SM_LDAP_ERROR_CLEANUP();
112640266059SGregory Neil Shapiro 		errno = save_errno;
112740266059SGregory Neil Shapiro 		return statp;
112840266059SGregory Neil Shapiro 	}
112940266059SGregory Neil Shapiro 
113040266059SGregory Neil Shapiro 	if (lmap->ldap_res != NULL)
113140266059SGregory Neil Shapiro 	{
113240266059SGregory Neil Shapiro 		ldap_msgfree(lmap->ldap_res);
113340266059SGregory Neil Shapiro 		lmap->ldap_res = NULL;
113440266059SGregory Neil Shapiro 	}
113540266059SGregory Neil Shapiro 
113640266059SGregory Neil Shapiro 	if (toplevel)
113740266059SGregory Neil Shapiro 	{
1138605302a5SGregory Neil Shapiro 		int rlidx;
113940266059SGregory Neil Shapiro 
114040266059SGregory Neil Shapiro 		/*
114140266059SGregory Neil Shapiro 		**  Spin through the built-up recurse list at the top
114240266059SGregory Neil Shapiro 		**  of the recursion.  Since new items are added at the
114340266059SGregory Neil Shapiro 		**  end of the shared list, we actually only ever get
114440266059SGregory Neil Shapiro 		**  one level of recursion before things pop back to the
114540266059SGregory Neil Shapiro 		**  top.  Any items added to the list during that recursion
114640266059SGregory Neil Shapiro 		**  will be expanded by the top level.
114740266059SGregory Neil Shapiro 		*/
114840266059SGregory Neil Shapiro 
1149d0cef73dSGregory Neil Shapiro 		for (rlidx = 0; recurse != NULL && rlidx < recurse->lrl_cnt;
1150d0cef73dSGregory Neil Shapiro 		     rlidx++)
115140266059SGregory Neil Shapiro 		{
1152605302a5SGregory Neil Shapiro 			int newflags;
115340266059SGregory Neil Shapiro 			int sid;
115440266059SGregory Neil Shapiro 			int status;
115540266059SGregory Neil Shapiro 
1156d0cef73dSGregory Neil Shapiro 			rl = recurse->lrl_data[rlidx];
1157605302a5SGregory Neil Shapiro 
1158605302a5SGregory Neil Shapiro 			newflags = flags;
1159605302a5SGregory Neil Shapiro 			if (rl->lr_done)
116040266059SGregory Neil Shapiro 			{
116140266059SGregory Neil Shapiro 				/* already expanded */
116240266059SGregory Neil Shapiro 				continue;
116340266059SGregory Neil Shapiro 			}
1164605302a5SGregory Neil Shapiro 
1165605302a5SGregory Neil Shapiro 			if (rl->lr_type == SM_LDAP_ATTR_DN)
116640266059SGregory Neil Shapiro 			{
116740266059SGregory Neil Shapiro 				/* do DN search */
116840266059SGregory Neil Shapiro 				sid = ldap_search(lmap->ldap_ld,
116940266059SGregory Neil Shapiro 						  rl->lr_search,
117040266059SGregory Neil Shapiro 						  lmap->ldap_scope,
117140266059SGregory Neil Shapiro 						  "(objectClass=*)",
1172605302a5SGregory Neil Shapiro 						  (lmap->ldap_attr[0] == NULL ?
1173605302a5SGregory Neil Shapiro 						   NULL : lmap->ldap_attr),
117440266059SGregory Neil Shapiro 						  lmap->ldap_attrsonly);
117540266059SGregory Neil Shapiro 			}
1176605302a5SGregory Neil Shapiro 			else if (rl->lr_type == SM_LDAP_ATTR_FILTER)
117740266059SGregory Neil Shapiro 			{
117840266059SGregory Neil Shapiro 				/* do new search */
117940266059SGregory Neil Shapiro 				sid = ldap_search(lmap->ldap_ld,
118040266059SGregory Neil Shapiro 						  lmap->ldap_base,
118140266059SGregory Neil Shapiro 						  lmap->ldap_scope,
118240266059SGregory Neil Shapiro 						  rl->lr_search,
1183605302a5SGregory Neil Shapiro 						  (lmap->ldap_attr[0] == NULL ?
1184605302a5SGregory Neil Shapiro 						   NULL : lmap->ldap_attr),
118540266059SGregory Neil Shapiro 						  lmap->ldap_attrsonly);
118640266059SGregory Neil Shapiro 			}
1187605302a5SGregory Neil Shapiro 			else if (rl->lr_type == SM_LDAP_ATTR_URL)
118840266059SGregory Neil Shapiro 			{
1189e92d3f3fSGregory Neil Shapiro 				/* Parse URL */
1190e92d3f3fSGregory Neil Shapiro 				sid = ldap_url_parse(rl->lr_search,
1191e92d3f3fSGregory Neil Shapiro 						     &rl->lr_ludp);
1192e92d3f3fSGregory Neil Shapiro 
1193e92d3f3fSGregory Neil Shapiro 				if (sid != 0)
1194e92d3f3fSGregory Neil Shapiro 				{
1195e92d3f3fSGregory Neil Shapiro 					errno = sid + E_LDAPURLBASE;
1196e92d3f3fSGregory Neil Shapiro 					return EX_TEMPFAIL;
1197e92d3f3fSGregory Neil Shapiro 				}
1198e92d3f3fSGregory Neil Shapiro 
1199e92d3f3fSGregory Neil Shapiro 				/* We need to add objectClass */
1200e92d3f3fSGregory Neil Shapiro 				if (rl->lr_ludp->lud_attrs != NULL)
1201e92d3f3fSGregory Neil Shapiro 				{
1202e92d3f3fSGregory Neil Shapiro 					int attrnum = 0;
1203e92d3f3fSGregory Neil Shapiro 
1204e92d3f3fSGregory Neil Shapiro 					while (rl->lr_ludp->lud_attrs[attrnum] != NULL)
1205e92d3f3fSGregory Neil Shapiro 					{
1206e92d3f3fSGregory Neil Shapiro 						if (strcasecmp(rl->lr_ludp->lud_attrs[attrnum],
1207e92d3f3fSGregory Neil Shapiro 							       "objectClass") == 0)
1208e92d3f3fSGregory Neil Shapiro 						{
1209e92d3f3fSGregory Neil Shapiro 							/* already requested */
1210e92d3f3fSGregory Neil Shapiro 							attrnum = -1;
1211e92d3f3fSGregory Neil Shapiro 							break;
1212e92d3f3fSGregory Neil Shapiro 						}
1213e92d3f3fSGregory Neil Shapiro 						attrnum++;
1214e92d3f3fSGregory Neil Shapiro 					}
1215e92d3f3fSGregory Neil Shapiro 
1216e92d3f3fSGregory Neil Shapiro 					if (attrnum >= 0)
1217e92d3f3fSGregory Neil Shapiro 					{
1218e92d3f3fSGregory Neil Shapiro 						int i;
1219e92d3f3fSGregory Neil Shapiro 
1220e92d3f3fSGregory Neil Shapiro 						rl->lr_attrs = (char **)malloc(sizeof(char *) * (attrnum + 2));
1221e92d3f3fSGregory Neil Shapiro 						if (rl->lr_attrs == NULL)
1222e92d3f3fSGregory Neil Shapiro 						{
1223e92d3f3fSGregory Neil Shapiro 							save_errno = errno;
1224e92d3f3fSGregory Neil Shapiro 							ldap_free_urldesc(rl->lr_ludp);
1225e92d3f3fSGregory Neil Shapiro 							errno = save_errno;
1226e92d3f3fSGregory Neil Shapiro 							return EX_TEMPFAIL;
1227e92d3f3fSGregory Neil Shapiro 						}
1228e92d3f3fSGregory Neil Shapiro 						for (i = 0 ; i < attrnum; i++)
1229e92d3f3fSGregory Neil Shapiro 						{
1230e92d3f3fSGregory Neil Shapiro 							rl->lr_attrs[i] = rl->lr_ludp->lud_attrs[i];
1231e92d3f3fSGregory Neil Shapiro 						}
1232e92d3f3fSGregory Neil Shapiro 						rl->lr_attrs[i++] = "objectClass";
1233e92d3f3fSGregory Neil Shapiro 						rl->lr_attrs[i++] = NULL;
1234e92d3f3fSGregory Neil Shapiro 					}
1235e92d3f3fSGregory Neil Shapiro 				}
1236e92d3f3fSGregory Neil Shapiro 
1237e92d3f3fSGregory Neil Shapiro 				/*
1238e92d3f3fSGregory Neil Shapiro 				**  Use the existing connection
1239e92d3f3fSGregory Neil Shapiro 				**  for this search.  It really
1240e92d3f3fSGregory Neil Shapiro 				**  should use lud_scheme://lud_host:lud_port/
1241e92d3f3fSGregory Neil Shapiro 				**  instead but that would require
1242e92d3f3fSGregory Neil Shapiro 				**  opening a new connection.
1243e92d3f3fSGregory Neil Shapiro 				**  This should be fixed ASAP.
1244e92d3f3fSGregory Neil Shapiro 				*/
1245e92d3f3fSGregory Neil Shapiro 
1246e92d3f3fSGregory Neil Shapiro 				sid = ldap_search(lmap->ldap_ld,
1247e92d3f3fSGregory Neil Shapiro 						  rl->lr_ludp->lud_dn,
1248e92d3f3fSGregory Neil Shapiro 						  rl->lr_ludp->lud_scope,
1249e92d3f3fSGregory Neil Shapiro 						  rl->lr_ludp->lud_filter,
1250e92d3f3fSGregory Neil Shapiro 						  rl->lr_attrs,
125140266059SGregory Neil Shapiro 						  lmap->ldap_attrsonly);
1252e92d3f3fSGregory Neil Shapiro 
1253e92d3f3fSGregory Neil Shapiro 				/* Use the attributes specified by URL */
1254605302a5SGregory Neil Shapiro 				newflags |= SM_LDAP_USE_ALLATTR;
125540266059SGregory Neil Shapiro 			}
125640266059SGregory Neil Shapiro 			else
125740266059SGregory Neil Shapiro 			{
125840266059SGregory Neil Shapiro 				/* unknown or illegal attribute type */
125940266059SGregory Neil Shapiro 				errno = EFAULT;
126040266059SGregory Neil Shapiro 				return EX_SOFTWARE;
126140266059SGregory Neil Shapiro 			}
126240266059SGregory Neil Shapiro 
126340266059SGregory Neil Shapiro 			/* Collect results */
126440266059SGregory Neil Shapiro 			if (sid == -1)
126540266059SGregory Neil Shapiro 			{
126640266059SGregory Neil Shapiro 				save_errno = sm_ldap_geterrno(lmap->ldap_ld);
126740266059SGregory Neil Shapiro 				statp = EX_TEMPFAIL;
126840266059SGregory Neil Shapiro 				switch (save_errno)
126940266059SGregory Neil Shapiro 				{
127040266059SGregory Neil Shapiro #ifdef LDAP_SERVER_DOWN
127140266059SGregory Neil Shapiro 				  case LDAP_SERVER_DOWN:
127240266059SGregory Neil Shapiro #endif /* LDAP_SERVER_DOWN */
127340266059SGregory Neil Shapiro 				  case LDAP_TIMEOUT:
1274ffb83623SGregory Neil Shapiro 				  case ETIMEDOUT:
127540266059SGregory Neil Shapiro 				  case LDAP_UNAVAILABLE:
1276605302a5SGregory Neil Shapiro 
1277605302a5SGregory Neil Shapiro 					/*
1278605302a5SGregory Neil Shapiro 					**  server disappeared,
1279605302a5SGregory Neil Shapiro 					**  try reopen on next search
1280605302a5SGregory Neil Shapiro 					*/
1281605302a5SGregory Neil Shapiro 
128240266059SGregory Neil Shapiro 					statp = EX_RESTART;
128340266059SGregory Neil Shapiro 					break;
128440266059SGregory Neil Shapiro 				}
128540266059SGregory Neil Shapiro 				errno = save_errno + E_LDAPBASE;
128640266059SGregory Neil Shapiro 				return statp;
128740266059SGregory Neil Shapiro 			}
128840266059SGregory Neil Shapiro 
1289605302a5SGregory Neil Shapiro 			status = sm_ldap_results(lmap, sid, newflags, delim,
1290605302a5SGregory Neil Shapiro 						 rpool, result, resultln,
1291605302a5SGregory Neil Shapiro 						 resultsz, recurse);
129240266059SGregory Neil Shapiro 			save_errno = errno;
129340266059SGregory Neil Shapiro 			if (status != EX_OK && status != EX_NOTFOUND)
129440266059SGregory Neil Shapiro 			{
129540266059SGregory Neil Shapiro 				errno = save_errno;
129640266059SGregory Neil Shapiro 				return status;
129740266059SGregory Neil Shapiro 			}
129840266059SGregory Neil Shapiro 
129940266059SGregory Neil Shapiro 			/* Mark as done */
1300605302a5SGregory Neil Shapiro 			rl->lr_done = true;
1301e92d3f3fSGregory Neil Shapiro 			if (rl->lr_ludp != NULL)
1302e92d3f3fSGregory Neil Shapiro 			{
1303e92d3f3fSGregory Neil Shapiro 				ldap_free_urldesc(rl->lr_ludp);
1304e92d3f3fSGregory Neil Shapiro 				rl->lr_ludp = NULL;
1305e92d3f3fSGregory Neil Shapiro 			}
1306e92d3f3fSGregory Neil Shapiro 			if (rl->lr_attrs != NULL)
1307e92d3f3fSGregory Neil Shapiro 			{
1308e92d3f3fSGregory Neil Shapiro 				free(rl->lr_attrs);
1309e92d3f3fSGregory Neil Shapiro 				rl->lr_attrs = NULL;
1310e92d3f3fSGregory Neil Shapiro 			}
1311605302a5SGregory Neil Shapiro 
1312605302a5SGregory Neil Shapiro 			/* Reset rlidx as new items may have been added */
1313605302a5SGregory Neil Shapiro 			rlidx = -1;
131440266059SGregory Neil Shapiro 		}
131540266059SGregory Neil Shapiro 	}
131640266059SGregory Neil Shapiro 	return statp;
131740266059SGregory Neil Shapiro }
131840266059SGregory Neil Shapiro 
131940266059SGregory Neil Shapiro /*
132040266059SGregory Neil Shapiro **  SM_LDAP_CLOSE -- close LDAP connection
132140266059SGregory Neil Shapiro **
132240266059SGregory Neil Shapiro **	Parameters:
132340266059SGregory Neil Shapiro **		lmap -- LDAP map information
132440266059SGregory Neil Shapiro **
132540266059SGregory Neil Shapiro **	Returns:
132640266059SGregory Neil Shapiro **		None.
132740266059SGregory Neil Shapiro **
132840266059SGregory Neil Shapiro */
132940266059SGregory Neil Shapiro 
133040266059SGregory Neil Shapiro void
133140266059SGregory Neil Shapiro sm_ldap_close(lmap)
133240266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
133340266059SGregory Neil Shapiro {
133440266059SGregory Neil Shapiro 	if (lmap->ldap_ld == NULL)
133540266059SGregory Neil Shapiro 		return;
133640266059SGregory Neil Shapiro 
133740266059SGregory Neil Shapiro 	if (lmap->ldap_pid == getpid())
133840266059SGregory Neil Shapiro 		ldap_unbind(lmap->ldap_ld);
133940266059SGregory Neil Shapiro 	lmap->ldap_ld = NULL;
134040266059SGregory Neil Shapiro 	lmap->ldap_pid = 0;
134140266059SGregory Neil Shapiro }
134240266059SGregory Neil Shapiro 
134340266059SGregory Neil Shapiro /*
134440266059SGregory Neil Shapiro **  SM_LDAP_SETOPTS -- set LDAP options
134540266059SGregory Neil Shapiro **
134640266059SGregory Neil Shapiro **	Parameters:
134740266059SGregory Neil Shapiro **		ld -- LDAP session handle
134840266059SGregory Neil Shapiro **		lmap -- LDAP map information
134940266059SGregory Neil Shapiro **
135040266059SGregory Neil Shapiro **	Returns:
135140266059SGregory Neil Shapiro **		None.
135240266059SGregory Neil Shapiro **
135340266059SGregory Neil Shapiro */
135440266059SGregory Neil Shapiro 
135540266059SGregory Neil Shapiro void
135640266059SGregory Neil Shapiro sm_ldap_setopts(ld, lmap)
135740266059SGregory Neil Shapiro 	LDAP *ld;
135840266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
135940266059SGregory Neil Shapiro {
136040266059SGregory Neil Shapiro # if USE_LDAP_SET_OPTION
1361605302a5SGregory Neil Shapiro 	if (lmap->ldap_version != 0)
1362605302a5SGregory Neil Shapiro 	{
1363605302a5SGregory Neil Shapiro 		ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
1364605302a5SGregory Neil Shapiro 				&lmap->ldap_version);
1365605302a5SGregory Neil Shapiro 	}
136640266059SGregory Neil Shapiro 	ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref);
136740266059SGregory Neil Shapiro 	if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options))
136840266059SGregory Neil Shapiro 		ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
136940266059SGregory Neil Shapiro 	else
137040266059SGregory Neil Shapiro 		ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
137140266059SGregory Neil Shapiro 	ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit);
137240266059SGregory Neil Shapiro 	ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit);
1373ffb83623SGregory Neil Shapiro # if _FFR_LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT)
1374ffb83623SGregory Neil Shapiro 	ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &lmap->ldap_networktmo);
1375ffb83623SGregory Neil Shapiro # endif /* _FFR_LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) */
1376959366dcSGregory Neil Shapiro #  ifdef LDAP_OPT_RESTART
1377959366dcSGregory Neil Shapiro 	ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON);
1378959366dcSGregory Neil Shapiro #  endif /* LDAP_OPT_RESTART */
137940266059SGregory Neil Shapiro # else /* USE_LDAP_SET_OPTION */
138040266059SGregory Neil Shapiro 	/* From here on in we can use ldap internal timelimits */
138140266059SGregory Neil Shapiro 	ld->ld_deref = lmap->ldap_deref;
138240266059SGregory Neil Shapiro 	ld->ld_options = lmap->ldap_options;
138340266059SGregory Neil Shapiro 	ld->ld_sizelimit = lmap->ldap_sizelimit;
138440266059SGregory Neil Shapiro 	ld->ld_timelimit = lmap->ldap_timelimit;
138540266059SGregory Neil Shapiro # endif /* USE_LDAP_SET_OPTION */
138640266059SGregory Neil Shapiro }
138740266059SGregory Neil Shapiro 
138840266059SGregory Neil Shapiro /*
138940266059SGregory Neil Shapiro **  SM_LDAP_GETERRNO -- get ldap errno value
139040266059SGregory Neil Shapiro **
139140266059SGregory Neil Shapiro **	Parameters:
139240266059SGregory Neil Shapiro **		ld -- LDAP session handle
139340266059SGregory Neil Shapiro **
139440266059SGregory Neil Shapiro **	Returns:
139540266059SGregory Neil Shapiro **		LDAP errno.
139640266059SGregory Neil Shapiro **
139740266059SGregory Neil Shapiro */
139840266059SGregory Neil Shapiro 
139940266059SGregory Neil Shapiro int
140040266059SGregory Neil Shapiro sm_ldap_geterrno(ld)
140140266059SGregory Neil Shapiro 	LDAP *ld;
140240266059SGregory Neil Shapiro {
140340266059SGregory Neil Shapiro 	int err = LDAP_SUCCESS;
140440266059SGregory Neil Shapiro 
140540266059SGregory Neil Shapiro # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3
140640266059SGregory Neil Shapiro 	(void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err);
140740266059SGregory Neil Shapiro # else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */
140840266059SGregory Neil Shapiro #  ifdef LDAP_OPT_SIZELIMIT
140940266059SGregory Neil Shapiro 	err = ldap_get_lderrno(ld, NULL, NULL);
141040266059SGregory Neil Shapiro #  else /* LDAP_OPT_SIZELIMIT */
141140266059SGregory Neil Shapiro 	err = ld->ld_errno;
141240266059SGregory Neil Shapiro 
141340266059SGregory Neil Shapiro 	/*
141440266059SGregory Neil Shapiro 	**  Reset value to prevent lingering LDAP_DECODING_ERROR due to
141540266059SGregory Neil Shapiro 	**  OpenLDAP 1.X's hack (see above)
141640266059SGregory Neil Shapiro 	*/
141740266059SGregory Neil Shapiro 
141840266059SGregory Neil Shapiro 	ld->ld_errno = LDAP_SUCCESS;
141940266059SGregory Neil Shapiro #  endif /* LDAP_OPT_SIZELIMIT */
142040266059SGregory Neil Shapiro # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */
142140266059SGregory Neil Shapiro 	return err;
142240266059SGregory Neil Shapiro }
142340266059SGregory Neil Shapiro # endif /* LDAPMAP */
1424