xref: /freebsd/contrib/sendmail/libsm/ldap.c (revision d39bd2c1388b520fcba9abed1932acacead60fba)
140266059SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro  * Copyright (c) 2001-2009 Proofpoint, 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>
144313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: ldap.c,v 1.86 2013-11-22 20:51:43 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>
3040266059SGregory Neil Shapiro # include <sm/sysexits.h>
312fb4f839SGregory Neil Shapiro # include <sm/sendmail.h>
3240266059SGregory Neil Shapiro 
3340266059SGregory Neil Shapiro SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap",
3440266059SGregory Neil Shapiro 	"@(#)$Debug: sm_trace_ldap - trace LDAP operations $");
3540266059SGregory Neil Shapiro 
36b6bacd31SGregory Neil Shapiro static bool	sm_ldap_has_objectclass __P((SM_LDAP_STRUCT *, LDAPMessage *, char *));
37b6bacd31SGregory Neil Shapiro static SM_LDAP_RECURSE_ENTRY *sm_ldap_add_recurse __P((SM_LDAP_RECURSE_LIST **, char *, int, SM_RPOOL_T *));
3840266059SGregory Neil Shapiro 
39*d39bd2c1SGregory Neil Shapiro static char *sm_ldap_geterror __P((LDAP *));
40*d39bd2c1SGregory Neil Shapiro 
4140266059SGregory Neil Shapiro /*
4240266059SGregory Neil Shapiro **  SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT
4340266059SGregory Neil Shapiro **
4440266059SGregory Neil Shapiro **	Parameters:
4540266059SGregory Neil Shapiro **		lmap -- pointer to SM_LDAP_STRUCT to clear
4640266059SGregory Neil Shapiro **
4740266059SGregory Neil Shapiro **	Returns:
4840266059SGregory Neil Shapiro **		None.
4940266059SGregory Neil Shapiro **
5040266059SGregory Neil Shapiro */
5140266059SGregory Neil Shapiro 
524e4196cbSGregory Neil Shapiro # if _FFR_LDAP_VERSION
534e4196cbSGregory Neil Shapiro #  if defined(LDAP_VERSION_MAX) && _FFR_LDAP_VERSION > LDAP_VERSION_MAX
54*d39bd2c1SGregory Neil Shapiro #   error "_FFR_LDAP_VERSION > LDAP_VERSION_MAX"
555b0945b5SGregory Neil Shapiro #  endif
564e4196cbSGregory Neil Shapiro #  if defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN
57*d39bd2c1SGregory Neil Shapiro #   error "_FFR_LDAP_VERSION < LDAP_VERSION_MAX"
585b0945b5SGregory Neil Shapiro #  endif
594e4196cbSGregory Neil Shapiro #  define SM_LDAP_VERSION_DEFAULT	_FFR_LDAP_VERSION
604e4196cbSGregory Neil Shapiro # else /* _FFR_LDAP_VERSION */
614e4196cbSGregory Neil Shapiro #  define SM_LDAP_VERSION_DEFAULT	0
624e4196cbSGregory Neil Shapiro # endif /* _FFR_LDAP_VERSION */
634e4196cbSGregory Neil Shapiro 
6440266059SGregory Neil Shapiro void
sm_ldap_clear(lmap)6540266059SGregory Neil Shapiro sm_ldap_clear(lmap)
6640266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
6740266059SGregory Neil Shapiro {
6840266059SGregory Neil Shapiro 	if (lmap == NULL)
6940266059SGregory Neil Shapiro 		return;
7040266059SGregory Neil Shapiro 
71e92d3f3fSGregory Neil Shapiro 	lmap->ldap_host = NULL;
7240266059SGregory Neil Shapiro 	lmap->ldap_port = LDAP_PORT;
73e92d3f3fSGregory Neil Shapiro 	lmap->ldap_uri = NULL;
744e4196cbSGregory Neil Shapiro 	lmap->ldap_version = SM_LDAP_VERSION_DEFAULT;
7540266059SGregory Neil Shapiro 	lmap->ldap_deref = LDAP_DEREF_NEVER;
7640266059SGregory Neil Shapiro 	lmap->ldap_timelimit = LDAP_NO_LIMIT;
7740266059SGregory Neil Shapiro 	lmap->ldap_sizelimit = LDAP_NO_LIMIT;
7840266059SGregory Neil Shapiro # ifdef LDAP_REFERRALS
7940266059SGregory Neil Shapiro 	lmap->ldap_options = LDAP_OPT_REFERRALS;
805b0945b5SGregory Neil Shapiro # else
8140266059SGregory Neil Shapiro 	lmap->ldap_options = 0;
825b0945b5SGregory Neil Shapiro # endif
8340266059SGregory Neil Shapiro 	lmap->ldap_attrsep = '\0';
84*d39bd2c1SGregory Neil Shapiro # if LDAP_NETWORK_TIMEOUT
85*d39bd2c1SGregory Neil Shapiro 	lmap->ldap_networktmo = 0;
86*d39bd2c1SGregory Neil Shapiro # endif
8740266059SGregory Neil Shapiro 	lmap->ldap_binddn = NULL;
8840266059SGregory Neil Shapiro 	lmap->ldap_secret = NULL;
8940266059SGregory Neil Shapiro 	lmap->ldap_method = LDAP_AUTH_SIMPLE;
9040266059SGregory Neil Shapiro 	lmap->ldap_base = NULL;
9140266059SGregory Neil Shapiro 	lmap->ldap_scope = LDAP_SCOPE_SUBTREE;
9240266059SGregory Neil Shapiro 	lmap->ldap_attrsonly = LDAPMAP_FALSE;
9340266059SGregory Neil Shapiro 	lmap->ldap_timeout.tv_sec = 0;
9440266059SGregory Neil Shapiro 	lmap->ldap_timeout.tv_usec = 0;
9540266059SGregory Neil Shapiro 	lmap->ldap_ld = NULL;
9640266059SGregory Neil Shapiro 	lmap->ldap_filter = NULL;
9740266059SGregory Neil Shapiro 	lmap->ldap_attr[0] = NULL;
98605302a5SGregory Neil Shapiro 	lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE;
99605302a5SGregory Neil Shapiro 	lmap->ldap_attr_needobjclass[0] = NULL;
10040266059SGregory Neil Shapiro 	lmap->ldap_res = NULL;
10140266059SGregory Neil Shapiro 	lmap->ldap_next = NULL;
10240266059SGregory Neil Shapiro 	lmap->ldap_pid = 0;
103d0cef73dSGregory Neil Shapiro 	lmap->ldap_multi_args = false;
10440266059SGregory Neil Shapiro }
10540266059SGregory Neil Shapiro 
1065b0945b5SGregory Neil Shapiro # if _FFR_SM_LDAP_DBG && defined(LBER_OPT_LOG_PRINT_FN)
1075b0945b5SGregory Neil Shapiro static void ldap_debug_cb __P((const char *msg));
1085b0945b5SGregory Neil Shapiro 
1095b0945b5SGregory Neil Shapiro static void
ldap_debug_cb(msg)1105b0945b5SGregory Neil Shapiro ldap_debug_cb(msg)
1115b0945b5SGregory Neil Shapiro 	const char *msg;
1125b0945b5SGregory Neil Shapiro {
1135b0945b5SGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 4))
1145b0945b5SGregory Neil Shapiro 		sm_dprintf("%s", msg);
1155b0945b5SGregory Neil Shapiro }
1165b0945b5SGregory Neil Shapiro # endif /* _FFR_SM_LDAP_DBG && defined(LBER_OPT_LOG_PRINT_FN) */
1175b0945b5SGregory Neil Shapiro 
1185b0945b5SGregory Neil Shapiro 
1195b0945b5SGregory Neil Shapiro # if LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT)
1205b0945b5SGregory Neil Shapiro #  define SET_LDAP_TMO(ld, lmap)					\
1215b0945b5SGregory Neil Shapiro 	do								\
1225b0945b5SGregory Neil Shapiro 	{								\
1235b0945b5SGregory Neil Shapiro 		if (lmap->ldap_networktmo > 0)				\
1245b0945b5SGregory Neil Shapiro 		{							\
1255b0945b5SGregory Neil Shapiro 			struct timeval tmo;				\
1265b0945b5SGregory Neil Shapiro 									\
1275b0945b5SGregory Neil Shapiro 			if (sm_debug_active(&SmLDAPTrace, 9))		\
1285b0945b5SGregory Neil Shapiro 				sm_dprintf("ldap_networktmo=%d\n",	\
1295b0945b5SGregory Neil Shapiro 					lmap->ldap_networktmo);		\
1305b0945b5SGregory Neil Shapiro 			tmo.tv_sec = lmap->ldap_networktmo;		\
1315b0945b5SGregory Neil Shapiro 			tmo.tv_usec = 0;				\
1325b0945b5SGregory Neil Shapiro 			ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tmo); \
1335b0945b5SGregory Neil Shapiro 		}	\
1345b0945b5SGregory Neil Shapiro 	} while (0)
1355b0945b5SGregory Neil Shapiro # else /* LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) */
1365b0945b5SGregory Neil Shapiro #  define SET_LDAP_TMO(ld, lmap)
1375b0945b5SGregory Neil Shapiro # endif /* LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) */
1385b0945b5SGregory Neil Shapiro 
1395b0945b5SGregory Neil Shapiro /*
1405b0945b5SGregory Neil Shapiro **  SM_LDAP_SETOPTSG -- set some (global) LDAP options
1415b0945b5SGregory Neil Shapiro **
1425b0945b5SGregory Neil Shapiro **	Parameters:
1435b0945b5SGregory Neil Shapiro **		lmap -- LDAP map information
1445b0945b5SGregory Neil Shapiro **
1455b0945b5SGregory Neil Shapiro **	Returns:
1465b0945b5SGregory Neil Shapiro **		None.
1475b0945b5SGregory Neil Shapiro **
1485b0945b5SGregory Neil Shapiro */
1495b0945b5SGregory Neil Shapiro 
1505b0945b5SGregory Neil Shapiro # if _FFR_SM_LDAP_DBG
1515b0945b5SGregory Neil Shapiro static bool dbg_init = false;
1525b0945b5SGregory Neil Shapiro # endif
1535b0945b5SGregory Neil Shapiro # if SM_CONF_LDAP_INITIALIZE
1545b0945b5SGregory Neil Shapiro static void sm_ldap_setoptsg __P((SM_LDAP_STRUCT *lmap));
1555b0945b5SGregory Neil Shapiro static void
sm_ldap_setoptsg(lmap)1565b0945b5SGregory Neil Shapiro sm_ldap_setoptsg(lmap)
1575b0945b5SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
1585b0945b5SGregory Neil Shapiro {
1595b0945b5SGregory Neil Shapiro #  if USE_LDAP_SET_OPTION
1605b0945b5SGregory Neil Shapiro 
1615b0945b5SGregory Neil Shapiro 	SET_LDAP_TMO(NULL, lmap);
1625b0945b5SGregory Neil Shapiro 
1635b0945b5SGregory Neil Shapiro #   if _FFR_SM_LDAP_DBG
1645b0945b5SGregory Neil Shapiro 	if (!dbg_init && sm_debug_active(&SmLDAPTrace, 1) &&
1655b0945b5SGregory Neil Shapiro 	    lmap->ldap_debug != 0)
1665b0945b5SGregory Neil Shapiro 	{
1675b0945b5SGregory Neil Shapiro 		int r;
1685b0945b5SGregory Neil Shapiro #    if defined(LBER_OPT_LOG_PRINT_FN)
1695b0945b5SGregory Neil Shapiro 		r = ber_set_option(NULL, LBER_OPT_LOG_PRINT_FN, ldap_debug_cb);
1705b0945b5SGregory Neil Shapiro #    endif
1715b0945b5SGregory Neil Shapiro 		if (sm_debug_active(&SmLDAPTrace, 9))
1725b0945b5SGregory Neil Shapiro 			sm_dprintf("ldap_debug0=%d\n", lmap->ldap_debug);
1735b0945b5SGregory Neil Shapiro 		r = ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL,
1745b0945b5SGregory Neil Shapiro 				&(lmap->ldap_debug));
1755b0945b5SGregory Neil Shapiro 		if (sm_debug_active(&SmLDAPTrace, 9) && r != LDAP_OPT_SUCCESS)
1765b0945b5SGregory Neil Shapiro 			sm_dprintf("ber_set_option=%d\n", r);
1775b0945b5SGregory Neil Shapiro 		r = ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL,
1785b0945b5SGregory Neil Shapiro 				&(lmap->ldap_debug));
1795b0945b5SGregory Neil Shapiro 		if (sm_debug_active(&SmLDAPTrace, 9) && r != LDAP_OPT_SUCCESS)
1805b0945b5SGregory Neil Shapiro 			sm_dprintf("ldap_set_option=%d\n", r);
1815b0945b5SGregory Neil Shapiro 		dbg_init = true;
1825b0945b5SGregory Neil Shapiro 	}
1835b0945b5SGregory Neil Shapiro #   endif /* _FFR_SM_LDAP_DBG */
1845b0945b5SGregory Neil Shapiro #  endif /* USE_LDAP_SET_OPTION */
1855b0945b5SGregory Neil Shapiro }
1865b0945b5SGregory Neil Shapiro # endif /* SM_CONF_LDAP_INITIALIZE */
1875b0945b5SGregory Neil Shapiro 
1885b0945b5SGregory Neil Shapiro /*
1895b0945b5SGregory Neil Shapiro **  SM_LDAP_SETOPTS -- set LDAP options
1905b0945b5SGregory Neil Shapiro **
1915b0945b5SGregory Neil Shapiro **	Parameters:
1925b0945b5SGregory Neil Shapiro **		ld -- LDAP session handle
1935b0945b5SGregory Neil Shapiro **		lmap -- LDAP map information
1945b0945b5SGregory Neil Shapiro **
1955b0945b5SGregory Neil Shapiro **	Returns:
1965b0945b5SGregory Neil Shapiro **		None.
1975b0945b5SGregory Neil Shapiro **
1985b0945b5SGregory Neil Shapiro */
1995b0945b5SGregory Neil Shapiro 
2005b0945b5SGregory Neil Shapiro void
sm_ldap_setopts(ld,lmap)2015b0945b5SGregory Neil Shapiro sm_ldap_setopts(ld, lmap)
2025b0945b5SGregory Neil Shapiro 	LDAP *ld;
2035b0945b5SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
2045b0945b5SGregory Neil Shapiro {
2055b0945b5SGregory Neil Shapiro # if USE_LDAP_SET_OPTION
2065b0945b5SGregory Neil Shapiro 	if (lmap->ldap_version != 0)
2075b0945b5SGregory Neil Shapiro 	{
2085b0945b5SGregory Neil Shapiro 		ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
2095b0945b5SGregory Neil Shapiro 				&lmap->ldap_version);
2105b0945b5SGregory Neil Shapiro 	}
2115b0945b5SGregory Neil Shapiro 	ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref);
2125b0945b5SGregory Neil Shapiro 	if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options))
2135b0945b5SGregory Neil Shapiro 		ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
2145b0945b5SGregory Neil Shapiro 	else
2155b0945b5SGregory Neil Shapiro 		ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
2165b0945b5SGregory Neil Shapiro 	ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit);
2175b0945b5SGregory Neil Shapiro 	ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit);
2185b0945b5SGregory Neil Shapiro 	SET_LDAP_TMO(ld, lmap);
2195b0945b5SGregory Neil Shapiro #  if _FFR_SM_LDAP_DBG
2205b0945b5SGregory Neil Shapiro 	if ((!dbg_init || ld != NULL) && sm_debug_active(&SmLDAPTrace, 1)
2215b0945b5SGregory Neil Shapiro 	    && lmap->ldap_debug > 0)
2225b0945b5SGregory Neil Shapiro 	{
2235b0945b5SGregory Neil Shapiro 		int r;
2245b0945b5SGregory Neil Shapiro 
2255b0945b5SGregory Neil Shapiro 		if (sm_debug_active(&SmLDAPTrace, 9))
2265b0945b5SGregory Neil Shapiro 			sm_dprintf("ldap_debug=%d, dbg_init=%d\n",
2275b0945b5SGregory Neil Shapiro 				lmap->ldap_debug, dbg_init);
2285b0945b5SGregory Neil Shapiro 		r = ldap_set_option(ld, LDAP_OPT_DEBUG_LEVEL,
2295b0945b5SGregory Neil Shapiro 				&(lmap->ldap_debug));
2305b0945b5SGregory Neil Shapiro 		if (sm_debug_active(&SmLDAPTrace, 9) && r != LDAP_OPT_SUCCESS)
2315b0945b5SGregory Neil Shapiro 			sm_dprintf("ldap_set_option=%d\n", r);
2325b0945b5SGregory Neil Shapiro 	}
2335b0945b5SGregory Neil Shapiro #  endif /* _FFR_SM_LDAP_DBG */
2345b0945b5SGregory Neil Shapiro #  ifdef LDAP_OPT_RESTART
2355b0945b5SGregory Neil Shapiro 	ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON);
2365b0945b5SGregory Neil Shapiro #  endif
237*d39bd2c1SGregory Neil Shapiro #  if _FFR_TESTS
238*d39bd2c1SGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 101))
239*d39bd2c1SGregory Neil Shapiro 	{
240*d39bd2c1SGregory Neil Shapiro 		char *cert;
241*d39bd2c1SGregory Neil Shapiro 		char buf[PATH_MAX];
242*d39bd2c1SGregory Neil Shapiro 
243*d39bd2c1SGregory Neil Shapiro 		cert = getcwd(buf, sizeof(buf));
244*d39bd2c1SGregory Neil Shapiro 		if (NULL != cert)
245*d39bd2c1SGregory Neil Shapiro 		{
246*d39bd2c1SGregory Neil Shapiro 			int r;
247*d39bd2c1SGregory Neil Shapiro 
248*d39bd2c1SGregory Neil Shapiro 			(void) sm_strlcat(buf, "/ldaps.pem", sizeof(buf));
249*d39bd2c1SGregory Neil Shapiro 			r = ldap_set_option(ld, LDAP_OPT_X_TLS_CACERTFILE, cert);
250*d39bd2c1SGregory Neil Shapiro 			sm_dprintf("LDAP_OPT_X_TLS_CACERTFILE(%s)=%d\n", cert, r);
251*d39bd2c1SGregory Neil Shapiro 		}
252*d39bd2c1SGregory Neil Shapiro 	}
253*d39bd2c1SGregory Neil Shapiro #  endif /* _FFR_TESTS */
2545b0945b5SGregory Neil Shapiro 
2555b0945b5SGregory Neil Shapiro # else /* USE_LDAP_SET_OPTION */
2565b0945b5SGregory Neil Shapiro 	/* From here on in we can use ldap internal timelimits */
2575b0945b5SGregory Neil Shapiro 	ld->ld_deref = lmap->ldap_deref;
2585b0945b5SGregory Neil Shapiro 	ld->ld_options = lmap->ldap_options;
2595b0945b5SGregory Neil Shapiro 	ld->ld_sizelimit = lmap->ldap_sizelimit;
2605b0945b5SGregory Neil Shapiro 	ld->ld_timelimit = lmap->ldap_timelimit;
2615b0945b5SGregory Neil Shapiro # endif /* USE_LDAP_SET_OPTION */
2625b0945b5SGregory Neil Shapiro }
2635b0945b5SGregory Neil Shapiro 
26440266059SGregory Neil Shapiro /*
26540266059SGregory Neil Shapiro **  SM_LDAP_START -- actually connect to an LDAP server
26640266059SGregory Neil Shapiro **
26740266059SGregory Neil Shapiro **	Parameters:
26840266059SGregory Neil Shapiro **		name -- name of map for debug output.
26940266059SGregory Neil Shapiro **		lmap -- the LDAP map being opened.
27040266059SGregory Neil Shapiro **
27140266059SGregory Neil Shapiro **	Returns:
27240266059SGregory Neil Shapiro **		true if connection is successful, false otherwise.
27340266059SGregory Neil Shapiro **
27440266059SGregory Neil Shapiro **	Side Effects:
27540266059SGregory Neil Shapiro **		Populates lmap->ldap_ld.
27640266059SGregory Neil Shapiro */
27740266059SGregory Neil Shapiro 
2785b0945b5SGregory Neil Shapiro # if !USE_LDAP_INIT || !LDAP_NETWORK_TIMEOUT
27940266059SGregory Neil Shapiro static jmp_buf	LDAPTimeout;
2805b0945b5SGregory Neil Shapiro static void	ldaptimeout __P((int));
28140266059SGregory Neil Shapiro 
2825b0945b5SGregory Neil Shapiro /* ARGSUSED */
2835b0945b5SGregory Neil Shapiro static void
ldaptimeout(unused)2845b0945b5SGregory Neil Shapiro ldaptimeout(unused)
2855b0945b5SGregory Neil Shapiro 	int unused;
2865b0945b5SGregory Neil Shapiro {
2875b0945b5SGregory Neil Shapiro 	/*
2885b0945b5SGregory Neil Shapiro 	**  NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
2895b0945b5SGregory Neil Shapiro 	**	ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
2905b0945b5SGregory Neil Shapiro 	**	DOING.
2915b0945b5SGregory Neil Shapiro 	*/
2925b0945b5SGregory Neil Shapiro 
2935b0945b5SGregory Neil Shapiro 	errno = ETIMEDOUT;
2945b0945b5SGregory Neil Shapiro 	longjmp(LDAPTimeout, 1);
2955b0945b5SGregory Neil Shapiro }
2965b0945b5SGregory Neil Shapiro 
2975b0945b5SGregory Neil Shapiro 
2985b0945b5SGregory Neil Shapiro #define SM_LDAP_SETTIMEOUT(to, where)					\
29940266059SGregory Neil Shapiro do									\
30040266059SGregory Neil Shapiro {									\
30140266059SGregory Neil Shapiro 	if (to != 0)							\
30240266059SGregory Neil Shapiro 	{								\
30340266059SGregory Neil Shapiro 		if (setjmp(LDAPTimeout) != 0)				\
30440266059SGregory Neil Shapiro 		{							\
3055b0945b5SGregory Neil Shapiro 			if (sm_debug_active(&SmLDAPTrace, 9))		\
3065b0945b5SGregory Neil Shapiro 				sm_dprintf("ldap_settimeout(%s)=triggered\n",\
3075b0945b5SGregory Neil Shapiro 					where);				\
30840266059SGregory Neil Shapiro 			errno = ETIMEDOUT;				\
30940266059SGregory Neil Shapiro 			return false;					\
31040266059SGregory Neil Shapiro 		}							\
31140266059SGregory Neil Shapiro 		ev = sm_setevent(to, ldaptimeout, 0);			\
31240266059SGregory Neil Shapiro 	}								\
31340266059SGregory Neil Shapiro } while (0)
31440266059SGregory Neil Shapiro 
31540266059SGregory Neil Shapiro #define SM_LDAP_CLEARTIMEOUT()						\
31640266059SGregory Neil Shapiro do									\
31740266059SGregory Neil Shapiro {									\
31840266059SGregory Neil Shapiro 	if (ev != NULL)							\
31940266059SGregory Neil Shapiro 		sm_clrevent(ev);					\
32040266059SGregory Neil Shapiro } while (0)
3215b0945b5SGregory Neil Shapiro # endif /* !USE_LDAP_INIT || !LDAP_NETWORK_TIMEOUT */
32240266059SGregory Neil Shapiro 
32340266059SGregory Neil Shapiro bool
sm_ldap_start(name,lmap)32440266059SGregory Neil Shapiro sm_ldap_start(name, lmap)
32540266059SGregory Neil Shapiro 	char *name;
32640266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
32740266059SGregory Neil Shapiro {
328b6bacd31SGregory Neil Shapiro 	int save_errno = 0;
329e92d3f3fSGregory Neil Shapiro 	char *id;
330*d39bd2c1SGregory Neil Shapiro 	char *errmsg;
3315b0945b5SGregory Neil Shapiro # if !USE_LDAP_INIT || !LDAP_NETWORK_TIMEOUT
33240266059SGregory Neil Shapiro 	SM_EVENT *ev = NULL;
3335b0945b5SGregory Neil Shapiro # endif
334e92d3f3fSGregory Neil Shapiro 	LDAP *ld = NULL;
3355b0945b5SGregory Neil Shapiro 	struct timeval tmo;
3365b0945b5SGregory Neil Shapiro 	int msgid, err, r;
33740266059SGregory Neil Shapiro 
338*d39bd2c1SGregory Neil Shapiro 	errmsg = NULL;
33940266059SGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 2))
34040266059SGregory Neil Shapiro 		sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name);
34140266059SGregory Neil Shapiro 
342e92d3f3fSGregory Neil Shapiro 	if (lmap->ldap_host != NULL)
343e92d3f3fSGregory Neil Shapiro 		id = lmap->ldap_host;
344e92d3f3fSGregory Neil Shapiro 	else if (lmap->ldap_uri != NULL)
345e92d3f3fSGregory Neil Shapiro 		id = lmap->ldap_uri;
346605302a5SGregory Neil Shapiro 	else
347e92d3f3fSGregory Neil Shapiro 		id = "localhost";
348e92d3f3fSGregory Neil Shapiro 
349e92d3f3fSGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 9))
350e92d3f3fSGregory Neil Shapiro 	{
351e92d3f3fSGregory Neil Shapiro 		/* Don't print a port number for LDAP URIs */
352e92d3f3fSGregory Neil Shapiro 		if (lmap->ldap_uri != NULL)
353e92d3f3fSGregory Neil Shapiro 			sm_dprintf("ldapmap_start(%s)\n", id);
354e92d3f3fSGregory Neil Shapiro 		else
355e92d3f3fSGregory Neil Shapiro 			sm_dprintf("ldapmap_start(%s, %d)\n", id,
356e92d3f3fSGregory Neil Shapiro 				   lmap->ldap_port);
357e92d3f3fSGregory Neil Shapiro 	}
358e92d3f3fSGregory Neil Shapiro 
359e92d3f3fSGregory Neil Shapiro 	if (lmap->ldap_uri != NULL)
360e92d3f3fSGregory Neil Shapiro 	{
361e92d3f3fSGregory Neil Shapiro # if SM_CONF_LDAP_INITIALIZE
3625b0945b5SGregory Neil Shapiro 		if (sm_debug_active(&SmLDAPTrace, 9))
3635b0945b5SGregory Neil Shapiro 			sm_dprintf("ldap_initialize(%s)\n", lmap->ldap_uri);
364e92d3f3fSGregory Neil Shapiro 		/* LDAP server supports URIs so use them directly */
365e92d3f3fSGregory Neil Shapiro 		save_errno = ldap_initialize(&ld, lmap->ldap_uri);
3665b0945b5SGregory Neil Shapiro 		if (sm_debug_active(&SmLDAPTrace, 9))
3675b0945b5SGregory Neil Shapiro 			sm_dprintf("ldap_initialize(%s)=%d, ld=%p\n", lmap->ldap_uri, save_errno, ld);
3685b0945b5SGregory Neil Shapiro 		sm_ldap_setoptsg(lmap);
3695b0945b5SGregory Neil Shapiro 
370e92d3f3fSGregory Neil Shapiro # else /* SM_CONF_LDAP_INITIALIZE */
371e92d3f3fSGregory Neil Shapiro 		LDAPURLDesc *ludp = NULL;
372e92d3f3fSGregory Neil Shapiro 
373e92d3f3fSGregory Neil Shapiro 		/* Blast apart URL and use the ldap_init/ldap_open below */
374e92d3f3fSGregory Neil Shapiro 		err = ldap_url_parse(lmap->ldap_uri, &ludp);
375e92d3f3fSGregory Neil Shapiro 		if (err != 0)
376e92d3f3fSGregory Neil Shapiro 		{
377e92d3f3fSGregory Neil Shapiro 			errno = err + E_LDAPURLBASE;
378e92d3f3fSGregory Neil Shapiro 			return false;
379e92d3f3fSGregory Neil Shapiro 		}
380e92d3f3fSGregory Neil Shapiro 		lmap->ldap_host = sm_strdup_x(ludp->lud_host);
381e92d3f3fSGregory Neil Shapiro 		if (lmap->ldap_host == NULL)
382e92d3f3fSGregory Neil Shapiro 		{
383e92d3f3fSGregory Neil Shapiro 			save_errno = errno;
384e92d3f3fSGregory Neil Shapiro 			ldap_free_urldesc(ludp);
385e92d3f3fSGregory Neil Shapiro 			errno = save_errno;
386e92d3f3fSGregory Neil Shapiro 			return false;
387e92d3f3fSGregory Neil Shapiro 		}
388e92d3f3fSGregory Neil Shapiro 		lmap->ldap_port = ludp->lud_port;
389e92d3f3fSGregory Neil Shapiro 		ldap_free_urldesc(ludp);
390e92d3f3fSGregory Neil Shapiro # endif /* SM_CONF_LDAP_INITIALIZE */
391e92d3f3fSGregory Neil Shapiro 	}
392e92d3f3fSGregory Neil Shapiro 
393e92d3f3fSGregory Neil Shapiro 	if (ld == NULL)
394e92d3f3fSGregory Neil Shapiro 	{
395e92d3f3fSGregory Neil Shapiro # if USE_LDAP_INIT
3965b0945b5SGregory Neil Shapiro 		if (sm_debug_active(&SmLDAPTrace, 9))
3975b0945b5SGregory Neil Shapiro 			sm_dprintf("ldap_init(%s, %d)\n", lmap->ldap_host, lmap->ldap_port);
398e92d3f3fSGregory Neil Shapiro 		ld = ldap_init(lmap->ldap_host, lmap->ldap_port);
39940266059SGregory Neil Shapiro 		save_errno = errno;
4005b0945b5SGregory Neil Shapiro 
40140266059SGregory Neil Shapiro # else /* USE_LDAP_INIT */
40240266059SGregory Neil Shapiro 		/*
40340266059SGregory Neil Shapiro 		**  If using ldap_open(), the actual connection to the server
40440266059SGregory Neil Shapiro 		**  happens now so we need the timeout here.  For ldap_init(),
40540266059SGregory Neil Shapiro 		**  the connection happens at bind time.
40640266059SGregory Neil Shapiro 		*/
40740266059SGregory Neil Shapiro 
4085b0945b5SGregory Neil Shapiro 		if (sm_debug_active(&SmLDAPTrace, 9))
4095b0945b5SGregory Neil Shapiro 			sm_dprintf("ldap_open(%s, %d)\n", lmap->ldap_host, lmap->ldap_port);
4105b0945b5SGregory Neil Shapiro 
4115b0945b5SGregory Neil Shapiro 		SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec, "ldap_open");
412e92d3f3fSGregory Neil Shapiro 		ld = ldap_open(lmap->ldap_host, lmap->ldap_port);
41340266059SGregory Neil Shapiro 		save_errno = errno;
41440266059SGregory Neil Shapiro 
41540266059SGregory Neil Shapiro 		/* clear the event if it has not sprung */
41640266059SGregory Neil Shapiro 		SM_LDAP_CLEARTIMEOUT();
41740266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */
418e92d3f3fSGregory Neil Shapiro 	}
41940266059SGregory Neil Shapiro 
42040266059SGregory Neil Shapiro 	errno = save_errno;
42140266059SGregory Neil Shapiro 	if (ld == NULL)
4225b0945b5SGregory Neil Shapiro 	{
4235b0945b5SGregory Neil Shapiro 		if (sm_debug_active(&SmLDAPTrace, 7))
4245b0945b5SGregory Neil Shapiro 			sm_dprintf("FAIL: ldap_open(%s, %d)=%d\n", lmap->ldap_host, lmap->ldap_port, save_errno);
42540266059SGregory Neil Shapiro 		return false;
4265b0945b5SGregory Neil Shapiro 	}
42740266059SGregory Neil Shapiro 
42840266059SGregory Neil Shapiro 	sm_ldap_setopts(ld, lmap);
4295b0945b5SGregory Neil Shapiro # if USE_LDAP_INIT && !LDAP_NETWORK_TIMEOUT
43040266059SGregory Neil Shapiro 	/*
43140266059SGregory Neil Shapiro 	**  If using ldap_init(), the actual connection to the server
43240266059SGregory Neil Shapiro 	**  happens at ldap_bind_s() so we need the timeout here.
43340266059SGregory Neil Shapiro 	*/
43440266059SGregory Neil Shapiro 
4355b0945b5SGregory Neil Shapiro 	SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec, "ldap_bind");
4365b0945b5SGregory Neil Shapiro # endif /* USE_LDAP_INIT && !LDAP_NETWORK_TIMEOUT */
43740266059SGregory Neil Shapiro 
43840266059SGregory Neil Shapiro # ifdef LDAP_AUTH_KRBV4
43940266059SGregory Neil Shapiro 	if (lmap->ldap_method == LDAP_AUTH_KRBV4 &&
44040266059SGregory Neil Shapiro 	    lmap->ldap_secret != NULL)
44140266059SGregory Neil Shapiro 	{
44240266059SGregory Neil Shapiro 		/*
44340266059SGregory Neil Shapiro 		**  Need to put ticket in environment here instead of
44440266059SGregory Neil Shapiro 		**  during parseargs as there may be different tickets
44540266059SGregory Neil Shapiro 		**  for different LDAP connections.
44640266059SGregory Neil Shapiro 		*/
44740266059SGregory Neil Shapiro 
44840266059SGregory Neil Shapiro 		(void) putenv(lmap->ldap_secret);
44940266059SGregory Neil Shapiro 	}
45040266059SGregory Neil Shapiro # endif /* LDAP_AUTH_KRBV4 */
45140266059SGregory Neil Shapiro 
4525b0945b5SGregory Neil Shapiro # if LDAP_NETWORK_TIMEOUT
4535b0945b5SGregory Neil Shapiro 	tmo.tv_sec = lmap->ldap_networktmo;
4545b0945b5SGregory Neil Shapiro # else
4555b0945b5SGregory Neil Shapiro 	tmo.tv_sec = lmap->ldap_timeout.tv_sec;
4565b0945b5SGregory Neil Shapiro # endif
4575b0945b5SGregory Neil Shapiro 	tmo.tv_usec = 0;
45840266059SGregory Neil Shapiro 
4595b0945b5SGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 9))
4605b0945b5SGregory Neil Shapiro 		sm_dprintf("ldap_bind(%s)\n", lmap->ldap_uri);
4615b0945b5SGregory Neil Shapiro 	errno = 0;
4625b0945b5SGregory Neil Shapiro 	msgid = ldap_bind(ld, lmap->ldap_binddn, lmap->ldap_secret,
4635b0945b5SGregory Neil Shapiro 			lmap->ldap_method);
4645b0945b5SGregory Neil Shapiro 	save_errno = errno;
4655b0945b5SGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 9))
466*d39bd2c1SGregory Neil Shapiro 	{
467*d39bd2c1SGregory Neil Shapiro 		errmsg = sm_ldap_geterror(ld);
468*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("ldap_bind(%s)=%d, errno=%d, ldaperr=%d, ld_error=%s, tmo=%lld\n",
4695b0945b5SGregory Neil Shapiro 			lmap->ldap_uri, msgid, save_errno,
470*d39bd2c1SGregory Neil Shapiro 			sm_ldap_geterrno(ld), errmsg, (long long) tmo.tv_sec);
471*d39bd2c1SGregory Neil Shapiro 		if (NULL != errmsg)
472*d39bd2c1SGregory Neil Shapiro 		{
473*d39bd2c1SGregory Neil Shapiro 			ldap_memfree(errmsg);
474*d39bd2c1SGregory Neil Shapiro 			errmsg = NULL;
475*d39bd2c1SGregory Neil Shapiro 		}
476*d39bd2c1SGregory Neil Shapiro 	}
4775b0945b5SGregory Neil Shapiro 	if (-1 == msgid)
4785b0945b5SGregory Neil Shapiro 	{
4795b0945b5SGregory Neil Shapiro 		r = -1;
480*d39bd2c1SGregory Neil Shapiro 		err = sm_ldap_geterrno(ld);
481*d39bd2c1SGregory Neil Shapiro 		if (LDAP_SUCCESS != err)
482*d39bd2c1SGregory Neil Shapiro 			save_errno = err + E_LDAPBASE;
4835b0945b5SGregory Neil Shapiro 		goto fail;
4845b0945b5SGregory Neil Shapiro 	}
4855b0945b5SGregory Neil Shapiro 
4865b0945b5SGregory Neil Shapiro 	errno = 0;
4875b0945b5SGregory Neil Shapiro 	r = ldap_result(ld, msgid, LDAP_MSG_ALL,
4885b0945b5SGregory Neil Shapiro 			tmo.tv_sec == 0 ? NULL : &(tmo), &(lmap->ldap_res));
489*d39bd2c1SGregory Neil Shapiro 	save_errno = errno;
4905b0945b5SGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 9))
491*d39bd2c1SGregory Neil Shapiro 	{
492*d39bd2c1SGregory Neil Shapiro 		errmsg = sm_ldap_geterror(ld);
493*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("ldap_result(%s)=%d, errno=%d, ldaperr=%d, ld_error=%s\n",
494*d39bd2c1SGregory Neil Shapiro 			lmap->ldap_uri, r, errno,
495*d39bd2c1SGregory Neil Shapiro 			sm_ldap_geterrno(ld), errmsg);
496*d39bd2c1SGregory Neil Shapiro 		if (NULL != errmsg)
497*d39bd2c1SGregory Neil Shapiro 		{
498*d39bd2c1SGregory Neil Shapiro 			ldap_memfree(errmsg);
499*d39bd2c1SGregory Neil Shapiro 			errmsg = NULL;
500*d39bd2c1SGregory Neil Shapiro 		}
501*d39bd2c1SGregory Neil Shapiro 	}
5025b0945b5SGregory Neil Shapiro 	if (-1 == r)
503*d39bd2c1SGregory Neil Shapiro 	{
504*d39bd2c1SGregory Neil Shapiro 		err = sm_ldap_geterrno(ld);
505*d39bd2c1SGregory Neil Shapiro 		if (LDAP_SUCCESS != err)
506*d39bd2c1SGregory Neil Shapiro 			save_errno = err + E_LDAPBASE;
5075b0945b5SGregory Neil Shapiro 		goto fail;
508*d39bd2c1SGregory Neil Shapiro 	}
5095b0945b5SGregory Neil Shapiro 	if (0 == r)
5105b0945b5SGregory Neil Shapiro 	{
5115b0945b5SGregory Neil Shapiro 		save_errno = ETIMEDOUT;
5125b0945b5SGregory Neil Shapiro 		r = -1;
5135b0945b5SGregory Neil Shapiro 		goto fail;
5145b0945b5SGregory Neil Shapiro 	}
515*d39bd2c1SGregory Neil Shapiro 	r = ldap_parse_result(ld, lmap->ldap_res, &err, NULL, &errmsg, NULL,
516*d39bd2c1SGregory Neil Shapiro 				NULL, 1);
517*d39bd2c1SGregory Neil Shapiro 	save_errno = errno;
5185b0945b5SGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 9))
519*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("ldap_parse_result(%s)=%d, err=%d, errmsg=%s\n",
520*d39bd2c1SGregory Neil Shapiro 				lmap->ldap_uri, r, err, errmsg);
5215b0945b5SGregory Neil Shapiro 	if (r != LDAP_SUCCESS)
5225b0945b5SGregory Neil Shapiro 		goto fail;
5235b0945b5SGregory Neil Shapiro 	if (err != LDAP_SUCCESS)
5245b0945b5SGregory Neil Shapiro 	{
525*d39bd2c1SGregory Neil Shapiro 		r = err;
5265b0945b5SGregory Neil Shapiro 		goto fail;
5275b0945b5SGregory Neil Shapiro 	}
5285b0945b5SGregory Neil Shapiro 
5295b0945b5SGregory Neil Shapiro # if USE_LDAP_INIT && !LDAP_NETWORK_TIMEOUT
53040266059SGregory Neil Shapiro 	/* clear the event if it has not sprung */
53140266059SGregory Neil Shapiro 	SM_LDAP_CLEARTIMEOUT();
5325b0945b5SGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 9))
5335b0945b5SGregory Neil Shapiro 		sm_dprintf("ldap_cleartimeout(%s)\n", lmap->ldap_uri);
5345b0945b5SGregory Neil Shapiro # endif /* USE_LDAP_INIT && !LDAP_NETWORK_TIMEOUT */
53540266059SGregory Neil Shapiro 
5365b0945b5SGregory Neil Shapiro 	if (r != LDAP_SUCCESS)
53740266059SGregory Neil Shapiro 	{
5385b0945b5SGregory Neil Shapiro   fail:
5395b0945b5SGregory Neil Shapiro 		if (-1 == r)
5405b0945b5SGregory Neil Shapiro 			errno = save_errno;
5415b0945b5SGregory Neil Shapiro 		else
5425b0945b5SGregory Neil Shapiro 			errno = r + E_LDAPBASE;
543*d39bd2c1SGregory Neil Shapiro 		if (NULL != errmsg)
544*d39bd2c1SGregory Neil Shapiro 		{
545*d39bd2c1SGregory Neil Shapiro 			ldap_memfree(errmsg);
546*d39bd2c1SGregory Neil Shapiro 			errmsg = NULL;
547*d39bd2c1SGregory Neil Shapiro 		}
54840266059SGregory Neil Shapiro 		return false;
54940266059SGregory Neil Shapiro 	}
55040266059SGregory Neil Shapiro 
55140266059SGregory Neil Shapiro 	/* Save PID to make sure only this PID closes the LDAP connection */
55240266059SGregory Neil Shapiro 	lmap->ldap_pid = getpid();
55340266059SGregory Neil Shapiro 	lmap->ldap_ld = ld;
554*d39bd2c1SGregory Neil Shapiro 	if (NULL != errmsg)
555*d39bd2c1SGregory Neil Shapiro 	{
556*d39bd2c1SGregory Neil Shapiro 		ldap_memfree(errmsg);
557*d39bd2c1SGregory Neil Shapiro 		errmsg = NULL;
558*d39bd2c1SGregory Neil Shapiro 	}
55940266059SGregory Neil Shapiro 	return true;
56040266059SGregory Neil Shapiro }
56140266059SGregory Neil Shapiro 
56240266059SGregory Neil Shapiro /*
563d0cef73dSGregory Neil Shapiro **  SM_LDAP_SEARCH_M -- initiate multi-key LDAP search
56440266059SGregory Neil Shapiro **
56540266059SGregory Neil Shapiro **	Initiate an LDAP search, return the msgid.
56640266059SGregory Neil Shapiro **	The calling function must collect the results.
56740266059SGregory Neil Shapiro **
56840266059SGregory Neil Shapiro **	Parameters:
56940266059SGregory Neil Shapiro **		lmap -- LDAP map information
570d0cef73dSGregory Neil Shapiro **		argv -- key vector of substitutions in LDAP filter
571d0cef73dSGregory Neil Shapiro **			NOTE: argv must have SM_LDAP_ARGS elements to prevent
572d0cef73dSGregory Neil Shapiro **			      out of bound array references
57340266059SGregory Neil Shapiro **
57440266059SGregory Neil Shapiro **	Returns:
575d0cef73dSGregory Neil Shapiro **		<0 on failure (SM_LDAP_ERR*), msgid on success
57640266059SGregory Neil Shapiro **
57740266059SGregory Neil Shapiro */
57840266059SGregory Neil Shapiro 
57940266059SGregory Neil Shapiro int
sm_ldap_search_m(lmap,argv)580d0cef73dSGregory Neil Shapiro sm_ldap_search_m(lmap, argv)
58140266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
582d0cef73dSGregory Neil Shapiro 	char **argv;
58340266059SGregory Neil Shapiro {
58440266059SGregory Neil Shapiro 	int msgid;
58540266059SGregory Neil Shapiro 	char *fp, *p, *q;
58640266059SGregory Neil Shapiro 	char filter[LDAPMAP_MAX_FILTER + 1];
58740266059SGregory Neil Shapiro 
588d0cef73dSGregory Neil Shapiro 	SM_REQUIRE(lmap != NULL);
589d0cef73dSGregory Neil Shapiro 	SM_REQUIRE(argv != NULL);
590d0cef73dSGregory Neil Shapiro 	SM_REQUIRE(argv[0] != NULL);
591d0cef73dSGregory Neil Shapiro 
59240266059SGregory Neil Shapiro 	memset(filter, '\0', sizeof filter);
59340266059SGregory Neil Shapiro 	fp = filter;
59440266059SGregory Neil Shapiro 	p = lmap->ldap_filter;
59540266059SGregory Neil Shapiro 	while ((q = strchr(p, '%')) != NULL)
59640266059SGregory Neil Shapiro 	{
597d0cef73dSGregory Neil Shapiro 		char *key;
598d0cef73dSGregory Neil Shapiro 
599d0cef73dSGregory Neil Shapiro 		if (lmap->ldap_multi_args)
600d0cef73dSGregory Neil Shapiro 		{
601d0cef73dSGregory Neil Shapiro # if SM_LDAP_ARGS < 10
602*d39bd2c1SGregory Neil Shapiro #  error _SM_LDAP_ARGS must be 10
6032fb4f839SGregory Neil Shapiro # endif
604d0cef73dSGregory Neil Shapiro 			if (q[1] == 's')
605d0cef73dSGregory Neil Shapiro 				key = argv[0];
606d0cef73dSGregory Neil Shapiro 			else if (q[1] >= '0' && q[1] <= '9')
607d0cef73dSGregory Neil Shapiro 			{
608d0cef73dSGregory Neil Shapiro 				key = argv[q[1] - '0'];
609d0cef73dSGregory Neil Shapiro 				if (key == NULL)
610d0cef73dSGregory Neil Shapiro 				{
611d0cef73dSGregory Neil Shapiro # if SM_LDAP_ERROR_ON_MISSING_ARGS
612d0cef73dSGregory Neil Shapiro 					return SM_LDAP_ERR_ARG_MISS;
6132fb4f839SGregory Neil Shapiro # else
614d0cef73dSGregory Neil Shapiro 					key = "";
6152fb4f839SGregory Neil Shapiro # endif
616d0cef73dSGregory Neil Shapiro 				}
617d0cef73dSGregory Neil Shapiro 			}
618d0cef73dSGregory Neil Shapiro 			else
619d0cef73dSGregory Neil Shapiro 				key = NULL;
620d0cef73dSGregory Neil Shapiro 		}
621d0cef73dSGregory Neil Shapiro 		else
622d0cef73dSGregory Neil Shapiro 			key = argv[0];
623d0cef73dSGregory Neil Shapiro 
62440266059SGregory Neil Shapiro 		if (q[1] == 's')
62540266059SGregory Neil Shapiro 		{
62640266059SGregory Neil Shapiro 			(void) sm_snprintf(fp, SPACELEFT(filter, fp),
62740266059SGregory Neil Shapiro 					   "%.*s%s", (int) (q - p), p, key);
62840266059SGregory Neil Shapiro 			fp += strlen(fp);
62940266059SGregory Neil Shapiro 			p = q + 2;
63040266059SGregory Neil Shapiro 		}
631d0cef73dSGregory Neil Shapiro 		else if (q[1] == '0' ||
632d0cef73dSGregory Neil Shapiro 			 (lmap->ldap_multi_args && q[1] >= '0' && q[1] <= '9'))
63340266059SGregory Neil Shapiro 		{
63440266059SGregory Neil Shapiro 			char *k = key;
63540266059SGregory Neil Shapiro 
63640266059SGregory Neil Shapiro 			(void) sm_snprintf(fp, SPACELEFT(filter, fp),
63740266059SGregory Neil Shapiro 					   "%.*s", (int) (q - p), p);
63840266059SGregory Neil Shapiro 			fp += strlen(fp);
63940266059SGregory Neil Shapiro 			p = q + 2;
64040266059SGregory Neil Shapiro 
64140266059SGregory Neil Shapiro 			/* Properly escape LDAP special characters */
64240266059SGregory Neil Shapiro 			while (SPACELEFT(filter, fp) > 0 &&
64340266059SGregory Neil Shapiro 			       *k != '\0')
64440266059SGregory Neil Shapiro 			{
64540266059SGregory Neil Shapiro 				if (*k == '*' || *k == '(' ||
64640266059SGregory Neil Shapiro 				    *k == ')' || *k == '\\')
64740266059SGregory Neil Shapiro 				{
64840266059SGregory Neil Shapiro 					(void) sm_strlcat(fp,
64940266059SGregory Neil Shapiro 						       (*k == '*' ? "\\2A" :
65040266059SGregory Neil Shapiro 							(*k == '(' ? "\\28" :
65140266059SGregory Neil Shapiro 							 (*k == ')' ? "\\29" :
65240266059SGregory Neil Shapiro 							  (*k == '\\' ? "\\5C" :
65340266059SGregory Neil Shapiro 							   "\00")))),
65440266059SGregory Neil Shapiro 						SPACELEFT(filter, fp));
65540266059SGregory Neil Shapiro 					fp += strlen(fp);
65640266059SGregory Neil Shapiro 					k++;
65740266059SGregory Neil Shapiro 				}
65840266059SGregory Neil Shapiro 				else
65940266059SGregory Neil Shapiro 					*fp++ = *k++;
66040266059SGregory Neil Shapiro 			}
66140266059SGregory Neil Shapiro 		}
66240266059SGregory Neil Shapiro 		else
66340266059SGregory Neil Shapiro 		{
66440266059SGregory Neil Shapiro 			(void) sm_snprintf(fp, SPACELEFT(filter, fp),
66540266059SGregory Neil Shapiro 				"%.*s", (int) (q - p + 1), p);
66640266059SGregory Neil Shapiro 			p = q + (q[1] == '%' ? 2 : 1);
66740266059SGregory Neil Shapiro 			fp += strlen(fp);
66840266059SGregory Neil Shapiro 		}
66940266059SGregory Neil Shapiro 	}
67040266059SGregory Neil Shapiro 	(void) sm_strlcpy(fp, p, SPACELEFT(filter, fp));
67140266059SGregory Neil Shapiro 	if (sm_debug_active(&SmLDAPTrace, 20))
67240266059SGregory Neil Shapiro 		sm_dprintf("ldap search filter=%s\n", filter);
67340266059SGregory Neil Shapiro 
67440266059SGregory Neil Shapiro 	lmap->ldap_res = NULL;
675605302a5SGregory Neil Shapiro 	msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base,
676605302a5SGregory Neil Shapiro 			    lmap->ldap_scope, filter,
67740266059SGregory Neil Shapiro 			    (lmap->ldap_attr[0] == NULL ? NULL :
67840266059SGregory Neil Shapiro 			     lmap->ldap_attr),
67940266059SGregory Neil Shapiro 			    lmap->ldap_attrsonly);
68040266059SGregory Neil Shapiro 	return msgid;
68140266059SGregory Neil Shapiro }
68240266059SGregory Neil Shapiro 
68340266059SGregory Neil Shapiro /*
684d0cef73dSGregory Neil Shapiro **  SM_LDAP_SEARCH -- initiate LDAP search
685d0cef73dSGregory Neil Shapiro **
686d0cef73dSGregory Neil Shapiro **	Initiate an LDAP search, return the msgid.
687d0cef73dSGregory Neil Shapiro **	The calling function must collect the results.
688d0cef73dSGregory Neil Shapiro **	Note this is just a wrapper into sm_ldap_search_m()
689d0cef73dSGregory Neil Shapiro **
690d0cef73dSGregory Neil Shapiro **	Parameters:
691d0cef73dSGregory Neil Shapiro **		lmap -- LDAP map information
692d0cef73dSGregory Neil Shapiro **		key -- key to substitute in LDAP filter
693d0cef73dSGregory Neil Shapiro **
694d0cef73dSGregory Neil Shapiro **	Returns:
695d0cef73dSGregory Neil Shapiro **		<0 on failure, msgid on success
696d0cef73dSGregory Neil Shapiro **
697d0cef73dSGregory Neil Shapiro */
698d0cef73dSGregory Neil Shapiro 
699d0cef73dSGregory Neil Shapiro int
sm_ldap_search(lmap,key)700d0cef73dSGregory Neil Shapiro sm_ldap_search(lmap, key)
701d0cef73dSGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
702d0cef73dSGregory Neil Shapiro 	char *key;
703d0cef73dSGregory Neil Shapiro {
704d0cef73dSGregory Neil Shapiro 	char *argv[SM_LDAP_ARGS];
705d0cef73dSGregory Neil Shapiro 
706d0cef73dSGregory Neil Shapiro 	memset(argv, '\0', sizeof argv);
707d0cef73dSGregory Neil Shapiro 	argv[0] = key;
708d0cef73dSGregory Neil Shapiro 	return sm_ldap_search_m(lmap, argv);
709d0cef73dSGregory Neil Shapiro }
710d0cef73dSGregory Neil Shapiro 
711d0cef73dSGregory Neil Shapiro /*
712605302a5SGregory Neil Shapiro **  SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a
713605302a5SGregory Neil Shapiro **			       particular objectClass
714605302a5SGregory Neil Shapiro **
715605302a5SGregory Neil Shapiro **	Parameters:
716605302a5SGregory Neil Shapiro **		lmap -- pointer to SM_LDAP_STRUCT in use
717605302a5SGregory Neil Shapiro **		entry -- current LDAP entry struct
718605302a5SGregory Neil Shapiro **		ocvalue -- particular objectclass in question.
719605302a5SGregory Neil Shapiro **			   may be of form (fee|foo|fum) meaning
720605302a5SGregory Neil Shapiro **			   any entry can be part of either fee,
721605302a5SGregory Neil Shapiro **			   foo or fum objectclass
722605302a5SGregory Neil Shapiro **
723605302a5SGregory Neil Shapiro **	Returns:
724605302a5SGregory Neil Shapiro **		true if item has that objectClass
725605302a5SGregory Neil Shapiro */
726605302a5SGregory Neil Shapiro 
727605302a5SGregory Neil Shapiro static bool
sm_ldap_has_objectclass(lmap,entry,ocvalue)728605302a5SGregory Neil Shapiro sm_ldap_has_objectclass(lmap, entry, ocvalue)
729605302a5SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
730605302a5SGregory Neil Shapiro 	LDAPMessage *entry;
731605302a5SGregory Neil Shapiro 	char *ocvalue;
732605302a5SGregory Neil Shapiro {
733605302a5SGregory Neil Shapiro 	char **vals = NULL;
734605302a5SGregory Neil Shapiro 	int i;
735605302a5SGregory Neil Shapiro 
736605302a5SGregory Neil Shapiro 	if (ocvalue == NULL)
737605302a5SGregory Neil Shapiro 		return false;
738605302a5SGregory Neil Shapiro 
739605302a5SGregory Neil Shapiro 	vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass");
740605302a5SGregory Neil Shapiro 	if (vals == NULL)
741605302a5SGregory Neil Shapiro 		return false;
742605302a5SGregory Neil Shapiro 
743605302a5SGregory Neil Shapiro 	for (i = 0; vals[i] != NULL; i++)
744605302a5SGregory Neil Shapiro 	{
745605302a5SGregory Neil Shapiro 		char *p;
746605302a5SGregory Neil Shapiro 		char *q;
747605302a5SGregory Neil Shapiro 
748605302a5SGregory Neil Shapiro 		p = q = ocvalue;
749605302a5SGregory Neil Shapiro 		while (*p != '\0')
750605302a5SGregory Neil Shapiro 		{
751605302a5SGregory Neil Shapiro 			while (*p != '\0' && *p != '|')
752605302a5SGregory Neil Shapiro 				p++;
753605302a5SGregory Neil Shapiro 
754605302a5SGregory Neil Shapiro 			if ((p - q) == strlen(vals[i]) &&
755605302a5SGregory Neil Shapiro 			    sm_strncasecmp(vals[i], q, p - q) == 0)
756605302a5SGregory Neil Shapiro 			{
757605302a5SGregory Neil Shapiro 				ldap_value_free(vals);
758605302a5SGregory Neil Shapiro 				return true;
759605302a5SGregory Neil Shapiro 			}
760605302a5SGregory Neil Shapiro 
761605302a5SGregory Neil Shapiro 			while (*p == '|')
762605302a5SGregory Neil Shapiro 				p++;
763605302a5SGregory Neil Shapiro 			q = p;
764605302a5SGregory Neil Shapiro 		}
765605302a5SGregory Neil Shapiro 	}
766605302a5SGregory Neil Shapiro 
767605302a5SGregory Neil Shapiro 	ldap_value_free(vals);
768605302a5SGregory Neil Shapiro 	return false;
769605302a5SGregory Neil Shapiro }
770605302a5SGregory Neil Shapiro 
771605302a5SGregory Neil Shapiro /*
77240266059SGregory Neil Shapiro **  SM_LDAP_RESULTS -- return results from an LDAP lookup in result
77340266059SGregory Neil Shapiro **
77440266059SGregory Neil Shapiro **	Parameters:
77540266059SGregory Neil Shapiro **		lmap -- pointer to SM_LDAP_STRUCT in use
77640266059SGregory Neil Shapiro **		msgid -- msgid returned by sm_ldap_search()
77740266059SGregory Neil Shapiro **		flags -- flags for the lookup
77840266059SGregory Neil Shapiro **		delim -- delimiter for result concatenation
77940266059SGregory Neil Shapiro **		rpool -- memory pool for storage
78040266059SGregory Neil Shapiro **		result -- return string
78140266059SGregory Neil Shapiro **		recurse -- recursion list
78240266059SGregory Neil Shapiro **
78340266059SGregory Neil Shapiro **	Returns:
78440266059SGregory Neil Shapiro **		status (sysexit)
78540266059SGregory Neil Shapiro */
78640266059SGregory Neil Shapiro 
787605302a5SGregory Neil Shapiro # define SM_LDAP_ERROR_CLEANUP()				\
78840266059SGregory Neil Shapiro {								\
78940266059SGregory Neil Shapiro 	if (lmap->ldap_res != NULL)				\
79040266059SGregory Neil Shapiro 	{							\
79140266059SGregory Neil Shapiro 		ldap_msgfree(lmap->ldap_res);			\
79240266059SGregory Neil Shapiro 		lmap->ldap_res = NULL;				\
79340266059SGregory Neil Shapiro 	}							\
79440266059SGregory Neil Shapiro 	(void) ldap_abandon(lmap->ldap_ld, msgid);		\
79540266059SGregory Neil Shapiro }
79640266059SGregory Neil Shapiro 
797605302a5SGregory Neil Shapiro static SM_LDAP_RECURSE_ENTRY *
sm_ldap_add_recurse(top,item,type,rpool)798605302a5SGregory Neil Shapiro sm_ldap_add_recurse(top, item, type, rpool)
79940266059SGregory Neil Shapiro 	SM_LDAP_RECURSE_LIST **top;
80040266059SGregory Neil Shapiro 	char *item;
80140266059SGregory Neil Shapiro 	int type;
80240266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
80340266059SGregory Neil Shapiro {
804605302a5SGregory Neil Shapiro 	int n;
805605302a5SGregory Neil Shapiro 	int m;
806605302a5SGregory Neil Shapiro 	int p;
807605302a5SGregory Neil Shapiro 	int insertat;
808605302a5SGregory Neil Shapiro 	int moveb;
809605302a5SGregory Neil Shapiro 	int oldsizeb;
810605302a5SGregory Neil Shapiro 	int rc;
811605302a5SGregory Neil Shapiro 	SM_LDAP_RECURSE_ENTRY *newe;
812605302a5SGregory Neil Shapiro 	SM_LDAP_RECURSE_ENTRY **olddata;
81340266059SGregory Neil Shapiro 
814605302a5SGregory Neil Shapiro 	/*
815605302a5SGregory Neil Shapiro 	**  This code will maintain a list of
816605302a5SGregory Neil Shapiro 	**  SM_LDAP_RECURSE_ENTRY structures
817605302a5SGregory Neil Shapiro 	**  in ascending order.
818605302a5SGregory Neil Shapiro 	*/
819605302a5SGregory Neil Shapiro 
820605302a5SGregory Neil Shapiro 	if (*top == NULL)
82140266059SGregory Neil Shapiro 	{
822605302a5SGregory Neil Shapiro 		/* Allocate an initial SM_LDAP_RECURSE_LIST struct */
823605302a5SGregory Neil Shapiro 		*top = sm_rpool_malloc_x(rpool, sizeof **top);
824d0cef73dSGregory Neil Shapiro 		(*top)->lrl_cnt = 0;
825d0cef73dSGregory Neil Shapiro 		(*top)->lrl_size = 0;
826d0cef73dSGregory Neil Shapiro 		(*top)->lrl_data = NULL;
82740266059SGregory Neil Shapiro 	}
82840266059SGregory Neil Shapiro 
829d0cef73dSGregory Neil Shapiro 	if ((*top)->lrl_cnt >= (*top)->lrl_size)
830605302a5SGregory Neil Shapiro 	{
831605302a5SGregory Neil Shapiro 		/* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */
832d0cef73dSGregory Neil Shapiro 		olddata = (*top)->lrl_data;
833d0cef73dSGregory Neil Shapiro 		if ((*top)->lrl_size == 0)
834605302a5SGregory Neil Shapiro 		{
835605302a5SGregory Neil Shapiro 			oldsizeb = 0;
836d0cef73dSGregory Neil Shapiro 			(*top)->lrl_size = 256;
837605302a5SGregory Neil Shapiro 		}
83840266059SGregory Neil Shapiro 		else
839605302a5SGregory Neil Shapiro 		{
840d0cef73dSGregory Neil Shapiro 			oldsizeb = (*top)->lrl_size * sizeof *((*top)->lrl_data);
841d0cef73dSGregory Neil Shapiro 			(*top)->lrl_size *= 2;
842605302a5SGregory Neil Shapiro 		}
843d0cef73dSGregory Neil Shapiro 		(*top)->lrl_data = sm_rpool_malloc_x(rpool,
844d0cef73dSGregory Neil Shapiro 						    (*top)->lrl_size * sizeof *((*top)->lrl_data));
845605302a5SGregory Neil Shapiro 		if (oldsizeb > 0)
846d0cef73dSGregory Neil Shapiro 			memcpy((*top)->lrl_data, olddata, oldsizeb);
847605302a5SGregory Neil Shapiro 	}
848605302a5SGregory Neil Shapiro 
849605302a5SGregory Neil Shapiro 	/*
850605302a5SGregory Neil Shapiro 	**  Binary search/insert item:type into list.
851605302a5SGregory Neil Shapiro 	**  Return current entry pointer if already exists.
852605302a5SGregory Neil Shapiro 	*/
853605302a5SGregory Neil Shapiro 
854605302a5SGregory Neil Shapiro 	n = 0;
855d0cef73dSGregory Neil Shapiro 	m = (*top)->lrl_cnt - 1;
856605302a5SGregory Neil Shapiro 	if (m < 0)
857605302a5SGregory Neil Shapiro 		insertat = 0;
858605302a5SGregory Neil Shapiro 	else
859605302a5SGregory Neil Shapiro 		insertat = -1;
860605302a5SGregory Neil Shapiro 
861605302a5SGregory Neil Shapiro 	while (insertat == -1)
862605302a5SGregory Neil Shapiro 	{
863605302a5SGregory Neil Shapiro 		p = (m + n) / 2;
864605302a5SGregory Neil Shapiro 
865d0cef73dSGregory Neil Shapiro 		rc = sm_strcasecmp(item, (*top)->lrl_data[p]->lr_search);
866605302a5SGregory Neil Shapiro 		if (rc == 0)
867d0cef73dSGregory Neil Shapiro 			rc = type - (*top)->lrl_data[p]->lr_type;
868605302a5SGregory Neil Shapiro 
869605302a5SGregory Neil Shapiro 		if (rc < 0)
870605302a5SGregory Neil Shapiro 			m = p - 1;
871605302a5SGregory Neil Shapiro 		else if (rc > 0)
872605302a5SGregory Neil Shapiro 			n = p + 1;
873605302a5SGregory Neil Shapiro 		else
874d0cef73dSGregory Neil Shapiro 			return (*top)->lrl_data[p];
875605302a5SGregory Neil Shapiro 
876605302a5SGregory Neil Shapiro 		if (m == -1)
877605302a5SGregory Neil Shapiro 			insertat = 0;
878d0cef73dSGregory Neil Shapiro 		else if (n >= (*top)->lrl_cnt)
879d0cef73dSGregory Neil Shapiro 			insertat = (*top)->lrl_cnt;
880605302a5SGregory Neil Shapiro 		else if (m < n)
881605302a5SGregory Neil Shapiro 			insertat = m + 1;
882605302a5SGregory Neil Shapiro 	}
883605302a5SGregory Neil Shapiro 
884605302a5SGregory Neil Shapiro 	/*
885605302a5SGregory Neil Shapiro 	** Not found in list, make room
886605302a5SGregory Neil Shapiro 	** at insert point and add it.
887605302a5SGregory Neil Shapiro 	*/
888605302a5SGregory Neil Shapiro 
889605302a5SGregory Neil Shapiro 	newe = sm_rpool_malloc_x(rpool, sizeof *newe);
890605302a5SGregory Neil Shapiro 	if (newe != NULL)
891605302a5SGregory Neil Shapiro 	{
892d0cef73dSGregory Neil Shapiro 		moveb = ((*top)->lrl_cnt - insertat) * sizeof *((*top)->lrl_data);
893605302a5SGregory Neil Shapiro 		if (moveb > 0)
894d0cef73dSGregory Neil Shapiro 			memmove(&((*top)->lrl_data[insertat + 1]),
895d0cef73dSGregory Neil Shapiro 				&((*top)->lrl_data[insertat]),
896605302a5SGregory Neil Shapiro 				moveb);
897605302a5SGregory Neil Shapiro 
898605302a5SGregory Neil Shapiro 		newe->lr_search = sm_rpool_strdup_x(rpool, item);
899605302a5SGregory Neil Shapiro 		newe->lr_type = type;
900e92d3f3fSGregory Neil Shapiro 		newe->lr_ludp = NULL;
901e92d3f3fSGregory Neil Shapiro 		newe->lr_attrs = NULL;
902605302a5SGregory Neil Shapiro 		newe->lr_done = false;
903605302a5SGregory Neil Shapiro 
904d0cef73dSGregory Neil Shapiro 		((*top)->lrl_data)[insertat] = newe;
905d0cef73dSGregory Neil Shapiro 		(*top)->lrl_cnt++;
906605302a5SGregory Neil Shapiro 	}
907605302a5SGregory Neil Shapiro 	return newe;
90840266059SGregory Neil Shapiro }
90940266059SGregory Neil Shapiro 
91040266059SGregory Neil Shapiro int
sm_ldap_results(lmap,msgid,flags,delim,rpool,result,resultln,resultsz,recurse)911605302a5SGregory Neil Shapiro sm_ldap_results(lmap, msgid, flags, delim, rpool, result,
912605302a5SGregory Neil Shapiro 		resultln, resultsz, recurse)
91340266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
91440266059SGregory Neil Shapiro 	int msgid;
91540266059SGregory Neil Shapiro 	int flags;
916605302a5SGregory Neil Shapiro 	int delim;
91740266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
91840266059SGregory Neil Shapiro 	char **result;
919605302a5SGregory Neil Shapiro 	int *resultln;
920605302a5SGregory Neil Shapiro 	int *resultsz;
92140266059SGregory Neil Shapiro 	SM_LDAP_RECURSE_LIST *recurse;
92240266059SGregory Neil Shapiro {
92340266059SGregory Neil Shapiro 	bool toplevel;
92440266059SGregory Neil Shapiro 	int i;
92540266059SGregory Neil Shapiro 	int statp;
92640266059SGregory Neil Shapiro 	int vsize;
92740266059SGregory Neil Shapiro 	int ret;
92840266059SGregory Neil Shapiro 	int save_errno;
92940266059SGregory Neil Shapiro 	char *p;
930605302a5SGregory Neil Shapiro 	SM_LDAP_RECURSE_ENTRY *rl;
93140266059SGregory Neil Shapiro 
93240266059SGregory Neil Shapiro 	/* Are we the top top level of the search? */
93340266059SGregory Neil Shapiro 	toplevel = (recurse == NULL);
93440266059SGregory Neil Shapiro 
93540266059SGregory Neil Shapiro 	/* Get results */
93640266059SGregory Neil Shapiro 	statp = EX_NOTFOUND;
93740266059SGregory Neil Shapiro 	while ((ret = ldap_result(lmap->ldap_ld, msgid, 0,
93840266059SGregory Neil Shapiro 				  (lmap->ldap_timeout.tv_sec == 0 ? NULL :
93940266059SGregory Neil Shapiro 				   &(lmap->ldap_timeout)),
94040266059SGregory Neil Shapiro 				  &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY)
94140266059SGregory Neil Shapiro 	{
94240266059SGregory Neil Shapiro 		LDAPMessage *entry;
94340266059SGregory Neil Shapiro 
94440266059SGregory Neil Shapiro 		/* If we don't want multiple values and we have one, break */
94513d88268SGregory Neil Shapiro 		if ((char) delim == '\0' &&
94613d88268SGregory Neil Shapiro 		    !bitset(SM_LDAP_SINGLEMATCH, flags) &&
94713d88268SGregory Neil Shapiro 		    *result != NULL)
94840266059SGregory Neil Shapiro 			break;
94940266059SGregory Neil Shapiro 
95040266059SGregory Neil Shapiro 		/* Cycle through all entries */
95140266059SGregory Neil Shapiro 		for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res);
95240266059SGregory Neil Shapiro 		     entry != NULL;
95340266059SGregory Neil Shapiro 		     entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res))
95440266059SGregory Neil Shapiro 		{
95540266059SGregory Neil Shapiro 			BerElement *ber;
95640266059SGregory Neil Shapiro 			char *attr;
95740266059SGregory Neil Shapiro 			char **vals = NULL;
95840266059SGregory Neil Shapiro 			char *dn;
95940266059SGregory Neil Shapiro 
96040266059SGregory Neil Shapiro 			/*
96140266059SGregory Neil Shapiro 			**  If matching only and found an entry,
96240266059SGregory Neil Shapiro 			**  no need to spin through attributes
96340266059SGregory Neil Shapiro 			*/
96440266059SGregory Neil Shapiro 
965323f6dcbSGregory Neil Shapiro 			if (bitset(SM_LDAP_MATCHONLY, flags))
966323f6dcbSGregory Neil Shapiro 			{
967323f6dcbSGregory Neil Shapiro 				statp = EX_OK;
96840266059SGregory Neil Shapiro 				continue;
969323f6dcbSGregory Neil Shapiro 			}
97040266059SGregory Neil Shapiro 
9714e4196cbSGregory Neil Shapiro # if _FFR_LDAP_SINGLEDN
9724e4196cbSGregory Neil Shapiro 			if (bitset(SM_LDAP_SINGLEDN, flags) && *result != NULL)
9734e4196cbSGregory Neil Shapiro 			{
9744e4196cbSGregory Neil Shapiro 				/* only wanted one match */
9754e4196cbSGregory Neil Shapiro 				SM_LDAP_ERROR_CLEANUP();
9764e4196cbSGregory Neil Shapiro 				errno = ENOENT;
9774e4196cbSGregory Neil Shapiro 				return EX_NOTFOUND;
9784e4196cbSGregory Neil Shapiro 			}
9794e4196cbSGregory Neil Shapiro # endif /* _FFR_LDAP_SINGLEDN */
9804e4196cbSGregory Neil Shapiro 
98140266059SGregory Neil Shapiro 			/* record completed DN's to prevent loops */
98240266059SGregory Neil Shapiro 			dn = ldap_get_dn(lmap->ldap_ld, entry);
98340266059SGregory Neil Shapiro 			if (dn == NULL)
98440266059SGregory Neil Shapiro 			{
98540266059SGregory Neil Shapiro 				save_errno = sm_ldap_geterrno(lmap->ldap_ld);
98640266059SGregory Neil Shapiro 				save_errno += E_LDAPBASE;
987605302a5SGregory Neil Shapiro 				SM_LDAP_ERROR_CLEANUP();
98840266059SGregory Neil Shapiro 				errno = save_errno;
989a7ec597cSGregory Neil Shapiro 				return EX_TEMPFAIL;
99040266059SGregory Neil Shapiro 			}
99140266059SGregory Neil Shapiro 
992605302a5SGregory Neil Shapiro 			rl = sm_ldap_add_recurse(&recurse, dn,
993605302a5SGregory Neil Shapiro 						 SM_LDAP_ATTR_DN,
994605302a5SGregory Neil Shapiro 						 rpool);
995605302a5SGregory Neil Shapiro 
996605302a5SGregory Neil Shapiro 			if (rl == NULL)
99740266059SGregory Neil Shapiro 			{
99840266059SGregory Neil Shapiro 				ldap_memfree(dn);
999605302a5SGregory Neil Shapiro 				SM_LDAP_ERROR_CLEANUP();
100040266059SGregory Neil Shapiro 				errno = ENOMEM;
100140266059SGregory Neil Shapiro 				return EX_OSERR;
1002605302a5SGregory Neil Shapiro 			}
1003605302a5SGregory Neil Shapiro 			else if (rl->lr_done)
1004605302a5SGregory Neil Shapiro 			{
100540266059SGregory Neil Shapiro 				/* already on list, skip it */
100640266059SGregory Neil Shapiro 				ldap_memfree(dn);
100740266059SGregory Neil Shapiro 				continue;
100840266059SGregory Neil Shapiro 			}
100940266059SGregory Neil Shapiro 			ldap_memfree(dn);
101040266059SGregory Neil Shapiro 
101140266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT)
101240266059SGregory Neil Shapiro 			/*
101340266059SGregory Neil Shapiro 			**  Reset value to prevent lingering
101440266059SGregory Neil Shapiro 			**  LDAP_DECODING_ERROR due to
101540266059SGregory Neil Shapiro 			**  OpenLDAP 1.X's hack (see below)
101640266059SGregory Neil Shapiro 			*/
101740266059SGregory Neil Shapiro 
101840266059SGregory Neil Shapiro 			lmap->ldap_ld->ld_errno = LDAP_SUCCESS;
101940266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */
102040266059SGregory Neil Shapiro 
102140266059SGregory Neil Shapiro 			for (attr = ldap_first_attribute(lmap->ldap_ld, entry,
102240266059SGregory Neil Shapiro 							 &ber);
102340266059SGregory Neil Shapiro 			     attr != NULL;
102440266059SGregory Neil Shapiro 			     attr = ldap_next_attribute(lmap->ldap_ld, entry,
102540266059SGregory Neil Shapiro 							ber))
102640266059SGregory Neil Shapiro 			{
102740266059SGregory Neil Shapiro 				char *tmp, *vp_tmp;
102840266059SGregory Neil Shapiro 				int type;
1029605302a5SGregory Neil Shapiro 				char *needobjclass = NULL;
103040266059SGregory Neil Shapiro 
1031605302a5SGregory Neil Shapiro 				type = SM_LDAP_ATTR_NONE;
103240266059SGregory Neil Shapiro 				for (i = 0; lmap->ldap_attr[i] != NULL; i++)
103340266059SGregory Neil Shapiro 				{
10342fb4f839SGregory Neil Shapiro 					if (SM_STRCASEEQ(lmap->ldap_attr[i],
10352fb4f839SGregory Neil Shapiro 							 attr))
103640266059SGregory Neil Shapiro 					{
103740266059SGregory Neil Shapiro 						type = lmap->ldap_attr_type[i];
1038605302a5SGregory Neil Shapiro 						needobjclass = lmap->ldap_attr_needobjclass[i];
103940266059SGregory Neil Shapiro 						break;
104040266059SGregory Neil Shapiro 					}
104140266059SGregory Neil Shapiro 				}
1042605302a5SGregory Neil Shapiro 
1043605302a5SGregory Neil Shapiro 				if (bitset(SM_LDAP_USE_ALLATTR, flags) &&
1044605302a5SGregory Neil Shapiro 				    type == SM_LDAP_ATTR_NONE)
1045605302a5SGregory Neil Shapiro 				{
1046605302a5SGregory Neil Shapiro 					/* URL lookups specify attrs to use */
1047605302a5SGregory Neil Shapiro 					type = SM_LDAP_ATTR_NORMAL;
1048605302a5SGregory Neil Shapiro 					needobjclass = NULL;
1049605302a5SGregory Neil Shapiro 				}
1050605302a5SGregory Neil Shapiro 
1051605302a5SGregory Neil Shapiro 				if (type == SM_LDAP_ATTR_NONE)
105240266059SGregory Neil Shapiro 				{
105340266059SGregory Neil Shapiro 					/* attribute not requested */
105440266059SGregory Neil Shapiro 					ldap_memfree(attr);
1055605302a5SGregory Neil Shapiro 					SM_LDAP_ERROR_CLEANUP();
105640266059SGregory Neil Shapiro 					errno = EFAULT;
105740266059SGregory Neil Shapiro 					return EX_SOFTWARE;
105840266059SGregory Neil Shapiro 				}
105940266059SGregory Neil Shapiro 
1060605302a5SGregory Neil Shapiro 				/*
1061605302a5SGregory Neil Shapiro 				**  For recursion on a particular attribute,
1062605302a5SGregory Neil Shapiro 				**  we may need to see if this entry is
1063605302a5SGregory Neil Shapiro 				**  part of a particular objectclass.
1064605302a5SGregory Neil Shapiro 				**  Also, ignore objectClass attribute.
1065605302a5SGregory Neil Shapiro 				**  Otherwise we just ignore this attribute.
1066605302a5SGregory Neil Shapiro 				*/
1067605302a5SGregory Neil Shapiro 
1068605302a5SGregory Neil Shapiro 				if (type == SM_LDAP_ATTR_OBJCLASS ||
1069605302a5SGregory Neil Shapiro 				    (needobjclass != NULL &&
1070605302a5SGregory Neil Shapiro 				     !sm_ldap_has_objectclass(lmap, entry,
1071605302a5SGregory Neil Shapiro 							      needobjclass)))
1072605302a5SGregory Neil Shapiro 				{
1073605302a5SGregory Neil Shapiro 					ldap_memfree(attr);
1074605302a5SGregory Neil Shapiro 					continue;
1075605302a5SGregory Neil Shapiro 				}
1076605302a5SGregory Neil Shapiro 
107740266059SGregory Neil Shapiro 				if (lmap->ldap_attrsonly == LDAPMAP_FALSE)
107840266059SGregory Neil Shapiro 				{
107940266059SGregory Neil Shapiro 					vals = ldap_get_values(lmap->ldap_ld,
108040266059SGregory Neil Shapiro 							       entry,
108140266059SGregory Neil Shapiro 							       attr);
108240266059SGregory Neil Shapiro 					if (vals == NULL)
108340266059SGregory Neil Shapiro 					{
108440266059SGregory Neil Shapiro 						save_errno = sm_ldap_geterrno(lmap->ldap_ld);
108540266059SGregory Neil Shapiro 						if (save_errno == LDAP_SUCCESS)
108640266059SGregory Neil Shapiro 						{
108740266059SGregory Neil Shapiro 							ldap_memfree(attr);
108840266059SGregory Neil Shapiro 							continue;
108940266059SGregory Neil Shapiro 						}
109040266059SGregory Neil Shapiro 
109140266059SGregory Neil Shapiro 						/* Must be an error */
109240266059SGregory Neil Shapiro 						save_errno += E_LDAPBASE;
109340266059SGregory Neil Shapiro 						ldap_memfree(attr);
1094605302a5SGregory Neil Shapiro 						SM_LDAP_ERROR_CLEANUP();
109540266059SGregory Neil Shapiro 						errno = save_errno;
109640266059SGregory Neil Shapiro 						return EX_TEMPFAIL;
109740266059SGregory Neil Shapiro 					}
109840266059SGregory Neil Shapiro 				}
109940266059SGregory Neil Shapiro 
110040266059SGregory Neil Shapiro 				statp = EX_OK;
110140266059SGregory Neil Shapiro 
110240266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT)
110340266059SGregory Neil Shapiro 				/*
110440266059SGregory Neil Shapiro 				**  Reset value to prevent lingering
110540266059SGregory Neil Shapiro 				**  LDAP_DECODING_ERROR due to
110640266059SGregory Neil Shapiro 				**  OpenLDAP 1.X's hack (see below)
110740266059SGregory Neil Shapiro 				*/
110840266059SGregory Neil Shapiro 
110940266059SGregory Neil Shapiro 				lmap->ldap_ld->ld_errno = LDAP_SUCCESS;
111040266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */
111140266059SGregory Neil Shapiro 
111240266059SGregory Neil Shapiro 				/*
111340266059SGregory Neil Shapiro 				**  If matching only,
111440266059SGregory Neil Shapiro 				**  no need to spin through entries
111540266059SGregory Neil Shapiro 				*/
111640266059SGregory Neil Shapiro 
111740266059SGregory Neil Shapiro 				if (bitset(SM_LDAP_MATCHONLY, flags))
111840266059SGregory Neil Shapiro 				{
111940266059SGregory Neil Shapiro 					if (lmap->ldap_attrsonly == LDAPMAP_FALSE)
112040266059SGregory Neil Shapiro 						ldap_value_free(vals);
112140266059SGregory Neil Shapiro 					ldap_memfree(attr);
112240266059SGregory Neil Shapiro 					continue;
112340266059SGregory Neil Shapiro 				}
112440266059SGregory Neil Shapiro 
112540266059SGregory Neil Shapiro 				/*
112640266059SGregory Neil Shapiro 				**  If we don't want multiple values,
112740266059SGregory Neil Shapiro 				**  return first found.
112840266059SGregory Neil Shapiro 				*/
112940266059SGregory Neil Shapiro 
1130605302a5SGregory Neil Shapiro 				if ((char) delim == '\0')
113140266059SGregory Neil Shapiro 				{
1132605302a5SGregory Neil Shapiro 					if (*result != NULL)
1133605302a5SGregory Neil Shapiro 					{
1134605302a5SGregory Neil Shapiro 						/* already have a value */
1135605302a5SGregory Neil Shapiro 						if (bitset(SM_LDAP_SINGLEMATCH,
113613d88268SGregory Neil Shapiro 							   flags))
1137605302a5SGregory Neil Shapiro 						{
1138605302a5SGregory Neil Shapiro 							/* only wanted one match */
1139605302a5SGregory Neil Shapiro 							SM_LDAP_ERROR_CLEANUP();
1140605302a5SGregory Neil Shapiro 							errno = ENOENT;
1141605302a5SGregory Neil Shapiro 							return EX_NOTFOUND;
1142605302a5SGregory Neil Shapiro 						}
114313d88268SGregory Neil Shapiro 						break;
114413d88268SGregory Neil Shapiro 					}
1145605302a5SGregory Neil Shapiro 
114640266059SGregory Neil Shapiro 					if (lmap->ldap_attrsonly == LDAPMAP_TRUE)
114740266059SGregory Neil Shapiro 					{
114840266059SGregory Neil Shapiro 						*result = sm_rpool_strdup_x(rpool,
114940266059SGregory Neil Shapiro 									    attr);
115040266059SGregory Neil Shapiro 						ldap_memfree(attr);
115140266059SGregory Neil Shapiro 						break;
115240266059SGregory Neil Shapiro 					}
115340266059SGregory Neil Shapiro 
115440266059SGregory Neil Shapiro 					if (vals[0] == NULL)
115540266059SGregory Neil Shapiro 					{
115640266059SGregory Neil Shapiro 						ldap_value_free(vals);
115740266059SGregory Neil Shapiro 						ldap_memfree(attr);
115840266059SGregory Neil Shapiro 						continue;
115940266059SGregory Neil Shapiro 					}
116040266059SGregory Neil Shapiro 
116140266059SGregory Neil Shapiro 					vsize = strlen(vals[0]) + 1;
116240266059SGregory Neil Shapiro 					if (lmap->ldap_attrsep != '\0')
116340266059SGregory Neil Shapiro 						vsize += strlen(attr) + 1;
116440266059SGregory Neil Shapiro 					*result = sm_rpool_malloc_x(rpool,
116540266059SGregory Neil Shapiro 								    vsize);
116640266059SGregory Neil Shapiro 					if (lmap->ldap_attrsep != '\0')
116740266059SGregory Neil Shapiro 						sm_snprintf(*result, vsize,
116840266059SGregory Neil Shapiro 							    "%s%c%s",
116940266059SGregory Neil Shapiro 							    attr,
117040266059SGregory Neil Shapiro 							    lmap->ldap_attrsep,
117140266059SGregory Neil Shapiro 							    vals[0]);
117240266059SGregory Neil Shapiro 					else
117340266059SGregory Neil Shapiro 						sm_strlcpy(*result, vals[0],
117440266059SGregory Neil Shapiro 							   vsize);
117540266059SGregory Neil Shapiro 					ldap_value_free(vals);
117640266059SGregory Neil Shapiro 					ldap_memfree(attr);
117740266059SGregory Neil Shapiro 					break;
117840266059SGregory Neil Shapiro 				}
117940266059SGregory Neil Shapiro 
118040266059SGregory Neil Shapiro 				/* attributes only */
118140266059SGregory Neil Shapiro 				if (lmap->ldap_attrsonly == LDAPMAP_TRUE)
118240266059SGregory Neil Shapiro 				{
118340266059SGregory Neil Shapiro 					if (*result == NULL)
118440266059SGregory Neil Shapiro 						*result = sm_rpool_strdup_x(rpool,
118540266059SGregory Neil Shapiro 									    attr);
118640266059SGregory Neil Shapiro 					else
118740266059SGregory Neil Shapiro 					{
1188605302a5SGregory Neil Shapiro 						if (bitset(SM_LDAP_SINGLEMATCH,
1189605302a5SGregory Neil Shapiro 							   flags) &&
1190605302a5SGregory Neil Shapiro 						    *result != NULL)
1191605302a5SGregory Neil Shapiro 						{
1192605302a5SGregory Neil Shapiro 							/* only wanted one match */
1193605302a5SGregory Neil Shapiro 							SM_LDAP_ERROR_CLEANUP();
1194605302a5SGregory Neil Shapiro 							errno = ENOENT;
1195605302a5SGregory Neil Shapiro 							return EX_NOTFOUND;
1196605302a5SGregory Neil Shapiro 						}
1197605302a5SGregory Neil Shapiro 
119840266059SGregory Neil Shapiro 						vsize = strlen(*result) +
119940266059SGregory Neil Shapiro 							strlen(attr) + 2;
120040266059SGregory Neil Shapiro 						tmp = sm_rpool_malloc_x(rpool,
120140266059SGregory Neil Shapiro 									vsize);
120240266059SGregory Neil Shapiro 						(void) sm_snprintf(tmp,
120340266059SGregory Neil Shapiro 							vsize, "%s%c%s",
1204605302a5SGregory Neil Shapiro 							*result, (char) delim,
120540266059SGregory Neil Shapiro 							attr);
120640266059SGregory Neil Shapiro 						*result = tmp;
120740266059SGregory Neil Shapiro 					}
120840266059SGregory Neil Shapiro 					ldap_memfree(attr);
120940266059SGregory Neil Shapiro 					continue;
121040266059SGregory Neil Shapiro 				}
121140266059SGregory Neil Shapiro 
121240266059SGregory Neil Shapiro 				/*
1213605302a5SGregory Neil Shapiro 				**  If there is more than one, munge then
1214605302a5SGregory Neil Shapiro 				**  into a map_coldelim separated string.
1215605302a5SGregory Neil Shapiro 				**  If we are recursing we may have an entry
1216605302a5SGregory Neil Shapiro 				**  with no 'normal' values to put in the
1217605302a5SGregory Neil Shapiro 				**  string.
1218605302a5SGregory Neil Shapiro 				**  This is not an error.
121940266059SGregory Neil Shapiro 				*/
122040266059SGregory Neil Shapiro 
1221605302a5SGregory Neil Shapiro 				if (type == SM_LDAP_ATTR_NORMAL &&
1222605302a5SGregory Neil Shapiro 				    bitset(SM_LDAP_SINGLEMATCH, flags) &&
1223605302a5SGregory Neil Shapiro 				    *result != NULL)
1224605302a5SGregory Neil Shapiro 				{
1225605302a5SGregory Neil Shapiro 					/* only wanted one match */
1226605302a5SGregory Neil Shapiro 					SM_LDAP_ERROR_CLEANUP();
1227605302a5SGregory Neil Shapiro 					errno = ENOENT;
1228605302a5SGregory Neil Shapiro 					return EX_NOTFOUND;
1229605302a5SGregory Neil Shapiro 				}
1230605302a5SGregory Neil Shapiro 
123140266059SGregory Neil Shapiro 				vsize = 0;
123240266059SGregory Neil Shapiro 				for (i = 0; vals[i] != NULL; i++)
123340266059SGregory Neil Shapiro 				{
1234605302a5SGregory Neil Shapiro 					if (type == SM_LDAP_ATTR_DN ||
1235605302a5SGregory Neil Shapiro 					    type == SM_LDAP_ATTR_FILTER ||
1236605302a5SGregory Neil Shapiro 					    type == SM_LDAP_ATTR_URL)
123740266059SGregory Neil Shapiro 					{
1238605302a5SGregory Neil Shapiro 						/* add to recursion */
1239605302a5SGregory Neil Shapiro 						if (sm_ldap_add_recurse(&recurse,
124040266059SGregory Neil Shapiro 									vals[i],
1241605302a5SGregory Neil Shapiro 									type,
1242605302a5SGregory Neil Shapiro 									rpool) == NULL)
124340266059SGregory Neil Shapiro 						{
1244605302a5SGregory Neil Shapiro 							SM_LDAP_ERROR_CLEANUP();
124540266059SGregory Neil Shapiro 							errno = ENOMEM;
124640266059SGregory Neil Shapiro 							return EX_OSERR;
124740266059SGregory Neil Shapiro 						}
124840266059SGregory Neil Shapiro 						continue;
124940266059SGregory Neil Shapiro 					}
1250605302a5SGregory Neil Shapiro 
125140266059SGregory Neil Shapiro 					vsize += strlen(vals[i]) + 1;
125240266059SGregory Neil Shapiro 					if (lmap->ldap_attrsep != '\0')
125340266059SGregory Neil Shapiro 						vsize += strlen(attr) + 1;
125440266059SGregory Neil Shapiro 				}
1255605302a5SGregory Neil Shapiro 
1256605302a5SGregory Neil Shapiro 				/*
1257605302a5SGregory Neil Shapiro 				**  Create/Append to string any normal
1258605302a5SGregory Neil Shapiro 				**  attribute values.  Otherwise, just free
1259605302a5SGregory Neil Shapiro 				**  memory and move on to the next
1260605302a5SGregory Neil Shapiro 				**  attribute in this entry.
1261605302a5SGregory Neil Shapiro 				*/
1262605302a5SGregory Neil Shapiro 
1263605302a5SGregory Neil Shapiro 				if (type == SM_LDAP_ATTR_NORMAL && vsize > 0)
1264605302a5SGregory Neil Shapiro 				{
1265605302a5SGregory Neil Shapiro 					char *pe;
1266605302a5SGregory Neil Shapiro 
1267605302a5SGregory Neil Shapiro 					/* Grow result string if needed */
1268605302a5SGregory Neil Shapiro 					if ((*resultln + vsize) >= *resultsz)
1269605302a5SGregory Neil Shapiro 					{
1270605302a5SGregory Neil Shapiro 						while ((*resultln + vsize) >= *resultsz)
1271605302a5SGregory Neil Shapiro 						{
1272605302a5SGregory Neil Shapiro 							if (*resultsz == 0)
1273605302a5SGregory Neil Shapiro 								*resultsz = 1024;
1274605302a5SGregory Neil Shapiro 							else
1275605302a5SGregory Neil Shapiro 								*resultsz *= 2;
1276605302a5SGregory Neil Shapiro 						}
1277605302a5SGregory Neil Shapiro 
1278605302a5SGregory Neil Shapiro 						vp_tmp = sm_rpool_malloc_x(rpool, *resultsz);
127940266059SGregory Neil Shapiro 						*vp_tmp = '\0';
128040266059SGregory Neil Shapiro 
1281605302a5SGregory Neil Shapiro 						if (*result != NULL)
1282605302a5SGregory Neil Shapiro 							sm_strlcpy(vp_tmp,
1283605302a5SGregory Neil Shapiro 								   *result,
1284605302a5SGregory Neil Shapiro 								   *resultsz);
1285605302a5SGregory Neil Shapiro 						*result = vp_tmp;
1286605302a5SGregory Neil Shapiro 					}
1287605302a5SGregory Neil Shapiro 
1288605302a5SGregory Neil Shapiro 					p = *result + *resultln;
1289605302a5SGregory Neil Shapiro 					pe = *result + *resultsz;
1290605302a5SGregory Neil Shapiro 
129140266059SGregory Neil Shapiro 					for (i = 0; vals[i] != NULL; i++)
129240266059SGregory Neil Shapiro 					{
1293959366dcSGregory Neil Shapiro 						if (*resultln > 0 &&
1294959366dcSGregory Neil Shapiro 						    p < pe)
1295605302a5SGregory Neil Shapiro 							*p++ = (char) delim;
1296605302a5SGregory Neil Shapiro 
129740266059SGregory Neil Shapiro 						if (lmap->ldap_attrsep != '\0')
129840266059SGregory Neil Shapiro 						{
129940266059SGregory Neil Shapiro 							p += sm_strlcpy(p, attr,
1300605302a5SGregory Neil Shapiro 									pe - p);
1301605302a5SGregory Neil Shapiro 							if (p < pe)
130240266059SGregory Neil Shapiro 								*p++ = lmap->ldap_attrsep;
130340266059SGregory Neil Shapiro 						}
1304605302a5SGregory Neil Shapiro 
130540266059SGregory Neil Shapiro 						p += sm_strlcpy(p, vals[i],
1306605302a5SGregory Neil Shapiro 								pe - p);
1307605302a5SGregory Neil Shapiro 						*resultln = p - (*result);
1308605302a5SGregory Neil Shapiro 						if (p >= pe)
130940266059SGregory Neil Shapiro 						{
131040266059SGregory Neil Shapiro 							/* Internal error: buffer too small for LDAP values */
1311605302a5SGregory Neil Shapiro 							SM_LDAP_ERROR_CLEANUP();
131240266059SGregory Neil Shapiro 							errno = ENOMEM;
131340266059SGregory Neil Shapiro 							return EX_OSERR;
131440266059SGregory Neil Shapiro 						}
1315605302a5SGregory Neil Shapiro 					}
131640266059SGregory Neil Shapiro 				}
131740266059SGregory Neil Shapiro 
131840266059SGregory Neil Shapiro 				ldap_value_free(vals);
131940266059SGregory Neil Shapiro 				ldap_memfree(attr);
132040266059SGregory Neil Shapiro 			}
132140266059SGregory Neil Shapiro 			save_errno = sm_ldap_geterrno(lmap->ldap_ld);
132240266059SGregory Neil Shapiro 
132340266059SGregory Neil Shapiro 			/*
132440266059SGregory Neil Shapiro 			**  We check save_errno != LDAP_DECODING_ERROR since
132540266059SGregory Neil Shapiro 			**  OpenLDAP 1.X has a very ugly *undocumented*
132640266059SGregory Neil Shapiro 			**  hack of returning this error code from
132740266059SGregory Neil Shapiro 			**  ldap_next_attribute() if the library freed the
132840266059SGregory Neil Shapiro 			**  ber attribute.  See:
132940266059SGregory Neil Shapiro 			**  http://www.openldap.org/lists/openldap-devel/9901/msg00064.html
133040266059SGregory Neil Shapiro 			*/
133140266059SGregory Neil Shapiro 
133240266059SGregory Neil Shapiro 			if (save_errno != LDAP_SUCCESS &&
133340266059SGregory Neil Shapiro 			    save_errno != LDAP_DECODING_ERROR)
133440266059SGregory Neil Shapiro 			{
133540266059SGregory Neil Shapiro 				/* Must be an error */
133640266059SGregory Neil Shapiro 				save_errno += E_LDAPBASE;
1337605302a5SGregory Neil Shapiro 				SM_LDAP_ERROR_CLEANUP();
133840266059SGregory Neil Shapiro 				errno = save_errno;
133940266059SGregory Neil Shapiro 				return EX_TEMPFAIL;
134040266059SGregory Neil Shapiro 			}
134140266059SGregory Neil Shapiro 
1342605302a5SGregory Neil Shapiro 			/* mark this DN as done */
1343605302a5SGregory Neil Shapiro 			rl->lr_done = true;
1344e92d3f3fSGregory Neil Shapiro 			if (rl->lr_ludp != NULL)
1345e92d3f3fSGregory Neil Shapiro 			{
1346e92d3f3fSGregory Neil Shapiro 				ldap_free_urldesc(rl->lr_ludp);
1347e92d3f3fSGregory Neil Shapiro 				rl->lr_ludp = NULL;
1348e92d3f3fSGregory Neil Shapiro 			}
1349e92d3f3fSGregory Neil Shapiro 			if (rl->lr_attrs != NULL)
1350e92d3f3fSGregory Neil Shapiro 			{
1351e92d3f3fSGregory Neil Shapiro 				free(rl->lr_attrs);
1352e92d3f3fSGregory Neil Shapiro 				rl->lr_attrs = NULL;
1353e92d3f3fSGregory Neil Shapiro 			}
1354605302a5SGregory Neil Shapiro 
135540266059SGregory Neil Shapiro 			/* We don't want multiple values and we have one */
135613d88268SGregory Neil Shapiro 			if ((char) delim == '\0' &&
135713d88268SGregory Neil Shapiro 			    !bitset(SM_LDAP_SINGLEMATCH, flags) &&
135813d88268SGregory Neil Shapiro 			    *result != NULL)
135940266059SGregory Neil Shapiro 				break;
136040266059SGregory Neil Shapiro 		}
136140266059SGregory Neil Shapiro 		save_errno = sm_ldap_geterrno(lmap->ldap_ld);
136240266059SGregory Neil Shapiro 		if (save_errno != LDAP_SUCCESS &&
136340266059SGregory Neil Shapiro 		    save_errno != LDAP_DECODING_ERROR)
136440266059SGregory Neil Shapiro 		{
136540266059SGregory Neil Shapiro 			/* Must be an error */
136640266059SGregory Neil Shapiro 			save_errno += E_LDAPBASE;
1367605302a5SGregory Neil Shapiro 			SM_LDAP_ERROR_CLEANUP();
136840266059SGregory Neil Shapiro 			errno = save_errno;
136940266059SGregory Neil Shapiro 			return EX_TEMPFAIL;
137040266059SGregory Neil Shapiro 		}
137140266059SGregory Neil Shapiro 		ldap_msgfree(lmap->ldap_res);
137240266059SGregory Neil Shapiro 		lmap->ldap_res = NULL;
137340266059SGregory Neil Shapiro 	}
137440266059SGregory Neil Shapiro 
137540266059SGregory Neil Shapiro 	if (ret == 0)
137640266059SGregory Neil Shapiro 		save_errno = ETIMEDOUT;
13776f9c8e5bSGregory Neil Shapiro 	else if (ret == LDAP_RES_SEARCH_RESULT)
13789bd497b8SGregory Neil Shapiro 	{
13799bd497b8SGregory Neil Shapiro 		/*
13809bd497b8SGregory Neil Shapiro 		**  We may have gotten an LDAP_RES_SEARCH_RESULT response
13819bd497b8SGregory Neil Shapiro 		**  with an error inside it, so we have to extract that
13829bd497b8SGregory Neil Shapiro 		**  with ldap_parse_result().  This can happen when talking
13839bd497b8SGregory Neil Shapiro 		**  to an LDAP proxy whose backend has gone down.
13849bd497b8SGregory Neil Shapiro 		*/
13859bd497b8SGregory Neil Shapiro 
13866f9c8e5bSGregory Neil Shapiro 		if (lmap->ldap_res == NULL)
13876f9c8e5bSGregory Neil Shapiro 			save_errno = LDAP_UNAVAILABLE;
13886f9c8e5bSGregory Neil Shapiro 		else
13896f9c8e5bSGregory Neil Shapiro 		{
13906f9c8e5bSGregory Neil Shapiro 			int rc;
13916f9c8e5bSGregory Neil Shapiro 
13926f9c8e5bSGregory Neil Shapiro 			save_errno = ldap_parse_result(lmap->ldap_ld,
13936f9c8e5bSGregory Neil Shapiro 					lmap->ldap_res, &rc, NULL, NULL,
13946f9c8e5bSGregory Neil Shapiro 					NULL, NULL, 0);
13959bd497b8SGregory Neil Shapiro 			if (save_errno == LDAP_SUCCESS)
13969bd497b8SGregory Neil Shapiro 				save_errno = rc;
13979bd497b8SGregory Neil Shapiro 		}
13986f9c8e5bSGregory Neil Shapiro 	}
13996f9c8e5bSGregory Neil Shapiro 	else
14006f9c8e5bSGregory Neil Shapiro 		save_errno = sm_ldap_geterrno(lmap->ldap_ld);
140140266059SGregory Neil Shapiro 	if (save_errno != LDAP_SUCCESS)
140240266059SGregory Neil Shapiro 	{
140340266059SGregory Neil Shapiro 		statp = EX_TEMPFAIL;
140440266059SGregory Neil Shapiro 		switch (save_errno)
140540266059SGregory Neil Shapiro 		{
140640266059SGregory Neil Shapiro # ifdef LDAP_SERVER_DOWN
140740266059SGregory Neil Shapiro 		  case LDAP_SERVER_DOWN:
14082fb4f839SGregory Neil Shapiro # endif
140940266059SGregory Neil Shapiro 		  case LDAP_TIMEOUT:
1410ffb83623SGregory Neil Shapiro 		  case ETIMEDOUT:
141140266059SGregory Neil Shapiro 		  case LDAP_UNAVAILABLE:
1412605302a5SGregory Neil Shapiro 
1413605302a5SGregory Neil Shapiro 			/*
1414605302a5SGregory Neil Shapiro 			**  server disappeared,
1415605302a5SGregory Neil Shapiro 			**  try reopen on next search
1416605302a5SGregory Neil Shapiro 			*/
1417605302a5SGregory Neil Shapiro 
141840266059SGregory Neil Shapiro 			statp = EX_RESTART;
141940266059SGregory Neil Shapiro 			break;
142040266059SGregory Neil Shapiro 		}
1421ffb83623SGregory Neil Shapiro 		if (ret != 0)
142240266059SGregory Neil Shapiro 			save_errno += E_LDAPBASE;
1423605302a5SGregory Neil Shapiro 		SM_LDAP_ERROR_CLEANUP();
142440266059SGregory Neil Shapiro 		errno = save_errno;
142540266059SGregory Neil Shapiro 		return statp;
142640266059SGregory Neil Shapiro 	}
142740266059SGregory Neil Shapiro 
142840266059SGregory Neil Shapiro 	if (lmap->ldap_res != NULL)
142940266059SGregory Neil Shapiro 	{
143040266059SGregory Neil Shapiro 		ldap_msgfree(lmap->ldap_res);
143140266059SGregory Neil Shapiro 		lmap->ldap_res = NULL;
143240266059SGregory Neil Shapiro 	}
143340266059SGregory Neil Shapiro 
143440266059SGregory Neil Shapiro 	if (toplevel)
143540266059SGregory Neil Shapiro 	{
1436605302a5SGregory Neil Shapiro 		int rlidx;
143740266059SGregory Neil Shapiro 
143840266059SGregory Neil Shapiro 		/*
143940266059SGregory Neil Shapiro 		**  Spin through the built-up recurse list at the top
144040266059SGregory Neil Shapiro 		**  of the recursion.  Since new items are added at the
144140266059SGregory Neil Shapiro 		**  end of the shared list, we actually only ever get
144240266059SGregory Neil Shapiro 		**  one level of recursion before things pop back to the
144340266059SGregory Neil Shapiro 		**  top.  Any items added to the list during that recursion
144440266059SGregory Neil Shapiro 		**  will be expanded by the top level.
144540266059SGregory Neil Shapiro 		*/
144640266059SGregory Neil Shapiro 
1447d0cef73dSGregory Neil Shapiro 		for (rlidx = 0; recurse != NULL && rlidx < recurse->lrl_cnt;
1448d0cef73dSGregory Neil Shapiro 		     rlidx++)
144940266059SGregory Neil Shapiro 		{
1450605302a5SGregory Neil Shapiro 			int newflags;
145140266059SGregory Neil Shapiro 			int sid;
145240266059SGregory Neil Shapiro 			int status;
145340266059SGregory Neil Shapiro 
1454d0cef73dSGregory Neil Shapiro 			rl = recurse->lrl_data[rlidx];
1455605302a5SGregory Neil Shapiro 
1456605302a5SGregory Neil Shapiro 			newflags = flags;
1457605302a5SGregory Neil Shapiro 			if (rl->lr_done)
145840266059SGregory Neil Shapiro 			{
145940266059SGregory Neil Shapiro 				/* already expanded */
146040266059SGregory Neil Shapiro 				continue;
146140266059SGregory Neil Shapiro 			}
1462605302a5SGregory Neil Shapiro 
1463605302a5SGregory Neil Shapiro 			if (rl->lr_type == SM_LDAP_ATTR_DN)
146440266059SGregory Neil Shapiro 			{
146540266059SGregory Neil Shapiro 				/* do DN search */
146640266059SGregory Neil Shapiro 				sid = ldap_search(lmap->ldap_ld,
146740266059SGregory Neil Shapiro 						  rl->lr_search,
146840266059SGregory Neil Shapiro 						  lmap->ldap_scope,
146940266059SGregory Neil Shapiro 						  "(objectClass=*)",
1470605302a5SGregory Neil Shapiro 						  (lmap->ldap_attr[0] == NULL ?
1471605302a5SGregory Neil Shapiro 						   NULL : lmap->ldap_attr),
147240266059SGregory Neil Shapiro 						  lmap->ldap_attrsonly);
147340266059SGregory Neil Shapiro 			}
1474605302a5SGregory Neil Shapiro 			else if (rl->lr_type == SM_LDAP_ATTR_FILTER)
147540266059SGregory Neil Shapiro 			{
147640266059SGregory Neil Shapiro 				/* do new search */
147740266059SGregory Neil Shapiro 				sid = ldap_search(lmap->ldap_ld,
147840266059SGregory Neil Shapiro 						  lmap->ldap_base,
147940266059SGregory Neil Shapiro 						  lmap->ldap_scope,
148040266059SGregory Neil Shapiro 						  rl->lr_search,
1481605302a5SGregory Neil Shapiro 						  (lmap->ldap_attr[0] == NULL ?
1482605302a5SGregory Neil Shapiro 						   NULL : lmap->ldap_attr),
148340266059SGregory Neil Shapiro 						  lmap->ldap_attrsonly);
148440266059SGregory Neil Shapiro 			}
1485605302a5SGregory Neil Shapiro 			else if (rl->lr_type == SM_LDAP_ATTR_URL)
148640266059SGregory Neil Shapiro 			{
1487e92d3f3fSGregory Neil Shapiro 				/* Parse URL */
1488e92d3f3fSGregory Neil Shapiro 				sid = ldap_url_parse(rl->lr_search,
1489e92d3f3fSGregory Neil Shapiro 						     &rl->lr_ludp);
1490e92d3f3fSGregory Neil Shapiro 
1491e92d3f3fSGregory Neil Shapiro 				if (sid != 0)
1492e92d3f3fSGregory Neil Shapiro 				{
1493e92d3f3fSGregory Neil Shapiro 					errno = sid + E_LDAPURLBASE;
1494e92d3f3fSGregory Neil Shapiro 					return EX_TEMPFAIL;
1495e92d3f3fSGregory Neil Shapiro 				}
1496e92d3f3fSGregory Neil Shapiro 
1497e92d3f3fSGregory Neil Shapiro 				/* We need to add objectClass */
1498e92d3f3fSGregory Neil Shapiro 				if (rl->lr_ludp->lud_attrs != NULL)
1499e92d3f3fSGregory Neil Shapiro 				{
1500e92d3f3fSGregory Neil Shapiro 					int attrnum = 0;
1501e92d3f3fSGregory Neil Shapiro 
1502e92d3f3fSGregory Neil Shapiro 					while (rl->lr_ludp->lud_attrs[attrnum] != NULL)
1503e92d3f3fSGregory Neil Shapiro 					{
1504e92d3f3fSGregory Neil Shapiro 						if (strcasecmp(rl->lr_ludp->lud_attrs[attrnum],
1505e92d3f3fSGregory Neil Shapiro 							       "objectClass") == 0)
1506e92d3f3fSGregory Neil Shapiro 						{
1507e92d3f3fSGregory Neil Shapiro 							/* already requested */
1508e92d3f3fSGregory Neil Shapiro 							attrnum = -1;
1509e92d3f3fSGregory Neil Shapiro 							break;
1510e92d3f3fSGregory Neil Shapiro 						}
1511e92d3f3fSGregory Neil Shapiro 						attrnum++;
1512e92d3f3fSGregory Neil Shapiro 					}
1513e92d3f3fSGregory Neil Shapiro 
1514e92d3f3fSGregory Neil Shapiro 					if (attrnum >= 0)
1515e92d3f3fSGregory Neil Shapiro 					{
1516e92d3f3fSGregory Neil Shapiro 						int i;
1517e92d3f3fSGregory Neil Shapiro 
1518e92d3f3fSGregory Neil Shapiro 						rl->lr_attrs = (char **)malloc(sizeof(char *) * (attrnum + 2));
1519e92d3f3fSGregory Neil Shapiro 						if (rl->lr_attrs == NULL)
1520e92d3f3fSGregory Neil Shapiro 						{
1521e92d3f3fSGregory Neil Shapiro 							save_errno = errno;
1522e92d3f3fSGregory Neil Shapiro 							ldap_free_urldesc(rl->lr_ludp);
1523e92d3f3fSGregory Neil Shapiro 							errno = save_errno;
1524e92d3f3fSGregory Neil Shapiro 							return EX_TEMPFAIL;
1525e92d3f3fSGregory Neil Shapiro 						}
1526e92d3f3fSGregory Neil Shapiro 						for (i = 0 ; i < attrnum; i++)
1527e92d3f3fSGregory Neil Shapiro 						{
1528e92d3f3fSGregory Neil Shapiro 							rl->lr_attrs[i] = rl->lr_ludp->lud_attrs[i];
1529e92d3f3fSGregory Neil Shapiro 						}
1530e92d3f3fSGregory Neil Shapiro 						rl->lr_attrs[i++] = "objectClass";
1531e92d3f3fSGregory Neil Shapiro 						rl->lr_attrs[i++] = NULL;
1532e92d3f3fSGregory Neil Shapiro 					}
1533e92d3f3fSGregory Neil Shapiro 				}
1534e92d3f3fSGregory Neil Shapiro 
1535e92d3f3fSGregory Neil Shapiro 				/*
1536e92d3f3fSGregory Neil Shapiro 				**  Use the existing connection
1537e92d3f3fSGregory Neil Shapiro 				**  for this search.  It really
1538e92d3f3fSGregory Neil Shapiro 				**  should use lud_scheme://lud_host:lud_port/
1539e92d3f3fSGregory Neil Shapiro 				**  instead but that would require
1540e92d3f3fSGregory Neil Shapiro 				**  opening a new connection.
1541e92d3f3fSGregory Neil Shapiro 				**  This should be fixed ASAP.
1542e92d3f3fSGregory Neil Shapiro 				*/
1543e92d3f3fSGregory Neil Shapiro 
1544e92d3f3fSGregory Neil Shapiro 				sid = ldap_search(lmap->ldap_ld,
1545e92d3f3fSGregory Neil Shapiro 						  rl->lr_ludp->lud_dn,
1546e92d3f3fSGregory Neil Shapiro 						  rl->lr_ludp->lud_scope,
1547e92d3f3fSGregory Neil Shapiro 						  rl->lr_ludp->lud_filter,
1548e92d3f3fSGregory Neil Shapiro 						  rl->lr_attrs,
154940266059SGregory Neil Shapiro 						  lmap->ldap_attrsonly);
1550e92d3f3fSGregory Neil Shapiro 
1551e92d3f3fSGregory Neil Shapiro 				/* Use the attributes specified by URL */
1552605302a5SGregory Neil Shapiro 				newflags |= SM_LDAP_USE_ALLATTR;
155340266059SGregory Neil Shapiro 			}
155440266059SGregory Neil Shapiro 			else
155540266059SGregory Neil Shapiro 			{
155640266059SGregory Neil Shapiro 				/* unknown or illegal attribute type */
155740266059SGregory Neil Shapiro 				errno = EFAULT;
155840266059SGregory Neil Shapiro 				return EX_SOFTWARE;
155940266059SGregory Neil Shapiro 			}
156040266059SGregory Neil Shapiro 
156140266059SGregory Neil Shapiro 			/* Collect results */
156240266059SGregory Neil Shapiro 			if (sid == -1)
156340266059SGregory Neil Shapiro 			{
156440266059SGregory Neil Shapiro 				save_errno = sm_ldap_geterrno(lmap->ldap_ld);
156540266059SGregory Neil Shapiro 				statp = EX_TEMPFAIL;
156640266059SGregory Neil Shapiro 				switch (save_errno)
156740266059SGregory Neil Shapiro 				{
156840266059SGregory Neil Shapiro # ifdef LDAP_SERVER_DOWN
156940266059SGregory Neil Shapiro 				  case LDAP_SERVER_DOWN:
15702fb4f839SGregory Neil Shapiro # endif
157140266059SGregory Neil Shapiro 				  case LDAP_TIMEOUT:
1572ffb83623SGregory Neil Shapiro 				  case ETIMEDOUT:
157340266059SGregory Neil Shapiro 				  case LDAP_UNAVAILABLE:
1574605302a5SGregory Neil Shapiro 
1575605302a5SGregory Neil Shapiro 					/*
1576605302a5SGregory Neil Shapiro 					**  server disappeared,
1577605302a5SGregory Neil Shapiro 					**  try reopen on next search
1578605302a5SGregory Neil Shapiro 					*/
1579605302a5SGregory Neil Shapiro 
158040266059SGregory Neil Shapiro 					statp = EX_RESTART;
158140266059SGregory Neil Shapiro 					break;
158240266059SGregory Neil Shapiro 				}
158340266059SGregory Neil Shapiro 				errno = save_errno + E_LDAPBASE;
158440266059SGregory Neil Shapiro 				return statp;
158540266059SGregory Neil Shapiro 			}
158640266059SGregory Neil Shapiro 
1587605302a5SGregory Neil Shapiro 			status = sm_ldap_results(lmap, sid, newflags, delim,
1588605302a5SGregory Neil Shapiro 						 rpool, result, resultln,
1589605302a5SGregory Neil Shapiro 						 resultsz, recurse);
159040266059SGregory Neil Shapiro 			save_errno = errno;
159140266059SGregory Neil Shapiro 			if (status != EX_OK && status != EX_NOTFOUND)
159240266059SGregory Neil Shapiro 			{
159340266059SGregory Neil Shapiro 				errno = save_errno;
159440266059SGregory Neil Shapiro 				return status;
159540266059SGregory Neil Shapiro 			}
159640266059SGregory Neil Shapiro 
159740266059SGregory Neil Shapiro 			/* Mark as done */
1598605302a5SGregory Neil Shapiro 			rl->lr_done = true;
1599e92d3f3fSGregory Neil Shapiro 			if (rl->lr_ludp != NULL)
1600e92d3f3fSGregory Neil Shapiro 			{
1601e92d3f3fSGregory Neil Shapiro 				ldap_free_urldesc(rl->lr_ludp);
1602e92d3f3fSGregory Neil Shapiro 				rl->lr_ludp = NULL;
1603e92d3f3fSGregory Neil Shapiro 			}
1604e92d3f3fSGregory Neil Shapiro 			if (rl->lr_attrs != NULL)
1605e92d3f3fSGregory Neil Shapiro 			{
1606e92d3f3fSGregory Neil Shapiro 				free(rl->lr_attrs);
1607e92d3f3fSGregory Neil Shapiro 				rl->lr_attrs = NULL;
1608e92d3f3fSGregory Neil Shapiro 			}
1609605302a5SGregory Neil Shapiro 
1610605302a5SGregory Neil Shapiro 			/* Reset rlidx as new items may have been added */
1611605302a5SGregory Neil Shapiro 			rlidx = -1;
161240266059SGregory Neil Shapiro 		}
161340266059SGregory Neil Shapiro 	}
161440266059SGregory Neil Shapiro 	return statp;
161540266059SGregory Neil Shapiro }
161640266059SGregory Neil Shapiro 
161740266059SGregory Neil Shapiro /*
161840266059SGregory Neil Shapiro **  SM_LDAP_CLOSE -- close LDAP connection
161940266059SGregory Neil Shapiro **
162040266059SGregory Neil Shapiro **	Parameters:
162140266059SGregory Neil Shapiro **		lmap -- LDAP map information
162240266059SGregory Neil Shapiro **
162340266059SGregory Neil Shapiro **	Returns:
162440266059SGregory Neil Shapiro **		None.
162540266059SGregory Neil Shapiro */
162640266059SGregory Neil Shapiro 
162740266059SGregory Neil Shapiro void
sm_ldap_close(lmap)162840266059SGregory Neil Shapiro sm_ldap_close(lmap)
162940266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
163040266059SGregory Neil Shapiro {
163140266059SGregory Neil Shapiro 	if (lmap->ldap_ld == NULL)
163240266059SGregory Neil Shapiro 		return;
163340266059SGregory Neil Shapiro 
163440266059SGregory Neil Shapiro 	if (lmap->ldap_pid == getpid())
163540266059SGregory Neil Shapiro 		ldap_unbind(lmap->ldap_ld);
163640266059SGregory Neil Shapiro 	lmap->ldap_ld = NULL;
163740266059SGregory Neil Shapiro 	lmap->ldap_pid = 0;
163840266059SGregory Neil Shapiro }
1639*d39bd2c1SGregory Neil Shapiro 
164040266059SGregory Neil Shapiro /*
164140266059SGregory Neil Shapiro **  SM_LDAP_GETERRNO -- get ldap errno value
164240266059SGregory Neil Shapiro **
164340266059SGregory Neil Shapiro **	Parameters:
164440266059SGregory Neil Shapiro **		ld -- LDAP session handle
164540266059SGregory Neil Shapiro **
164640266059SGregory Neil Shapiro **	Returns:
164740266059SGregory Neil Shapiro **		LDAP errno.
164840266059SGregory Neil Shapiro */
164940266059SGregory Neil Shapiro 
165040266059SGregory Neil Shapiro int
sm_ldap_geterrno(ld)165140266059SGregory Neil Shapiro sm_ldap_geterrno(ld)
165240266059SGregory Neil Shapiro 	LDAP *ld;
165340266059SGregory Neil Shapiro {
165440266059SGregory Neil Shapiro 	int err = LDAP_SUCCESS;
165540266059SGregory Neil Shapiro 
165640266059SGregory Neil Shapiro # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3
16575b0945b5SGregory Neil Shapiro #  ifdef LDAP_OPT_RESULT_CODE
16585b0945b5SGregory Neil Shapiro #   define LDAP_GET_RESULT_CODE LDAP_OPT_RESULT_CODE
16595b0945b5SGregory Neil Shapiro #  else
16605b0945b5SGregory Neil Shapiro #   define LDAP_GET_RESULT_CODE LDAP_OPT_ERROR_NUMBER
16615b0945b5SGregory Neil Shapiro #  endif
16625b0945b5SGregory Neil Shapiro 	(void) ldap_get_option(ld, LDAP_GET_RESULT_CODE, &err);
16635b0945b5SGregory Neil Shapiro # else
166440266059SGregory Neil Shapiro #  ifdef LDAP_OPT_SIZELIMIT
166540266059SGregory Neil Shapiro 	err = ldap_get_lderrno(ld, NULL, NULL);
16665b0945b5SGregory Neil Shapiro #  else
166740266059SGregory Neil Shapiro 	err = ld->ld_errno;
166840266059SGregory Neil Shapiro 
166940266059SGregory Neil Shapiro 	/*
167040266059SGregory Neil Shapiro 	**  Reset value to prevent lingering LDAP_DECODING_ERROR due to
167140266059SGregory Neil Shapiro 	**  OpenLDAP 1.X's hack (see above)
167240266059SGregory Neil Shapiro 	*/
167340266059SGregory Neil Shapiro 
167440266059SGregory Neil Shapiro 	ld->ld_errno = LDAP_SUCCESS;
167540266059SGregory Neil Shapiro #  endif /* LDAP_OPT_SIZELIMIT */
167640266059SGregory Neil Shapiro # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */
167740266059SGregory Neil Shapiro 	return err;
167840266059SGregory Neil Shapiro }
1679*d39bd2c1SGregory Neil Shapiro 
1680*d39bd2c1SGregory Neil Shapiro /*
1681*d39bd2c1SGregory Neil Shapiro **  SM_LDAP_GETERROR -- get ldap error value
1682*d39bd2c1SGregory Neil Shapiro **
1683*d39bd2c1SGregory Neil Shapiro **	Parameters:
1684*d39bd2c1SGregory Neil Shapiro **		ld -- LDAP session handle
1685*d39bd2c1SGregory Neil Shapiro **
1686*d39bd2c1SGregory Neil Shapiro **	Returns:
1687*d39bd2c1SGregory Neil Shapiro **		LDAP error
1688*d39bd2c1SGregory Neil Shapiro */
1689*d39bd2c1SGregory Neil Shapiro 
1690*d39bd2c1SGregory Neil Shapiro static char *
sm_ldap_geterror(ld)1691*d39bd2c1SGregory Neil Shapiro sm_ldap_geterror(ld)
1692*d39bd2c1SGregory Neil Shapiro 	LDAP *ld;
1693*d39bd2c1SGregory Neil Shapiro {
1694*d39bd2c1SGregory Neil Shapiro 	char *error = NULL;
1695*d39bd2c1SGregory Neil Shapiro 
1696*d39bd2c1SGregory Neil Shapiro # if defined(LDAP_OPT_DIAGNOSTIC_MESSAGE)
1697*d39bd2c1SGregory Neil Shapiro 	(void) ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &error);
1698*d39bd2c1SGregory Neil Shapiro # endif
1699*d39bd2c1SGregory Neil Shapiro 	return error;
1700*d39bd2c1SGregory Neil Shapiro }
1701*d39bd2c1SGregory Neil Shapiro 
1702*d39bd2c1SGregory Neil Shapiro 
170340266059SGregory Neil Shapiro #endif /* LDAPMAP */
1704