140266059SGregory Neil Shapiro /* 213d88268SGregory Neil Shapiro * Copyright (c) 2001-2005 Sendmail, Inc. and its suppliers. 340266059SGregory Neil Shapiro * All rights reserved. 440266059SGregory Neil Shapiro * 540266059SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set 640266059SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of 740266059SGregory Neil Shapiro * the sendmail distribution. 840266059SGregory Neil Shapiro */ 940266059SGregory Neil Shapiro 1040266059SGregory Neil Shapiro #include <sm/gen.h> 1113d88268SGregory Neil Shapiro SM_RCSID("@(#)$Id: ldap.c,v 1.62 2005/02/24 00:30:01 ca Exp $") 1240266059SGregory Neil Shapiro 1340266059SGregory Neil Shapiro #if LDAPMAP 1440266059SGregory Neil Shapiro # include <sys/types.h> 1540266059SGregory Neil Shapiro # include <errno.h> 1640266059SGregory Neil Shapiro # include <setjmp.h> 1740266059SGregory Neil Shapiro # include <stdlib.h> 1840266059SGregory Neil Shapiro # include <unistd.h> 1940266059SGregory Neil Shapiro 2040266059SGregory Neil Shapiro # include <sm/bitops.h> 2140266059SGregory Neil Shapiro # include <sm/clock.h> 2240266059SGregory Neil Shapiro # include <sm/conf.h> 2340266059SGregory Neil Shapiro # include <sm/debug.h> 2440266059SGregory Neil Shapiro # include <sm/errstring.h> 2540266059SGregory Neil Shapiro # include <sm/ldap.h> 2640266059SGregory Neil Shapiro # include <sm/string.h> 27605302a5SGregory Neil Shapiro # ifdef EX_OK 28605302a5SGregory Neil Shapiro # undef EX_OK /* for SVr4.2 SMP */ 29605302a5SGregory Neil Shapiro # endif /* EX_OK */ 3040266059SGregory Neil Shapiro # include <sm/sysexits.h> 3140266059SGregory Neil Shapiro 3240266059SGregory Neil Shapiro SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap", 3340266059SGregory Neil Shapiro "@(#)$Debug: sm_trace_ldap - trace LDAP operations $"); 3440266059SGregory Neil Shapiro 3540266059SGregory Neil Shapiro static void ldaptimeout __P((int)); 36b6bacd31SGregory Neil Shapiro static bool sm_ldap_has_objectclass __P((SM_LDAP_STRUCT *, LDAPMessage *, char *)); 37b6bacd31SGregory Neil Shapiro static SM_LDAP_RECURSE_ENTRY *sm_ldap_add_recurse __P((SM_LDAP_RECURSE_LIST **, char *, int, SM_RPOOL_T *)); 3840266059SGregory Neil Shapiro 3940266059SGregory Neil Shapiro /* 4040266059SGregory Neil Shapiro ** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT 4140266059SGregory Neil Shapiro ** 4240266059SGregory Neil Shapiro ** Parameters: 4340266059SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT to clear 4440266059SGregory Neil Shapiro ** 4540266059SGregory Neil Shapiro ** Returns: 4640266059SGregory Neil Shapiro ** None. 4740266059SGregory Neil Shapiro ** 4840266059SGregory Neil Shapiro */ 4940266059SGregory Neil Shapiro 5040266059SGregory Neil Shapiro void 5140266059SGregory Neil Shapiro sm_ldap_clear(lmap) 5240266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 5340266059SGregory Neil Shapiro { 5440266059SGregory Neil Shapiro if (lmap == NULL) 5540266059SGregory Neil Shapiro return; 5640266059SGregory Neil Shapiro 57e92d3f3fSGregory Neil Shapiro lmap->ldap_host = NULL; 5840266059SGregory Neil Shapiro lmap->ldap_port = LDAP_PORT; 59e92d3f3fSGregory Neil Shapiro lmap->ldap_uri = NULL; 60605302a5SGregory Neil Shapiro lmap->ldap_version = 0; 6140266059SGregory Neil Shapiro lmap->ldap_deref = LDAP_DEREF_NEVER; 6240266059SGregory Neil Shapiro lmap->ldap_timelimit = LDAP_NO_LIMIT; 6340266059SGregory Neil Shapiro lmap->ldap_sizelimit = LDAP_NO_LIMIT; 6440266059SGregory Neil Shapiro # ifdef LDAP_REFERRALS 6540266059SGregory Neil Shapiro lmap->ldap_options = LDAP_OPT_REFERRALS; 6640266059SGregory Neil Shapiro # else /* LDAP_REFERRALS */ 6740266059SGregory Neil Shapiro lmap->ldap_options = 0; 6840266059SGregory Neil Shapiro # endif /* LDAP_REFERRALS */ 6940266059SGregory Neil Shapiro lmap->ldap_attrsep = '\0'; 7040266059SGregory Neil Shapiro lmap->ldap_binddn = NULL; 7140266059SGregory Neil Shapiro lmap->ldap_secret = NULL; 7240266059SGregory Neil Shapiro lmap->ldap_method = LDAP_AUTH_SIMPLE; 7340266059SGregory Neil Shapiro lmap->ldap_base = NULL; 7440266059SGregory Neil Shapiro lmap->ldap_scope = LDAP_SCOPE_SUBTREE; 7540266059SGregory Neil Shapiro lmap->ldap_attrsonly = LDAPMAP_FALSE; 7640266059SGregory Neil Shapiro lmap->ldap_timeout.tv_sec = 0; 7740266059SGregory Neil Shapiro lmap->ldap_timeout.tv_usec = 0; 7840266059SGregory Neil Shapiro lmap->ldap_ld = NULL; 7940266059SGregory Neil Shapiro lmap->ldap_filter = NULL; 8040266059SGregory Neil Shapiro lmap->ldap_attr[0] = NULL; 81605302a5SGregory Neil Shapiro lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE; 82605302a5SGregory Neil Shapiro lmap->ldap_attr_needobjclass[0] = NULL; 8340266059SGregory Neil Shapiro lmap->ldap_res = NULL; 8440266059SGregory Neil Shapiro lmap->ldap_next = NULL; 8540266059SGregory Neil Shapiro lmap->ldap_pid = 0; 8640266059SGregory Neil Shapiro } 8740266059SGregory Neil Shapiro 8840266059SGregory Neil Shapiro /* 8940266059SGregory Neil Shapiro ** SM_LDAP_START -- actually connect to an LDAP server 9040266059SGregory Neil Shapiro ** 9140266059SGregory Neil Shapiro ** Parameters: 9240266059SGregory Neil Shapiro ** name -- name of map for debug output. 9340266059SGregory Neil Shapiro ** lmap -- the LDAP map being opened. 9440266059SGregory Neil Shapiro ** 9540266059SGregory Neil Shapiro ** Returns: 9640266059SGregory Neil Shapiro ** true if connection is successful, false otherwise. 9740266059SGregory Neil Shapiro ** 9840266059SGregory Neil Shapiro ** Side Effects: 9940266059SGregory Neil Shapiro ** Populates lmap->ldap_ld. 10040266059SGregory Neil Shapiro */ 10140266059SGregory Neil Shapiro 10240266059SGregory Neil Shapiro static jmp_buf LDAPTimeout; 10340266059SGregory Neil Shapiro 10440266059SGregory Neil Shapiro #define SM_LDAP_SETTIMEOUT(to) \ 10540266059SGregory Neil Shapiro do \ 10640266059SGregory Neil Shapiro { \ 10740266059SGregory Neil Shapiro if (to != 0) \ 10840266059SGregory Neil Shapiro { \ 10940266059SGregory Neil Shapiro if (setjmp(LDAPTimeout) != 0) \ 11040266059SGregory Neil Shapiro { \ 11140266059SGregory Neil Shapiro errno = ETIMEDOUT; \ 11240266059SGregory Neil Shapiro return false; \ 11340266059SGregory Neil Shapiro } \ 11440266059SGregory Neil Shapiro ev = sm_setevent(to, ldaptimeout, 0); \ 11540266059SGregory Neil Shapiro } \ 11640266059SGregory Neil Shapiro } while (0) 11740266059SGregory Neil Shapiro 11840266059SGregory Neil Shapiro #define SM_LDAP_CLEARTIMEOUT() \ 11940266059SGregory Neil Shapiro do \ 12040266059SGregory Neil Shapiro { \ 12140266059SGregory Neil Shapiro if (ev != NULL) \ 12240266059SGregory Neil Shapiro sm_clrevent(ev); \ 12340266059SGregory Neil Shapiro } while (0) 12440266059SGregory Neil Shapiro 12540266059SGregory Neil Shapiro bool 12640266059SGregory Neil Shapiro sm_ldap_start(name, lmap) 12740266059SGregory Neil Shapiro char *name; 12840266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 12940266059SGregory Neil Shapiro { 13040266059SGregory Neil Shapiro int bind_result; 131b6bacd31SGregory Neil Shapiro int save_errno = 0; 132e92d3f3fSGregory Neil Shapiro char *id; 13340266059SGregory Neil Shapiro SM_EVENT *ev = NULL; 134e92d3f3fSGregory Neil Shapiro LDAP *ld = NULL; 13540266059SGregory Neil Shapiro 13640266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 2)) 13740266059SGregory Neil Shapiro sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name); 13840266059SGregory Neil Shapiro 139e92d3f3fSGregory Neil Shapiro if (lmap->ldap_host != NULL) 140e92d3f3fSGregory Neil Shapiro id = lmap->ldap_host; 141e92d3f3fSGregory Neil Shapiro else if (lmap->ldap_uri != NULL) 142e92d3f3fSGregory Neil Shapiro id = lmap->ldap_uri; 143605302a5SGregory Neil Shapiro else 144e92d3f3fSGregory Neil Shapiro id = "localhost"; 145e92d3f3fSGregory Neil Shapiro 146e92d3f3fSGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 147e92d3f3fSGregory Neil Shapiro { 148e92d3f3fSGregory Neil Shapiro /* Don't print a port number for LDAP URIs */ 149e92d3f3fSGregory Neil Shapiro if (lmap->ldap_uri != NULL) 150e92d3f3fSGregory Neil Shapiro sm_dprintf("ldapmap_start(%s)\n", id); 151e92d3f3fSGregory Neil Shapiro else 152e92d3f3fSGregory Neil Shapiro sm_dprintf("ldapmap_start(%s, %d)\n", id, 153e92d3f3fSGregory Neil Shapiro lmap->ldap_port); 154e92d3f3fSGregory Neil Shapiro } 155e92d3f3fSGregory Neil Shapiro 156e92d3f3fSGregory Neil Shapiro if (lmap->ldap_uri != NULL) 157e92d3f3fSGregory Neil Shapiro { 158e92d3f3fSGregory Neil Shapiro #if SM_CONF_LDAP_INITIALIZE 159e92d3f3fSGregory Neil Shapiro /* LDAP server supports URIs so use them directly */ 160e92d3f3fSGregory Neil Shapiro save_errno = ldap_initialize(&ld, lmap->ldap_uri); 161e92d3f3fSGregory Neil Shapiro #else /* SM_CONF_LDAP_INITIALIZE */ 162e92d3f3fSGregory Neil Shapiro int err; 163e92d3f3fSGregory Neil Shapiro LDAPURLDesc *ludp = NULL; 164e92d3f3fSGregory Neil Shapiro 165e92d3f3fSGregory Neil Shapiro /* Blast apart URL and use the ldap_init/ldap_open below */ 166e92d3f3fSGregory Neil Shapiro err = ldap_url_parse(lmap->ldap_uri, &ludp); 167e92d3f3fSGregory Neil Shapiro if (err != 0) 168e92d3f3fSGregory Neil Shapiro { 169e92d3f3fSGregory Neil Shapiro errno = err + E_LDAPURLBASE; 170e92d3f3fSGregory Neil Shapiro return false; 171e92d3f3fSGregory Neil Shapiro } 172e92d3f3fSGregory Neil Shapiro lmap->ldap_host = sm_strdup_x(ludp->lud_host); 173e92d3f3fSGregory Neil Shapiro if (lmap->ldap_host == NULL) 174e92d3f3fSGregory Neil Shapiro { 175e92d3f3fSGregory Neil Shapiro save_errno = errno; 176e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(ludp); 177e92d3f3fSGregory Neil Shapiro errno = save_errno; 178e92d3f3fSGregory Neil Shapiro return false; 179e92d3f3fSGregory Neil Shapiro } 180e92d3f3fSGregory Neil Shapiro lmap->ldap_port = ludp->lud_port; 181e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(ludp); 182e92d3f3fSGregory Neil Shapiro #endif /* SM_CONF_LDAP_INITIALIZE */ 183e92d3f3fSGregory Neil Shapiro } 184e92d3f3fSGregory Neil Shapiro 185e92d3f3fSGregory Neil Shapiro if (ld == NULL) 186e92d3f3fSGregory Neil Shapiro { 187e92d3f3fSGregory Neil Shapiro # if USE_LDAP_INIT 188e92d3f3fSGregory Neil Shapiro ld = ldap_init(lmap->ldap_host, lmap->ldap_port); 18940266059SGregory Neil Shapiro save_errno = errno; 19040266059SGregory Neil Shapiro # else /* USE_LDAP_INIT */ 19140266059SGregory Neil Shapiro /* 19240266059SGregory Neil Shapiro ** If using ldap_open(), the actual connection to the server 19340266059SGregory Neil Shapiro ** happens now so we need the timeout here. For ldap_init(), 19440266059SGregory Neil Shapiro ** the connection happens at bind time. 19540266059SGregory Neil Shapiro */ 19640266059SGregory Neil Shapiro 19740266059SGregory Neil Shapiro SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); 198e92d3f3fSGregory Neil Shapiro ld = ldap_open(lmap->ldap_host, lmap->ldap_port); 19940266059SGregory Neil Shapiro save_errno = errno; 20040266059SGregory Neil Shapiro 20140266059SGregory Neil Shapiro /* clear the event if it has not sprung */ 20240266059SGregory Neil Shapiro SM_LDAP_CLEARTIMEOUT(); 20340266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 204e92d3f3fSGregory Neil Shapiro } 20540266059SGregory Neil Shapiro 20640266059SGregory Neil Shapiro errno = save_errno; 20740266059SGregory Neil Shapiro if (ld == NULL) 20840266059SGregory Neil Shapiro return false; 20940266059SGregory Neil Shapiro 21040266059SGregory Neil Shapiro sm_ldap_setopts(ld, lmap); 21140266059SGregory Neil Shapiro 21240266059SGregory Neil Shapiro # if USE_LDAP_INIT 21340266059SGregory Neil Shapiro /* 21440266059SGregory Neil Shapiro ** If using ldap_init(), the actual connection to the server 21540266059SGregory Neil Shapiro ** happens at ldap_bind_s() so we need the timeout here. 21640266059SGregory Neil Shapiro */ 21740266059SGregory Neil Shapiro 21840266059SGregory Neil Shapiro SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); 21940266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 22040266059SGregory Neil Shapiro 22140266059SGregory Neil Shapiro # ifdef LDAP_AUTH_KRBV4 22240266059SGregory Neil Shapiro if (lmap->ldap_method == LDAP_AUTH_KRBV4 && 22340266059SGregory Neil Shapiro lmap->ldap_secret != NULL) 22440266059SGregory Neil Shapiro { 22540266059SGregory Neil Shapiro /* 22640266059SGregory Neil Shapiro ** Need to put ticket in environment here instead of 22740266059SGregory Neil Shapiro ** during parseargs as there may be different tickets 22840266059SGregory Neil Shapiro ** for different LDAP connections. 22940266059SGregory Neil Shapiro */ 23040266059SGregory Neil Shapiro 23140266059SGregory Neil Shapiro (void) putenv(lmap->ldap_secret); 23240266059SGregory Neil Shapiro } 23340266059SGregory Neil Shapiro # endif /* LDAP_AUTH_KRBV4 */ 23440266059SGregory Neil Shapiro 23540266059SGregory Neil Shapiro bind_result = ldap_bind_s(ld, lmap->ldap_binddn, 23640266059SGregory Neil Shapiro lmap->ldap_secret, lmap->ldap_method); 23740266059SGregory Neil Shapiro 23840266059SGregory Neil Shapiro # if USE_LDAP_INIT 23940266059SGregory Neil Shapiro /* clear the event if it has not sprung */ 24040266059SGregory Neil Shapiro SM_LDAP_CLEARTIMEOUT(); 24140266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 24240266059SGregory Neil Shapiro 24340266059SGregory Neil Shapiro if (bind_result != LDAP_SUCCESS) 24440266059SGregory Neil Shapiro { 24540266059SGregory Neil Shapiro errno = bind_result + E_LDAPBASE; 24640266059SGregory Neil Shapiro return false; 24740266059SGregory Neil Shapiro } 24840266059SGregory Neil Shapiro 24940266059SGregory Neil Shapiro /* Save PID to make sure only this PID closes the LDAP connection */ 25040266059SGregory Neil Shapiro lmap->ldap_pid = getpid(); 25140266059SGregory Neil Shapiro lmap->ldap_ld = ld; 25240266059SGregory Neil Shapiro return true; 25340266059SGregory Neil Shapiro } 25440266059SGregory Neil Shapiro 25540266059SGregory Neil Shapiro /* ARGSUSED */ 25640266059SGregory Neil Shapiro static void 25740266059SGregory Neil Shapiro ldaptimeout(unused) 25840266059SGregory Neil Shapiro int unused; 25940266059SGregory Neil Shapiro { 26040266059SGregory Neil Shapiro /* 26140266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 26240266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 26340266059SGregory Neil Shapiro ** DOING. 26440266059SGregory Neil Shapiro */ 26540266059SGregory Neil Shapiro 26640266059SGregory Neil Shapiro errno = ETIMEDOUT; 26740266059SGregory Neil Shapiro longjmp(LDAPTimeout, 1); 26840266059SGregory Neil Shapiro } 26940266059SGregory Neil Shapiro 27040266059SGregory Neil Shapiro /* 271e92d3f3fSGregory Neil Shapiro ** SM_LDAP_SEARCH -- initiate LDAP search 27240266059SGregory Neil Shapiro ** 27340266059SGregory Neil Shapiro ** Initiate an LDAP search, return the msgid. 27440266059SGregory Neil Shapiro ** The calling function must collect the results. 27540266059SGregory Neil Shapiro ** 27640266059SGregory Neil Shapiro ** Parameters: 27740266059SGregory Neil Shapiro ** lmap -- LDAP map information 27840266059SGregory Neil Shapiro ** key -- key to substitute in LDAP filter 27940266059SGregory Neil Shapiro ** 28040266059SGregory Neil Shapiro ** Returns: 28140266059SGregory Neil Shapiro ** -1 on failure, msgid on success 28240266059SGregory Neil Shapiro ** 28340266059SGregory Neil Shapiro */ 28440266059SGregory Neil Shapiro 28540266059SGregory Neil Shapiro int 28640266059SGregory Neil Shapiro sm_ldap_search(lmap, key) 28740266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 28840266059SGregory Neil Shapiro char *key; 28940266059SGregory Neil Shapiro { 29040266059SGregory Neil Shapiro int msgid; 29140266059SGregory Neil Shapiro char *fp, *p, *q; 29240266059SGregory Neil Shapiro char filter[LDAPMAP_MAX_FILTER + 1]; 29340266059SGregory Neil Shapiro 29440266059SGregory Neil Shapiro /* substitute key into filter, perhaps multiple times */ 29540266059SGregory Neil Shapiro memset(filter, '\0', sizeof filter); 29640266059SGregory Neil Shapiro fp = filter; 29740266059SGregory Neil Shapiro p = lmap->ldap_filter; 29840266059SGregory Neil Shapiro while ((q = strchr(p, '%')) != NULL) 29940266059SGregory Neil Shapiro { 30040266059SGregory Neil Shapiro if (q[1] == 's') 30140266059SGregory Neil Shapiro { 30240266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 30340266059SGregory Neil Shapiro "%.*s%s", (int) (q - p), p, key); 30440266059SGregory Neil Shapiro fp += strlen(fp); 30540266059SGregory Neil Shapiro p = q + 2; 30640266059SGregory Neil Shapiro } 30740266059SGregory Neil Shapiro else if (q[1] == '0') 30840266059SGregory Neil Shapiro { 30940266059SGregory Neil Shapiro char *k = key; 31040266059SGregory Neil Shapiro 31140266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 31240266059SGregory Neil Shapiro "%.*s", (int) (q - p), p); 31340266059SGregory Neil Shapiro fp += strlen(fp); 31440266059SGregory Neil Shapiro p = q + 2; 31540266059SGregory Neil Shapiro 31640266059SGregory Neil Shapiro /* Properly escape LDAP special characters */ 31740266059SGregory Neil Shapiro while (SPACELEFT(filter, fp) > 0 && 31840266059SGregory Neil Shapiro *k != '\0') 31940266059SGregory Neil Shapiro { 32040266059SGregory Neil Shapiro if (*k == '*' || *k == '(' || 32140266059SGregory Neil Shapiro *k == ')' || *k == '\\') 32240266059SGregory Neil Shapiro { 32340266059SGregory Neil Shapiro (void) sm_strlcat(fp, 32440266059SGregory Neil Shapiro (*k == '*' ? "\\2A" : 32540266059SGregory Neil Shapiro (*k == '(' ? "\\28" : 32640266059SGregory Neil Shapiro (*k == ')' ? "\\29" : 32740266059SGregory Neil Shapiro (*k == '\\' ? "\\5C" : 32840266059SGregory Neil Shapiro "\00")))), 32940266059SGregory Neil Shapiro SPACELEFT(filter, fp)); 33040266059SGregory Neil Shapiro fp += strlen(fp); 33140266059SGregory Neil Shapiro k++; 33240266059SGregory Neil Shapiro } 33340266059SGregory Neil Shapiro else 33440266059SGregory Neil Shapiro *fp++ = *k++; 33540266059SGregory Neil Shapiro } 33640266059SGregory Neil Shapiro } 33740266059SGregory Neil Shapiro else 33840266059SGregory Neil Shapiro { 33940266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 34040266059SGregory Neil Shapiro "%.*s", (int) (q - p + 1), p); 34140266059SGregory Neil Shapiro p = q + (q[1] == '%' ? 2 : 1); 34240266059SGregory Neil Shapiro fp += strlen(fp); 34340266059SGregory Neil Shapiro } 34440266059SGregory Neil Shapiro } 34540266059SGregory Neil Shapiro (void) sm_strlcpy(fp, p, SPACELEFT(filter, fp)); 34640266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 20)) 34740266059SGregory Neil Shapiro sm_dprintf("ldap search filter=%s\n", filter); 34840266059SGregory Neil Shapiro 34940266059SGregory Neil Shapiro lmap->ldap_res = NULL; 350605302a5SGregory Neil Shapiro msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, 351605302a5SGregory Neil Shapiro lmap->ldap_scope, filter, 35240266059SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? NULL : 35340266059SGregory Neil Shapiro lmap->ldap_attr), 35440266059SGregory Neil Shapiro lmap->ldap_attrsonly); 35540266059SGregory Neil Shapiro return msgid; 35640266059SGregory Neil Shapiro } 35740266059SGregory Neil Shapiro 35840266059SGregory Neil Shapiro /* 359605302a5SGregory Neil Shapiro ** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a 360605302a5SGregory Neil Shapiro ** particular objectClass 361605302a5SGregory Neil Shapiro ** 362605302a5SGregory Neil Shapiro ** Parameters: 363605302a5SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT in use 364605302a5SGregory Neil Shapiro ** entry -- current LDAP entry struct 365605302a5SGregory Neil Shapiro ** ocvalue -- particular objectclass in question. 366605302a5SGregory Neil Shapiro ** may be of form (fee|foo|fum) meaning 367605302a5SGregory Neil Shapiro ** any entry can be part of either fee, 368605302a5SGregory Neil Shapiro ** foo or fum objectclass 369605302a5SGregory Neil Shapiro ** 370605302a5SGregory Neil Shapiro ** Returns: 371605302a5SGregory Neil Shapiro ** true if item has that objectClass 372605302a5SGregory Neil Shapiro */ 373605302a5SGregory Neil Shapiro 374605302a5SGregory Neil Shapiro static bool 375605302a5SGregory Neil Shapiro sm_ldap_has_objectclass(lmap, entry, ocvalue) 376605302a5SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 377605302a5SGregory Neil Shapiro LDAPMessage *entry; 378605302a5SGregory Neil Shapiro char *ocvalue; 379605302a5SGregory Neil Shapiro { 380605302a5SGregory Neil Shapiro char **vals = NULL; 381605302a5SGregory Neil Shapiro int i; 382605302a5SGregory Neil Shapiro 383605302a5SGregory Neil Shapiro if (ocvalue == NULL) 384605302a5SGregory Neil Shapiro return false; 385605302a5SGregory Neil Shapiro 386605302a5SGregory Neil Shapiro vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass"); 387605302a5SGregory Neil Shapiro if (vals == NULL) 388605302a5SGregory Neil Shapiro return false; 389605302a5SGregory Neil Shapiro 390605302a5SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 391605302a5SGregory Neil Shapiro { 392605302a5SGregory Neil Shapiro char *p; 393605302a5SGregory Neil Shapiro char *q; 394605302a5SGregory Neil Shapiro 395605302a5SGregory Neil Shapiro p = q = ocvalue; 396605302a5SGregory Neil Shapiro while (*p != '\0') 397605302a5SGregory Neil Shapiro { 398605302a5SGregory Neil Shapiro while (*p != '\0' && *p != '|') 399605302a5SGregory Neil Shapiro p++; 400605302a5SGregory Neil Shapiro 401605302a5SGregory Neil Shapiro if ((p - q) == strlen(vals[i]) && 402605302a5SGregory Neil Shapiro sm_strncasecmp(vals[i], q, p - q) == 0) 403605302a5SGregory Neil Shapiro { 404605302a5SGregory Neil Shapiro ldap_value_free(vals); 405605302a5SGregory Neil Shapiro return true; 406605302a5SGregory Neil Shapiro } 407605302a5SGregory Neil Shapiro 408605302a5SGregory Neil Shapiro while (*p == '|') 409605302a5SGregory Neil Shapiro p++; 410605302a5SGregory Neil Shapiro q = p; 411605302a5SGregory Neil Shapiro } 412605302a5SGregory Neil Shapiro } 413605302a5SGregory Neil Shapiro 414605302a5SGregory Neil Shapiro ldap_value_free(vals); 415605302a5SGregory Neil Shapiro return false; 416605302a5SGregory Neil Shapiro } 417605302a5SGregory Neil Shapiro 418605302a5SGregory Neil Shapiro /* 41940266059SGregory Neil Shapiro ** SM_LDAP_RESULTS -- return results from an LDAP lookup in result 42040266059SGregory Neil Shapiro ** 42140266059SGregory Neil Shapiro ** Parameters: 42240266059SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT in use 42340266059SGregory Neil Shapiro ** msgid -- msgid returned by sm_ldap_search() 42440266059SGregory Neil Shapiro ** flags -- flags for the lookup 42540266059SGregory Neil Shapiro ** delim -- delimiter for result concatenation 42640266059SGregory Neil Shapiro ** rpool -- memory pool for storage 42740266059SGregory Neil Shapiro ** result -- return string 42840266059SGregory Neil Shapiro ** recurse -- recursion list 42940266059SGregory Neil Shapiro ** 43040266059SGregory Neil Shapiro ** Returns: 43140266059SGregory Neil Shapiro ** status (sysexit) 43240266059SGregory Neil Shapiro */ 43340266059SGregory Neil Shapiro 434605302a5SGregory Neil Shapiro # define SM_LDAP_ERROR_CLEANUP() \ 43540266059SGregory Neil Shapiro { \ 43640266059SGregory Neil Shapiro if (lmap->ldap_res != NULL) \ 43740266059SGregory Neil Shapiro { \ 43840266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); \ 43940266059SGregory Neil Shapiro lmap->ldap_res = NULL; \ 44040266059SGregory Neil Shapiro } \ 44140266059SGregory Neil Shapiro (void) ldap_abandon(lmap->ldap_ld, msgid); \ 44240266059SGregory Neil Shapiro } 44340266059SGregory Neil Shapiro 444605302a5SGregory Neil Shapiro static SM_LDAP_RECURSE_ENTRY * 445605302a5SGregory Neil Shapiro sm_ldap_add_recurse(top, item, type, rpool) 44640266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST **top; 44740266059SGregory Neil Shapiro char *item; 44840266059SGregory Neil Shapiro int type; 44940266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 45040266059SGregory Neil Shapiro { 451605302a5SGregory Neil Shapiro int n; 452605302a5SGregory Neil Shapiro int m; 453605302a5SGregory Neil Shapiro int p; 454605302a5SGregory Neil Shapiro int insertat; 455605302a5SGregory Neil Shapiro int moveb; 456605302a5SGregory Neil Shapiro int oldsizeb; 457605302a5SGregory Neil Shapiro int rc; 458605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY *newe; 459605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY **olddata; 46040266059SGregory Neil Shapiro 461605302a5SGregory Neil Shapiro /* 462605302a5SGregory Neil Shapiro ** This code will maintain a list of 463605302a5SGregory Neil Shapiro ** SM_LDAP_RECURSE_ENTRY structures 464605302a5SGregory Neil Shapiro ** in ascending order. 465605302a5SGregory Neil Shapiro */ 466605302a5SGregory Neil Shapiro 467605302a5SGregory Neil Shapiro if (*top == NULL) 46840266059SGregory Neil Shapiro { 469605302a5SGregory Neil Shapiro /* Allocate an initial SM_LDAP_RECURSE_LIST struct */ 470605302a5SGregory Neil Shapiro *top = sm_rpool_malloc_x(rpool, sizeof **top); 471605302a5SGregory Neil Shapiro (*top)->lr_cnt = 0; 472605302a5SGregory Neil Shapiro (*top)->lr_size = 0; 473605302a5SGregory Neil Shapiro (*top)->lr_data = NULL; 47440266059SGregory Neil Shapiro } 47540266059SGregory Neil Shapiro 476605302a5SGregory Neil Shapiro if ((*top)->lr_cnt >= (*top)->lr_size) 477605302a5SGregory Neil Shapiro { 478605302a5SGregory Neil Shapiro /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */ 479605302a5SGregory Neil Shapiro olddata = (*top)->lr_data; 480605302a5SGregory Neil Shapiro if ((*top)->lr_size == 0) 481605302a5SGregory Neil Shapiro { 482605302a5SGregory Neil Shapiro oldsizeb = 0; 483605302a5SGregory Neil Shapiro (*top)->lr_size = 256; 484605302a5SGregory Neil Shapiro } 48540266059SGregory Neil Shapiro else 486605302a5SGregory Neil Shapiro { 487605302a5SGregory Neil Shapiro oldsizeb = (*top)->lr_size * sizeof *((*top)->lr_data); 488605302a5SGregory Neil Shapiro (*top)->lr_size *= 2; 489605302a5SGregory Neil Shapiro } 490605302a5SGregory Neil Shapiro (*top)->lr_data = sm_rpool_malloc_x(rpool, 491605302a5SGregory Neil Shapiro (*top)->lr_size * sizeof *((*top)->lr_data)); 492605302a5SGregory Neil Shapiro if (oldsizeb > 0) 493605302a5SGregory Neil Shapiro memcpy((*top)->lr_data, olddata, oldsizeb); 494605302a5SGregory Neil Shapiro } 495605302a5SGregory Neil Shapiro 496605302a5SGregory Neil Shapiro /* 497605302a5SGregory Neil Shapiro ** Binary search/insert item:type into list. 498605302a5SGregory Neil Shapiro ** Return current entry pointer if already exists. 499605302a5SGregory Neil Shapiro */ 500605302a5SGregory Neil Shapiro 501605302a5SGregory Neil Shapiro n = 0; 502605302a5SGregory Neil Shapiro m = (*top)->lr_cnt - 1; 503605302a5SGregory Neil Shapiro if (m < 0) 504605302a5SGregory Neil Shapiro insertat = 0; 505605302a5SGregory Neil Shapiro else 506605302a5SGregory Neil Shapiro insertat = -1; 507605302a5SGregory Neil Shapiro 508605302a5SGregory Neil Shapiro while (insertat == -1) 509605302a5SGregory Neil Shapiro { 510605302a5SGregory Neil Shapiro p = (m + n) / 2; 511605302a5SGregory Neil Shapiro 512605302a5SGregory Neil Shapiro rc = sm_strcasecmp(item, (*top)->lr_data[p]->lr_search); 513605302a5SGregory Neil Shapiro if (rc == 0) 514605302a5SGregory Neil Shapiro rc = type - (*top)->lr_data[p]->lr_type; 515605302a5SGregory Neil Shapiro 516605302a5SGregory Neil Shapiro if (rc < 0) 517605302a5SGregory Neil Shapiro m = p - 1; 518605302a5SGregory Neil Shapiro else if (rc > 0) 519605302a5SGregory Neil Shapiro n = p + 1; 520605302a5SGregory Neil Shapiro else 521605302a5SGregory Neil Shapiro return (*top)->lr_data[p]; 522605302a5SGregory Neil Shapiro 523605302a5SGregory Neil Shapiro if (m == -1) 524605302a5SGregory Neil Shapiro insertat = 0; 525605302a5SGregory Neil Shapiro else if (n >= (*top)->lr_cnt) 526605302a5SGregory Neil Shapiro insertat = (*top)->lr_cnt; 527605302a5SGregory Neil Shapiro else if (m < n) 528605302a5SGregory Neil Shapiro insertat = m + 1; 529605302a5SGregory Neil Shapiro } 530605302a5SGregory Neil Shapiro 531605302a5SGregory Neil Shapiro /* 532605302a5SGregory Neil Shapiro ** Not found in list, make room 533605302a5SGregory Neil Shapiro ** at insert point and add it. 534605302a5SGregory Neil Shapiro */ 535605302a5SGregory Neil Shapiro 536605302a5SGregory Neil Shapiro newe = sm_rpool_malloc_x(rpool, sizeof *newe); 537605302a5SGregory Neil Shapiro if (newe != NULL) 538605302a5SGregory Neil Shapiro { 539605302a5SGregory Neil Shapiro moveb = ((*top)->lr_cnt - insertat) * sizeof *((*top)->lr_data); 540605302a5SGregory Neil Shapiro if (moveb > 0) 541605302a5SGregory Neil Shapiro memmove(&((*top)->lr_data[insertat + 1]), 542605302a5SGregory Neil Shapiro &((*top)->lr_data[insertat]), 543605302a5SGregory Neil Shapiro moveb); 544605302a5SGregory Neil Shapiro 545605302a5SGregory Neil Shapiro newe->lr_search = sm_rpool_strdup_x(rpool, item); 546605302a5SGregory Neil Shapiro newe->lr_type = type; 547e92d3f3fSGregory Neil Shapiro newe->lr_ludp = NULL; 548e92d3f3fSGregory Neil Shapiro newe->lr_attrs = NULL; 549605302a5SGregory Neil Shapiro newe->lr_done = false; 550605302a5SGregory Neil Shapiro 551605302a5SGregory Neil Shapiro ((*top)->lr_data)[insertat] = newe; 552605302a5SGregory Neil Shapiro (*top)->lr_cnt++; 553605302a5SGregory Neil Shapiro } 554605302a5SGregory Neil Shapiro return newe; 55540266059SGregory Neil Shapiro } 55640266059SGregory Neil Shapiro 55740266059SGregory Neil Shapiro int 558605302a5SGregory Neil Shapiro sm_ldap_results(lmap, msgid, flags, delim, rpool, result, 559605302a5SGregory Neil Shapiro resultln, resultsz, recurse) 56040266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 56140266059SGregory Neil Shapiro int msgid; 56240266059SGregory Neil Shapiro int flags; 563605302a5SGregory Neil Shapiro int delim; 56440266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 56540266059SGregory Neil Shapiro char **result; 566605302a5SGregory Neil Shapiro int *resultln; 567605302a5SGregory Neil Shapiro int *resultsz; 56840266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST *recurse; 56940266059SGregory Neil Shapiro { 57040266059SGregory Neil Shapiro bool toplevel; 57140266059SGregory Neil Shapiro int i; 57240266059SGregory Neil Shapiro int statp; 57340266059SGregory Neil Shapiro int vsize; 57440266059SGregory Neil Shapiro int ret; 57540266059SGregory Neil Shapiro int save_errno; 57640266059SGregory Neil Shapiro char *p; 577605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY *rl; 57840266059SGregory Neil Shapiro 57940266059SGregory Neil Shapiro /* Are we the top top level of the search? */ 58040266059SGregory Neil Shapiro toplevel = (recurse == NULL); 58140266059SGregory Neil Shapiro 58240266059SGregory Neil Shapiro /* Get results */ 58340266059SGregory Neil Shapiro statp = EX_NOTFOUND; 58440266059SGregory Neil Shapiro while ((ret = ldap_result(lmap->ldap_ld, msgid, 0, 58540266059SGregory Neil Shapiro (lmap->ldap_timeout.tv_sec == 0 ? NULL : 58640266059SGregory Neil Shapiro &(lmap->ldap_timeout)), 58740266059SGregory Neil Shapiro &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) 58840266059SGregory Neil Shapiro { 58940266059SGregory Neil Shapiro LDAPMessage *entry; 59040266059SGregory Neil Shapiro 59140266059SGregory Neil Shapiro /* If we don't want multiple values and we have one, break */ 59213d88268SGregory Neil Shapiro if ((char) delim == '\0' && 59313d88268SGregory Neil Shapiro !bitset(SM_LDAP_SINGLEMATCH, flags) && 59413d88268SGregory Neil Shapiro *result != NULL) 59540266059SGregory Neil Shapiro break; 59640266059SGregory Neil Shapiro 59740266059SGregory Neil Shapiro /* Cycle through all entries */ 59840266059SGregory Neil Shapiro for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); 59940266059SGregory Neil Shapiro entry != NULL; 60040266059SGregory Neil Shapiro entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) 60140266059SGregory Neil Shapiro { 60240266059SGregory Neil Shapiro BerElement *ber; 60340266059SGregory Neil Shapiro char *attr; 60440266059SGregory Neil Shapiro char **vals = NULL; 60540266059SGregory Neil Shapiro char *dn; 60640266059SGregory Neil Shapiro 60740266059SGregory Neil Shapiro /* 60840266059SGregory Neil Shapiro ** If matching only and found an entry, 60940266059SGregory Neil Shapiro ** no need to spin through attributes 61040266059SGregory Neil Shapiro */ 61140266059SGregory Neil Shapiro 612323f6dcbSGregory Neil Shapiro if (bitset(SM_LDAP_MATCHONLY, flags)) 613323f6dcbSGregory Neil Shapiro { 614323f6dcbSGregory Neil Shapiro statp = EX_OK; 61540266059SGregory Neil Shapiro continue; 616323f6dcbSGregory Neil Shapiro } 61740266059SGregory Neil Shapiro 61840266059SGregory Neil Shapiro /* record completed DN's to prevent loops */ 61940266059SGregory Neil Shapiro dn = ldap_get_dn(lmap->ldap_ld, entry); 62040266059SGregory Neil Shapiro if (dn == NULL) 62140266059SGregory Neil Shapiro { 62240266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 62340266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 624605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 62540266059SGregory Neil Shapiro errno = save_errno; 626a7ec597cSGregory Neil Shapiro return EX_TEMPFAIL; 62740266059SGregory Neil Shapiro } 62840266059SGregory Neil Shapiro 629605302a5SGregory Neil Shapiro rl = sm_ldap_add_recurse(&recurse, dn, 630605302a5SGregory Neil Shapiro SM_LDAP_ATTR_DN, 631605302a5SGregory Neil Shapiro rpool); 632605302a5SGregory Neil Shapiro 633605302a5SGregory Neil Shapiro if (rl == NULL) 63440266059SGregory Neil Shapiro { 63540266059SGregory Neil Shapiro ldap_memfree(dn); 636605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 63740266059SGregory Neil Shapiro errno = ENOMEM; 63840266059SGregory Neil Shapiro return EX_OSERR; 639605302a5SGregory Neil Shapiro } 640605302a5SGregory Neil Shapiro else if (rl->lr_done) 641605302a5SGregory Neil Shapiro { 64240266059SGregory Neil Shapiro /* already on list, skip it */ 64340266059SGregory Neil Shapiro ldap_memfree(dn); 64440266059SGregory Neil Shapiro continue; 64540266059SGregory Neil Shapiro } 64640266059SGregory Neil Shapiro ldap_memfree(dn); 64740266059SGregory Neil Shapiro 64840266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 64940266059SGregory Neil Shapiro /* 65040266059SGregory Neil Shapiro ** Reset value to prevent lingering 65140266059SGregory Neil Shapiro ** LDAP_DECODING_ERROR due to 65240266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see below) 65340266059SGregory Neil Shapiro */ 65440266059SGregory Neil Shapiro 65540266059SGregory Neil Shapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 65640266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 65740266059SGregory Neil Shapiro 65840266059SGregory Neil Shapiro for (attr = ldap_first_attribute(lmap->ldap_ld, entry, 65940266059SGregory Neil Shapiro &ber); 66040266059SGregory Neil Shapiro attr != NULL; 66140266059SGregory Neil Shapiro attr = ldap_next_attribute(lmap->ldap_ld, entry, 66240266059SGregory Neil Shapiro ber)) 66340266059SGregory Neil Shapiro { 66440266059SGregory Neil Shapiro char *tmp, *vp_tmp; 66540266059SGregory Neil Shapiro int type; 666605302a5SGregory Neil Shapiro char *needobjclass = NULL; 66740266059SGregory Neil Shapiro 668605302a5SGregory Neil Shapiro type = SM_LDAP_ATTR_NONE; 66940266059SGregory Neil Shapiro for (i = 0; lmap->ldap_attr[i] != NULL; i++) 67040266059SGregory Neil Shapiro { 67140266059SGregory Neil Shapiro if (sm_strcasecmp(lmap->ldap_attr[i], 67240266059SGregory Neil Shapiro attr) == 0) 67340266059SGregory Neil Shapiro { 67440266059SGregory Neil Shapiro type = lmap->ldap_attr_type[i]; 675605302a5SGregory Neil Shapiro needobjclass = lmap->ldap_attr_needobjclass[i]; 67640266059SGregory Neil Shapiro break; 67740266059SGregory Neil Shapiro } 67840266059SGregory Neil Shapiro } 679605302a5SGregory Neil Shapiro 680605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_USE_ALLATTR, flags) && 681605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_NONE) 682605302a5SGregory Neil Shapiro { 683605302a5SGregory Neil Shapiro /* URL lookups specify attrs to use */ 684605302a5SGregory Neil Shapiro type = SM_LDAP_ATTR_NORMAL; 685605302a5SGregory Neil Shapiro needobjclass = NULL; 686605302a5SGregory Neil Shapiro } 687605302a5SGregory Neil Shapiro 688605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NONE) 68940266059SGregory Neil Shapiro { 69040266059SGregory Neil Shapiro /* attribute not requested */ 69140266059SGregory Neil Shapiro ldap_memfree(attr); 692605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 69340266059SGregory Neil Shapiro errno = EFAULT; 69440266059SGregory Neil Shapiro return EX_SOFTWARE; 69540266059SGregory Neil Shapiro } 69640266059SGregory Neil Shapiro 697605302a5SGregory Neil Shapiro /* 698605302a5SGregory Neil Shapiro ** For recursion on a particular attribute, 699605302a5SGregory Neil Shapiro ** we may need to see if this entry is 700605302a5SGregory Neil Shapiro ** part of a particular objectclass. 701605302a5SGregory Neil Shapiro ** Also, ignore objectClass attribute. 702605302a5SGregory Neil Shapiro ** Otherwise we just ignore this attribute. 703605302a5SGregory Neil Shapiro */ 704605302a5SGregory Neil Shapiro 705605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_OBJCLASS || 706605302a5SGregory Neil Shapiro (needobjclass != NULL && 707605302a5SGregory Neil Shapiro !sm_ldap_has_objectclass(lmap, entry, 708605302a5SGregory Neil Shapiro needobjclass))) 709605302a5SGregory Neil Shapiro { 710605302a5SGregory Neil Shapiro ldap_memfree(attr); 711605302a5SGregory Neil Shapiro continue; 712605302a5SGregory Neil Shapiro } 713605302a5SGregory Neil Shapiro 71440266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 71540266059SGregory Neil Shapiro { 71640266059SGregory Neil Shapiro vals = ldap_get_values(lmap->ldap_ld, 71740266059SGregory Neil Shapiro entry, 71840266059SGregory Neil Shapiro attr); 71940266059SGregory Neil Shapiro if (vals == NULL) 72040266059SGregory Neil Shapiro { 72140266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 72240266059SGregory Neil Shapiro if (save_errno == LDAP_SUCCESS) 72340266059SGregory Neil Shapiro { 72440266059SGregory Neil Shapiro ldap_memfree(attr); 72540266059SGregory Neil Shapiro continue; 72640266059SGregory Neil Shapiro } 72740266059SGregory Neil Shapiro 72840266059SGregory Neil Shapiro /* Must be an error */ 72940266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 73040266059SGregory Neil Shapiro ldap_memfree(attr); 731605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 73240266059SGregory Neil Shapiro errno = save_errno; 73340266059SGregory Neil Shapiro return EX_TEMPFAIL; 73440266059SGregory Neil Shapiro } 73540266059SGregory Neil Shapiro } 73640266059SGregory Neil Shapiro 73740266059SGregory Neil Shapiro statp = EX_OK; 73840266059SGregory Neil Shapiro 73940266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 74040266059SGregory Neil Shapiro /* 74140266059SGregory Neil Shapiro ** Reset value to prevent lingering 74240266059SGregory Neil Shapiro ** LDAP_DECODING_ERROR due to 74340266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see below) 74440266059SGregory Neil Shapiro */ 74540266059SGregory Neil Shapiro 74640266059SGregory Neil Shapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 74740266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 74840266059SGregory Neil Shapiro 74940266059SGregory Neil Shapiro /* 75040266059SGregory Neil Shapiro ** If matching only, 75140266059SGregory Neil Shapiro ** no need to spin through entries 75240266059SGregory Neil Shapiro */ 75340266059SGregory Neil Shapiro 75440266059SGregory Neil Shapiro if (bitset(SM_LDAP_MATCHONLY, flags)) 75540266059SGregory Neil Shapiro { 75640266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 75740266059SGregory Neil Shapiro ldap_value_free(vals); 75840266059SGregory Neil Shapiro ldap_memfree(attr); 75940266059SGregory Neil Shapiro continue; 76040266059SGregory Neil Shapiro } 76140266059SGregory Neil Shapiro 76240266059SGregory Neil Shapiro /* 76340266059SGregory Neil Shapiro ** If we don't want multiple values, 76440266059SGregory Neil Shapiro ** return first found. 76540266059SGregory Neil Shapiro */ 76640266059SGregory Neil Shapiro 767605302a5SGregory Neil Shapiro if ((char) delim == '\0') 76840266059SGregory Neil Shapiro { 769605302a5SGregory Neil Shapiro if (*result != NULL) 770605302a5SGregory Neil Shapiro { 771605302a5SGregory Neil Shapiro /* already have a value */ 772605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEMATCH, 77313d88268SGregory Neil Shapiro flags)) 774605302a5SGregory Neil Shapiro { 775605302a5SGregory Neil Shapiro /* only wanted one match */ 776605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 777605302a5SGregory Neil Shapiro errno = ENOENT; 778605302a5SGregory Neil Shapiro return EX_NOTFOUND; 779605302a5SGregory Neil Shapiro } 78013d88268SGregory Neil Shapiro break; 78113d88268SGregory Neil Shapiro } 782605302a5SGregory Neil Shapiro 78340266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 78440266059SGregory Neil Shapiro { 78540266059SGregory Neil Shapiro *result = sm_rpool_strdup_x(rpool, 78640266059SGregory Neil Shapiro attr); 78740266059SGregory Neil Shapiro ldap_memfree(attr); 78840266059SGregory Neil Shapiro break; 78940266059SGregory Neil Shapiro } 79040266059SGregory Neil Shapiro 79140266059SGregory Neil Shapiro if (vals[0] == NULL) 79240266059SGregory Neil Shapiro { 79340266059SGregory Neil Shapiro ldap_value_free(vals); 79440266059SGregory Neil Shapiro ldap_memfree(attr); 79540266059SGregory Neil Shapiro continue; 79640266059SGregory Neil Shapiro } 79740266059SGregory Neil Shapiro 79840266059SGregory Neil Shapiro vsize = strlen(vals[0]) + 1; 79940266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 80040266059SGregory Neil Shapiro vsize += strlen(attr) + 1; 80140266059SGregory Neil Shapiro *result = sm_rpool_malloc_x(rpool, 80240266059SGregory Neil Shapiro vsize); 80340266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 80440266059SGregory Neil Shapiro sm_snprintf(*result, vsize, 80540266059SGregory Neil Shapiro "%s%c%s", 80640266059SGregory Neil Shapiro attr, 80740266059SGregory Neil Shapiro lmap->ldap_attrsep, 80840266059SGregory Neil Shapiro vals[0]); 80940266059SGregory Neil Shapiro else 81040266059SGregory Neil Shapiro sm_strlcpy(*result, vals[0], 81140266059SGregory Neil Shapiro vsize); 81240266059SGregory Neil Shapiro ldap_value_free(vals); 81340266059SGregory Neil Shapiro ldap_memfree(attr); 81440266059SGregory Neil Shapiro break; 81540266059SGregory Neil Shapiro } 81640266059SGregory Neil Shapiro 81740266059SGregory Neil Shapiro /* attributes only */ 81840266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 81940266059SGregory Neil Shapiro { 82040266059SGregory Neil Shapiro if (*result == NULL) 82140266059SGregory Neil Shapiro *result = sm_rpool_strdup_x(rpool, 82240266059SGregory Neil Shapiro attr); 82340266059SGregory Neil Shapiro else 82440266059SGregory Neil Shapiro { 825605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEMATCH, 826605302a5SGregory Neil Shapiro flags) && 827605302a5SGregory Neil Shapiro *result != NULL) 828605302a5SGregory Neil Shapiro { 829605302a5SGregory Neil Shapiro /* only wanted one match */ 830605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 831605302a5SGregory Neil Shapiro errno = ENOENT; 832605302a5SGregory Neil Shapiro return EX_NOTFOUND; 833605302a5SGregory Neil Shapiro } 834605302a5SGregory Neil Shapiro 83540266059SGregory Neil Shapiro vsize = strlen(*result) + 83640266059SGregory Neil Shapiro strlen(attr) + 2; 83740266059SGregory Neil Shapiro tmp = sm_rpool_malloc_x(rpool, 83840266059SGregory Neil Shapiro vsize); 83940266059SGregory Neil Shapiro (void) sm_snprintf(tmp, 84040266059SGregory Neil Shapiro vsize, "%s%c%s", 841605302a5SGregory Neil Shapiro *result, (char) delim, 84240266059SGregory Neil Shapiro attr); 84340266059SGregory Neil Shapiro *result = tmp; 84440266059SGregory Neil Shapiro } 84540266059SGregory Neil Shapiro ldap_memfree(attr); 84640266059SGregory Neil Shapiro continue; 84740266059SGregory Neil Shapiro } 84840266059SGregory Neil Shapiro 84940266059SGregory Neil Shapiro /* 850605302a5SGregory Neil Shapiro ** If there is more than one, munge then 851605302a5SGregory Neil Shapiro ** into a map_coldelim separated string. 852605302a5SGregory Neil Shapiro ** If we are recursing we may have an entry 853605302a5SGregory Neil Shapiro ** with no 'normal' values to put in the 854605302a5SGregory Neil Shapiro ** string. 855605302a5SGregory Neil Shapiro ** This is not an error. 85640266059SGregory Neil Shapiro */ 85740266059SGregory Neil Shapiro 858605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NORMAL && 859605302a5SGregory Neil Shapiro bitset(SM_LDAP_SINGLEMATCH, flags) && 860605302a5SGregory Neil Shapiro *result != NULL) 861605302a5SGregory Neil Shapiro { 862605302a5SGregory Neil Shapiro /* only wanted one match */ 863605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 864605302a5SGregory Neil Shapiro errno = ENOENT; 865605302a5SGregory Neil Shapiro return EX_NOTFOUND; 866605302a5SGregory Neil Shapiro } 867605302a5SGregory Neil Shapiro 86840266059SGregory Neil Shapiro vsize = 0; 86940266059SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 87040266059SGregory Neil Shapiro { 871605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_DN || 872605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_FILTER || 873605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_URL) 87440266059SGregory Neil Shapiro { 875605302a5SGregory Neil Shapiro /* add to recursion */ 876605302a5SGregory Neil Shapiro if (sm_ldap_add_recurse(&recurse, 87740266059SGregory Neil Shapiro vals[i], 878605302a5SGregory Neil Shapiro type, 879605302a5SGregory Neil Shapiro rpool) == NULL) 88040266059SGregory Neil Shapiro { 881605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 88240266059SGregory Neil Shapiro errno = ENOMEM; 88340266059SGregory Neil Shapiro return EX_OSERR; 88440266059SGregory Neil Shapiro } 88540266059SGregory Neil Shapiro continue; 88640266059SGregory Neil Shapiro } 887605302a5SGregory Neil Shapiro 88840266059SGregory Neil Shapiro vsize += strlen(vals[i]) + 1; 88940266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 89040266059SGregory Neil Shapiro vsize += strlen(attr) + 1; 89140266059SGregory Neil Shapiro } 892605302a5SGregory Neil Shapiro 893605302a5SGregory Neil Shapiro /* 894605302a5SGregory Neil Shapiro ** Create/Append to string any normal 895605302a5SGregory Neil Shapiro ** attribute values. Otherwise, just free 896605302a5SGregory Neil Shapiro ** memory and move on to the next 897605302a5SGregory Neil Shapiro ** attribute in this entry. 898605302a5SGregory Neil Shapiro */ 899605302a5SGregory Neil Shapiro 900605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NORMAL && vsize > 0) 901605302a5SGregory Neil Shapiro { 902605302a5SGregory Neil Shapiro char *pe; 903605302a5SGregory Neil Shapiro 904605302a5SGregory Neil Shapiro /* Grow result string if needed */ 905605302a5SGregory Neil Shapiro if ((*resultln + vsize) >= *resultsz) 906605302a5SGregory Neil Shapiro { 907605302a5SGregory Neil Shapiro while ((*resultln + vsize) >= *resultsz) 908605302a5SGregory Neil Shapiro { 909605302a5SGregory Neil Shapiro if (*resultsz == 0) 910605302a5SGregory Neil Shapiro *resultsz = 1024; 911605302a5SGregory Neil Shapiro else 912605302a5SGregory Neil Shapiro *resultsz *= 2; 913605302a5SGregory Neil Shapiro } 914605302a5SGregory Neil Shapiro 915605302a5SGregory Neil Shapiro vp_tmp = sm_rpool_malloc_x(rpool, *resultsz); 91640266059SGregory Neil Shapiro *vp_tmp = '\0'; 91740266059SGregory Neil Shapiro 918605302a5SGregory Neil Shapiro if (*result != NULL) 919605302a5SGregory Neil Shapiro sm_strlcpy(vp_tmp, 920605302a5SGregory Neil Shapiro *result, 921605302a5SGregory Neil Shapiro *resultsz); 922605302a5SGregory Neil Shapiro *result = vp_tmp; 923605302a5SGregory Neil Shapiro } 924605302a5SGregory Neil Shapiro 925605302a5SGregory Neil Shapiro p = *result + *resultln; 926605302a5SGregory Neil Shapiro pe = *result + *resultsz; 927605302a5SGregory Neil Shapiro 92840266059SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 92940266059SGregory Neil Shapiro { 930959366dcSGregory Neil Shapiro if (*resultln > 0 && 931959366dcSGregory Neil Shapiro p < pe) 932605302a5SGregory Neil Shapiro *p++ = (char) delim; 933605302a5SGregory Neil Shapiro 93440266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 93540266059SGregory Neil Shapiro { 93640266059SGregory Neil Shapiro p += sm_strlcpy(p, attr, 937605302a5SGregory Neil Shapiro pe - p); 938605302a5SGregory Neil Shapiro if (p < pe) 93940266059SGregory Neil Shapiro *p++ = lmap->ldap_attrsep; 94040266059SGregory Neil Shapiro } 941605302a5SGregory Neil Shapiro 94240266059SGregory Neil Shapiro p += sm_strlcpy(p, vals[i], 943605302a5SGregory Neil Shapiro pe - p); 944605302a5SGregory Neil Shapiro *resultln = p - (*result); 945605302a5SGregory Neil Shapiro if (p >= pe) 94640266059SGregory Neil Shapiro { 94740266059SGregory Neil Shapiro /* Internal error: buffer too small for LDAP values */ 948605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 94940266059SGregory Neil Shapiro errno = ENOMEM; 95040266059SGregory Neil Shapiro return EX_OSERR; 95140266059SGregory Neil Shapiro } 952605302a5SGregory Neil Shapiro } 95340266059SGregory Neil Shapiro } 95440266059SGregory Neil Shapiro 95540266059SGregory Neil Shapiro ldap_value_free(vals); 95640266059SGregory Neil Shapiro ldap_memfree(attr); 95740266059SGregory Neil Shapiro } 95840266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 95940266059SGregory Neil Shapiro 96040266059SGregory Neil Shapiro /* 96140266059SGregory Neil Shapiro ** We check save_errno != LDAP_DECODING_ERROR since 96240266059SGregory Neil Shapiro ** OpenLDAP 1.X has a very ugly *undocumented* 96340266059SGregory Neil Shapiro ** hack of returning this error code from 96440266059SGregory Neil Shapiro ** ldap_next_attribute() if the library freed the 96540266059SGregory Neil Shapiro ** ber attribute. See: 96640266059SGregory Neil Shapiro ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 96740266059SGregory Neil Shapiro */ 96840266059SGregory Neil Shapiro 96940266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS && 97040266059SGregory Neil Shapiro save_errno != LDAP_DECODING_ERROR) 97140266059SGregory Neil Shapiro { 97240266059SGregory Neil Shapiro /* Must be an error */ 97340266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 974605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 97540266059SGregory Neil Shapiro errno = save_errno; 97640266059SGregory Neil Shapiro return EX_TEMPFAIL; 97740266059SGregory Neil Shapiro } 97840266059SGregory Neil Shapiro 979605302a5SGregory Neil Shapiro /* mark this DN as done */ 980605302a5SGregory Neil Shapiro rl->lr_done = true; 981e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp != NULL) 982e92d3f3fSGregory Neil Shapiro { 983e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 984e92d3f3fSGregory Neil Shapiro rl->lr_ludp = NULL; 985e92d3f3fSGregory Neil Shapiro } 986e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs != NULL) 987e92d3f3fSGregory Neil Shapiro { 988e92d3f3fSGregory Neil Shapiro free(rl->lr_attrs); 989e92d3f3fSGregory Neil Shapiro rl->lr_attrs = NULL; 990e92d3f3fSGregory Neil Shapiro } 991605302a5SGregory Neil Shapiro 99240266059SGregory Neil Shapiro /* We don't want multiple values and we have one */ 99313d88268SGregory Neil Shapiro if ((char) delim == '\0' && 99413d88268SGregory Neil Shapiro !bitset(SM_LDAP_SINGLEMATCH, flags) && 99513d88268SGregory Neil Shapiro *result != NULL) 99640266059SGregory Neil Shapiro break; 99740266059SGregory Neil Shapiro } 99840266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 99940266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS && 100040266059SGregory Neil Shapiro save_errno != LDAP_DECODING_ERROR) 100140266059SGregory Neil Shapiro { 100240266059SGregory Neil Shapiro /* Must be an error */ 100340266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 1004605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 100540266059SGregory Neil Shapiro errno = save_errno; 100640266059SGregory Neil Shapiro return EX_TEMPFAIL; 100740266059SGregory Neil Shapiro } 100840266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); 100940266059SGregory Neil Shapiro lmap->ldap_res = NULL; 101040266059SGregory Neil Shapiro } 101140266059SGregory Neil Shapiro 101240266059SGregory Neil Shapiro if (ret == 0) 101340266059SGregory Neil Shapiro save_errno = ETIMEDOUT; 101440266059SGregory Neil Shapiro else 101540266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 101640266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS) 101740266059SGregory Neil Shapiro { 101840266059SGregory Neil Shapiro statp = EX_TEMPFAIL; 101940266059SGregory Neil Shapiro if (ret != 0) 102040266059SGregory Neil Shapiro { 102140266059SGregory Neil Shapiro switch (save_errno) 102240266059SGregory Neil Shapiro { 102340266059SGregory Neil Shapiro #ifdef LDAP_SERVER_DOWN 102440266059SGregory Neil Shapiro case LDAP_SERVER_DOWN: 102540266059SGregory Neil Shapiro #endif /* LDAP_SERVER_DOWN */ 102640266059SGregory Neil Shapiro case LDAP_TIMEOUT: 102740266059SGregory Neil Shapiro case LDAP_UNAVAILABLE: 1028605302a5SGregory Neil Shapiro 1029605302a5SGregory Neil Shapiro /* 1030605302a5SGregory Neil Shapiro ** server disappeared, 1031605302a5SGregory Neil Shapiro ** try reopen on next search 1032605302a5SGregory Neil Shapiro */ 1033605302a5SGregory Neil Shapiro 103440266059SGregory Neil Shapiro statp = EX_RESTART; 103540266059SGregory Neil Shapiro break; 103640266059SGregory Neil Shapiro } 103740266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 103840266059SGregory Neil Shapiro } 1039605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 104040266059SGregory Neil Shapiro errno = save_errno; 104140266059SGregory Neil Shapiro return statp; 104240266059SGregory Neil Shapiro } 104340266059SGregory Neil Shapiro 104440266059SGregory Neil Shapiro if (lmap->ldap_res != NULL) 104540266059SGregory Neil Shapiro { 104640266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); 104740266059SGregory Neil Shapiro lmap->ldap_res = NULL; 104840266059SGregory Neil Shapiro } 104940266059SGregory Neil Shapiro 105040266059SGregory Neil Shapiro if (toplevel) 105140266059SGregory Neil Shapiro { 1052605302a5SGregory Neil Shapiro int rlidx; 105340266059SGregory Neil Shapiro 105440266059SGregory Neil Shapiro /* 105540266059SGregory Neil Shapiro ** Spin through the built-up recurse list at the top 105640266059SGregory Neil Shapiro ** of the recursion. Since new items are added at the 105740266059SGregory Neil Shapiro ** end of the shared list, we actually only ever get 105840266059SGregory Neil Shapiro ** one level of recursion before things pop back to the 105940266059SGregory Neil Shapiro ** top. Any items added to the list during that recursion 106040266059SGregory Neil Shapiro ** will be expanded by the top level. 106140266059SGregory Neil Shapiro */ 106240266059SGregory Neil Shapiro 1063605302a5SGregory Neil Shapiro for (rlidx = 0; recurse != NULL && rlidx < recurse->lr_cnt; rlidx++) 106440266059SGregory Neil Shapiro { 1065605302a5SGregory Neil Shapiro int newflags; 106640266059SGregory Neil Shapiro int sid; 106740266059SGregory Neil Shapiro int status; 106840266059SGregory Neil Shapiro 1069605302a5SGregory Neil Shapiro rl = recurse->lr_data[rlidx]; 1070605302a5SGregory Neil Shapiro 1071605302a5SGregory Neil Shapiro newflags = flags; 1072605302a5SGregory Neil Shapiro if (rl->lr_done) 107340266059SGregory Neil Shapiro { 107440266059SGregory Neil Shapiro /* already expanded */ 107540266059SGregory Neil Shapiro continue; 107640266059SGregory Neil Shapiro } 1077605302a5SGregory Neil Shapiro 1078605302a5SGregory Neil Shapiro if (rl->lr_type == SM_LDAP_ATTR_DN) 107940266059SGregory Neil Shapiro { 108040266059SGregory Neil Shapiro /* do DN search */ 108140266059SGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 108240266059SGregory Neil Shapiro rl->lr_search, 108340266059SGregory Neil Shapiro lmap->ldap_scope, 108440266059SGregory Neil Shapiro "(objectClass=*)", 1085605302a5SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? 1086605302a5SGregory Neil Shapiro NULL : lmap->ldap_attr), 108740266059SGregory Neil Shapiro lmap->ldap_attrsonly); 108840266059SGregory Neil Shapiro } 1089605302a5SGregory Neil Shapiro else if (rl->lr_type == SM_LDAP_ATTR_FILTER) 109040266059SGregory Neil Shapiro { 109140266059SGregory Neil Shapiro /* do new search */ 109240266059SGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 109340266059SGregory Neil Shapiro lmap->ldap_base, 109440266059SGregory Neil Shapiro lmap->ldap_scope, 109540266059SGregory Neil Shapiro rl->lr_search, 1096605302a5SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? 1097605302a5SGregory Neil Shapiro NULL : lmap->ldap_attr), 109840266059SGregory Neil Shapiro lmap->ldap_attrsonly); 109940266059SGregory Neil Shapiro } 1100605302a5SGregory Neil Shapiro else if (rl->lr_type == SM_LDAP_ATTR_URL) 110140266059SGregory Neil Shapiro { 1102e92d3f3fSGregory Neil Shapiro /* Parse URL */ 1103e92d3f3fSGregory Neil Shapiro sid = ldap_url_parse(rl->lr_search, 1104e92d3f3fSGregory Neil Shapiro &rl->lr_ludp); 1105e92d3f3fSGregory Neil Shapiro 1106e92d3f3fSGregory Neil Shapiro if (sid != 0) 1107e92d3f3fSGregory Neil Shapiro { 1108e92d3f3fSGregory Neil Shapiro errno = sid + E_LDAPURLBASE; 1109e92d3f3fSGregory Neil Shapiro return EX_TEMPFAIL; 1110e92d3f3fSGregory Neil Shapiro } 1111e92d3f3fSGregory Neil Shapiro 1112e92d3f3fSGregory Neil Shapiro /* We need to add objectClass */ 1113e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp->lud_attrs != NULL) 1114e92d3f3fSGregory Neil Shapiro { 1115e92d3f3fSGregory Neil Shapiro int attrnum = 0; 1116e92d3f3fSGregory Neil Shapiro 1117e92d3f3fSGregory Neil Shapiro while (rl->lr_ludp->lud_attrs[attrnum] != NULL) 1118e92d3f3fSGregory Neil Shapiro { 1119e92d3f3fSGregory Neil Shapiro if (strcasecmp(rl->lr_ludp->lud_attrs[attrnum], 1120e92d3f3fSGregory Neil Shapiro "objectClass") == 0) 1121e92d3f3fSGregory Neil Shapiro { 1122e92d3f3fSGregory Neil Shapiro /* already requested */ 1123e92d3f3fSGregory Neil Shapiro attrnum = -1; 1124e92d3f3fSGregory Neil Shapiro break; 1125e92d3f3fSGregory Neil Shapiro } 1126e92d3f3fSGregory Neil Shapiro attrnum++; 1127e92d3f3fSGregory Neil Shapiro } 1128e92d3f3fSGregory Neil Shapiro 1129e92d3f3fSGregory Neil Shapiro if (attrnum >= 0) 1130e92d3f3fSGregory Neil Shapiro { 1131e92d3f3fSGregory Neil Shapiro int i; 1132e92d3f3fSGregory Neil Shapiro 1133e92d3f3fSGregory Neil Shapiro rl->lr_attrs = (char **)malloc(sizeof(char *) * (attrnum + 2)); 1134e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs == NULL) 1135e92d3f3fSGregory Neil Shapiro { 1136e92d3f3fSGregory Neil Shapiro save_errno = errno; 1137e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1138e92d3f3fSGregory Neil Shapiro errno = save_errno; 1139e92d3f3fSGregory Neil Shapiro return EX_TEMPFAIL; 1140e92d3f3fSGregory Neil Shapiro } 1141e92d3f3fSGregory Neil Shapiro for (i = 0 ; i < attrnum; i++) 1142e92d3f3fSGregory Neil Shapiro { 1143e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i] = rl->lr_ludp->lud_attrs[i]; 1144e92d3f3fSGregory Neil Shapiro } 1145e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i++] = "objectClass"; 1146e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i++] = NULL; 1147e92d3f3fSGregory Neil Shapiro } 1148e92d3f3fSGregory Neil Shapiro } 1149e92d3f3fSGregory Neil Shapiro 1150e92d3f3fSGregory Neil Shapiro /* 1151e92d3f3fSGregory Neil Shapiro ** Use the existing connection 1152e92d3f3fSGregory Neil Shapiro ** for this search. It really 1153e92d3f3fSGregory Neil Shapiro ** should use lud_scheme://lud_host:lud_port/ 1154e92d3f3fSGregory Neil Shapiro ** instead but that would require 1155e92d3f3fSGregory Neil Shapiro ** opening a new connection. 1156e92d3f3fSGregory Neil Shapiro ** This should be fixed ASAP. 1157e92d3f3fSGregory Neil Shapiro */ 1158e92d3f3fSGregory Neil Shapiro 1159e92d3f3fSGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 1160e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_dn, 1161e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_scope, 1162e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_filter, 1163e92d3f3fSGregory Neil Shapiro rl->lr_attrs, 116440266059SGregory Neil Shapiro lmap->ldap_attrsonly); 1165e92d3f3fSGregory Neil Shapiro 1166e92d3f3fSGregory Neil Shapiro /* Use the attributes specified by URL */ 1167605302a5SGregory Neil Shapiro newflags |= SM_LDAP_USE_ALLATTR; 116840266059SGregory Neil Shapiro } 116940266059SGregory Neil Shapiro else 117040266059SGregory Neil Shapiro { 117140266059SGregory Neil Shapiro /* unknown or illegal attribute type */ 117240266059SGregory Neil Shapiro errno = EFAULT; 117340266059SGregory Neil Shapiro return EX_SOFTWARE; 117440266059SGregory Neil Shapiro } 117540266059SGregory Neil Shapiro 117640266059SGregory Neil Shapiro /* Collect results */ 117740266059SGregory Neil Shapiro if (sid == -1) 117840266059SGregory Neil Shapiro { 117940266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 118040266059SGregory Neil Shapiro statp = EX_TEMPFAIL; 118140266059SGregory Neil Shapiro switch (save_errno) 118240266059SGregory Neil Shapiro { 118340266059SGregory Neil Shapiro #ifdef LDAP_SERVER_DOWN 118440266059SGregory Neil Shapiro case LDAP_SERVER_DOWN: 118540266059SGregory Neil Shapiro #endif /* LDAP_SERVER_DOWN */ 118640266059SGregory Neil Shapiro case LDAP_TIMEOUT: 118740266059SGregory Neil Shapiro case LDAP_UNAVAILABLE: 1188605302a5SGregory Neil Shapiro 1189605302a5SGregory Neil Shapiro /* 1190605302a5SGregory Neil Shapiro ** server disappeared, 1191605302a5SGregory Neil Shapiro ** try reopen on next search 1192605302a5SGregory Neil Shapiro */ 1193605302a5SGregory Neil Shapiro 119440266059SGregory Neil Shapiro statp = EX_RESTART; 119540266059SGregory Neil Shapiro break; 119640266059SGregory Neil Shapiro } 119740266059SGregory Neil Shapiro errno = save_errno + E_LDAPBASE; 119840266059SGregory Neil Shapiro return statp; 119940266059SGregory Neil Shapiro } 120040266059SGregory Neil Shapiro 1201605302a5SGregory Neil Shapiro status = sm_ldap_results(lmap, sid, newflags, delim, 1202605302a5SGregory Neil Shapiro rpool, result, resultln, 1203605302a5SGregory Neil Shapiro resultsz, recurse); 120440266059SGregory Neil Shapiro save_errno = errno; 120540266059SGregory Neil Shapiro if (status != EX_OK && status != EX_NOTFOUND) 120640266059SGregory Neil Shapiro { 120740266059SGregory Neil Shapiro errno = save_errno; 120840266059SGregory Neil Shapiro return status; 120940266059SGregory Neil Shapiro } 121040266059SGregory Neil Shapiro 121140266059SGregory Neil Shapiro /* Mark as done */ 1212605302a5SGregory Neil Shapiro rl->lr_done = true; 1213e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp != NULL) 1214e92d3f3fSGregory Neil Shapiro { 1215e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1216e92d3f3fSGregory Neil Shapiro rl->lr_ludp = NULL; 1217e92d3f3fSGregory Neil Shapiro } 1218e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs != NULL) 1219e92d3f3fSGregory Neil Shapiro { 1220e92d3f3fSGregory Neil Shapiro free(rl->lr_attrs); 1221e92d3f3fSGregory Neil Shapiro rl->lr_attrs = NULL; 1222e92d3f3fSGregory Neil Shapiro } 1223605302a5SGregory Neil Shapiro 1224605302a5SGregory Neil Shapiro /* Reset rlidx as new items may have been added */ 1225605302a5SGregory Neil Shapiro rlidx = -1; 122640266059SGregory Neil Shapiro } 122740266059SGregory Neil Shapiro } 122840266059SGregory Neil Shapiro return statp; 122940266059SGregory Neil Shapiro } 123040266059SGregory Neil Shapiro 123140266059SGregory Neil Shapiro /* 123240266059SGregory Neil Shapiro ** SM_LDAP_CLOSE -- close LDAP connection 123340266059SGregory Neil Shapiro ** 123440266059SGregory Neil Shapiro ** Parameters: 123540266059SGregory Neil Shapiro ** lmap -- LDAP map information 123640266059SGregory Neil Shapiro ** 123740266059SGregory Neil Shapiro ** Returns: 123840266059SGregory Neil Shapiro ** None. 123940266059SGregory Neil Shapiro ** 124040266059SGregory Neil Shapiro */ 124140266059SGregory Neil Shapiro 124240266059SGregory Neil Shapiro void 124340266059SGregory Neil Shapiro sm_ldap_close(lmap) 124440266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 124540266059SGregory Neil Shapiro { 124640266059SGregory Neil Shapiro if (lmap->ldap_ld == NULL) 124740266059SGregory Neil Shapiro return; 124840266059SGregory Neil Shapiro 124940266059SGregory Neil Shapiro if (lmap->ldap_pid == getpid()) 125040266059SGregory Neil Shapiro ldap_unbind(lmap->ldap_ld); 125140266059SGregory Neil Shapiro lmap->ldap_ld = NULL; 125240266059SGregory Neil Shapiro lmap->ldap_pid = 0; 125340266059SGregory Neil Shapiro } 125440266059SGregory Neil Shapiro 125540266059SGregory Neil Shapiro /* 125640266059SGregory Neil Shapiro ** SM_LDAP_SETOPTS -- set LDAP options 125740266059SGregory Neil Shapiro ** 125840266059SGregory Neil Shapiro ** Parameters: 125940266059SGregory Neil Shapiro ** ld -- LDAP session handle 126040266059SGregory Neil Shapiro ** lmap -- LDAP map information 126140266059SGregory Neil Shapiro ** 126240266059SGregory Neil Shapiro ** Returns: 126340266059SGregory Neil Shapiro ** None. 126440266059SGregory Neil Shapiro ** 126540266059SGregory Neil Shapiro */ 126640266059SGregory Neil Shapiro 126740266059SGregory Neil Shapiro void 126840266059SGregory Neil Shapiro sm_ldap_setopts(ld, lmap) 126940266059SGregory Neil Shapiro LDAP *ld; 127040266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 127140266059SGregory Neil Shapiro { 127240266059SGregory Neil Shapiro # if USE_LDAP_SET_OPTION 1273605302a5SGregory Neil Shapiro if (lmap->ldap_version != 0) 1274605302a5SGregory Neil Shapiro { 1275605302a5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, 1276605302a5SGregory Neil Shapiro &lmap->ldap_version); 1277605302a5SGregory Neil Shapiro } 127840266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); 127940266059SGregory Neil Shapiro if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) 128040266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); 128140266059SGregory Neil Shapiro else 128240266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 128340266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); 128440266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); 1285959366dcSGregory Neil Shapiro # ifdef LDAP_OPT_RESTART 1286959366dcSGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); 1287959366dcSGregory Neil Shapiro # endif /* LDAP_OPT_RESTART */ 128840266059SGregory Neil Shapiro # else /* USE_LDAP_SET_OPTION */ 128940266059SGregory Neil Shapiro /* From here on in we can use ldap internal timelimits */ 129040266059SGregory Neil Shapiro ld->ld_deref = lmap->ldap_deref; 129140266059SGregory Neil Shapiro ld->ld_options = lmap->ldap_options; 129240266059SGregory Neil Shapiro ld->ld_sizelimit = lmap->ldap_sizelimit; 129340266059SGregory Neil Shapiro ld->ld_timelimit = lmap->ldap_timelimit; 129440266059SGregory Neil Shapiro # endif /* USE_LDAP_SET_OPTION */ 129540266059SGregory Neil Shapiro } 129640266059SGregory Neil Shapiro 129740266059SGregory Neil Shapiro /* 129840266059SGregory Neil Shapiro ** SM_LDAP_GETERRNO -- get ldap errno value 129940266059SGregory Neil Shapiro ** 130040266059SGregory Neil Shapiro ** Parameters: 130140266059SGregory Neil Shapiro ** ld -- LDAP session handle 130240266059SGregory Neil Shapiro ** 130340266059SGregory Neil Shapiro ** Returns: 130440266059SGregory Neil Shapiro ** LDAP errno. 130540266059SGregory Neil Shapiro ** 130640266059SGregory Neil Shapiro */ 130740266059SGregory Neil Shapiro 130840266059SGregory Neil Shapiro int 130940266059SGregory Neil Shapiro sm_ldap_geterrno(ld) 131040266059SGregory Neil Shapiro LDAP *ld; 131140266059SGregory Neil Shapiro { 131240266059SGregory Neil Shapiro int err = LDAP_SUCCESS; 131340266059SGregory Neil Shapiro 131440266059SGregory Neil Shapiro # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 131540266059SGregory Neil Shapiro (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); 131640266059SGregory Neil Shapiro # else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 131740266059SGregory Neil Shapiro # ifdef LDAP_OPT_SIZELIMIT 131840266059SGregory Neil Shapiro err = ldap_get_lderrno(ld, NULL, NULL); 131940266059SGregory Neil Shapiro # else /* LDAP_OPT_SIZELIMIT */ 132040266059SGregory Neil Shapiro err = ld->ld_errno; 132140266059SGregory Neil Shapiro 132240266059SGregory Neil Shapiro /* 132340266059SGregory Neil Shapiro ** Reset value to prevent lingering LDAP_DECODING_ERROR due to 132440266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see above) 132540266059SGregory Neil Shapiro */ 132640266059SGregory Neil Shapiro 132740266059SGregory Neil Shapiro ld->ld_errno = LDAP_SUCCESS; 132840266059SGregory Neil Shapiro # endif /* LDAP_OPT_SIZELIMIT */ 132940266059SGregory Neil Shapiro # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 133040266059SGregory Neil Shapiro return err; 133140266059SGregory Neil Shapiro } 133240266059SGregory Neil Shapiro # endif /* LDAPMAP */ 1333