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> 30605302a5SGregory Neil Shapiro # ifdef EX_OK 31605302a5SGregory Neil Shapiro # undef EX_OK /* for SVr4.2 SMP */ 32*5b0945b5SGregory Neil Shapiro # endif 3340266059SGregory Neil Shapiro # include <sm/sysexits.h> 3440266059SGregory Neil Shapiro 3540266059SGregory Neil Shapiro SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap", 3640266059SGregory Neil Shapiro "@(#)$Debug: sm_trace_ldap - trace LDAP operations $"); 3740266059SGregory Neil Shapiro 38b6bacd31SGregory Neil Shapiro static bool sm_ldap_has_objectclass __P((SM_LDAP_STRUCT *, LDAPMessage *, char *)); 39b6bacd31SGregory Neil Shapiro static SM_LDAP_RECURSE_ENTRY *sm_ldap_add_recurse __P((SM_LDAP_RECURSE_LIST **, char *, int, SM_RPOOL_T *)); 4040266059SGregory 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 544e4196cbSGregory Neil Shapiro ERROR FFR_LDAP_VERSION > _LDAP_VERSION_MAX 55*5b0945b5SGregory Neil Shapiro # endif 564e4196cbSGregory Neil Shapiro # if defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN 574e4196cbSGregory Neil Shapiro ERROR FFR_LDAP_VERSION < _LDAP_VERSION_MIN 58*5b0945b5SGregory 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 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; 80*5b0945b5SGregory Neil Shapiro # else 8140266059SGregory Neil Shapiro lmap->ldap_options = 0; 82*5b0945b5SGregory Neil Shapiro # endif 8340266059SGregory Neil Shapiro lmap->ldap_attrsep = '\0'; 8440266059SGregory Neil Shapiro lmap->ldap_binddn = NULL; 8540266059SGregory Neil Shapiro lmap->ldap_secret = NULL; 8640266059SGregory Neil Shapiro lmap->ldap_method = LDAP_AUTH_SIMPLE; 8740266059SGregory Neil Shapiro lmap->ldap_base = NULL; 8840266059SGregory Neil Shapiro lmap->ldap_scope = LDAP_SCOPE_SUBTREE; 8940266059SGregory Neil Shapiro lmap->ldap_attrsonly = LDAPMAP_FALSE; 9040266059SGregory Neil Shapiro lmap->ldap_timeout.tv_sec = 0; 9140266059SGregory Neil Shapiro lmap->ldap_timeout.tv_usec = 0; 9240266059SGregory Neil Shapiro lmap->ldap_ld = NULL; 9340266059SGregory Neil Shapiro lmap->ldap_filter = NULL; 9440266059SGregory Neil Shapiro lmap->ldap_attr[0] = NULL; 95605302a5SGregory Neil Shapiro lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE; 96605302a5SGregory Neil Shapiro lmap->ldap_attr_needobjclass[0] = NULL; 9740266059SGregory Neil Shapiro lmap->ldap_res = NULL; 9840266059SGregory Neil Shapiro lmap->ldap_next = NULL; 9940266059SGregory Neil Shapiro lmap->ldap_pid = 0; 100d0cef73dSGregory Neil Shapiro lmap->ldap_multi_args = false; 10140266059SGregory Neil Shapiro } 10240266059SGregory Neil Shapiro 103*5b0945b5SGregory Neil Shapiro # if _FFR_SM_LDAP_DBG && defined(LBER_OPT_LOG_PRINT_FN) 104*5b0945b5SGregory Neil Shapiro static void ldap_debug_cb __P((const char *msg)); 105*5b0945b5SGregory Neil Shapiro 106*5b0945b5SGregory Neil Shapiro static void 107*5b0945b5SGregory Neil Shapiro ldap_debug_cb(msg) 108*5b0945b5SGregory Neil Shapiro const char *msg; 109*5b0945b5SGregory Neil Shapiro { 110*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 4)) 111*5b0945b5SGregory Neil Shapiro sm_dprintf("%s", msg); 112*5b0945b5SGregory Neil Shapiro } 113*5b0945b5SGregory Neil Shapiro # endif /* _FFR_SM_LDAP_DBG && defined(LBER_OPT_LOG_PRINT_FN) */ 114*5b0945b5SGregory Neil Shapiro 115*5b0945b5SGregory Neil Shapiro 116*5b0945b5SGregory Neil Shapiro # if LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) 117*5b0945b5SGregory Neil Shapiro # define SET_LDAP_TMO(ld, lmap) \ 118*5b0945b5SGregory Neil Shapiro do \ 119*5b0945b5SGregory Neil Shapiro { \ 120*5b0945b5SGregory Neil Shapiro if (lmap->ldap_networktmo > 0) \ 121*5b0945b5SGregory Neil Shapiro { \ 122*5b0945b5SGregory Neil Shapiro struct timeval tmo; \ 123*5b0945b5SGregory Neil Shapiro \ 124*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) \ 125*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_networktmo=%d\n", \ 126*5b0945b5SGregory Neil Shapiro lmap->ldap_networktmo); \ 127*5b0945b5SGregory Neil Shapiro tmo.tv_sec = lmap->ldap_networktmo; \ 128*5b0945b5SGregory Neil Shapiro tmo.tv_usec = 0; \ 129*5b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tmo); \ 130*5b0945b5SGregory Neil Shapiro } \ 131*5b0945b5SGregory Neil Shapiro } while (0) 132*5b0945b5SGregory Neil Shapiro # else /* LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) */ 133*5b0945b5SGregory Neil Shapiro # define SET_LDAP_TMO(ld, lmap) 134*5b0945b5SGregory Neil Shapiro # endif /* LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) */ 135*5b0945b5SGregory Neil Shapiro 136*5b0945b5SGregory Neil Shapiro /* 137*5b0945b5SGregory Neil Shapiro ** SM_LDAP_SETOPTSG -- set some (global) LDAP options 138*5b0945b5SGregory Neil Shapiro ** 139*5b0945b5SGregory Neil Shapiro ** Parameters: 140*5b0945b5SGregory Neil Shapiro ** lmap -- LDAP map information 141*5b0945b5SGregory Neil Shapiro ** 142*5b0945b5SGregory Neil Shapiro ** Returns: 143*5b0945b5SGregory Neil Shapiro ** None. 144*5b0945b5SGregory Neil Shapiro ** 145*5b0945b5SGregory Neil Shapiro */ 146*5b0945b5SGregory Neil Shapiro 147*5b0945b5SGregory Neil Shapiro # if _FFR_SM_LDAP_DBG 148*5b0945b5SGregory Neil Shapiro static bool dbg_init = false; 149*5b0945b5SGregory Neil Shapiro # endif 150*5b0945b5SGregory Neil Shapiro # if SM_CONF_LDAP_INITIALIZE 151*5b0945b5SGregory Neil Shapiro static void sm_ldap_setoptsg __P((SM_LDAP_STRUCT *lmap)); 152*5b0945b5SGregory Neil Shapiro static void 153*5b0945b5SGregory Neil Shapiro sm_ldap_setoptsg(lmap) 154*5b0945b5SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 155*5b0945b5SGregory Neil Shapiro { 156*5b0945b5SGregory Neil Shapiro # if USE_LDAP_SET_OPTION 157*5b0945b5SGregory Neil Shapiro 158*5b0945b5SGregory Neil Shapiro SET_LDAP_TMO(NULL, lmap); 159*5b0945b5SGregory Neil Shapiro 160*5b0945b5SGregory Neil Shapiro # if _FFR_SM_LDAP_DBG 161*5b0945b5SGregory Neil Shapiro if (!dbg_init && sm_debug_active(&SmLDAPTrace, 1) && 162*5b0945b5SGregory Neil Shapiro lmap->ldap_debug != 0) 163*5b0945b5SGregory Neil Shapiro { 164*5b0945b5SGregory Neil Shapiro int r; 165*5b0945b5SGregory Neil Shapiro # if defined(LBER_OPT_LOG_PRINT_FN) 166*5b0945b5SGregory Neil Shapiro r = ber_set_option(NULL, LBER_OPT_LOG_PRINT_FN, ldap_debug_cb); 167*5b0945b5SGregory Neil Shapiro # endif 168*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 169*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_debug0=%d\n", lmap->ldap_debug); 170*5b0945b5SGregory Neil Shapiro r = ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, 171*5b0945b5SGregory Neil Shapiro &(lmap->ldap_debug)); 172*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9) && r != LDAP_OPT_SUCCESS) 173*5b0945b5SGregory Neil Shapiro sm_dprintf("ber_set_option=%d\n", r); 174*5b0945b5SGregory Neil Shapiro r = ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 175*5b0945b5SGregory Neil Shapiro &(lmap->ldap_debug)); 176*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9) && r != LDAP_OPT_SUCCESS) 177*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_set_option=%d\n", r); 178*5b0945b5SGregory Neil Shapiro dbg_init = true; 179*5b0945b5SGregory Neil Shapiro } 180*5b0945b5SGregory Neil Shapiro # endif /* _FFR_SM_LDAP_DBG */ 181*5b0945b5SGregory Neil Shapiro # endif /* USE_LDAP_SET_OPTION */ 182*5b0945b5SGregory Neil Shapiro } 183*5b0945b5SGregory Neil Shapiro # endif /* SM_CONF_LDAP_INITIALIZE */ 184*5b0945b5SGregory Neil Shapiro 185*5b0945b5SGregory Neil Shapiro /* 186*5b0945b5SGregory Neil Shapiro ** SM_LDAP_SETOPTS -- set LDAP options 187*5b0945b5SGregory Neil Shapiro ** 188*5b0945b5SGregory Neil Shapiro ** Parameters: 189*5b0945b5SGregory Neil Shapiro ** ld -- LDAP session handle 190*5b0945b5SGregory Neil Shapiro ** lmap -- LDAP map information 191*5b0945b5SGregory Neil Shapiro ** 192*5b0945b5SGregory Neil Shapiro ** Returns: 193*5b0945b5SGregory Neil Shapiro ** None. 194*5b0945b5SGregory Neil Shapiro ** 195*5b0945b5SGregory Neil Shapiro */ 196*5b0945b5SGregory Neil Shapiro 197*5b0945b5SGregory Neil Shapiro void 198*5b0945b5SGregory Neil Shapiro sm_ldap_setopts(ld, lmap) 199*5b0945b5SGregory Neil Shapiro LDAP *ld; 200*5b0945b5SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 201*5b0945b5SGregory Neil Shapiro { 202*5b0945b5SGregory Neil Shapiro # if USE_LDAP_SET_OPTION 203*5b0945b5SGregory Neil Shapiro if (lmap->ldap_version != 0) 204*5b0945b5SGregory Neil Shapiro { 205*5b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, 206*5b0945b5SGregory Neil Shapiro &lmap->ldap_version); 207*5b0945b5SGregory Neil Shapiro } 208*5b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); 209*5b0945b5SGregory Neil Shapiro if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) 210*5b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); 211*5b0945b5SGregory Neil Shapiro else 212*5b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 213*5b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); 214*5b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); 215*5b0945b5SGregory Neil Shapiro SET_LDAP_TMO(ld, lmap); 216*5b0945b5SGregory Neil Shapiro # if _FFR_SM_LDAP_DBG 217*5b0945b5SGregory Neil Shapiro if ((!dbg_init || ld != NULL) && sm_debug_active(&SmLDAPTrace, 1) 218*5b0945b5SGregory Neil Shapiro && lmap->ldap_debug > 0) 219*5b0945b5SGregory Neil Shapiro { 220*5b0945b5SGregory Neil Shapiro int r; 221*5b0945b5SGregory Neil Shapiro 222*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 223*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_debug=%d, dbg_init=%d\n", 224*5b0945b5SGregory Neil Shapiro lmap->ldap_debug, dbg_init); 225*5b0945b5SGregory Neil Shapiro r = ldap_set_option(ld, LDAP_OPT_DEBUG_LEVEL, 226*5b0945b5SGregory Neil Shapiro &(lmap->ldap_debug)); 227*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9) && r != LDAP_OPT_SUCCESS) 228*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_set_option=%d\n", r); 229*5b0945b5SGregory Neil Shapiro } 230*5b0945b5SGregory Neil Shapiro # endif /* _FFR_SM_LDAP_DBG */ 231*5b0945b5SGregory Neil Shapiro # ifdef LDAP_OPT_RESTART 232*5b0945b5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); 233*5b0945b5SGregory Neil Shapiro # endif 234*5b0945b5SGregory Neil Shapiro 235*5b0945b5SGregory Neil Shapiro # else /* USE_LDAP_SET_OPTION */ 236*5b0945b5SGregory Neil Shapiro /* From here on in we can use ldap internal timelimits */ 237*5b0945b5SGregory Neil Shapiro ld->ld_deref = lmap->ldap_deref; 238*5b0945b5SGregory Neil Shapiro ld->ld_options = lmap->ldap_options; 239*5b0945b5SGregory Neil Shapiro ld->ld_sizelimit = lmap->ldap_sizelimit; 240*5b0945b5SGregory Neil Shapiro ld->ld_timelimit = lmap->ldap_timelimit; 241*5b0945b5SGregory Neil Shapiro # endif /* USE_LDAP_SET_OPTION */ 242*5b0945b5SGregory Neil Shapiro } 243*5b0945b5SGregory Neil Shapiro 24440266059SGregory Neil Shapiro /* 24540266059SGregory Neil Shapiro ** SM_LDAP_START -- actually connect to an LDAP server 24640266059SGregory Neil Shapiro ** 24740266059SGregory Neil Shapiro ** Parameters: 24840266059SGregory Neil Shapiro ** name -- name of map for debug output. 24940266059SGregory Neil Shapiro ** lmap -- the LDAP map being opened. 25040266059SGregory Neil Shapiro ** 25140266059SGregory Neil Shapiro ** Returns: 25240266059SGregory Neil Shapiro ** true if connection is successful, false otherwise. 25340266059SGregory Neil Shapiro ** 25440266059SGregory Neil Shapiro ** Side Effects: 25540266059SGregory Neil Shapiro ** Populates lmap->ldap_ld. 25640266059SGregory Neil Shapiro */ 25740266059SGregory Neil Shapiro 258*5b0945b5SGregory Neil Shapiro # if !USE_LDAP_INIT || !LDAP_NETWORK_TIMEOUT 25940266059SGregory Neil Shapiro static jmp_buf LDAPTimeout; 260*5b0945b5SGregory Neil Shapiro static void ldaptimeout __P((int)); 26140266059SGregory Neil Shapiro 262*5b0945b5SGregory Neil Shapiro /* ARGSUSED */ 263*5b0945b5SGregory Neil Shapiro static void 264*5b0945b5SGregory Neil Shapiro ldaptimeout(unused) 265*5b0945b5SGregory Neil Shapiro int unused; 266*5b0945b5SGregory Neil Shapiro { 267*5b0945b5SGregory Neil Shapiro /* 268*5b0945b5SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 269*5b0945b5SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 270*5b0945b5SGregory Neil Shapiro ** DOING. 271*5b0945b5SGregory Neil Shapiro */ 272*5b0945b5SGregory Neil Shapiro 273*5b0945b5SGregory Neil Shapiro errno = ETIMEDOUT; 274*5b0945b5SGregory Neil Shapiro longjmp(LDAPTimeout, 1); 275*5b0945b5SGregory Neil Shapiro } 276*5b0945b5SGregory Neil Shapiro 277*5b0945b5SGregory Neil Shapiro 278*5b0945b5SGregory Neil Shapiro #define SM_LDAP_SETTIMEOUT(to, where) \ 27940266059SGregory Neil Shapiro do \ 28040266059SGregory Neil Shapiro { \ 28140266059SGregory Neil Shapiro if (to != 0) \ 28240266059SGregory Neil Shapiro { \ 28340266059SGregory Neil Shapiro if (setjmp(LDAPTimeout) != 0) \ 28440266059SGregory Neil Shapiro { \ 285*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) \ 286*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_settimeout(%s)=triggered\n",\ 287*5b0945b5SGregory Neil Shapiro where); \ 28840266059SGregory Neil Shapiro errno = ETIMEDOUT; \ 28940266059SGregory Neil Shapiro return false; \ 29040266059SGregory Neil Shapiro } \ 29140266059SGregory Neil Shapiro ev = sm_setevent(to, ldaptimeout, 0); \ 29240266059SGregory Neil Shapiro } \ 29340266059SGregory Neil Shapiro } while (0) 29440266059SGregory Neil Shapiro 29540266059SGregory Neil Shapiro #define SM_LDAP_CLEARTIMEOUT() \ 29640266059SGregory Neil Shapiro do \ 29740266059SGregory Neil Shapiro { \ 29840266059SGregory Neil Shapiro if (ev != NULL) \ 29940266059SGregory Neil Shapiro sm_clrevent(ev); \ 30040266059SGregory Neil Shapiro } while (0) 301*5b0945b5SGregory Neil Shapiro #endif /* !USE_LDAP_INIT || !LDAP_NETWORK_TIMEOUT */ 30240266059SGregory Neil Shapiro 30340266059SGregory Neil Shapiro bool 30440266059SGregory Neil Shapiro sm_ldap_start(name, lmap) 30540266059SGregory Neil Shapiro char *name; 30640266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 30740266059SGregory Neil Shapiro { 308b6bacd31SGregory Neil Shapiro int save_errno = 0; 309e92d3f3fSGregory Neil Shapiro char *id; 310*5b0945b5SGregory Neil Shapiro # if !USE_LDAP_INIT || !LDAP_NETWORK_TIMEOUT 31140266059SGregory Neil Shapiro SM_EVENT *ev = NULL; 312*5b0945b5SGregory Neil Shapiro # endif 313e92d3f3fSGregory Neil Shapiro LDAP *ld = NULL; 314*5b0945b5SGregory Neil Shapiro struct timeval tmo; 315*5b0945b5SGregory Neil Shapiro int msgid, err, r; 31640266059SGregory Neil Shapiro 31740266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 2)) 31840266059SGregory Neil Shapiro sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name); 31940266059SGregory Neil Shapiro 320e92d3f3fSGregory Neil Shapiro if (lmap->ldap_host != NULL) 321e92d3f3fSGregory Neil Shapiro id = lmap->ldap_host; 322e92d3f3fSGregory Neil Shapiro else if (lmap->ldap_uri != NULL) 323e92d3f3fSGregory Neil Shapiro id = lmap->ldap_uri; 324605302a5SGregory Neil Shapiro else 325e92d3f3fSGregory Neil Shapiro id = "localhost"; 326e92d3f3fSGregory Neil Shapiro 327e92d3f3fSGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 328e92d3f3fSGregory Neil Shapiro { 329e92d3f3fSGregory Neil Shapiro /* Don't print a port number for LDAP URIs */ 330e92d3f3fSGregory Neil Shapiro if (lmap->ldap_uri != NULL) 331e92d3f3fSGregory Neil Shapiro sm_dprintf("ldapmap_start(%s)\n", id); 332e92d3f3fSGregory Neil Shapiro else 333e92d3f3fSGregory Neil Shapiro sm_dprintf("ldapmap_start(%s, %d)\n", id, 334e92d3f3fSGregory Neil Shapiro lmap->ldap_port); 335e92d3f3fSGregory Neil Shapiro } 336e92d3f3fSGregory Neil Shapiro 337e92d3f3fSGregory Neil Shapiro if (lmap->ldap_uri != NULL) 338e92d3f3fSGregory Neil Shapiro { 339e92d3f3fSGregory Neil Shapiro #if SM_CONF_LDAP_INITIALIZE 340*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 341*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_initialize(%s)\n", lmap->ldap_uri); 342e92d3f3fSGregory Neil Shapiro /* LDAP server supports URIs so use them directly */ 343e92d3f3fSGregory Neil Shapiro save_errno = ldap_initialize(&ld, lmap->ldap_uri); 344*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 345*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_initialize(%s)=%d, ld=%p\n", lmap->ldap_uri, save_errno, ld); 346*5b0945b5SGregory Neil Shapiro sm_ldap_setoptsg(lmap); 347*5b0945b5SGregory Neil Shapiro 348e92d3f3fSGregory Neil Shapiro #else /* SM_CONF_LDAP_INITIALIZE */ 349e92d3f3fSGregory Neil Shapiro LDAPURLDesc *ludp = NULL; 350e92d3f3fSGregory Neil Shapiro 351e92d3f3fSGregory Neil Shapiro /* Blast apart URL and use the ldap_init/ldap_open below */ 352e92d3f3fSGregory Neil Shapiro err = ldap_url_parse(lmap->ldap_uri, &ludp); 353e92d3f3fSGregory Neil Shapiro if (err != 0) 354e92d3f3fSGregory Neil Shapiro { 355e92d3f3fSGregory Neil Shapiro errno = err + E_LDAPURLBASE; 356e92d3f3fSGregory Neil Shapiro return false; 357e92d3f3fSGregory Neil Shapiro } 358e92d3f3fSGregory Neil Shapiro lmap->ldap_host = sm_strdup_x(ludp->lud_host); 359e92d3f3fSGregory Neil Shapiro if (lmap->ldap_host == NULL) 360e92d3f3fSGregory Neil Shapiro { 361e92d3f3fSGregory Neil Shapiro save_errno = errno; 362e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(ludp); 363e92d3f3fSGregory Neil Shapiro errno = save_errno; 364e92d3f3fSGregory Neil Shapiro return false; 365e92d3f3fSGregory Neil Shapiro } 366e92d3f3fSGregory Neil Shapiro lmap->ldap_port = ludp->lud_port; 367e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(ludp); 368e92d3f3fSGregory Neil Shapiro #endif /* SM_CONF_LDAP_INITIALIZE */ 369e92d3f3fSGregory Neil Shapiro } 370e92d3f3fSGregory Neil Shapiro 371e92d3f3fSGregory Neil Shapiro if (ld == NULL) 372e92d3f3fSGregory Neil Shapiro { 373e92d3f3fSGregory Neil Shapiro # if USE_LDAP_INIT 374*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 375*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_init(%s, %d)\n", lmap->ldap_host, lmap->ldap_port); 376e92d3f3fSGregory Neil Shapiro ld = ldap_init(lmap->ldap_host, lmap->ldap_port); 37740266059SGregory Neil Shapiro save_errno = errno; 378*5b0945b5SGregory Neil Shapiro 37940266059SGregory Neil Shapiro # else /* USE_LDAP_INIT */ 38040266059SGregory Neil Shapiro /* 38140266059SGregory Neil Shapiro ** If using ldap_open(), the actual connection to the server 38240266059SGregory Neil Shapiro ** happens now so we need the timeout here. For ldap_init(), 38340266059SGregory Neil Shapiro ** the connection happens at bind time. 38440266059SGregory Neil Shapiro */ 38540266059SGregory Neil Shapiro 386*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 387*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_open(%s, %d)\n", lmap->ldap_host, lmap->ldap_port); 388*5b0945b5SGregory Neil Shapiro 389*5b0945b5SGregory Neil Shapiro SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec, "ldap_open"); 390e92d3f3fSGregory Neil Shapiro ld = ldap_open(lmap->ldap_host, lmap->ldap_port); 39140266059SGregory Neil Shapiro save_errno = errno; 39240266059SGregory Neil Shapiro 39340266059SGregory Neil Shapiro /* clear the event if it has not sprung */ 39440266059SGregory Neil Shapiro SM_LDAP_CLEARTIMEOUT(); 39540266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 396e92d3f3fSGregory Neil Shapiro } 39740266059SGregory Neil Shapiro 39840266059SGregory Neil Shapiro errno = save_errno; 39940266059SGregory Neil Shapiro if (ld == NULL) 400*5b0945b5SGregory Neil Shapiro { 401*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 7)) 402*5b0945b5SGregory Neil Shapiro sm_dprintf("FAIL: ldap_open(%s, %d)=%d\n", lmap->ldap_host, lmap->ldap_port, save_errno); 40340266059SGregory Neil Shapiro return false; 404*5b0945b5SGregory Neil Shapiro } 40540266059SGregory Neil Shapiro 40640266059SGregory Neil Shapiro sm_ldap_setopts(ld, lmap); 407*5b0945b5SGregory Neil Shapiro # if USE_LDAP_INIT && !LDAP_NETWORK_TIMEOUT 40840266059SGregory Neil Shapiro /* 40940266059SGregory Neil Shapiro ** If using ldap_init(), the actual connection to the server 41040266059SGregory Neil Shapiro ** happens at ldap_bind_s() so we need the timeout here. 41140266059SGregory Neil Shapiro */ 41240266059SGregory Neil Shapiro 413*5b0945b5SGregory Neil Shapiro SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec, "ldap_bind"); 414*5b0945b5SGregory Neil Shapiro # endif /* USE_LDAP_INIT && !LDAP_NETWORK_TIMEOUT */ 41540266059SGregory Neil Shapiro 41640266059SGregory Neil Shapiro # ifdef LDAP_AUTH_KRBV4 41740266059SGregory Neil Shapiro if (lmap->ldap_method == LDAP_AUTH_KRBV4 && 41840266059SGregory Neil Shapiro lmap->ldap_secret != NULL) 41940266059SGregory Neil Shapiro { 42040266059SGregory Neil Shapiro /* 42140266059SGregory Neil Shapiro ** Need to put ticket in environment here instead of 42240266059SGregory Neil Shapiro ** during parseargs as there may be different tickets 42340266059SGregory Neil Shapiro ** for different LDAP connections. 42440266059SGregory Neil Shapiro */ 42540266059SGregory Neil Shapiro 42640266059SGregory Neil Shapiro (void) putenv(lmap->ldap_secret); 42740266059SGregory Neil Shapiro } 42840266059SGregory Neil Shapiro # endif /* LDAP_AUTH_KRBV4 */ 42940266059SGregory Neil Shapiro 430*5b0945b5SGregory Neil Shapiro # if LDAP_NETWORK_TIMEOUT 431*5b0945b5SGregory Neil Shapiro tmo.tv_sec = lmap->ldap_networktmo; 432*5b0945b5SGregory Neil Shapiro # else 433*5b0945b5SGregory Neil Shapiro tmo.tv_sec = lmap->ldap_timeout.tv_sec; 434*5b0945b5SGregory Neil Shapiro # endif 435*5b0945b5SGregory Neil Shapiro tmo.tv_usec = 0; 43640266059SGregory Neil Shapiro 437*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 438*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_bind(%s)\n", lmap->ldap_uri); 439*5b0945b5SGregory Neil Shapiro errno = 0; 440*5b0945b5SGregory Neil Shapiro msgid = ldap_bind(ld, lmap->ldap_binddn, lmap->ldap_secret, 441*5b0945b5SGregory Neil Shapiro lmap->ldap_method); 442*5b0945b5SGregory Neil Shapiro save_errno = errno; 443*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 444*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_bind(%s)=%d, errno=%d, tmo=%ld\n", 445*5b0945b5SGregory Neil Shapiro lmap->ldap_uri, msgid, save_errno, 446*5b0945b5SGregory Neil Shapiro (long) tmo.tv_sec); 447*5b0945b5SGregory Neil Shapiro if (-1 == msgid) 448*5b0945b5SGregory Neil Shapiro { 449*5b0945b5SGregory Neil Shapiro r = -1; 450*5b0945b5SGregory Neil Shapiro goto fail; 451*5b0945b5SGregory Neil Shapiro } 452*5b0945b5SGregory Neil Shapiro 453*5b0945b5SGregory Neil Shapiro errno = 0; 454*5b0945b5SGregory Neil Shapiro r = ldap_result(ld, msgid, LDAP_MSG_ALL, 455*5b0945b5SGregory Neil Shapiro tmo.tv_sec == 0 ? NULL : &(tmo), &(lmap->ldap_res)); 456*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 457*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_result(%s)=%d, errno=%d\n", lmap->ldap_uri, r, errno); 458*5b0945b5SGregory Neil Shapiro if (-1 == r) 459*5b0945b5SGregory Neil Shapiro goto fail; 460*5b0945b5SGregory Neil Shapiro if (0 == r) 461*5b0945b5SGregory Neil Shapiro { 462*5b0945b5SGregory Neil Shapiro save_errno = ETIMEDOUT; 463*5b0945b5SGregory Neil Shapiro r = -1; 464*5b0945b5SGregory Neil Shapiro goto fail; 465*5b0945b5SGregory Neil Shapiro } 466*5b0945b5SGregory Neil Shapiro r = ldap_parse_result(ld, lmap->ldap_res, &err, NULL, NULL, NULL, NULL, 467*5b0945b5SGregory Neil Shapiro 1); 468*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 469*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_parse_result(%s)=%d, err=%d\n", lmap->ldap_uri, r, err); 470*5b0945b5SGregory Neil Shapiro if (r != LDAP_SUCCESS) 471*5b0945b5SGregory Neil Shapiro goto fail; 472*5b0945b5SGregory Neil Shapiro if (err != LDAP_SUCCESS) 473*5b0945b5SGregory Neil Shapiro { 474*5b0945b5SGregory Neil Shapiro r = -1; 475*5b0945b5SGregory Neil Shapiro goto fail; 476*5b0945b5SGregory Neil Shapiro } 477*5b0945b5SGregory Neil Shapiro 478*5b0945b5SGregory Neil Shapiro # if USE_LDAP_INIT && !LDAP_NETWORK_TIMEOUT 47940266059SGregory Neil Shapiro /* clear the event if it has not sprung */ 48040266059SGregory Neil Shapiro SM_LDAP_CLEARTIMEOUT(); 481*5b0945b5SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 482*5b0945b5SGregory Neil Shapiro sm_dprintf("ldap_cleartimeout(%s)\n", lmap->ldap_uri); 483*5b0945b5SGregory Neil Shapiro # endif /* USE_LDAP_INIT && !LDAP_NETWORK_TIMEOUT */ 48440266059SGregory Neil Shapiro 485*5b0945b5SGregory Neil Shapiro if (r != LDAP_SUCCESS) 48640266059SGregory Neil Shapiro { 487*5b0945b5SGregory Neil Shapiro fail: 488*5b0945b5SGregory Neil Shapiro if (-1 == r) 489*5b0945b5SGregory Neil Shapiro errno = save_errno; 490*5b0945b5SGregory Neil Shapiro else 491*5b0945b5SGregory Neil Shapiro errno = r + E_LDAPBASE; 49240266059SGregory Neil Shapiro return false; 49340266059SGregory Neil Shapiro } 49440266059SGregory Neil Shapiro 49540266059SGregory Neil Shapiro /* Save PID to make sure only this PID closes the LDAP connection */ 49640266059SGregory Neil Shapiro lmap->ldap_pid = getpid(); 49740266059SGregory Neil Shapiro lmap->ldap_ld = ld; 49840266059SGregory Neil Shapiro return true; 49940266059SGregory Neil Shapiro } 50040266059SGregory Neil Shapiro 50140266059SGregory Neil Shapiro /* 502d0cef73dSGregory Neil Shapiro ** SM_LDAP_SEARCH_M -- initiate multi-key LDAP search 50340266059SGregory Neil Shapiro ** 50440266059SGregory Neil Shapiro ** Initiate an LDAP search, return the msgid. 50540266059SGregory Neil Shapiro ** The calling function must collect the results. 50640266059SGregory Neil Shapiro ** 50740266059SGregory Neil Shapiro ** Parameters: 50840266059SGregory Neil Shapiro ** lmap -- LDAP map information 509d0cef73dSGregory Neil Shapiro ** argv -- key vector of substitutions in LDAP filter 510d0cef73dSGregory Neil Shapiro ** NOTE: argv must have SM_LDAP_ARGS elements to prevent 511d0cef73dSGregory Neil Shapiro ** out of bound array references 51240266059SGregory Neil Shapiro ** 51340266059SGregory Neil Shapiro ** Returns: 514d0cef73dSGregory Neil Shapiro ** <0 on failure (SM_LDAP_ERR*), msgid on success 51540266059SGregory Neil Shapiro ** 51640266059SGregory Neil Shapiro */ 51740266059SGregory Neil Shapiro 51840266059SGregory Neil Shapiro int 519d0cef73dSGregory Neil Shapiro sm_ldap_search_m(lmap, argv) 52040266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 521d0cef73dSGregory Neil Shapiro char **argv; 52240266059SGregory Neil Shapiro { 52340266059SGregory Neil Shapiro int msgid; 52440266059SGregory Neil Shapiro char *fp, *p, *q; 52540266059SGregory Neil Shapiro char filter[LDAPMAP_MAX_FILTER + 1]; 52640266059SGregory Neil Shapiro 527d0cef73dSGregory Neil Shapiro SM_REQUIRE(lmap != NULL); 528d0cef73dSGregory Neil Shapiro SM_REQUIRE(argv != NULL); 529d0cef73dSGregory Neil Shapiro SM_REQUIRE(argv[0] != NULL); 530d0cef73dSGregory Neil Shapiro 53140266059SGregory Neil Shapiro memset(filter, '\0', sizeof filter); 53240266059SGregory Neil Shapiro fp = filter; 53340266059SGregory Neil Shapiro p = lmap->ldap_filter; 53440266059SGregory Neil Shapiro while ((q = strchr(p, '%')) != NULL) 53540266059SGregory Neil Shapiro { 536d0cef73dSGregory Neil Shapiro char *key; 537d0cef73dSGregory Neil Shapiro 538d0cef73dSGregory Neil Shapiro if (lmap->ldap_multi_args) 539d0cef73dSGregory Neil Shapiro { 540d0cef73dSGregory Neil Shapiro #if SM_LDAP_ARGS < 10 541d0cef73dSGregory Neil Shapiro # ERROR _SM_LDAP_ARGS must be 10 542d0cef73dSGregory Neil Shapiro #endif /* SM_LDAP_ARGS < 10 */ 543d0cef73dSGregory Neil Shapiro if (q[1] == 's') 544d0cef73dSGregory Neil Shapiro key = argv[0]; 545d0cef73dSGregory Neil Shapiro else if (q[1] >= '0' && q[1] <= '9') 546d0cef73dSGregory Neil Shapiro { 547d0cef73dSGregory Neil Shapiro key = argv[q[1] - '0']; 548d0cef73dSGregory Neil Shapiro if (key == NULL) 549d0cef73dSGregory Neil Shapiro { 550d0cef73dSGregory Neil Shapiro # if SM_LDAP_ERROR_ON_MISSING_ARGS 551d0cef73dSGregory Neil Shapiro return SM_LDAP_ERR_ARG_MISS; 552d0cef73dSGregory Neil Shapiro # else /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 553d0cef73dSGregory Neil Shapiro key = ""; 554d0cef73dSGregory Neil Shapiro # endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 555d0cef73dSGregory Neil Shapiro } 556d0cef73dSGregory Neil Shapiro } 557d0cef73dSGregory Neil Shapiro else 558d0cef73dSGregory Neil Shapiro key = NULL; 559d0cef73dSGregory Neil Shapiro } 560d0cef73dSGregory Neil Shapiro else 561d0cef73dSGregory Neil Shapiro key = argv[0]; 562d0cef73dSGregory Neil Shapiro 56340266059SGregory Neil Shapiro if (q[1] == 's') 56440266059SGregory Neil Shapiro { 56540266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 56640266059SGregory Neil Shapiro "%.*s%s", (int) (q - p), p, key); 56740266059SGregory Neil Shapiro fp += strlen(fp); 56840266059SGregory Neil Shapiro p = q + 2; 56940266059SGregory Neil Shapiro } 570d0cef73dSGregory Neil Shapiro else if (q[1] == '0' || 571d0cef73dSGregory Neil Shapiro (lmap->ldap_multi_args && q[1] >= '0' && q[1] <= '9')) 57240266059SGregory Neil Shapiro { 57340266059SGregory Neil Shapiro char *k = key; 57440266059SGregory Neil Shapiro 57540266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 57640266059SGregory Neil Shapiro "%.*s", (int) (q - p), p); 57740266059SGregory Neil Shapiro fp += strlen(fp); 57840266059SGregory Neil Shapiro p = q + 2; 57940266059SGregory Neil Shapiro 58040266059SGregory Neil Shapiro /* Properly escape LDAP special characters */ 58140266059SGregory Neil Shapiro while (SPACELEFT(filter, fp) > 0 && 58240266059SGregory Neil Shapiro *k != '\0') 58340266059SGregory Neil Shapiro { 58440266059SGregory Neil Shapiro if (*k == '*' || *k == '(' || 58540266059SGregory Neil Shapiro *k == ')' || *k == '\\') 58640266059SGregory Neil Shapiro { 58740266059SGregory Neil Shapiro (void) sm_strlcat(fp, 58840266059SGregory Neil Shapiro (*k == '*' ? "\\2A" : 58940266059SGregory Neil Shapiro (*k == '(' ? "\\28" : 59040266059SGregory Neil Shapiro (*k == ')' ? "\\29" : 59140266059SGregory Neil Shapiro (*k == '\\' ? "\\5C" : 59240266059SGregory Neil Shapiro "\00")))), 59340266059SGregory Neil Shapiro SPACELEFT(filter, fp)); 59440266059SGregory Neil Shapiro fp += strlen(fp); 59540266059SGregory Neil Shapiro k++; 59640266059SGregory Neil Shapiro } 59740266059SGregory Neil Shapiro else 59840266059SGregory Neil Shapiro *fp++ = *k++; 59940266059SGregory Neil Shapiro } 60040266059SGregory Neil Shapiro } 60140266059SGregory Neil Shapiro else 60240266059SGregory Neil Shapiro { 60340266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 60440266059SGregory Neil Shapiro "%.*s", (int) (q - p + 1), p); 60540266059SGregory Neil Shapiro p = q + (q[1] == '%' ? 2 : 1); 60640266059SGregory Neil Shapiro fp += strlen(fp); 60740266059SGregory Neil Shapiro } 60840266059SGregory Neil Shapiro } 60940266059SGregory Neil Shapiro (void) sm_strlcpy(fp, p, SPACELEFT(filter, fp)); 61040266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 20)) 61140266059SGregory Neil Shapiro sm_dprintf("ldap search filter=%s\n", filter); 61240266059SGregory Neil Shapiro 61340266059SGregory Neil Shapiro lmap->ldap_res = NULL; 614605302a5SGregory Neil Shapiro msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, 615605302a5SGregory Neil Shapiro lmap->ldap_scope, filter, 61640266059SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? NULL : 61740266059SGregory Neil Shapiro lmap->ldap_attr), 61840266059SGregory Neil Shapiro lmap->ldap_attrsonly); 61940266059SGregory Neil Shapiro return msgid; 62040266059SGregory Neil Shapiro } 62140266059SGregory Neil Shapiro 62240266059SGregory Neil Shapiro /* 623d0cef73dSGregory Neil Shapiro ** SM_LDAP_SEARCH -- initiate LDAP search 624d0cef73dSGregory Neil Shapiro ** 625d0cef73dSGregory Neil Shapiro ** Initiate an LDAP search, return the msgid. 626d0cef73dSGregory Neil Shapiro ** The calling function must collect the results. 627d0cef73dSGregory Neil Shapiro ** Note this is just a wrapper into sm_ldap_search_m() 628d0cef73dSGregory Neil Shapiro ** 629d0cef73dSGregory Neil Shapiro ** Parameters: 630d0cef73dSGregory Neil Shapiro ** lmap -- LDAP map information 631d0cef73dSGregory Neil Shapiro ** key -- key to substitute in LDAP filter 632d0cef73dSGregory Neil Shapiro ** 633d0cef73dSGregory Neil Shapiro ** Returns: 634d0cef73dSGregory Neil Shapiro ** <0 on failure, msgid on success 635d0cef73dSGregory Neil Shapiro ** 636d0cef73dSGregory Neil Shapiro */ 637d0cef73dSGregory Neil Shapiro 638d0cef73dSGregory Neil Shapiro int 639d0cef73dSGregory Neil Shapiro sm_ldap_search(lmap, key) 640d0cef73dSGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 641d0cef73dSGregory Neil Shapiro char *key; 642d0cef73dSGregory Neil Shapiro { 643d0cef73dSGregory Neil Shapiro char *argv[SM_LDAP_ARGS]; 644d0cef73dSGregory Neil Shapiro 645d0cef73dSGregory Neil Shapiro memset(argv, '\0', sizeof argv); 646d0cef73dSGregory Neil Shapiro argv[0] = key; 647d0cef73dSGregory Neil Shapiro return sm_ldap_search_m(lmap, argv); 648d0cef73dSGregory Neil Shapiro } 649d0cef73dSGregory Neil Shapiro 650d0cef73dSGregory Neil Shapiro /* 651605302a5SGregory Neil Shapiro ** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a 652605302a5SGregory Neil Shapiro ** particular objectClass 653605302a5SGregory Neil Shapiro ** 654605302a5SGregory Neil Shapiro ** Parameters: 655605302a5SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT in use 656605302a5SGregory Neil Shapiro ** entry -- current LDAP entry struct 657605302a5SGregory Neil Shapiro ** ocvalue -- particular objectclass in question. 658605302a5SGregory Neil Shapiro ** may be of form (fee|foo|fum) meaning 659605302a5SGregory Neil Shapiro ** any entry can be part of either fee, 660605302a5SGregory Neil Shapiro ** foo or fum objectclass 661605302a5SGregory Neil Shapiro ** 662605302a5SGregory Neil Shapiro ** Returns: 663605302a5SGregory Neil Shapiro ** true if item has that objectClass 664605302a5SGregory Neil Shapiro */ 665605302a5SGregory Neil Shapiro 666605302a5SGregory Neil Shapiro static bool 667605302a5SGregory Neil Shapiro sm_ldap_has_objectclass(lmap, entry, ocvalue) 668605302a5SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 669605302a5SGregory Neil Shapiro LDAPMessage *entry; 670605302a5SGregory Neil Shapiro char *ocvalue; 671605302a5SGregory Neil Shapiro { 672605302a5SGregory Neil Shapiro char **vals = NULL; 673605302a5SGregory Neil Shapiro int i; 674605302a5SGregory Neil Shapiro 675605302a5SGregory Neil Shapiro if (ocvalue == NULL) 676605302a5SGregory Neil Shapiro return false; 677605302a5SGregory Neil Shapiro 678605302a5SGregory Neil Shapiro vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass"); 679605302a5SGregory Neil Shapiro if (vals == NULL) 680605302a5SGregory Neil Shapiro return false; 681605302a5SGregory Neil Shapiro 682605302a5SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 683605302a5SGregory Neil Shapiro { 684605302a5SGregory Neil Shapiro char *p; 685605302a5SGregory Neil Shapiro char *q; 686605302a5SGregory Neil Shapiro 687605302a5SGregory Neil Shapiro p = q = ocvalue; 688605302a5SGregory Neil Shapiro while (*p != '\0') 689605302a5SGregory Neil Shapiro { 690605302a5SGregory Neil Shapiro while (*p != '\0' && *p != '|') 691605302a5SGregory Neil Shapiro p++; 692605302a5SGregory Neil Shapiro 693605302a5SGregory Neil Shapiro if ((p - q) == strlen(vals[i]) && 694605302a5SGregory Neil Shapiro sm_strncasecmp(vals[i], q, p - q) == 0) 695605302a5SGregory Neil Shapiro { 696605302a5SGregory Neil Shapiro ldap_value_free(vals); 697605302a5SGregory Neil Shapiro return true; 698605302a5SGregory Neil Shapiro } 699605302a5SGregory Neil Shapiro 700605302a5SGregory Neil Shapiro while (*p == '|') 701605302a5SGregory Neil Shapiro p++; 702605302a5SGregory Neil Shapiro q = p; 703605302a5SGregory Neil Shapiro } 704605302a5SGregory Neil Shapiro } 705605302a5SGregory Neil Shapiro 706605302a5SGregory Neil Shapiro ldap_value_free(vals); 707605302a5SGregory Neil Shapiro return false; 708605302a5SGregory Neil Shapiro } 709605302a5SGregory Neil Shapiro 710605302a5SGregory Neil Shapiro /* 71140266059SGregory Neil Shapiro ** SM_LDAP_RESULTS -- return results from an LDAP lookup in result 71240266059SGregory Neil Shapiro ** 71340266059SGregory Neil Shapiro ** Parameters: 71440266059SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT in use 71540266059SGregory Neil Shapiro ** msgid -- msgid returned by sm_ldap_search() 71640266059SGregory Neil Shapiro ** flags -- flags for the lookup 71740266059SGregory Neil Shapiro ** delim -- delimiter for result concatenation 71840266059SGregory Neil Shapiro ** rpool -- memory pool for storage 71940266059SGregory Neil Shapiro ** result -- return string 72040266059SGregory Neil Shapiro ** recurse -- recursion list 72140266059SGregory Neil Shapiro ** 72240266059SGregory Neil Shapiro ** Returns: 72340266059SGregory Neil Shapiro ** status (sysexit) 72440266059SGregory Neil Shapiro */ 72540266059SGregory Neil Shapiro 726605302a5SGregory Neil Shapiro # define SM_LDAP_ERROR_CLEANUP() \ 72740266059SGregory Neil Shapiro { \ 72840266059SGregory Neil Shapiro if (lmap->ldap_res != NULL) \ 72940266059SGregory Neil Shapiro { \ 73040266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); \ 73140266059SGregory Neil Shapiro lmap->ldap_res = NULL; \ 73240266059SGregory Neil Shapiro } \ 73340266059SGregory Neil Shapiro (void) ldap_abandon(lmap->ldap_ld, msgid); \ 73440266059SGregory Neil Shapiro } 73540266059SGregory Neil Shapiro 736605302a5SGregory Neil Shapiro static SM_LDAP_RECURSE_ENTRY * 737605302a5SGregory Neil Shapiro sm_ldap_add_recurse(top, item, type, rpool) 73840266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST **top; 73940266059SGregory Neil Shapiro char *item; 74040266059SGregory Neil Shapiro int type; 74140266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 74240266059SGregory Neil Shapiro { 743605302a5SGregory Neil Shapiro int n; 744605302a5SGregory Neil Shapiro int m; 745605302a5SGregory Neil Shapiro int p; 746605302a5SGregory Neil Shapiro int insertat; 747605302a5SGregory Neil Shapiro int moveb; 748605302a5SGregory Neil Shapiro int oldsizeb; 749605302a5SGregory Neil Shapiro int rc; 750605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY *newe; 751605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY **olddata; 75240266059SGregory Neil Shapiro 753605302a5SGregory Neil Shapiro /* 754605302a5SGregory Neil Shapiro ** This code will maintain a list of 755605302a5SGregory Neil Shapiro ** SM_LDAP_RECURSE_ENTRY structures 756605302a5SGregory Neil Shapiro ** in ascending order. 757605302a5SGregory Neil Shapiro */ 758605302a5SGregory Neil Shapiro 759605302a5SGregory Neil Shapiro if (*top == NULL) 76040266059SGregory Neil Shapiro { 761605302a5SGregory Neil Shapiro /* Allocate an initial SM_LDAP_RECURSE_LIST struct */ 762605302a5SGregory Neil Shapiro *top = sm_rpool_malloc_x(rpool, sizeof **top); 763d0cef73dSGregory Neil Shapiro (*top)->lrl_cnt = 0; 764d0cef73dSGregory Neil Shapiro (*top)->lrl_size = 0; 765d0cef73dSGregory Neil Shapiro (*top)->lrl_data = NULL; 76640266059SGregory Neil Shapiro } 76740266059SGregory Neil Shapiro 768d0cef73dSGregory Neil Shapiro if ((*top)->lrl_cnt >= (*top)->lrl_size) 769605302a5SGregory Neil Shapiro { 770605302a5SGregory Neil Shapiro /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */ 771d0cef73dSGregory Neil Shapiro olddata = (*top)->lrl_data; 772d0cef73dSGregory Neil Shapiro if ((*top)->lrl_size == 0) 773605302a5SGregory Neil Shapiro { 774605302a5SGregory Neil Shapiro oldsizeb = 0; 775d0cef73dSGregory Neil Shapiro (*top)->lrl_size = 256; 776605302a5SGregory Neil Shapiro } 77740266059SGregory Neil Shapiro else 778605302a5SGregory Neil Shapiro { 779d0cef73dSGregory Neil Shapiro oldsizeb = (*top)->lrl_size * sizeof *((*top)->lrl_data); 780d0cef73dSGregory Neil Shapiro (*top)->lrl_size *= 2; 781605302a5SGregory Neil Shapiro } 782d0cef73dSGregory Neil Shapiro (*top)->lrl_data = sm_rpool_malloc_x(rpool, 783d0cef73dSGregory Neil Shapiro (*top)->lrl_size * sizeof *((*top)->lrl_data)); 784605302a5SGregory Neil Shapiro if (oldsizeb > 0) 785d0cef73dSGregory Neil Shapiro memcpy((*top)->lrl_data, olddata, oldsizeb); 786605302a5SGregory Neil Shapiro } 787605302a5SGregory Neil Shapiro 788605302a5SGregory Neil Shapiro /* 789605302a5SGregory Neil Shapiro ** Binary search/insert item:type into list. 790605302a5SGregory Neil Shapiro ** Return current entry pointer if already exists. 791605302a5SGregory Neil Shapiro */ 792605302a5SGregory Neil Shapiro 793605302a5SGregory Neil Shapiro n = 0; 794d0cef73dSGregory Neil Shapiro m = (*top)->lrl_cnt - 1; 795605302a5SGregory Neil Shapiro if (m < 0) 796605302a5SGregory Neil Shapiro insertat = 0; 797605302a5SGregory Neil Shapiro else 798605302a5SGregory Neil Shapiro insertat = -1; 799605302a5SGregory Neil Shapiro 800605302a5SGregory Neil Shapiro while (insertat == -1) 801605302a5SGregory Neil Shapiro { 802605302a5SGregory Neil Shapiro p = (m + n) / 2; 803605302a5SGregory Neil Shapiro 804d0cef73dSGregory Neil Shapiro rc = sm_strcasecmp(item, (*top)->lrl_data[p]->lr_search); 805605302a5SGregory Neil Shapiro if (rc == 0) 806d0cef73dSGregory Neil Shapiro rc = type - (*top)->lrl_data[p]->lr_type; 807605302a5SGregory Neil Shapiro 808605302a5SGregory Neil Shapiro if (rc < 0) 809605302a5SGregory Neil Shapiro m = p - 1; 810605302a5SGregory Neil Shapiro else if (rc > 0) 811605302a5SGregory Neil Shapiro n = p + 1; 812605302a5SGregory Neil Shapiro else 813d0cef73dSGregory Neil Shapiro return (*top)->lrl_data[p]; 814605302a5SGregory Neil Shapiro 815605302a5SGregory Neil Shapiro if (m == -1) 816605302a5SGregory Neil Shapiro insertat = 0; 817d0cef73dSGregory Neil Shapiro else if (n >= (*top)->lrl_cnt) 818d0cef73dSGregory Neil Shapiro insertat = (*top)->lrl_cnt; 819605302a5SGregory Neil Shapiro else if (m < n) 820605302a5SGregory Neil Shapiro insertat = m + 1; 821605302a5SGregory Neil Shapiro } 822605302a5SGregory Neil Shapiro 823605302a5SGregory Neil Shapiro /* 824605302a5SGregory Neil Shapiro ** Not found in list, make room 825605302a5SGregory Neil Shapiro ** at insert point and add it. 826605302a5SGregory Neil Shapiro */ 827605302a5SGregory Neil Shapiro 828605302a5SGregory Neil Shapiro newe = sm_rpool_malloc_x(rpool, sizeof *newe); 829605302a5SGregory Neil Shapiro if (newe != NULL) 830605302a5SGregory Neil Shapiro { 831d0cef73dSGregory Neil Shapiro moveb = ((*top)->lrl_cnt - insertat) * sizeof *((*top)->lrl_data); 832605302a5SGregory Neil Shapiro if (moveb > 0) 833d0cef73dSGregory Neil Shapiro memmove(&((*top)->lrl_data[insertat + 1]), 834d0cef73dSGregory Neil Shapiro &((*top)->lrl_data[insertat]), 835605302a5SGregory Neil Shapiro moveb); 836605302a5SGregory Neil Shapiro 837605302a5SGregory Neil Shapiro newe->lr_search = sm_rpool_strdup_x(rpool, item); 838605302a5SGregory Neil Shapiro newe->lr_type = type; 839e92d3f3fSGregory Neil Shapiro newe->lr_ludp = NULL; 840e92d3f3fSGregory Neil Shapiro newe->lr_attrs = NULL; 841605302a5SGregory Neil Shapiro newe->lr_done = false; 842605302a5SGregory Neil Shapiro 843d0cef73dSGregory Neil Shapiro ((*top)->lrl_data)[insertat] = newe; 844d0cef73dSGregory Neil Shapiro (*top)->lrl_cnt++; 845605302a5SGregory Neil Shapiro } 846605302a5SGregory Neil Shapiro return newe; 84740266059SGregory Neil Shapiro } 84840266059SGregory Neil Shapiro 84940266059SGregory Neil Shapiro int 850605302a5SGregory Neil Shapiro sm_ldap_results(lmap, msgid, flags, delim, rpool, result, 851605302a5SGregory Neil Shapiro resultln, resultsz, recurse) 85240266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 85340266059SGregory Neil Shapiro int msgid; 85440266059SGregory Neil Shapiro int flags; 855605302a5SGregory Neil Shapiro int delim; 85640266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 85740266059SGregory Neil Shapiro char **result; 858605302a5SGregory Neil Shapiro int *resultln; 859605302a5SGregory Neil Shapiro int *resultsz; 86040266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST *recurse; 86140266059SGregory Neil Shapiro { 86240266059SGregory Neil Shapiro bool toplevel; 86340266059SGregory Neil Shapiro int i; 86440266059SGregory Neil Shapiro int statp; 86540266059SGregory Neil Shapiro int vsize; 86640266059SGregory Neil Shapiro int ret; 86740266059SGregory Neil Shapiro int save_errno; 86840266059SGregory Neil Shapiro char *p; 869605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY *rl; 87040266059SGregory Neil Shapiro 87140266059SGregory Neil Shapiro /* Are we the top top level of the search? */ 87240266059SGregory Neil Shapiro toplevel = (recurse == NULL); 87340266059SGregory Neil Shapiro 87440266059SGregory Neil Shapiro /* Get results */ 87540266059SGregory Neil Shapiro statp = EX_NOTFOUND; 87640266059SGregory Neil Shapiro while ((ret = ldap_result(lmap->ldap_ld, msgid, 0, 87740266059SGregory Neil Shapiro (lmap->ldap_timeout.tv_sec == 0 ? NULL : 87840266059SGregory Neil Shapiro &(lmap->ldap_timeout)), 87940266059SGregory Neil Shapiro &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) 88040266059SGregory Neil Shapiro { 88140266059SGregory Neil Shapiro LDAPMessage *entry; 88240266059SGregory Neil Shapiro 88340266059SGregory Neil Shapiro /* If we don't want multiple values and we have one, break */ 88413d88268SGregory Neil Shapiro if ((char) delim == '\0' && 88513d88268SGregory Neil Shapiro !bitset(SM_LDAP_SINGLEMATCH, flags) && 88613d88268SGregory Neil Shapiro *result != NULL) 88740266059SGregory Neil Shapiro break; 88840266059SGregory Neil Shapiro 88940266059SGregory Neil Shapiro /* Cycle through all entries */ 89040266059SGregory Neil Shapiro for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); 89140266059SGregory Neil Shapiro entry != NULL; 89240266059SGregory Neil Shapiro entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) 89340266059SGregory Neil Shapiro { 89440266059SGregory Neil Shapiro BerElement *ber; 89540266059SGregory Neil Shapiro char *attr; 89640266059SGregory Neil Shapiro char **vals = NULL; 89740266059SGregory Neil Shapiro char *dn; 89840266059SGregory Neil Shapiro 89940266059SGregory Neil Shapiro /* 90040266059SGregory Neil Shapiro ** If matching only and found an entry, 90140266059SGregory Neil Shapiro ** no need to spin through attributes 90240266059SGregory Neil Shapiro */ 90340266059SGregory Neil Shapiro 904323f6dcbSGregory Neil Shapiro if (bitset(SM_LDAP_MATCHONLY, flags)) 905323f6dcbSGregory Neil Shapiro { 906323f6dcbSGregory Neil Shapiro statp = EX_OK; 90740266059SGregory Neil Shapiro continue; 908323f6dcbSGregory Neil Shapiro } 90940266059SGregory Neil Shapiro 9104e4196cbSGregory Neil Shapiro #if _FFR_LDAP_SINGLEDN 9114e4196cbSGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEDN, flags) && *result != NULL) 9124e4196cbSGregory Neil Shapiro { 9134e4196cbSGregory Neil Shapiro /* only wanted one match */ 9144e4196cbSGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 9154e4196cbSGregory Neil Shapiro errno = ENOENT; 9164e4196cbSGregory Neil Shapiro return EX_NOTFOUND; 9174e4196cbSGregory Neil Shapiro } 9184e4196cbSGregory Neil Shapiro #endif /* _FFR_LDAP_SINGLEDN */ 9194e4196cbSGregory Neil Shapiro 92040266059SGregory Neil Shapiro /* record completed DN's to prevent loops */ 92140266059SGregory Neil Shapiro dn = ldap_get_dn(lmap->ldap_ld, entry); 92240266059SGregory Neil Shapiro if (dn == NULL) 92340266059SGregory Neil Shapiro { 92440266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 92540266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 926605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 92740266059SGregory Neil Shapiro errno = save_errno; 928a7ec597cSGregory Neil Shapiro return EX_TEMPFAIL; 92940266059SGregory Neil Shapiro } 93040266059SGregory Neil Shapiro 931605302a5SGregory Neil Shapiro rl = sm_ldap_add_recurse(&recurse, dn, 932605302a5SGregory Neil Shapiro SM_LDAP_ATTR_DN, 933605302a5SGregory Neil Shapiro rpool); 934605302a5SGregory Neil Shapiro 935605302a5SGregory Neil Shapiro if (rl == NULL) 93640266059SGregory Neil Shapiro { 93740266059SGregory Neil Shapiro ldap_memfree(dn); 938605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 93940266059SGregory Neil Shapiro errno = ENOMEM; 94040266059SGregory Neil Shapiro return EX_OSERR; 941605302a5SGregory Neil Shapiro } 942605302a5SGregory Neil Shapiro else if (rl->lr_done) 943605302a5SGregory Neil Shapiro { 94440266059SGregory Neil Shapiro /* already on list, skip it */ 94540266059SGregory Neil Shapiro ldap_memfree(dn); 94640266059SGregory Neil Shapiro continue; 94740266059SGregory Neil Shapiro } 94840266059SGregory Neil Shapiro ldap_memfree(dn); 94940266059SGregory Neil Shapiro 95040266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 95140266059SGregory Neil Shapiro /* 95240266059SGregory Neil Shapiro ** Reset value to prevent lingering 95340266059SGregory Neil Shapiro ** LDAP_DECODING_ERROR due to 95440266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see below) 95540266059SGregory Neil Shapiro */ 95640266059SGregory Neil Shapiro 95740266059SGregory Neil Shapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 95840266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 95940266059SGregory Neil Shapiro 96040266059SGregory Neil Shapiro for (attr = ldap_first_attribute(lmap->ldap_ld, entry, 96140266059SGregory Neil Shapiro &ber); 96240266059SGregory Neil Shapiro attr != NULL; 96340266059SGregory Neil Shapiro attr = ldap_next_attribute(lmap->ldap_ld, entry, 96440266059SGregory Neil Shapiro ber)) 96540266059SGregory Neil Shapiro { 96640266059SGregory Neil Shapiro char *tmp, *vp_tmp; 96740266059SGregory Neil Shapiro int type; 968605302a5SGregory Neil Shapiro char *needobjclass = NULL; 96940266059SGregory Neil Shapiro 970605302a5SGregory Neil Shapiro type = SM_LDAP_ATTR_NONE; 97140266059SGregory Neil Shapiro for (i = 0; lmap->ldap_attr[i] != NULL; i++) 97240266059SGregory Neil Shapiro { 97340266059SGregory Neil Shapiro if (sm_strcasecmp(lmap->ldap_attr[i], 97440266059SGregory Neil Shapiro attr) == 0) 97540266059SGregory Neil Shapiro { 97640266059SGregory Neil Shapiro type = lmap->ldap_attr_type[i]; 977605302a5SGregory Neil Shapiro needobjclass = lmap->ldap_attr_needobjclass[i]; 97840266059SGregory Neil Shapiro break; 97940266059SGregory Neil Shapiro } 98040266059SGregory Neil Shapiro } 981605302a5SGregory Neil Shapiro 982605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_USE_ALLATTR, flags) && 983605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_NONE) 984605302a5SGregory Neil Shapiro { 985605302a5SGregory Neil Shapiro /* URL lookups specify attrs to use */ 986605302a5SGregory Neil Shapiro type = SM_LDAP_ATTR_NORMAL; 987605302a5SGregory Neil Shapiro needobjclass = NULL; 988605302a5SGregory Neil Shapiro } 989605302a5SGregory Neil Shapiro 990605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NONE) 99140266059SGregory Neil Shapiro { 99240266059SGregory Neil Shapiro /* attribute not requested */ 99340266059SGregory Neil Shapiro ldap_memfree(attr); 994605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 99540266059SGregory Neil Shapiro errno = EFAULT; 99640266059SGregory Neil Shapiro return EX_SOFTWARE; 99740266059SGregory Neil Shapiro } 99840266059SGregory Neil Shapiro 999605302a5SGregory Neil Shapiro /* 1000605302a5SGregory Neil Shapiro ** For recursion on a particular attribute, 1001605302a5SGregory Neil Shapiro ** we may need to see if this entry is 1002605302a5SGregory Neil Shapiro ** part of a particular objectclass. 1003605302a5SGregory Neil Shapiro ** Also, ignore objectClass attribute. 1004605302a5SGregory Neil Shapiro ** Otherwise we just ignore this attribute. 1005605302a5SGregory Neil Shapiro */ 1006605302a5SGregory Neil Shapiro 1007605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_OBJCLASS || 1008605302a5SGregory Neil Shapiro (needobjclass != NULL && 1009605302a5SGregory Neil Shapiro !sm_ldap_has_objectclass(lmap, entry, 1010605302a5SGregory Neil Shapiro needobjclass))) 1011605302a5SGregory Neil Shapiro { 1012605302a5SGregory Neil Shapiro ldap_memfree(attr); 1013605302a5SGregory Neil Shapiro continue; 1014605302a5SGregory Neil Shapiro } 1015605302a5SGregory Neil Shapiro 101640266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 101740266059SGregory Neil Shapiro { 101840266059SGregory Neil Shapiro vals = ldap_get_values(lmap->ldap_ld, 101940266059SGregory Neil Shapiro entry, 102040266059SGregory Neil Shapiro attr); 102140266059SGregory Neil Shapiro if (vals == NULL) 102240266059SGregory Neil Shapiro { 102340266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 102440266059SGregory Neil Shapiro if (save_errno == LDAP_SUCCESS) 102540266059SGregory Neil Shapiro { 102640266059SGregory Neil Shapiro ldap_memfree(attr); 102740266059SGregory Neil Shapiro continue; 102840266059SGregory Neil Shapiro } 102940266059SGregory Neil Shapiro 103040266059SGregory Neil Shapiro /* Must be an error */ 103140266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 103240266059SGregory Neil Shapiro ldap_memfree(attr); 1033605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 103440266059SGregory Neil Shapiro errno = save_errno; 103540266059SGregory Neil Shapiro return EX_TEMPFAIL; 103640266059SGregory Neil Shapiro } 103740266059SGregory Neil Shapiro } 103840266059SGregory Neil Shapiro 103940266059SGregory Neil Shapiro statp = EX_OK; 104040266059SGregory Neil Shapiro 104140266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 104240266059SGregory Neil Shapiro /* 104340266059SGregory Neil Shapiro ** Reset value to prevent lingering 104440266059SGregory Neil Shapiro ** LDAP_DECODING_ERROR due to 104540266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see below) 104640266059SGregory Neil Shapiro */ 104740266059SGregory Neil Shapiro 104840266059SGregory Neil Shapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 104940266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 105040266059SGregory Neil Shapiro 105140266059SGregory Neil Shapiro /* 105240266059SGregory Neil Shapiro ** If matching only, 105340266059SGregory Neil Shapiro ** no need to spin through entries 105440266059SGregory Neil Shapiro */ 105540266059SGregory Neil Shapiro 105640266059SGregory Neil Shapiro if (bitset(SM_LDAP_MATCHONLY, flags)) 105740266059SGregory Neil Shapiro { 105840266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 105940266059SGregory Neil Shapiro ldap_value_free(vals); 106040266059SGregory Neil Shapiro ldap_memfree(attr); 106140266059SGregory Neil Shapiro continue; 106240266059SGregory Neil Shapiro } 106340266059SGregory Neil Shapiro 106440266059SGregory Neil Shapiro /* 106540266059SGregory Neil Shapiro ** If we don't want multiple values, 106640266059SGregory Neil Shapiro ** return first found. 106740266059SGregory Neil Shapiro */ 106840266059SGregory Neil Shapiro 1069605302a5SGregory Neil Shapiro if ((char) delim == '\0') 107040266059SGregory Neil Shapiro { 1071605302a5SGregory Neil Shapiro if (*result != NULL) 1072605302a5SGregory Neil Shapiro { 1073605302a5SGregory Neil Shapiro /* already have a value */ 1074605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEMATCH, 107513d88268SGregory Neil Shapiro flags)) 1076605302a5SGregory Neil Shapiro { 1077605302a5SGregory Neil Shapiro /* only wanted one match */ 1078605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 1079605302a5SGregory Neil Shapiro errno = ENOENT; 1080605302a5SGregory Neil Shapiro return EX_NOTFOUND; 1081605302a5SGregory Neil Shapiro } 108213d88268SGregory Neil Shapiro break; 108313d88268SGregory Neil Shapiro } 1084605302a5SGregory Neil Shapiro 108540266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 108640266059SGregory Neil Shapiro { 108740266059SGregory Neil Shapiro *result = sm_rpool_strdup_x(rpool, 108840266059SGregory Neil Shapiro attr); 108940266059SGregory Neil Shapiro ldap_memfree(attr); 109040266059SGregory Neil Shapiro break; 109140266059SGregory Neil Shapiro } 109240266059SGregory Neil Shapiro 109340266059SGregory Neil Shapiro if (vals[0] == NULL) 109440266059SGregory Neil Shapiro { 109540266059SGregory Neil Shapiro ldap_value_free(vals); 109640266059SGregory Neil Shapiro ldap_memfree(attr); 109740266059SGregory Neil Shapiro continue; 109840266059SGregory Neil Shapiro } 109940266059SGregory Neil Shapiro 110040266059SGregory Neil Shapiro vsize = strlen(vals[0]) + 1; 110140266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 110240266059SGregory Neil Shapiro vsize += strlen(attr) + 1; 110340266059SGregory Neil Shapiro *result = sm_rpool_malloc_x(rpool, 110440266059SGregory Neil Shapiro vsize); 110540266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 110640266059SGregory Neil Shapiro sm_snprintf(*result, vsize, 110740266059SGregory Neil Shapiro "%s%c%s", 110840266059SGregory Neil Shapiro attr, 110940266059SGregory Neil Shapiro lmap->ldap_attrsep, 111040266059SGregory Neil Shapiro vals[0]); 111140266059SGregory Neil Shapiro else 111240266059SGregory Neil Shapiro sm_strlcpy(*result, vals[0], 111340266059SGregory Neil Shapiro vsize); 111440266059SGregory Neil Shapiro ldap_value_free(vals); 111540266059SGregory Neil Shapiro ldap_memfree(attr); 111640266059SGregory Neil Shapiro break; 111740266059SGregory Neil Shapiro } 111840266059SGregory Neil Shapiro 111940266059SGregory Neil Shapiro /* attributes only */ 112040266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 112140266059SGregory Neil Shapiro { 112240266059SGregory Neil Shapiro if (*result == NULL) 112340266059SGregory Neil Shapiro *result = sm_rpool_strdup_x(rpool, 112440266059SGregory Neil Shapiro attr); 112540266059SGregory Neil Shapiro else 112640266059SGregory Neil Shapiro { 1127605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEMATCH, 1128605302a5SGregory Neil Shapiro flags) && 1129605302a5SGregory Neil Shapiro *result != NULL) 1130605302a5SGregory Neil Shapiro { 1131605302a5SGregory Neil Shapiro /* only wanted one match */ 1132605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 1133605302a5SGregory Neil Shapiro errno = ENOENT; 1134605302a5SGregory Neil Shapiro return EX_NOTFOUND; 1135605302a5SGregory Neil Shapiro } 1136605302a5SGregory Neil Shapiro 113740266059SGregory Neil Shapiro vsize = strlen(*result) + 113840266059SGregory Neil Shapiro strlen(attr) + 2; 113940266059SGregory Neil Shapiro tmp = sm_rpool_malloc_x(rpool, 114040266059SGregory Neil Shapiro vsize); 114140266059SGregory Neil Shapiro (void) sm_snprintf(tmp, 114240266059SGregory Neil Shapiro vsize, "%s%c%s", 1143605302a5SGregory Neil Shapiro *result, (char) delim, 114440266059SGregory Neil Shapiro attr); 114540266059SGregory Neil Shapiro *result = tmp; 114640266059SGregory Neil Shapiro } 114740266059SGregory Neil Shapiro ldap_memfree(attr); 114840266059SGregory Neil Shapiro continue; 114940266059SGregory Neil Shapiro } 115040266059SGregory Neil Shapiro 115140266059SGregory Neil Shapiro /* 1152605302a5SGregory Neil Shapiro ** If there is more than one, munge then 1153605302a5SGregory Neil Shapiro ** into a map_coldelim separated string. 1154605302a5SGregory Neil Shapiro ** If we are recursing we may have an entry 1155605302a5SGregory Neil Shapiro ** with no 'normal' values to put in the 1156605302a5SGregory Neil Shapiro ** string. 1157605302a5SGregory Neil Shapiro ** This is not an error. 115840266059SGregory Neil Shapiro */ 115940266059SGregory Neil Shapiro 1160605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NORMAL && 1161605302a5SGregory Neil Shapiro bitset(SM_LDAP_SINGLEMATCH, flags) && 1162605302a5SGregory Neil Shapiro *result != NULL) 1163605302a5SGregory Neil Shapiro { 1164605302a5SGregory Neil Shapiro /* only wanted one match */ 1165605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 1166605302a5SGregory Neil Shapiro errno = ENOENT; 1167605302a5SGregory Neil Shapiro return EX_NOTFOUND; 1168605302a5SGregory Neil Shapiro } 1169605302a5SGregory Neil Shapiro 117040266059SGregory Neil Shapiro vsize = 0; 117140266059SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 117240266059SGregory Neil Shapiro { 1173605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_DN || 1174605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_FILTER || 1175605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_URL) 117640266059SGregory Neil Shapiro { 1177605302a5SGregory Neil Shapiro /* add to recursion */ 1178605302a5SGregory Neil Shapiro if (sm_ldap_add_recurse(&recurse, 117940266059SGregory Neil Shapiro vals[i], 1180605302a5SGregory Neil Shapiro type, 1181605302a5SGregory Neil Shapiro rpool) == NULL) 118240266059SGregory Neil Shapiro { 1183605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 118440266059SGregory Neil Shapiro errno = ENOMEM; 118540266059SGregory Neil Shapiro return EX_OSERR; 118640266059SGregory Neil Shapiro } 118740266059SGregory Neil Shapiro continue; 118840266059SGregory Neil Shapiro } 1189605302a5SGregory Neil Shapiro 119040266059SGregory Neil Shapiro vsize += strlen(vals[i]) + 1; 119140266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 119240266059SGregory Neil Shapiro vsize += strlen(attr) + 1; 119340266059SGregory Neil Shapiro } 1194605302a5SGregory Neil Shapiro 1195605302a5SGregory Neil Shapiro /* 1196605302a5SGregory Neil Shapiro ** Create/Append to string any normal 1197605302a5SGregory Neil Shapiro ** attribute values. Otherwise, just free 1198605302a5SGregory Neil Shapiro ** memory and move on to the next 1199605302a5SGregory Neil Shapiro ** attribute in this entry. 1200605302a5SGregory Neil Shapiro */ 1201605302a5SGregory Neil Shapiro 1202605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NORMAL && vsize > 0) 1203605302a5SGregory Neil Shapiro { 1204605302a5SGregory Neil Shapiro char *pe; 1205605302a5SGregory Neil Shapiro 1206605302a5SGregory Neil Shapiro /* Grow result string if needed */ 1207605302a5SGregory Neil Shapiro if ((*resultln + vsize) >= *resultsz) 1208605302a5SGregory Neil Shapiro { 1209605302a5SGregory Neil Shapiro while ((*resultln + vsize) >= *resultsz) 1210605302a5SGregory Neil Shapiro { 1211605302a5SGregory Neil Shapiro if (*resultsz == 0) 1212605302a5SGregory Neil Shapiro *resultsz = 1024; 1213605302a5SGregory Neil Shapiro else 1214605302a5SGregory Neil Shapiro *resultsz *= 2; 1215605302a5SGregory Neil Shapiro } 1216605302a5SGregory Neil Shapiro 1217605302a5SGregory Neil Shapiro vp_tmp = sm_rpool_malloc_x(rpool, *resultsz); 121840266059SGregory Neil Shapiro *vp_tmp = '\0'; 121940266059SGregory Neil Shapiro 1220605302a5SGregory Neil Shapiro if (*result != NULL) 1221605302a5SGregory Neil Shapiro sm_strlcpy(vp_tmp, 1222605302a5SGregory Neil Shapiro *result, 1223605302a5SGregory Neil Shapiro *resultsz); 1224605302a5SGregory Neil Shapiro *result = vp_tmp; 1225605302a5SGregory Neil Shapiro } 1226605302a5SGregory Neil Shapiro 1227605302a5SGregory Neil Shapiro p = *result + *resultln; 1228605302a5SGregory Neil Shapiro pe = *result + *resultsz; 1229605302a5SGregory Neil Shapiro 123040266059SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 123140266059SGregory Neil Shapiro { 1232959366dcSGregory Neil Shapiro if (*resultln > 0 && 1233959366dcSGregory Neil Shapiro p < pe) 1234605302a5SGregory Neil Shapiro *p++ = (char) delim; 1235605302a5SGregory Neil Shapiro 123640266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 123740266059SGregory Neil Shapiro { 123840266059SGregory Neil Shapiro p += sm_strlcpy(p, attr, 1239605302a5SGregory Neil Shapiro pe - p); 1240605302a5SGregory Neil Shapiro if (p < pe) 124140266059SGregory Neil Shapiro *p++ = lmap->ldap_attrsep; 124240266059SGregory Neil Shapiro } 1243605302a5SGregory Neil Shapiro 124440266059SGregory Neil Shapiro p += sm_strlcpy(p, vals[i], 1245605302a5SGregory Neil Shapiro pe - p); 1246605302a5SGregory Neil Shapiro *resultln = p - (*result); 1247605302a5SGregory Neil Shapiro if (p >= pe) 124840266059SGregory Neil Shapiro { 124940266059SGregory Neil Shapiro /* Internal error: buffer too small for LDAP values */ 1250605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 125140266059SGregory Neil Shapiro errno = ENOMEM; 125240266059SGregory Neil Shapiro return EX_OSERR; 125340266059SGregory Neil Shapiro } 1254605302a5SGregory Neil Shapiro } 125540266059SGregory Neil Shapiro } 125640266059SGregory Neil Shapiro 125740266059SGregory Neil Shapiro ldap_value_free(vals); 125840266059SGregory Neil Shapiro ldap_memfree(attr); 125940266059SGregory Neil Shapiro } 126040266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 126140266059SGregory Neil Shapiro 126240266059SGregory Neil Shapiro /* 126340266059SGregory Neil Shapiro ** We check save_errno != LDAP_DECODING_ERROR since 126440266059SGregory Neil Shapiro ** OpenLDAP 1.X has a very ugly *undocumented* 126540266059SGregory Neil Shapiro ** hack of returning this error code from 126640266059SGregory Neil Shapiro ** ldap_next_attribute() if the library freed the 126740266059SGregory Neil Shapiro ** ber attribute. See: 126840266059SGregory Neil Shapiro ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 126940266059SGregory Neil Shapiro */ 127040266059SGregory Neil Shapiro 127140266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS && 127240266059SGregory Neil Shapiro save_errno != LDAP_DECODING_ERROR) 127340266059SGregory Neil Shapiro { 127440266059SGregory Neil Shapiro /* Must be an error */ 127540266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 1276605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 127740266059SGregory Neil Shapiro errno = save_errno; 127840266059SGregory Neil Shapiro return EX_TEMPFAIL; 127940266059SGregory Neil Shapiro } 128040266059SGregory Neil Shapiro 1281605302a5SGregory Neil Shapiro /* mark this DN as done */ 1282605302a5SGregory Neil Shapiro rl->lr_done = true; 1283e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp != NULL) 1284e92d3f3fSGregory Neil Shapiro { 1285e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1286e92d3f3fSGregory Neil Shapiro rl->lr_ludp = NULL; 1287e92d3f3fSGregory Neil Shapiro } 1288e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs != NULL) 1289e92d3f3fSGregory Neil Shapiro { 1290e92d3f3fSGregory Neil Shapiro free(rl->lr_attrs); 1291e92d3f3fSGregory Neil Shapiro rl->lr_attrs = NULL; 1292e92d3f3fSGregory Neil Shapiro } 1293605302a5SGregory Neil Shapiro 129440266059SGregory Neil Shapiro /* We don't want multiple values and we have one */ 129513d88268SGregory Neil Shapiro if ((char) delim == '\0' && 129613d88268SGregory Neil Shapiro !bitset(SM_LDAP_SINGLEMATCH, flags) && 129713d88268SGregory Neil Shapiro *result != NULL) 129840266059SGregory Neil Shapiro break; 129940266059SGregory Neil Shapiro } 130040266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 130140266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS && 130240266059SGregory Neil Shapiro save_errno != LDAP_DECODING_ERROR) 130340266059SGregory Neil Shapiro { 130440266059SGregory Neil Shapiro /* Must be an error */ 130540266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 1306605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 130740266059SGregory Neil Shapiro errno = save_errno; 130840266059SGregory Neil Shapiro return EX_TEMPFAIL; 130940266059SGregory Neil Shapiro } 131040266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); 131140266059SGregory Neil Shapiro lmap->ldap_res = NULL; 131240266059SGregory Neil Shapiro } 131340266059SGregory Neil Shapiro 131440266059SGregory Neil Shapiro if (ret == 0) 131540266059SGregory Neil Shapiro save_errno = ETIMEDOUT; 13166f9c8e5bSGregory Neil Shapiro else if (ret == LDAP_RES_SEARCH_RESULT) 13179bd497b8SGregory Neil Shapiro { 13189bd497b8SGregory Neil Shapiro /* 13199bd497b8SGregory Neil Shapiro ** We may have gotten an LDAP_RES_SEARCH_RESULT response 13209bd497b8SGregory Neil Shapiro ** with an error inside it, so we have to extract that 13219bd497b8SGregory Neil Shapiro ** with ldap_parse_result(). This can happen when talking 13229bd497b8SGregory Neil Shapiro ** to an LDAP proxy whose backend has gone down. 13239bd497b8SGregory Neil Shapiro */ 13249bd497b8SGregory Neil Shapiro 13256f9c8e5bSGregory Neil Shapiro if (lmap->ldap_res == NULL) 13266f9c8e5bSGregory Neil Shapiro save_errno = LDAP_UNAVAILABLE; 13276f9c8e5bSGregory Neil Shapiro else 13286f9c8e5bSGregory Neil Shapiro { 13296f9c8e5bSGregory Neil Shapiro int rc; 13306f9c8e5bSGregory Neil Shapiro 13316f9c8e5bSGregory Neil Shapiro save_errno = ldap_parse_result(lmap->ldap_ld, 13326f9c8e5bSGregory Neil Shapiro lmap->ldap_res, &rc, NULL, NULL, 13336f9c8e5bSGregory Neil Shapiro NULL, NULL, 0); 13349bd497b8SGregory Neil Shapiro if (save_errno == LDAP_SUCCESS) 13359bd497b8SGregory Neil Shapiro save_errno = rc; 13369bd497b8SGregory Neil Shapiro } 13376f9c8e5bSGregory Neil Shapiro } 13386f9c8e5bSGregory Neil Shapiro else 13396f9c8e5bSGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 134040266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS) 134140266059SGregory Neil Shapiro { 134240266059SGregory Neil Shapiro statp = EX_TEMPFAIL; 134340266059SGregory Neil Shapiro switch (save_errno) 134440266059SGregory Neil Shapiro { 134540266059SGregory Neil Shapiro #ifdef LDAP_SERVER_DOWN 134640266059SGregory Neil Shapiro case LDAP_SERVER_DOWN: 134740266059SGregory Neil Shapiro #endif /* LDAP_SERVER_DOWN */ 134840266059SGregory Neil Shapiro case LDAP_TIMEOUT: 1349ffb83623SGregory Neil Shapiro case ETIMEDOUT: 135040266059SGregory Neil Shapiro case LDAP_UNAVAILABLE: 1351605302a5SGregory Neil Shapiro 1352605302a5SGregory Neil Shapiro /* 1353605302a5SGregory Neil Shapiro ** server disappeared, 1354605302a5SGregory Neil Shapiro ** try reopen on next search 1355605302a5SGregory Neil Shapiro */ 1356605302a5SGregory Neil Shapiro 135740266059SGregory Neil Shapiro statp = EX_RESTART; 135840266059SGregory Neil Shapiro break; 135940266059SGregory Neil Shapiro } 1360ffb83623SGregory Neil Shapiro if (ret != 0) 136140266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 1362605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 136340266059SGregory Neil Shapiro errno = save_errno; 136440266059SGregory Neil Shapiro return statp; 136540266059SGregory Neil Shapiro } 136640266059SGregory Neil Shapiro 136740266059SGregory Neil Shapiro if (lmap->ldap_res != NULL) 136840266059SGregory Neil Shapiro { 136940266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); 137040266059SGregory Neil Shapiro lmap->ldap_res = NULL; 137140266059SGregory Neil Shapiro } 137240266059SGregory Neil Shapiro 137340266059SGregory Neil Shapiro if (toplevel) 137440266059SGregory Neil Shapiro { 1375605302a5SGregory Neil Shapiro int rlidx; 137640266059SGregory Neil Shapiro 137740266059SGregory Neil Shapiro /* 137840266059SGregory Neil Shapiro ** Spin through the built-up recurse list at the top 137940266059SGregory Neil Shapiro ** of the recursion. Since new items are added at the 138040266059SGregory Neil Shapiro ** end of the shared list, we actually only ever get 138140266059SGregory Neil Shapiro ** one level of recursion before things pop back to the 138240266059SGregory Neil Shapiro ** top. Any items added to the list during that recursion 138340266059SGregory Neil Shapiro ** will be expanded by the top level. 138440266059SGregory Neil Shapiro */ 138540266059SGregory Neil Shapiro 1386d0cef73dSGregory Neil Shapiro for (rlidx = 0; recurse != NULL && rlidx < recurse->lrl_cnt; 1387d0cef73dSGregory Neil Shapiro rlidx++) 138840266059SGregory Neil Shapiro { 1389605302a5SGregory Neil Shapiro int newflags; 139040266059SGregory Neil Shapiro int sid; 139140266059SGregory Neil Shapiro int status; 139240266059SGregory Neil Shapiro 1393d0cef73dSGregory Neil Shapiro rl = recurse->lrl_data[rlidx]; 1394605302a5SGregory Neil Shapiro 1395605302a5SGregory Neil Shapiro newflags = flags; 1396605302a5SGregory Neil Shapiro if (rl->lr_done) 139740266059SGregory Neil Shapiro { 139840266059SGregory Neil Shapiro /* already expanded */ 139940266059SGregory Neil Shapiro continue; 140040266059SGregory Neil Shapiro } 1401605302a5SGregory Neil Shapiro 1402605302a5SGregory Neil Shapiro if (rl->lr_type == SM_LDAP_ATTR_DN) 140340266059SGregory Neil Shapiro { 140440266059SGregory Neil Shapiro /* do DN search */ 140540266059SGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 140640266059SGregory Neil Shapiro rl->lr_search, 140740266059SGregory Neil Shapiro lmap->ldap_scope, 140840266059SGregory Neil Shapiro "(objectClass=*)", 1409605302a5SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? 1410605302a5SGregory Neil Shapiro NULL : lmap->ldap_attr), 141140266059SGregory Neil Shapiro lmap->ldap_attrsonly); 141240266059SGregory Neil Shapiro } 1413605302a5SGregory Neil Shapiro else if (rl->lr_type == SM_LDAP_ATTR_FILTER) 141440266059SGregory Neil Shapiro { 141540266059SGregory Neil Shapiro /* do new search */ 141640266059SGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 141740266059SGregory Neil Shapiro lmap->ldap_base, 141840266059SGregory Neil Shapiro lmap->ldap_scope, 141940266059SGregory Neil Shapiro rl->lr_search, 1420605302a5SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? 1421605302a5SGregory Neil Shapiro NULL : lmap->ldap_attr), 142240266059SGregory Neil Shapiro lmap->ldap_attrsonly); 142340266059SGregory Neil Shapiro } 1424605302a5SGregory Neil Shapiro else if (rl->lr_type == SM_LDAP_ATTR_URL) 142540266059SGregory Neil Shapiro { 1426e92d3f3fSGregory Neil Shapiro /* Parse URL */ 1427e92d3f3fSGregory Neil Shapiro sid = ldap_url_parse(rl->lr_search, 1428e92d3f3fSGregory Neil Shapiro &rl->lr_ludp); 1429e92d3f3fSGregory Neil Shapiro 1430e92d3f3fSGregory Neil Shapiro if (sid != 0) 1431e92d3f3fSGregory Neil Shapiro { 1432e92d3f3fSGregory Neil Shapiro errno = sid + E_LDAPURLBASE; 1433e92d3f3fSGregory Neil Shapiro return EX_TEMPFAIL; 1434e92d3f3fSGregory Neil Shapiro } 1435e92d3f3fSGregory Neil Shapiro 1436e92d3f3fSGregory Neil Shapiro /* We need to add objectClass */ 1437e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp->lud_attrs != NULL) 1438e92d3f3fSGregory Neil Shapiro { 1439e92d3f3fSGregory Neil Shapiro int attrnum = 0; 1440e92d3f3fSGregory Neil Shapiro 1441e92d3f3fSGregory Neil Shapiro while (rl->lr_ludp->lud_attrs[attrnum] != NULL) 1442e92d3f3fSGregory Neil Shapiro { 1443e92d3f3fSGregory Neil Shapiro if (strcasecmp(rl->lr_ludp->lud_attrs[attrnum], 1444e92d3f3fSGregory Neil Shapiro "objectClass") == 0) 1445e92d3f3fSGregory Neil Shapiro { 1446e92d3f3fSGregory Neil Shapiro /* already requested */ 1447e92d3f3fSGregory Neil Shapiro attrnum = -1; 1448e92d3f3fSGregory Neil Shapiro break; 1449e92d3f3fSGregory Neil Shapiro } 1450e92d3f3fSGregory Neil Shapiro attrnum++; 1451e92d3f3fSGregory Neil Shapiro } 1452e92d3f3fSGregory Neil Shapiro 1453e92d3f3fSGregory Neil Shapiro if (attrnum >= 0) 1454e92d3f3fSGregory Neil Shapiro { 1455e92d3f3fSGregory Neil Shapiro int i; 1456e92d3f3fSGregory Neil Shapiro 1457e92d3f3fSGregory Neil Shapiro rl->lr_attrs = (char **)malloc(sizeof(char *) * (attrnum + 2)); 1458e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs == NULL) 1459e92d3f3fSGregory Neil Shapiro { 1460e92d3f3fSGregory Neil Shapiro save_errno = errno; 1461e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1462e92d3f3fSGregory Neil Shapiro errno = save_errno; 1463e92d3f3fSGregory Neil Shapiro return EX_TEMPFAIL; 1464e92d3f3fSGregory Neil Shapiro } 1465e92d3f3fSGregory Neil Shapiro for (i = 0 ; i < attrnum; i++) 1466e92d3f3fSGregory Neil Shapiro { 1467e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i] = rl->lr_ludp->lud_attrs[i]; 1468e92d3f3fSGregory Neil Shapiro } 1469e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i++] = "objectClass"; 1470e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i++] = NULL; 1471e92d3f3fSGregory Neil Shapiro } 1472e92d3f3fSGregory Neil Shapiro } 1473e92d3f3fSGregory Neil Shapiro 1474e92d3f3fSGregory Neil Shapiro /* 1475e92d3f3fSGregory Neil Shapiro ** Use the existing connection 1476e92d3f3fSGregory Neil Shapiro ** for this search. It really 1477e92d3f3fSGregory Neil Shapiro ** should use lud_scheme://lud_host:lud_port/ 1478e92d3f3fSGregory Neil Shapiro ** instead but that would require 1479e92d3f3fSGregory Neil Shapiro ** opening a new connection. 1480e92d3f3fSGregory Neil Shapiro ** This should be fixed ASAP. 1481e92d3f3fSGregory Neil Shapiro */ 1482e92d3f3fSGregory Neil Shapiro 1483e92d3f3fSGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 1484e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_dn, 1485e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_scope, 1486e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_filter, 1487e92d3f3fSGregory Neil Shapiro rl->lr_attrs, 148840266059SGregory Neil Shapiro lmap->ldap_attrsonly); 1489e92d3f3fSGregory Neil Shapiro 1490e92d3f3fSGregory Neil Shapiro /* Use the attributes specified by URL */ 1491605302a5SGregory Neil Shapiro newflags |= SM_LDAP_USE_ALLATTR; 149240266059SGregory Neil Shapiro } 149340266059SGregory Neil Shapiro else 149440266059SGregory Neil Shapiro { 149540266059SGregory Neil Shapiro /* unknown or illegal attribute type */ 149640266059SGregory Neil Shapiro errno = EFAULT; 149740266059SGregory Neil Shapiro return EX_SOFTWARE; 149840266059SGregory Neil Shapiro } 149940266059SGregory Neil Shapiro 150040266059SGregory Neil Shapiro /* Collect results */ 150140266059SGregory Neil Shapiro if (sid == -1) 150240266059SGregory Neil Shapiro { 150340266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 150440266059SGregory Neil Shapiro statp = EX_TEMPFAIL; 150540266059SGregory Neil Shapiro switch (save_errno) 150640266059SGregory Neil Shapiro { 150740266059SGregory Neil Shapiro #ifdef LDAP_SERVER_DOWN 150840266059SGregory Neil Shapiro case LDAP_SERVER_DOWN: 150940266059SGregory Neil Shapiro #endif /* LDAP_SERVER_DOWN */ 151040266059SGregory Neil Shapiro case LDAP_TIMEOUT: 1511ffb83623SGregory Neil Shapiro case ETIMEDOUT: 151240266059SGregory Neil Shapiro case LDAP_UNAVAILABLE: 1513605302a5SGregory Neil Shapiro 1514605302a5SGregory Neil Shapiro /* 1515605302a5SGregory Neil Shapiro ** server disappeared, 1516605302a5SGregory Neil Shapiro ** try reopen on next search 1517605302a5SGregory Neil Shapiro */ 1518605302a5SGregory Neil Shapiro 151940266059SGregory Neil Shapiro statp = EX_RESTART; 152040266059SGregory Neil Shapiro break; 152140266059SGregory Neil Shapiro } 152240266059SGregory Neil Shapiro errno = save_errno + E_LDAPBASE; 152340266059SGregory Neil Shapiro return statp; 152440266059SGregory Neil Shapiro } 152540266059SGregory Neil Shapiro 1526605302a5SGregory Neil Shapiro status = sm_ldap_results(lmap, sid, newflags, delim, 1527605302a5SGregory Neil Shapiro rpool, result, resultln, 1528605302a5SGregory Neil Shapiro resultsz, recurse); 152940266059SGregory Neil Shapiro save_errno = errno; 153040266059SGregory Neil Shapiro if (status != EX_OK && status != EX_NOTFOUND) 153140266059SGregory Neil Shapiro { 153240266059SGregory Neil Shapiro errno = save_errno; 153340266059SGregory Neil Shapiro return status; 153440266059SGregory Neil Shapiro } 153540266059SGregory Neil Shapiro 153640266059SGregory Neil Shapiro /* Mark as done */ 1537605302a5SGregory Neil Shapiro rl->lr_done = true; 1538e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp != NULL) 1539e92d3f3fSGregory Neil Shapiro { 1540e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1541e92d3f3fSGregory Neil Shapiro rl->lr_ludp = NULL; 1542e92d3f3fSGregory Neil Shapiro } 1543e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs != NULL) 1544e92d3f3fSGregory Neil Shapiro { 1545e92d3f3fSGregory Neil Shapiro free(rl->lr_attrs); 1546e92d3f3fSGregory Neil Shapiro rl->lr_attrs = NULL; 1547e92d3f3fSGregory Neil Shapiro } 1548605302a5SGregory Neil Shapiro 1549605302a5SGregory Neil Shapiro /* Reset rlidx as new items may have been added */ 1550605302a5SGregory Neil Shapiro rlidx = -1; 155140266059SGregory Neil Shapiro } 155240266059SGregory Neil Shapiro } 155340266059SGregory Neil Shapiro return statp; 155440266059SGregory Neil Shapiro } 155540266059SGregory Neil Shapiro 155640266059SGregory Neil Shapiro /* 155740266059SGregory Neil Shapiro ** SM_LDAP_CLOSE -- close LDAP connection 155840266059SGregory Neil Shapiro ** 155940266059SGregory Neil Shapiro ** Parameters: 156040266059SGregory Neil Shapiro ** lmap -- LDAP map information 156140266059SGregory Neil Shapiro ** 156240266059SGregory Neil Shapiro ** Returns: 156340266059SGregory Neil Shapiro ** None. 156440266059SGregory Neil Shapiro ** 156540266059SGregory Neil Shapiro */ 156640266059SGregory Neil Shapiro 156740266059SGregory Neil Shapiro void 156840266059SGregory Neil Shapiro sm_ldap_close(lmap) 156940266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 157040266059SGregory Neil Shapiro { 157140266059SGregory Neil Shapiro if (lmap->ldap_ld == NULL) 157240266059SGregory Neil Shapiro return; 157340266059SGregory Neil Shapiro 157440266059SGregory Neil Shapiro if (lmap->ldap_pid == getpid()) 157540266059SGregory Neil Shapiro ldap_unbind(lmap->ldap_ld); 157640266059SGregory Neil Shapiro lmap->ldap_ld = NULL; 157740266059SGregory Neil Shapiro lmap->ldap_pid = 0; 157840266059SGregory Neil Shapiro } 157940266059SGregory Neil Shapiro /* 158040266059SGregory Neil Shapiro ** SM_LDAP_GETERRNO -- get ldap errno value 158140266059SGregory Neil Shapiro ** 158240266059SGregory Neil Shapiro ** Parameters: 158340266059SGregory Neil Shapiro ** ld -- LDAP session handle 158440266059SGregory Neil Shapiro ** 158540266059SGregory Neil Shapiro ** Returns: 158640266059SGregory Neil Shapiro ** LDAP errno. 158740266059SGregory Neil Shapiro ** 158840266059SGregory Neil Shapiro */ 158940266059SGregory Neil Shapiro 159040266059SGregory Neil Shapiro int 159140266059SGregory Neil Shapiro sm_ldap_geterrno(ld) 159240266059SGregory Neil Shapiro LDAP *ld; 159340266059SGregory Neil Shapiro { 159440266059SGregory Neil Shapiro int err = LDAP_SUCCESS; 159540266059SGregory Neil Shapiro 159640266059SGregory Neil Shapiro # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 1597*5b0945b5SGregory Neil Shapiro # ifdef LDAP_OPT_RESULT_CODE 1598*5b0945b5SGregory Neil Shapiro # define LDAP_GET_RESULT_CODE LDAP_OPT_RESULT_CODE 1599*5b0945b5SGregory Neil Shapiro # else 1600*5b0945b5SGregory Neil Shapiro # define LDAP_GET_RESULT_CODE LDAP_OPT_ERROR_NUMBER 1601*5b0945b5SGregory Neil Shapiro # endif 1602*5b0945b5SGregory Neil Shapiro (void) ldap_get_option(ld, LDAP_GET_RESULT_CODE, &err); 1603*5b0945b5SGregory Neil Shapiro # else 160440266059SGregory Neil Shapiro # ifdef LDAP_OPT_SIZELIMIT 160540266059SGregory Neil Shapiro err = ldap_get_lderrno(ld, NULL, NULL); 1606*5b0945b5SGregory Neil Shapiro # else 160740266059SGregory Neil Shapiro err = ld->ld_errno; 160840266059SGregory Neil Shapiro 160940266059SGregory Neil Shapiro /* 161040266059SGregory Neil Shapiro ** Reset value to prevent lingering LDAP_DECODING_ERROR due to 161140266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see above) 161240266059SGregory Neil Shapiro */ 161340266059SGregory Neil Shapiro 161440266059SGregory Neil Shapiro ld->ld_errno = LDAP_SUCCESS; 161540266059SGregory Neil Shapiro # endif /* LDAP_OPT_SIZELIMIT */ 161640266059SGregory Neil Shapiro # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 161740266059SGregory Neil Shapiro return err; 161840266059SGregory Neil Shapiro } 161940266059SGregory Neil Shapiro # endif /* LDAPMAP */ 1620