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