140266059SGregory Neil Shapiro /* 2323f6dcbSGregory Neil Shapiro * Copyright (c) 2001-2003 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> 11e92d3f3fSGregory Neil Shapiro SM_RCSID("@(#)$Id: ldap.c,v 1.59 2003/12/23 21:20:15 gshapiro 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)); 3640266059SGregory Neil Shapiro 3740266059SGregory Neil Shapiro /* 3840266059SGregory Neil Shapiro ** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT 3940266059SGregory Neil Shapiro ** 4040266059SGregory Neil Shapiro ** Parameters: 4140266059SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT to clear 4240266059SGregory Neil Shapiro ** 4340266059SGregory Neil Shapiro ** Returns: 4440266059SGregory Neil Shapiro ** None. 4540266059SGregory Neil Shapiro ** 4640266059SGregory Neil Shapiro */ 4740266059SGregory Neil Shapiro 4840266059SGregory Neil Shapiro void 4940266059SGregory Neil Shapiro sm_ldap_clear(lmap) 5040266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 5140266059SGregory Neil Shapiro { 5240266059SGregory Neil Shapiro if (lmap == NULL) 5340266059SGregory Neil Shapiro return; 5440266059SGregory Neil Shapiro 55e92d3f3fSGregory Neil Shapiro lmap->ldap_host = NULL; 5640266059SGregory Neil Shapiro lmap->ldap_port = LDAP_PORT; 57e92d3f3fSGregory Neil Shapiro lmap->ldap_uri = NULL; 58605302a5SGregory Neil Shapiro lmap->ldap_version = 0; 5940266059SGregory Neil Shapiro lmap->ldap_deref = LDAP_DEREF_NEVER; 6040266059SGregory Neil Shapiro lmap->ldap_timelimit = LDAP_NO_LIMIT; 6140266059SGregory Neil Shapiro lmap->ldap_sizelimit = LDAP_NO_LIMIT; 6240266059SGregory Neil Shapiro # ifdef LDAP_REFERRALS 6340266059SGregory Neil Shapiro lmap->ldap_options = LDAP_OPT_REFERRALS; 6440266059SGregory Neil Shapiro # else /* LDAP_REFERRALS */ 6540266059SGregory Neil Shapiro lmap->ldap_options = 0; 6640266059SGregory Neil Shapiro # endif /* LDAP_REFERRALS */ 6740266059SGregory Neil Shapiro lmap->ldap_attrsep = '\0'; 6840266059SGregory Neil Shapiro lmap->ldap_binddn = NULL; 6940266059SGregory Neil Shapiro lmap->ldap_secret = NULL; 7040266059SGregory Neil Shapiro lmap->ldap_method = LDAP_AUTH_SIMPLE; 7140266059SGregory Neil Shapiro lmap->ldap_base = NULL; 7240266059SGregory Neil Shapiro lmap->ldap_scope = LDAP_SCOPE_SUBTREE; 7340266059SGregory Neil Shapiro lmap->ldap_attrsonly = LDAPMAP_FALSE; 7440266059SGregory Neil Shapiro lmap->ldap_timeout.tv_sec = 0; 7540266059SGregory Neil Shapiro lmap->ldap_timeout.tv_usec = 0; 7640266059SGregory Neil Shapiro lmap->ldap_ld = NULL; 7740266059SGregory Neil Shapiro lmap->ldap_filter = NULL; 7840266059SGregory Neil Shapiro lmap->ldap_attr[0] = NULL; 79605302a5SGregory Neil Shapiro lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE; 80605302a5SGregory Neil Shapiro lmap->ldap_attr_needobjclass[0] = NULL; 8140266059SGregory Neil Shapiro lmap->ldap_res = NULL; 8240266059SGregory Neil Shapiro lmap->ldap_next = NULL; 8340266059SGregory Neil Shapiro lmap->ldap_pid = 0; 8440266059SGregory Neil Shapiro } 8540266059SGregory Neil Shapiro 8640266059SGregory Neil Shapiro /* 8740266059SGregory Neil Shapiro ** SM_LDAP_START -- actually connect to an LDAP server 8840266059SGregory Neil Shapiro ** 8940266059SGregory Neil Shapiro ** Parameters: 9040266059SGregory Neil Shapiro ** name -- name of map for debug output. 9140266059SGregory Neil Shapiro ** lmap -- the LDAP map being opened. 9240266059SGregory Neil Shapiro ** 9340266059SGregory Neil Shapiro ** Returns: 9440266059SGregory Neil Shapiro ** true if connection is successful, false otherwise. 9540266059SGregory Neil Shapiro ** 9640266059SGregory Neil Shapiro ** Side Effects: 9740266059SGregory Neil Shapiro ** Populates lmap->ldap_ld. 9840266059SGregory Neil Shapiro */ 9940266059SGregory Neil Shapiro 10040266059SGregory Neil Shapiro static jmp_buf LDAPTimeout; 10140266059SGregory Neil Shapiro 10240266059SGregory Neil Shapiro #define SM_LDAP_SETTIMEOUT(to) \ 10340266059SGregory Neil Shapiro do \ 10440266059SGregory Neil Shapiro { \ 10540266059SGregory Neil Shapiro if (to != 0) \ 10640266059SGregory Neil Shapiro { \ 10740266059SGregory Neil Shapiro if (setjmp(LDAPTimeout) != 0) \ 10840266059SGregory Neil Shapiro { \ 10940266059SGregory Neil Shapiro errno = ETIMEDOUT; \ 11040266059SGregory Neil Shapiro return false; \ 11140266059SGregory Neil Shapiro } \ 11240266059SGregory Neil Shapiro ev = sm_setevent(to, ldaptimeout, 0); \ 11340266059SGregory Neil Shapiro } \ 11440266059SGregory Neil Shapiro } while (0) 11540266059SGregory Neil Shapiro 11640266059SGregory Neil Shapiro #define SM_LDAP_CLEARTIMEOUT() \ 11740266059SGregory Neil Shapiro do \ 11840266059SGregory Neil Shapiro { \ 11940266059SGregory Neil Shapiro if (ev != NULL) \ 12040266059SGregory Neil Shapiro sm_clrevent(ev); \ 12140266059SGregory Neil Shapiro } while (0) 12240266059SGregory Neil Shapiro 12340266059SGregory Neil Shapiro bool 12440266059SGregory Neil Shapiro sm_ldap_start(name, lmap) 12540266059SGregory Neil Shapiro char *name; 12640266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 12740266059SGregory Neil Shapiro { 12840266059SGregory Neil Shapiro int bind_result; 12940266059SGregory Neil Shapiro int save_errno; 130e92d3f3fSGregory Neil Shapiro char *id; 13140266059SGregory Neil Shapiro SM_EVENT *ev = NULL; 132e92d3f3fSGregory Neil Shapiro LDAP *ld = NULL; 13340266059SGregory Neil Shapiro 13440266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 2)) 13540266059SGregory Neil Shapiro sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name); 13640266059SGregory Neil Shapiro 137e92d3f3fSGregory Neil Shapiro if (lmap->ldap_host != NULL) 138e92d3f3fSGregory Neil Shapiro id = lmap->ldap_host; 139e92d3f3fSGregory Neil Shapiro else if (lmap->ldap_uri != NULL) 140e92d3f3fSGregory Neil Shapiro id = lmap->ldap_uri; 141605302a5SGregory Neil Shapiro else 142e92d3f3fSGregory Neil Shapiro id = "localhost"; 143e92d3f3fSGregory Neil Shapiro 144e92d3f3fSGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 145e92d3f3fSGregory Neil Shapiro { 146e92d3f3fSGregory Neil Shapiro /* Don't print a port number for LDAP URIs */ 147e92d3f3fSGregory Neil Shapiro if (lmap->ldap_uri != NULL) 148e92d3f3fSGregory Neil Shapiro sm_dprintf("ldapmap_start(%s)\n", id); 149e92d3f3fSGregory Neil Shapiro else 150e92d3f3fSGregory Neil Shapiro sm_dprintf("ldapmap_start(%s, %d)\n", id, 151e92d3f3fSGregory Neil Shapiro lmap->ldap_port); 152e92d3f3fSGregory Neil Shapiro } 153e92d3f3fSGregory Neil Shapiro 154e92d3f3fSGregory Neil Shapiro if (lmap->ldap_uri != NULL) 155e92d3f3fSGregory Neil Shapiro { 156e92d3f3fSGregory Neil Shapiro #if SM_CONF_LDAP_INITIALIZE 157e92d3f3fSGregory Neil Shapiro /* LDAP server supports URIs so use them directly */ 158e92d3f3fSGregory Neil Shapiro save_errno = ldap_initialize(&ld, lmap->ldap_uri); 159e92d3f3fSGregory Neil Shapiro #else /* SM_CONF_LDAP_INITIALIZE */ 160e92d3f3fSGregory Neil Shapiro int err; 161e92d3f3fSGregory Neil Shapiro LDAPURLDesc *ludp = NULL; 162e92d3f3fSGregory Neil Shapiro 163e92d3f3fSGregory Neil Shapiro /* Blast apart URL and use the ldap_init/ldap_open below */ 164e92d3f3fSGregory Neil Shapiro err = ldap_url_parse(lmap->ldap_uri, &ludp); 165e92d3f3fSGregory Neil Shapiro if (err != 0) 166e92d3f3fSGregory Neil Shapiro { 167e92d3f3fSGregory Neil Shapiro errno = err + E_LDAPURLBASE; 168e92d3f3fSGregory Neil Shapiro return false; 169e92d3f3fSGregory Neil Shapiro } 170e92d3f3fSGregory Neil Shapiro lmap->ldap_host = sm_strdup_x(ludp->lud_host); 171e92d3f3fSGregory Neil Shapiro if (lmap->ldap_host == NULL) 172e92d3f3fSGregory Neil Shapiro { 173e92d3f3fSGregory Neil Shapiro save_errno = errno; 174e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(ludp); 175e92d3f3fSGregory Neil Shapiro errno = save_errno; 176e92d3f3fSGregory Neil Shapiro return false; 177e92d3f3fSGregory Neil Shapiro } 178e92d3f3fSGregory Neil Shapiro lmap->ldap_port = ludp->lud_port; 179e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(ludp); 180e92d3f3fSGregory Neil Shapiro #endif /* SM_CONF_LDAP_INITIALIZE */ 181e92d3f3fSGregory Neil Shapiro } 182e92d3f3fSGregory Neil Shapiro 183e92d3f3fSGregory Neil Shapiro if (ld == NULL) 184e92d3f3fSGregory Neil Shapiro { 185e92d3f3fSGregory Neil Shapiro # if USE_LDAP_INIT 186e92d3f3fSGregory Neil Shapiro ld = ldap_init(lmap->ldap_host, lmap->ldap_port); 18740266059SGregory Neil Shapiro save_errno = errno; 18840266059SGregory Neil Shapiro # else /* USE_LDAP_INIT */ 18940266059SGregory Neil Shapiro /* 19040266059SGregory Neil Shapiro ** If using ldap_open(), the actual connection to the server 19140266059SGregory Neil Shapiro ** happens now so we need the timeout here. For ldap_init(), 19240266059SGregory Neil Shapiro ** the connection happens at bind time. 19340266059SGregory Neil Shapiro */ 19440266059SGregory Neil Shapiro 19540266059SGregory Neil Shapiro SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); 196e92d3f3fSGregory Neil Shapiro ld = ldap_open(lmap->ldap_host, lmap->ldap_port); 19740266059SGregory Neil Shapiro save_errno = errno; 19840266059SGregory Neil Shapiro 19940266059SGregory Neil Shapiro /* clear the event if it has not sprung */ 20040266059SGregory Neil Shapiro SM_LDAP_CLEARTIMEOUT(); 20140266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 202e92d3f3fSGregory Neil Shapiro } 20340266059SGregory Neil Shapiro 20440266059SGregory Neil Shapiro errno = save_errno; 20540266059SGregory Neil Shapiro if (ld == NULL) 20640266059SGregory Neil Shapiro return false; 20740266059SGregory Neil Shapiro 20840266059SGregory Neil Shapiro sm_ldap_setopts(ld, lmap); 20940266059SGregory Neil Shapiro 21040266059SGregory Neil Shapiro # if USE_LDAP_INIT 21140266059SGregory Neil Shapiro /* 21240266059SGregory Neil Shapiro ** If using ldap_init(), the actual connection to the server 21340266059SGregory Neil Shapiro ** happens at ldap_bind_s() so we need the timeout here. 21440266059SGregory Neil Shapiro */ 21540266059SGregory Neil Shapiro 21640266059SGregory Neil Shapiro SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); 21740266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 21840266059SGregory Neil Shapiro 21940266059SGregory Neil Shapiro # ifdef LDAP_AUTH_KRBV4 22040266059SGregory Neil Shapiro if (lmap->ldap_method == LDAP_AUTH_KRBV4 && 22140266059SGregory Neil Shapiro lmap->ldap_secret != NULL) 22240266059SGregory Neil Shapiro { 22340266059SGregory Neil Shapiro /* 22440266059SGregory Neil Shapiro ** Need to put ticket in environment here instead of 22540266059SGregory Neil Shapiro ** during parseargs as there may be different tickets 22640266059SGregory Neil Shapiro ** for different LDAP connections. 22740266059SGregory Neil Shapiro */ 22840266059SGregory Neil Shapiro 22940266059SGregory Neil Shapiro (void) putenv(lmap->ldap_secret); 23040266059SGregory Neil Shapiro } 23140266059SGregory Neil Shapiro # endif /* LDAP_AUTH_KRBV4 */ 23240266059SGregory Neil Shapiro 23340266059SGregory Neil Shapiro bind_result = ldap_bind_s(ld, lmap->ldap_binddn, 23440266059SGregory Neil Shapiro lmap->ldap_secret, lmap->ldap_method); 23540266059SGregory Neil Shapiro 23640266059SGregory Neil Shapiro # if USE_LDAP_INIT 23740266059SGregory Neil Shapiro /* clear the event if it has not sprung */ 23840266059SGregory Neil Shapiro SM_LDAP_CLEARTIMEOUT(); 23940266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 24040266059SGregory Neil Shapiro 24140266059SGregory Neil Shapiro if (bind_result != LDAP_SUCCESS) 24240266059SGregory Neil Shapiro { 24340266059SGregory Neil Shapiro errno = bind_result + E_LDAPBASE; 24440266059SGregory Neil Shapiro return false; 24540266059SGregory Neil Shapiro } 24640266059SGregory Neil Shapiro 24740266059SGregory Neil Shapiro /* Save PID to make sure only this PID closes the LDAP connection */ 24840266059SGregory Neil Shapiro lmap->ldap_pid = getpid(); 24940266059SGregory Neil Shapiro lmap->ldap_ld = ld; 25040266059SGregory Neil Shapiro return true; 25140266059SGregory Neil Shapiro } 25240266059SGregory Neil Shapiro 25340266059SGregory Neil Shapiro /* ARGSUSED */ 25440266059SGregory Neil Shapiro static void 25540266059SGregory Neil Shapiro ldaptimeout(unused) 25640266059SGregory Neil Shapiro int unused; 25740266059SGregory Neil Shapiro { 25840266059SGregory Neil Shapiro /* 25940266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 26040266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 26140266059SGregory Neil Shapiro ** DOING. 26240266059SGregory Neil Shapiro */ 26340266059SGregory Neil Shapiro 26440266059SGregory Neil Shapiro errno = ETIMEDOUT; 26540266059SGregory Neil Shapiro longjmp(LDAPTimeout, 1); 26640266059SGregory Neil Shapiro } 26740266059SGregory Neil Shapiro 26840266059SGregory Neil Shapiro /* 269e92d3f3fSGregory Neil Shapiro ** SM_LDAP_SEARCH -- initiate LDAP search 27040266059SGregory Neil Shapiro ** 27140266059SGregory Neil Shapiro ** Initiate an LDAP search, return the msgid. 27240266059SGregory Neil Shapiro ** The calling function must collect the results. 27340266059SGregory Neil Shapiro ** 27440266059SGregory Neil Shapiro ** Parameters: 27540266059SGregory Neil Shapiro ** lmap -- LDAP map information 27640266059SGregory Neil Shapiro ** key -- key to substitute in LDAP filter 27740266059SGregory Neil Shapiro ** 27840266059SGregory Neil Shapiro ** Returns: 27940266059SGregory Neil Shapiro ** -1 on failure, msgid on success 28040266059SGregory Neil Shapiro ** 28140266059SGregory Neil Shapiro */ 28240266059SGregory Neil Shapiro 28340266059SGregory Neil Shapiro int 28440266059SGregory Neil Shapiro sm_ldap_search(lmap, key) 28540266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 28640266059SGregory Neil Shapiro char *key; 28740266059SGregory Neil Shapiro { 28840266059SGregory Neil Shapiro int msgid; 28940266059SGregory Neil Shapiro char *fp, *p, *q; 29040266059SGregory Neil Shapiro char filter[LDAPMAP_MAX_FILTER + 1]; 29140266059SGregory Neil Shapiro 29240266059SGregory Neil Shapiro /* substitute key into filter, perhaps multiple times */ 29340266059SGregory Neil Shapiro memset(filter, '\0', sizeof filter); 29440266059SGregory Neil Shapiro fp = filter; 29540266059SGregory Neil Shapiro p = lmap->ldap_filter; 29640266059SGregory Neil Shapiro while ((q = strchr(p, '%')) != NULL) 29740266059SGregory Neil Shapiro { 29840266059SGregory Neil Shapiro if (q[1] == 's') 29940266059SGregory Neil Shapiro { 30040266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 30140266059SGregory Neil Shapiro "%.*s%s", (int) (q - p), p, key); 30240266059SGregory Neil Shapiro fp += strlen(fp); 30340266059SGregory Neil Shapiro p = q + 2; 30440266059SGregory Neil Shapiro } 30540266059SGregory Neil Shapiro else if (q[1] == '0') 30640266059SGregory Neil Shapiro { 30740266059SGregory Neil Shapiro char *k = key; 30840266059SGregory Neil Shapiro 30940266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 31040266059SGregory Neil Shapiro "%.*s", (int) (q - p), p); 31140266059SGregory Neil Shapiro fp += strlen(fp); 31240266059SGregory Neil Shapiro p = q + 2; 31340266059SGregory Neil Shapiro 31440266059SGregory Neil Shapiro /* Properly escape LDAP special characters */ 31540266059SGregory Neil Shapiro while (SPACELEFT(filter, fp) > 0 && 31640266059SGregory Neil Shapiro *k != '\0') 31740266059SGregory Neil Shapiro { 31840266059SGregory Neil Shapiro if (*k == '*' || *k == '(' || 31940266059SGregory Neil Shapiro *k == ')' || *k == '\\') 32040266059SGregory Neil Shapiro { 32140266059SGregory Neil Shapiro (void) sm_strlcat(fp, 32240266059SGregory Neil Shapiro (*k == '*' ? "\\2A" : 32340266059SGregory Neil Shapiro (*k == '(' ? "\\28" : 32440266059SGregory Neil Shapiro (*k == ')' ? "\\29" : 32540266059SGregory Neil Shapiro (*k == '\\' ? "\\5C" : 32640266059SGregory Neil Shapiro "\00")))), 32740266059SGregory Neil Shapiro SPACELEFT(filter, fp)); 32840266059SGregory Neil Shapiro fp += strlen(fp); 32940266059SGregory Neil Shapiro k++; 33040266059SGregory Neil Shapiro } 33140266059SGregory Neil Shapiro else 33240266059SGregory Neil Shapiro *fp++ = *k++; 33340266059SGregory Neil Shapiro } 33440266059SGregory Neil Shapiro } 33540266059SGregory Neil Shapiro else 33640266059SGregory Neil Shapiro { 33740266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 33840266059SGregory Neil Shapiro "%.*s", (int) (q - p + 1), p); 33940266059SGregory Neil Shapiro p = q + (q[1] == '%' ? 2 : 1); 34040266059SGregory Neil Shapiro fp += strlen(fp); 34140266059SGregory Neil Shapiro } 34240266059SGregory Neil Shapiro } 34340266059SGregory Neil Shapiro (void) sm_strlcpy(fp, p, SPACELEFT(filter, fp)); 34440266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 20)) 34540266059SGregory Neil Shapiro sm_dprintf("ldap search filter=%s\n", filter); 34640266059SGregory Neil Shapiro 34740266059SGregory Neil Shapiro lmap->ldap_res = NULL; 348605302a5SGregory Neil Shapiro msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, 349605302a5SGregory Neil Shapiro lmap->ldap_scope, filter, 35040266059SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? NULL : 35140266059SGregory Neil Shapiro lmap->ldap_attr), 35240266059SGregory Neil Shapiro lmap->ldap_attrsonly); 35340266059SGregory Neil Shapiro return msgid; 35440266059SGregory Neil Shapiro } 35540266059SGregory Neil Shapiro 35640266059SGregory Neil Shapiro /* 357605302a5SGregory Neil Shapiro ** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a 358605302a5SGregory Neil Shapiro ** particular objectClass 359605302a5SGregory Neil Shapiro ** 360605302a5SGregory Neil Shapiro ** Parameters: 361605302a5SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT in use 362605302a5SGregory Neil Shapiro ** entry -- current LDAP entry struct 363605302a5SGregory Neil Shapiro ** ocvalue -- particular objectclass in question. 364605302a5SGregory Neil Shapiro ** may be of form (fee|foo|fum) meaning 365605302a5SGregory Neil Shapiro ** any entry can be part of either fee, 366605302a5SGregory Neil Shapiro ** foo or fum objectclass 367605302a5SGregory Neil Shapiro ** 368605302a5SGregory Neil Shapiro ** Returns: 369605302a5SGregory Neil Shapiro ** true if item has that objectClass 370605302a5SGregory Neil Shapiro */ 371605302a5SGregory Neil Shapiro 372605302a5SGregory Neil Shapiro static bool 373605302a5SGregory Neil Shapiro sm_ldap_has_objectclass(lmap, entry, ocvalue) 374605302a5SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 375605302a5SGregory Neil Shapiro LDAPMessage *entry; 376605302a5SGregory Neil Shapiro char *ocvalue; 377605302a5SGregory Neil Shapiro { 378605302a5SGregory Neil Shapiro char **vals = NULL; 379605302a5SGregory Neil Shapiro int i; 380605302a5SGregory Neil Shapiro 381605302a5SGregory Neil Shapiro if (ocvalue == NULL) 382605302a5SGregory Neil Shapiro return false; 383605302a5SGregory Neil Shapiro 384605302a5SGregory Neil Shapiro vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass"); 385605302a5SGregory Neil Shapiro if (vals == NULL) 386605302a5SGregory Neil Shapiro return false; 387605302a5SGregory Neil Shapiro 388605302a5SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 389605302a5SGregory Neil Shapiro { 390605302a5SGregory Neil Shapiro char *p; 391605302a5SGregory Neil Shapiro char *q; 392605302a5SGregory Neil Shapiro 393605302a5SGregory Neil Shapiro p = q = ocvalue; 394605302a5SGregory Neil Shapiro while (*p != '\0') 395605302a5SGregory Neil Shapiro { 396605302a5SGregory Neil Shapiro while (*p != '\0' && *p != '|') 397605302a5SGregory Neil Shapiro p++; 398605302a5SGregory Neil Shapiro 399605302a5SGregory Neil Shapiro if ((p - q) == strlen(vals[i]) && 400605302a5SGregory Neil Shapiro sm_strncasecmp(vals[i], q, p - q) == 0) 401605302a5SGregory Neil Shapiro { 402605302a5SGregory Neil Shapiro ldap_value_free(vals); 403605302a5SGregory Neil Shapiro return true; 404605302a5SGregory Neil Shapiro } 405605302a5SGregory Neil Shapiro 406605302a5SGregory Neil Shapiro while (*p == '|') 407605302a5SGregory Neil Shapiro p++; 408605302a5SGregory Neil Shapiro q = p; 409605302a5SGregory Neil Shapiro } 410605302a5SGregory Neil Shapiro } 411605302a5SGregory Neil Shapiro 412605302a5SGregory Neil Shapiro ldap_value_free(vals); 413605302a5SGregory Neil Shapiro return false; 414605302a5SGregory Neil Shapiro } 415605302a5SGregory Neil Shapiro 416605302a5SGregory Neil Shapiro /* 41740266059SGregory Neil Shapiro ** SM_LDAP_RESULTS -- return results from an LDAP lookup in result 41840266059SGregory Neil Shapiro ** 41940266059SGregory Neil Shapiro ** Parameters: 42040266059SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT in use 42140266059SGregory Neil Shapiro ** msgid -- msgid returned by sm_ldap_search() 42240266059SGregory Neil Shapiro ** flags -- flags for the lookup 42340266059SGregory Neil Shapiro ** delim -- delimiter for result concatenation 42440266059SGregory Neil Shapiro ** rpool -- memory pool for storage 42540266059SGregory Neil Shapiro ** result -- return string 42640266059SGregory Neil Shapiro ** recurse -- recursion list 42740266059SGregory Neil Shapiro ** 42840266059SGregory Neil Shapiro ** Returns: 42940266059SGregory Neil Shapiro ** status (sysexit) 43040266059SGregory Neil Shapiro */ 43140266059SGregory Neil Shapiro 432605302a5SGregory Neil Shapiro # define SM_LDAP_ERROR_CLEANUP() \ 43340266059SGregory Neil Shapiro { \ 43440266059SGregory Neil Shapiro if (lmap->ldap_res != NULL) \ 43540266059SGregory Neil Shapiro { \ 43640266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); \ 43740266059SGregory Neil Shapiro lmap->ldap_res = NULL; \ 43840266059SGregory Neil Shapiro } \ 43940266059SGregory Neil Shapiro (void) ldap_abandon(lmap->ldap_ld, msgid); \ 44040266059SGregory Neil Shapiro } 44140266059SGregory Neil Shapiro 442605302a5SGregory Neil Shapiro static SM_LDAP_RECURSE_ENTRY * 443605302a5SGregory Neil Shapiro sm_ldap_add_recurse(top, item, type, rpool) 44440266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST **top; 44540266059SGregory Neil Shapiro char *item; 44640266059SGregory Neil Shapiro int type; 44740266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 44840266059SGregory Neil Shapiro { 449605302a5SGregory Neil Shapiro int n; 450605302a5SGregory Neil Shapiro int m; 451605302a5SGregory Neil Shapiro int p; 452605302a5SGregory Neil Shapiro int insertat; 453605302a5SGregory Neil Shapiro int moveb; 454605302a5SGregory Neil Shapiro int oldsizeb; 455605302a5SGregory Neil Shapiro int rc; 456605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY *newe; 457605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY **olddata; 45840266059SGregory Neil Shapiro 459605302a5SGregory Neil Shapiro /* 460605302a5SGregory Neil Shapiro ** This code will maintain a list of 461605302a5SGregory Neil Shapiro ** SM_LDAP_RECURSE_ENTRY structures 462605302a5SGregory Neil Shapiro ** in ascending order. 463605302a5SGregory Neil Shapiro */ 464605302a5SGregory Neil Shapiro 465605302a5SGregory Neil Shapiro if (*top == NULL) 46640266059SGregory Neil Shapiro { 467605302a5SGregory Neil Shapiro /* Allocate an initial SM_LDAP_RECURSE_LIST struct */ 468605302a5SGregory Neil Shapiro *top = sm_rpool_malloc_x(rpool, sizeof **top); 469605302a5SGregory Neil Shapiro (*top)->lr_cnt = 0; 470605302a5SGregory Neil Shapiro (*top)->lr_size = 0; 471605302a5SGregory Neil Shapiro (*top)->lr_data = NULL; 47240266059SGregory Neil Shapiro } 47340266059SGregory Neil Shapiro 474605302a5SGregory Neil Shapiro if ((*top)->lr_cnt >= (*top)->lr_size) 475605302a5SGregory Neil Shapiro { 476605302a5SGregory Neil Shapiro /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */ 477605302a5SGregory Neil Shapiro olddata = (*top)->lr_data; 478605302a5SGregory Neil Shapiro if ((*top)->lr_size == 0) 479605302a5SGregory Neil Shapiro { 480605302a5SGregory Neil Shapiro oldsizeb = 0; 481605302a5SGregory Neil Shapiro (*top)->lr_size = 256; 482605302a5SGregory Neil Shapiro } 48340266059SGregory Neil Shapiro else 484605302a5SGregory Neil Shapiro { 485605302a5SGregory Neil Shapiro oldsizeb = (*top)->lr_size * sizeof *((*top)->lr_data); 486605302a5SGregory Neil Shapiro (*top)->lr_size *= 2; 487605302a5SGregory Neil Shapiro } 488605302a5SGregory Neil Shapiro (*top)->lr_data = sm_rpool_malloc_x(rpool, 489605302a5SGregory Neil Shapiro (*top)->lr_size * sizeof *((*top)->lr_data)); 490605302a5SGregory Neil Shapiro if (oldsizeb > 0) 491605302a5SGregory Neil Shapiro memcpy((*top)->lr_data, olddata, oldsizeb); 492605302a5SGregory Neil Shapiro } 493605302a5SGregory Neil Shapiro 494605302a5SGregory Neil Shapiro /* 495605302a5SGregory Neil Shapiro ** Binary search/insert item:type into list. 496605302a5SGregory Neil Shapiro ** Return current entry pointer if already exists. 497605302a5SGregory Neil Shapiro */ 498605302a5SGregory Neil Shapiro 499605302a5SGregory Neil Shapiro n = 0; 500605302a5SGregory Neil Shapiro m = (*top)->lr_cnt - 1; 501605302a5SGregory Neil Shapiro if (m < 0) 502605302a5SGregory Neil Shapiro insertat = 0; 503605302a5SGregory Neil Shapiro else 504605302a5SGregory Neil Shapiro insertat = -1; 505605302a5SGregory Neil Shapiro 506605302a5SGregory Neil Shapiro while (insertat == -1) 507605302a5SGregory Neil Shapiro { 508605302a5SGregory Neil Shapiro p = (m + n) / 2; 509605302a5SGregory Neil Shapiro 510605302a5SGregory Neil Shapiro rc = sm_strcasecmp(item, (*top)->lr_data[p]->lr_search); 511605302a5SGregory Neil Shapiro if (rc == 0) 512605302a5SGregory Neil Shapiro rc = type - (*top)->lr_data[p]->lr_type; 513605302a5SGregory Neil Shapiro 514605302a5SGregory Neil Shapiro if (rc < 0) 515605302a5SGregory Neil Shapiro m = p - 1; 516605302a5SGregory Neil Shapiro else if (rc > 0) 517605302a5SGregory Neil Shapiro n = p + 1; 518605302a5SGregory Neil Shapiro else 519605302a5SGregory Neil Shapiro return (*top)->lr_data[p]; 520605302a5SGregory Neil Shapiro 521605302a5SGregory Neil Shapiro if (m == -1) 522605302a5SGregory Neil Shapiro insertat = 0; 523605302a5SGregory Neil Shapiro else if (n >= (*top)->lr_cnt) 524605302a5SGregory Neil Shapiro insertat = (*top)->lr_cnt; 525605302a5SGregory Neil Shapiro else if (m < n) 526605302a5SGregory Neil Shapiro insertat = m + 1; 527605302a5SGregory Neil Shapiro } 528605302a5SGregory Neil Shapiro 529605302a5SGregory Neil Shapiro /* 530605302a5SGregory Neil Shapiro ** Not found in list, make room 531605302a5SGregory Neil Shapiro ** at insert point and add it. 532605302a5SGregory Neil Shapiro */ 533605302a5SGregory Neil Shapiro 534605302a5SGregory Neil Shapiro newe = sm_rpool_malloc_x(rpool, sizeof *newe); 535605302a5SGregory Neil Shapiro if (newe != NULL) 536605302a5SGregory Neil Shapiro { 537605302a5SGregory Neil Shapiro moveb = ((*top)->lr_cnt - insertat) * sizeof *((*top)->lr_data); 538605302a5SGregory Neil Shapiro if (moveb > 0) 539605302a5SGregory Neil Shapiro memmove(&((*top)->lr_data[insertat + 1]), 540605302a5SGregory Neil Shapiro &((*top)->lr_data[insertat]), 541605302a5SGregory Neil Shapiro moveb); 542605302a5SGregory Neil Shapiro 543605302a5SGregory Neil Shapiro newe->lr_search = sm_rpool_strdup_x(rpool, item); 544605302a5SGregory Neil Shapiro newe->lr_type = type; 545e92d3f3fSGregory Neil Shapiro newe->lr_ludp = NULL; 546e92d3f3fSGregory Neil Shapiro newe->lr_attrs = NULL; 547605302a5SGregory Neil Shapiro newe->lr_done = false; 548605302a5SGregory Neil Shapiro 549605302a5SGregory Neil Shapiro ((*top)->lr_data)[insertat] = newe; 550605302a5SGregory Neil Shapiro (*top)->lr_cnt++; 551605302a5SGregory Neil Shapiro } 552605302a5SGregory Neil Shapiro return newe; 55340266059SGregory Neil Shapiro } 55440266059SGregory Neil Shapiro 55540266059SGregory Neil Shapiro int 556605302a5SGregory Neil Shapiro sm_ldap_results(lmap, msgid, flags, delim, rpool, result, 557605302a5SGregory Neil Shapiro resultln, resultsz, recurse) 55840266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 55940266059SGregory Neil Shapiro int msgid; 56040266059SGregory Neil Shapiro int flags; 561605302a5SGregory Neil Shapiro int delim; 56240266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 56340266059SGregory Neil Shapiro char **result; 564605302a5SGregory Neil Shapiro int *resultln; 565605302a5SGregory Neil Shapiro int *resultsz; 56640266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST *recurse; 56740266059SGregory Neil Shapiro { 56840266059SGregory Neil Shapiro bool toplevel; 56940266059SGregory Neil Shapiro int i; 57040266059SGregory Neil Shapiro int statp; 57140266059SGregory Neil Shapiro int vsize; 57240266059SGregory Neil Shapiro int ret; 57340266059SGregory Neil Shapiro int save_errno; 57440266059SGregory Neil Shapiro char *p; 575605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY *rl; 57640266059SGregory Neil Shapiro 57740266059SGregory Neil Shapiro /* Are we the top top level of the search? */ 57840266059SGregory Neil Shapiro toplevel = (recurse == NULL); 57940266059SGregory Neil Shapiro 58040266059SGregory Neil Shapiro /* Get results */ 58140266059SGregory Neil Shapiro statp = EX_NOTFOUND; 58240266059SGregory Neil Shapiro while ((ret = ldap_result(lmap->ldap_ld, msgid, 0, 58340266059SGregory Neil Shapiro (lmap->ldap_timeout.tv_sec == 0 ? NULL : 58440266059SGregory Neil Shapiro &(lmap->ldap_timeout)), 58540266059SGregory Neil Shapiro &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) 58640266059SGregory Neil Shapiro { 58740266059SGregory Neil Shapiro LDAPMessage *entry; 58840266059SGregory Neil Shapiro 58940266059SGregory Neil Shapiro /* If we don't want multiple values and we have one, break */ 590605302a5SGregory Neil Shapiro if ((char) delim == '\0' && *result != NULL) 59140266059SGregory Neil Shapiro break; 59240266059SGregory Neil Shapiro 59340266059SGregory Neil Shapiro /* Cycle through all entries */ 59440266059SGregory Neil Shapiro for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); 59540266059SGregory Neil Shapiro entry != NULL; 59640266059SGregory Neil Shapiro entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) 59740266059SGregory Neil Shapiro { 59840266059SGregory Neil Shapiro BerElement *ber; 59940266059SGregory Neil Shapiro char *attr; 60040266059SGregory Neil Shapiro char **vals = NULL; 60140266059SGregory Neil Shapiro char *dn; 60240266059SGregory Neil Shapiro 60340266059SGregory Neil Shapiro /* 60440266059SGregory Neil Shapiro ** If matching only and found an entry, 60540266059SGregory Neil Shapiro ** no need to spin through attributes 60640266059SGregory Neil Shapiro */ 60740266059SGregory Neil Shapiro 608323f6dcbSGregory Neil Shapiro if (bitset(SM_LDAP_MATCHONLY, flags)) 609323f6dcbSGregory Neil Shapiro { 610323f6dcbSGregory Neil Shapiro statp = EX_OK; 61140266059SGregory Neil Shapiro continue; 612323f6dcbSGregory Neil Shapiro } 61340266059SGregory Neil Shapiro 61440266059SGregory Neil Shapiro /* record completed DN's to prevent loops */ 61540266059SGregory Neil Shapiro dn = ldap_get_dn(lmap->ldap_ld, entry); 61640266059SGregory Neil Shapiro if (dn == NULL) 61740266059SGregory Neil Shapiro { 61840266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 61940266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 620605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 62140266059SGregory Neil Shapiro errno = save_errno; 622a7ec597cSGregory Neil Shapiro return EX_TEMPFAIL; 62340266059SGregory Neil Shapiro } 62440266059SGregory Neil Shapiro 625605302a5SGregory Neil Shapiro rl = sm_ldap_add_recurse(&recurse, dn, 626605302a5SGregory Neil Shapiro SM_LDAP_ATTR_DN, 627605302a5SGregory Neil Shapiro rpool); 628605302a5SGregory Neil Shapiro 629605302a5SGregory Neil Shapiro if (rl == NULL) 63040266059SGregory Neil Shapiro { 63140266059SGregory Neil Shapiro ldap_memfree(dn); 632605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 63340266059SGregory Neil Shapiro errno = ENOMEM; 63440266059SGregory Neil Shapiro return EX_OSERR; 635605302a5SGregory Neil Shapiro } 636605302a5SGregory Neil Shapiro else if (rl->lr_done) 637605302a5SGregory Neil Shapiro { 63840266059SGregory Neil Shapiro /* already on list, skip it */ 63940266059SGregory Neil Shapiro ldap_memfree(dn); 64040266059SGregory Neil Shapiro continue; 64140266059SGregory Neil Shapiro } 64240266059SGregory Neil Shapiro ldap_memfree(dn); 64340266059SGregory Neil Shapiro 64440266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 64540266059SGregory Neil Shapiro /* 64640266059SGregory Neil Shapiro ** Reset value to prevent lingering 64740266059SGregory Neil Shapiro ** LDAP_DECODING_ERROR due to 64840266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see below) 64940266059SGregory Neil Shapiro */ 65040266059SGregory Neil Shapiro 65140266059SGregory Neil Shapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 65240266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 65340266059SGregory Neil Shapiro 65440266059SGregory Neil Shapiro for (attr = ldap_first_attribute(lmap->ldap_ld, entry, 65540266059SGregory Neil Shapiro &ber); 65640266059SGregory Neil Shapiro attr != NULL; 65740266059SGregory Neil Shapiro attr = ldap_next_attribute(lmap->ldap_ld, entry, 65840266059SGregory Neil Shapiro ber)) 65940266059SGregory Neil Shapiro { 66040266059SGregory Neil Shapiro char *tmp, *vp_tmp; 66140266059SGregory Neil Shapiro int type; 662605302a5SGregory Neil Shapiro char *needobjclass = NULL; 66340266059SGregory Neil Shapiro 664605302a5SGregory Neil Shapiro type = SM_LDAP_ATTR_NONE; 66540266059SGregory Neil Shapiro for (i = 0; lmap->ldap_attr[i] != NULL; i++) 66640266059SGregory Neil Shapiro { 66740266059SGregory Neil Shapiro if (sm_strcasecmp(lmap->ldap_attr[i], 66840266059SGregory Neil Shapiro attr) == 0) 66940266059SGregory Neil Shapiro { 67040266059SGregory Neil Shapiro type = lmap->ldap_attr_type[i]; 671605302a5SGregory Neil Shapiro needobjclass = lmap->ldap_attr_needobjclass[i]; 67240266059SGregory Neil Shapiro break; 67340266059SGregory Neil Shapiro } 67440266059SGregory Neil Shapiro } 675605302a5SGregory Neil Shapiro 676605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_USE_ALLATTR, flags) && 677605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_NONE) 678605302a5SGregory Neil Shapiro { 679605302a5SGregory Neil Shapiro /* URL lookups specify attrs to use */ 680605302a5SGregory Neil Shapiro type = SM_LDAP_ATTR_NORMAL; 681605302a5SGregory Neil Shapiro needobjclass = NULL; 682605302a5SGregory Neil Shapiro } 683605302a5SGregory Neil Shapiro 684605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NONE) 68540266059SGregory Neil Shapiro { 68640266059SGregory Neil Shapiro /* attribute not requested */ 68740266059SGregory Neil Shapiro ldap_memfree(attr); 688605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 68940266059SGregory Neil Shapiro errno = EFAULT; 69040266059SGregory Neil Shapiro return EX_SOFTWARE; 69140266059SGregory Neil Shapiro } 69240266059SGregory Neil Shapiro 693605302a5SGregory Neil Shapiro /* 694605302a5SGregory Neil Shapiro ** For recursion on a particular attribute, 695605302a5SGregory Neil Shapiro ** we may need to see if this entry is 696605302a5SGregory Neil Shapiro ** part of a particular objectclass. 697605302a5SGregory Neil Shapiro ** Also, ignore objectClass attribute. 698605302a5SGregory Neil Shapiro ** Otherwise we just ignore this attribute. 699605302a5SGregory Neil Shapiro */ 700605302a5SGregory Neil Shapiro 701605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_OBJCLASS || 702605302a5SGregory Neil Shapiro (needobjclass != NULL && 703605302a5SGregory Neil Shapiro !sm_ldap_has_objectclass(lmap, entry, 704605302a5SGregory Neil Shapiro needobjclass))) 705605302a5SGregory Neil Shapiro { 706605302a5SGregory Neil Shapiro ldap_memfree(attr); 707605302a5SGregory Neil Shapiro continue; 708605302a5SGregory Neil Shapiro } 709605302a5SGregory Neil Shapiro 71040266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 71140266059SGregory Neil Shapiro { 71240266059SGregory Neil Shapiro vals = ldap_get_values(lmap->ldap_ld, 71340266059SGregory Neil Shapiro entry, 71440266059SGregory Neil Shapiro attr); 71540266059SGregory Neil Shapiro if (vals == NULL) 71640266059SGregory Neil Shapiro { 71740266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 71840266059SGregory Neil Shapiro if (save_errno == LDAP_SUCCESS) 71940266059SGregory Neil Shapiro { 72040266059SGregory Neil Shapiro ldap_memfree(attr); 72140266059SGregory Neil Shapiro continue; 72240266059SGregory Neil Shapiro } 72340266059SGregory Neil Shapiro 72440266059SGregory Neil Shapiro /* Must be an error */ 72540266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 72640266059SGregory Neil Shapiro ldap_memfree(attr); 727605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 72840266059SGregory Neil Shapiro errno = save_errno; 72940266059SGregory Neil Shapiro return EX_TEMPFAIL; 73040266059SGregory Neil Shapiro } 73140266059SGregory Neil Shapiro } 73240266059SGregory Neil Shapiro 73340266059SGregory Neil Shapiro statp = EX_OK; 73440266059SGregory Neil Shapiro 73540266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 73640266059SGregory Neil Shapiro /* 73740266059SGregory Neil Shapiro ** Reset value to prevent lingering 73840266059SGregory Neil Shapiro ** LDAP_DECODING_ERROR due to 73940266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see below) 74040266059SGregory Neil Shapiro */ 74140266059SGregory Neil Shapiro 74240266059SGregory Neil Shapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 74340266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 74440266059SGregory Neil Shapiro 74540266059SGregory Neil Shapiro /* 74640266059SGregory Neil Shapiro ** If matching only, 74740266059SGregory Neil Shapiro ** no need to spin through entries 74840266059SGregory Neil Shapiro */ 74940266059SGregory Neil Shapiro 75040266059SGregory Neil Shapiro if (bitset(SM_LDAP_MATCHONLY, flags)) 75140266059SGregory Neil Shapiro { 75240266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 75340266059SGregory Neil Shapiro ldap_value_free(vals); 75440266059SGregory Neil Shapiro ldap_memfree(attr); 75540266059SGregory Neil Shapiro continue; 75640266059SGregory Neil Shapiro } 75740266059SGregory Neil Shapiro 75840266059SGregory Neil Shapiro /* 75940266059SGregory Neil Shapiro ** If we don't want multiple values, 76040266059SGregory Neil Shapiro ** return first found. 76140266059SGregory Neil Shapiro */ 76240266059SGregory Neil Shapiro 763605302a5SGregory Neil Shapiro if ((char) delim == '\0') 76440266059SGregory Neil Shapiro { 765605302a5SGregory Neil Shapiro if (*result != NULL) 766605302a5SGregory Neil Shapiro { 767605302a5SGregory Neil Shapiro /* already have a value */ 768605302a5SGregory Neil Shapiro break; 769605302a5SGregory Neil Shapiro } 770605302a5SGregory Neil Shapiro 771605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEMATCH, 772605302a5SGregory Neil Shapiro flags) && 773605302a5SGregory Neil Shapiro *result != NULL) 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 } 780605302a5SGregory Neil Shapiro 78140266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 78240266059SGregory Neil Shapiro { 78340266059SGregory Neil Shapiro *result = sm_rpool_strdup_x(rpool, 78440266059SGregory Neil Shapiro attr); 78540266059SGregory Neil Shapiro ldap_memfree(attr); 78640266059SGregory Neil Shapiro break; 78740266059SGregory Neil Shapiro } 78840266059SGregory Neil Shapiro 78940266059SGregory Neil Shapiro if (vals[0] == NULL) 79040266059SGregory Neil Shapiro { 79140266059SGregory Neil Shapiro ldap_value_free(vals); 79240266059SGregory Neil Shapiro ldap_memfree(attr); 79340266059SGregory Neil Shapiro continue; 79440266059SGregory Neil Shapiro } 79540266059SGregory Neil Shapiro 79640266059SGregory Neil Shapiro vsize = strlen(vals[0]) + 1; 79740266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 79840266059SGregory Neil Shapiro vsize += strlen(attr) + 1; 79940266059SGregory Neil Shapiro *result = sm_rpool_malloc_x(rpool, 80040266059SGregory Neil Shapiro vsize); 80140266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 80240266059SGregory Neil Shapiro sm_snprintf(*result, vsize, 80340266059SGregory Neil Shapiro "%s%c%s", 80440266059SGregory Neil Shapiro attr, 80540266059SGregory Neil Shapiro lmap->ldap_attrsep, 80640266059SGregory Neil Shapiro vals[0]); 80740266059SGregory Neil Shapiro else 80840266059SGregory Neil Shapiro sm_strlcpy(*result, vals[0], 80940266059SGregory Neil Shapiro vsize); 81040266059SGregory Neil Shapiro ldap_value_free(vals); 81140266059SGregory Neil Shapiro ldap_memfree(attr); 81240266059SGregory Neil Shapiro break; 81340266059SGregory Neil Shapiro } 81440266059SGregory Neil Shapiro 81540266059SGregory Neil Shapiro /* attributes only */ 81640266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 81740266059SGregory Neil Shapiro { 81840266059SGregory Neil Shapiro if (*result == NULL) 81940266059SGregory Neil Shapiro *result = sm_rpool_strdup_x(rpool, 82040266059SGregory Neil Shapiro attr); 82140266059SGregory Neil Shapiro else 82240266059SGregory Neil Shapiro { 823605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEMATCH, 824605302a5SGregory Neil Shapiro flags) && 825605302a5SGregory Neil Shapiro *result != NULL) 826605302a5SGregory Neil Shapiro { 827605302a5SGregory Neil Shapiro /* only wanted one match */ 828605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 829605302a5SGregory Neil Shapiro errno = ENOENT; 830605302a5SGregory Neil Shapiro return EX_NOTFOUND; 831605302a5SGregory Neil Shapiro } 832605302a5SGregory Neil Shapiro 83340266059SGregory Neil Shapiro vsize = strlen(*result) + 83440266059SGregory Neil Shapiro strlen(attr) + 2; 83540266059SGregory Neil Shapiro tmp = sm_rpool_malloc_x(rpool, 83640266059SGregory Neil Shapiro vsize); 83740266059SGregory Neil Shapiro (void) sm_snprintf(tmp, 83840266059SGregory Neil Shapiro vsize, "%s%c%s", 839605302a5SGregory Neil Shapiro *result, (char) delim, 84040266059SGregory Neil Shapiro attr); 84140266059SGregory Neil Shapiro *result = tmp; 84240266059SGregory Neil Shapiro } 84340266059SGregory Neil Shapiro ldap_memfree(attr); 84440266059SGregory Neil Shapiro continue; 84540266059SGregory Neil Shapiro } 84640266059SGregory Neil Shapiro 84740266059SGregory Neil Shapiro /* 848605302a5SGregory Neil Shapiro ** If there is more than one, munge then 849605302a5SGregory Neil Shapiro ** into a map_coldelim separated string. 850605302a5SGregory Neil Shapiro ** If we are recursing we may have an entry 851605302a5SGregory Neil Shapiro ** with no 'normal' values to put in the 852605302a5SGregory Neil Shapiro ** string. 853605302a5SGregory Neil Shapiro ** This is not an error. 85440266059SGregory Neil Shapiro */ 85540266059SGregory Neil Shapiro 856605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NORMAL && 857605302a5SGregory Neil Shapiro bitset(SM_LDAP_SINGLEMATCH, flags) && 858605302a5SGregory Neil Shapiro *result != NULL) 859605302a5SGregory Neil Shapiro { 860605302a5SGregory Neil Shapiro /* only wanted one match */ 861605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 862605302a5SGregory Neil Shapiro errno = ENOENT; 863605302a5SGregory Neil Shapiro return EX_NOTFOUND; 864605302a5SGregory Neil Shapiro } 865605302a5SGregory Neil Shapiro 86640266059SGregory Neil Shapiro vsize = 0; 86740266059SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 86840266059SGregory Neil Shapiro { 869605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_DN || 870605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_FILTER || 871605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_URL) 87240266059SGregory Neil Shapiro { 873605302a5SGregory Neil Shapiro /* add to recursion */ 874605302a5SGregory Neil Shapiro if (sm_ldap_add_recurse(&recurse, 87540266059SGregory Neil Shapiro vals[i], 876605302a5SGregory Neil Shapiro type, 877605302a5SGregory Neil Shapiro rpool) == NULL) 87840266059SGregory Neil Shapiro { 879605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 88040266059SGregory Neil Shapiro errno = ENOMEM; 88140266059SGregory Neil Shapiro return EX_OSERR; 88240266059SGregory Neil Shapiro } 88340266059SGregory Neil Shapiro continue; 88440266059SGregory Neil Shapiro } 885605302a5SGregory Neil Shapiro 88640266059SGregory Neil Shapiro vsize += strlen(vals[i]) + 1; 88740266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 88840266059SGregory Neil Shapiro vsize += strlen(attr) + 1; 88940266059SGregory Neil Shapiro } 890605302a5SGregory Neil Shapiro 891605302a5SGregory Neil Shapiro /* 892605302a5SGregory Neil Shapiro ** Create/Append to string any normal 893605302a5SGregory Neil Shapiro ** attribute values. Otherwise, just free 894605302a5SGregory Neil Shapiro ** memory and move on to the next 895605302a5SGregory Neil Shapiro ** attribute in this entry. 896605302a5SGregory Neil Shapiro */ 897605302a5SGregory Neil Shapiro 898605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NORMAL && vsize > 0) 899605302a5SGregory Neil Shapiro { 900605302a5SGregory Neil Shapiro char *pe; 901605302a5SGregory Neil Shapiro 902605302a5SGregory Neil Shapiro /* Grow result string if needed */ 903605302a5SGregory Neil Shapiro if ((*resultln + vsize) >= *resultsz) 904605302a5SGregory Neil Shapiro { 905605302a5SGregory Neil Shapiro while ((*resultln + vsize) >= *resultsz) 906605302a5SGregory Neil Shapiro { 907605302a5SGregory Neil Shapiro if (*resultsz == 0) 908605302a5SGregory Neil Shapiro *resultsz = 1024; 909605302a5SGregory Neil Shapiro else 910605302a5SGregory Neil Shapiro *resultsz *= 2; 911605302a5SGregory Neil Shapiro } 912605302a5SGregory Neil Shapiro 913605302a5SGregory Neil Shapiro vp_tmp = sm_rpool_malloc_x(rpool, *resultsz); 91440266059SGregory Neil Shapiro *vp_tmp = '\0'; 91540266059SGregory Neil Shapiro 916605302a5SGregory Neil Shapiro if (*result != NULL) 917605302a5SGregory Neil Shapiro sm_strlcpy(vp_tmp, 918605302a5SGregory Neil Shapiro *result, 919605302a5SGregory Neil Shapiro *resultsz); 920605302a5SGregory Neil Shapiro *result = vp_tmp; 921605302a5SGregory Neil Shapiro } 922605302a5SGregory Neil Shapiro 923605302a5SGregory Neil Shapiro p = *result + *resultln; 924605302a5SGregory Neil Shapiro pe = *result + *resultsz; 925605302a5SGregory Neil Shapiro 92640266059SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 92740266059SGregory Neil Shapiro { 928959366dcSGregory Neil Shapiro if (*resultln > 0 && 929959366dcSGregory Neil Shapiro p < pe) 930605302a5SGregory Neil Shapiro *p++ = (char) delim; 931605302a5SGregory Neil Shapiro 93240266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 93340266059SGregory Neil Shapiro { 93440266059SGregory Neil Shapiro p += sm_strlcpy(p, attr, 935605302a5SGregory Neil Shapiro pe - p); 936605302a5SGregory Neil Shapiro if (p < pe) 93740266059SGregory Neil Shapiro *p++ = lmap->ldap_attrsep; 93840266059SGregory Neil Shapiro } 939605302a5SGregory Neil Shapiro 94040266059SGregory Neil Shapiro p += sm_strlcpy(p, vals[i], 941605302a5SGregory Neil Shapiro pe - p); 942605302a5SGregory Neil Shapiro *resultln = p - (*result); 943605302a5SGregory Neil Shapiro if (p >= pe) 94440266059SGregory Neil Shapiro { 94540266059SGregory Neil Shapiro /* Internal error: buffer too small for LDAP values */ 946605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 94740266059SGregory Neil Shapiro errno = ENOMEM; 94840266059SGregory Neil Shapiro return EX_OSERR; 94940266059SGregory Neil Shapiro } 950605302a5SGregory Neil Shapiro } 95140266059SGregory Neil Shapiro } 95240266059SGregory Neil Shapiro 95340266059SGregory Neil Shapiro ldap_value_free(vals); 95440266059SGregory Neil Shapiro ldap_memfree(attr); 95540266059SGregory Neil Shapiro } 95640266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 95740266059SGregory Neil Shapiro 95840266059SGregory Neil Shapiro /* 95940266059SGregory Neil Shapiro ** We check save_errno != LDAP_DECODING_ERROR since 96040266059SGregory Neil Shapiro ** OpenLDAP 1.X has a very ugly *undocumented* 96140266059SGregory Neil Shapiro ** hack of returning this error code from 96240266059SGregory Neil Shapiro ** ldap_next_attribute() if the library freed the 96340266059SGregory Neil Shapiro ** ber attribute. See: 96440266059SGregory Neil Shapiro ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 96540266059SGregory Neil Shapiro */ 96640266059SGregory Neil Shapiro 96740266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS && 96840266059SGregory Neil Shapiro save_errno != LDAP_DECODING_ERROR) 96940266059SGregory Neil Shapiro { 97040266059SGregory Neil Shapiro /* Must be an error */ 97140266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 972605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 97340266059SGregory Neil Shapiro errno = save_errno; 97440266059SGregory Neil Shapiro return EX_TEMPFAIL; 97540266059SGregory Neil Shapiro } 97640266059SGregory Neil Shapiro 977605302a5SGregory Neil Shapiro /* mark this DN as done */ 978605302a5SGregory Neil Shapiro rl->lr_done = true; 979e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp != NULL) 980e92d3f3fSGregory Neil Shapiro { 981e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 982e92d3f3fSGregory Neil Shapiro rl->lr_ludp = NULL; 983e92d3f3fSGregory Neil Shapiro } 984e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs != NULL) 985e92d3f3fSGregory Neil Shapiro { 986e92d3f3fSGregory Neil Shapiro free(rl->lr_attrs); 987e92d3f3fSGregory Neil Shapiro rl->lr_attrs = NULL; 988e92d3f3fSGregory Neil Shapiro } 989605302a5SGregory Neil Shapiro 99040266059SGregory Neil Shapiro /* We don't want multiple values and we have one */ 991605302a5SGregory Neil Shapiro if ((char) delim == '\0' && *result != NULL) 99240266059SGregory Neil Shapiro break; 99340266059SGregory Neil Shapiro } 99440266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 99540266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS && 99640266059SGregory Neil Shapiro save_errno != LDAP_DECODING_ERROR) 99740266059SGregory Neil Shapiro { 99840266059SGregory Neil Shapiro /* Must be an error */ 99940266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 1000605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 100140266059SGregory Neil Shapiro errno = save_errno; 100240266059SGregory Neil Shapiro return EX_TEMPFAIL; 100340266059SGregory Neil Shapiro } 100440266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); 100540266059SGregory Neil Shapiro lmap->ldap_res = NULL; 100640266059SGregory Neil Shapiro } 100740266059SGregory Neil Shapiro 100840266059SGregory Neil Shapiro if (ret == 0) 100940266059SGregory Neil Shapiro save_errno = ETIMEDOUT; 101040266059SGregory Neil Shapiro else 101140266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 101240266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS) 101340266059SGregory Neil Shapiro { 101440266059SGregory Neil Shapiro statp = EX_TEMPFAIL; 101540266059SGregory Neil Shapiro if (ret != 0) 101640266059SGregory Neil Shapiro { 101740266059SGregory Neil Shapiro switch (save_errno) 101840266059SGregory Neil Shapiro { 101940266059SGregory Neil Shapiro #ifdef LDAP_SERVER_DOWN 102040266059SGregory Neil Shapiro case LDAP_SERVER_DOWN: 102140266059SGregory Neil Shapiro #endif /* LDAP_SERVER_DOWN */ 102240266059SGregory Neil Shapiro case LDAP_TIMEOUT: 102340266059SGregory Neil Shapiro case LDAP_UNAVAILABLE: 1024605302a5SGregory Neil Shapiro 1025605302a5SGregory Neil Shapiro /* 1026605302a5SGregory Neil Shapiro ** server disappeared, 1027605302a5SGregory Neil Shapiro ** try reopen on next search 1028605302a5SGregory Neil Shapiro */ 1029605302a5SGregory Neil Shapiro 103040266059SGregory Neil Shapiro statp = EX_RESTART; 103140266059SGregory Neil Shapiro break; 103240266059SGregory Neil Shapiro } 103340266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 103440266059SGregory Neil Shapiro } 1035605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 103640266059SGregory Neil Shapiro errno = save_errno; 103740266059SGregory Neil Shapiro return statp; 103840266059SGregory Neil Shapiro } 103940266059SGregory Neil Shapiro 104040266059SGregory Neil Shapiro if (lmap->ldap_res != NULL) 104140266059SGregory Neil Shapiro { 104240266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); 104340266059SGregory Neil Shapiro lmap->ldap_res = NULL; 104440266059SGregory Neil Shapiro } 104540266059SGregory Neil Shapiro 104640266059SGregory Neil Shapiro if (toplevel) 104740266059SGregory Neil Shapiro { 1048605302a5SGregory Neil Shapiro int rlidx; 104940266059SGregory Neil Shapiro 105040266059SGregory Neil Shapiro /* 105140266059SGregory Neil Shapiro ** Spin through the built-up recurse list at the top 105240266059SGregory Neil Shapiro ** of the recursion. Since new items are added at the 105340266059SGregory Neil Shapiro ** end of the shared list, we actually only ever get 105440266059SGregory Neil Shapiro ** one level of recursion before things pop back to the 105540266059SGregory Neil Shapiro ** top. Any items added to the list during that recursion 105640266059SGregory Neil Shapiro ** will be expanded by the top level. 105740266059SGregory Neil Shapiro */ 105840266059SGregory Neil Shapiro 1059605302a5SGregory Neil Shapiro for (rlidx = 0; recurse != NULL && rlidx < recurse->lr_cnt; rlidx++) 106040266059SGregory Neil Shapiro { 1061605302a5SGregory Neil Shapiro int newflags; 106240266059SGregory Neil Shapiro int sid; 106340266059SGregory Neil Shapiro int status; 106440266059SGregory Neil Shapiro 1065605302a5SGregory Neil Shapiro rl = recurse->lr_data[rlidx]; 1066605302a5SGregory Neil Shapiro 1067605302a5SGregory Neil Shapiro newflags = flags; 1068605302a5SGregory Neil Shapiro if (rl->lr_done) 106940266059SGregory Neil Shapiro { 107040266059SGregory Neil Shapiro /* already expanded */ 107140266059SGregory Neil Shapiro continue; 107240266059SGregory Neil Shapiro } 1073605302a5SGregory Neil Shapiro 1074605302a5SGregory Neil Shapiro if (rl->lr_type == SM_LDAP_ATTR_DN) 107540266059SGregory Neil Shapiro { 107640266059SGregory Neil Shapiro /* do DN search */ 107740266059SGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 107840266059SGregory Neil Shapiro rl->lr_search, 107940266059SGregory Neil Shapiro lmap->ldap_scope, 108040266059SGregory Neil Shapiro "(objectClass=*)", 1081605302a5SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? 1082605302a5SGregory Neil Shapiro NULL : lmap->ldap_attr), 108340266059SGregory Neil Shapiro lmap->ldap_attrsonly); 108440266059SGregory Neil Shapiro } 1085605302a5SGregory Neil Shapiro else if (rl->lr_type == SM_LDAP_ATTR_FILTER) 108640266059SGregory Neil Shapiro { 108740266059SGregory Neil Shapiro /* do new search */ 108840266059SGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 108940266059SGregory Neil Shapiro lmap->ldap_base, 109040266059SGregory Neil Shapiro lmap->ldap_scope, 109140266059SGregory Neil Shapiro rl->lr_search, 1092605302a5SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? 1093605302a5SGregory Neil Shapiro NULL : lmap->ldap_attr), 109440266059SGregory Neil Shapiro lmap->ldap_attrsonly); 109540266059SGregory Neil Shapiro } 1096605302a5SGregory Neil Shapiro else if (rl->lr_type == SM_LDAP_ATTR_URL) 109740266059SGregory Neil Shapiro { 1098e92d3f3fSGregory Neil Shapiro /* Parse URL */ 1099e92d3f3fSGregory Neil Shapiro sid = ldap_url_parse(rl->lr_search, 1100e92d3f3fSGregory Neil Shapiro &rl->lr_ludp); 1101e92d3f3fSGregory Neil Shapiro 1102e92d3f3fSGregory Neil Shapiro if (sid != 0) 1103e92d3f3fSGregory Neil Shapiro { 1104e92d3f3fSGregory Neil Shapiro errno = sid + E_LDAPURLBASE; 1105e92d3f3fSGregory Neil Shapiro return EX_TEMPFAIL; 1106e92d3f3fSGregory Neil Shapiro } 1107e92d3f3fSGregory Neil Shapiro 1108e92d3f3fSGregory Neil Shapiro /* We need to add objectClass */ 1109e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp->lud_attrs != NULL) 1110e92d3f3fSGregory Neil Shapiro { 1111e92d3f3fSGregory Neil Shapiro int attrnum = 0; 1112e92d3f3fSGregory Neil Shapiro 1113e92d3f3fSGregory Neil Shapiro while (rl->lr_ludp->lud_attrs[attrnum] != NULL) 1114e92d3f3fSGregory Neil Shapiro { 1115e92d3f3fSGregory Neil Shapiro if (strcasecmp(rl->lr_ludp->lud_attrs[attrnum], 1116e92d3f3fSGregory Neil Shapiro "objectClass") == 0) 1117e92d3f3fSGregory Neil Shapiro { 1118e92d3f3fSGregory Neil Shapiro /* already requested */ 1119e92d3f3fSGregory Neil Shapiro attrnum = -1; 1120e92d3f3fSGregory Neil Shapiro break; 1121e92d3f3fSGregory Neil Shapiro } 1122e92d3f3fSGregory Neil Shapiro attrnum++; 1123e92d3f3fSGregory Neil Shapiro } 1124e92d3f3fSGregory Neil Shapiro 1125e92d3f3fSGregory Neil Shapiro if (attrnum >= 0) 1126e92d3f3fSGregory Neil Shapiro { 1127e92d3f3fSGregory Neil Shapiro int i; 1128e92d3f3fSGregory Neil Shapiro 1129e92d3f3fSGregory Neil Shapiro rl->lr_attrs = (char **)malloc(sizeof(char *) * (attrnum + 2)); 1130e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs == NULL) 1131e92d3f3fSGregory Neil Shapiro { 1132e92d3f3fSGregory Neil Shapiro save_errno = errno; 1133e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1134e92d3f3fSGregory Neil Shapiro errno = save_errno; 1135e92d3f3fSGregory Neil Shapiro return EX_TEMPFAIL; 1136e92d3f3fSGregory Neil Shapiro } 1137e92d3f3fSGregory Neil Shapiro for (i = 0 ; i < attrnum; i++) 1138e92d3f3fSGregory Neil Shapiro { 1139e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i] = rl->lr_ludp->lud_attrs[i]; 1140e92d3f3fSGregory Neil Shapiro } 1141e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i++] = "objectClass"; 1142e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i++] = NULL; 1143e92d3f3fSGregory Neil Shapiro } 1144e92d3f3fSGregory Neil Shapiro } 1145e92d3f3fSGregory Neil Shapiro 1146e92d3f3fSGregory Neil Shapiro /* 1147e92d3f3fSGregory Neil Shapiro ** Use the existing connection 1148e92d3f3fSGregory Neil Shapiro ** for this search. It really 1149e92d3f3fSGregory Neil Shapiro ** should use lud_scheme://lud_host:lud_port/ 1150e92d3f3fSGregory Neil Shapiro ** instead but that would require 1151e92d3f3fSGregory Neil Shapiro ** opening a new connection. 1152e92d3f3fSGregory Neil Shapiro ** This should be fixed ASAP. 1153e92d3f3fSGregory Neil Shapiro */ 1154e92d3f3fSGregory Neil Shapiro 1155e92d3f3fSGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 1156e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_dn, 1157e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_scope, 1158e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_filter, 1159e92d3f3fSGregory Neil Shapiro rl->lr_attrs, 116040266059SGregory Neil Shapiro lmap->ldap_attrsonly); 1161e92d3f3fSGregory Neil Shapiro 1162e92d3f3fSGregory Neil Shapiro /* Use the attributes specified by URL */ 1163605302a5SGregory Neil Shapiro newflags |= SM_LDAP_USE_ALLATTR; 116440266059SGregory Neil Shapiro } 116540266059SGregory Neil Shapiro else 116640266059SGregory Neil Shapiro { 116740266059SGregory Neil Shapiro /* unknown or illegal attribute type */ 116840266059SGregory Neil Shapiro errno = EFAULT; 116940266059SGregory Neil Shapiro return EX_SOFTWARE; 117040266059SGregory Neil Shapiro } 117140266059SGregory Neil Shapiro 117240266059SGregory Neil Shapiro /* Collect results */ 117340266059SGregory Neil Shapiro if (sid == -1) 117440266059SGregory Neil Shapiro { 117540266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 117640266059SGregory Neil Shapiro statp = EX_TEMPFAIL; 117740266059SGregory Neil Shapiro switch (save_errno) 117840266059SGregory Neil Shapiro { 117940266059SGregory Neil Shapiro #ifdef LDAP_SERVER_DOWN 118040266059SGregory Neil Shapiro case LDAP_SERVER_DOWN: 118140266059SGregory Neil Shapiro #endif /* LDAP_SERVER_DOWN */ 118240266059SGregory Neil Shapiro case LDAP_TIMEOUT: 118340266059SGregory Neil Shapiro case LDAP_UNAVAILABLE: 1184605302a5SGregory Neil Shapiro 1185605302a5SGregory Neil Shapiro /* 1186605302a5SGregory Neil Shapiro ** server disappeared, 1187605302a5SGregory Neil Shapiro ** try reopen on next search 1188605302a5SGregory Neil Shapiro */ 1189605302a5SGregory Neil Shapiro 119040266059SGregory Neil Shapiro statp = EX_RESTART; 119140266059SGregory Neil Shapiro break; 119240266059SGregory Neil Shapiro } 119340266059SGregory Neil Shapiro errno = save_errno + E_LDAPBASE; 119440266059SGregory Neil Shapiro return statp; 119540266059SGregory Neil Shapiro } 119640266059SGregory Neil Shapiro 1197605302a5SGregory Neil Shapiro status = sm_ldap_results(lmap, sid, newflags, delim, 1198605302a5SGregory Neil Shapiro rpool, result, resultln, 1199605302a5SGregory Neil Shapiro resultsz, recurse); 120040266059SGregory Neil Shapiro save_errno = errno; 120140266059SGregory Neil Shapiro if (status != EX_OK && status != EX_NOTFOUND) 120240266059SGregory Neil Shapiro { 120340266059SGregory Neil Shapiro errno = save_errno; 120440266059SGregory Neil Shapiro return status; 120540266059SGregory Neil Shapiro } 120640266059SGregory Neil Shapiro 120740266059SGregory Neil Shapiro /* Mark as done */ 1208605302a5SGregory Neil Shapiro rl->lr_done = true; 1209e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp != NULL) 1210e92d3f3fSGregory Neil Shapiro { 1211e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1212e92d3f3fSGregory Neil Shapiro rl->lr_ludp = NULL; 1213e92d3f3fSGregory Neil Shapiro } 1214e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs != NULL) 1215e92d3f3fSGregory Neil Shapiro { 1216e92d3f3fSGregory Neil Shapiro free(rl->lr_attrs); 1217e92d3f3fSGregory Neil Shapiro rl->lr_attrs = NULL; 1218e92d3f3fSGregory Neil Shapiro } 1219605302a5SGregory Neil Shapiro 1220605302a5SGregory Neil Shapiro /* Reset rlidx as new items may have been added */ 1221605302a5SGregory Neil Shapiro rlidx = -1; 122240266059SGregory Neil Shapiro } 122340266059SGregory Neil Shapiro } 122440266059SGregory Neil Shapiro return statp; 122540266059SGregory Neil Shapiro } 122640266059SGregory Neil Shapiro 122740266059SGregory Neil Shapiro /* 122840266059SGregory Neil Shapiro ** SM_LDAP_CLOSE -- close LDAP connection 122940266059SGregory Neil Shapiro ** 123040266059SGregory Neil Shapiro ** Parameters: 123140266059SGregory Neil Shapiro ** lmap -- LDAP map information 123240266059SGregory Neil Shapiro ** 123340266059SGregory Neil Shapiro ** Returns: 123440266059SGregory Neil Shapiro ** None. 123540266059SGregory Neil Shapiro ** 123640266059SGregory Neil Shapiro */ 123740266059SGregory Neil Shapiro 123840266059SGregory Neil Shapiro void 123940266059SGregory Neil Shapiro sm_ldap_close(lmap) 124040266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 124140266059SGregory Neil Shapiro { 124240266059SGregory Neil Shapiro if (lmap->ldap_ld == NULL) 124340266059SGregory Neil Shapiro return; 124440266059SGregory Neil Shapiro 124540266059SGregory Neil Shapiro if (lmap->ldap_pid == getpid()) 124640266059SGregory Neil Shapiro ldap_unbind(lmap->ldap_ld); 124740266059SGregory Neil Shapiro lmap->ldap_ld = NULL; 124840266059SGregory Neil Shapiro lmap->ldap_pid = 0; 124940266059SGregory Neil Shapiro } 125040266059SGregory Neil Shapiro 125140266059SGregory Neil Shapiro /* 125240266059SGregory Neil Shapiro ** SM_LDAP_SETOPTS -- set LDAP options 125340266059SGregory Neil Shapiro ** 125440266059SGregory Neil Shapiro ** Parameters: 125540266059SGregory Neil Shapiro ** ld -- LDAP session handle 125640266059SGregory Neil Shapiro ** lmap -- LDAP map information 125740266059SGregory Neil Shapiro ** 125840266059SGregory Neil Shapiro ** Returns: 125940266059SGregory Neil Shapiro ** None. 126040266059SGregory Neil Shapiro ** 126140266059SGregory Neil Shapiro */ 126240266059SGregory Neil Shapiro 126340266059SGregory Neil Shapiro void 126440266059SGregory Neil Shapiro sm_ldap_setopts(ld, lmap) 126540266059SGregory Neil Shapiro LDAP *ld; 126640266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 126740266059SGregory Neil Shapiro { 126840266059SGregory Neil Shapiro # if USE_LDAP_SET_OPTION 1269605302a5SGregory Neil Shapiro if (lmap->ldap_version != 0) 1270605302a5SGregory Neil Shapiro { 1271605302a5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, 1272605302a5SGregory Neil Shapiro &lmap->ldap_version); 1273605302a5SGregory Neil Shapiro } 127440266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); 127540266059SGregory Neil Shapiro if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) 127640266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); 127740266059SGregory Neil Shapiro else 127840266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 127940266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); 128040266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); 1281959366dcSGregory Neil Shapiro # ifdef LDAP_OPT_RESTART 1282959366dcSGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); 1283959366dcSGregory Neil Shapiro # endif /* LDAP_OPT_RESTART */ 128440266059SGregory Neil Shapiro # else /* USE_LDAP_SET_OPTION */ 128540266059SGregory Neil Shapiro /* From here on in we can use ldap internal timelimits */ 128640266059SGregory Neil Shapiro ld->ld_deref = lmap->ldap_deref; 128740266059SGregory Neil Shapiro ld->ld_options = lmap->ldap_options; 128840266059SGregory Neil Shapiro ld->ld_sizelimit = lmap->ldap_sizelimit; 128940266059SGregory Neil Shapiro ld->ld_timelimit = lmap->ldap_timelimit; 129040266059SGregory Neil Shapiro # endif /* USE_LDAP_SET_OPTION */ 129140266059SGregory Neil Shapiro } 129240266059SGregory Neil Shapiro 129340266059SGregory Neil Shapiro /* 129440266059SGregory Neil Shapiro ** SM_LDAP_GETERRNO -- get ldap errno value 129540266059SGregory Neil Shapiro ** 129640266059SGregory Neil Shapiro ** Parameters: 129740266059SGregory Neil Shapiro ** ld -- LDAP session handle 129840266059SGregory Neil Shapiro ** 129940266059SGregory Neil Shapiro ** Returns: 130040266059SGregory Neil Shapiro ** LDAP errno. 130140266059SGregory Neil Shapiro ** 130240266059SGregory Neil Shapiro */ 130340266059SGregory Neil Shapiro 130440266059SGregory Neil Shapiro int 130540266059SGregory Neil Shapiro sm_ldap_geterrno(ld) 130640266059SGregory Neil Shapiro LDAP *ld; 130740266059SGregory Neil Shapiro { 130840266059SGregory Neil Shapiro int err = LDAP_SUCCESS; 130940266059SGregory Neil Shapiro 131040266059SGregory Neil Shapiro # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 131140266059SGregory Neil Shapiro (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); 131240266059SGregory Neil Shapiro # else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 131340266059SGregory Neil Shapiro # ifdef LDAP_OPT_SIZELIMIT 131440266059SGregory Neil Shapiro err = ldap_get_lderrno(ld, NULL, NULL); 131540266059SGregory Neil Shapiro # else /* LDAP_OPT_SIZELIMIT */ 131640266059SGregory Neil Shapiro err = ld->ld_errno; 131740266059SGregory Neil Shapiro 131840266059SGregory Neil Shapiro /* 131940266059SGregory Neil Shapiro ** Reset value to prevent lingering LDAP_DECODING_ERROR due to 132040266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see above) 132140266059SGregory Neil Shapiro */ 132240266059SGregory Neil Shapiro 132340266059SGregory Neil Shapiro ld->ld_errno = LDAP_SUCCESS; 132440266059SGregory Neil Shapiro # endif /* LDAP_OPT_SIZELIMIT */ 132540266059SGregory Neil Shapiro # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 132640266059SGregory Neil Shapiro return err; 132740266059SGregory Neil Shapiro } 132840266059SGregory Neil Shapiro # endif /* LDAPMAP */ 1329