1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 2001-2005 Sendmail, Inc. and its suppliers. 3*7c478bd9Sstevel@tonic-gate * All rights reserved. 4*7c478bd9Sstevel@tonic-gate * 5*7c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 6*7c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 7*7c478bd9Sstevel@tonic-gate * the sendmail distribution. 8*7c478bd9Sstevel@tonic-gate */ 9*7c478bd9Sstevel@tonic-gate 10*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 11*7c478bd9Sstevel@tonic-gate 12*7c478bd9Sstevel@tonic-gate #include <sm/gen.h> 13*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: ldap.c,v 1.62 2005/02/24 00:30:01 ca Exp $") 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #if LDAPMAP 16*7c478bd9Sstevel@tonic-gate # include <sys/types.h> 17*7c478bd9Sstevel@tonic-gate # include <errno.h> 18*7c478bd9Sstevel@tonic-gate # include <setjmp.h> 19*7c478bd9Sstevel@tonic-gate # include <stdlib.h> 20*7c478bd9Sstevel@tonic-gate # include <unistd.h> 21*7c478bd9Sstevel@tonic-gate 22*7c478bd9Sstevel@tonic-gate # include <sm/bitops.h> 23*7c478bd9Sstevel@tonic-gate # include <sm/clock.h> 24*7c478bd9Sstevel@tonic-gate # include <sm/conf.h> 25*7c478bd9Sstevel@tonic-gate # include <sm/debug.h> 26*7c478bd9Sstevel@tonic-gate # include <sm/errstring.h> 27*7c478bd9Sstevel@tonic-gate # include <sm/ldap.h> 28*7c478bd9Sstevel@tonic-gate # include <sm/string.h> 29*7c478bd9Sstevel@tonic-gate # ifdef EX_OK 30*7c478bd9Sstevel@tonic-gate # undef EX_OK /* for SVr4.2 SMP */ 31*7c478bd9Sstevel@tonic-gate # endif /* EX_OK */ 32*7c478bd9Sstevel@tonic-gate # include <sm/sysexits.h> 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap", 35*7c478bd9Sstevel@tonic-gate "@(#)$Debug: sm_trace_ldap - trace LDAP operations $"); 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate static void ldaptimeout __P((int)); 38*7c478bd9Sstevel@tonic-gate static bool sm_ldap_has_objectclass __P((SM_LDAP_STRUCT *, LDAPMessage *, char *)); 39*7c478bd9Sstevel@tonic-gate static SM_LDAP_RECURSE_ENTRY *sm_ldap_add_recurse __P((SM_LDAP_RECURSE_LIST **, char *, int, SM_RPOOL_T *)); 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* 42*7c478bd9Sstevel@tonic-gate ** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT 43*7c478bd9Sstevel@tonic-gate ** 44*7c478bd9Sstevel@tonic-gate ** Parameters: 45*7c478bd9Sstevel@tonic-gate ** lmap -- pointer to SM_LDAP_STRUCT to clear 46*7c478bd9Sstevel@tonic-gate ** 47*7c478bd9Sstevel@tonic-gate ** Returns: 48*7c478bd9Sstevel@tonic-gate ** None. 49*7c478bd9Sstevel@tonic-gate ** 50*7c478bd9Sstevel@tonic-gate */ 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate void 53*7c478bd9Sstevel@tonic-gate sm_ldap_clear(lmap) 54*7c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 55*7c478bd9Sstevel@tonic-gate { 56*7c478bd9Sstevel@tonic-gate if (lmap == NULL) 57*7c478bd9Sstevel@tonic-gate return; 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate lmap->ldap_host = NULL; 60*7c478bd9Sstevel@tonic-gate lmap->ldap_port = LDAP_PORT; 61*7c478bd9Sstevel@tonic-gate lmap->ldap_uri = NULL; 62*7c478bd9Sstevel@tonic-gate lmap->ldap_version = 0; 63*7c478bd9Sstevel@tonic-gate lmap->ldap_deref = LDAP_DEREF_NEVER; 64*7c478bd9Sstevel@tonic-gate lmap->ldap_timelimit = LDAP_NO_LIMIT; 65*7c478bd9Sstevel@tonic-gate lmap->ldap_sizelimit = LDAP_NO_LIMIT; 66*7c478bd9Sstevel@tonic-gate # ifdef LDAP_REFERRALS 67*7c478bd9Sstevel@tonic-gate lmap->ldap_options = LDAP_OPT_REFERRALS; 68*7c478bd9Sstevel@tonic-gate # else /* LDAP_REFERRALS */ 69*7c478bd9Sstevel@tonic-gate lmap->ldap_options = 0; 70*7c478bd9Sstevel@tonic-gate # endif /* LDAP_REFERRALS */ 71*7c478bd9Sstevel@tonic-gate lmap->ldap_attrsep = '\0'; 72*7c478bd9Sstevel@tonic-gate lmap->ldap_binddn = NULL; 73*7c478bd9Sstevel@tonic-gate lmap->ldap_secret = NULL; 74*7c478bd9Sstevel@tonic-gate lmap->ldap_method = LDAP_AUTH_SIMPLE; 75*7c478bd9Sstevel@tonic-gate lmap->ldap_base = NULL; 76*7c478bd9Sstevel@tonic-gate lmap->ldap_scope = LDAP_SCOPE_SUBTREE; 77*7c478bd9Sstevel@tonic-gate lmap->ldap_attrsonly = LDAPMAP_FALSE; 78*7c478bd9Sstevel@tonic-gate lmap->ldap_timeout.tv_sec = 0; 79*7c478bd9Sstevel@tonic-gate lmap->ldap_timeout.tv_usec = 0; 80*7c478bd9Sstevel@tonic-gate lmap->ldap_ld = NULL; 81*7c478bd9Sstevel@tonic-gate lmap->ldap_filter = NULL; 82*7c478bd9Sstevel@tonic-gate lmap->ldap_attr[0] = NULL; 83*7c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE; 84*7c478bd9Sstevel@tonic-gate lmap->ldap_attr_needobjclass[0] = NULL; 85*7c478bd9Sstevel@tonic-gate lmap->ldap_res = NULL; 86*7c478bd9Sstevel@tonic-gate lmap->ldap_next = NULL; 87*7c478bd9Sstevel@tonic-gate lmap->ldap_pid = 0; 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate /* 91*7c478bd9Sstevel@tonic-gate ** SM_LDAP_START -- actually connect to an LDAP server 92*7c478bd9Sstevel@tonic-gate ** 93*7c478bd9Sstevel@tonic-gate ** Parameters: 94*7c478bd9Sstevel@tonic-gate ** name -- name of map for debug output. 95*7c478bd9Sstevel@tonic-gate ** lmap -- the LDAP map being opened. 96*7c478bd9Sstevel@tonic-gate ** 97*7c478bd9Sstevel@tonic-gate ** Returns: 98*7c478bd9Sstevel@tonic-gate ** true if connection is successful, false otherwise. 99*7c478bd9Sstevel@tonic-gate ** 100*7c478bd9Sstevel@tonic-gate ** Side Effects: 101*7c478bd9Sstevel@tonic-gate ** Populates lmap->ldap_ld. 102*7c478bd9Sstevel@tonic-gate */ 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate static jmp_buf LDAPTimeout; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate #define SM_LDAP_SETTIMEOUT(to) \ 107*7c478bd9Sstevel@tonic-gate do \ 108*7c478bd9Sstevel@tonic-gate { \ 109*7c478bd9Sstevel@tonic-gate if (to != 0) \ 110*7c478bd9Sstevel@tonic-gate { \ 111*7c478bd9Sstevel@tonic-gate if (setjmp(LDAPTimeout) != 0) \ 112*7c478bd9Sstevel@tonic-gate { \ 113*7c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; \ 114*7c478bd9Sstevel@tonic-gate return false; \ 115*7c478bd9Sstevel@tonic-gate } \ 116*7c478bd9Sstevel@tonic-gate ev = sm_setevent(to, ldaptimeout, 0); \ 117*7c478bd9Sstevel@tonic-gate } \ 118*7c478bd9Sstevel@tonic-gate } while (0) 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate #define SM_LDAP_CLEARTIMEOUT() \ 121*7c478bd9Sstevel@tonic-gate do \ 122*7c478bd9Sstevel@tonic-gate { \ 123*7c478bd9Sstevel@tonic-gate if (ev != NULL) \ 124*7c478bd9Sstevel@tonic-gate sm_clrevent(ev); \ 125*7c478bd9Sstevel@tonic-gate } while (0) 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate bool 128*7c478bd9Sstevel@tonic-gate sm_ldap_start(name, lmap) 129*7c478bd9Sstevel@tonic-gate char *name; 130*7c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 131*7c478bd9Sstevel@tonic-gate { 132*7c478bd9Sstevel@tonic-gate int bind_result; 133*7c478bd9Sstevel@tonic-gate int save_errno = 0; 134*7c478bd9Sstevel@tonic-gate char *id; 135*7c478bd9Sstevel@tonic-gate SM_EVENT *ev = NULL; 136*7c478bd9Sstevel@tonic-gate LDAP *ld = NULL; 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate if (sm_debug_active(&SmLDAPTrace, 2)) 139*7c478bd9Sstevel@tonic-gate sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name); 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate if (lmap->ldap_host != NULL) 142*7c478bd9Sstevel@tonic-gate id = lmap->ldap_host; 143*7c478bd9Sstevel@tonic-gate else if (lmap->ldap_uri != NULL) 144*7c478bd9Sstevel@tonic-gate id = lmap->ldap_uri; 145*7c478bd9Sstevel@tonic-gate else 146*7c478bd9Sstevel@tonic-gate id = "localhost"; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate if (sm_debug_active(&SmLDAPTrace, 9)) 149*7c478bd9Sstevel@tonic-gate { 150*7c478bd9Sstevel@tonic-gate /* Don't print a port number for LDAP URIs */ 151*7c478bd9Sstevel@tonic-gate if (lmap->ldap_uri != NULL) 152*7c478bd9Sstevel@tonic-gate sm_dprintf("ldapmap_start(%s)\n", id); 153*7c478bd9Sstevel@tonic-gate else 154*7c478bd9Sstevel@tonic-gate sm_dprintf("ldapmap_start(%s, %d)\n", id, 155*7c478bd9Sstevel@tonic-gate lmap->ldap_port); 156*7c478bd9Sstevel@tonic-gate } 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate if (lmap->ldap_uri != NULL) 159*7c478bd9Sstevel@tonic-gate { 160*7c478bd9Sstevel@tonic-gate #if SM_CONF_LDAP_INITIALIZE 161*7c478bd9Sstevel@tonic-gate /* LDAP server supports URIs so use them directly */ 162*7c478bd9Sstevel@tonic-gate save_errno = ldap_initialize(&ld, lmap->ldap_uri); 163*7c478bd9Sstevel@tonic-gate #else /* SM_CONF_LDAP_INITIALIZE */ 164*7c478bd9Sstevel@tonic-gate int err; 165*7c478bd9Sstevel@tonic-gate LDAPURLDesc *ludp = NULL; 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate /* Blast apart URL and use the ldap_init/ldap_open below */ 168*7c478bd9Sstevel@tonic-gate err = ldap_url_parse(lmap->ldap_uri, &ludp); 169*7c478bd9Sstevel@tonic-gate if (err != 0) 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate errno = err + E_LDAPURLBASE; 172*7c478bd9Sstevel@tonic-gate return false; 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate lmap->ldap_host = sm_strdup_x(ludp->lud_host); 175*7c478bd9Sstevel@tonic-gate if (lmap->ldap_host == NULL) 176*7c478bd9Sstevel@tonic-gate { 177*7c478bd9Sstevel@tonic-gate save_errno = errno; 178*7c478bd9Sstevel@tonic-gate ldap_free_urldesc(ludp); 179*7c478bd9Sstevel@tonic-gate errno = save_errno; 180*7c478bd9Sstevel@tonic-gate return false; 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate lmap->ldap_port = ludp->lud_port; 183*7c478bd9Sstevel@tonic-gate ldap_free_urldesc(ludp); 184*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_LDAP_INITIALIZE */ 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate if (ld == NULL) 188*7c478bd9Sstevel@tonic-gate { 189*7c478bd9Sstevel@tonic-gate # if USE_LDAP_INIT 190*7c478bd9Sstevel@tonic-gate ld = ldap_init(lmap->ldap_host, lmap->ldap_port); 191*7c478bd9Sstevel@tonic-gate save_errno = errno; 192*7c478bd9Sstevel@tonic-gate # else /* USE_LDAP_INIT */ 193*7c478bd9Sstevel@tonic-gate /* 194*7c478bd9Sstevel@tonic-gate ** If using ldap_open(), the actual connection to the server 195*7c478bd9Sstevel@tonic-gate ** happens now so we need the timeout here. For ldap_init(), 196*7c478bd9Sstevel@tonic-gate ** the connection happens at bind time. 197*7c478bd9Sstevel@tonic-gate */ 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); 200*7c478bd9Sstevel@tonic-gate ld = ldap_open(lmap->ldap_host, lmap->ldap_port); 201*7c478bd9Sstevel@tonic-gate save_errno = errno; 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate /* clear the event if it has not sprung */ 204*7c478bd9Sstevel@tonic-gate SM_LDAP_CLEARTIMEOUT(); 205*7c478bd9Sstevel@tonic-gate # endif /* USE_LDAP_INIT */ 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate errno = save_errno; 209*7c478bd9Sstevel@tonic-gate if (ld == NULL) 210*7c478bd9Sstevel@tonic-gate return false; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate sm_ldap_setopts(ld, lmap); 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate # if USE_LDAP_INIT 215*7c478bd9Sstevel@tonic-gate /* 216*7c478bd9Sstevel@tonic-gate ** If using ldap_init(), the actual connection to the server 217*7c478bd9Sstevel@tonic-gate ** happens at ldap_bind_s() so we need the timeout here. 218*7c478bd9Sstevel@tonic-gate */ 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); 221*7c478bd9Sstevel@tonic-gate # endif /* USE_LDAP_INIT */ 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate # ifdef LDAP_AUTH_KRBV4 224*7c478bd9Sstevel@tonic-gate if (lmap->ldap_method == LDAP_AUTH_KRBV4 && 225*7c478bd9Sstevel@tonic-gate lmap->ldap_secret != NULL) 226*7c478bd9Sstevel@tonic-gate { 227*7c478bd9Sstevel@tonic-gate /* 228*7c478bd9Sstevel@tonic-gate ** Need to put ticket in environment here instead of 229*7c478bd9Sstevel@tonic-gate ** during parseargs as there may be different tickets 230*7c478bd9Sstevel@tonic-gate ** for different LDAP connections. 231*7c478bd9Sstevel@tonic-gate */ 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate (void) putenv(lmap->ldap_secret); 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate # endif /* LDAP_AUTH_KRBV4 */ 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate bind_result = ldap_bind_s(ld, lmap->ldap_binddn, 238*7c478bd9Sstevel@tonic-gate lmap->ldap_secret, lmap->ldap_method); 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate # if USE_LDAP_INIT 241*7c478bd9Sstevel@tonic-gate /* clear the event if it has not sprung */ 242*7c478bd9Sstevel@tonic-gate SM_LDAP_CLEARTIMEOUT(); 243*7c478bd9Sstevel@tonic-gate # endif /* USE_LDAP_INIT */ 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate if (bind_result != LDAP_SUCCESS) 246*7c478bd9Sstevel@tonic-gate { 247*7c478bd9Sstevel@tonic-gate errno = bind_result + E_LDAPBASE; 248*7c478bd9Sstevel@tonic-gate return false; 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* Save PID to make sure only this PID closes the LDAP connection */ 252*7c478bd9Sstevel@tonic-gate lmap->ldap_pid = getpid(); 253*7c478bd9Sstevel@tonic-gate lmap->ldap_ld = ld; 254*7c478bd9Sstevel@tonic-gate return true; 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 258*7c478bd9Sstevel@tonic-gate static void 259*7c478bd9Sstevel@tonic-gate ldaptimeout(unused) 260*7c478bd9Sstevel@tonic-gate int unused; 261*7c478bd9Sstevel@tonic-gate { 262*7c478bd9Sstevel@tonic-gate /* 263*7c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 264*7c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 265*7c478bd9Sstevel@tonic-gate ** DOING. 266*7c478bd9Sstevel@tonic-gate */ 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 269*7c478bd9Sstevel@tonic-gate longjmp(LDAPTimeout, 1); 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* 273*7c478bd9Sstevel@tonic-gate ** SM_LDAP_SEARCH -- initiate LDAP search 274*7c478bd9Sstevel@tonic-gate ** 275*7c478bd9Sstevel@tonic-gate ** Initiate an LDAP search, return the msgid. 276*7c478bd9Sstevel@tonic-gate ** The calling function must collect the results. 277*7c478bd9Sstevel@tonic-gate ** 278*7c478bd9Sstevel@tonic-gate ** Parameters: 279*7c478bd9Sstevel@tonic-gate ** lmap -- LDAP map information 280*7c478bd9Sstevel@tonic-gate ** key -- key to substitute in LDAP filter 281*7c478bd9Sstevel@tonic-gate ** 282*7c478bd9Sstevel@tonic-gate ** Returns: 283*7c478bd9Sstevel@tonic-gate ** -1 on failure, msgid on success 284*7c478bd9Sstevel@tonic-gate ** 285*7c478bd9Sstevel@tonic-gate */ 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate int 288*7c478bd9Sstevel@tonic-gate sm_ldap_search(lmap, key) 289*7c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 290*7c478bd9Sstevel@tonic-gate char *key; 291*7c478bd9Sstevel@tonic-gate { 292*7c478bd9Sstevel@tonic-gate int msgid; 293*7c478bd9Sstevel@tonic-gate char *fp, *p, *q; 294*7c478bd9Sstevel@tonic-gate char filter[LDAPMAP_MAX_FILTER + 1]; 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate /* substitute key into filter, perhaps multiple times */ 297*7c478bd9Sstevel@tonic-gate memset(filter, '\0', sizeof filter); 298*7c478bd9Sstevel@tonic-gate fp = filter; 299*7c478bd9Sstevel@tonic-gate p = lmap->ldap_filter; 300*7c478bd9Sstevel@tonic-gate while ((q = strchr(p, '%')) != NULL) 301*7c478bd9Sstevel@tonic-gate { 302*7c478bd9Sstevel@tonic-gate if (q[1] == 's') 303*7c478bd9Sstevel@tonic-gate { 304*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(fp, SPACELEFT(filter, fp), 305*7c478bd9Sstevel@tonic-gate "%.*s%s", (int) (q - p), p, key); 306*7c478bd9Sstevel@tonic-gate fp += strlen(fp); 307*7c478bd9Sstevel@tonic-gate p = q + 2; 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate else if (q[1] == '0') 310*7c478bd9Sstevel@tonic-gate { 311*7c478bd9Sstevel@tonic-gate char *k = key; 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(fp, SPACELEFT(filter, fp), 314*7c478bd9Sstevel@tonic-gate "%.*s", (int) (q - p), p); 315*7c478bd9Sstevel@tonic-gate fp += strlen(fp); 316*7c478bd9Sstevel@tonic-gate p = q + 2; 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate /* Properly escape LDAP special characters */ 319*7c478bd9Sstevel@tonic-gate while (SPACELEFT(filter, fp) > 0 && 320*7c478bd9Sstevel@tonic-gate *k != '\0') 321*7c478bd9Sstevel@tonic-gate { 322*7c478bd9Sstevel@tonic-gate if (*k == '*' || *k == '(' || 323*7c478bd9Sstevel@tonic-gate *k == ')' || *k == '\\') 324*7c478bd9Sstevel@tonic-gate { 325*7c478bd9Sstevel@tonic-gate (void) sm_strlcat(fp, 326*7c478bd9Sstevel@tonic-gate (*k == '*' ? "\\2A" : 327*7c478bd9Sstevel@tonic-gate (*k == '(' ? "\\28" : 328*7c478bd9Sstevel@tonic-gate (*k == ')' ? "\\29" : 329*7c478bd9Sstevel@tonic-gate (*k == '\\' ? "\\5C" : 330*7c478bd9Sstevel@tonic-gate "\00")))), 331*7c478bd9Sstevel@tonic-gate SPACELEFT(filter, fp)); 332*7c478bd9Sstevel@tonic-gate fp += strlen(fp); 333*7c478bd9Sstevel@tonic-gate k++; 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate else 336*7c478bd9Sstevel@tonic-gate *fp++ = *k++; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate else 340*7c478bd9Sstevel@tonic-gate { 341*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(fp, SPACELEFT(filter, fp), 342*7c478bd9Sstevel@tonic-gate "%.*s", (int) (q - p + 1), p); 343*7c478bd9Sstevel@tonic-gate p = q + (q[1] == '%' ? 2 : 1); 344*7c478bd9Sstevel@tonic-gate fp += strlen(fp); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(fp, p, SPACELEFT(filter, fp)); 348*7c478bd9Sstevel@tonic-gate if (sm_debug_active(&SmLDAPTrace, 20)) 349*7c478bd9Sstevel@tonic-gate sm_dprintf("ldap search filter=%s\n", filter); 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate lmap->ldap_res = NULL; 352*7c478bd9Sstevel@tonic-gate msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, 353*7c478bd9Sstevel@tonic-gate lmap->ldap_scope, filter, 354*7c478bd9Sstevel@tonic-gate (lmap->ldap_attr[0] == NULL ? NULL : 355*7c478bd9Sstevel@tonic-gate lmap->ldap_attr), 356*7c478bd9Sstevel@tonic-gate lmap->ldap_attrsonly); 357*7c478bd9Sstevel@tonic-gate return msgid; 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate /* 361*7c478bd9Sstevel@tonic-gate ** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a 362*7c478bd9Sstevel@tonic-gate ** particular objectClass 363*7c478bd9Sstevel@tonic-gate ** 364*7c478bd9Sstevel@tonic-gate ** Parameters: 365*7c478bd9Sstevel@tonic-gate ** lmap -- pointer to SM_LDAP_STRUCT in use 366*7c478bd9Sstevel@tonic-gate ** entry -- current LDAP entry struct 367*7c478bd9Sstevel@tonic-gate ** ocvalue -- particular objectclass in question. 368*7c478bd9Sstevel@tonic-gate ** may be of form (fee|foo|fum) meaning 369*7c478bd9Sstevel@tonic-gate ** any entry can be part of either fee, 370*7c478bd9Sstevel@tonic-gate ** foo or fum objectclass 371*7c478bd9Sstevel@tonic-gate ** 372*7c478bd9Sstevel@tonic-gate ** Returns: 373*7c478bd9Sstevel@tonic-gate ** true if item has that objectClass 374*7c478bd9Sstevel@tonic-gate */ 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate static bool 377*7c478bd9Sstevel@tonic-gate sm_ldap_has_objectclass(lmap, entry, ocvalue) 378*7c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 379*7c478bd9Sstevel@tonic-gate LDAPMessage *entry; 380*7c478bd9Sstevel@tonic-gate char *ocvalue; 381*7c478bd9Sstevel@tonic-gate { 382*7c478bd9Sstevel@tonic-gate char **vals = NULL; 383*7c478bd9Sstevel@tonic-gate int i; 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate if (ocvalue == NULL) 386*7c478bd9Sstevel@tonic-gate return false; 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass"); 389*7c478bd9Sstevel@tonic-gate if (vals == NULL) 390*7c478bd9Sstevel@tonic-gate return false; 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate for (i = 0; vals[i] != NULL; i++) 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate char *p; 395*7c478bd9Sstevel@tonic-gate char *q; 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate p = q = ocvalue; 398*7c478bd9Sstevel@tonic-gate while (*p != '\0') 399*7c478bd9Sstevel@tonic-gate { 400*7c478bd9Sstevel@tonic-gate while (*p != '\0' && *p != '|') 401*7c478bd9Sstevel@tonic-gate p++; 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate if ((p - q) == strlen(vals[i]) && 404*7c478bd9Sstevel@tonic-gate sm_strncasecmp(vals[i], q, p - q) == 0) 405*7c478bd9Sstevel@tonic-gate { 406*7c478bd9Sstevel@tonic-gate ldap_value_free(vals); 407*7c478bd9Sstevel@tonic-gate return true; 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate while (*p == '|') 411*7c478bd9Sstevel@tonic-gate p++; 412*7c478bd9Sstevel@tonic-gate q = p; 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate ldap_value_free(vals); 417*7c478bd9Sstevel@tonic-gate return false; 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate /* 421*7c478bd9Sstevel@tonic-gate ** SM_LDAP_RESULTS -- return results from an LDAP lookup in result 422*7c478bd9Sstevel@tonic-gate ** 423*7c478bd9Sstevel@tonic-gate ** Parameters: 424*7c478bd9Sstevel@tonic-gate ** lmap -- pointer to SM_LDAP_STRUCT in use 425*7c478bd9Sstevel@tonic-gate ** msgid -- msgid returned by sm_ldap_search() 426*7c478bd9Sstevel@tonic-gate ** flags -- flags for the lookup 427*7c478bd9Sstevel@tonic-gate ** delim -- delimiter for result concatenation 428*7c478bd9Sstevel@tonic-gate ** rpool -- memory pool for storage 429*7c478bd9Sstevel@tonic-gate ** result -- return string 430*7c478bd9Sstevel@tonic-gate ** recurse -- recursion list 431*7c478bd9Sstevel@tonic-gate ** 432*7c478bd9Sstevel@tonic-gate ** Returns: 433*7c478bd9Sstevel@tonic-gate ** status (sysexit) 434*7c478bd9Sstevel@tonic-gate */ 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate # define SM_LDAP_ERROR_CLEANUP() \ 437*7c478bd9Sstevel@tonic-gate { \ 438*7c478bd9Sstevel@tonic-gate if (lmap->ldap_res != NULL) \ 439*7c478bd9Sstevel@tonic-gate { \ 440*7c478bd9Sstevel@tonic-gate ldap_msgfree(lmap->ldap_res); \ 441*7c478bd9Sstevel@tonic-gate lmap->ldap_res = NULL; \ 442*7c478bd9Sstevel@tonic-gate } \ 443*7c478bd9Sstevel@tonic-gate (void) ldap_abandon(lmap->ldap_ld, msgid); \ 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate static SM_LDAP_RECURSE_ENTRY * 447*7c478bd9Sstevel@tonic-gate sm_ldap_add_recurse(top, item, type, rpool) 448*7c478bd9Sstevel@tonic-gate SM_LDAP_RECURSE_LIST **top; 449*7c478bd9Sstevel@tonic-gate char *item; 450*7c478bd9Sstevel@tonic-gate int type; 451*7c478bd9Sstevel@tonic-gate SM_RPOOL_T *rpool; 452*7c478bd9Sstevel@tonic-gate { 453*7c478bd9Sstevel@tonic-gate int n; 454*7c478bd9Sstevel@tonic-gate int m; 455*7c478bd9Sstevel@tonic-gate int p; 456*7c478bd9Sstevel@tonic-gate int insertat; 457*7c478bd9Sstevel@tonic-gate int moveb; 458*7c478bd9Sstevel@tonic-gate int oldsizeb; 459*7c478bd9Sstevel@tonic-gate int rc; 460*7c478bd9Sstevel@tonic-gate SM_LDAP_RECURSE_ENTRY *newe; 461*7c478bd9Sstevel@tonic-gate SM_LDAP_RECURSE_ENTRY **olddata; 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate /* 464*7c478bd9Sstevel@tonic-gate ** This code will maintain a list of 465*7c478bd9Sstevel@tonic-gate ** SM_LDAP_RECURSE_ENTRY structures 466*7c478bd9Sstevel@tonic-gate ** in ascending order. 467*7c478bd9Sstevel@tonic-gate */ 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate if (*top == NULL) 470*7c478bd9Sstevel@tonic-gate { 471*7c478bd9Sstevel@tonic-gate /* Allocate an initial SM_LDAP_RECURSE_LIST struct */ 472*7c478bd9Sstevel@tonic-gate *top = sm_rpool_malloc_x(rpool, sizeof **top); 473*7c478bd9Sstevel@tonic-gate (*top)->lr_cnt = 0; 474*7c478bd9Sstevel@tonic-gate (*top)->lr_size = 0; 475*7c478bd9Sstevel@tonic-gate (*top)->lr_data = NULL; 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate if ((*top)->lr_cnt >= (*top)->lr_size) 479*7c478bd9Sstevel@tonic-gate { 480*7c478bd9Sstevel@tonic-gate /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */ 481*7c478bd9Sstevel@tonic-gate olddata = (*top)->lr_data; 482*7c478bd9Sstevel@tonic-gate if ((*top)->lr_size == 0) 483*7c478bd9Sstevel@tonic-gate { 484*7c478bd9Sstevel@tonic-gate oldsizeb = 0; 485*7c478bd9Sstevel@tonic-gate (*top)->lr_size = 256; 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate else 488*7c478bd9Sstevel@tonic-gate { 489*7c478bd9Sstevel@tonic-gate oldsizeb = (*top)->lr_size * sizeof *((*top)->lr_data); 490*7c478bd9Sstevel@tonic-gate (*top)->lr_size *= 2; 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate (*top)->lr_data = sm_rpool_malloc_x(rpool, 493*7c478bd9Sstevel@tonic-gate (*top)->lr_size * sizeof *((*top)->lr_data)); 494*7c478bd9Sstevel@tonic-gate if (oldsizeb > 0) 495*7c478bd9Sstevel@tonic-gate memcpy((*top)->lr_data, olddata, oldsizeb); 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate /* 499*7c478bd9Sstevel@tonic-gate ** Binary search/insert item:type into list. 500*7c478bd9Sstevel@tonic-gate ** Return current entry pointer if already exists. 501*7c478bd9Sstevel@tonic-gate */ 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate n = 0; 504*7c478bd9Sstevel@tonic-gate m = (*top)->lr_cnt - 1; 505*7c478bd9Sstevel@tonic-gate if (m < 0) 506*7c478bd9Sstevel@tonic-gate insertat = 0; 507*7c478bd9Sstevel@tonic-gate else 508*7c478bd9Sstevel@tonic-gate insertat = -1; 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate while (insertat == -1) 511*7c478bd9Sstevel@tonic-gate { 512*7c478bd9Sstevel@tonic-gate p = (m + n) / 2; 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate rc = sm_strcasecmp(item, (*top)->lr_data[p]->lr_search); 515*7c478bd9Sstevel@tonic-gate if (rc == 0) 516*7c478bd9Sstevel@tonic-gate rc = type - (*top)->lr_data[p]->lr_type; 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate if (rc < 0) 519*7c478bd9Sstevel@tonic-gate m = p - 1; 520*7c478bd9Sstevel@tonic-gate else if (rc > 0) 521*7c478bd9Sstevel@tonic-gate n = p + 1; 522*7c478bd9Sstevel@tonic-gate else 523*7c478bd9Sstevel@tonic-gate return (*top)->lr_data[p]; 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate if (m == -1) 526*7c478bd9Sstevel@tonic-gate insertat = 0; 527*7c478bd9Sstevel@tonic-gate else if (n >= (*top)->lr_cnt) 528*7c478bd9Sstevel@tonic-gate insertat = (*top)->lr_cnt; 529*7c478bd9Sstevel@tonic-gate else if (m < n) 530*7c478bd9Sstevel@tonic-gate insertat = m + 1; 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate /* 534*7c478bd9Sstevel@tonic-gate ** Not found in list, make room 535*7c478bd9Sstevel@tonic-gate ** at insert point and add it. 536*7c478bd9Sstevel@tonic-gate */ 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate newe = sm_rpool_malloc_x(rpool, sizeof *newe); 539*7c478bd9Sstevel@tonic-gate if (newe != NULL) 540*7c478bd9Sstevel@tonic-gate { 541*7c478bd9Sstevel@tonic-gate moveb = ((*top)->lr_cnt - insertat) * sizeof *((*top)->lr_data); 542*7c478bd9Sstevel@tonic-gate if (moveb > 0) 543*7c478bd9Sstevel@tonic-gate memmove(&((*top)->lr_data[insertat + 1]), 544*7c478bd9Sstevel@tonic-gate &((*top)->lr_data[insertat]), 545*7c478bd9Sstevel@tonic-gate moveb); 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate newe->lr_search = sm_rpool_strdup_x(rpool, item); 548*7c478bd9Sstevel@tonic-gate newe->lr_type = type; 549*7c478bd9Sstevel@tonic-gate newe->lr_ludp = NULL; 550*7c478bd9Sstevel@tonic-gate newe->lr_attrs = NULL; 551*7c478bd9Sstevel@tonic-gate newe->lr_done = false; 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate ((*top)->lr_data)[insertat] = newe; 554*7c478bd9Sstevel@tonic-gate (*top)->lr_cnt++; 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate return newe; 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate int 560*7c478bd9Sstevel@tonic-gate sm_ldap_results(lmap, msgid, flags, delim, rpool, result, 561*7c478bd9Sstevel@tonic-gate resultln, resultsz, recurse) 562*7c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 563*7c478bd9Sstevel@tonic-gate int msgid; 564*7c478bd9Sstevel@tonic-gate int flags; 565*7c478bd9Sstevel@tonic-gate int delim; 566*7c478bd9Sstevel@tonic-gate SM_RPOOL_T *rpool; 567*7c478bd9Sstevel@tonic-gate char **result; 568*7c478bd9Sstevel@tonic-gate int *resultln; 569*7c478bd9Sstevel@tonic-gate int *resultsz; 570*7c478bd9Sstevel@tonic-gate SM_LDAP_RECURSE_LIST *recurse; 571*7c478bd9Sstevel@tonic-gate { 572*7c478bd9Sstevel@tonic-gate bool toplevel; 573*7c478bd9Sstevel@tonic-gate int i; 574*7c478bd9Sstevel@tonic-gate int statp; 575*7c478bd9Sstevel@tonic-gate int vsize; 576*7c478bd9Sstevel@tonic-gate int ret; 577*7c478bd9Sstevel@tonic-gate int save_errno; 578*7c478bd9Sstevel@tonic-gate char *p; 579*7c478bd9Sstevel@tonic-gate SM_LDAP_RECURSE_ENTRY *rl; 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate /* Are we the top top level of the search? */ 582*7c478bd9Sstevel@tonic-gate toplevel = (recurse == NULL); 583*7c478bd9Sstevel@tonic-gate 584*7c478bd9Sstevel@tonic-gate /* Get results */ 585*7c478bd9Sstevel@tonic-gate statp = EX_NOTFOUND; 586*7c478bd9Sstevel@tonic-gate while ((ret = ldap_result(lmap->ldap_ld, msgid, 0, 587*7c478bd9Sstevel@tonic-gate (lmap->ldap_timeout.tv_sec == 0 ? NULL : 588*7c478bd9Sstevel@tonic-gate &(lmap->ldap_timeout)), 589*7c478bd9Sstevel@tonic-gate &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) 590*7c478bd9Sstevel@tonic-gate { 591*7c478bd9Sstevel@tonic-gate LDAPMessage *entry; 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate /* If we don't want multiple values and we have one, break */ 594*7c478bd9Sstevel@tonic-gate if ((char) delim == '\0' && 595*7c478bd9Sstevel@tonic-gate !bitset(SM_LDAP_SINGLEMATCH, flags) && 596*7c478bd9Sstevel@tonic-gate *result != NULL) 597*7c478bd9Sstevel@tonic-gate break; 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate /* Cycle through all entries */ 600*7c478bd9Sstevel@tonic-gate for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); 601*7c478bd9Sstevel@tonic-gate entry != NULL; 602*7c478bd9Sstevel@tonic-gate entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) 603*7c478bd9Sstevel@tonic-gate { 604*7c478bd9Sstevel@tonic-gate BerElement *ber; 605*7c478bd9Sstevel@tonic-gate char *attr; 606*7c478bd9Sstevel@tonic-gate char **vals = NULL; 607*7c478bd9Sstevel@tonic-gate char *dn; 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate /* 610*7c478bd9Sstevel@tonic-gate ** If matching only and found an entry, 611*7c478bd9Sstevel@tonic-gate ** no need to spin through attributes 612*7c478bd9Sstevel@tonic-gate */ 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate if (bitset(SM_LDAP_MATCHONLY, flags)) 615*7c478bd9Sstevel@tonic-gate { 616*7c478bd9Sstevel@tonic-gate statp = EX_OK; 617*7c478bd9Sstevel@tonic-gate continue; 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate /* record completed DN's to prevent loops */ 621*7c478bd9Sstevel@tonic-gate dn = ldap_get_dn(lmap->ldap_ld, entry); 622*7c478bd9Sstevel@tonic-gate if (dn == NULL) 623*7c478bd9Sstevel@tonic-gate { 624*7c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(lmap->ldap_ld); 625*7c478bd9Sstevel@tonic-gate save_errno += E_LDAPBASE; 626*7c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 627*7c478bd9Sstevel@tonic-gate errno = save_errno; 628*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate rl = sm_ldap_add_recurse(&recurse, dn, 632*7c478bd9Sstevel@tonic-gate SM_LDAP_ATTR_DN, 633*7c478bd9Sstevel@tonic-gate rpool); 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate if (rl == NULL) 636*7c478bd9Sstevel@tonic-gate { 637*7c478bd9Sstevel@tonic-gate ldap_memfree(dn); 638*7c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 639*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 640*7c478bd9Sstevel@tonic-gate return EX_OSERR; 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate else if (rl->lr_done) 643*7c478bd9Sstevel@tonic-gate { 644*7c478bd9Sstevel@tonic-gate /* already on list, skip it */ 645*7c478bd9Sstevel@tonic-gate ldap_memfree(dn); 646*7c478bd9Sstevel@tonic-gate continue; 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate ldap_memfree(dn); 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 651*7c478bd9Sstevel@tonic-gate /* 652*7c478bd9Sstevel@tonic-gate ** Reset value to prevent lingering 653*7c478bd9Sstevel@tonic-gate ** LDAP_DECODING_ERROR due to 654*7c478bd9Sstevel@tonic-gate ** OpenLDAP 1.X's hack (see below) 655*7c478bd9Sstevel@tonic-gate */ 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 658*7c478bd9Sstevel@tonic-gate # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 659*7c478bd9Sstevel@tonic-gate 660*7c478bd9Sstevel@tonic-gate for (attr = ldap_first_attribute(lmap->ldap_ld, entry, 661*7c478bd9Sstevel@tonic-gate &ber); 662*7c478bd9Sstevel@tonic-gate attr != NULL; 663*7c478bd9Sstevel@tonic-gate attr = ldap_next_attribute(lmap->ldap_ld, entry, 664*7c478bd9Sstevel@tonic-gate ber)) 665*7c478bd9Sstevel@tonic-gate { 666*7c478bd9Sstevel@tonic-gate char *tmp, *vp_tmp; 667*7c478bd9Sstevel@tonic-gate int type; 668*7c478bd9Sstevel@tonic-gate char *needobjclass = NULL; 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate type = SM_LDAP_ATTR_NONE; 671*7c478bd9Sstevel@tonic-gate for (i = 0; lmap->ldap_attr[i] != NULL; i++) 672*7c478bd9Sstevel@tonic-gate { 673*7c478bd9Sstevel@tonic-gate if (sm_strcasecmp(lmap->ldap_attr[i], 674*7c478bd9Sstevel@tonic-gate attr) == 0) 675*7c478bd9Sstevel@tonic-gate { 676*7c478bd9Sstevel@tonic-gate type = lmap->ldap_attr_type[i]; 677*7c478bd9Sstevel@tonic-gate needobjclass = lmap->ldap_attr_needobjclass[i]; 678*7c478bd9Sstevel@tonic-gate break; 679*7c478bd9Sstevel@tonic-gate } 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate if (bitset(SM_LDAP_USE_ALLATTR, flags) && 683*7c478bd9Sstevel@tonic-gate type == SM_LDAP_ATTR_NONE) 684*7c478bd9Sstevel@tonic-gate { 685*7c478bd9Sstevel@tonic-gate /* URL lookups specify attrs to use */ 686*7c478bd9Sstevel@tonic-gate type = SM_LDAP_ATTR_NORMAL; 687*7c478bd9Sstevel@tonic-gate needobjclass = NULL; 688*7c478bd9Sstevel@tonic-gate } 689*7c478bd9Sstevel@tonic-gate 690*7c478bd9Sstevel@tonic-gate if (type == SM_LDAP_ATTR_NONE) 691*7c478bd9Sstevel@tonic-gate { 692*7c478bd9Sstevel@tonic-gate /* attribute not requested */ 693*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 694*7c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 695*7c478bd9Sstevel@tonic-gate errno = EFAULT; 696*7c478bd9Sstevel@tonic-gate return EX_SOFTWARE; 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate /* 700*7c478bd9Sstevel@tonic-gate ** For recursion on a particular attribute, 701*7c478bd9Sstevel@tonic-gate ** we may need to see if this entry is 702*7c478bd9Sstevel@tonic-gate ** part of a particular objectclass. 703*7c478bd9Sstevel@tonic-gate ** Also, ignore objectClass attribute. 704*7c478bd9Sstevel@tonic-gate ** Otherwise we just ignore this attribute. 705*7c478bd9Sstevel@tonic-gate */ 706*7c478bd9Sstevel@tonic-gate 707*7c478bd9Sstevel@tonic-gate if (type == SM_LDAP_ATTR_OBJCLASS || 708*7c478bd9Sstevel@tonic-gate (needobjclass != NULL && 709*7c478bd9Sstevel@tonic-gate !sm_ldap_has_objectclass(lmap, entry, 710*7c478bd9Sstevel@tonic-gate needobjclass))) 711*7c478bd9Sstevel@tonic-gate { 712*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 713*7c478bd9Sstevel@tonic-gate continue; 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 717*7c478bd9Sstevel@tonic-gate { 718*7c478bd9Sstevel@tonic-gate vals = ldap_get_values(lmap->ldap_ld, 719*7c478bd9Sstevel@tonic-gate entry, 720*7c478bd9Sstevel@tonic-gate attr); 721*7c478bd9Sstevel@tonic-gate if (vals == NULL) 722*7c478bd9Sstevel@tonic-gate { 723*7c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(lmap->ldap_ld); 724*7c478bd9Sstevel@tonic-gate if (save_errno == LDAP_SUCCESS) 725*7c478bd9Sstevel@tonic-gate { 726*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 727*7c478bd9Sstevel@tonic-gate continue; 728*7c478bd9Sstevel@tonic-gate } 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate /* Must be an error */ 731*7c478bd9Sstevel@tonic-gate save_errno += E_LDAPBASE; 732*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 733*7c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 734*7c478bd9Sstevel@tonic-gate errno = save_errno; 735*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate } 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate statp = EX_OK; 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 742*7c478bd9Sstevel@tonic-gate /* 743*7c478bd9Sstevel@tonic-gate ** Reset value to prevent lingering 744*7c478bd9Sstevel@tonic-gate ** LDAP_DECODING_ERROR due to 745*7c478bd9Sstevel@tonic-gate ** OpenLDAP 1.X's hack (see below) 746*7c478bd9Sstevel@tonic-gate */ 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 749*7c478bd9Sstevel@tonic-gate # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate /* 752*7c478bd9Sstevel@tonic-gate ** If matching only, 753*7c478bd9Sstevel@tonic-gate ** no need to spin through entries 754*7c478bd9Sstevel@tonic-gate */ 755*7c478bd9Sstevel@tonic-gate 756*7c478bd9Sstevel@tonic-gate if (bitset(SM_LDAP_MATCHONLY, flags)) 757*7c478bd9Sstevel@tonic-gate { 758*7c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 759*7c478bd9Sstevel@tonic-gate ldap_value_free(vals); 760*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 761*7c478bd9Sstevel@tonic-gate continue; 762*7c478bd9Sstevel@tonic-gate } 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate /* 765*7c478bd9Sstevel@tonic-gate ** If we don't want multiple values, 766*7c478bd9Sstevel@tonic-gate ** return first found. 767*7c478bd9Sstevel@tonic-gate */ 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate if ((char) delim == '\0') 770*7c478bd9Sstevel@tonic-gate { 771*7c478bd9Sstevel@tonic-gate if (*result != NULL) 772*7c478bd9Sstevel@tonic-gate { 773*7c478bd9Sstevel@tonic-gate /* already have a value */ 774*7c478bd9Sstevel@tonic-gate if (bitset(SM_LDAP_SINGLEMATCH, 775*7c478bd9Sstevel@tonic-gate flags)) 776*7c478bd9Sstevel@tonic-gate { 777*7c478bd9Sstevel@tonic-gate /* only wanted one match */ 778*7c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 779*7c478bd9Sstevel@tonic-gate errno = ENOENT; 780*7c478bd9Sstevel@tonic-gate return EX_NOTFOUND; 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate break; 783*7c478bd9Sstevel@tonic-gate } 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 786*7c478bd9Sstevel@tonic-gate { 787*7c478bd9Sstevel@tonic-gate *result = sm_rpool_strdup_x(rpool, 788*7c478bd9Sstevel@tonic-gate attr); 789*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 790*7c478bd9Sstevel@tonic-gate break; 791*7c478bd9Sstevel@tonic-gate } 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate if (vals[0] == NULL) 794*7c478bd9Sstevel@tonic-gate { 795*7c478bd9Sstevel@tonic-gate ldap_value_free(vals); 796*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 797*7c478bd9Sstevel@tonic-gate continue; 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate vsize = strlen(vals[0]) + 1; 801*7c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsep != '\0') 802*7c478bd9Sstevel@tonic-gate vsize += strlen(attr) + 1; 803*7c478bd9Sstevel@tonic-gate *result = sm_rpool_malloc_x(rpool, 804*7c478bd9Sstevel@tonic-gate vsize); 805*7c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsep != '\0') 806*7c478bd9Sstevel@tonic-gate sm_snprintf(*result, vsize, 807*7c478bd9Sstevel@tonic-gate "%s%c%s", 808*7c478bd9Sstevel@tonic-gate attr, 809*7c478bd9Sstevel@tonic-gate lmap->ldap_attrsep, 810*7c478bd9Sstevel@tonic-gate vals[0]); 811*7c478bd9Sstevel@tonic-gate else 812*7c478bd9Sstevel@tonic-gate sm_strlcpy(*result, vals[0], 813*7c478bd9Sstevel@tonic-gate vsize); 814*7c478bd9Sstevel@tonic-gate ldap_value_free(vals); 815*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 816*7c478bd9Sstevel@tonic-gate break; 817*7c478bd9Sstevel@tonic-gate } 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate /* attributes only */ 820*7c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 821*7c478bd9Sstevel@tonic-gate { 822*7c478bd9Sstevel@tonic-gate if (*result == NULL) 823*7c478bd9Sstevel@tonic-gate *result = sm_rpool_strdup_x(rpool, 824*7c478bd9Sstevel@tonic-gate attr); 825*7c478bd9Sstevel@tonic-gate else 826*7c478bd9Sstevel@tonic-gate { 827*7c478bd9Sstevel@tonic-gate if (bitset(SM_LDAP_SINGLEMATCH, 828*7c478bd9Sstevel@tonic-gate flags) && 829*7c478bd9Sstevel@tonic-gate *result != NULL) 830*7c478bd9Sstevel@tonic-gate { 831*7c478bd9Sstevel@tonic-gate /* only wanted one match */ 832*7c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 833*7c478bd9Sstevel@tonic-gate errno = ENOENT; 834*7c478bd9Sstevel@tonic-gate return EX_NOTFOUND; 835*7c478bd9Sstevel@tonic-gate } 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate vsize = strlen(*result) + 838*7c478bd9Sstevel@tonic-gate strlen(attr) + 2; 839*7c478bd9Sstevel@tonic-gate tmp = sm_rpool_malloc_x(rpool, 840*7c478bd9Sstevel@tonic-gate vsize); 841*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(tmp, 842*7c478bd9Sstevel@tonic-gate vsize, "%s%c%s", 843*7c478bd9Sstevel@tonic-gate *result, (char) delim, 844*7c478bd9Sstevel@tonic-gate attr); 845*7c478bd9Sstevel@tonic-gate *result = tmp; 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 848*7c478bd9Sstevel@tonic-gate continue; 849*7c478bd9Sstevel@tonic-gate } 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate /* 852*7c478bd9Sstevel@tonic-gate ** If there is more than one, munge then 853*7c478bd9Sstevel@tonic-gate ** into a map_coldelim separated string. 854*7c478bd9Sstevel@tonic-gate ** If we are recursing we may have an entry 855*7c478bd9Sstevel@tonic-gate ** with no 'normal' values to put in the 856*7c478bd9Sstevel@tonic-gate ** string. 857*7c478bd9Sstevel@tonic-gate ** This is not an error. 858*7c478bd9Sstevel@tonic-gate */ 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate if (type == SM_LDAP_ATTR_NORMAL && 861*7c478bd9Sstevel@tonic-gate bitset(SM_LDAP_SINGLEMATCH, flags) && 862*7c478bd9Sstevel@tonic-gate *result != NULL) 863*7c478bd9Sstevel@tonic-gate { 864*7c478bd9Sstevel@tonic-gate /* only wanted one match */ 865*7c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 866*7c478bd9Sstevel@tonic-gate errno = ENOENT; 867*7c478bd9Sstevel@tonic-gate return EX_NOTFOUND; 868*7c478bd9Sstevel@tonic-gate } 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate vsize = 0; 871*7c478bd9Sstevel@tonic-gate for (i = 0; vals[i] != NULL; i++) 872*7c478bd9Sstevel@tonic-gate { 873*7c478bd9Sstevel@tonic-gate if (type == SM_LDAP_ATTR_DN || 874*7c478bd9Sstevel@tonic-gate type == SM_LDAP_ATTR_FILTER || 875*7c478bd9Sstevel@tonic-gate type == SM_LDAP_ATTR_URL) 876*7c478bd9Sstevel@tonic-gate { 877*7c478bd9Sstevel@tonic-gate /* add to recursion */ 878*7c478bd9Sstevel@tonic-gate if (sm_ldap_add_recurse(&recurse, 879*7c478bd9Sstevel@tonic-gate vals[i], 880*7c478bd9Sstevel@tonic-gate type, 881*7c478bd9Sstevel@tonic-gate rpool) == NULL) 882*7c478bd9Sstevel@tonic-gate { 883*7c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 884*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 885*7c478bd9Sstevel@tonic-gate return EX_OSERR; 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate continue; 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate vsize += strlen(vals[i]) + 1; 891*7c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsep != '\0') 892*7c478bd9Sstevel@tonic-gate vsize += strlen(attr) + 1; 893*7c478bd9Sstevel@tonic-gate } 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate /* 896*7c478bd9Sstevel@tonic-gate ** Create/Append to string any normal 897*7c478bd9Sstevel@tonic-gate ** attribute values. Otherwise, just free 898*7c478bd9Sstevel@tonic-gate ** memory and move on to the next 899*7c478bd9Sstevel@tonic-gate ** attribute in this entry. 900*7c478bd9Sstevel@tonic-gate */ 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate if (type == SM_LDAP_ATTR_NORMAL && vsize > 0) 903*7c478bd9Sstevel@tonic-gate { 904*7c478bd9Sstevel@tonic-gate char *pe; 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate /* Grow result string if needed */ 907*7c478bd9Sstevel@tonic-gate if ((*resultln + vsize) >= *resultsz) 908*7c478bd9Sstevel@tonic-gate { 909*7c478bd9Sstevel@tonic-gate while ((*resultln + vsize) >= *resultsz) 910*7c478bd9Sstevel@tonic-gate { 911*7c478bd9Sstevel@tonic-gate if (*resultsz == 0) 912*7c478bd9Sstevel@tonic-gate *resultsz = 1024; 913*7c478bd9Sstevel@tonic-gate else 914*7c478bd9Sstevel@tonic-gate *resultsz *= 2; 915*7c478bd9Sstevel@tonic-gate } 916*7c478bd9Sstevel@tonic-gate 917*7c478bd9Sstevel@tonic-gate vp_tmp = sm_rpool_malloc_x(rpool, *resultsz); 918*7c478bd9Sstevel@tonic-gate *vp_tmp = '\0'; 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate if (*result != NULL) 921*7c478bd9Sstevel@tonic-gate sm_strlcpy(vp_tmp, 922*7c478bd9Sstevel@tonic-gate *result, 923*7c478bd9Sstevel@tonic-gate *resultsz); 924*7c478bd9Sstevel@tonic-gate *result = vp_tmp; 925*7c478bd9Sstevel@tonic-gate } 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate p = *result + *resultln; 928*7c478bd9Sstevel@tonic-gate pe = *result + *resultsz; 929*7c478bd9Sstevel@tonic-gate 930*7c478bd9Sstevel@tonic-gate for (i = 0; vals[i] != NULL; i++) 931*7c478bd9Sstevel@tonic-gate { 932*7c478bd9Sstevel@tonic-gate if (*resultln > 0 && 933*7c478bd9Sstevel@tonic-gate p < pe) 934*7c478bd9Sstevel@tonic-gate *p++ = (char) delim; 935*7c478bd9Sstevel@tonic-gate 936*7c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsep != '\0') 937*7c478bd9Sstevel@tonic-gate { 938*7c478bd9Sstevel@tonic-gate p += sm_strlcpy(p, attr, 939*7c478bd9Sstevel@tonic-gate pe - p); 940*7c478bd9Sstevel@tonic-gate if (p < pe) 941*7c478bd9Sstevel@tonic-gate *p++ = lmap->ldap_attrsep; 942*7c478bd9Sstevel@tonic-gate } 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate p += sm_strlcpy(p, vals[i], 945*7c478bd9Sstevel@tonic-gate pe - p); 946*7c478bd9Sstevel@tonic-gate *resultln = p - (*result); 947*7c478bd9Sstevel@tonic-gate if (p >= pe) 948*7c478bd9Sstevel@tonic-gate { 949*7c478bd9Sstevel@tonic-gate /* Internal error: buffer too small for LDAP values */ 950*7c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 951*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 952*7c478bd9Sstevel@tonic-gate return EX_OSERR; 953*7c478bd9Sstevel@tonic-gate } 954*7c478bd9Sstevel@tonic-gate } 955*7c478bd9Sstevel@tonic-gate } 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate ldap_value_free(vals); 958*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 959*7c478bd9Sstevel@tonic-gate } 960*7c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(lmap->ldap_ld); 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate /* 963*7c478bd9Sstevel@tonic-gate ** We check save_errno != LDAP_DECODING_ERROR since 964*7c478bd9Sstevel@tonic-gate ** OpenLDAP 1.X has a very ugly *undocumented* 965*7c478bd9Sstevel@tonic-gate ** hack of returning this error code from 966*7c478bd9Sstevel@tonic-gate ** ldap_next_attribute() if the library freed the 967*7c478bd9Sstevel@tonic-gate ** ber attribute. See: 968*7c478bd9Sstevel@tonic-gate ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 969*7c478bd9Sstevel@tonic-gate */ 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate if (save_errno != LDAP_SUCCESS && 972*7c478bd9Sstevel@tonic-gate save_errno != LDAP_DECODING_ERROR) 973*7c478bd9Sstevel@tonic-gate { 974*7c478bd9Sstevel@tonic-gate /* Must be an error */ 975*7c478bd9Sstevel@tonic-gate save_errno += E_LDAPBASE; 976*7c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 977*7c478bd9Sstevel@tonic-gate errno = save_errno; 978*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 979*7c478bd9Sstevel@tonic-gate } 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate /* mark this DN as done */ 982*7c478bd9Sstevel@tonic-gate rl->lr_done = true; 983*7c478bd9Sstevel@tonic-gate if (rl->lr_ludp != NULL) 984*7c478bd9Sstevel@tonic-gate { 985*7c478bd9Sstevel@tonic-gate ldap_free_urldesc(rl->lr_ludp); 986*7c478bd9Sstevel@tonic-gate rl->lr_ludp = NULL; 987*7c478bd9Sstevel@tonic-gate } 988*7c478bd9Sstevel@tonic-gate if (rl->lr_attrs != NULL) 989*7c478bd9Sstevel@tonic-gate { 990*7c478bd9Sstevel@tonic-gate free(rl->lr_attrs); 991*7c478bd9Sstevel@tonic-gate rl->lr_attrs = NULL; 992*7c478bd9Sstevel@tonic-gate } 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate /* We don't want multiple values and we have one */ 995*7c478bd9Sstevel@tonic-gate if ((char) delim == '\0' && 996*7c478bd9Sstevel@tonic-gate !bitset(SM_LDAP_SINGLEMATCH, flags) && 997*7c478bd9Sstevel@tonic-gate *result != NULL) 998*7c478bd9Sstevel@tonic-gate break; 999*7c478bd9Sstevel@tonic-gate } 1000*7c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(lmap->ldap_ld); 1001*7c478bd9Sstevel@tonic-gate if (save_errno != LDAP_SUCCESS && 1002*7c478bd9Sstevel@tonic-gate save_errno != LDAP_DECODING_ERROR) 1003*7c478bd9Sstevel@tonic-gate { 1004*7c478bd9Sstevel@tonic-gate /* Must be an error */ 1005*7c478bd9Sstevel@tonic-gate save_errno += E_LDAPBASE; 1006*7c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 1007*7c478bd9Sstevel@tonic-gate errno = save_errno; 1008*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 1009*7c478bd9Sstevel@tonic-gate } 1010*7c478bd9Sstevel@tonic-gate ldap_msgfree(lmap->ldap_res); 1011*7c478bd9Sstevel@tonic-gate lmap->ldap_res = NULL; 1012*7c478bd9Sstevel@tonic-gate } 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate if (ret == 0) 1015*7c478bd9Sstevel@tonic-gate save_errno = ETIMEDOUT; 1016*7c478bd9Sstevel@tonic-gate else 1017*7c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(lmap->ldap_ld); 1018*7c478bd9Sstevel@tonic-gate if (save_errno != LDAP_SUCCESS) 1019*7c478bd9Sstevel@tonic-gate { 1020*7c478bd9Sstevel@tonic-gate statp = EX_TEMPFAIL; 1021*7c478bd9Sstevel@tonic-gate if (ret != 0) 1022*7c478bd9Sstevel@tonic-gate { 1023*7c478bd9Sstevel@tonic-gate switch (save_errno) 1024*7c478bd9Sstevel@tonic-gate { 1025*7c478bd9Sstevel@tonic-gate #ifdef LDAP_SERVER_DOWN 1026*7c478bd9Sstevel@tonic-gate case LDAP_SERVER_DOWN: 1027*7c478bd9Sstevel@tonic-gate #endif /* LDAP_SERVER_DOWN */ 1028*7c478bd9Sstevel@tonic-gate case LDAP_TIMEOUT: 1029*7c478bd9Sstevel@tonic-gate case LDAP_UNAVAILABLE: 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate /* 1032*7c478bd9Sstevel@tonic-gate ** server disappeared, 1033*7c478bd9Sstevel@tonic-gate ** try reopen on next search 1034*7c478bd9Sstevel@tonic-gate */ 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate statp = EX_RESTART; 1037*7c478bd9Sstevel@tonic-gate break; 1038*7c478bd9Sstevel@tonic-gate } 1039*7c478bd9Sstevel@tonic-gate save_errno += E_LDAPBASE; 1040*7c478bd9Sstevel@tonic-gate } 1041*7c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 1042*7c478bd9Sstevel@tonic-gate errno = save_errno; 1043*7c478bd9Sstevel@tonic-gate return statp; 1044*7c478bd9Sstevel@tonic-gate } 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate if (lmap->ldap_res != NULL) 1047*7c478bd9Sstevel@tonic-gate { 1048*7c478bd9Sstevel@tonic-gate ldap_msgfree(lmap->ldap_res); 1049*7c478bd9Sstevel@tonic-gate lmap->ldap_res = NULL; 1050*7c478bd9Sstevel@tonic-gate } 1051*7c478bd9Sstevel@tonic-gate 1052*7c478bd9Sstevel@tonic-gate if (toplevel) 1053*7c478bd9Sstevel@tonic-gate { 1054*7c478bd9Sstevel@tonic-gate int rlidx; 1055*7c478bd9Sstevel@tonic-gate 1056*7c478bd9Sstevel@tonic-gate /* 1057*7c478bd9Sstevel@tonic-gate ** Spin through the built-up recurse list at the top 1058*7c478bd9Sstevel@tonic-gate ** of the recursion. Since new items are added at the 1059*7c478bd9Sstevel@tonic-gate ** end of the shared list, we actually only ever get 1060*7c478bd9Sstevel@tonic-gate ** one level of recursion before things pop back to the 1061*7c478bd9Sstevel@tonic-gate ** top. Any items added to the list during that recursion 1062*7c478bd9Sstevel@tonic-gate ** will be expanded by the top level. 1063*7c478bd9Sstevel@tonic-gate */ 1064*7c478bd9Sstevel@tonic-gate 1065*7c478bd9Sstevel@tonic-gate for (rlidx = 0; recurse != NULL && rlidx < recurse->lr_cnt; rlidx++) 1066*7c478bd9Sstevel@tonic-gate { 1067*7c478bd9Sstevel@tonic-gate int newflags; 1068*7c478bd9Sstevel@tonic-gate int sid; 1069*7c478bd9Sstevel@tonic-gate int status; 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate rl = recurse->lr_data[rlidx]; 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate newflags = flags; 1074*7c478bd9Sstevel@tonic-gate if (rl->lr_done) 1075*7c478bd9Sstevel@tonic-gate { 1076*7c478bd9Sstevel@tonic-gate /* already expanded */ 1077*7c478bd9Sstevel@tonic-gate continue; 1078*7c478bd9Sstevel@tonic-gate } 1079*7c478bd9Sstevel@tonic-gate 1080*7c478bd9Sstevel@tonic-gate if (rl->lr_type == SM_LDAP_ATTR_DN) 1081*7c478bd9Sstevel@tonic-gate { 1082*7c478bd9Sstevel@tonic-gate /* do DN search */ 1083*7c478bd9Sstevel@tonic-gate sid = ldap_search(lmap->ldap_ld, 1084*7c478bd9Sstevel@tonic-gate rl->lr_search, 1085*7c478bd9Sstevel@tonic-gate lmap->ldap_scope, 1086*7c478bd9Sstevel@tonic-gate "(objectClass=*)", 1087*7c478bd9Sstevel@tonic-gate (lmap->ldap_attr[0] == NULL ? 1088*7c478bd9Sstevel@tonic-gate NULL : lmap->ldap_attr), 1089*7c478bd9Sstevel@tonic-gate lmap->ldap_attrsonly); 1090*7c478bd9Sstevel@tonic-gate } 1091*7c478bd9Sstevel@tonic-gate else if (rl->lr_type == SM_LDAP_ATTR_FILTER) 1092*7c478bd9Sstevel@tonic-gate { 1093*7c478bd9Sstevel@tonic-gate /* do new search */ 1094*7c478bd9Sstevel@tonic-gate sid = ldap_search(lmap->ldap_ld, 1095*7c478bd9Sstevel@tonic-gate lmap->ldap_base, 1096*7c478bd9Sstevel@tonic-gate lmap->ldap_scope, 1097*7c478bd9Sstevel@tonic-gate rl->lr_search, 1098*7c478bd9Sstevel@tonic-gate (lmap->ldap_attr[0] == NULL ? 1099*7c478bd9Sstevel@tonic-gate NULL : lmap->ldap_attr), 1100*7c478bd9Sstevel@tonic-gate lmap->ldap_attrsonly); 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate else if (rl->lr_type == SM_LDAP_ATTR_URL) 1103*7c478bd9Sstevel@tonic-gate { 1104*7c478bd9Sstevel@tonic-gate /* Parse URL */ 1105*7c478bd9Sstevel@tonic-gate sid = ldap_url_parse(rl->lr_search, 1106*7c478bd9Sstevel@tonic-gate &rl->lr_ludp); 1107*7c478bd9Sstevel@tonic-gate 1108*7c478bd9Sstevel@tonic-gate if (sid != 0) 1109*7c478bd9Sstevel@tonic-gate { 1110*7c478bd9Sstevel@tonic-gate errno = sid + E_LDAPURLBASE; 1111*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 1112*7c478bd9Sstevel@tonic-gate } 1113*7c478bd9Sstevel@tonic-gate 1114*7c478bd9Sstevel@tonic-gate /* We need to add objectClass */ 1115*7c478bd9Sstevel@tonic-gate if (rl->lr_ludp->lud_attrs != NULL) 1116*7c478bd9Sstevel@tonic-gate { 1117*7c478bd9Sstevel@tonic-gate int attrnum = 0; 1118*7c478bd9Sstevel@tonic-gate 1119*7c478bd9Sstevel@tonic-gate while (rl->lr_ludp->lud_attrs[attrnum] != NULL) 1120*7c478bd9Sstevel@tonic-gate { 1121*7c478bd9Sstevel@tonic-gate if (strcasecmp(rl->lr_ludp->lud_attrs[attrnum], 1122*7c478bd9Sstevel@tonic-gate "objectClass") == 0) 1123*7c478bd9Sstevel@tonic-gate { 1124*7c478bd9Sstevel@tonic-gate /* already requested */ 1125*7c478bd9Sstevel@tonic-gate attrnum = -1; 1126*7c478bd9Sstevel@tonic-gate break; 1127*7c478bd9Sstevel@tonic-gate } 1128*7c478bd9Sstevel@tonic-gate attrnum++; 1129*7c478bd9Sstevel@tonic-gate } 1130*7c478bd9Sstevel@tonic-gate 1131*7c478bd9Sstevel@tonic-gate if (attrnum >= 0) 1132*7c478bd9Sstevel@tonic-gate { 1133*7c478bd9Sstevel@tonic-gate int i; 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate rl->lr_attrs = (char **)malloc(sizeof(char *) * (attrnum + 2)); 1136*7c478bd9Sstevel@tonic-gate if (rl->lr_attrs == NULL) 1137*7c478bd9Sstevel@tonic-gate { 1138*7c478bd9Sstevel@tonic-gate save_errno = errno; 1139*7c478bd9Sstevel@tonic-gate ldap_free_urldesc(rl->lr_ludp); 1140*7c478bd9Sstevel@tonic-gate errno = save_errno; 1141*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 1142*7c478bd9Sstevel@tonic-gate } 1143*7c478bd9Sstevel@tonic-gate for (i = 0 ; i < attrnum; i++) 1144*7c478bd9Sstevel@tonic-gate { 1145*7c478bd9Sstevel@tonic-gate rl->lr_attrs[i] = rl->lr_ludp->lud_attrs[i]; 1146*7c478bd9Sstevel@tonic-gate } 1147*7c478bd9Sstevel@tonic-gate rl->lr_attrs[i++] = "objectClass"; 1148*7c478bd9Sstevel@tonic-gate rl->lr_attrs[i++] = NULL; 1149*7c478bd9Sstevel@tonic-gate } 1150*7c478bd9Sstevel@tonic-gate } 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate /* 1153*7c478bd9Sstevel@tonic-gate ** Use the existing connection 1154*7c478bd9Sstevel@tonic-gate ** for this search. It really 1155*7c478bd9Sstevel@tonic-gate ** should use lud_scheme://lud_host:lud_port/ 1156*7c478bd9Sstevel@tonic-gate ** instead but that would require 1157*7c478bd9Sstevel@tonic-gate ** opening a new connection. 1158*7c478bd9Sstevel@tonic-gate ** This should be fixed ASAP. 1159*7c478bd9Sstevel@tonic-gate */ 1160*7c478bd9Sstevel@tonic-gate 1161*7c478bd9Sstevel@tonic-gate sid = ldap_search(lmap->ldap_ld, 1162*7c478bd9Sstevel@tonic-gate rl->lr_ludp->lud_dn, 1163*7c478bd9Sstevel@tonic-gate rl->lr_ludp->lud_scope, 1164*7c478bd9Sstevel@tonic-gate rl->lr_ludp->lud_filter, 1165*7c478bd9Sstevel@tonic-gate rl->lr_attrs, 1166*7c478bd9Sstevel@tonic-gate lmap->ldap_attrsonly); 1167*7c478bd9Sstevel@tonic-gate 1168*7c478bd9Sstevel@tonic-gate /* Use the attributes specified by URL */ 1169*7c478bd9Sstevel@tonic-gate newflags |= SM_LDAP_USE_ALLATTR; 1170*7c478bd9Sstevel@tonic-gate } 1171*7c478bd9Sstevel@tonic-gate else 1172*7c478bd9Sstevel@tonic-gate { 1173*7c478bd9Sstevel@tonic-gate /* unknown or illegal attribute type */ 1174*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1175*7c478bd9Sstevel@tonic-gate return EX_SOFTWARE; 1176*7c478bd9Sstevel@tonic-gate } 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate /* Collect results */ 1179*7c478bd9Sstevel@tonic-gate if (sid == -1) 1180*7c478bd9Sstevel@tonic-gate { 1181*7c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(lmap->ldap_ld); 1182*7c478bd9Sstevel@tonic-gate statp = EX_TEMPFAIL; 1183*7c478bd9Sstevel@tonic-gate switch (save_errno) 1184*7c478bd9Sstevel@tonic-gate { 1185*7c478bd9Sstevel@tonic-gate #ifdef LDAP_SERVER_DOWN 1186*7c478bd9Sstevel@tonic-gate case LDAP_SERVER_DOWN: 1187*7c478bd9Sstevel@tonic-gate #endif /* LDAP_SERVER_DOWN */ 1188*7c478bd9Sstevel@tonic-gate case LDAP_TIMEOUT: 1189*7c478bd9Sstevel@tonic-gate case LDAP_UNAVAILABLE: 1190*7c478bd9Sstevel@tonic-gate 1191*7c478bd9Sstevel@tonic-gate /* 1192*7c478bd9Sstevel@tonic-gate ** server disappeared, 1193*7c478bd9Sstevel@tonic-gate ** try reopen on next search 1194*7c478bd9Sstevel@tonic-gate */ 1195*7c478bd9Sstevel@tonic-gate 1196*7c478bd9Sstevel@tonic-gate statp = EX_RESTART; 1197*7c478bd9Sstevel@tonic-gate break; 1198*7c478bd9Sstevel@tonic-gate } 1199*7c478bd9Sstevel@tonic-gate errno = save_errno + E_LDAPBASE; 1200*7c478bd9Sstevel@tonic-gate return statp; 1201*7c478bd9Sstevel@tonic-gate } 1202*7c478bd9Sstevel@tonic-gate 1203*7c478bd9Sstevel@tonic-gate status = sm_ldap_results(lmap, sid, newflags, delim, 1204*7c478bd9Sstevel@tonic-gate rpool, result, resultln, 1205*7c478bd9Sstevel@tonic-gate resultsz, recurse); 1206*7c478bd9Sstevel@tonic-gate save_errno = errno; 1207*7c478bd9Sstevel@tonic-gate if (status != EX_OK && status != EX_NOTFOUND) 1208*7c478bd9Sstevel@tonic-gate { 1209*7c478bd9Sstevel@tonic-gate errno = save_errno; 1210*7c478bd9Sstevel@tonic-gate return status; 1211*7c478bd9Sstevel@tonic-gate } 1212*7c478bd9Sstevel@tonic-gate 1213*7c478bd9Sstevel@tonic-gate /* Mark as done */ 1214*7c478bd9Sstevel@tonic-gate rl->lr_done = true; 1215*7c478bd9Sstevel@tonic-gate if (rl->lr_ludp != NULL) 1216*7c478bd9Sstevel@tonic-gate { 1217*7c478bd9Sstevel@tonic-gate ldap_free_urldesc(rl->lr_ludp); 1218*7c478bd9Sstevel@tonic-gate rl->lr_ludp = NULL; 1219*7c478bd9Sstevel@tonic-gate } 1220*7c478bd9Sstevel@tonic-gate if (rl->lr_attrs != NULL) 1221*7c478bd9Sstevel@tonic-gate { 1222*7c478bd9Sstevel@tonic-gate free(rl->lr_attrs); 1223*7c478bd9Sstevel@tonic-gate rl->lr_attrs = NULL; 1224*7c478bd9Sstevel@tonic-gate } 1225*7c478bd9Sstevel@tonic-gate 1226*7c478bd9Sstevel@tonic-gate /* Reset rlidx as new items may have been added */ 1227*7c478bd9Sstevel@tonic-gate rlidx = -1; 1228*7c478bd9Sstevel@tonic-gate } 1229*7c478bd9Sstevel@tonic-gate } 1230*7c478bd9Sstevel@tonic-gate return statp; 1231*7c478bd9Sstevel@tonic-gate } 1232*7c478bd9Sstevel@tonic-gate 1233*7c478bd9Sstevel@tonic-gate /* 1234*7c478bd9Sstevel@tonic-gate ** SM_LDAP_CLOSE -- close LDAP connection 1235*7c478bd9Sstevel@tonic-gate ** 1236*7c478bd9Sstevel@tonic-gate ** Parameters: 1237*7c478bd9Sstevel@tonic-gate ** lmap -- LDAP map information 1238*7c478bd9Sstevel@tonic-gate ** 1239*7c478bd9Sstevel@tonic-gate ** Returns: 1240*7c478bd9Sstevel@tonic-gate ** None. 1241*7c478bd9Sstevel@tonic-gate ** 1242*7c478bd9Sstevel@tonic-gate */ 1243*7c478bd9Sstevel@tonic-gate 1244*7c478bd9Sstevel@tonic-gate void 1245*7c478bd9Sstevel@tonic-gate sm_ldap_close(lmap) 1246*7c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 1247*7c478bd9Sstevel@tonic-gate { 1248*7c478bd9Sstevel@tonic-gate if (lmap->ldap_ld == NULL) 1249*7c478bd9Sstevel@tonic-gate return; 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate if (lmap->ldap_pid == getpid()) 1252*7c478bd9Sstevel@tonic-gate ldap_unbind(lmap->ldap_ld); 1253*7c478bd9Sstevel@tonic-gate lmap->ldap_ld = NULL; 1254*7c478bd9Sstevel@tonic-gate lmap->ldap_pid = 0; 1255*7c478bd9Sstevel@tonic-gate } 1256*7c478bd9Sstevel@tonic-gate 1257*7c478bd9Sstevel@tonic-gate /* 1258*7c478bd9Sstevel@tonic-gate ** SM_LDAP_SETOPTS -- set LDAP options 1259*7c478bd9Sstevel@tonic-gate ** 1260*7c478bd9Sstevel@tonic-gate ** Parameters: 1261*7c478bd9Sstevel@tonic-gate ** ld -- LDAP session handle 1262*7c478bd9Sstevel@tonic-gate ** lmap -- LDAP map information 1263*7c478bd9Sstevel@tonic-gate ** 1264*7c478bd9Sstevel@tonic-gate ** Returns: 1265*7c478bd9Sstevel@tonic-gate ** None. 1266*7c478bd9Sstevel@tonic-gate ** 1267*7c478bd9Sstevel@tonic-gate */ 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate void 1270*7c478bd9Sstevel@tonic-gate sm_ldap_setopts(ld, lmap) 1271*7c478bd9Sstevel@tonic-gate LDAP *ld; 1272*7c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 1273*7c478bd9Sstevel@tonic-gate { 1274*7c478bd9Sstevel@tonic-gate # if USE_LDAP_SET_OPTION 1275*7c478bd9Sstevel@tonic-gate if (lmap->ldap_version != 0) 1276*7c478bd9Sstevel@tonic-gate { 1277*7c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, 1278*7c478bd9Sstevel@tonic-gate &lmap->ldap_version); 1279*7c478bd9Sstevel@tonic-gate } 1280*7c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); 1281*7c478bd9Sstevel@tonic-gate if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) 1282*7c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); 1283*7c478bd9Sstevel@tonic-gate else 1284*7c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 1285*7c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); 1286*7c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); 1287*7c478bd9Sstevel@tonic-gate # ifdef LDAP_OPT_RESTART 1288*7c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); 1289*7c478bd9Sstevel@tonic-gate # endif /* LDAP_OPT_RESTART */ 1290*7c478bd9Sstevel@tonic-gate # else /* USE_LDAP_SET_OPTION */ 1291*7c478bd9Sstevel@tonic-gate /* From here on in we can use ldap internal timelimits */ 1292*7c478bd9Sstevel@tonic-gate ld->ld_deref = lmap->ldap_deref; 1293*7c478bd9Sstevel@tonic-gate ld->ld_options = lmap->ldap_options; 1294*7c478bd9Sstevel@tonic-gate ld->ld_sizelimit = lmap->ldap_sizelimit; 1295*7c478bd9Sstevel@tonic-gate ld->ld_timelimit = lmap->ldap_timelimit; 1296*7c478bd9Sstevel@tonic-gate # endif /* USE_LDAP_SET_OPTION */ 1297*7c478bd9Sstevel@tonic-gate } 1298*7c478bd9Sstevel@tonic-gate 1299*7c478bd9Sstevel@tonic-gate /* 1300*7c478bd9Sstevel@tonic-gate ** SM_LDAP_GETERRNO -- get ldap errno value 1301*7c478bd9Sstevel@tonic-gate ** 1302*7c478bd9Sstevel@tonic-gate ** Parameters: 1303*7c478bd9Sstevel@tonic-gate ** ld -- LDAP session handle 1304*7c478bd9Sstevel@tonic-gate ** 1305*7c478bd9Sstevel@tonic-gate ** Returns: 1306*7c478bd9Sstevel@tonic-gate ** LDAP errno. 1307*7c478bd9Sstevel@tonic-gate ** 1308*7c478bd9Sstevel@tonic-gate */ 1309*7c478bd9Sstevel@tonic-gate 1310*7c478bd9Sstevel@tonic-gate int 1311*7c478bd9Sstevel@tonic-gate sm_ldap_geterrno(ld) 1312*7c478bd9Sstevel@tonic-gate LDAP *ld; 1313*7c478bd9Sstevel@tonic-gate { 1314*7c478bd9Sstevel@tonic-gate int err = LDAP_SUCCESS; 1315*7c478bd9Sstevel@tonic-gate 1316*7c478bd9Sstevel@tonic-gate # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 1317*7c478bd9Sstevel@tonic-gate (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); 1318*7c478bd9Sstevel@tonic-gate # else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 1319*7c478bd9Sstevel@tonic-gate # ifdef LDAP_OPT_SIZELIMIT 1320*7c478bd9Sstevel@tonic-gate err = ldap_get_lderrno(ld, NULL, NULL); 1321*7c478bd9Sstevel@tonic-gate # else /* LDAP_OPT_SIZELIMIT */ 1322*7c478bd9Sstevel@tonic-gate err = ld->ld_errno; 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate /* 1325*7c478bd9Sstevel@tonic-gate ** Reset value to prevent lingering LDAP_DECODING_ERROR due to 1326*7c478bd9Sstevel@tonic-gate ** OpenLDAP 1.X's hack (see above) 1327*7c478bd9Sstevel@tonic-gate */ 1328*7c478bd9Sstevel@tonic-gate 1329*7c478bd9Sstevel@tonic-gate ld->ld_errno = LDAP_SUCCESS; 1330*7c478bd9Sstevel@tonic-gate # endif /* LDAP_OPT_SIZELIMIT */ 1331*7c478bd9Sstevel@tonic-gate # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 1332*7c478bd9Sstevel@tonic-gate return err; 1333*7c478bd9Sstevel@tonic-gate } 1334*7c478bd9Sstevel@tonic-gate # endif /* LDAPMAP */ 1335