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> 31*2fb4f839SGregory 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 3940266059SGregory Neil Shapiro /* 4040266059SGregory Neil Shapiro ** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT 4140266059SGregory Neil Shapiro ** 4240266059SGregory Neil Shapiro ** Parameters: 4340266059SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT to clear 4440266059SGregory Neil Shapiro ** 4540266059SGregory Neil Shapiro ** Returns: 4640266059SGregory Neil Shapiro ** None. 4740266059SGregory Neil Shapiro ** 4840266059SGregory Neil Shapiro */ 4940266059SGregory Neil Shapiro 504e4196cbSGregory Neil Shapiro # if _FFR_LDAP_VERSION 514e4196cbSGregory Neil Shapiro # if defined(LDAP_VERSION_MAX) && _FFR_LDAP_VERSION > LDAP_VERSION_MAX 52*2fb4f839SGregory Neil Shapiro # ERROR "_FFR_LDAP_VERSION > LDAP_VERSION_MAX" 535b0945b5SGregory Neil Shapiro # endif 544e4196cbSGregory Neil Shapiro # if defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN 55*2fb4f839SGregory Neil Shapiro # ERROR "_FFR_LDAP_VERSION < LDAP_VERSION_MAX" 565b0945b5SGregory Neil Shapiro # endif 574e4196cbSGregory Neil Shapiro # define SM_LDAP_VERSION_DEFAULT _FFR_LDAP_VERSION 584e4196cbSGregory Neil Shapiro # else /* _FFR_LDAP_VERSION */ 594e4196cbSGregory Neil Shapiro # define SM_LDAP_VERSION_DEFAULT 0 604e4196cbSGregory Neil Shapiro # endif /* _FFR_LDAP_VERSION */ 614e4196cbSGregory Neil Shapiro 6240266059SGregory Neil Shapiro void 6340266059SGregory Neil Shapiro sm_ldap_clear(lmap) 6440266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 6540266059SGregory Neil Shapiro { 6640266059SGregory Neil Shapiro if (lmap == NULL) 6740266059SGregory Neil Shapiro return; 6840266059SGregory Neil Shapiro 69e92d3f3fSGregory Neil Shapiro lmap->ldap_host = NULL; 7040266059SGregory Neil Shapiro lmap->ldap_port = LDAP_PORT; 71e92d3f3fSGregory Neil Shapiro lmap->ldap_uri = NULL; 724e4196cbSGregory Neil Shapiro lmap->ldap_version = SM_LDAP_VERSION_DEFAULT; 7340266059SGregory Neil Shapiro lmap->ldap_deref = LDAP_DEREF_NEVER; 7440266059SGregory Neil Shapiro lmap->ldap_timelimit = LDAP_NO_LIMIT; 7540266059SGregory Neil Shapiro lmap->ldap_sizelimit = LDAP_NO_LIMIT; 7640266059SGregory Neil Shapiro # ifdef LDAP_REFERRALS 7740266059SGregory Neil Shapiro lmap->ldap_options = LDAP_OPT_REFERRALS; 785b0945b5SGregory Neil Shapiro # else 7940266059SGregory Neil Shapiro lmap->ldap_options = 0; 805b0945b5SGregory Neil Shapiro # endif 8140266059SGregory Neil Shapiro lmap->ldap_attrsep = '\0'; 8240266059SGregory Neil Shapiro lmap->ldap_binddn = NULL; 8340266059SGregory Neil Shapiro lmap->ldap_secret = NULL; 8440266059SGregory Neil Shapiro lmap->ldap_method = LDAP_AUTH_SIMPLE; 8540266059SGregory Neil Shapiro lmap->ldap_base = NULL; 8640266059SGregory Neil Shapiro lmap->ldap_scope = LDAP_SCOPE_SUBTREE; 8740266059SGregory Neil Shapiro lmap->ldap_attrsonly = LDAPMAP_FALSE; 8840266059SGregory Neil Shapiro lmap->ldap_timeout.tv_sec = 0; 8940266059SGregory Neil Shapiro lmap->ldap_timeout.tv_usec = 0; 9040266059SGregory Neil Shapiro lmap->ldap_ld = NULL; 9140266059SGregory Neil Shapiro lmap->ldap_filter = NULL; 9240266059SGregory Neil Shapiro lmap->ldap_attr[0] = NULL; 93605302a5SGregory Neil Shapiro lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE; 94605302a5SGregory Neil Shapiro lmap->ldap_attr_needobjclass[0] = NULL; 9540266059SGregory Neil Shapiro lmap->ldap_res = NULL; 9640266059SGregory Neil Shapiro lmap->ldap_next = NULL; 9740266059SGregory Neil Shapiro lmap->ldap_pid = 0; 98d0cef73dSGregory Neil Shapiro lmap->ldap_multi_args = false; 9940266059SGregory Neil Shapiro } 10040266059SGregory Neil Shapiro 1015b0945b5SGregory Neil Shapiro # if _FFR_SM_LDAP_DBG && defined(LBER_OPT_LOG_PRINT_FN) 1025b0945b5SGregory Neil Shapiro static void ldap_debug_cb __P((const char *msg)); 1035b0945b5SGregory Neil Shapiro 1045b0945b5SGregory Neil Shapiro static void 1055b0945b5SGregory Neil Shapiro ldap_debug_cb(msg) 1065b0945b5SGregory Neil Shapiro const char *msg; 1075b0945b5SGregory Neil Shapiro { 1085b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 4)) 1095b0945b5SGregory Neil Shapiro sm_dprintf("%s", msg); 1105b0945b5SGregory Neil Shapiro } 1115b0945b5SGregory Neil Shapiro # endif /* _FFR_SM_LDAP_DBG && defined(LBER_OPT_LOG_PRINT_FN) */ 1125b0945b5SGregory Neil Shapiro 1135b0945b5SGregory Neil Shapiro 1145b0945b5SGregory Neil Shapiro # if LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) 1155b0945b5SGregory Neil Shapiro # define SET_LDAP_TMO(ld, lmap) \ 1165b0945b5SGregory Neil Shapiro do \ 1175b0945b5SGregory Neil Shapiro { \ 1185b0945b5SGregory Neil Shapiro if (lmap->ldap_networktmo > 0) \ 1195b0945b5SGregory Neil Shapiro { \ 1205b0945b5SGregory Neil Shapiro struct timeval tmo; \ 1215b0945b5SGregory Neil Shapiro \ 1225b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) \ 1235b0945b5SGregory Neil Shapiro sm_dprintf("ldap_networktmo=%d\n", \ 1245b0945b5SGregory Neil Shapiro lmap->ldap_networktmo); \ 1255b0945b5SGregory Neil Shapiro tmo.tv_sec = lmap->ldap_networktmo; \ 1265b0945b5SGregory Neil Shapiro tmo.tv_usec = 0; \ 1275b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tmo); \ 1285b0945b5SGregory Neil Shapiro } \ 1295b0945b5SGregory Neil Shapiro } while (0) 1305b0945b5SGregory Neil Shapiro # else /* LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) */ 1315b0945b5SGregory Neil Shapiro # define SET_LDAP_TMO(ld, lmap) 1325b0945b5SGregory Neil Shapiro # endif /* LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) */ 1335b0945b5SGregory Neil Shapiro 1345b0945b5SGregory Neil Shapiro /* 1355b0945b5SGregory Neil Shapiro ** SM_LDAP_SETOPTSG -- set some (global) LDAP options 1365b0945b5SGregory Neil Shapiro ** 1375b0945b5SGregory Neil Shapiro ** Parameters: 1385b0945b5SGregory Neil Shapiro ** lmap -- LDAP map information 1395b0945b5SGregory Neil Shapiro ** 1405b0945b5SGregory Neil Shapiro ** Returns: 1415b0945b5SGregory Neil Shapiro ** None. 1425b0945b5SGregory Neil Shapiro ** 1435b0945b5SGregory Neil Shapiro */ 1445b0945b5SGregory Neil Shapiro 1455b0945b5SGregory Neil Shapiro # if _FFR_SM_LDAP_DBG 1465b0945b5SGregory Neil Shapiro static bool dbg_init = false; 1475b0945b5SGregory Neil Shapiro # endif 1485b0945b5SGregory Neil Shapiro # if SM_CONF_LDAP_INITIALIZE 1495b0945b5SGregory Neil Shapiro static void sm_ldap_setoptsg __P((SM_LDAP_STRUCT *lmap)); 1505b0945b5SGregory Neil Shapiro static void 1515b0945b5SGregory Neil Shapiro sm_ldap_setoptsg(lmap) 1525b0945b5SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 1535b0945b5SGregory Neil Shapiro { 1545b0945b5SGregory Neil Shapiro # if USE_LDAP_SET_OPTION 1555b0945b5SGregory Neil Shapiro 1565b0945b5SGregory Neil Shapiro SET_LDAP_TMO(NULL, lmap); 1575b0945b5SGregory Neil Shapiro 1585b0945b5SGregory Neil Shapiro # if _FFR_SM_LDAP_DBG 1595b0945b5SGregory Neil Shapiro if (!dbg_init && sm_debug_active(&SmLDAPTrace, 1) && 1605b0945b5SGregory Neil Shapiro lmap->ldap_debug != 0) 1615b0945b5SGregory Neil Shapiro { 1625b0945b5SGregory Neil Shapiro int r; 1635b0945b5SGregory Neil Shapiro # if defined(LBER_OPT_LOG_PRINT_FN) 1645b0945b5SGregory Neil Shapiro r = ber_set_option(NULL, LBER_OPT_LOG_PRINT_FN, ldap_debug_cb); 1655b0945b5SGregory Neil Shapiro # endif 1665b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 1675b0945b5SGregory Neil Shapiro sm_dprintf("ldap_debug0=%d\n", lmap->ldap_debug); 1685b0945b5SGregory Neil Shapiro r = ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, 1695b0945b5SGregory Neil Shapiro &(lmap->ldap_debug)); 1705b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9) && r != LDAP_OPT_SUCCESS) 1715b0945b5SGregory Neil Shapiro sm_dprintf("ber_set_option=%d\n", r); 1725b0945b5SGregory Neil Shapiro r = ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 1735b0945b5SGregory Neil Shapiro &(lmap->ldap_debug)); 1745b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9) && r != LDAP_OPT_SUCCESS) 1755b0945b5SGregory Neil Shapiro sm_dprintf("ldap_set_option=%d\n", r); 1765b0945b5SGregory Neil Shapiro dbg_init = true; 1775b0945b5SGregory Neil Shapiro } 1785b0945b5SGregory Neil Shapiro # endif /* _FFR_SM_LDAP_DBG */ 1795b0945b5SGregory Neil Shapiro # endif /* USE_LDAP_SET_OPTION */ 1805b0945b5SGregory Neil Shapiro } 1815b0945b5SGregory Neil Shapiro # endif /* SM_CONF_LDAP_INITIALIZE */ 1825b0945b5SGregory Neil Shapiro 1835b0945b5SGregory Neil Shapiro /* 1845b0945b5SGregory Neil Shapiro ** SM_LDAP_SETOPTS -- set LDAP options 1855b0945b5SGregory Neil Shapiro ** 1865b0945b5SGregory Neil Shapiro ** Parameters: 1875b0945b5SGregory Neil Shapiro ** ld -- LDAP session handle 1885b0945b5SGregory Neil Shapiro ** lmap -- LDAP map information 1895b0945b5SGregory Neil Shapiro ** 1905b0945b5SGregory Neil Shapiro ** Returns: 1915b0945b5SGregory Neil Shapiro ** None. 1925b0945b5SGregory Neil Shapiro ** 1935b0945b5SGregory Neil Shapiro */ 1945b0945b5SGregory Neil Shapiro 1955b0945b5SGregory Neil Shapiro void 1965b0945b5SGregory Neil Shapiro sm_ldap_setopts(ld, lmap) 1975b0945b5SGregory Neil Shapiro LDAP *ld; 1985b0945b5SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 1995b0945b5SGregory Neil Shapiro { 2005b0945b5SGregory Neil Shapiro # if USE_LDAP_SET_OPTION 2015b0945b5SGregory Neil Shapiro if (lmap->ldap_version != 0) 2025b0945b5SGregory Neil Shapiro { 2035b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, 2045b0945b5SGregory Neil Shapiro &lmap->ldap_version); 2055b0945b5SGregory Neil Shapiro } 2065b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); 2075b0945b5SGregory Neil Shapiro if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) 2085b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); 2095b0945b5SGregory Neil Shapiro else 2105b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 2115b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); 2125b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); 2135b0945b5SGregory Neil Shapiro SET_LDAP_TMO(ld, lmap); 2145b0945b5SGregory Neil Shapiro # if _FFR_SM_LDAP_DBG 2155b0945b5SGregory Neil Shapiro if ((!dbg_init || ld != NULL) && sm_debug_active(&SmLDAPTrace, 1) 2165b0945b5SGregory Neil Shapiro && lmap->ldap_debug > 0) 2175b0945b5SGregory Neil Shapiro { 2185b0945b5SGregory Neil Shapiro int r; 2195b0945b5SGregory Neil Shapiro 2205b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 2215b0945b5SGregory Neil Shapiro sm_dprintf("ldap_debug=%d, dbg_init=%d\n", 2225b0945b5SGregory Neil Shapiro lmap->ldap_debug, dbg_init); 2235b0945b5SGregory Neil Shapiro r = ldap_set_option(ld, LDAP_OPT_DEBUG_LEVEL, 2245b0945b5SGregory Neil Shapiro &(lmap->ldap_debug)); 2255b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9) && r != LDAP_OPT_SUCCESS) 2265b0945b5SGregory Neil Shapiro sm_dprintf("ldap_set_option=%d\n", r); 2275b0945b5SGregory Neil Shapiro } 2285b0945b5SGregory Neil Shapiro # endif /* _FFR_SM_LDAP_DBG */ 2295b0945b5SGregory Neil Shapiro # ifdef LDAP_OPT_RESTART 2305b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); 2315b0945b5SGregory Neil Shapiro # endif 2325b0945b5SGregory Neil Shapiro 2335b0945b5SGregory Neil Shapiro # else /* USE_LDAP_SET_OPTION */ 2345b0945b5SGregory Neil Shapiro /* From here on in we can use ldap internal timelimits */ 2355b0945b5SGregory Neil Shapiro ld->ld_deref = lmap->ldap_deref; 2365b0945b5SGregory Neil Shapiro ld->ld_options = lmap->ldap_options; 2375b0945b5SGregory Neil Shapiro ld->ld_sizelimit = lmap->ldap_sizelimit; 2385b0945b5SGregory Neil Shapiro ld->ld_timelimit = lmap->ldap_timelimit; 2395b0945b5SGregory Neil Shapiro # endif /* USE_LDAP_SET_OPTION */ 2405b0945b5SGregory Neil Shapiro } 2415b0945b5SGregory Neil Shapiro 24240266059SGregory Neil Shapiro /* 24340266059SGregory Neil Shapiro ** SM_LDAP_START -- actually connect to an LDAP server 24440266059SGregory Neil Shapiro ** 24540266059SGregory Neil Shapiro ** Parameters: 24640266059SGregory Neil Shapiro ** name -- name of map for debug output. 24740266059SGregory Neil Shapiro ** lmap -- the LDAP map being opened. 24840266059SGregory Neil Shapiro ** 24940266059SGregory Neil Shapiro ** Returns: 25040266059SGregory Neil Shapiro ** true if connection is successful, false otherwise. 25140266059SGregory Neil Shapiro ** 25240266059SGregory Neil Shapiro ** Side Effects: 25340266059SGregory Neil Shapiro ** Populates lmap->ldap_ld. 25440266059SGregory Neil Shapiro */ 25540266059SGregory Neil Shapiro 2565b0945b5SGregory Neil Shapiro # if !USE_LDAP_INIT || !LDAP_NETWORK_TIMEOUT 25740266059SGregory Neil Shapiro static jmp_buf LDAPTimeout; 2585b0945b5SGregory Neil Shapiro static void ldaptimeout __P((int)); 25940266059SGregory Neil Shapiro 2605b0945b5SGregory Neil Shapiro /* ARGSUSED */ 2615b0945b5SGregory Neil Shapiro static void 2625b0945b5SGregory Neil Shapiro ldaptimeout(unused) 2635b0945b5SGregory Neil Shapiro int unused; 2645b0945b5SGregory Neil Shapiro { 2655b0945b5SGregory Neil Shapiro /* 2665b0945b5SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 2675b0945b5SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 2685b0945b5SGregory Neil Shapiro ** DOING. 2695b0945b5SGregory Neil Shapiro */ 2705b0945b5SGregory Neil Shapiro 2715b0945b5SGregory Neil Shapiro errno = ETIMEDOUT; 2725b0945b5SGregory Neil Shapiro longjmp(LDAPTimeout, 1); 2735b0945b5SGregory Neil Shapiro } 2745b0945b5SGregory Neil Shapiro 2755b0945b5SGregory Neil Shapiro 2765b0945b5SGregory Neil Shapiro #define SM_LDAP_SETTIMEOUT(to, where) \ 27740266059SGregory Neil Shapiro do \ 27840266059SGregory Neil Shapiro { \ 27940266059SGregory Neil Shapiro if (to != 0) \ 28040266059SGregory Neil Shapiro { \ 28140266059SGregory Neil Shapiro if (setjmp(LDAPTimeout) != 0) \ 28240266059SGregory Neil Shapiro { \ 2835b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) \ 2845b0945b5SGregory Neil Shapiro sm_dprintf("ldap_settimeout(%s)=triggered\n",\ 2855b0945b5SGregory Neil Shapiro where); \ 28640266059SGregory Neil Shapiro errno = ETIMEDOUT; \ 28740266059SGregory Neil Shapiro return false; \ 28840266059SGregory Neil Shapiro } \ 28940266059SGregory Neil Shapiro ev = sm_setevent(to, ldaptimeout, 0); \ 29040266059SGregory Neil Shapiro } \ 29140266059SGregory Neil Shapiro } while (0) 29240266059SGregory Neil Shapiro 29340266059SGregory Neil Shapiro #define SM_LDAP_CLEARTIMEOUT() \ 29440266059SGregory Neil Shapiro do \ 29540266059SGregory Neil Shapiro { \ 29640266059SGregory Neil Shapiro if (ev != NULL) \ 29740266059SGregory Neil Shapiro sm_clrevent(ev); \ 29840266059SGregory Neil Shapiro } while (0) 2995b0945b5SGregory Neil Shapiro # endif /* !USE_LDAP_INIT || !LDAP_NETWORK_TIMEOUT */ 30040266059SGregory Neil Shapiro 30140266059SGregory Neil Shapiro bool 30240266059SGregory Neil Shapiro sm_ldap_start(name, lmap) 30340266059SGregory Neil Shapiro char *name; 30440266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 30540266059SGregory Neil Shapiro { 306b6bacd31SGregory Neil Shapiro int save_errno = 0; 307e92d3f3fSGregory Neil Shapiro char *id; 3085b0945b5SGregory Neil Shapiro # if !USE_LDAP_INIT || !LDAP_NETWORK_TIMEOUT 30940266059SGregory Neil Shapiro SM_EVENT *ev = NULL; 3105b0945b5SGregory Neil Shapiro # endif 311e92d3f3fSGregory Neil Shapiro LDAP *ld = NULL; 3125b0945b5SGregory Neil Shapiro struct timeval tmo; 3135b0945b5SGregory Neil Shapiro int msgid, err, r; 31440266059SGregory Neil Shapiro 31540266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 2)) 31640266059SGregory Neil Shapiro sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name); 31740266059SGregory Neil Shapiro 318e92d3f3fSGregory Neil Shapiro if (lmap->ldap_host != NULL) 319e92d3f3fSGregory Neil Shapiro id = lmap->ldap_host; 320e92d3f3fSGregory Neil Shapiro else if (lmap->ldap_uri != NULL) 321e92d3f3fSGregory Neil Shapiro id = lmap->ldap_uri; 322605302a5SGregory Neil Shapiro else 323e92d3f3fSGregory Neil Shapiro id = "localhost"; 324e92d3f3fSGregory Neil Shapiro 325e92d3f3fSGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 326e92d3f3fSGregory Neil Shapiro { 327e92d3f3fSGregory Neil Shapiro /* Don't print a port number for LDAP URIs */ 328e92d3f3fSGregory Neil Shapiro if (lmap->ldap_uri != NULL) 329e92d3f3fSGregory Neil Shapiro sm_dprintf("ldapmap_start(%s)\n", id); 330e92d3f3fSGregory Neil Shapiro else 331e92d3f3fSGregory Neil Shapiro sm_dprintf("ldapmap_start(%s, %d)\n", id, 332e92d3f3fSGregory Neil Shapiro lmap->ldap_port); 333e92d3f3fSGregory Neil Shapiro } 334e92d3f3fSGregory Neil Shapiro 335e92d3f3fSGregory Neil Shapiro if (lmap->ldap_uri != NULL) 336e92d3f3fSGregory Neil Shapiro { 337e92d3f3fSGregory Neil Shapiro # if SM_CONF_LDAP_INITIALIZE 3385b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 3395b0945b5SGregory Neil Shapiro sm_dprintf("ldap_initialize(%s)\n", lmap->ldap_uri); 340e92d3f3fSGregory Neil Shapiro /* LDAP server supports URIs so use them directly */ 341e92d3f3fSGregory Neil Shapiro save_errno = ldap_initialize(&ld, lmap->ldap_uri); 3425b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 3435b0945b5SGregory Neil Shapiro sm_dprintf("ldap_initialize(%s)=%d, ld=%p\n", lmap->ldap_uri, save_errno, ld); 3445b0945b5SGregory Neil Shapiro sm_ldap_setoptsg(lmap); 3455b0945b5SGregory Neil Shapiro 346e92d3f3fSGregory Neil Shapiro # else /* SM_CONF_LDAP_INITIALIZE */ 347e92d3f3fSGregory Neil Shapiro LDAPURLDesc *ludp = NULL; 348e92d3f3fSGregory Neil Shapiro 349e92d3f3fSGregory Neil Shapiro /* Blast apart URL and use the ldap_init/ldap_open below */ 350e92d3f3fSGregory Neil Shapiro err = ldap_url_parse(lmap->ldap_uri, &ludp); 351e92d3f3fSGregory Neil Shapiro if (err != 0) 352e92d3f3fSGregory Neil Shapiro { 353e92d3f3fSGregory Neil Shapiro errno = err + E_LDAPURLBASE; 354e92d3f3fSGregory Neil Shapiro return false; 355e92d3f3fSGregory Neil Shapiro } 356e92d3f3fSGregory Neil Shapiro lmap->ldap_host = sm_strdup_x(ludp->lud_host); 357e92d3f3fSGregory Neil Shapiro if (lmap->ldap_host == NULL) 358e92d3f3fSGregory Neil Shapiro { 359e92d3f3fSGregory Neil Shapiro save_errno = errno; 360e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(ludp); 361e92d3f3fSGregory Neil Shapiro errno = save_errno; 362e92d3f3fSGregory Neil Shapiro return false; 363e92d3f3fSGregory Neil Shapiro } 364e92d3f3fSGregory Neil Shapiro lmap->ldap_port = ludp->lud_port; 365e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(ludp); 366e92d3f3fSGregory Neil Shapiro # endif /* SM_CONF_LDAP_INITIALIZE */ 367e92d3f3fSGregory Neil Shapiro } 368e92d3f3fSGregory Neil Shapiro 369e92d3f3fSGregory Neil Shapiro if (ld == NULL) 370e92d3f3fSGregory Neil Shapiro { 371e92d3f3fSGregory Neil Shapiro # if USE_LDAP_INIT 3725b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 3735b0945b5SGregory Neil Shapiro sm_dprintf("ldap_init(%s, %d)\n", lmap->ldap_host, lmap->ldap_port); 374e92d3f3fSGregory Neil Shapiro ld = ldap_init(lmap->ldap_host, lmap->ldap_port); 37540266059SGregory Neil Shapiro save_errno = errno; 3765b0945b5SGregory Neil Shapiro 37740266059SGregory Neil Shapiro # else /* USE_LDAP_INIT */ 37840266059SGregory Neil Shapiro /* 37940266059SGregory Neil Shapiro ** If using ldap_open(), the actual connection to the server 38040266059SGregory Neil Shapiro ** happens now so we need the timeout here. For ldap_init(), 38140266059SGregory Neil Shapiro ** the connection happens at bind time. 38240266059SGregory Neil Shapiro */ 38340266059SGregory Neil Shapiro 3845b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 3855b0945b5SGregory Neil Shapiro sm_dprintf("ldap_open(%s, %d)\n", lmap->ldap_host, lmap->ldap_port); 3865b0945b5SGregory Neil Shapiro 3875b0945b5SGregory Neil Shapiro SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec, "ldap_open"); 388e92d3f3fSGregory Neil Shapiro ld = ldap_open(lmap->ldap_host, lmap->ldap_port); 38940266059SGregory Neil Shapiro save_errno = errno; 39040266059SGregory Neil Shapiro 39140266059SGregory Neil Shapiro /* clear the event if it has not sprung */ 39240266059SGregory Neil Shapiro SM_LDAP_CLEARTIMEOUT(); 39340266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 394e92d3f3fSGregory Neil Shapiro } 39540266059SGregory Neil Shapiro 39640266059SGregory Neil Shapiro errno = save_errno; 39740266059SGregory Neil Shapiro if (ld == NULL) 3985b0945b5SGregory Neil Shapiro { 3995b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 7)) 4005b0945b5SGregory Neil Shapiro sm_dprintf("FAIL: ldap_open(%s, %d)=%d\n", lmap->ldap_host, lmap->ldap_port, save_errno); 40140266059SGregory Neil Shapiro return false; 4025b0945b5SGregory Neil Shapiro } 40340266059SGregory Neil Shapiro 40440266059SGregory Neil Shapiro sm_ldap_setopts(ld, lmap); 4055b0945b5SGregory Neil Shapiro # if USE_LDAP_INIT && !LDAP_NETWORK_TIMEOUT 40640266059SGregory Neil Shapiro /* 40740266059SGregory Neil Shapiro ** If using ldap_init(), the actual connection to the server 40840266059SGregory Neil Shapiro ** happens at ldap_bind_s() so we need the timeout here. 40940266059SGregory Neil Shapiro */ 41040266059SGregory Neil Shapiro 4115b0945b5SGregory Neil Shapiro SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec, "ldap_bind"); 4125b0945b5SGregory Neil Shapiro # endif /* USE_LDAP_INIT && !LDAP_NETWORK_TIMEOUT */ 41340266059SGregory Neil Shapiro 41440266059SGregory Neil Shapiro # ifdef LDAP_AUTH_KRBV4 41540266059SGregory Neil Shapiro if (lmap->ldap_method == LDAP_AUTH_KRBV4 && 41640266059SGregory Neil Shapiro lmap->ldap_secret != NULL) 41740266059SGregory Neil Shapiro { 41840266059SGregory Neil Shapiro /* 41940266059SGregory Neil Shapiro ** Need to put ticket in environment here instead of 42040266059SGregory Neil Shapiro ** during parseargs as there may be different tickets 42140266059SGregory Neil Shapiro ** for different LDAP connections. 42240266059SGregory Neil Shapiro */ 42340266059SGregory Neil Shapiro 42440266059SGregory Neil Shapiro (void) putenv(lmap->ldap_secret); 42540266059SGregory Neil Shapiro } 42640266059SGregory Neil Shapiro # endif /* LDAP_AUTH_KRBV4 */ 42740266059SGregory Neil Shapiro 4285b0945b5SGregory Neil Shapiro # if LDAP_NETWORK_TIMEOUT 4295b0945b5SGregory Neil Shapiro tmo.tv_sec = lmap->ldap_networktmo; 4305b0945b5SGregory Neil Shapiro # else 4315b0945b5SGregory Neil Shapiro tmo.tv_sec = lmap->ldap_timeout.tv_sec; 4325b0945b5SGregory Neil Shapiro # endif 4335b0945b5SGregory Neil Shapiro tmo.tv_usec = 0; 43440266059SGregory Neil Shapiro 4355b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 4365b0945b5SGregory Neil Shapiro sm_dprintf("ldap_bind(%s)\n", lmap->ldap_uri); 4375b0945b5SGregory Neil Shapiro errno = 0; 4385b0945b5SGregory Neil Shapiro msgid = ldap_bind(ld, lmap->ldap_binddn, lmap->ldap_secret, 4395b0945b5SGregory Neil Shapiro lmap->ldap_method); 4405b0945b5SGregory Neil Shapiro save_errno = errno; 4415b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 4425b0945b5SGregory Neil Shapiro sm_dprintf("ldap_bind(%s)=%d, errno=%d, tmo=%ld\n", 4435b0945b5SGregory Neil Shapiro lmap->ldap_uri, msgid, save_errno, 4445b0945b5SGregory Neil Shapiro (long) tmo.tv_sec); 4455b0945b5SGregory Neil Shapiro if (-1 == msgid) 4465b0945b5SGregory Neil Shapiro { 4475b0945b5SGregory Neil Shapiro r = -1; 4485b0945b5SGregory Neil Shapiro goto fail; 4495b0945b5SGregory Neil Shapiro } 4505b0945b5SGregory Neil Shapiro 4515b0945b5SGregory Neil Shapiro errno = 0; 4525b0945b5SGregory Neil Shapiro r = ldap_result(ld, msgid, LDAP_MSG_ALL, 4535b0945b5SGregory Neil Shapiro tmo.tv_sec == 0 ? NULL : &(tmo), &(lmap->ldap_res)); 4545b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 4555b0945b5SGregory Neil Shapiro sm_dprintf("ldap_result(%s)=%d, errno=%d\n", lmap->ldap_uri, r, errno); 4565b0945b5SGregory Neil Shapiro if (-1 == r) 4575b0945b5SGregory Neil Shapiro goto fail; 4585b0945b5SGregory Neil Shapiro if (0 == r) 4595b0945b5SGregory Neil Shapiro { 4605b0945b5SGregory Neil Shapiro save_errno = ETIMEDOUT; 4615b0945b5SGregory Neil Shapiro r = -1; 4625b0945b5SGregory Neil Shapiro goto fail; 4635b0945b5SGregory Neil Shapiro } 4645b0945b5SGregory Neil Shapiro r = ldap_parse_result(ld, lmap->ldap_res, &err, NULL, NULL, NULL, NULL, 4655b0945b5SGregory Neil Shapiro 1); 4665b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 4675b0945b5SGregory Neil Shapiro sm_dprintf("ldap_parse_result(%s)=%d, err=%d\n", lmap->ldap_uri, r, err); 4685b0945b5SGregory Neil Shapiro if (r != LDAP_SUCCESS) 4695b0945b5SGregory Neil Shapiro goto fail; 4705b0945b5SGregory Neil Shapiro if (err != LDAP_SUCCESS) 4715b0945b5SGregory Neil Shapiro { 4725b0945b5SGregory Neil Shapiro r = -1; 4735b0945b5SGregory Neil Shapiro goto fail; 4745b0945b5SGregory Neil Shapiro } 4755b0945b5SGregory Neil Shapiro 4765b0945b5SGregory Neil Shapiro # if USE_LDAP_INIT && !LDAP_NETWORK_TIMEOUT 47740266059SGregory Neil Shapiro /* clear the event if it has not sprung */ 47840266059SGregory Neil Shapiro SM_LDAP_CLEARTIMEOUT(); 4795b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 4805b0945b5SGregory Neil Shapiro sm_dprintf("ldap_cleartimeout(%s)\n", lmap->ldap_uri); 4815b0945b5SGregory Neil Shapiro # endif /* USE_LDAP_INIT && !LDAP_NETWORK_TIMEOUT */ 48240266059SGregory Neil Shapiro 4835b0945b5SGregory Neil Shapiro if (r != LDAP_SUCCESS) 48440266059SGregory Neil Shapiro { 4855b0945b5SGregory Neil Shapiro fail: 4865b0945b5SGregory Neil Shapiro if (-1 == r) 4875b0945b5SGregory Neil Shapiro errno = save_errno; 4885b0945b5SGregory Neil Shapiro else 4895b0945b5SGregory Neil Shapiro errno = r + E_LDAPBASE; 49040266059SGregory Neil Shapiro return false; 49140266059SGregory Neil Shapiro } 49240266059SGregory Neil Shapiro 49340266059SGregory Neil Shapiro /* Save PID to make sure only this PID closes the LDAP connection */ 49440266059SGregory Neil Shapiro lmap->ldap_pid = getpid(); 49540266059SGregory Neil Shapiro lmap->ldap_ld = ld; 49640266059SGregory Neil Shapiro return true; 49740266059SGregory Neil Shapiro } 49840266059SGregory Neil Shapiro 49940266059SGregory Neil Shapiro /* 500d0cef73dSGregory Neil Shapiro ** SM_LDAP_SEARCH_M -- initiate multi-key LDAP search 50140266059SGregory Neil Shapiro ** 50240266059SGregory Neil Shapiro ** Initiate an LDAP search, return the msgid. 50340266059SGregory Neil Shapiro ** The calling function must collect the results. 50440266059SGregory Neil Shapiro ** 50540266059SGregory Neil Shapiro ** Parameters: 50640266059SGregory Neil Shapiro ** lmap -- LDAP map information 507d0cef73dSGregory Neil Shapiro ** argv -- key vector of substitutions in LDAP filter 508d0cef73dSGregory Neil Shapiro ** NOTE: argv must have SM_LDAP_ARGS elements to prevent 509d0cef73dSGregory Neil Shapiro ** out of bound array references 51040266059SGregory Neil Shapiro ** 51140266059SGregory Neil Shapiro ** Returns: 512d0cef73dSGregory Neil Shapiro ** <0 on failure (SM_LDAP_ERR*), msgid on success 51340266059SGregory Neil Shapiro ** 51440266059SGregory Neil Shapiro */ 51540266059SGregory Neil Shapiro 51640266059SGregory Neil Shapiro int 517d0cef73dSGregory Neil Shapiro sm_ldap_search_m(lmap, argv) 51840266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 519d0cef73dSGregory Neil Shapiro char **argv; 52040266059SGregory Neil Shapiro { 52140266059SGregory Neil Shapiro int msgid; 52240266059SGregory Neil Shapiro char *fp, *p, *q; 52340266059SGregory Neil Shapiro char filter[LDAPMAP_MAX_FILTER + 1]; 52440266059SGregory Neil Shapiro 525d0cef73dSGregory Neil Shapiro SM_REQUIRE(lmap != NULL); 526d0cef73dSGregory Neil Shapiro SM_REQUIRE(argv != NULL); 527d0cef73dSGregory Neil Shapiro SM_REQUIRE(argv[0] != NULL); 528d0cef73dSGregory Neil Shapiro 52940266059SGregory Neil Shapiro memset(filter, '\0', sizeof filter); 53040266059SGregory Neil Shapiro fp = filter; 53140266059SGregory Neil Shapiro p = lmap->ldap_filter; 53240266059SGregory Neil Shapiro while ((q = strchr(p, '%')) != NULL) 53340266059SGregory Neil Shapiro { 534d0cef73dSGregory Neil Shapiro char *key; 535d0cef73dSGregory Neil Shapiro 536d0cef73dSGregory Neil Shapiro if (lmap->ldap_multi_args) 537d0cef73dSGregory Neil Shapiro { 538d0cef73dSGregory Neil Shapiro # if SM_LDAP_ARGS < 10 539d0cef73dSGregory Neil Shapiro # ERROR _SM_LDAP_ARGS must be 10 540*2fb4f839SGregory Neil Shapiro # endif 541d0cef73dSGregory Neil Shapiro if (q[1] == 's') 542d0cef73dSGregory Neil Shapiro key = argv[0]; 543d0cef73dSGregory Neil Shapiro else if (q[1] >= '0' && q[1] <= '9') 544d0cef73dSGregory Neil Shapiro { 545d0cef73dSGregory Neil Shapiro key = argv[q[1] - '0']; 546d0cef73dSGregory Neil Shapiro if (key == NULL) 547d0cef73dSGregory Neil Shapiro { 548d0cef73dSGregory Neil Shapiro # if SM_LDAP_ERROR_ON_MISSING_ARGS 549d0cef73dSGregory Neil Shapiro return SM_LDAP_ERR_ARG_MISS; 550*2fb4f839SGregory Neil Shapiro # else 551d0cef73dSGregory Neil Shapiro key = ""; 552*2fb4f839SGregory Neil Shapiro # endif 553d0cef73dSGregory Neil Shapiro } 554d0cef73dSGregory Neil Shapiro } 555d0cef73dSGregory Neil Shapiro else 556d0cef73dSGregory Neil Shapiro key = NULL; 557d0cef73dSGregory Neil Shapiro } 558d0cef73dSGregory Neil Shapiro else 559d0cef73dSGregory Neil Shapiro key = argv[0]; 560d0cef73dSGregory Neil Shapiro 56140266059SGregory Neil Shapiro if (q[1] == 's') 56240266059SGregory Neil Shapiro { 56340266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 56440266059SGregory Neil Shapiro "%.*s%s", (int) (q - p), p, key); 56540266059SGregory Neil Shapiro fp += strlen(fp); 56640266059SGregory Neil Shapiro p = q + 2; 56740266059SGregory Neil Shapiro } 568d0cef73dSGregory Neil Shapiro else if (q[1] == '0' || 569d0cef73dSGregory Neil Shapiro (lmap->ldap_multi_args && q[1] >= '0' && q[1] <= '9')) 57040266059SGregory Neil Shapiro { 57140266059SGregory Neil Shapiro char *k = key; 57240266059SGregory Neil Shapiro 57340266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 57440266059SGregory Neil Shapiro "%.*s", (int) (q - p), p); 57540266059SGregory Neil Shapiro fp += strlen(fp); 57640266059SGregory Neil Shapiro p = q + 2; 57740266059SGregory Neil Shapiro 57840266059SGregory Neil Shapiro /* Properly escape LDAP special characters */ 57940266059SGregory Neil Shapiro while (SPACELEFT(filter, fp) > 0 && 58040266059SGregory Neil Shapiro *k != '\0') 58140266059SGregory Neil Shapiro { 58240266059SGregory Neil Shapiro if (*k == '*' || *k == '(' || 58340266059SGregory Neil Shapiro *k == ')' || *k == '\\') 58440266059SGregory Neil Shapiro { 58540266059SGregory Neil Shapiro (void) sm_strlcat(fp, 58640266059SGregory Neil Shapiro (*k == '*' ? "\\2A" : 58740266059SGregory Neil Shapiro (*k == '(' ? "\\28" : 58840266059SGregory Neil Shapiro (*k == ')' ? "\\29" : 58940266059SGregory Neil Shapiro (*k == '\\' ? "\\5C" : 59040266059SGregory Neil Shapiro "\00")))), 59140266059SGregory Neil Shapiro SPACELEFT(filter, fp)); 59240266059SGregory Neil Shapiro fp += strlen(fp); 59340266059SGregory Neil Shapiro k++; 59440266059SGregory Neil Shapiro } 59540266059SGregory Neil Shapiro else 59640266059SGregory Neil Shapiro *fp++ = *k++; 59740266059SGregory Neil Shapiro } 59840266059SGregory Neil Shapiro } 59940266059SGregory Neil Shapiro else 60040266059SGregory Neil Shapiro { 60140266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 60240266059SGregory Neil Shapiro "%.*s", (int) (q - p + 1), p); 60340266059SGregory Neil Shapiro p = q + (q[1] == '%' ? 2 : 1); 60440266059SGregory Neil Shapiro fp += strlen(fp); 60540266059SGregory Neil Shapiro } 60640266059SGregory Neil Shapiro } 60740266059SGregory Neil Shapiro (void) sm_strlcpy(fp, p, SPACELEFT(filter, fp)); 60840266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 20)) 60940266059SGregory Neil Shapiro sm_dprintf("ldap search filter=%s\n", filter); 61040266059SGregory Neil Shapiro 61140266059SGregory Neil Shapiro lmap->ldap_res = NULL; 612605302a5SGregory Neil Shapiro msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, 613605302a5SGregory Neil Shapiro lmap->ldap_scope, filter, 61440266059SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? NULL : 61540266059SGregory Neil Shapiro lmap->ldap_attr), 61640266059SGregory Neil Shapiro lmap->ldap_attrsonly); 61740266059SGregory Neil Shapiro return msgid; 61840266059SGregory Neil Shapiro } 61940266059SGregory Neil Shapiro 62040266059SGregory Neil Shapiro /* 621d0cef73dSGregory Neil Shapiro ** SM_LDAP_SEARCH -- initiate LDAP search 622d0cef73dSGregory Neil Shapiro ** 623d0cef73dSGregory Neil Shapiro ** Initiate an LDAP search, return the msgid. 624d0cef73dSGregory Neil Shapiro ** The calling function must collect the results. 625d0cef73dSGregory Neil Shapiro ** Note this is just a wrapper into sm_ldap_search_m() 626d0cef73dSGregory Neil Shapiro ** 627d0cef73dSGregory Neil Shapiro ** Parameters: 628d0cef73dSGregory Neil Shapiro ** lmap -- LDAP map information 629d0cef73dSGregory Neil Shapiro ** key -- key to substitute in LDAP filter 630d0cef73dSGregory Neil Shapiro ** 631d0cef73dSGregory Neil Shapiro ** Returns: 632d0cef73dSGregory Neil Shapiro ** <0 on failure, msgid on success 633d0cef73dSGregory Neil Shapiro ** 634d0cef73dSGregory Neil Shapiro */ 635d0cef73dSGregory Neil Shapiro 636d0cef73dSGregory Neil Shapiro int 637d0cef73dSGregory Neil Shapiro sm_ldap_search(lmap, key) 638d0cef73dSGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 639d0cef73dSGregory Neil Shapiro char *key; 640d0cef73dSGregory Neil Shapiro { 641d0cef73dSGregory Neil Shapiro char *argv[SM_LDAP_ARGS]; 642d0cef73dSGregory Neil Shapiro 643d0cef73dSGregory Neil Shapiro memset(argv, '\0', sizeof argv); 644d0cef73dSGregory Neil Shapiro argv[0] = key; 645d0cef73dSGregory Neil Shapiro return sm_ldap_search_m(lmap, argv); 646d0cef73dSGregory Neil Shapiro } 647d0cef73dSGregory Neil Shapiro 648d0cef73dSGregory Neil Shapiro /* 649605302a5SGregory Neil Shapiro ** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a 650605302a5SGregory Neil Shapiro ** particular objectClass 651605302a5SGregory Neil Shapiro ** 652605302a5SGregory Neil Shapiro ** Parameters: 653605302a5SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT in use 654605302a5SGregory Neil Shapiro ** entry -- current LDAP entry struct 655605302a5SGregory Neil Shapiro ** ocvalue -- particular objectclass in question. 656605302a5SGregory Neil Shapiro ** may be of form (fee|foo|fum) meaning 657605302a5SGregory Neil Shapiro ** any entry can be part of either fee, 658605302a5SGregory Neil Shapiro ** foo or fum objectclass 659605302a5SGregory Neil Shapiro ** 660605302a5SGregory Neil Shapiro ** Returns: 661605302a5SGregory Neil Shapiro ** true if item has that objectClass 662605302a5SGregory Neil Shapiro */ 663605302a5SGregory Neil Shapiro 664605302a5SGregory Neil Shapiro static bool 665605302a5SGregory Neil Shapiro sm_ldap_has_objectclass(lmap, entry, ocvalue) 666605302a5SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 667605302a5SGregory Neil Shapiro LDAPMessage *entry; 668605302a5SGregory Neil Shapiro char *ocvalue; 669605302a5SGregory Neil Shapiro { 670605302a5SGregory Neil Shapiro char **vals = NULL; 671605302a5SGregory Neil Shapiro int i; 672605302a5SGregory Neil Shapiro 673605302a5SGregory Neil Shapiro if (ocvalue == NULL) 674605302a5SGregory Neil Shapiro return false; 675605302a5SGregory Neil Shapiro 676605302a5SGregory Neil Shapiro vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass"); 677605302a5SGregory Neil Shapiro if (vals == NULL) 678605302a5SGregory Neil Shapiro return false; 679605302a5SGregory Neil Shapiro 680605302a5SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 681605302a5SGregory Neil Shapiro { 682605302a5SGregory Neil Shapiro char *p; 683605302a5SGregory Neil Shapiro char *q; 684605302a5SGregory Neil Shapiro 685605302a5SGregory Neil Shapiro p = q = ocvalue; 686605302a5SGregory Neil Shapiro while (*p != '\0') 687605302a5SGregory Neil Shapiro { 688605302a5SGregory Neil Shapiro while (*p != '\0' && *p != '|') 689605302a5SGregory Neil Shapiro p++; 690605302a5SGregory Neil Shapiro 691605302a5SGregory Neil Shapiro if ((p - q) == strlen(vals[i]) && 692605302a5SGregory Neil Shapiro sm_strncasecmp(vals[i], q, p - q) == 0) 693605302a5SGregory Neil Shapiro { 694605302a5SGregory Neil Shapiro ldap_value_free(vals); 695605302a5SGregory Neil Shapiro return true; 696605302a5SGregory Neil Shapiro } 697605302a5SGregory Neil Shapiro 698605302a5SGregory Neil Shapiro while (*p == '|') 699605302a5SGregory Neil Shapiro p++; 700605302a5SGregory Neil Shapiro q = p; 701605302a5SGregory Neil Shapiro } 702605302a5SGregory Neil Shapiro } 703605302a5SGregory Neil Shapiro 704605302a5SGregory Neil Shapiro ldap_value_free(vals); 705605302a5SGregory Neil Shapiro return false; 706605302a5SGregory Neil Shapiro } 707605302a5SGregory Neil Shapiro 708605302a5SGregory Neil Shapiro /* 70940266059SGregory Neil Shapiro ** SM_LDAP_RESULTS -- return results from an LDAP lookup in result 71040266059SGregory Neil Shapiro ** 71140266059SGregory Neil Shapiro ** Parameters: 71240266059SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT in use 71340266059SGregory Neil Shapiro ** msgid -- msgid returned by sm_ldap_search() 71440266059SGregory Neil Shapiro ** flags -- flags for the lookup 71540266059SGregory Neil Shapiro ** delim -- delimiter for result concatenation 71640266059SGregory Neil Shapiro ** rpool -- memory pool for storage 71740266059SGregory Neil Shapiro ** result -- return string 71840266059SGregory Neil Shapiro ** recurse -- recursion list 71940266059SGregory Neil Shapiro ** 72040266059SGregory Neil Shapiro ** Returns: 72140266059SGregory Neil Shapiro ** status (sysexit) 72240266059SGregory Neil Shapiro */ 72340266059SGregory Neil Shapiro 724605302a5SGregory Neil Shapiro # define SM_LDAP_ERROR_CLEANUP() \ 72540266059SGregory Neil Shapiro { \ 72640266059SGregory Neil Shapiro if (lmap->ldap_res != NULL) \ 72740266059SGregory Neil Shapiro { \ 72840266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); \ 72940266059SGregory Neil Shapiro lmap->ldap_res = NULL; \ 73040266059SGregory Neil Shapiro } \ 73140266059SGregory Neil Shapiro (void) ldap_abandon(lmap->ldap_ld, msgid); \ 73240266059SGregory Neil Shapiro } 73340266059SGregory Neil Shapiro 734605302a5SGregory Neil Shapiro static SM_LDAP_RECURSE_ENTRY * 735605302a5SGregory Neil Shapiro sm_ldap_add_recurse(top, item, type, rpool) 73640266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST **top; 73740266059SGregory Neil Shapiro char *item; 73840266059SGregory Neil Shapiro int type; 73940266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 74040266059SGregory Neil Shapiro { 741605302a5SGregory Neil Shapiro int n; 742605302a5SGregory Neil Shapiro int m; 743605302a5SGregory Neil Shapiro int p; 744605302a5SGregory Neil Shapiro int insertat; 745605302a5SGregory Neil Shapiro int moveb; 746605302a5SGregory Neil Shapiro int oldsizeb; 747605302a5SGregory Neil Shapiro int rc; 748605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY *newe; 749605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY **olddata; 75040266059SGregory Neil Shapiro 751605302a5SGregory Neil Shapiro /* 752605302a5SGregory Neil Shapiro ** This code will maintain a list of 753605302a5SGregory Neil Shapiro ** SM_LDAP_RECURSE_ENTRY structures 754605302a5SGregory Neil Shapiro ** in ascending order. 755605302a5SGregory Neil Shapiro */ 756605302a5SGregory Neil Shapiro 757605302a5SGregory Neil Shapiro if (*top == NULL) 75840266059SGregory Neil Shapiro { 759605302a5SGregory Neil Shapiro /* Allocate an initial SM_LDAP_RECURSE_LIST struct */ 760605302a5SGregory Neil Shapiro *top = sm_rpool_malloc_x(rpool, sizeof **top); 761d0cef73dSGregory Neil Shapiro (*top)->lrl_cnt = 0; 762d0cef73dSGregory Neil Shapiro (*top)->lrl_size = 0; 763d0cef73dSGregory Neil Shapiro (*top)->lrl_data = NULL; 76440266059SGregory Neil Shapiro } 76540266059SGregory Neil Shapiro 766d0cef73dSGregory Neil Shapiro if ((*top)->lrl_cnt >= (*top)->lrl_size) 767605302a5SGregory Neil Shapiro { 768605302a5SGregory Neil Shapiro /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */ 769d0cef73dSGregory Neil Shapiro olddata = (*top)->lrl_data; 770d0cef73dSGregory Neil Shapiro if ((*top)->lrl_size == 0) 771605302a5SGregory Neil Shapiro { 772605302a5SGregory Neil Shapiro oldsizeb = 0; 773d0cef73dSGregory Neil Shapiro (*top)->lrl_size = 256; 774605302a5SGregory Neil Shapiro } 77540266059SGregory Neil Shapiro else 776605302a5SGregory Neil Shapiro { 777d0cef73dSGregory Neil Shapiro oldsizeb = (*top)->lrl_size * sizeof *((*top)->lrl_data); 778d0cef73dSGregory Neil Shapiro (*top)->lrl_size *= 2; 779605302a5SGregory Neil Shapiro } 780d0cef73dSGregory Neil Shapiro (*top)->lrl_data = sm_rpool_malloc_x(rpool, 781d0cef73dSGregory Neil Shapiro (*top)->lrl_size * sizeof *((*top)->lrl_data)); 782605302a5SGregory Neil Shapiro if (oldsizeb > 0) 783d0cef73dSGregory Neil Shapiro memcpy((*top)->lrl_data, olddata, oldsizeb); 784605302a5SGregory Neil Shapiro } 785605302a5SGregory Neil Shapiro 786605302a5SGregory Neil Shapiro /* 787605302a5SGregory Neil Shapiro ** Binary search/insert item:type into list. 788605302a5SGregory Neil Shapiro ** Return current entry pointer if already exists. 789605302a5SGregory Neil Shapiro */ 790605302a5SGregory Neil Shapiro 791605302a5SGregory Neil Shapiro n = 0; 792d0cef73dSGregory Neil Shapiro m = (*top)->lrl_cnt - 1; 793605302a5SGregory Neil Shapiro if (m < 0) 794605302a5SGregory Neil Shapiro insertat = 0; 795605302a5SGregory Neil Shapiro else 796605302a5SGregory Neil Shapiro insertat = -1; 797605302a5SGregory Neil Shapiro 798605302a5SGregory Neil Shapiro while (insertat == -1) 799605302a5SGregory Neil Shapiro { 800605302a5SGregory Neil Shapiro p = (m + n) / 2; 801605302a5SGregory Neil Shapiro 802d0cef73dSGregory Neil Shapiro rc = sm_strcasecmp(item, (*top)->lrl_data[p]->lr_search); 803605302a5SGregory Neil Shapiro if (rc == 0) 804d0cef73dSGregory Neil Shapiro rc = type - (*top)->lrl_data[p]->lr_type; 805605302a5SGregory Neil Shapiro 806605302a5SGregory Neil Shapiro if (rc < 0) 807605302a5SGregory Neil Shapiro m = p - 1; 808605302a5SGregory Neil Shapiro else if (rc > 0) 809605302a5SGregory Neil Shapiro n = p + 1; 810605302a5SGregory Neil Shapiro else 811d0cef73dSGregory Neil Shapiro return (*top)->lrl_data[p]; 812605302a5SGregory Neil Shapiro 813605302a5SGregory Neil Shapiro if (m == -1) 814605302a5SGregory Neil Shapiro insertat = 0; 815d0cef73dSGregory Neil Shapiro else if (n >= (*top)->lrl_cnt) 816d0cef73dSGregory Neil Shapiro insertat = (*top)->lrl_cnt; 817605302a5SGregory Neil Shapiro else if (m < n) 818605302a5SGregory Neil Shapiro insertat = m + 1; 819605302a5SGregory Neil Shapiro } 820605302a5SGregory Neil Shapiro 821605302a5SGregory Neil Shapiro /* 822605302a5SGregory Neil Shapiro ** Not found in list, make room 823605302a5SGregory Neil Shapiro ** at insert point and add it. 824605302a5SGregory Neil Shapiro */ 825605302a5SGregory Neil Shapiro 826605302a5SGregory Neil Shapiro newe = sm_rpool_malloc_x(rpool, sizeof *newe); 827605302a5SGregory Neil Shapiro if (newe != NULL) 828605302a5SGregory Neil Shapiro { 829d0cef73dSGregory Neil Shapiro moveb = ((*top)->lrl_cnt - insertat) * sizeof *((*top)->lrl_data); 830605302a5SGregory Neil Shapiro if (moveb > 0) 831d0cef73dSGregory Neil Shapiro memmove(&((*top)->lrl_data[insertat + 1]), 832d0cef73dSGregory Neil Shapiro &((*top)->lrl_data[insertat]), 833605302a5SGregory Neil Shapiro moveb); 834605302a5SGregory Neil Shapiro 835605302a5SGregory Neil Shapiro newe->lr_search = sm_rpool_strdup_x(rpool, item); 836605302a5SGregory Neil Shapiro newe->lr_type = type; 837e92d3f3fSGregory Neil Shapiro newe->lr_ludp = NULL; 838e92d3f3fSGregory Neil Shapiro newe->lr_attrs = NULL; 839605302a5SGregory Neil Shapiro newe->lr_done = false; 840605302a5SGregory Neil Shapiro 841d0cef73dSGregory Neil Shapiro ((*top)->lrl_data)[insertat] = newe; 842d0cef73dSGregory Neil Shapiro (*top)->lrl_cnt++; 843605302a5SGregory Neil Shapiro } 844605302a5SGregory Neil Shapiro return newe; 84540266059SGregory Neil Shapiro } 84640266059SGregory Neil Shapiro 84740266059SGregory Neil Shapiro int 848605302a5SGregory Neil Shapiro sm_ldap_results(lmap, msgid, flags, delim, rpool, result, 849605302a5SGregory Neil Shapiro resultln, resultsz, recurse) 85040266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 85140266059SGregory Neil Shapiro int msgid; 85240266059SGregory Neil Shapiro int flags; 853605302a5SGregory Neil Shapiro int delim; 85440266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 85540266059SGregory Neil Shapiro char **result; 856605302a5SGregory Neil Shapiro int *resultln; 857605302a5SGregory Neil Shapiro int *resultsz; 85840266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST *recurse; 85940266059SGregory Neil Shapiro { 86040266059SGregory Neil Shapiro bool toplevel; 86140266059SGregory Neil Shapiro int i; 86240266059SGregory Neil Shapiro int statp; 86340266059SGregory Neil Shapiro int vsize; 86440266059SGregory Neil Shapiro int ret; 86540266059SGregory Neil Shapiro int save_errno; 86640266059SGregory Neil Shapiro char *p; 867605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY *rl; 86840266059SGregory Neil Shapiro 86940266059SGregory Neil Shapiro /* Are we the top top level of the search? */ 87040266059SGregory Neil Shapiro toplevel = (recurse == NULL); 87140266059SGregory Neil Shapiro 87240266059SGregory Neil Shapiro /* Get results */ 87340266059SGregory Neil Shapiro statp = EX_NOTFOUND; 87440266059SGregory Neil Shapiro while ((ret = ldap_result(lmap->ldap_ld, msgid, 0, 87540266059SGregory Neil Shapiro (lmap->ldap_timeout.tv_sec == 0 ? NULL : 87640266059SGregory Neil Shapiro &(lmap->ldap_timeout)), 87740266059SGregory Neil Shapiro &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) 87840266059SGregory Neil Shapiro { 87940266059SGregory Neil Shapiro LDAPMessage *entry; 88040266059SGregory Neil Shapiro 88140266059SGregory Neil Shapiro /* If we don't want multiple values and we have one, break */ 88213d88268SGregory Neil Shapiro if ((char) delim == '\0' && 88313d88268SGregory Neil Shapiro !bitset(SM_LDAP_SINGLEMATCH, flags) && 88413d88268SGregory Neil Shapiro *result != NULL) 88540266059SGregory Neil Shapiro break; 88640266059SGregory Neil Shapiro 88740266059SGregory Neil Shapiro /* Cycle through all entries */ 88840266059SGregory Neil Shapiro for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); 88940266059SGregory Neil Shapiro entry != NULL; 89040266059SGregory Neil Shapiro entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) 89140266059SGregory Neil Shapiro { 89240266059SGregory Neil Shapiro BerElement *ber; 89340266059SGregory Neil Shapiro char *attr; 89440266059SGregory Neil Shapiro char **vals = NULL; 89540266059SGregory Neil Shapiro char *dn; 89640266059SGregory Neil Shapiro 89740266059SGregory Neil Shapiro /* 89840266059SGregory Neil Shapiro ** If matching only and found an entry, 89940266059SGregory Neil Shapiro ** no need to spin through attributes 90040266059SGregory Neil Shapiro */ 90140266059SGregory Neil Shapiro 902323f6dcbSGregory Neil Shapiro if (bitset(SM_LDAP_MATCHONLY, flags)) 903323f6dcbSGregory Neil Shapiro { 904323f6dcbSGregory Neil Shapiro statp = EX_OK; 90540266059SGregory Neil Shapiro continue; 906323f6dcbSGregory Neil Shapiro } 90740266059SGregory Neil Shapiro 9084e4196cbSGregory Neil Shapiro # if _FFR_LDAP_SINGLEDN 9094e4196cbSGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEDN, flags) && *result != NULL) 9104e4196cbSGregory Neil Shapiro { 9114e4196cbSGregory Neil Shapiro /* only wanted one match */ 9124e4196cbSGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 9134e4196cbSGregory Neil Shapiro errno = ENOENT; 9144e4196cbSGregory Neil Shapiro return EX_NOTFOUND; 9154e4196cbSGregory Neil Shapiro } 9164e4196cbSGregory Neil Shapiro # endif /* _FFR_LDAP_SINGLEDN */ 9174e4196cbSGregory Neil Shapiro 91840266059SGregory Neil Shapiro /* record completed DN's to prevent loops */ 91940266059SGregory Neil Shapiro dn = ldap_get_dn(lmap->ldap_ld, entry); 92040266059SGregory Neil Shapiro if (dn == NULL) 92140266059SGregory Neil Shapiro { 92240266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 92340266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 924605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 92540266059SGregory Neil Shapiro errno = save_errno; 926a7ec597cSGregory Neil Shapiro return EX_TEMPFAIL; 92740266059SGregory Neil Shapiro } 92840266059SGregory Neil Shapiro 929605302a5SGregory Neil Shapiro rl = sm_ldap_add_recurse(&recurse, dn, 930605302a5SGregory Neil Shapiro SM_LDAP_ATTR_DN, 931605302a5SGregory Neil Shapiro rpool); 932605302a5SGregory Neil Shapiro 933605302a5SGregory Neil Shapiro if (rl == NULL) 93440266059SGregory Neil Shapiro { 93540266059SGregory Neil Shapiro ldap_memfree(dn); 936605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 93740266059SGregory Neil Shapiro errno = ENOMEM; 93840266059SGregory Neil Shapiro return EX_OSERR; 939605302a5SGregory Neil Shapiro } 940605302a5SGregory Neil Shapiro else if (rl->lr_done) 941605302a5SGregory Neil Shapiro { 94240266059SGregory Neil Shapiro /* already on list, skip it */ 94340266059SGregory Neil Shapiro ldap_memfree(dn); 94440266059SGregory Neil Shapiro continue; 94540266059SGregory Neil Shapiro } 94640266059SGregory Neil Shapiro ldap_memfree(dn); 94740266059SGregory Neil Shapiro 94840266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 94940266059SGregory Neil Shapiro /* 95040266059SGregory Neil Shapiro ** Reset value to prevent lingering 95140266059SGregory Neil Shapiro ** LDAP_DECODING_ERROR due to 95240266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see below) 95340266059SGregory Neil Shapiro */ 95440266059SGregory Neil Shapiro 95540266059SGregory Neil Shapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 95640266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 95740266059SGregory Neil Shapiro 95840266059SGregory Neil Shapiro for (attr = ldap_first_attribute(lmap->ldap_ld, entry, 95940266059SGregory Neil Shapiro &ber); 96040266059SGregory Neil Shapiro attr != NULL; 96140266059SGregory Neil Shapiro attr = ldap_next_attribute(lmap->ldap_ld, entry, 96240266059SGregory Neil Shapiro ber)) 96340266059SGregory Neil Shapiro { 96440266059SGregory Neil Shapiro char *tmp, *vp_tmp; 96540266059SGregory Neil Shapiro int type; 966605302a5SGregory Neil Shapiro char *needobjclass = NULL; 96740266059SGregory Neil Shapiro 968605302a5SGregory Neil Shapiro type = SM_LDAP_ATTR_NONE; 96940266059SGregory Neil Shapiro for (i = 0; lmap->ldap_attr[i] != NULL; i++) 97040266059SGregory Neil Shapiro { 971*2fb4f839SGregory Neil Shapiro if (SM_STRCASEEQ(lmap->ldap_attr[i], 972*2fb4f839SGregory Neil Shapiro attr)) 97340266059SGregory Neil Shapiro { 97440266059SGregory Neil Shapiro type = lmap->ldap_attr_type[i]; 975605302a5SGregory Neil Shapiro needobjclass = lmap->ldap_attr_needobjclass[i]; 97640266059SGregory Neil Shapiro break; 97740266059SGregory Neil Shapiro } 97840266059SGregory Neil Shapiro } 979605302a5SGregory Neil Shapiro 980605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_USE_ALLATTR, flags) && 981605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_NONE) 982605302a5SGregory Neil Shapiro { 983605302a5SGregory Neil Shapiro /* URL lookups specify attrs to use */ 984605302a5SGregory Neil Shapiro type = SM_LDAP_ATTR_NORMAL; 985605302a5SGregory Neil Shapiro needobjclass = NULL; 986605302a5SGregory Neil Shapiro } 987605302a5SGregory Neil Shapiro 988605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NONE) 98940266059SGregory Neil Shapiro { 99040266059SGregory Neil Shapiro /* attribute not requested */ 99140266059SGregory Neil Shapiro ldap_memfree(attr); 992605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 99340266059SGregory Neil Shapiro errno = EFAULT; 99440266059SGregory Neil Shapiro return EX_SOFTWARE; 99540266059SGregory Neil Shapiro } 99640266059SGregory Neil Shapiro 997605302a5SGregory Neil Shapiro /* 998605302a5SGregory Neil Shapiro ** For recursion on a particular attribute, 999605302a5SGregory Neil Shapiro ** we may need to see if this entry is 1000605302a5SGregory Neil Shapiro ** part of a particular objectclass. 1001605302a5SGregory Neil Shapiro ** Also, ignore objectClass attribute. 1002605302a5SGregory Neil Shapiro ** Otherwise we just ignore this attribute. 1003605302a5SGregory Neil Shapiro */ 1004605302a5SGregory Neil Shapiro 1005605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_OBJCLASS || 1006605302a5SGregory Neil Shapiro (needobjclass != NULL && 1007605302a5SGregory Neil Shapiro !sm_ldap_has_objectclass(lmap, entry, 1008605302a5SGregory Neil Shapiro needobjclass))) 1009605302a5SGregory Neil Shapiro { 1010605302a5SGregory Neil Shapiro ldap_memfree(attr); 1011605302a5SGregory Neil Shapiro continue; 1012605302a5SGregory Neil Shapiro } 1013605302a5SGregory Neil Shapiro 101440266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 101540266059SGregory Neil Shapiro { 101640266059SGregory Neil Shapiro vals = ldap_get_values(lmap->ldap_ld, 101740266059SGregory Neil Shapiro entry, 101840266059SGregory Neil Shapiro attr); 101940266059SGregory Neil Shapiro if (vals == NULL) 102040266059SGregory Neil Shapiro { 102140266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 102240266059SGregory Neil Shapiro if (save_errno == LDAP_SUCCESS) 102340266059SGregory Neil Shapiro { 102440266059SGregory Neil Shapiro ldap_memfree(attr); 102540266059SGregory Neil Shapiro continue; 102640266059SGregory Neil Shapiro } 102740266059SGregory Neil Shapiro 102840266059SGregory Neil Shapiro /* Must be an error */ 102940266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 103040266059SGregory Neil Shapiro ldap_memfree(attr); 1031605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 103240266059SGregory Neil Shapiro errno = save_errno; 103340266059SGregory Neil Shapiro return EX_TEMPFAIL; 103440266059SGregory Neil Shapiro } 103540266059SGregory Neil Shapiro } 103640266059SGregory Neil Shapiro 103740266059SGregory Neil Shapiro statp = EX_OK; 103840266059SGregory Neil Shapiro 103940266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 104040266059SGregory Neil Shapiro /* 104140266059SGregory Neil Shapiro ** Reset value to prevent lingering 104240266059SGregory Neil Shapiro ** LDAP_DECODING_ERROR due to 104340266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see below) 104440266059SGregory Neil Shapiro */ 104540266059SGregory Neil Shapiro 104640266059SGregory Neil Shapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 104740266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 104840266059SGregory Neil Shapiro 104940266059SGregory Neil Shapiro /* 105040266059SGregory Neil Shapiro ** If matching only, 105140266059SGregory Neil Shapiro ** no need to spin through entries 105240266059SGregory Neil Shapiro */ 105340266059SGregory Neil Shapiro 105440266059SGregory Neil Shapiro if (bitset(SM_LDAP_MATCHONLY, flags)) 105540266059SGregory Neil Shapiro { 105640266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 105740266059SGregory Neil Shapiro ldap_value_free(vals); 105840266059SGregory Neil Shapiro ldap_memfree(attr); 105940266059SGregory Neil Shapiro continue; 106040266059SGregory Neil Shapiro } 106140266059SGregory Neil Shapiro 106240266059SGregory Neil Shapiro /* 106340266059SGregory Neil Shapiro ** If we don't want multiple values, 106440266059SGregory Neil Shapiro ** return first found. 106540266059SGregory Neil Shapiro */ 106640266059SGregory Neil Shapiro 1067605302a5SGregory Neil Shapiro if ((char) delim == '\0') 106840266059SGregory Neil Shapiro { 1069605302a5SGregory Neil Shapiro if (*result != NULL) 1070605302a5SGregory Neil Shapiro { 1071605302a5SGregory Neil Shapiro /* already have a value */ 1072605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEMATCH, 107313d88268SGregory Neil Shapiro flags)) 1074605302a5SGregory Neil Shapiro { 1075605302a5SGregory Neil Shapiro /* only wanted one match */ 1076605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 1077605302a5SGregory Neil Shapiro errno = ENOENT; 1078605302a5SGregory Neil Shapiro return EX_NOTFOUND; 1079605302a5SGregory Neil Shapiro } 108013d88268SGregory Neil Shapiro break; 108113d88268SGregory Neil Shapiro } 1082605302a5SGregory Neil Shapiro 108340266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 108440266059SGregory Neil Shapiro { 108540266059SGregory Neil Shapiro *result = sm_rpool_strdup_x(rpool, 108640266059SGregory Neil Shapiro attr); 108740266059SGregory Neil Shapiro ldap_memfree(attr); 108840266059SGregory Neil Shapiro break; 108940266059SGregory Neil Shapiro } 109040266059SGregory Neil Shapiro 109140266059SGregory Neil Shapiro if (vals[0] == NULL) 109240266059SGregory Neil Shapiro { 109340266059SGregory Neil Shapiro ldap_value_free(vals); 109440266059SGregory Neil Shapiro ldap_memfree(attr); 109540266059SGregory Neil Shapiro continue; 109640266059SGregory Neil Shapiro } 109740266059SGregory Neil Shapiro 109840266059SGregory Neil Shapiro vsize = strlen(vals[0]) + 1; 109940266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 110040266059SGregory Neil Shapiro vsize += strlen(attr) + 1; 110140266059SGregory Neil Shapiro *result = sm_rpool_malloc_x(rpool, 110240266059SGregory Neil Shapiro vsize); 110340266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 110440266059SGregory Neil Shapiro sm_snprintf(*result, vsize, 110540266059SGregory Neil Shapiro "%s%c%s", 110640266059SGregory Neil Shapiro attr, 110740266059SGregory Neil Shapiro lmap->ldap_attrsep, 110840266059SGregory Neil Shapiro vals[0]); 110940266059SGregory Neil Shapiro else 111040266059SGregory Neil Shapiro sm_strlcpy(*result, vals[0], 111140266059SGregory Neil Shapiro vsize); 111240266059SGregory Neil Shapiro ldap_value_free(vals); 111340266059SGregory Neil Shapiro ldap_memfree(attr); 111440266059SGregory Neil Shapiro break; 111540266059SGregory Neil Shapiro } 111640266059SGregory Neil Shapiro 111740266059SGregory Neil Shapiro /* attributes only */ 111840266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 111940266059SGregory Neil Shapiro { 112040266059SGregory Neil Shapiro if (*result == NULL) 112140266059SGregory Neil Shapiro *result = sm_rpool_strdup_x(rpool, 112240266059SGregory Neil Shapiro attr); 112340266059SGregory Neil Shapiro else 112440266059SGregory Neil Shapiro { 1125605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEMATCH, 1126605302a5SGregory Neil Shapiro flags) && 1127605302a5SGregory Neil Shapiro *result != NULL) 1128605302a5SGregory Neil Shapiro { 1129605302a5SGregory Neil Shapiro /* only wanted one match */ 1130605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 1131605302a5SGregory Neil Shapiro errno = ENOENT; 1132605302a5SGregory Neil Shapiro return EX_NOTFOUND; 1133605302a5SGregory Neil Shapiro } 1134605302a5SGregory Neil Shapiro 113540266059SGregory Neil Shapiro vsize = strlen(*result) + 113640266059SGregory Neil Shapiro strlen(attr) + 2; 113740266059SGregory Neil Shapiro tmp = sm_rpool_malloc_x(rpool, 113840266059SGregory Neil Shapiro vsize); 113940266059SGregory Neil Shapiro (void) sm_snprintf(tmp, 114040266059SGregory Neil Shapiro vsize, "%s%c%s", 1141605302a5SGregory Neil Shapiro *result, (char) delim, 114240266059SGregory Neil Shapiro attr); 114340266059SGregory Neil Shapiro *result = tmp; 114440266059SGregory Neil Shapiro } 114540266059SGregory Neil Shapiro ldap_memfree(attr); 114640266059SGregory Neil Shapiro continue; 114740266059SGregory Neil Shapiro } 114840266059SGregory Neil Shapiro 114940266059SGregory Neil Shapiro /* 1150605302a5SGregory Neil Shapiro ** If there is more than one, munge then 1151605302a5SGregory Neil Shapiro ** into a map_coldelim separated string. 1152605302a5SGregory Neil Shapiro ** If we are recursing we may have an entry 1153605302a5SGregory Neil Shapiro ** with no 'normal' values to put in the 1154605302a5SGregory Neil Shapiro ** string. 1155605302a5SGregory Neil Shapiro ** This is not an error. 115640266059SGregory Neil Shapiro */ 115740266059SGregory Neil Shapiro 1158605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NORMAL && 1159605302a5SGregory Neil Shapiro bitset(SM_LDAP_SINGLEMATCH, flags) && 1160605302a5SGregory Neil Shapiro *result != NULL) 1161605302a5SGregory Neil Shapiro { 1162605302a5SGregory Neil Shapiro /* only wanted one match */ 1163605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 1164605302a5SGregory Neil Shapiro errno = ENOENT; 1165605302a5SGregory Neil Shapiro return EX_NOTFOUND; 1166605302a5SGregory Neil Shapiro } 1167605302a5SGregory Neil Shapiro 116840266059SGregory Neil Shapiro vsize = 0; 116940266059SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 117040266059SGregory Neil Shapiro { 1171605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_DN || 1172605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_FILTER || 1173605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_URL) 117440266059SGregory Neil Shapiro { 1175605302a5SGregory Neil Shapiro /* add to recursion */ 1176605302a5SGregory Neil Shapiro if (sm_ldap_add_recurse(&recurse, 117740266059SGregory Neil Shapiro vals[i], 1178605302a5SGregory Neil Shapiro type, 1179605302a5SGregory Neil Shapiro rpool) == NULL) 118040266059SGregory Neil Shapiro { 1181605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 118240266059SGregory Neil Shapiro errno = ENOMEM; 118340266059SGregory Neil Shapiro return EX_OSERR; 118440266059SGregory Neil Shapiro } 118540266059SGregory Neil Shapiro continue; 118640266059SGregory Neil Shapiro } 1187605302a5SGregory Neil Shapiro 118840266059SGregory Neil Shapiro vsize += strlen(vals[i]) + 1; 118940266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 119040266059SGregory Neil Shapiro vsize += strlen(attr) + 1; 119140266059SGregory Neil Shapiro } 1192605302a5SGregory Neil Shapiro 1193605302a5SGregory Neil Shapiro /* 1194605302a5SGregory Neil Shapiro ** Create/Append to string any normal 1195605302a5SGregory Neil Shapiro ** attribute values. Otherwise, just free 1196605302a5SGregory Neil Shapiro ** memory and move on to the next 1197605302a5SGregory Neil Shapiro ** attribute in this entry. 1198605302a5SGregory Neil Shapiro */ 1199605302a5SGregory Neil Shapiro 1200605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NORMAL && vsize > 0) 1201605302a5SGregory Neil Shapiro { 1202605302a5SGregory Neil Shapiro char *pe; 1203605302a5SGregory Neil Shapiro 1204605302a5SGregory Neil Shapiro /* Grow result string if needed */ 1205605302a5SGregory Neil Shapiro if ((*resultln + vsize) >= *resultsz) 1206605302a5SGregory Neil Shapiro { 1207605302a5SGregory Neil Shapiro while ((*resultln + vsize) >= *resultsz) 1208605302a5SGregory Neil Shapiro { 1209605302a5SGregory Neil Shapiro if (*resultsz == 0) 1210605302a5SGregory Neil Shapiro *resultsz = 1024; 1211605302a5SGregory Neil Shapiro else 1212605302a5SGregory Neil Shapiro *resultsz *= 2; 1213605302a5SGregory Neil Shapiro } 1214605302a5SGregory Neil Shapiro 1215605302a5SGregory Neil Shapiro vp_tmp = sm_rpool_malloc_x(rpool, *resultsz); 121640266059SGregory Neil Shapiro *vp_tmp = '\0'; 121740266059SGregory Neil Shapiro 1218605302a5SGregory Neil Shapiro if (*result != NULL) 1219605302a5SGregory Neil Shapiro sm_strlcpy(vp_tmp, 1220605302a5SGregory Neil Shapiro *result, 1221605302a5SGregory Neil Shapiro *resultsz); 1222605302a5SGregory Neil Shapiro *result = vp_tmp; 1223605302a5SGregory Neil Shapiro } 1224605302a5SGregory Neil Shapiro 1225605302a5SGregory Neil Shapiro p = *result + *resultln; 1226605302a5SGregory Neil Shapiro pe = *result + *resultsz; 1227605302a5SGregory Neil Shapiro 122840266059SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 122940266059SGregory Neil Shapiro { 1230959366dcSGregory Neil Shapiro if (*resultln > 0 && 1231959366dcSGregory Neil Shapiro p < pe) 1232605302a5SGregory Neil Shapiro *p++ = (char) delim; 1233605302a5SGregory Neil Shapiro 123440266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 123540266059SGregory Neil Shapiro { 123640266059SGregory Neil Shapiro p += sm_strlcpy(p, attr, 1237605302a5SGregory Neil Shapiro pe - p); 1238605302a5SGregory Neil Shapiro if (p < pe) 123940266059SGregory Neil Shapiro *p++ = lmap->ldap_attrsep; 124040266059SGregory Neil Shapiro } 1241605302a5SGregory Neil Shapiro 124240266059SGregory Neil Shapiro p += sm_strlcpy(p, vals[i], 1243605302a5SGregory Neil Shapiro pe - p); 1244605302a5SGregory Neil Shapiro *resultln = p - (*result); 1245605302a5SGregory Neil Shapiro if (p >= pe) 124640266059SGregory Neil Shapiro { 124740266059SGregory Neil Shapiro /* Internal error: buffer too small for LDAP values */ 1248605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 124940266059SGregory Neil Shapiro errno = ENOMEM; 125040266059SGregory Neil Shapiro return EX_OSERR; 125140266059SGregory Neil Shapiro } 1252605302a5SGregory Neil Shapiro } 125340266059SGregory Neil Shapiro } 125440266059SGregory Neil Shapiro 125540266059SGregory Neil Shapiro ldap_value_free(vals); 125640266059SGregory Neil Shapiro ldap_memfree(attr); 125740266059SGregory Neil Shapiro } 125840266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 125940266059SGregory Neil Shapiro 126040266059SGregory Neil Shapiro /* 126140266059SGregory Neil Shapiro ** We check save_errno != LDAP_DECODING_ERROR since 126240266059SGregory Neil Shapiro ** OpenLDAP 1.X has a very ugly *undocumented* 126340266059SGregory Neil Shapiro ** hack of returning this error code from 126440266059SGregory Neil Shapiro ** ldap_next_attribute() if the library freed the 126540266059SGregory Neil Shapiro ** ber attribute. See: 126640266059SGregory Neil Shapiro ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 126740266059SGregory Neil Shapiro */ 126840266059SGregory Neil Shapiro 126940266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS && 127040266059SGregory Neil Shapiro save_errno != LDAP_DECODING_ERROR) 127140266059SGregory Neil Shapiro { 127240266059SGregory Neil Shapiro /* Must be an error */ 127340266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 1274605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 127540266059SGregory Neil Shapiro errno = save_errno; 127640266059SGregory Neil Shapiro return EX_TEMPFAIL; 127740266059SGregory Neil Shapiro } 127840266059SGregory Neil Shapiro 1279605302a5SGregory Neil Shapiro /* mark this DN as done */ 1280605302a5SGregory Neil Shapiro rl->lr_done = true; 1281e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp != NULL) 1282e92d3f3fSGregory Neil Shapiro { 1283e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1284e92d3f3fSGregory Neil Shapiro rl->lr_ludp = NULL; 1285e92d3f3fSGregory Neil Shapiro } 1286e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs != NULL) 1287e92d3f3fSGregory Neil Shapiro { 1288e92d3f3fSGregory Neil Shapiro free(rl->lr_attrs); 1289e92d3f3fSGregory Neil Shapiro rl->lr_attrs = NULL; 1290e92d3f3fSGregory Neil Shapiro } 1291605302a5SGregory Neil Shapiro 129240266059SGregory Neil Shapiro /* We don't want multiple values and we have one */ 129313d88268SGregory Neil Shapiro if ((char) delim == '\0' && 129413d88268SGregory Neil Shapiro !bitset(SM_LDAP_SINGLEMATCH, flags) && 129513d88268SGregory Neil Shapiro *result != NULL) 129640266059SGregory Neil Shapiro break; 129740266059SGregory Neil Shapiro } 129840266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 129940266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS && 130040266059SGregory Neil Shapiro save_errno != LDAP_DECODING_ERROR) 130140266059SGregory Neil Shapiro { 130240266059SGregory Neil Shapiro /* Must be an error */ 130340266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 1304605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 130540266059SGregory Neil Shapiro errno = save_errno; 130640266059SGregory Neil Shapiro return EX_TEMPFAIL; 130740266059SGregory Neil Shapiro } 130840266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); 130940266059SGregory Neil Shapiro lmap->ldap_res = NULL; 131040266059SGregory Neil Shapiro } 131140266059SGregory Neil Shapiro 131240266059SGregory Neil Shapiro if (ret == 0) 131340266059SGregory Neil Shapiro save_errno = ETIMEDOUT; 13146f9c8e5bSGregory Neil Shapiro else if (ret == LDAP_RES_SEARCH_RESULT) 13159bd497b8SGregory Neil Shapiro { 13169bd497b8SGregory Neil Shapiro /* 13179bd497b8SGregory Neil Shapiro ** We may have gotten an LDAP_RES_SEARCH_RESULT response 13189bd497b8SGregory Neil Shapiro ** with an error inside it, so we have to extract that 13199bd497b8SGregory Neil Shapiro ** with ldap_parse_result(). This can happen when talking 13209bd497b8SGregory Neil Shapiro ** to an LDAP proxy whose backend has gone down. 13219bd497b8SGregory Neil Shapiro */ 13229bd497b8SGregory Neil Shapiro 13236f9c8e5bSGregory Neil Shapiro if (lmap->ldap_res == NULL) 13246f9c8e5bSGregory Neil Shapiro save_errno = LDAP_UNAVAILABLE; 13256f9c8e5bSGregory Neil Shapiro else 13266f9c8e5bSGregory Neil Shapiro { 13276f9c8e5bSGregory Neil Shapiro int rc; 13286f9c8e5bSGregory Neil Shapiro 13296f9c8e5bSGregory Neil Shapiro save_errno = ldap_parse_result(lmap->ldap_ld, 13306f9c8e5bSGregory Neil Shapiro lmap->ldap_res, &rc, NULL, NULL, 13316f9c8e5bSGregory Neil Shapiro NULL, NULL, 0); 13329bd497b8SGregory Neil Shapiro if (save_errno == LDAP_SUCCESS) 13339bd497b8SGregory Neil Shapiro save_errno = rc; 13349bd497b8SGregory Neil Shapiro } 13356f9c8e5bSGregory Neil Shapiro } 13366f9c8e5bSGregory Neil Shapiro else 13376f9c8e5bSGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 133840266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS) 133940266059SGregory Neil Shapiro { 134040266059SGregory Neil Shapiro statp = EX_TEMPFAIL; 134140266059SGregory Neil Shapiro switch (save_errno) 134240266059SGregory Neil Shapiro { 134340266059SGregory Neil Shapiro # ifdef LDAP_SERVER_DOWN 134440266059SGregory Neil Shapiro case LDAP_SERVER_DOWN: 1345*2fb4f839SGregory Neil Shapiro # endif 134640266059SGregory Neil Shapiro case LDAP_TIMEOUT: 1347ffb83623SGregory Neil Shapiro case ETIMEDOUT: 134840266059SGregory Neil Shapiro case LDAP_UNAVAILABLE: 1349605302a5SGregory Neil Shapiro 1350605302a5SGregory Neil Shapiro /* 1351605302a5SGregory Neil Shapiro ** server disappeared, 1352605302a5SGregory Neil Shapiro ** try reopen on next search 1353605302a5SGregory Neil Shapiro */ 1354605302a5SGregory Neil Shapiro 135540266059SGregory Neil Shapiro statp = EX_RESTART; 135640266059SGregory Neil Shapiro break; 135740266059SGregory Neil Shapiro } 1358ffb83623SGregory Neil Shapiro if (ret != 0) 135940266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 1360605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 136140266059SGregory Neil Shapiro errno = save_errno; 136240266059SGregory Neil Shapiro return statp; 136340266059SGregory Neil Shapiro } 136440266059SGregory Neil Shapiro 136540266059SGregory Neil Shapiro if (lmap->ldap_res != NULL) 136640266059SGregory Neil Shapiro { 136740266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); 136840266059SGregory Neil Shapiro lmap->ldap_res = NULL; 136940266059SGregory Neil Shapiro } 137040266059SGregory Neil Shapiro 137140266059SGregory Neil Shapiro if (toplevel) 137240266059SGregory Neil Shapiro { 1373605302a5SGregory Neil Shapiro int rlidx; 137440266059SGregory Neil Shapiro 137540266059SGregory Neil Shapiro /* 137640266059SGregory Neil Shapiro ** Spin through the built-up recurse list at the top 137740266059SGregory Neil Shapiro ** of the recursion. Since new items are added at the 137840266059SGregory Neil Shapiro ** end of the shared list, we actually only ever get 137940266059SGregory Neil Shapiro ** one level of recursion before things pop back to the 138040266059SGregory Neil Shapiro ** top. Any items added to the list during that recursion 138140266059SGregory Neil Shapiro ** will be expanded by the top level. 138240266059SGregory Neil Shapiro */ 138340266059SGregory Neil Shapiro 1384d0cef73dSGregory Neil Shapiro for (rlidx = 0; recurse != NULL && rlidx < recurse->lrl_cnt; 1385d0cef73dSGregory Neil Shapiro rlidx++) 138640266059SGregory Neil Shapiro { 1387605302a5SGregory Neil Shapiro int newflags; 138840266059SGregory Neil Shapiro int sid; 138940266059SGregory Neil Shapiro int status; 139040266059SGregory Neil Shapiro 1391d0cef73dSGregory Neil Shapiro rl = recurse->lrl_data[rlidx]; 1392605302a5SGregory Neil Shapiro 1393605302a5SGregory Neil Shapiro newflags = flags; 1394605302a5SGregory Neil Shapiro if (rl->lr_done) 139540266059SGregory Neil Shapiro { 139640266059SGregory Neil Shapiro /* already expanded */ 139740266059SGregory Neil Shapiro continue; 139840266059SGregory Neil Shapiro } 1399605302a5SGregory Neil Shapiro 1400605302a5SGregory Neil Shapiro if (rl->lr_type == SM_LDAP_ATTR_DN) 140140266059SGregory Neil Shapiro { 140240266059SGregory Neil Shapiro /* do DN search */ 140340266059SGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 140440266059SGregory Neil Shapiro rl->lr_search, 140540266059SGregory Neil Shapiro lmap->ldap_scope, 140640266059SGregory Neil Shapiro "(objectClass=*)", 1407605302a5SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? 1408605302a5SGregory Neil Shapiro NULL : lmap->ldap_attr), 140940266059SGregory Neil Shapiro lmap->ldap_attrsonly); 141040266059SGregory Neil Shapiro } 1411605302a5SGregory Neil Shapiro else if (rl->lr_type == SM_LDAP_ATTR_FILTER) 141240266059SGregory Neil Shapiro { 141340266059SGregory Neil Shapiro /* do new search */ 141440266059SGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 141540266059SGregory Neil Shapiro lmap->ldap_base, 141640266059SGregory Neil Shapiro lmap->ldap_scope, 141740266059SGregory Neil Shapiro rl->lr_search, 1418605302a5SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? 1419605302a5SGregory Neil Shapiro NULL : lmap->ldap_attr), 142040266059SGregory Neil Shapiro lmap->ldap_attrsonly); 142140266059SGregory Neil Shapiro } 1422605302a5SGregory Neil Shapiro else if (rl->lr_type == SM_LDAP_ATTR_URL) 142340266059SGregory Neil Shapiro { 1424e92d3f3fSGregory Neil Shapiro /* Parse URL */ 1425e92d3f3fSGregory Neil Shapiro sid = ldap_url_parse(rl->lr_search, 1426e92d3f3fSGregory Neil Shapiro &rl->lr_ludp); 1427e92d3f3fSGregory Neil Shapiro 1428e92d3f3fSGregory Neil Shapiro if (sid != 0) 1429e92d3f3fSGregory Neil Shapiro { 1430e92d3f3fSGregory Neil Shapiro errno = sid + E_LDAPURLBASE; 1431e92d3f3fSGregory Neil Shapiro return EX_TEMPFAIL; 1432e92d3f3fSGregory Neil Shapiro } 1433e92d3f3fSGregory Neil Shapiro 1434e92d3f3fSGregory Neil Shapiro /* We need to add objectClass */ 1435e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp->lud_attrs != NULL) 1436e92d3f3fSGregory Neil Shapiro { 1437e92d3f3fSGregory Neil Shapiro int attrnum = 0; 1438e92d3f3fSGregory Neil Shapiro 1439e92d3f3fSGregory Neil Shapiro while (rl->lr_ludp->lud_attrs[attrnum] != NULL) 1440e92d3f3fSGregory Neil Shapiro { 1441e92d3f3fSGregory Neil Shapiro if (strcasecmp(rl->lr_ludp->lud_attrs[attrnum], 1442e92d3f3fSGregory Neil Shapiro "objectClass") == 0) 1443e92d3f3fSGregory Neil Shapiro { 1444e92d3f3fSGregory Neil Shapiro /* already requested */ 1445e92d3f3fSGregory Neil Shapiro attrnum = -1; 1446e92d3f3fSGregory Neil Shapiro break; 1447e92d3f3fSGregory Neil Shapiro } 1448e92d3f3fSGregory Neil Shapiro attrnum++; 1449e92d3f3fSGregory Neil Shapiro } 1450e92d3f3fSGregory Neil Shapiro 1451e92d3f3fSGregory Neil Shapiro if (attrnum >= 0) 1452e92d3f3fSGregory Neil Shapiro { 1453e92d3f3fSGregory Neil Shapiro int i; 1454e92d3f3fSGregory Neil Shapiro 1455e92d3f3fSGregory Neil Shapiro rl->lr_attrs = (char **)malloc(sizeof(char *) * (attrnum + 2)); 1456e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs == NULL) 1457e92d3f3fSGregory Neil Shapiro { 1458e92d3f3fSGregory Neil Shapiro save_errno = errno; 1459e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1460e92d3f3fSGregory Neil Shapiro errno = save_errno; 1461e92d3f3fSGregory Neil Shapiro return EX_TEMPFAIL; 1462e92d3f3fSGregory Neil Shapiro } 1463e92d3f3fSGregory Neil Shapiro for (i = 0 ; i < attrnum; i++) 1464e92d3f3fSGregory Neil Shapiro { 1465e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i] = rl->lr_ludp->lud_attrs[i]; 1466e92d3f3fSGregory Neil Shapiro } 1467e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i++] = "objectClass"; 1468e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i++] = NULL; 1469e92d3f3fSGregory Neil Shapiro } 1470e92d3f3fSGregory Neil Shapiro } 1471e92d3f3fSGregory Neil Shapiro 1472e92d3f3fSGregory Neil Shapiro /* 1473e92d3f3fSGregory Neil Shapiro ** Use the existing connection 1474e92d3f3fSGregory Neil Shapiro ** for this search. It really 1475e92d3f3fSGregory Neil Shapiro ** should use lud_scheme://lud_host:lud_port/ 1476e92d3f3fSGregory Neil Shapiro ** instead but that would require 1477e92d3f3fSGregory Neil Shapiro ** opening a new connection. 1478e92d3f3fSGregory Neil Shapiro ** This should be fixed ASAP. 1479e92d3f3fSGregory Neil Shapiro */ 1480e92d3f3fSGregory Neil Shapiro 1481e92d3f3fSGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 1482e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_dn, 1483e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_scope, 1484e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_filter, 1485e92d3f3fSGregory Neil Shapiro rl->lr_attrs, 148640266059SGregory Neil Shapiro lmap->ldap_attrsonly); 1487e92d3f3fSGregory Neil Shapiro 1488e92d3f3fSGregory Neil Shapiro /* Use the attributes specified by URL */ 1489605302a5SGregory Neil Shapiro newflags |= SM_LDAP_USE_ALLATTR; 149040266059SGregory Neil Shapiro } 149140266059SGregory Neil Shapiro else 149240266059SGregory Neil Shapiro { 149340266059SGregory Neil Shapiro /* unknown or illegal attribute type */ 149440266059SGregory Neil Shapiro errno = EFAULT; 149540266059SGregory Neil Shapiro return EX_SOFTWARE; 149640266059SGregory Neil Shapiro } 149740266059SGregory Neil Shapiro 149840266059SGregory Neil Shapiro /* Collect results */ 149940266059SGregory Neil Shapiro if (sid == -1) 150040266059SGregory Neil Shapiro { 150140266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 150240266059SGregory Neil Shapiro statp = EX_TEMPFAIL; 150340266059SGregory Neil Shapiro switch (save_errno) 150440266059SGregory Neil Shapiro { 150540266059SGregory Neil Shapiro # ifdef LDAP_SERVER_DOWN 150640266059SGregory Neil Shapiro case LDAP_SERVER_DOWN: 1507*2fb4f839SGregory Neil Shapiro # endif 150840266059SGregory Neil Shapiro case LDAP_TIMEOUT: 1509ffb83623SGregory Neil Shapiro case ETIMEDOUT: 151040266059SGregory Neil Shapiro case LDAP_UNAVAILABLE: 1511605302a5SGregory Neil Shapiro 1512605302a5SGregory Neil Shapiro /* 1513605302a5SGregory Neil Shapiro ** server disappeared, 1514605302a5SGregory Neil Shapiro ** try reopen on next search 1515605302a5SGregory Neil Shapiro */ 1516605302a5SGregory Neil Shapiro 151740266059SGregory Neil Shapiro statp = EX_RESTART; 151840266059SGregory Neil Shapiro break; 151940266059SGregory Neil Shapiro } 152040266059SGregory Neil Shapiro errno = save_errno + E_LDAPBASE; 152140266059SGregory Neil Shapiro return statp; 152240266059SGregory Neil Shapiro } 152340266059SGregory Neil Shapiro 1524605302a5SGregory Neil Shapiro status = sm_ldap_results(lmap, sid, newflags, delim, 1525605302a5SGregory Neil Shapiro rpool, result, resultln, 1526605302a5SGregory Neil Shapiro resultsz, recurse); 152740266059SGregory Neil Shapiro save_errno = errno; 152840266059SGregory Neil Shapiro if (status != EX_OK && status != EX_NOTFOUND) 152940266059SGregory Neil Shapiro { 153040266059SGregory Neil Shapiro errno = save_errno; 153140266059SGregory Neil Shapiro return status; 153240266059SGregory Neil Shapiro } 153340266059SGregory Neil Shapiro 153440266059SGregory Neil Shapiro /* Mark as done */ 1535605302a5SGregory Neil Shapiro rl->lr_done = true; 1536e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp != NULL) 1537e92d3f3fSGregory Neil Shapiro { 1538e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1539e92d3f3fSGregory Neil Shapiro rl->lr_ludp = NULL; 1540e92d3f3fSGregory Neil Shapiro } 1541e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs != NULL) 1542e92d3f3fSGregory Neil Shapiro { 1543e92d3f3fSGregory Neil Shapiro free(rl->lr_attrs); 1544e92d3f3fSGregory Neil Shapiro rl->lr_attrs = NULL; 1545e92d3f3fSGregory Neil Shapiro } 1546605302a5SGregory Neil Shapiro 1547605302a5SGregory Neil Shapiro /* Reset rlidx as new items may have been added */ 1548605302a5SGregory Neil Shapiro rlidx = -1; 154940266059SGregory Neil Shapiro } 155040266059SGregory Neil Shapiro } 155140266059SGregory Neil Shapiro return statp; 155240266059SGregory Neil Shapiro } 155340266059SGregory Neil Shapiro 155440266059SGregory Neil Shapiro /* 155540266059SGregory Neil Shapiro ** SM_LDAP_CLOSE -- close LDAP connection 155640266059SGregory Neil Shapiro ** 155740266059SGregory Neil Shapiro ** Parameters: 155840266059SGregory Neil Shapiro ** lmap -- LDAP map information 155940266059SGregory Neil Shapiro ** 156040266059SGregory Neil Shapiro ** Returns: 156140266059SGregory Neil Shapiro ** None. 156240266059SGregory Neil Shapiro ** 156340266059SGregory Neil Shapiro */ 156440266059SGregory Neil Shapiro 156540266059SGregory Neil Shapiro void 156640266059SGregory Neil Shapiro sm_ldap_close(lmap) 156740266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 156840266059SGregory Neil Shapiro { 156940266059SGregory Neil Shapiro if (lmap->ldap_ld == NULL) 157040266059SGregory Neil Shapiro return; 157140266059SGregory Neil Shapiro 157240266059SGregory Neil Shapiro if (lmap->ldap_pid == getpid()) 157340266059SGregory Neil Shapiro ldap_unbind(lmap->ldap_ld); 157440266059SGregory Neil Shapiro lmap->ldap_ld = NULL; 157540266059SGregory Neil Shapiro lmap->ldap_pid = 0; 157640266059SGregory Neil Shapiro } 157740266059SGregory Neil Shapiro /* 157840266059SGregory Neil Shapiro ** SM_LDAP_GETERRNO -- get ldap errno value 157940266059SGregory Neil Shapiro ** 158040266059SGregory Neil Shapiro ** Parameters: 158140266059SGregory Neil Shapiro ** ld -- LDAP session handle 158240266059SGregory Neil Shapiro ** 158340266059SGregory Neil Shapiro ** Returns: 158440266059SGregory Neil Shapiro ** LDAP errno. 158540266059SGregory Neil Shapiro ** 158640266059SGregory Neil Shapiro */ 158740266059SGregory Neil Shapiro 158840266059SGregory Neil Shapiro int 158940266059SGregory Neil Shapiro sm_ldap_geterrno(ld) 159040266059SGregory Neil Shapiro LDAP *ld; 159140266059SGregory Neil Shapiro { 159240266059SGregory Neil Shapiro int err = LDAP_SUCCESS; 159340266059SGregory Neil Shapiro 159440266059SGregory Neil Shapiro # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 15955b0945b5SGregory Neil Shapiro # ifdef LDAP_OPT_RESULT_CODE 15965b0945b5SGregory Neil Shapiro # define LDAP_GET_RESULT_CODE LDAP_OPT_RESULT_CODE 15975b0945b5SGregory Neil Shapiro # else 15985b0945b5SGregory Neil Shapiro # define LDAP_GET_RESULT_CODE LDAP_OPT_ERROR_NUMBER 15995b0945b5SGregory Neil Shapiro # endif 16005b0945b5SGregory Neil Shapiro (void) ldap_get_option(ld, LDAP_GET_RESULT_CODE, &err); 16015b0945b5SGregory Neil Shapiro # else 160240266059SGregory Neil Shapiro # ifdef LDAP_OPT_SIZELIMIT 160340266059SGregory Neil Shapiro err = ldap_get_lderrno(ld, NULL, NULL); 16045b0945b5SGregory Neil Shapiro # else 160540266059SGregory Neil Shapiro err = ld->ld_errno; 160640266059SGregory Neil Shapiro 160740266059SGregory Neil Shapiro /* 160840266059SGregory Neil Shapiro ** Reset value to prevent lingering LDAP_DECODING_ERROR due to 160940266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see above) 161040266059SGregory Neil Shapiro */ 161140266059SGregory Neil Shapiro 161240266059SGregory Neil Shapiro ld->ld_errno = LDAP_SUCCESS; 161340266059SGregory Neil Shapiro # endif /* LDAP_OPT_SIZELIMIT */ 161440266059SGregory Neil Shapiro # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 161540266059SGregory Neil Shapiro return err; 161640266059SGregory Neil Shapiro } 161740266059SGregory Neil Shapiro #endif /* LDAPMAP */ 1618