17c478bd9Sstevel@tonic-gate /* 2*e9af4bc0SJohn Beck * Copyright (c) 2001-2009 Sendmail, Inc. and its suppliers. 37c478bd9Sstevel@tonic-gate * All rights reserved. 47c478bd9Sstevel@tonic-gate * 57c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 67c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 77c478bd9Sstevel@tonic-gate * the sendmail distribution. 87c478bd9Sstevel@tonic-gate */ 97c478bd9Sstevel@tonic-gate 10058561cbSjbeck /* some "deprecated" calls are used, e.g., ldap_get_values() */ 11058561cbSjbeck #define LDAP_DEPRECATED 1 12058561cbSjbeck 137c478bd9Sstevel@tonic-gate #include <sm/gen.h> 14*e9af4bc0SJohn Beck SM_RCSID("@(#)$Id: ldap.c,v 1.83 2009/06/19 22:02:26 guenther Exp $") 157c478bd9Sstevel@tonic-gate 167c478bd9Sstevel@tonic-gate #if LDAPMAP 177c478bd9Sstevel@tonic-gate # include <sys/types.h> 187c478bd9Sstevel@tonic-gate # include <errno.h> 197c478bd9Sstevel@tonic-gate # include <setjmp.h> 207c478bd9Sstevel@tonic-gate # include <stdlib.h> 217c478bd9Sstevel@tonic-gate # include <unistd.h> 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate # include <sm/bitops.h> 247c478bd9Sstevel@tonic-gate # include <sm/clock.h> 257c478bd9Sstevel@tonic-gate # include <sm/conf.h> 267c478bd9Sstevel@tonic-gate # include <sm/debug.h> 277c478bd9Sstevel@tonic-gate # include <sm/errstring.h> 287c478bd9Sstevel@tonic-gate # include <sm/ldap.h> 297c478bd9Sstevel@tonic-gate # include <sm/string.h> 307c478bd9Sstevel@tonic-gate # ifdef EX_OK 317c478bd9Sstevel@tonic-gate # undef EX_OK /* for SVr4.2 SMP */ 327c478bd9Sstevel@tonic-gate # endif /* EX_OK */ 337c478bd9Sstevel@tonic-gate # include <sm/sysexits.h> 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap", 367c478bd9Sstevel@tonic-gate "@(#)$Debug: sm_trace_ldap - trace LDAP operations $"); 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate static void ldaptimeout __P((int)); 397c478bd9Sstevel@tonic-gate static bool sm_ldap_has_objectclass __P((SM_LDAP_STRUCT *, LDAPMessage *, char *)); 407c478bd9Sstevel@tonic-gate static SM_LDAP_RECURSE_ENTRY *sm_ldap_add_recurse __P((SM_LDAP_RECURSE_LIST **, char *, int, SM_RPOOL_T *)); 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate /* 437c478bd9Sstevel@tonic-gate ** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT 447c478bd9Sstevel@tonic-gate ** 457c478bd9Sstevel@tonic-gate ** Parameters: 467c478bd9Sstevel@tonic-gate ** lmap -- pointer to SM_LDAP_STRUCT to clear 477c478bd9Sstevel@tonic-gate ** 487c478bd9Sstevel@tonic-gate ** Returns: 497c478bd9Sstevel@tonic-gate ** None. 507c478bd9Sstevel@tonic-gate ** 517c478bd9Sstevel@tonic-gate */ 527c478bd9Sstevel@tonic-gate 53445f2479Sjbeck #if _FFR_LDAP_VERSION 54445f2479Sjbeck # if defined(LDAP_VERSION_MAX) && _FFR_LDAP_VERSION > LDAP_VERSION_MAX 55445f2479Sjbeck ERROR FFR_LDAP_VERSION > _LDAP_VERSION_MAX 56445f2479Sjbeck # endif /* defined(LDAP_VERSION_MAX) && _FFR_LDAP_VERSION > LDAP_VERSION_MAX */ 57445f2479Sjbeck # if defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN 58445f2479Sjbeck ERROR FFR_LDAP_VERSION < _LDAP_VERSION_MIN 59445f2479Sjbeck # endif /* defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN */ 60445f2479Sjbeck # define SM_LDAP_VERSION_DEFAULT _FFR_LDAP_VERSION 61445f2479Sjbeck #else /* _FFR_LDAP_VERSION */ 62445f2479Sjbeck # define SM_LDAP_VERSION_DEFAULT 0 63445f2479Sjbeck #endif /* _FFR_LDAP_VERSION */ 64445f2479Sjbeck 657c478bd9Sstevel@tonic-gate void 667c478bd9Sstevel@tonic-gate sm_ldap_clear(lmap) 677c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 687c478bd9Sstevel@tonic-gate { 697c478bd9Sstevel@tonic-gate if (lmap == NULL) 707c478bd9Sstevel@tonic-gate return; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate lmap->ldap_host = NULL; 737c478bd9Sstevel@tonic-gate lmap->ldap_port = LDAP_PORT; 747c478bd9Sstevel@tonic-gate lmap->ldap_uri = NULL; 75445f2479Sjbeck lmap->ldap_version = SM_LDAP_VERSION_DEFAULT; 767c478bd9Sstevel@tonic-gate lmap->ldap_deref = LDAP_DEREF_NEVER; 777c478bd9Sstevel@tonic-gate lmap->ldap_timelimit = LDAP_NO_LIMIT; 787c478bd9Sstevel@tonic-gate lmap->ldap_sizelimit = LDAP_NO_LIMIT; 797c478bd9Sstevel@tonic-gate # ifdef LDAP_REFERRALS 807c478bd9Sstevel@tonic-gate lmap->ldap_options = LDAP_OPT_REFERRALS; 817c478bd9Sstevel@tonic-gate # else /* LDAP_REFERRALS */ 827c478bd9Sstevel@tonic-gate lmap->ldap_options = 0; 837c478bd9Sstevel@tonic-gate # endif /* LDAP_REFERRALS */ 847c478bd9Sstevel@tonic-gate lmap->ldap_attrsep = '\0'; 857c478bd9Sstevel@tonic-gate lmap->ldap_binddn = NULL; 867c478bd9Sstevel@tonic-gate lmap->ldap_secret = NULL; 877c478bd9Sstevel@tonic-gate lmap->ldap_method = LDAP_AUTH_SIMPLE; 887c478bd9Sstevel@tonic-gate lmap->ldap_base = NULL; 897c478bd9Sstevel@tonic-gate lmap->ldap_scope = LDAP_SCOPE_SUBTREE; 907c478bd9Sstevel@tonic-gate lmap->ldap_attrsonly = LDAPMAP_FALSE; 917c478bd9Sstevel@tonic-gate lmap->ldap_timeout.tv_sec = 0; 927c478bd9Sstevel@tonic-gate lmap->ldap_timeout.tv_usec = 0; 937c478bd9Sstevel@tonic-gate lmap->ldap_ld = NULL; 947c478bd9Sstevel@tonic-gate lmap->ldap_filter = NULL; 957c478bd9Sstevel@tonic-gate lmap->ldap_attr[0] = NULL; 967c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE; 977c478bd9Sstevel@tonic-gate lmap->ldap_attr_needobjclass[0] = NULL; 987c478bd9Sstevel@tonic-gate lmap->ldap_res = NULL; 997c478bd9Sstevel@tonic-gate lmap->ldap_next = NULL; 1007c478bd9Sstevel@tonic-gate lmap->ldap_pid = 0; 101058561cbSjbeck lmap->ldap_multi_args = false; 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* 1057c478bd9Sstevel@tonic-gate ** SM_LDAP_START -- actually connect to an LDAP server 1067c478bd9Sstevel@tonic-gate ** 1077c478bd9Sstevel@tonic-gate ** Parameters: 1087c478bd9Sstevel@tonic-gate ** name -- name of map for debug output. 1097c478bd9Sstevel@tonic-gate ** lmap -- the LDAP map being opened. 1107c478bd9Sstevel@tonic-gate ** 1117c478bd9Sstevel@tonic-gate ** Returns: 1127c478bd9Sstevel@tonic-gate ** true if connection is successful, false otherwise. 1137c478bd9Sstevel@tonic-gate ** 1147c478bd9Sstevel@tonic-gate ** Side Effects: 1157c478bd9Sstevel@tonic-gate ** Populates lmap->ldap_ld. 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate static jmp_buf LDAPTimeout; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate #define SM_LDAP_SETTIMEOUT(to) \ 1217c478bd9Sstevel@tonic-gate do \ 1227c478bd9Sstevel@tonic-gate { \ 1237c478bd9Sstevel@tonic-gate if (to != 0) \ 1247c478bd9Sstevel@tonic-gate { \ 1257c478bd9Sstevel@tonic-gate if (setjmp(LDAPTimeout) != 0) \ 1267c478bd9Sstevel@tonic-gate { \ 1277c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; \ 1287c478bd9Sstevel@tonic-gate return false; \ 1297c478bd9Sstevel@tonic-gate } \ 1307c478bd9Sstevel@tonic-gate ev = sm_setevent(to, ldaptimeout, 0); \ 1317c478bd9Sstevel@tonic-gate } \ 1327c478bd9Sstevel@tonic-gate } while (0) 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate #define SM_LDAP_CLEARTIMEOUT() \ 1357c478bd9Sstevel@tonic-gate do \ 1367c478bd9Sstevel@tonic-gate { \ 1377c478bd9Sstevel@tonic-gate if (ev != NULL) \ 1387c478bd9Sstevel@tonic-gate sm_clrevent(ev); \ 1397c478bd9Sstevel@tonic-gate } while (0) 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate bool 1427c478bd9Sstevel@tonic-gate sm_ldap_start(name, lmap) 1437c478bd9Sstevel@tonic-gate char *name; 1447c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 1457c478bd9Sstevel@tonic-gate { 1467c478bd9Sstevel@tonic-gate int bind_result; 1477c478bd9Sstevel@tonic-gate int save_errno = 0; 1487c478bd9Sstevel@tonic-gate char *id; 1497c478bd9Sstevel@tonic-gate SM_EVENT *ev = NULL; 1507c478bd9Sstevel@tonic-gate LDAP *ld = NULL; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate if (sm_debug_active(&SmLDAPTrace, 2)) 1537c478bd9Sstevel@tonic-gate sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name); 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate if (lmap->ldap_host != NULL) 1567c478bd9Sstevel@tonic-gate id = lmap->ldap_host; 1577c478bd9Sstevel@tonic-gate else if (lmap->ldap_uri != NULL) 1587c478bd9Sstevel@tonic-gate id = lmap->ldap_uri; 1597c478bd9Sstevel@tonic-gate else 1607c478bd9Sstevel@tonic-gate id = "localhost"; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate if (sm_debug_active(&SmLDAPTrace, 9)) 1637c478bd9Sstevel@tonic-gate { 1647c478bd9Sstevel@tonic-gate /* Don't print a port number for LDAP URIs */ 1657c478bd9Sstevel@tonic-gate if (lmap->ldap_uri != NULL) 1667c478bd9Sstevel@tonic-gate sm_dprintf("ldapmap_start(%s)\n", id); 1677c478bd9Sstevel@tonic-gate else 1687c478bd9Sstevel@tonic-gate sm_dprintf("ldapmap_start(%s, %d)\n", id, 1697c478bd9Sstevel@tonic-gate lmap->ldap_port); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate if (lmap->ldap_uri != NULL) 1737c478bd9Sstevel@tonic-gate { 1747c478bd9Sstevel@tonic-gate #if SM_CONF_LDAP_INITIALIZE 1757c478bd9Sstevel@tonic-gate /* LDAP server supports URIs so use them directly */ 1767c478bd9Sstevel@tonic-gate save_errno = ldap_initialize(&ld, lmap->ldap_uri); 1777c478bd9Sstevel@tonic-gate #else /* SM_CONF_LDAP_INITIALIZE */ 1787c478bd9Sstevel@tonic-gate int err; 1797c478bd9Sstevel@tonic-gate LDAPURLDesc *ludp = NULL; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate /* Blast apart URL and use the ldap_init/ldap_open below */ 1827c478bd9Sstevel@tonic-gate err = ldap_url_parse(lmap->ldap_uri, &ludp); 1837c478bd9Sstevel@tonic-gate if (err != 0) 1847c478bd9Sstevel@tonic-gate { 1857c478bd9Sstevel@tonic-gate errno = err + E_LDAPURLBASE; 1867c478bd9Sstevel@tonic-gate return false; 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate lmap->ldap_host = sm_strdup_x(ludp->lud_host); 1897c478bd9Sstevel@tonic-gate if (lmap->ldap_host == NULL) 1907c478bd9Sstevel@tonic-gate { 1917c478bd9Sstevel@tonic-gate save_errno = errno; 1927c478bd9Sstevel@tonic-gate ldap_free_urldesc(ludp); 1937c478bd9Sstevel@tonic-gate errno = save_errno; 1947c478bd9Sstevel@tonic-gate return false; 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate lmap->ldap_port = ludp->lud_port; 1977c478bd9Sstevel@tonic-gate ldap_free_urldesc(ludp); 1987c478bd9Sstevel@tonic-gate #endif /* SM_CONF_LDAP_INITIALIZE */ 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate if (ld == NULL) 2027c478bd9Sstevel@tonic-gate { 2037c478bd9Sstevel@tonic-gate # if USE_LDAP_INIT 2047c478bd9Sstevel@tonic-gate ld = ldap_init(lmap->ldap_host, lmap->ldap_port); 2057c478bd9Sstevel@tonic-gate save_errno = errno; 2067c478bd9Sstevel@tonic-gate # else /* USE_LDAP_INIT */ 2077c478bd9Sstevel@tonic-gate /* 2087c478bd9Sstevel@tonic-gate ** If using ldap_open(), the actual connection to the server 2097c478bd9Sstevel@tonic-gate ** happens now so we need the timeout here. For ldap_init(), 2107c478bd9Sstevel@tonic-gate ** the connection happens at bind time. 2117c478bd9Sstevel@tonic-gate */ 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); 2147c478bd9Sstevel@tonic-gate ld = ldap_open(lmap->ldap_host, lmap->ldap_port); 2157c478bd9Sstevel@tonic-gate save_errno = errno; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate /* clear the event if it has not sprung */ 2187c478bd9Sstevel@tonic-gate SM_LDAP_CLEARTIMEOUT(); 2197c478bd9Sstevel@tonic-gate # endif /* USE_LDAP_INIT */ 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate errno = save_errno; 2237c478bd9Sstevel@tonic-gate if (ld == NULL) 2247c478bd9Sstevel@tonic-gate return false; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate sm_ldap_setopts(ld, lmap); 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate # if USE_LDAP_INIT 2297c478bd9Sstevel@tonic-gate /* 2307c478bd9Sstevel@tonic-gate ** If using ldap_init(), the actual connection to the server 2317c478bd9Sstevel@tonic-gate ** happens at ldap_bind_s() so we need the timeout here. 2327c478bd9Sstevel@tonic-gate */ 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); 2357c478bd9Sstevel@tonic-gate # endif /* USE_LDAP_INIT */ 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate # ifdef LDAP_AUTH_KRBV4 2387c478bd9Sstevel@tonic-gate if (lmap->ldap_method == LDAP_AUTH_KRBV4 && 2397c478bd9Sstevel@tonic-gate lmap->ldap_secret != NULL) 2407c478bd9Sstevel@tonic-gate { 2417c478bd9Sstevel@tonic-gate /* 2427c478bd9Sstevel@tonic-gate ** Need to put ticket in environment here instead of 2437c478bd9Sstevel@tonic-gate ** during parseargs as there may be different tickets 2447c478bd9Sstevel@tonic-gate ** for different LDAP connections. 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate (void) putenv(lmap->ldap_secret); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate # endif /* LDAP_AUTH_KRBV4 */ 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate bind_result = ldap_bind_s(ld, lmap->ldap_binddn, 2527c478bd9Sstevel@tonic-gate lmap->ldap_secret, lmap->ldap_method); 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate # if USE_LDAP_INIT 2557c478bd9Sstevel@tonic-gate /* clear the event if it has not sprung */ 2567c478bd9Sstevel@tonic-gate SM_LDAP_CLEARTIMEOUT(); 2577c478bd9Sstevel@tonic-gate # endif /* USE_LDAP_INIT */ 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate if (bind_result != LDAP_SUCCESS) 2607c478bd9Sstevel@tonic-gate { 2617c478bd9Sstevel@tonic-gate errno = bind_result + E_LDAPBASE; 2627c478bd9Sstevel@tonic-gate return false; 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate /* Save PID to make sure only this PID closes the LDAP connection */ 2667c478bd9Sstevel@tonic-gate lmap->ldap_pid = getpid(); 2677c478bd9Sstevel@tonic-gate lmap->ldap_ld = ld; 2687c478bd9Sstevel@tonic-gate return true; 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2727c478bd9Sstevel@tonic-gate static void 2737c478bd9Sstevel@tonic-gate ldaptimeout(unused) 2747c478bd9Sstevel@tonic-gate int unused; 2757c478bd9Sstevel@tonic-gate { 2767c478bd9Sstevel@tonic-gate /* 2777c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 2787c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 2797c478bd9Sstevel@tonic-gate ** DOING. 2807c478bd9Sstevel@tonic-gate */ 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 2837c478bd9Sstevel@tonic-gate longjmp(LDAPTimeout, 1); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* 287058561cbSjbeck ** SM_LDAP_SEARCH_M -- initiate multi-key LDAP search 2887c478bd9Sstevel@tonic-gate ** 2897c478bd9Sstevel@tonic-gate ** Initiate an LDAP search, return the msgid. 2907c478bd9Sstevel@tonic-gate ** The calling function must collect the results. 2917c478bd9Sstevel@tonic-gate ** 2927c478bd9Sstevel@tonic-gate ** Parameters: 2937c478bd9Sstevel@tonic-gate ** lmap -- LDAP map information 294058561cbSjbeck ** argv -- key vector of substitutions in LDAP filter 295058561cbSjbeck ** NOTE: argv must have SM_LDAP_ARGS elements to prevent 296058561cbSjbeck ** out of bound array references 2977c478bd9Sstevel@tonic-gate ** 2987c478bd9Sstevel@tonic-gate ** Returns: 299058561cbSjbeck ** <0 on failure (SM_LDAP_ERR*), msgid on success 3007c478bd9Sstevel@tonic-gate ** 3017c478bd9Sstevel@tonic-gate */ 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate int 304058561cbSjbeck sm_ldap_search_m(lmap, argv) 3057c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 306058561cbSjbeck char **argv; 3077c478bd9Sstevel@tonic-gate { 3087c478bd9Sstevel@tonic-gate int msgid; 3097c478bd9Sstevel@tonic-gate char *fp, *p, *q; 3107c478bd9Sstevel@tonic-gate char filter[LDAPMAP_MAX_FILTER + 1]; 3117c478bd9Sstevel@tonic-gate 312058561cbSjbeck SM_REQUIRE(lmap != NULL); 313058561cbSjbeck SM_REQUIRE(argv != NULL); 314058561cbSjbeck SM_REQUIRE(argv[0] != NULL); 315058561cbSjbeck 3167c478bd9Sstevel@tonic-gate memset(filter, '\0', sizeof filter); 3177c478bd9Sstevel@tonic-gate fp = filter; 3187c478bd9Sstevel@tonic-gate p = lmap->ldap_filter; 3197c478bd9Sstevel@tonic-gate while ((q = strchr(p, '%')) != NULL) 3207c478bd9Sstevel@tonic-gate { 321058561cbSjbeck char *key; 322058561cbSjbeck 323058561cbSjbeck if (lmap->ldap_multi_args) 324058561cbSjbeck { 325058561cbSjbeck #if SM_LDAP_ARGS < 10 326058561cbSjbeck # ERROR _SM_LDAP_ARGS must be 10 327058561cbSjbeck #endif /* SM_LDAP_ARGS < 10 */ 328058561cbSjbeck if (q[1] == 's') 329058561cbSjbeck key = argv[0]; 330058561cbSjbeck else if (q[1] >= '0' && q[1] <= '9') 331058561cbSjbeck { 332058561cbSjbeck key = argv[q[1] - '0']; 333058561cbSjbeck if (key == NULL) 334058561cbSjbeck { 335058561cbSjbeck # if SM_LDAP_ERROR_ON_MISSING_ARGS 336058561cbSjbeck return SM_LDAP_ERR_ARG_MISS; 337058561cbSjbeck # else /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 338058561cbSjbeck key = ""; 339058561cbSjbeck # endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 340058561cbSjbeck } 341058561cbSjbeck } 342058561cbSjbeck else 343058561cbSjbeck key = NULL; 344058561cbSjbeck } 345058561cbSjbeck else 346058561cbSjbeck key = argv[0]; 347058561cbSjbeck 3487c478bd9Sstevel@tonic-gate if (q[1] == 's') 3497c478bd9Sstevel@tonic-gate { 3507c478bd9Sstevel@tonic-gate (void) sm_snprintf(fp, SPACELEFT(filter, fp), 3517c478bd9Sstevel@tonic-gate "%.*s%s", (int) (q - p), p, key); 3527c478bd9Sstevel@tonic-gate fp += strlen(fp); 3537c478bd9Sstevel@tonic-gate p = q + 2; 3547c478bd9Sstevel@tonic-gate } 355058561cbSjbeck else if (q[1] == '0' || 356058561cbSjbeck (lmap->ldap_multi_args && q[1] >= '0' && q[1] <= '9')) 3577c478bd9Sstevel@tonic-gate { 3587c478bd9Sstevel@tonic-gate char *k = key; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate (void) sm_snprintf(fp, SPACELEFT(filter, fp), 3617c478bd9Sstevel@tonic-gate "%.*s", (int) (q - p), p); 3627c478bd9Sstevel@tonic-gate fp += strlen(fp); 3637c478bd9Sstevel@tonic-gate p = q + 2; 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate /* Properly escape LDAP special characters */ 3667c478bd9Sstevel@tonic-gate while (SPACELEFT(filter, fp) > 0 && 3677c478bd9Sstevel@tonic-gate *k != '\0') 3687c478bd9Sstevel@tonic-gate { 3697c478bd9Sstevel@tonic-gate if (*k == '*' || *k == '(' || 3707c478bd9Sstevel@tonic-gate *k == ')' || *k == '\\') 3717c478bd9Sstevel@tonic-gate { 3727c478bd9Sstevel@tonic-gate (void) sm_strlcat(fp, 3737c478bd9Sstevel@tonic-gate (*k == '*' ? "\\2A" : 3747c478bd9Sstevel@tonic-gate (*k == '(' ? "\\28" : 3757c478bd9Sstevel@tonic-gate (*k == ')' ? "\\29" : 3767c478bd9Sstevel@tonic-gate (*k == '\\' ? "\\5C" : 3777c478bd9Sstevel@tonic-gate "\00")))), 3787c478bd9Sstevel@tonic-gate SPACELEFT(filter, fp)); 3797c478bd9Sstevel@tonic-gate fp += strlen(fp); 3807c478bd9Sstevel@tonic-gate k++; 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate else 3837c478bd9Sstevel@tonic-gate *fp++ = *k++; 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate else 3877c478bd9Sstevel@tonic-gate { 3887c478bd9Sstevel@tonic-gate (void) sm_snprintf(fp, SPACELEFT(filter, fp), 3897c478bd9Sstevel@tonic-gate "%.*s", (int) (q - p + 1), p); 3907c478bd9Sstevel@tonic-gate p = q + (q[1] == '%' ? 2 : 1); 3917c478bd9Sstevel@tonic-gate fp += strlen(fp); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate (void) sm_strlcpy(fp, p, SPACELEFT(filter, fp)); 3957c478bd9Sstevel@tonic-gate if (sm_debug_active(&SmLDAPTrace, 20)) 3967c478bd9Sstevel@tonic-gate sm_dprintf("ldap search filter=%s\n", filter); 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate lmap->ldap_res = NULL; 3997c478bd9Sstevel@tonic-gate msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, 4007c478bd9Sstevel@tonic-gate lmap->ldap_scope, filter, 4017c478bd9Sstevel@tonic-gate (lmap->ldap_attr[0] == NULL ? NULL : 4027c478bd9Sstevel@tonic-gate lmap->ldap_attr), 4037c478bd9Sstevel@tonic-gate lmap->ldap_attrsonly); 4047c478bd9Sstevel@tonic-gate return msgid; 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate /* 408058561cbSjbeck ** SM_LDAP_SEARCH -- initiate LDAP search 409058561cbSjbeck ** 410058561cbSjbeck ** Initiate an LDAP search, return the msgid. 411058561cbSjbeck ** The calling function must collect the results. 412058561cbSjbeck ** Note this is just a wrapper into sm_ldap_search_m() 413058561cbSjbeck ** 414058561cbSjbeck ** Parameters: 415058561cbSjbeck ** lmap -- LDAP map information 416058561cbSjbeck ** key -- key to substitute in LDAP filter 417058561cbSjbeck ** 418058561cbSjbeck ** Returns: 419058561cbSjbeck ** <0 on failure, msgid on success 420058561cbSjbeck ** 421058561cbSjbeck */ 422058561cbSjbeck 423058561cbSjbeck int 424058561cbSjbeck sm_ldap_search(lmap, key) 425058561cbSjbeck SM_LDAP_STRUCT *lmap; 426058561cbSjbeck char *key; 427058561cbSjbeck { 428058561cbSjbeck char *argv[SM_LDAP_ARGS]; 429058561cbSjbeck 430058561cbSjbeck memset(argv, '\0', sizeof argv); 431058561cbSjbeck argv[0] = key; 432058561cbSjbeck return sm_ldap_search_m(lmap, argv); 433058561cbSjbeck } 434058561cbSjbeck 435058561cbSjbeck /* 4367c478bd9Sstevel@tonic-gate ** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a 4377c478bd9Sstevel@tonic-gate ** particular objectClass 4387c478bd9Sstevel@tonic-gate ** 4397c478bd9Sstevel@tonic-gate ** Parameters: 4407c478bd9Sstevel@tonic-gate ** lmap -- pointer to SM_LDAP_STRUCT in use 4417c478bd9Sstevel@tonic-gate ** entry -- current LDAP entry struct 4427c478bd9Sstevel@tonic-gate ** ocvalue -- particular objectclass in question. 4437c478bd9Sstevel@tonic-gate ** may be of form (fee|foo|fum) meaning 4447c478bd9Sstevel@tonic-gate ** any entry can be part of either fee, 4457c478bd9Sstevel@tonic-gate ** foo or fum objectclass 4467c478bd9Sstevel@tonic-gate ** 4477c478bd9Sstevel@tonic-gate ** Returns: 4487c478bd9Sstevel@tonic-gate ** true if item has that objectClass 4497c478bd9Sstevel@tonic-gate */ 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate static bool 4527c478bd9Sstevel@tonic-gate sm_ldap_has_objectclass(lmap, entry, ocvalue) 4537c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 4547c478bd9Sstevel@tonic-gate LDAPMessage *entry; 4557c478bd9Sstevel@tonic-gate char *ocvalue; 4567c478bd9Sstevel@tonic-gate { 4577c478bd9Sstevel@tonic-gate char **vals = NULL; 4587c478bd9Sstevel@tonic-gate int i; 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate if (ocvalue == NULL) 4617c478bd9Sstevel@tonic-gate return false; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass"); 4647c478bd9Sstevel@tonic-gate if (vals == NULL) 4657c478bd9Sstevel@tonic-gate return false; 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate for (i = 0; vals[i] != NULL; i++) 4687c478bd9Sstevel@tonic-gate { 4697c478bd9Sstevel@tonic-gate char *p; 4707c478bd9Sstevel@tonic-gate char *q; 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate p = q = ocvalue; 4737c478bd9Sstevel@tonic-gate while (*p != '\0') 4747c478bd9Sstevel@tonic-gate { 4757c478bd9Sstevel@tonic-gate while (*p != '\0' && *p != '|') 4767c478bd9Sstevel@tonic-gate p++; 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate if ((p - q) == strlen(vals[i]) && 4797c478bd9Sstevel@tonic-gate sm_strncasecmp(vals[i], q, p - q) == 0) 4807c478bd9Sstevel@tonic-gate { 4817c478bd9Sstevel@tonic-gate ldap_value_free(vals); 4827c478bd9Sstevel@tonic-gate return true; 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate while (*p == '|') 4867c478bd9Sstevel@tonic-gate p++; 4877c478bd9Sstevel@tonic-gate q = p; 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate ldap_value_free(vals); 4927c478bd9Sstevel@tonic-gate return false; 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate /* 4967c478bd9Sstevel@tonic-gate ** SM_LDAP_RESULTS -- return results from an LDAP lookup in result 4977c478bd9Sstevel@tonic-gate ** 4987c478bd9Sstevel@tonic-gate ** Parameters: 4997c478bd9Sstevel@tonic-gate ** lmap -- pointer to SM_LDAP_STRUCT in use 5007c478bd9Sstevel@tonic-gate ** msgid -- msgid returned by sm_ldap_search() 5017c478bd9Sstevel@tonic-gate ** flags -- flags for the lookup 5027c478bd9Sstevel@tonic-gate ** delim -- delimiter for result concatenation 5037c478bd9Sstevel@tonic-gate ** rpool -- memory pool for storage 5047c478bd9Sstevel@tonic-gate ** result -- return string 5057c478bd9Sstevel@tonic-gate ** recurse -- recursion list 5067c478bd9Sstevel@tonic-gate ** 5077c478bd9Sstevel@tonic-gate ** Returns: 5087c478bd9Sstevel@tonic-gate ** status (sysexit) 5097c478bd9Sstevel@tonic-gate */ 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate # define SM_LDAP_ERROR_CLEANUP() \ 5127c478bd9Sstevel@tonic-gate { \ 5137c478bd9Sstevel@tonic-gate if (lmap->ldap_res != NULL) \ 5147c478bd9Sstevel@tonic-gate { \ 5157c478bd9Sstevel@tonic-gate ldap_msgfree(lmap->ldap_res); \ 5167c478bd9Sstevel@tonic-gate lmap->ldap_res = NULL; \ 5177c478bd9Sstevel@tonic-gate } \ 5187c478bd9Sstevel@tonic-gate (void) ldap_abandon(lmap->ldap_ld, msgid); \ 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate static SM_LDAP_RECURSE_ENTRY * 5227c478bd9Sstevel@tonic-gate sm_ldap_add_recurse(top, item, type, rpool) 5237c478bd9Sstevel@tonic-gate SM_LDAP_RECURSE_LIST **top; 5247c478bd9Sstevel@tonic-gate char *item; 5257c478bd9Sstevel@tonic-gate int type; 5267c478bd9Sstevel@tonic-gate SM_RPOOL_T *rpool; 5277c478bd9Sstevel@tonic-gate { 5287c478bd9Sstevel@tonic-gate int n; 5297c478bd9Sstevel@tonic-gate int m; 5307c478bd9Sstevel@tonic-gate int p; 5317c478bd9Sstevel@tonic-gate int insertat; 5327c478bd9Sstevel@tonic-gate int moveb; 5337c478bd9Sstevel@tonic-gate int oldsizeb; 5347c478bd9Sstevel@tonic-gate int rc; 5357c478bd9Sstevel@tonic-gate SM_LDAP_RECURSE_ENTRY *newe; 5367c478bd9Sstevel@tonic-gate SM_LDAP_RECURSE_ENTRY **olddata; 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate /* 5397c478bd9Sstevel@tonic-gate ** This code will maintain a list of 5407c478bd9Sstevel@tonic-gate ** SM_LDAP_RECURSE_ENTRY structures 5417c478bd9Sstevel@tonic-gate ** in ascending order. 5427c478bd9Sstevel@tonic-gate */ 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate if (*top == NULL) 5457c478bd9Sstevel@tonic-gate { 5467c478bd9Sstevel@tonic-gate /* Allocate an initial SM_LDAP_RECURSE_LIST struct */ 5477c478bd9Sstevel@tonic-gate *top = sm_rpool_malloc_x(rpool, sizeof **top); 548058561cbSjbeck (*top)->lrl_cnt = 0; 549058561cbSjbeck (*top)->lrl_size = 0; 550058561cbSjbeck (*top)->lrl_data = NULL; 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 553058561cbSjbeck if ((*top)->lrl_cnt >= (*top)->lrl_size) 5547c478bd9Sstevel@tonic-gate { 5557c478bd9Sstevel@tonic-gate /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */ 556058561cbSjbeck olddata = (*top)->lrl_data; 557058561cbSjbeck if ((*top)->lrl_size == 0) 5587c478bd9Sstevel@tonic-gate { 5597c478bd9Sstevel@tonic-gate oldsizeb = 0; 560058561cbSjbeck (*top)->lrl_size = 256; 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate else 5637c478bd9Sstevel@tonic-gate { 564058561cbSjbeck oldsizeb = (*top)->lrl_size * sizeof *((*top)->lrl_data); 565058561cbSjbeck (*top)->lrl_size *= 2; 5667c478bd9Sstevel@tonic-gate } 567058561cbSjbeck (*top)->lrl_data = sm_rpool_malloc_x(rpool, 568058561cbSjbeck (*top)->lrl_size * sizeof *((*top)->lrl_data)); 5697c478bd9Sstevel@tonic-gate if (oldsizeb > 0) 570058561cbSjbeck memcpy((*top)->lrl_data, olddata, oldsizeb); 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate /* 5747c478bd9Sstevel@tonic-gate ** Binary search/insert item:type into list. 5757c478bd9Sstevel@tonic-gate ** Return current entry pointer if already exists. 5767c478bd9Sstevel@tonic-gate */ 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate n = 0; 579058561cbSjbeck m = (*top)->lrl_cnt - 1; 5807c478bd9Sstevel@tonic-gate if (m < 0) 5817c478bd9Sstevel@tonic-gate insertat = 0; 5827c478bd9Sstevel@tonic-gate else 5837c478bd9Sstevel@tonic-gate insertat = -1; 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate while (insertat == -1) 5867c478bd9Sstevel@tonic-gate { 5877c478bd9Sstevel@tonic-gate p = (m + n) / 2; 5887c478bd9Sstevel@tonic-gate 589058561cbSjbeck rc = sm_strcasecmp(item, (*top)->lrl_data[p]->lr_search); 5907c478bd9Sstevel@tonic-gate if (rc == 0) 591058561cbSjbeck rc = type - (*top)->lrl_data[p]->lr_type; 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate if (rc < 0) 5947c478bd9Sstevel@tonic-gate m = p - 1; 5957c478bd9Sstevel@tonic-gate else if (rc > 0) 5967c478bd9Sstevel@tonic-gate n = p + 1; 5977c478bd9Sstevel@tonic-gate else 598058561cbSjbeck return (*top)->lrl_data[p]; 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate if (m == -1) 6017c478bd9Sstevel@tonic-gate insertat = 0; 602058561cbSjbeck else if (n >= (*top)->lrl_cnt) 603058561cbSjbeck insertat = (*top)->lrl_cnt; 6047c478bd9Sstevel@tonic-gate else if (m < n) 6057c478bd9Sstevel@tonic-gate insertat = m + 1; 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate /* 6097c478bd9Sstevel@tonic-gate ** Not found in list, make room 6107c478bd9Sstevel@tonic-gate ** at insert point and add it. 6117c478bd9Sstevel@tonic-gate */ 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate newe = sm_rpool_malloc_x(rpool, sizeof *newe); 6147c478bd9Sstevel@tonic-gate if (newe != NULL) 6157c478bd9Sstevel@tonic-gate { 616058561cbSjbeck moveb = ((*top)->lrl_cnt - insertat) * sizeof *((*top)->lrl_data); 6177c478bd9Sstevel@tonic-gate if (moveb > 0) 618058561cbSjbeck memmove(&((*top)->lrl_data[insertat + 1]), 619058561cbSjbeck &((*top)->lrl_data[insertat]), 6207c478bd9Sstevel@tonic-gate moveb); 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate newe->lr_search = sm_rpool_strdup_x(rpool, item); 6237c478bd9Sstevel@tonic-gate newe->lr_type = type; 6247c478bd9Sstevel@tonic-gate newe->lr_ludp = NULL; 6257c478bd9Sstevel@tonic-gate newe->lr_attrs = NULL; 6267c478bd9Sstevel@tonic-gate newe->lr_done = false; 6277c478bd9Sstevel@tonic-gate 628058561cbSjbeck ((*top)->lrl_data)[insertat] = newe; 629058561cbSjbeck (*top)->lrl_cnt++; 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate return newe; 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate int 6357c478bd9Sstevel@tonic-gate sm_ldap_results(lmap, msgid, flags, delim, rpool, result, 6367c478bd9Sstevel@tonic-gate resultln, resultsz, recurse) 6377c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 6387c478bd9Sstevel@tonic-gate int msgid; 6397c478bd9Sstevel@tonic-gate int flags; 6407c478bd9Sstevel@tonic-gate int delim; 6417c478bd9Sstevel@tonic-gate SM_RPOOL_T *rpool; 6427c478bd9Sstevel@tonic-gate char **result; 6437c478bd9Sstevel@tonic-gate int *resultln; 6447c478bd9Sstevel@tonic-gate int *resultsz; 6457c478bd9Sstevel@tonic-gate SM_LDAP_RECURSE_LIST *recurse; 6467c478bd9Sstevel@tonic-gate { 6477c478bd9Sstevel@tonic-gate bool toplevel; 6487c478bd9Sstevel@tonic-gate int i; 6497c478bd9Sstevel@tonic-gate int statp; 6507c478bd9Sstevel@tonic-gate int vsize; 6517c478bd9Sstevel@tonic-gate int ret; 6527c478bd9Sstevel@tonic-gate int save_errno; 6537c478bd9Sstevel@tonic-gate char *p; 6547c478bd9Sstevel@tonic-gate SM_LDAP_RECURSE_ENTRY *rl; 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate /* Are we the top top level of the search? */ 6577c478bd9Sstevel@tonic-gate toplevel = (recurse == NULL); 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate /* Get results */ 6607c478bd9Sstevel@tonic-gate statp = EX_NOTFOUND; 6617c478bd9Sstevel@tonic-gate while ((ret = ldap_result(lmap->ldap_ld, msgid, 0, 6627c478bd9Sstevel@tonic-gate (lmap->ldap_timeout.tv_sec == 0 ? NULL : 6637c478bd9Sstevel@tonic-gate &(lmap->ldap_timeout)), 6647c478bd9Sstevel@tonic-gate &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) 6657c478bd9Sstevel@tonic-gate { 6667c478bd9Sstevel@tonic-gate LDAPMessage *entry; 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate /* If we don't want multiple values and we have one, break */ 6697c478bd9Sstevel@tonic-gate if ((char) delim == '\0' && 6707c478bd9Sstevel@tonic-gate !bitset(SM_LDAP_SINGLEMATCH, flags) && 6717c478bd9Sstevel@tonic-gate *result != NULL) 6727c478bd9Sstevel@tonic-gate break; 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate /* Cycle through all entries */ 6757c478bd9Sstevel@tonic-gate for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); 6767c478bd9Sstevel@tonic-gate entry != NULL; 6777c478bd9Sstevel@tonic-gate entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) 6787c478bd9Sstevel@tonic-gate { 6797c478bd9Sstevel@tonic-gate BerElement *ber; 6807c478bd9Sstevel@tonic-gate char *attr; 6817c478bd9Sstevel@tonic-gate char **vals = NULL; 6827c478bd9Sstevel@tonic-gate char *dn; 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate /* 6857c478bd9Sstevel@tonic-gate ** If matching only and found an entry, 6867c478bd9Sstevel@tonic-gate ** no need to spin through attributes 6877c478bd9Sstevel@tonic-gate */ 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate if (bitset(SM_LDAP_MATCHONLY, flags)) 6907c478bd9Sstevel@tonic-gate { 6917c478bd9Sstevel@tonic-gate statp = EX_OK; 6927c478bd9Sstevel@tonic-gate continue; 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate 69549218d4fSjbeck #if _FFR_LDAP_SINGLEDN 69649218d4fSjbeck if (bitset(SM_LDAP_SINGLEDN, flags) && *result != NULL) 69749218d4fSjbeck { 69849218d4fSjbeck /* only wanted one match */ 69949218d4fSjbeck SM_LDAP_ERROR_CLEANUP(); 70049218d4fSjbeck errno = ENOENT; 70149218d4fSjbeck return EX_NOTFOUND; 70249218d4fSjbeck } 70349218d4fSjbeck #endif /* _FFR_LDAP_SINGLEDN */ 70449218d4fSjbeck 7057c478bd9Sstevel@tonic-gate /* record completed DN's to prevent loops */ 7067c478bd9Sstevel@tonic-gate dn = ldap_get_dn(lmap->ldap_ld, entry); 7077c478bd9Sstevel@tonic-gate if (dn == NULL) 7087c478bd9Sstevel@tonic-gate { 7097c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(lmap->ldap_ld); 7107c478bd9Sstevel@tonic-gate save_errno += E_LDAPBASE; 7117c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 7127c478bd9Sstevel@tonic-gate errno = save_errno; 7137c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate rl = sm_ldap_add_recurse(&recurse, dn, 7177c478bd9Sstevel@tonic-gate SM_LDAP_ATTR_DN, 7187c478bd9Sstevel@tonic-gate rpool); 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate if (rl == NULL) 7217c478bd9Sstevel@tonic-gate { 7227c478bd9Sstevel@tonic-gate ldap_memfree(dn); 7237c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 7247c478bd9Sstevel@tonic-gate errno = ENOMEM; 7257c478bd9Sstevel@tonic-gate return EX_OSERR; 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate else if (rl->lr_done) 7287c478bd9Sstevel@tonic-gate { 7297c478bd9Sstevel@tonic-gate /* already on list, skip it */ 7307c478bd9Sstevel@tonic-gate ldap_memfree(dn); 7317c478bd9Sstevel@tonic-gate continue; 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate ldap_memfree(dn); 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 7367c478bd9Sstevel@tonic-gate /* 7377c478bd9Sstevel@tonic-gate ** Reset value to prevent lingering 7387c478bd9Sstevel@tonic-gate ** LDAP_DECODING_ERROR due to 7397c478bd9Sstevel@tonic-gate ** OpenLDAP 1.X's hack (see below) 7407c478bd9Sstevel@tonic-gate */ 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 7437c478bd9Sstevel@tonic-gate # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate for (attr = ldap_first_attribute(lmap->ldap_ld, entry, 7467c478bd9Sstevel@tonic-gate &ber); 7477c478bd9Sstevel@tonic-gate attr != NULL; 7487c478bd9Sstevel@tonic-gate attr = ldap_next_attribute(lmap->ldap_ld, entry, 7497c478bd9Sstevel@tonic-gate ber)) 7507c478bd9Sstevel@tonic-gate { 7517c478bd9Sstevel@tonic-gate char *tmp, *vp_tmp; 7527c478bd9Sstevel@tonic-gate int type; 7537c478bd9Sstevel@tonic-gate char *needobjclass = NULL; 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate type = SM_LDAP_ATTR_NONE; 7567c478bd9Sstevel@tonic-gate for (i = 0; lmap->ldap_attr[i] != NULL; i++) 7577c478bd9Sstevel@tonic-gate { 7587c478bd9Sstevel@tonic-gate if (sm_strcasecmp(lmap->ldap_attr[i], 7597c478bd9Sstevel@tonic-gate attr) == 0) 7607c478bd9Sstevel@tonic-gate { 7617c478bd9Sstevel@tonic-gate type = lmap->ldap_attr_type[i]; 7627c478bd9Sstevel@tonic-gate needobjclass = lmap->ldap_attr_needobjclass[i]; 7637c478bd9Sstevel@tonic-gate break; 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate if (bitset(SM_LDAP_USE_ALLATTR, flags) && 7687c478bd9Sstevel@tonic-gate type == SM_LDAP_ATTR_NONE) 7697c478bd9Sstevel@tonic-gate { 7707c478bd9Sstevel@tonic-gate /* URL lookups specify attrs to use */ 7717c478bd9Sstevel@tonic-gate type = SM_LDAP_ATTR_NORMAL; 7727c478bd9Sstevel@tonic-gate needobjclass = NULL; 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate if (type == SM_LDAP_ATTR_NONE) 7767c478bd9Sstevel@tonic-gate { 7777c478bd9Sstevel@tonic-gate /* attribute not requested */ 7787c478bd9Sstevel@tonic-gate ldap_memfree(attr); 7797c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 7807c478bd9Sstevel@tonic-gate errno = EFAULT; 7817c478bd9Sstevel@tonic-gate return EX_SOFTWARE; 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate /* 7857c478bd9Sstevel@tonic-gate ** For recursion on a particular attribute, 7867c478bd9Sstevel@tonic-gate ** we may need to see if this entry is 7877c478bd9Sstevel@tonic-gate ** part of a particular objectclass. 7887c478bd9Sstevel@tonic-gate ** Also, ignore objectClass attribute. 7897c478bd9Sstevel@tonic-gate ** Otherwise we just ignore this attribute. 7907c478bd9Sstevel@tonic-gate */ 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if (type == SM_LDAP_ATTR_OBJCLASS || 7937c478bd9Sstevel@tonic-gate (needobjclass != NULL && 7947c478bd9Sstevel@tonic-gate !sm_ldap_has_objectclass(lmap, entry, 7957c478bd9Sstevel@tonic-gate needobjclass))) 7967c478bd9Sstevel@tonic-gate { 7977c478bd9Sstevel@tonic-gate ldap_memfree(attr); 7987c478bd9Sstevel@tonic-gate continue; 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 8027c478bd9Sstevel@tonic-gate { 8037c478bd9Sstevel@tonic-gate vals = ldap_get_values(lmap->ldap_ld, 8047c478bd9Sstevel@tonic-gate entry, 8057c478bd9Sstevel@tonic-gate attr); 8067c478bd9Sstevel@tonic-gate if (vals == NULL) 8077c478bd9Sstevel@tonic-gate { 8087c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(lmap->ldap_ld); 8097c478bd9Sstevel@tonic-gate if (save_errno == LDAP_SUCCESS) 8107c478bd9Sstevel@tonic-gate { 8117c478bd9Sstevel@tonic-gate ldap_memfree(attr); 8127c478bd9Sstevel@tonic-gate continue; 8137c478bd9Sstevel@tonic-gate } 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate /* Must be an error */ 8167c478bd9Sstevel@tonic-gate save_errno += E_LDAPBASE; 8177c478bd9Sstevel@tonic-gate ldap_memfree(attr); 8187c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 8197c478bd9Sstevel@tonic-gate errno = save_errno; 8207c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate } 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate statp = EX_OK; 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 8277c478bd9Sstevel@tonic-gate /* 8287c478bd9Sstevel@tonic-gate ** Reset value to prevent lingering 8297c478bd9Sstevel@tonic-gate ** LDAP_DECODING_ERROR due to 8307c478bd9Sstevel@tonic-gate ** OpenLDAP 1.X's hack (see below) 8317c478bd9Sstevel@tonic-gate */ 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 8347c478bd9Sstevel@tonic-gate # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate /* 8377c478bd9Sstevel@tonic-gate ** If matching only, 8387c478bd9Sstevel@tonic-gate ** no need to spin through entries 8397c478bd9Sstevel@tonic-gate */ 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate if (bitset(SM_LDAP_MATCHONLY, flags)) 8427c478bd9Sstevel@tonic-gate { 8437c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 8447c478bd9Sstevel@tonic-gate ldap_value_free(vals); 8457c478bd9Sstevel@tonic-gate ldap_memfree(attr); 8467c478bd9Sstevel@tonic-gate continue; 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate /* 8507c478bd9Sstevel@tonic-gate ** If we don't want multiple values, 8517c478bd9Sstevel@tonic-gate ** return first found. 8527c478bd9Sstevel@tonic-gate */ 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate if ((char) delim == '\0') 8557c478bd9Sstevel@tonic-gate { 8567c478bd9Sstevel@tonic-gate if (*result != NULL) 8577c478bd9Sstevel@tonic-gate { 8587c478bd9Sstevel@tonic-gate /* already have a value */ 8597c478bd9Sstevel@tonic-gate if (bitset(SM_LDAP_SINGLEMATCH, 8607c478bd9Sstevel@tonic-gate flags)) 8617c478bd9Sstevel@tonic-gate { 8627c478bd9Sstevel@tonic-gate /* only wanted one match */ 8637c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 8647c478bd9Sstevel@tonic-gate errno = ENOENT; 8657c478bd9Sstevel@tonic-gate return EX_NOTFOUND; 8667c478bd9Sstevel@tonic-gate } 8677c478bd9Sstevel@tonic-gate break; 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate 8707c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 8717c478bd9Sstevel@tonic-gate { 8727c478bd9Sstevel@tonic-gate *result = sm_rpool_strdup_x(rpool, 8737c478bd9Sstevel@tonic-gate attr); 8747c478bd9Sstevel@tonic-gate ldap_memfree(attr); 8757c478bd9Sstevel@tonic-gate break; 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate if (vals[0] == NULL) 8797c478bd9Sstevel@tonic-gate { 8807c478bd9Sstevel@tonic-gate ldap_value_free(vals); 8817c478bd9Sstevel@tonic-gate ldap_memfree(attr); 8827c478bd9Sstevel@tonic-gate continue; 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate vsize = strlen(vals[0]) + 1; 8867c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsep != '\0') 8877c478bd9Sstevel@tonic-gate vsize += strlen(attr) + 1; 8887c478bd9Sstevel@tonic-gate *result = sm_rpool_malloc_x(rpool, 8897c478bd9Sstevel@tonic-gate vsize); 8907c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsep != '\0') 8917c478bd9Sstevel@tonic-gate sm_snprintf(*result, vsize, 8927c478bd9Sstevel@tonic-gate "%s%c%s", 8937c478bd9Sstevel@tonic-gate attr, 8947c478bd9Sstevel@tonic-gate lmap->ldap_attrsep, 8957c478bd9Sstevel@tonic-gate vals[0]); 8967c478bd9Sstevel@tonic-gate else 8977c478bd9Sstevel@tonic-gate sm_strlcpy(*result, vals[0], 8987c478bd9Sstevel@tonic-gate vsize); 8997c478bd9Sstevel@tonic-gate ldap_value_free(vals); 9007c478bd9Sstevel@tonic-gate ldap_memfree(attr); 9017c478bd9Sstevel@tonic-gate break; 9027c478bd9Sstevel@tonic-gate } 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate /* attributes only */ 9057c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 9067c478bd9Sstevel@tonic-gate { 9077c478bd9Sstevel@tonic-gate if (*result == NULL) 9087c478bd9Sstevel@tonic-gate *result = sm_rpool_strdup_x(rpool, 9097c478bd9Sstevel@tonic-gate attr); 9107c478bd9Sstevel@tonic-gate else 9117c478bd9Sstevel@tonic-gate { 9127c478bd9Sstevel@tonic-gate if (bitset(SM_LDAP_SINGLEMATCH, 9137c478bd9Sstevel@tonic-gate flags) && 9147c478bd9Sstevel@tonic-gate *result != NULL) 9157c478bd9Sstevel@tonic-gate { 9167c478bd9Sstevel@tonic-gate /* only wanted one match */ 9177c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 9187c478bd9Sstevel@tonic-gate errno = ENOENT; 9197c478bd9Sstevel@tonic-gate return EX_NOTFOUND; 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate vsize = strlen(*result) + 9237c478bd9Sstevel@tonic-gate strlen(attr) + 2; 9247c478bd9Sstevel@tonic-gate tmp = sm_rpool_malloc_x(rpool, 9257c478bd9Sstevel@tonic-gate vsize); 9267c478bd9Sstevel@tonic-gate (void) sm_snprintf(tmp, 9277c478bd9Sstevel@tonic-gate vsize, "%s%c%s", 9287c478bd9Sstevel@tonic-gate *result, (char) delim, 9297c478bd9Sstevel@tonic-gate attr); 9307c478bd9Sstevel@tonic-gate *result = tmp; 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate ldap_memfree(attr); 9337c478bd9Sstevel@tonic-gate continue; 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate /* 9377c478bd9Sstevel@tonic-gate ** If there is more than one, munge then 9387c478bd9Sstevel@tonic-gate ** into a map_coldelim separated string. 9397c478bd9Sstevel@tonic-gate ** If we are recursing we may have an entry 9407c478bd9Sstevel@tonic-gate ** with no 'normal' values to put in the 9417c478bd9Sstevel@tonic-gate ** string. 9427c478bd9Sstevel@tonic-gate ** This is not an error. 9437c478bd9Sstevel@tonic-gate */ 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate if (type == SM_LDAP_ATTR_NORMAL && 9467c478bd9Sstevel@tonic-gate bitset(SM_LDAP_SINGLEMATCH, flags) && 9477c478bd9Sstevel@tonic-gate *result != NULL) 9487c478bd9Sstevel@tonic-gate { 9497c478bd9Sstevel@tonic-gate /* only wanted one match */ 9507c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 9517c478bd9Sstevel@tonic-gate errno = ENOENT; 9527c478bd9Sstevel@tonic-gate return EX_NOTFOUND; 9537c478bd9Sstevel@tonic-gate } 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate vsize = 0; 9567c478bd9Sstevel@tonic-gate for (i = 0; vals[i] != NULL; i++) 9577c478bd9Sstevel@tonic-gate { 9587c478bd9Sstevel@tonic-gate if (type == SM_LDAP_ATTR_DN || 9597c478bd9Sstevel@tonic-gate type == SM_LDAP_ATTR_FILTER || 9607c478bd9Sstevel@tonic-gate type == SM_LDAP_ATTR_URL) 9617c478bd9Sstevel@tonic-gate { 9627c478bd9Sstevel@tonic-gate /* add to recursion */ 9637c478bd9Sstevel@tonic-gate if (sm_ldap_add_recurse(&recurse, 9647c478bd9Sstevel@tonic-gate vals[i], 9657c478bd9Sstevel@tonic-gate type, 9667c478bd9Sstevel@tonic-gate rpool) == NULL) 9677c478bd9Sstevel@tonic-gate { 9687c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 9697c478bd9Sstevel@tonic-gate errno = ENOMEM; 9707c478bd9Sstevel@tonic-gate return EX_OSERR; 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate continue; 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate vsize += strlen(vals[i]) + 1; 9767c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsep != '\0') 9777c478bd9Sstevel@tonic-gate vsize += strlen(attr) + 1; 9787c478bd9Sstevel@tonic-gate } 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate /* 9817c478bd9Sstevel@tonic-gate ** Create/Append to string any normal 9827c478bd9Sstevel@tonic-gate ** attribute values. Otherwise, just free 9837c478bd9Sstevel@tonic-gate ** memory and move on to the next 9847c478bd9Sstevel@tonic-gate ** attribute in this entry. 9857c478bd9Sstevel@tonic-gate */ 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate if (type == SM_LDAP_ATTR_NORMAL && vsize > 0) 9887c478bd9Sstevel@tonic-gate { 9897c478bd9Sstevel@tonic-gate char *pe; 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate /* Grow result string if needed */ 9927c478bd9Sstevel@tonic-gate if ((*resultln + vsize) >= *resultsz) 9937c478bd9Sstevel@tonic-gate { 9947c478bd9Sstevel@tonic-gate while ((*resultln + vsize) >= *resultsz) 9957c478bd9Sstevel@tonic-gate { 9967c478bd9Sstevel@tonic-gate if (*resultsz == 0) 9977c478bd9Sstevel@tonic-gate *resultsz = 1024; 9987c478bd9Sstevel@tonic-gate else 9997c478bd9Sstevel@tonic-gate *resultsz *= 2; 10007c478bd9Sstevel@tonic-gate } 10017c478bd9Sstevel@tonic-gate 10027c478bd9Sstevel@tonic-gate vp_tmp = sm_rpool_malloc_x(rpool, *resultsz); 10037c478bd9Sstevel@tonic-gate *vp_tmp = '\0'; 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate if (*result != NULL) 10067c478bd9Sstevel@tonic-gate sm_strlcpy(vp_tmp, 10077c478bd9Sstevel@tonic-gate *result, 10087c478bd9Sstevel@tonic-gate *resultsz); 10097c478bd9Sstevel@tonic-gate *result = vp_tmp; 10107c478bd9Sstevel@tonic-gate } 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate p = *result + *resultln; 10137c478bd9Sstevel@tonic-gate pe = *result + *resultsz; 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate for (i = 0; vals[i] != NULL; i++) 10167c478bd9Sstevel@tonic-gate { 10177c478bd9Sstevel@tonic-gate if (*resultln > 0 && 10187c478bd9Sstevel@tonic-gate p < pe) 10197c478bd9Sstevel@tonic-gate *p++ = (char) delim; 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate if (lmap->ldap_attrsep != '\0') 10227c478bd9Sstevel@tonic-gate { 10237c478bd9Sstevel@tonic-gate p += sm_strlcpy(p, attr, 10247c478bd9Sstevel@tonic-gate pe - p); 10257c478bd9Sstevel@tonic-gate if (p < pe) 10267c478bd9Sstevel@tonic-gate *p++ = lmap->ldap_attrsep; 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate p += sm_strlcpy(p, vals[i], 10307c478bd9Sstevel@tonic-gate pe - p); 10317c478bd9Sstevel@tonic-gate *resultln = p - (*result); 10327c478bd9Sstevel@tonic-gate if (p >= pe) 10337c478bd9Sstevel@tonic-gate { 10347c478bd9Sstevel@tonic-gate /* Internal error: buffer too small for LDAP values */ 10357c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 10367c478bd9Sstevel@tonic-gate errno = ENOMEM; 10377c478bd9Sstevel@tonic-gate return EX_OSERR; 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate } 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate ldap_value_free(vals); 10437c478bd9Sstevel@tonic-gate ldap_memfree(attr); 10447c478bd9Sstevel@tonic-gate } 10457c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(lmap->ldap_ld); 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate /* 10487c478bd9Sstevel@tonic-gate ** We check save_errno != LDAP_DECODING_ERROR since 10497c478bd9Sstevel@tonic-gate ** OpenLDAP 1.X has a very ugly *undocumented* 10507c478bd9Sstevel@tonic-gate ** hack of returning this error code from 10517c478bd9Sstevel@tonic-gate ** ldap_next_attribute() if the library freed the 10527c478bd9Sstevel@tonic-gate ** ber attribute. See: 10537c478bd9Sstevel@tonic-gate ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 10547c478bd9Sstevel@tonic-gate */ 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate if (save_errno != LDAP_SUCCESS && 10577c478bd9Sstevel@tonic-gate save_errno != LDAP_DECODING_ERROR) 10587c478bd9Sstevel@tonic-gate { 10597c478bd9Sstevel@tonic-gate /* Must be an error */ 10607c478bd9Sstevel@tonic-gate save_errno += E_LDAPBASE; 10617c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 10627c478bd9Sstevel@tonic-gate errno = save_errno; 10637c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate /* mark this DN as done */ 10677c478bd9Sstevel@tonic-gate rl->lr_done = true; 10687c478bd9Sstevel@tonic-gate if (rl->lr_ludp != NULL) 10697c478bd9Sstevel@tonic-gate { 10707c478bd9Sstevel@tonic-gate ldap_free_urldesc(rl->lr_ludp); 10717c478bd9Sstevel@tonic-gate rl->lr_ludp = NULL; 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate if (rl->lr_attrs != NULL) 10747c478bd9Sstevel@tonic-gate { 10757c478bd9Sstevel@tonic-gate free(rl->lr_attrs); 10767c478bd9Sstevel@tonic-gate rl->lr_attrs = NULL; 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate /* We don't want multiple values and we have one */ 10807c478bd9Sstevel@tonic-gate if ((char) delim == '\0' && 10817c478bd9Sstevel@tonic-gate !bitset(SM_LDAP_SINGLEMATCH, flags) && 10827c478bd9Sstevel@tonic-gate *result != NULL) 10837c478bd9Sstevel@tonic-gate break; 10847c478bd9Sstevel@tonic-gate } 10857c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(lmap->ldap_ld); 10867c478bd9Sstevel@tonic-gate if (save_errno != LDAP_SUCCESS && 10877c478bd9Sstevel@tonic-gate save_errno != LDAP_DECODING_ERROR) 10887c478bd9Sstevel@tonic-gate { 10897c478bd9Sstevel@tonic-gate /* Must be an error */ 10907c478bd9Sstevel@tonic-gate save_errno += E_LDAPBASE; 10917c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 10927c478bd9Sstevel@tonic-gate errno = save_errno; 10937c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 10947c478bd9Sstevel@tonic-gate } 10957c478bd9Sstevel@tonic-gate ldap_msgfree(lmap->ldap_res); 10967c478bd9Sstevel@tonic-gate lmap->ldap_res = NULL; 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate if (ret == 0) 11007c478bd9Sstevel@tonic-gate save_errno = ETIMEDOUT; 11017c478bd9Sstevel@tonic-gate else 1102*e9af4bc0SJohn Beck { 1103*e9af4bc0SJohn Beck int rc; 1104*e9af4bc0SJohn Beck 1105*e9af4bc0SJohn Beck /* 1106*e9af4bc0SJohn Beck ** We may have gotten an LDAP_RES_SEARCH_RESULT response 1107*e9af4bc0SJohn Beck ** with an error inside it, so we have to extract that 1108*e9af4bc0SJohn Beck ** with ldap_parse_result(). This can happen when talking 1109*e9af4bc0SJohn Beck ** to an LDAP proxy whose backend has gone down. 1110*e9af4bc0SJohn Beck */ 1111*e9af4bc0SJohn Beck 1112*e9af4bc0SJohn Beck save_errno = ldap_parse_result(lmap->ldap_ld, lmap->ldap_res, 1113*e9af4bc0SJohn Beck &rc, NULL, NULL, NULL, NULL, 0); 1114*e9af4bc0SJohn Beck if (save_errno == LDAP_SUCCESS) 1115*e9af4bc0SJohn Beck save_errno = rc; 1116*e9af4bc0SJohn Beck } 11177c478bd9Sstevel@tonic-gate if (save_errno != LDAP_SUCCESS) 11187c478bd9Sstevel@tonic-gate { 11197c478bd9Sstevel@tonic-gate statp = EX_TEMPFAIL; 11207c478bd9Sstevel@tonic-gate switch (save_errno) 11217c478bd9Sstevel@tonic-gate { 11227c478bd9Sstevel@tonic-gate #ifdef LDAP_SERVER_DOWN 11237c478bd9Sstevel@tonic-gate case LDAP_SERVER_DOWN: 11247c478bd9Sstevel@tonic-gate #endif /* LDAP_SERVER_DOWN */ 11257c478bd9Sstevel@tonic-gate case LDAP_TIMEOUT: 11267800901eSjbeck case ETIMEDOUT: 11277c478bd9Sstevel@tonic-gate case LDAP_UNAVAILABLE: 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate /* 11307c478bd9Sstevel@tonic-gate ** server disappeared, 11317c478bd9Sstevel@tonic-gate ** try reopen on next search 11327c478bd9Sstevel@tonic-gate */ 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate statp = EX_RESTART; 11357c478bd9Sstevel@tonic-gate break; 11367c478bd9Sstevel@tonic-gate } 11377800901eSjbeck if (ret != 0) 11387c478bd9Sstevel@tonic-gate save_errno += E_LDAPBASE; 11397c478bd9Sstevel@tonic-gate SM_LDAP_ERROR_CLEANUP(); 11407c478bd9Sstevel@tonic-gate errno = save_errno; 11417c478bd9Sstevel@tonic-gate return statp; 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate if (lmap->ldap_res != NULL) 11457c478bd9Sstevel@tonic-gate { 11467c478bd9Sstevel@tonic-gate ldap_msgfree(lmap->ldap_res); 11477c478bd9Sstevel@tonic-gate lmap->ldap_res = NULL; 11487c478bd9Sstevel@tonic-gate } 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate if (toplevel) 11517c478bd9Sstevel@tonic-gate { 11527c478bd9Sstevel@tonic-gate int rlidx; 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate /* 11557c478bd9Sstevel@tonic-gate ** Spin through the built-up recurse list at the top 11567c478bd9Sstevel@tonic-gate ** of the recursion. Since new items are added at the 11577c478bd9Sstevel@tonic-gate ** end of the shared list, we actually only ever get 11587c478bd9Sstevel@tonic-gate ** one level of recursion before things pop back to the 11597c478bd9Sstevel@tonic-gate ** top. Any items added to the list during that recursion 11607c478bd9Sstevel@tonic-gate ** will be expanded by the top level. 11617c478bd9Sstevel@tonic-gate */ 11627c478bd9Sstevel@tonic-gate 1163058561cbSjbeck for (rlidx = 0; recurse != NULL && rlidx < recurse->lrl_cnt; 1164058561cbSjbeck rlidx++) 11657c478bd9Sstevel@tonic-gate { 11667c478bd9Sstevel@tonic-gate int newflags; 11677c478bd9Sstevel@tonic-gate int sid; 11687c478bd9Sstevel@tonic-gate int status; 11697c478bd9Sstevel@tonic-gate 1170058561cbSjbeck rl = recurse->lrl_data[rlidx]; 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate newflags = flags; 11737c478bd9Sstevel@tonic-gate if (rl->lr_done) 11747c478bd9Sstevel@tonic-gate { 11757c478bd9Sstevel@tonic-gate /* already expanded */ 11767c478bd9Sstevel@tonic-gate continue; 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate if (rl->lr_type == SM_LDAP_ATTR_DN) 11807c478bd9Sstevel@tonic-gate { 11817c478bd9Sstevel@tonic-gate /* do DN search */ 11827c478bd9Sstevel@tonic-gate sid = ldap_search(lmap->ldap_ld, 11837c478bd9Sstevel@tonic-gate rl->lr_search, 11847c478bd9Sstevel@tonic-gate lmap->ldap_scope, 11857c478bd9Sstevel@tonic-gate "(objectClass=*)", 11867c478bd9Sstevel@tonic-gate (lmap->ldap_attr[0] == NULL ? 11877c478bd9Sstevel@tonic-gate NULL : lmap->ldap_attr), 11887c478bd9Sstevel@tonic-gate lmap->ldap_attrsonly); 11897c478bd9Sstevel@tonic-gate } 11907c478bd9Sstevel@tonic-gate else if (rl->lr_type == SM_LDAP_ATTR_FILTER) 11917c478bd9Sstevel@tonic-gate { 11927c478bd9Sstevel@tonic-gate /* do new search */ 11937c478bd9Sstevel@tonic-gate sid = ldap_search(lmap->ldap_ld, 11947c478bd9Sstevel@tonic-gate lmap->ldap_base, 11957c478bd9Sstevel@tonic-gate lmap->ldap_scope, 11967c478bd9Sstevel@tonic-gate rl->lr_search, 11977c478bd9Sstevel@tonic-gate (lmap->ldap_attr[0] == NULL ? 11987c478bd9Sstevel@tonic-gate NULL : lmap->ldap_attr), 11997c478bd9Sstevel@tonic-gate lmap->ldap_attrsonly); 12007c478bd9Sstevel@tonic-gate } 12017c478bd9Sstevel@tonic-gate else if (rl->lr_type == SM_LDAP_ATTR_URL) 12027c478bd9Sstevel@tonic-gate { 12037c478bd9Sstevel@tonic-gate /* Parse URL */ 12047c478bd9Sstevel@tonic-gate sid = ldap_url_parse(rl->lr_search, 12057c478bd9Sstevel@tonic-gate &rl->lr_ludp); 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate if (sid != 0) 12087c478bd9Sstevel@tonic-gate { 12097c478bd9Sstevel@tonic-gate errno = sid + E_LDAPURLBASE; 12107c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 12117c478bd9Sstevel@tonic-gate } 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate /* We need to add objectClass */ 12147c478bd9Sstevel@tonic-gate if (rl->lr_ludp->lud_attrs != NULL) 12157c478bd9Sstevel@tonic-gate { 12167c478bd9Sstevel@tonic-gate int attrnum = 0; 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate while (rl->lr_ludp->lud_attrs[attrnum] != NULL) 12197c478bd9Sstevel@tonic-gate { 12207c478bd9Sstevel@tonic-gate if (strcasecmp(rl->lr_ludp->lud_attrs[attrnum], 12217c478bd9Sstevel@tonic-gate "objectClass") == 0) 12227c478bd9Sstevel@tonic-gate { 12237c478bd9Sstevel@tonic-gate /* already requested */ 12247c478bd9Sstevel@tonic-gate attrnum = -1; 12257c478bd9Sstevel@tonic-gate break; 12267c478bd9Sstevel@tonic-gate } 12277c478bd9Sstevel@tonic-gate attrnum++; 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate if (attrnum >= 0) 12317c478bd9Sstevel@tonic-gate { 12327c478bd9Sstevel@tonic-gate int i; 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate rl->lr_attrs = (char **)malloc(sizeof(char *) * (attrnum + 2)); 12357c478bd9Sstevel@tonic-gate if (rl->lr_attrs == NULL) 12367c478bd9Sstevel@tonic-gate { 12377c478bd9Sstevel@tonic-gate save_errno = errno; 12387c478bd9Sstevel@tonic-gate ldap_free_urldesc(rl->lr_ludp); 12397c478bd9Sstevel@tonic-gate errno = save_errno; 12407c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 12417c478bd9Sstevel@tonic-gate } 12427c478bd9Sstevel@tonic-gate for (i = 0 ; i < attrnum; i++) 12437c478bd9Sstevel@tonic-gate { 12447c478bd9Sstevel@tonic-gate rl->lr_attrs[i] = rl->lr_ludp->lud_attrs[i]; 12457c478bd9Sstevel@tonic-gate } 12467c478bd9Sstevel@tonic-gate rl->lr_attrs[i++] = "objectClass"; 12477c478bd9Sstevel@tonic-gate rl->lr_attrs[i++] = NULL; 12487c478bd9Sstevel@tonic-gate } 12497c478bd9Sstevel@tonic-gate } 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate /* 12527c478bd9Sstevel@tonic-gate ** Use the existing connection 12537c478bd9Sstevel@tonic-gate ** for this search. It really 12547c478bd9Sstevel@tonic-gate ** should use lud_scheme://lud_host:lud_port/ 12557c478bd9Sstevel@tonic-gate ** instead but that would require 12567c478bd9Sstevel@tonic-gate ** opening a new connection. 12577c478bd9Sstevel@tonic-gate ** This should be fixed ASAP. 12587c478bd9Sstevel@tonic-gate */ 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate sid = ldap_search(lmap->ldap_ld, 12617c478bd9Sstevel@tonic-gate rl->lr_ludp->lud_dn, 12627c478bd9Sstevel@tonic-gate rl->lr_ludp->lud_scope, 12637c478bd9Sstevel@tonic-gate rl->lr_ludp->lud_filter, 12647c478bd9Sstevel@tonic-gate rl->lr_attrs, 12657c478bd9Sstevel@tonic-gate lmap->ldap_attrsonly); 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate /* Use the attributes specified by URL */ 12687c478bd9Sstevel@tonic-gate newflags |= SM_LDAP_USE_ALLATTR; 12697c478bd9Sstevel@tonic-gate } 12707c478bd9Sstevel@tonic-gate else 12717c478bd9Sstevel@tonic-gate { 12727c478bd9Sstevel@tonic-gate /* unknown or illegal attribute type */ 12737c478bd9Sstevel@tonic-gate errno = EFAULT; 12747c478bd9Sstevel@tonic-gate return EX_SOFTWARE; 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate 12777c478bd9Sstevel@tonic-gate /* Collect results */ 12787c478bd9Sstevel@tonic-gate if (sid == -1) 12797c478bd9Sstevel@tonic-gate { 12807c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(lmap->ldap_ld); 12817c478bd9Sstevel@tonic-gate statp = EX_TEMPFAIL; 12827c478bd9Sstevel@tonic-gate switch (save_errno) 12837c478bd9Sstevel@tonic-gate { 12847c478bd9Sstevel@tonic-gate #ifdef LDAP_SERVER_DOWN 12857c478bd9Sstevel@tonic-gate case LDAP_SERVER_DOWN: 12867c478bd9Sstevel@tonic-gate #endif /* LDAP_SERVER_DOWN */ 12877c478bd9Sstevel@tonic-gate case LDAP_TIMEOUT: 12887800901eSjbeck case ETIMEDOUT: 12897c478bd9Sstevel@tonic-gate case LDAP_UNAVAILABLE: 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate /* 12927c478bd9Sstevel@tonic-gate ** server disappeared, 12937c478bd9Sstevel@tonic-gate ** try reopen on next search 12947c478bd9Sstevel@tonic-gate */ 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate statp = EX_RESTART; 12977c478bd9Sstevel@tonic-gate break; 12987c478bd9Sstevel@tonic-gate } 12997c478bd9Sstevel@tonic-gate errno = save_errno + E_LDAPBASE; 13007c478bd9Sstevel@tonic-gate return statp; 13017c478bd9Sstevel@tonic-gate } 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate status = sm_ldap_results(lmap, sid, newflags, delim, 13047c478bd9Sstevel@tonic-gate rpool, result, resultln, 13057c478bd9Sstevel@tonic-gate resultsz, recurse); 13067c478bd9Sstevel@tonic-gate save_errno = errno; 13077c478bd9Sstevel@tonic-gate if (status != EX_OK && status != EX_NOTFOUND) 13087c478bd9Sstevel@tonic-gate { 13097c478bd9Sstevel@tonic-gate errno = save_errno; 13107c478bd9Sstevel@tonic-gate return status; 13117c478bd9Sstevel@tonic-gate } 13127c478bd9Sstevel@tonic-gate 13137c478bd9Sstevel@tonic-gate /* Mark as done */ 13147c478bd9Sstevel@tonic-gate rl->lr_done = true; 13157c478bd9Sstevel@tonic-gate if (rl->lr_ludp != NULL) 13167c478bd9Sstevel@tonic-gate { 13177c478bd9Sstevel@tonic-gate ldap_free_urldesc(rl->lr_ludp); 13187c478bd9Sstevel@tonic-gate rl->lr_ludp = NULL; 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate if (rl->lr_attrs != NULL) 13217c478bd9Sstevel@tonic-gate { 13227c478bd9Sstevel@tonic-gate free(rl->lr_attrs); 13237c478bd9Sstevel@tonic-gate rl->lr_attrs = NULL; 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate /* Reset rlidx as new items may have been added */ 13277c478bd9Sstevel@tonic-gate rlidx = -1; 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate } 13307c478bd9Sstevel@tonic-gate return statp; 13317c478bd9Sstevel@tonic-gate } 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate /* 13347c478bd9Sstevel@tonic-gate ** SM_LDAP_CLOSE -- close LDAP connection 13357c478bd9Sstevel@tonic-gate ** 13367c478bd9Sstevel@tonic-gate ** Parameters: 13377c478bd9Sstevel@tonic-gate ** lmap -- LDAP map information 13387c478bd9Sstevel@tonic-gate ** 13397c478bd9Sstevel@tonic-gate ** Returns: 13407c478bd9Sstevel@tonic-gate ** None. 13417c478bd9Sstevel@tonic-gate ** 13427c478bd9Sstevel@tonic-gate */ 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate void 13457c478bd9Sstevel@tonic-gate sm_ldap_close(lmap) 13467c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 13477c478bd9Sstevel@tonic-gate { 13487c478bd9Sstevel@tonic-gate if (lmap->ldap_ld == NULL) 13497c478bd9Sstevel@tonic-gate return; 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate if (lmap->ldap_pid == getpid()) 13527c478bd9Sstevel@tonic-gate ldap_unbind(lmap->ldap_ld); 13537c478bd9Sstevel@tonic-gate lmap->ldap_ld = NULL; 13547c478bd9Sstevel@tonic-gate lmap->ldap_pid = 0; 13557c478bd9Sstevel@tonic-gate } 13567c478bd9Sstevel@tonic-gate 13577c478bd9Sstevel@tonic-gate /* 13587c478bd9Sstevel@tonic-gate ** SM_LDAP_SETOPTS -- set LDAP options 13597c478bd9Sstevel@tonic-gate ** 13607c478bd9Sstevel@tonic-gate ** Parameters: 13617c478bd9Sstevel@tonic-gate ** ld -- LDAP session handle 13627c478bd9Sstevel@tonic-gate ** lmap -- LDAP map information 13637c478bd9Sstevel@tonic-gate ** 13647c478bd9Sstevel@tonic-gate ** Returns: 13657c478bd9Sstevel@tonic-gate ** None. 13667c478bd9Sstevel@tonic-gate ** 13677c478bd9Sstevel@tonic-gate */ 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate void 13707c478bd9Sstevel@tonic-gate sm_ldap_setopts(ld, lmap) 13717c478bd9Sstevel@tonic-gate LDAP *ld; 13727c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 13737c478bd9Sstevel@tonic-gate { 13747c478bd9Sstevel@tonic-gate # if USE_LDAP_SET_OPTION 13757c478bd9Sstevel@tonic-gate if (lmap->ldap_version != 0) 13767c478bd9Sstevel@tonic-gate { 13777c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, 13787c478bd9Sstevel@tonic-gate &lmap->ldap_version); 13797c478bd9Sstevel@tonic-gate } 13807c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); 13817c478bd9Sstevel@tonic-gate if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) 13827c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); 13837c478bd9Sstevel@tonic-gate else 13847c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 13857c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); 13867c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); 13877800901eSjbeck # if _FFR_LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) 1388*e9af4bc0SJohn Beck if (lmap->ldap_networktmo > 0) 1389*e9af4bc0SJohn Beck { 1390*e9af4bc0SJohn Beck struct timeval tmo; 1391*e9af4bc0SJohn Beck 1392*e9af4bc0SJohn Beck tmo.tv_sec = lmap->ldap_networktmo; 1393*e9af4bc0SJohn Beck tmo.tv_usec = 0; 1394*e9af4bc0SJohn Beck ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tmo); 1395*e9af4bc0SJohn Beck } 13967800901eSjbeck # endif /* _FFR_LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) */ 13977c478bd9Sstevel@tonic-gate # ifdef LDAP_OPT_RESTART 13987c478bd9Sstevel@tonic-gate ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); 13997c478bd9Sstevel@tonic-gate # endif /* LDAP_OPT_RESTART */ 14007c478bd9Sstevel@tonic-gate # else /* USE_LDAP_SET_OPTION */ 14017c478bd9Sstevel@tonic-gate /* From here on in we can use ldap internal timelimits */ 14027c478bd9Sstevel@tonic-gate ld->ld_deref = lmap->ldap_deref; 14037c478bd9Sstevel@tonic-gate ld->ld_options = lmap->ldap_options; 14047c478bd9Sstevel@tonic-gate ld->ld_sizelimit = lmap->ldap_sizelimit; 14057c478bd9Sstevel@tonic-gate ld->ld_timelimit = lmap->ldap_timelimit; 14067c478bd9Sstevel@tonic-gate # endif /* USE_LDAP_SET_OPTION */ 14077c478bd9Sstevel@tonic-gate } 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate /* 14107c478bd9Sstevel@tonic-gate ** SM_LDAP_GETERRNO -- get ldap errno value 14117c478bd9Sstevel@tonic-gate ** 14127c478bd9Sstevel@tonic-gate ** Parameters: 14137c478bd9Sstevel@tonic-gate ** ld -- LDAP session handle 14147c478bd9Sstevel@tonic-gate ** 14157c478bd9Sstevel@tonic-gate ** Returns: 14167c478bd9Sstevel@tonic-gate ** LDAP errno. 14177c478bd9Sstevel@tonic-gate ** 14187c478bd9Sstevel@tonic-gate */ 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate int 14217c478bd9Sstevel@tonic-gate sm_ldap_geterrno(ld) 14227c478bd9Sstevel@tonic-gate LDAP *ld; 14237c478bd9Sstevel@tonic-gate { 14247c478bd9Sstevel@tonic-gate int err = LDAP_SUCCESS; 14257c478bd9Sstevel@tonic-gate 14267c478bd9Sstevel@tonic-gate # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 14277c478bd9Sstevel@tonic-gate (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); 14287c478bd9Sstevel@tonic-gate # else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 14297c478bd9Sstevel@tonic-gate # ifdef LDAP_OPT_SIZELIMIT 14307c478bd9Sstevel@tonic-gate err = ldap_get_lderrno(ld, NULL, NULL); 14317c478bd9Sstevel@tonic-gate # else /* LDAP_OPT_SIZELIMIT */ 14327c478bd9Sstevel@tonic-gate err = ld->ld_errno; 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate /* 14357c478bd9Sstevel@tonic-gate ** Reset value to prevent lingering LDAP_DECODING_ERROR due to 14367c478bd9Sstevel@tonic-gate ** OpenLDAP 1.X's hack (see above) 14377c478bd9Sstevel@tonic-gate */ 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate ld->ld_errno = LDAP_SUCCESS; 14407c478bd9Sstevel@tonic-gate # endif /* LDAP_OPT_SIZELIMIT */ 14417c478bd9Sstevel@tonic-gate # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 14427c478bd9Sstevel@tonic-gate return err; 14437c478bd9Sstevel@tonic-gate } 14447c478bd9Sstevel@tonic-gate # endif /* LDAPMAP */ 1445