140266059SGregory Neil Shapiro /* 240266059SGregory Neil Shapiro * Copyright (c) 2001-2002 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> 1140266059SGregory Neil Shapiro SM_RCSID("@(#)$Id: ldap.c,v 1.18 2002/01/11 22:06:51 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> 2740266059SGregory Neil Shapiro # include <sm/sysexits.h> 2840266059SGregory Neil Shapiro 2940266059SGregory Neil Shapiro SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap", 3040266059SGregory Neil Shapiro "@(#)$Debug: sm_trace_ldap - trace LDAP operations $"); 3140266059SGregory Neil Shapiro 3240266059SGregory Neil Shapiro static void ldaptimeout __P((int)); 3340266059SGregory Neil Shapiro 3440266059SGregory Neil Shapiro /* 3540266059SGregory Neil Shapiro ** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT 3640266059SGregory Neil Shapiro ** 3740266059SGregory Neil Shapiro ** Parameters: 3840266059SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT to clear 3940266059SGregory Neil Shapiro ** 4040266059SGregory Neil Shapiro ** Returns: 4140266059SGregory Neil Shapiro ** None. 4240266059SGregory Neil Shapiro ** 4340266059SGregory Neil Shapiro */ 4440266059SGregory Neil Shapiro 4540266059SGregory Neil Shapiro void 4640266059SGregory Neil Shapiro sm_ldap_clear(lmap) 4740266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 4840266059SGregory Neil Shapiro { 4940266059SGregory Neil Shapiro if (lmap == NULL) 5040266059SGregory Neil Shapiro return; 5140266059SGregory Neil Shapiro 5240266059SGregory Neil Shapiro lmap->ldap_host = NULL; 5340266059SGregory Neil Shapiro lmap->ldap_port = LDAP_PORT; 5440266059SGregory Neil Shapiro lmap->ldap_deref = LDAP_DEREF_NEVER; 5540266059SGregory Neil Shapiro lmap->ldap_timelimit = LDAP_NO_LIMIT; 5640266059SGregory Neil Shapiro lmap->ldap_sizelimit = LDAP_NO_LIMIT; 5740266059SGregory Neil Shapiro # ifdef LDAP_REFERRALS 5840266059SGregory Neil Shapiro lmap->ldap_options = LDAP_OPT_REFERRALS; 5940266059SGregory Neil Shapiro # else /* LDAP_REFERRALS */ 6040266059SGregory Neil Shapiro lmap->ldap_options = 0; 6140266059SGregory Neil Shapiro # endif /* LDAP_REFERRALS */ 6240266059SGregory Neil Shapiro lmap->ldap_attrsep = '\0'; 6340266059SGregory Neil Shapiro lmap->ldap_binddn = NULL; 6440266059SGregory Neil Shapiro lmap->ldap_secret = NULL; 6540266059SGregory Neil Shapiro lmap->ldap_method = LDAP_AUTH_SIMPLE; 6640266059SGregory Neil Shapiro lmap->ldap_base = NULL; 6740266059SGregory Neil Shapiro lmap->ldap_scope = LDAP_SCOPE_SUBTREE; 6840266059SGregory Neil Shapiro lmap->ldap_attrsonly = LDAPMAP_FALSE; 6940266059SGregory Neil Shapiro lmap->ldap_timeout.tv_sec = 0; 7040266059SGregory Neil Shapiro lmap->ldap_timeout.tv_usec = 0; 7140266059SGregory Neil Shapiro lmap->ldap_ld = NULL; 7240266059SGregory Neil Shapiro lmap->ldap_filter = NULL; 7340266059SGregory Neil Shapiro lmap->ldap_attr[0] = NULL; 7440266059SGregory Neil Shapiro #if _FFR_LDAP_RECURSION 7540266059SGregory Neil Shapiro lmap->ldap_attr_type[0] = LDAPMAP_ATTR_NORMAL; 7640266059SGregory Neil Shapiro lmap->ldap_attr_final[0] = NULL; 7740266059SGregory Neil Shapiro #endif /* _FFR_LDAP_RECURSION */ 7840266059SGregory Neil Shapiro lmap->ldap_res = NULL; 7940266059SGregory Neil Shapiro lmap->ldap_next = NULL; 8040266059SGregory Neil Shapiro lmap->ldap_pid = 0; 8140266059SGregory Neil Shapiro } 8240266059SGregory Neil Shapiro 8340266059SGregory Neil Shapiro /* 8440266059SGregory Neil Shapiro ** SM_LDAP_START -- actually connect to an LDAP server 8540266059SGregory Neil Shapiro ** 8640266059SGregory Neil Shapiro ** Parameters: 8740266059SGregory Neil Shapiro ** name -- name of map for debug output. 8840266059SGregory Neil Shapiro ** lmap -- the LDAP map being opened. 8940266059SGregory Neil Shapiro ** 9040266059SGregory Neil Shapiro ** Returns: 9140266059SGregory Neil Shapiro ** true if connection is successful, false otherwise. 9240266059SGregory Neil Shapiro ** 9340266059SGregory Neil Shapiro ** Side Effects: 9440266059SGregory Neil Shapiro ** Populates lmap->ldap_ld. 9540266059SGregory Neil Shapiro */ 9640266059SGregory Neil Shapiro 9740266059SGregory Neil Shapiro static jmp_buf LDAPTimeout; 9840266059SGregory Neil Shapiro 9940266059SGregory Neil Shapiro #define SM_LDAP_SETTIMEOUT(to) \ 10040266059SGregory Neil Shapiro do \ 10140266059SGregory Neil Shapiro { \ 10240266059SGregory Neil Shapiro if (to != 0) \ 10340266059SGregory Neil Shapiro { \ 10440266059SGregory Neil Shapiro if (setjmp(LDAPTimeout) != 0) \ 10540266059SGregory Neil Shapiro { \ 10640266059SGregory Neil Shapiro errno = ETIMEDOUT; \ 10740266059SGregory Neil Shapiro return false; \ 10840266059SGregory Neil Shapiro } \ 10940266059SGregory Neil Shapiro ev = sm_setevent(to, ldaptimeout, 0); \ 11040266059SGregory Neil Shapiro } \ 11140266059SGregory Neil Shapiro } while (0) 11240266059SGregory Neil Shapiro 11340266059SGregory Neil Shapiro #define SM_LDAP_CLEARTIMEOUT() \ 11440266059SGregory Neil Shapiro do \ 11540266059SGregory Neil Shapiro { \ 11640266059SGregory Neil Shapiro if (ev != NULL) \ 11740266059SGregory Neil Shapiro sm_clrevent(ev); \ 11840266059SGregory Neil Shapiro } while (0) 11940266059SGregory Neil Shapiro 12040266059SGregory Neil Shapiro bool 12140266059SGregory Neil Shapiro sm_ldap_start(name, lmap) 12240266059SGregory Neil Shapiro char *name; 12340266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 12440266059SGregory Neil Shapiro { 12540266059SGregory Neil Shapiro int bind_result; 12640266059SGregory Neil Shapiro int save_errno; 12740266059SGregory Neil Shapiro SM_EVENT *ev = NULL; 12840266059SGregory Neil Shapiro LDAP *ld; 12940266059SGregory Neil Shapiro 13040266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 2)) 13140266059SGregory Neil Shapiro sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name); 13240266059SGregory Neil Shapiro 13340266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 13440266059SGregory Neil Shapiro sm_dprintf("ldapmap_start(%s, %d)\n", 13540266059SGregory Neil Shapiro lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host, 13640266059SGregory Neil Shapiro lmap->ldap_port); 13740266059SGregory Neil Shapiro 13840266059SGregory Neil Shapiro # if USE_LDAP_INIT 13940266059SGregory Neil Shapiro ld = ldap_init(lmap->ldap_host, lmap->ldap_port); 14040266059SGregory Neil Shapiro save_errno = errno; 14140266059SGregory Neil Shapiro # else /* USE_LDAP_INIT */ 14240266059SGregory Neil Shapiro /* 14340266059SGregory Neil Shapiro ** If using ldap_open(), the actual connection to the server 14440266059SGregory Neil Shapiro ** happens now so we need the timeout here. For ldap_init(), 14540266059SGregory Neil Shapiro ** the connection happens at bind time. 14640266059SGregory Neil Shapiro */ 14740266059SGregory Neil Shapiro 14840266059SGregory Neil Shapiro SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); 14940266059SGregory Neil Shapiro ld = ldap_open(lmap->ldap_host, lmap->ldap_port); 15040266059SGregory Neil Shapiro save_errno = errno; 15140266059SGregory Neil Shapiro 15240266059SGregory Neil Shapiro /* clear the event if it has not sprung */ 15340266059SGregory Neil Shapiro SM_LDAP_CLEARTIMEOUT(); 15440266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 15540266059SGregory Neil Shapiro 15640266059SGregory Neil Shapiro errno = save_errno; 15740266059SGregory Neil Shapiro if (ld == NULL) 15840266059SGregory Neil Shapiro return false; 15940266059SGregory Neil Shapiro 16040266059SGregory Neil Shapiro sm_ldap_setopts(ld, lmap); 16140266059SGregory Neil Shapiro 16240266059SGregory Neil Shapiro # if USE_LDAP_INIT 16340266059SGregory Neil Shapiro /* 16440266059SGregory Neil Shapiro ** If using ldap_init(), the actual connection to the server 16540266059SGregory Neil Shapiro ** happens at ldap_bind_s() so we need the timeout here. 16640266059SGregory Neil Shapiro */ 16740266059SGregory Neil Shapiro 16840266059SGregory Neil Shapiro SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); 16940266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 17040266059SGregory Neil Shapiro 17140266059SGregory Neil Shapiro # ifdef LDAP_AUTH_KRBV4 17240266059SGregory Neil Shapiro if (lmap->ldap_method == LDAP_AUTH_KRBV4 && 17340266059SGregory Neil Shapiro lmap->ldap_secret != NULL) 17440266059SGregory Neil Shapiro { 17540266059SGregory Neil Shapiro /* 17640266059SGregory Neil Shapiro ** Need to put ticket in environment here instead of 17740266059SGregory Neil Shapiro ** during parseargs as there may be different tickets 17840266059SGregory Neil Shapiro ** for different LDAP connections. 17940266059SGregory Neil Shapiro */ 18040266059SGregory Neil Shapiro 18140266059SGregory Neil Shapiro (void) putenv(lmap->ldap_secret); 18240266059SGregory Neil Shapiro } 18340266059SGregory Neil Shapiro # endif /* LDAP_AUTH_KRBV4 */ 18440266059SGregory Neil Shapiro 18540266059SGregory Neil Shapiro bind_result = ldap_bind_s(ld, lmap->ldap_binddn, 18640266059SGregory Neil Shapiro lmap->ldap_secret, lmap->ldap_method); 18740266059SGregory Neil Shapiro 18840266059SGregory Neil Shapiro # if USE_LDAP_INIT 18940266059SGregory Neil Shapiro /* clear the event if it has not sprung */ 19040266059SGregory Neil Shapiro SM_LDAP_CLEARTIMEOUT(); 19140266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 19240266059SGregory Neil Shapiro 19340266059SGregory Neil Shapiro if (bind_result != LDAP_SUCCESS) 19440266059SGregory Neil Shapiro { 19540266059SGregory Neil Shapiro errno = bind_result + E_LDAPBASE; 19640266059SGregory Neil Shapiro return false; 19740266059SGregory Neil Shapiro } 19840266059SGregory Neil Shapiro 19940266059SGregory Neil Shapiro /* Save PID to make sure only this PID closes the LDAP connection */ 20040266059SGregory Neil Shapiro lmap->ldap_pid = getpid(); 20140266059SGregory Neil Shapiro lmap->ldap_ld = ld; 20240266059SGregory Neil Shapiro return true; 20340266059SGregory Neil Shapiro } 20440266059SGregory Neil Shapiro 20540266059SGregory Neil Shapiro /* ARGSUSED */ 20640266059SGregory Neil Shapiro static void 20740266059SGregory Neil Shapiro ldaptimeout(unused) 20840266059SGregory Neil Shapiro int unused; 20940266059SGregory Neil Shapiro { 21040266059SGregory Neil Shapiro /* 21140266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 21240266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 21340266059SGregory Neil Shapiro ** DOING. 21440266059SGregory Neil Shapiro */ 21540266059SGregory Neil Shapiro 21640266059SGregory Neil Shapiro errno = ETIMEDOUT; 21740266059SGregory Neil Shapiro longjmp(LDAPTimeout, 1); 21840266059SGregory Neil Shapiro } 21940266059SGregory Neil Shapiro 22040266059SGregory Neil Shapiro /* 22140266059SGregory Neil Shapiro ** SM_LDAP_SEARCH -- iniate LDAP search 22240266059SGregory Neil Shapiro ** 22340266059SGregory Neil Shapiro ** Initiate an LDAP search, return the msgid. 22440266059SGregory Neil Shapiro ** The calling function must collect the results. 22540266059SGregory Neil Shapiro ** 22640266059SGregory Neil Shapiro ** Parameters: 22740266059SGregory Neil Shapiro ** lmap -- LDAP map information 22840266059SGregory Neil Shapiro ** key -- key to substitute in LDAP filter 22940266059SGregory Neil Shapiro ** 23040266059SGregory Neil Shapiro ** Returns: 23140266059SGregory Neil Shapiro ** -1 on failure, msgid on success 23240266059SGregory Neil Shapiro ** 23340266059SGregory Neil Shapiro */ 23440266059SGregory Neil Shapiro 23540266059SGregory Neil Shapiro int 23640266059SGregory Neil Shapiro sm_ldap_search(lmap, key) 23740266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 23840266059SGregory Neil Shapiro char *key; 23940266059SGregory Neil Shapiro { 24040266059SGregory Neil Shapiro int msgid; 24140266059SGregory Neil Shapiro char *fp, *p, *q; 24240266059SGregory Neil Shapiro char filter[LDAPMAP_MAX_FILTER + 1]; 24340266059SGregory Neil Shapiro 24440266059SGregory Neil Shapiro /* substitute key into filter, perhaps multiple times */ 24540266059SGregory Neil Shapiro memset(filter, '\0', sizeof filter); 24640266059SGregory Neil Shapiro fp = filter; 24740266059SGregory Neil Shapiro p = lmap->ldap_filter; 24840266059SGregory Neil Shapiro while ((q = strchr(p, '%')) != NULL) 24940266059SGregory Neil Shapiro { 25040266059SGregory Neil Shapiro if (q[1] == 's') 25140266059SGregory Neil Shapiro { 25240266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 25340266059SGregory Neil Shapiro "%.*s%s", (int) (q - p), p, key); 25440266059SGregory Neil Shapiro fp += strlen(fp); 25540266059SGregory Neil Shapiro p = q + 2; 25640266059SGregory Neil Shapiro } 25740266059SGregory Neil Shapiro else if (q[1] == '0') 25840266059SGregory Neil Shapiro { 25940266059SGregory Neil Shapiro char *k = key; 26040266059SGregory Neil Shapiro 26140266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 26240266059SGregory Neil Shapiro "%.*s", (int) (q - p), p); 26340266059SGregory Neil Shapiro fp += strlen(fp); 26440266059SGregory Neil Shapiro p = q + 2; 26540266059SGregory Neil Shapiro 26640266059SGregory Neil Shapiro /* Properly escape LDAP special characters */ 26740266059SGregory Neil Shapiro while (SPACELEFT(filter, fp) > 0 && 26840266059SGregory Neil Shapiro *k != '\0') 26940266059SGregory Neil Shapiro { 27040266059SGregory Neil Shapiro if (*k == '*' || *k == '(' || 27140266059SGregory Neil Shapiro *k == ')' || *k == '\\') 27240266059SGregory Neil Shapiro { 27340266059SGregory Neil Shapiro (void) sm_strlcat(fp, 27440266059SGregory Neil Shapiro (*k == '*' ? "\\2A" : 27540266059SGregory Neil Shapiro (*k == '(' ? "\\28" : 27640266059SGregory Neil Shapiro (*k == ')' ? "\\29" : 27740266059SGregory Neil Shapiro (*k == '\\' ? "\\5C" : 27840266059SGregory Neil Shapiro "\00")))), 27940266059SGregory Neil Shapiro SPACELEFT(filter, fp)); 28040266059SGregory Neil Shapiro fp += strlen(fp); 28140266059SGregory Neil Shapiro k++; 28240266059SGregory Neil Shapiro } 28340266059SGregory Neil Shapiro else 28440266059SGregory Neil Shapiro *fp++ = *k++; 28540266059SGregory Neil Shapiro } 28640266059SGregory Neil Shapiro } 28740266059SGregory Neil Shapiro else 28840266059SGregory Neil Shapiro { 28940266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 29040266059SGregory Neil Shapiro "%.*s", (int) (q - p + 1), p); 29140266059SGregory Neil Shapiro p = q + (q[1] == '%' ? 2 : 1); 29240266059SGregory Neil Shapiro fp += strlen(fp); 29340266059SGregory Neil Shapiro } 29440266059SGregory Neil Shapiro } 29540266059SGregory Neil Shapiro (void) sm_strlcpy(fp, p, SPACELEFT(filter, fp)); 29640266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 20)) 29740266059SGregory Neil Shapiro sm_dprintf("ldap search filter=%s\n", filter); 29840266059SGregory Neil Shapiro 29940266059SGregory Neil Shapiro lmap->ldap_res = NULL; 30040266059SGregory Neil Shapiro msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, lmap->ldap_scope, 30140266059SGregory Neil Shapiro filter, 30240266059SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? NULL : 30340266059SGregory Neil Shapiro lmap->ldap_attr), 30440266059SGregory Neil Shapiro lmap->ldap_attrsonly); 30540266059SGregory Neil Shapiro return msgid; 30640266059SGregory Neil Shapiro } 30740266059SGregory Neil Shapiro 30840266059SGregory Neil Shapiro # if _FFR_LDAP_RECURSION 30940266059SGregory Neil Shapiro /* 31040266059SGregory Neil Shapiro ** SM_LDAP_RESULTS -- return results from an LDAP lookup in result 31140266059SGregory Neil Shapiro ** 31240266059SGregory Neil Shapiro ** Parameters: 31340266059SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT in use 31440266059SGregory Neil Shapiro ** msgid -- msgid returned by sm_ldap_search() 31540266059SGregory Neil Shapiro ** flags -- flags for the lookup 31640266059SGregory Neil Shapiro ** delim -- delimiter for result concatenation 31740266059SGregory Neil Shapiro ** rpool -- memory pool for storage 31840266059SGregory Neil Shapiro ** result -- return string 31940266059SGregory Neil Shapiro ** recurse -- recursion list 32040266059SGregory Neil Shapiro ** 32140266059SGregory Neil Shapiro ** Returns: 32240266059SGregory Neil Shapiro ** status (sysexit) 32340266059SGregory Neil Shapiro */ 32440266059SGregory Neil Shapiro 32540266059SGregory Neil Shapiro # define LDAPMAP_ERROR_CLEANUP() \ 32640266059SGregory Neil Shapiro { \ 32740266059SGregory Neil Shapiro if (lmap->ldap_res != NULL) \ 32840266059SGregory Neil Shapiro { \ 32940266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); \ 33040266059SGregory Neil Shapiro lmap->ldap_res = NULL; \ 33140266059SGregory Neil Shapiro } \ 33240266059SGregory Neil Shapiro (void) ldap_abandon(lmap->ldap_ld, msgid); \ 33340266059SGregory Neil Shapiro } 33440266059SGregory Neil Shapiro 33540266059SGregory Neil Shapiro static int 33640266059SGregory Neil Shapiro ldapmap_add_recurse(top, item, type, rpool) 33740266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST **top; 33840266059SGregory Neil Shapiro char *item; 33940266059SGregory Neil Shapiro int type; 34040266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 34140266059SGregory Neil Shapiro { 34240266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST *p; 34340266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST *last; 34440266059SGregory Neil Shapiro 34540266059SGregory Neil Shapiro last = NULL; 34640266059SGregory Neil Shapiro for (p = *top; p != NULL; p = p->lr_next) 34740266059SGregory Neil Shapiro { 34840266059SGregory Neil Shapiro if (strcasecmp(item, p->lr_search) == 0 && 34940266059SGregory Neil Shapiro type == p->lr_type) 35040266059SGregory Neil Shapiro { 35140266059SGregory Neil Shapiro /* already on list */ 35240266059SGregory Neil Shapiro return 1; 35340266059SGregory Neil Shapiro } 35440266059SGregory Neil Shapiro last = p; 35540266059SGregory Neil Shapiro } 35640266059SGregory Neil Shapiro 35740266059SGregory Neil Shapiro /* not on list, add it */ 35840266059SGregory Neil Shapiro p = sm_rpool_malloc_x(rpool, sizeof *p); 35940266059SGregory Neil Shapiro p->lr_search = sm_rpool_strdup_x(rpool, item); 36040266059SGregory Neil Shapiro p->lr_type = type; 36140266059SGregory Neil Shapiro p->lr_next = NULL; 36240266059SGregory Neil Shapiro if (last == NULL) 36340266059SGregory Neil Shapiro *top = p; 36440266059SGregory Neil Shapiro else 36540266059SGregory Neil Shapiro last->lr_next = p; 36640266059SGregory Neil Shapiro return 0; 36740266059SGregory Neil Shapiro } 36840266059SGregory Neil Shapiro 36940266059SGregory Neil Shapiro int 37040266059SGregory Neil Shapiro sm_ldap_results(lmap, msgid, flags, delim, rpool, result, recurse) 37140266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 37240266059SGregory Neil Shapiro int msgid; 37340266059SGregory Neil Shapiro int flags; 37440266059SGregory Neil Shapiro char delim; 37540266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 37640266059SGregory Neil Shapiro char **result; 37740266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST *recurse; 37840266059SGregory Neil Shapiro { 37940266059SGregory Neil Shapiro bool toplevel; 38040266059SGregory Neil Shapiro int i; 38140266059SGregory Neil Shapiro int entries = 0; 38240266059SGregory Neil Shapiro int statp; 38340266059SGregory Neil Shapiro int vsize; 38440266059SGregory Neil Shapiro int ret; 38540266059SGregory Neil Shapiro int save_errno; 38640266059SGregory Neil Shapiro char *p; 38740266059SGregory Neil Shapiro 38840266059SGregory Neil Shapiro /* Are we the top top level of the search? */ 38940266059SGregory Neil Shapiro toplevel = (recurse == NULL); 39040266059SGregory Neil Shapiro 39140266059SGregory Neil Shapiro /* Get results */ 39240266059SGregory Neil Shapiro statp = EX_NOTFOUND; 39340266059SGregory Neil Shapiro while ((ret = ldap_result(lmap->ldap_ld, msgid, 0, 39440266059SGregory Neil Shapiro (lmap->ldap_timeout.tv_sec == 0 ? NULL : 39540266059SGregory Neil Shapiro &(lmap->ldap_timeout)), 39640266059SGregory Neil Shapiro &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) 39740266059SGregory Neil Shapiro { 39840266059SGregory Neil Shapiro LDAPMessage *entry; 39940266059SGregory Neil Shapiro 40040266059SGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEMATCH, flags)) 40140266059SGregory Neil Shapiro { 40240266059SGregory Neil Shapiro entries += ldap_count_entries(lmap->ldap_ld, 40340266059SGregory Neil Shapiro lmap->ldap_res); 40440266059SGregory Neil Shapiro if (entries > 1) 40540266059SGregory Neil Shapiro { 40640266059SGregory Neil Shapiro LDAPMAP_ERROR_CLEANUP(); 40740266059SGregory Neil Shapiro errno = ENOENT; 40840266059SGregory Neil Shapiro return EX_NOTFOUND; 40940266059SGregory Neil Shapiro } 41040266059SGregory Neil Shapiro } 41140266059SGregory Neil Shapiro 41240266059SGregory Neil Shapiro /* If we don't want multiple values and we have one, break */ 41340266059SGregory Neil Shapiro if (delim == '\0' && *result != NULL) 41440266059SGregory Neil Shapiro break; 41540266059SGregory Neil Shapiro 41640266059SGregory Neil Shapiro /* Cycle through all entries */ 41740266059SGregory Neil Shapiro for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); 41840266059SGregory Neil Shapiro entry != NULL; 41940266059SGregory Neil Shapiro entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) 42040266059SGregory Neil Shapiro { 42140266059SGregory Neil Shapiro BerElement *ber; 42240266059SGregory Neil Shapiro char *attr; 42340266059SGregory Neil Shapiro char **vals = NULL; 42440266059SGregory Neil Shapiro char *dn; 42540266059SGregory Neil Shapiro 42640266059SGregory Neil Shapiro /* 42740266059SGregory Neil Shapiro ** If matching only and found an entry, 42840266059SGregory Neil Shapiro ** no need to spin through attributes 42940266059SGregory Neil Shapiro */ 43040266059SGregory Neil Shapiro 43140266059SGregory Neil Shapiro if (statp == EX_OK && 43240266059SGregory Neil Shapiro bitset(SM_LDAP_MATCHONLY, flags)) 43340266059SGregory Neil Shapiro continue; 43440266059SGregory Neil Shapiro 43540266059SGregory Neil Shapiro /* record completed DN's to prevent loops */ 43640266059SGregory Neil Shapiro dn = ldap_get_dn(lmap->ldap_ld, entry); 43740266059SGregory Neil Shapiro if (dn == NULL) 43840266059SGregory Neil Shapiro { 43940266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 44040266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 44140266059SGregory Neil Shapiro LDAPMAP_ERROR_CLEANUP(); 44240266059SGregory Neil Shapiro errno = save_errno; 44340266059SGregory Neil Shapiro return EX_OSERR; 44440266059SGregory Neil Shapiro } 44540266059SGregory Neil Shapiro 44640266059SGregory Neil Shapiro switch (ldapmap_add_recurse(&recurse, dn, 44740266059SGregory Neil Shapiro LDAPMAP_ATTR_NORMAL, 44840266059SGregory Neil Shapiro rpool)) 44940266059SGregory Neil Shapiro { 45040266059SGregory Neil Shapiro case -1: 45140266059SGregory Neil Shapiro /* error adding */ 45240266059SGregory Neil Shapiro ldap_memfree(dn); 45340266059SGregory Neil Shapiro LDAPMAP_ERROR_CLEANUP(); 45440266059SGregory Neil Shapiro errno = ENOMEM; 45540266059SGregory Neil Shapiro return EX_OSERR; 45640266059SGregory Neil Shapiro 45740266059SGregory Neil Shapiro case 1: 45840266059SGregory Neil Shapiro /* already on list, skip it */ 45940266059SGregory Neil Shapiro ldap_memfree(dn); 46040266059SGregory Neil Shapiro continue; 46140266059SGregory Neil Shapiro } 46240266059SGregory Neil Shapiro ldap_memfree(dn); 46340266059SGregory Neil Shapiro 46440266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 46540266059SGregory Neil Shapiro /* 46640266059SGregory Neil Shapiro ** Reset value to prevent lingering 46740266059SGregory Neil Shapiro ** LDAP_DECODING_ERROR due to 46840266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see below) 46940266059SGregory Neil Shapiro */ 47040266059SGregory Neil Shapiro 47140266059SGregory Neil Shapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 47240266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 47340266059SGregory Neil Shapiro 47440266059SGregory Neil Shapiro for (attr = ldap_first_attribute(lmap->ldap_ld, entry, 47540266059SGregory Neil Shapiro &ber); 47640266059SGregory Neil Shapiro attr != NULL; 47740266059SGregory Neil Shapiro attr = ldap_next_attribute(lmap->ldap_ld, entry, 47840266059SGregory Neil Shapiro ber)) 47940266059SGregory Neil Shapiro { 48040266059SGregory Neil Shapiro char *tmp, *vp_tmp; 48140266059SGregory Neil Shapiro int type; 48240266059SGregory Neil Shapiro 48340266059SGregory Neil Shapiro for (i = 0; lmap->ldap_attr[i] != NULL; i++) 48440266059SGregory Neil Shapiro { 48540266059SGregory Neil Shapiro if (sm_strcasecmp(lmap->ldap_attr[i], 48640266059SGregory Neil Shapiro attr) == 0) 48740266059SGregory Neil Shapiro { 48840266059SGregory Neil Shapiro type = lmap->ldap_attr_type[i]; 48940266059SGregory Neil Shapiro break; 49040266059SGregory Neil Shapiro } 49140266059SGregory Neil Shapiro } 49240266059SGregory Neil Shapiro if (lmap->ldap_attr[i] == NULL) 49340266059SGregory Neil Shapiro { 49440266059SGregory Neil Shapiro /* attribute not requested */ 49540266059SGregory Neil Shapiro # if USING_NETSCAPE_LDAP 49640266059SGregory Neil Shapiro ldap_memfree(attr); 49740266059SGregory Neil Shapiro # endif /* USING_NETSCAPE_LDAP */ 49840266059SGregory Neil Shapiro LDAPMAP_ERROR_CLEANUP(); 49940266059SGregory Neil Shapiro errno = EFAULT; 50040266059SGregory Neil Shapiro return EX_SOFTWARE; 50140266059SGregory Neil Shapiro } 50240266059SGregory Neil Shapiro 50340266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 50440266059SGregory Neil Shapiro { 50540266059SGregory Neil Shapiro vals = ldap_get_values(lmap->ldap_ld, 50640266059SGregory Neil Shapiro entry, 50740266059SGregory Neil Shapiro attr); 50840266059SGregory Neil Shapiro if (vals == NULL) 50940266059SGregory Neil Shapiro { 51040266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 51140266059SGregory Neil Shapiro if (save_errno == LDAP_SUCCESS) 51240266059SGregory Neil Shapiro { 51340266059SGregory Neil Shapiro # if USING_NETSCAPE_LDAP 51440266059SGregory Neil Shapiro ldap_memfree(attr); 51540266059SGregory Neil Shapiro # endif /* USING_NETSCAPE_LDAP */ 51640266059SGregory Neil Shapiro continue; 51740266059SGregory Neil Shapiro } 51840266059SGregory Neil Shapiro 51940266059SGregory Neil Shapiro /* Must be an error */ 52040266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 52140266059SGregory Neil Shapiro # if USING_NETSCAPE_LDAP 52240266059SGregory Neil Shapiro ldap_memfree(attr); 52340266059SGregory Neil Shapiro # endif /* USING_NETSCAPE_LDAP */ 52440266059SGregory Neil Shapiro LDAPMAP_ERROR_CLEANUP(); 52540266059SGregory Neil Shapiro errno = save_errno; 52640266059SGregory Neil Shapiro return EX_TEMPFAIL; 52740266059SGregory Neil Shapiro } 52840266059SGregory Neil Shapiro } 52940266059SGregory Neil Shapiro 53040266059SGregory Neil Shapiro statp = EX_OK; 53140266059SGregory Neil Shapiro 53240266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 53340266059SGregory Neil Shapiro /* 53440266059SGregory Neil Shapiro ** Reset value to prevent lingering 53540266059SGregory Neil Shapiro ** LDAP_DECODING_ERROR due to 53640266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see below) 53740266059SGregory Neil Shapiro */ 53840266059SGregory Neil Shapiro 53940266059SGregory Neil Shapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 54040266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 54140266059SGregory Neil Shapiro 54240266059SGregory Neil Shapiro /* 54340266059SGregory Neil Shapiro ** If matching only, 54440266059SGregory Neil Shapiro ** no need to spin through entries 54540266059SGregory Neil Shapiro */ 54640266059SGregory Neil Shapiro 54740266059SGregory Neil Shapiro if (bitset(SM_LDAP_MATCHONLY, flags)) 54840266059SGregory Neil Shapiro { 54940266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 55040266059SGregory Neil Shapiro ldap_value_free(vals); 55140266059SGregory Neil Shapiro 55240266059SGregory Neil Shapiro # if USING_NETSCAPE_LDAP 55340266059SGregory Neil Shapiro ldap_memfree(attr); 55440266059SGregory Neil Shapiro # endif /* USING_NETSCAPE_LDAP */ 55540266059SGregory Neil Shapiro continue; 55640266059SGregory Neil Shapiro } 55740266059SGregory Neil Shapiro 55840266059SGregory Neil Shapiro /* 55940266059SGregory Neil Shapiro ** If we don't want multiple values, 56040266059SGregory Neil Shapiro ** return first found. 56140266059SGregory Neil Shapiro */ 56240266059SGregory Neil Shapiro 56340266059SGregory Neil Shapiro if (delim == '\0') 56440266059SGregory Neil Shapiro { 56540266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 56640266059SGregory Neil Shapiro { 56740266059SGregory Neil Shapiro *result = sm_rpool_strdup_x(rpool, 56840266059SGregory Neil Shapiro attr); 56940266059SGregory Neil Shapiro # if USING_NETSCAPE_LDAP 57040266059SGregory Neil Shapiro ldap_memfree(attr); 57140266059SGregory Neil Shapiro # endif /* USING_NETSCAPE_LDAP */ 57240266059SGregory Neil Shapiro break; 57340266059SGregory Neil Shapiro } 57440266059SGregory Neil Shapiro 57540266059SGregory Neil Shapiro if (vals[0] == NULL) 57640266059SGregory Neil Shapiro { 57740266059SGregory Neil Shapiro ldap_value_free(vals); 57840266059SGregory Neil Shapiro # if USING_NETSCAPE_LDAP 57940266059SGregory Neil Shapiro ldap_memfree(attr); 58040266059SGregory Neil Shapiro # endif /* USING_NETSCAPE_LDAP */ 58140266059SGregory Neil Shapiro continue; 58240266059SGregory Neil Shapiro } 58340266059SGregory Neil Shapiro 58440266059SGregory Neil Shapiro vsize = strlen(vals[0]) + 1; 58540266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 58640266059SGregory Neil Shapiro vsize += strlen(attr) + 1; 58740266059SGregory Neil Shapiro *result = sm_rpool_malloc_x(rpool, 58840266059SGregory Neil Shapiro vsize); 58940266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 59040266059SGregory Neil Shapiro sm_snprintf(*result, vsize, 59140266059SGregory Neil Shapiro "%s%c%s", 59240266059SGregory Neil Shapiro attr, 59340266059SGregory Neil Shapiro lmap->ldap_attrsep, 59440266059SGregory Neil Shapiro vals[0]); 59540266059SGregory Neil Shapiro else 59640266059SGregory Neil Shapiro sm_strlcpy(*result, vals[0], 59740266059SGregory Neil Shapiro vsize); 59840266059SGregory Neil Shapiro ldap_value_free(vals); 59940266059SGregory Neil Shapiro # if USING_NETSCAPE_LDAP 60040266059SGregory Neil Shapiro ldap_memfree(attr); 60140266059SGregory Neil Shapiro # endif /* USING_NETSCAPE_LDAP */ 60240266059SGregory Neil Shapiro break; 60340266059SGregory Neil Shapiro } 60440266059SGregory Neil Shapiro 60540266059SGregory Neil Shapiro /* attributes only */ 60640266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 60740266059SGregory Neil Shapiro { 60840266059SGregory Neil Shapiro if (*result == NULL) 60940266059SGregory Neil Shapiro *result = sm_rpool_strdup_x(rpool, 61040266059SGregory Neil Shapiro attr); 61140266059SGregory Neil Shapiro else 61240266059SGregory Neil Shapiro { 61340266059SGregory Neil Shapiro vsize = strlen(*result) + 61440266059SGregory Neil Shapiro strlen(attr) + 2; 61540266059SGregory Neil Shapiro tmp = sm_rpool_malloc_x(rpool, 61640266059SGregory Neil Shapiro vsize); 61740266059SGregory Neil Shapiro (void) sm_snprintf(tmp, 61840266059SGregory Neil Shapiro vsize, "%s%c%s", 61940266059SGregory Neil Shapiro *result, delim, 62040266059SGregory Neil Shapiro attr); 62140266059SGregory Neil Shapiro *result = tmp; 62240266059SGregory Neil Shapiro } 62340266059SGregory Neil Shapiro # if USING_NETSCAPE_LDAP 62440266059SGregory Neil Shapiro ldap_memfree(attr); 62540266059SGregory Neil Shapiro # endif /* USING_NETSCAPE_LDAP */ 62640266059SGregory Neil Shapiro continue; 62740266059SGregory Neil Shapiro } 62840266059SGregory Neil Shapiro 62940266059SGregory Neil Shapiro /* 63040266059SGregory Neil Shapiro ** If there is more than one, 63140266059SGregory Neil Shapiro ** munge then into a map_coldelim 63240266059SGregory Neil Shapiro ** separated string 63340266059SGregory Neil Shapiro */ 63440266059SGregory Neil Shapiro 63540266059SGregory Neil Shapiro vsize = 0; 63640266059SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 63740266059SGregory Neil Shapiro { 63840266059SGregory Neil Shapiro if (type == LDAPMAP_ATTR_DN || 63940266059SGregory Neil Shapiro type == LDAPMAP_ATTR_FILTER || 64040266059SGregory Neil Shapiro type == LDAPMAP_ATTR_URL) 64140266059SGregory Neil Shapiro { 64240266059SGregory Neil Shapiro if (ldapmap_add_recurse(&recurse, 64340266059SGregory Neil Shapiro vals[i], 64440266059SGregory Neil Shapiro type) < 0) 64540266059SGregory Neil Shapiro { 64640266059SGregory Neil Shapiro LDAPMAP_ERROR_CLEANUP(); 64740266059SGregory Neil Shapiro errno = ENOMEM; 64840266059SGregory Neil Shapiro return EX_OSERR; 64940266059SGregory Neil Shapiro } 65040266059SGregory Neil Shapiro } 65140266059SGregory Neil Shapiro if (type != LDAPMAP_ATTR_NORMAL) 65240266059SGregory Neil Shapiro { 65340266059SGregory Neil Shapiro # if USING_NETSCAPE_LDAP 65440266059SGregory Neil Shapiro ldap_memfree(attr); 65540266059SGregory Neil Shapiro # endif /* USING_NETSCAPE_LDAP */ 65640266059SGregory Neil Shapiro continue; 65740266059SGregory Neil Shapiro } 65840266059SGregory Neil Shapiro vsize += strlen(vals[i]) + 1; 65940266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 66040266059SGregory Neil Shapiro vsize += strlen(attr) + 1; 66140266059SGregory Neil Shapiro } 66240266059SGregory Neil Shapiro vp_tmp = sm_rpool_malloc_x(rpool, vsize); 66340266059SGregory Neil Shapiro *vp_tmp = '\0'; 66440266059SGregory Neil Shapiro 66540266059SGregory Neil Shapiro p = vp_tmp; 66640266059SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 66740266059SGregory Neil Shapiro { 66840266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 66940266059SGregory Neil Shapiro { 67040266059SGregory Neil Shapiro p += sm_strlcpy(p, attr, 67140266059SGregory Neil Shapiro vsize - (p - vp_tmp)); 67240266059SGregory Neil Shapiro *p++ = lmap->ldap_attrsep; 67340266059SGregory Neil Shapiro } 67440266059SGregory Neil Shapiro p += sm_strlcpy(p, vals[i], 67540266059SGregory Neil Shapiro vsize - (p - vp_tmp)); 67640266059SGregory Neil Shapiro if (p >= vp_tmp + vsize) 67740266059SGregory Neil Shapiro { 67840266059SGregory Neil Shapiro /* Internal error: buffer too small for LDAP values */ 67940266059SGregory Neil Shapiro LDAPMAP_ERROR_CLEANUP(); 68040266059SGregory Neil Shapiro errno = ENOMEM; 68140266059SGregory Neil Shapiro return EX_OSERR; 68240266059SGregory Neil Shapiro } 68340266059SGregory Neil Shapiro if (vals[i + 1] != NULL) 68440266059SGregory Neil Shapiro *p++ = delim; 68540266059SGregory Neil Shapiro } 68640266059SGregory Neil Shapiro 68740266059SGregory Neil Shapiro ldap_value_free(vals); 68840266059SGregory Neil Shapiro # if USING_NETSCAPE_LDAP 68940266059SGregory Neil Shapiro ldap_memfree(attr); 69040266059SGregory Neil Shapiro # endif /* USING_NETSCAPE_LDAP */ 69140266059SGregory Neil Shapiro if (*result == NULL) 69240266059SGregory Neil Shapiro { 69340266059SGregory Neil Shapiro *result = vp_tmp; 69440266059SGregory Neil Shapiro continue; 69540266059SGregory Neil Shapiro } 69640266059SGregory Neil Shapiro vsize = strlen(*result) + strlen(vp_tmp) + 2; 69740266059SGregory Neil Shapiro tmp = sm_rpool_malloc_x(rpool, vsize); 69840266059SGregory Neil Shapiro (void) sm_snprintf(tmp, vsize, "%s%c%s", 69940266059SGregory Neil Shapiro *result, delim, vp_tmp); 70040266059SGregory Neil Shapiro *result = tmp; 70140266059SGregory Neil Shapiro } 70240266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 70340266059SGregory Neil Shapiro 70440266059SGregory Neil Shapiro /* 70540266059SGregory Neil Shapiro ** We check save_errno != LDAP_DECODING_ERROR since 70640266059SGregory Neil Shapiro ** OpenLDAP 1.X has a very ugly *undocumented* 70740266059SGregory Neil Shapiro ** hack of returning this error code from 70840266059SGregory Neil Shapiro ** ldap_next_attribute() if the library freed the 70940266059SGregory Neil Shapiro ** ber attribute. See: 71040266059SGregory Neil Shapiro ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 71140266059SGregory Neil Shapiro */ 71240266059SGregory Neil Shapiro 71340266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS && 71440266059SGregory Neil Shapiro save_errno != LDAP_DECODING_ERROR) 71540266059SGregory Neil Shapiro { 71640266059SGregory Neil Shapiro /* Must be an error */ 71740266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 71840266059SGregory Neil Shapiro LDAPMAP_ERROR_CLEANUP(); 71940266059SGregory Neil Shapiro errno = save_errno; 72040266059SGregory Neil Shapiro return EX_TEMPFAIL; 72140266059SGregory Neil Shapiro } 72240266059SGregory Neil Shapiro 72340266059SGregory Neil Shapiro /* We don't want multiple values and we have one */ 72440266059SGregory Neil Shapiro if (delim == '\0' && *result != NULL) 72540266059SGregory Neil Shapiro break; 72640266059SGregory Neil Shapiro } 72740266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 72840266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS && 72940266059SGregory Neil Shapiro save_errno != LDAP_DECODING_ERROR) 73040266059SGregory Neil Shapiro { 73140266059SGregory Neil Shapiro /* Must be an error */ 73240266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 73340266059SGregory Neil Shapiro LDAPMAP_ERROR_CLEANUP(); 73440266059SGregory Neil Shapiro errno = save_errno; 73540266059SGregory Neil Shapiro return EX_TEMPFAIL; 73640266059SGregory Neil Shapiro } 73740266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); 73840266059SGregory Neil Shapiro lmap->ldap_res = NULL; 73940266059SGregory Neil Shapiro } 74040266059SGregory Neil Shapiro 74140266059SGregory Neil Shapiro if (ret == 0) 74240266059SGregory Neil Shapiro save_errno = ETIMEDOUT; 74340266059SGregory Neil Shapiro else 74440266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 74540266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS) 74640266059SGregory Neil Shapiro { 74740266059SGregory Neil Shapiro statp = EX_TEMPFAIL; 74840266059SGregory Neil Shapiro if (ret != 0) 74940266059SGregory Neil Shapiro { 75040266059SGregory Neil Shapiro switch (save_errno) 75140266059SGregory Neil Shapiro { 75240266059SGregory Neil Shapiro #ifdef LDAP_SERVER_DOWN 75340266059SGregory Neil Shapiro case LDAP_SERVER_DOWN: 75440266059SGregory Neil Shapiro #endif /* LDAP_SERVER_DOWN */ 75540266059SGregory Neil Shapiro case LDAP_TIMEOUT: 75640266059SGregory Neil Shapiro case LDAP_UNAVAILABLE: 75740266059SGregory Neil Shapiro /* server disappeared, try reopen on next search */ 75840266059SGregory Neil Shapiro statp = EX_RESTART; 75940266059SGregory Neil Shapiro break; 76040266059SGregory Neil Shapiro } 76140266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 76240266059SGregory Neil Shapiro } 76340266059SGregory Neil Shapiro LDAPMAP_ERROR_CLEANUP(); 76440266059SGregory Neil Shapiro errno = save_errno; 76540266059SGregory Neil Shapiro return statp; 76640266059SGregory Neil Shapiro } 76740266059SGregory Neil Shapiro 76840266059SGregory Neil Shapiro if (lmap->ldap_res != NULL) 76940266059SGregory Neil Shapiro { 77040266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); 77140266059SGregory Neil Shapiro lmap->ldap_res = NULL; 77240266059SGregory Neil Shapiro } 77340266059SGregory Neil Shapiro 77440266059SGregory Neil Shapiro if (toplevel) 77540266059SGregory Neil Shapiro { 77640266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST *rl; 77740266059SGregory Neil Shapiro 77840266059SGregory Neil Shapiro /* 77940266059SGregory Neil Shapiro ** Spin through the built-up recurse list at the top 78040266059SGregory Neil Shapiro ** of the recursion. Since new items are added at the 78140266059SGregory Neil Shapiro ** end of the shared list, we actually only ever get 78240266059SGregory Neil Shapiro ** one level of recursion before things pop back to the 78340266059SGregory Neil Shapiro ** top. Any items added to the list during that recursion 78440266059SGregory Neil Shapiro ** will be expanded by the top level. 78540266059SGregory Neil Shapiro */ 78640266059SGregory Neil Shapiro 78740266059SGregory Neil Shapiro for (rl = recurse; rl != NULL; rl = rl->lr_next) 78840266059SGregory Neil Shapiro { 78940266059SGregory Neil Shapiro int sid; 79040266059SGregory Neil Shapiro int status; 79140266059SGregory Neil Shapiro 79240266059SGregory Neil Shapiro if (rl->lr_type == LDAPMAP_ATTR_NORMAL) 79340266059SGregory Neil Shapiro { 79440266059SGregory Neil Shapiro /* already expanded */ 79540266059SGregory Neil Shapiro continue; 79640266059SGregory Neil Shapiro } 79740266059SGregory Neil Shapiro else if (rl->lr_type == LDAPMAP_ATTR_DN) 79840266059SGregory Neil Shapiro { 79940266059SGregory Neil Shapiro /* do DN search */ 80040266059SGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 80140266059SGregory Neil Shapiro rl->lr_search, 80240266059SGregory Neil Shapiro lmap->ldap_scope, 80340266059SGregory Neil Shapiro "(objectClass=*)", 80440266059SGregory Neil Shapiro lmap->ldap_attr_final, 80540266059SGregory Neil Shapiro lmap->ldap_attrsonly); 80640266059SGregory Neil Shapiro } 80740266059SGregory Neil Shapiro else if (rl->lr_type == LDAPMAP_ATTR_FILTER) 80840266059SGregory Neil Shapiro { 80940266059SGregory Neil Shapiro /* do new search */ 81040266059SGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 81140266059SGregory Neil Shapiro lmap->ldap_base, 81240266059SGregory Neil Shapiro lmap->ldap_scope, 81340266059SGregory Neil Shapiro rl->lr_search, 81440266059SGregory Neil Shapiro lmap->ldap_attr_final, 81540266059SGregory Neil Shapiro lmap->ldap_attrsonly); 81640266059SGregory Neil Shapiro } 81740266059SGregory Neil Shapiro else if (rl->lr_type == LDAPMAP_ATTR_URL) 81840266059SGregory Neil Shapiro { 81940266059SGregory Neil Shapiro /* do new URL search */ 82040266059SGregory Neil Shapiro sid = ldap_url_search(lmap->ldap_ld, 82140266059SGregory Neil Shapiro rl->lr_search, 82240266059SGregory Neil Shapiro lmap->ldap_attrsonly); 82340266059SGregory Neil Shapiro } 82440266059SGregory Neil Shapiro else 82540266059SGregory Neil Shapiro { 82640266059SGregory Neil Shapiro /* unknown or illegal attribute type */ 82740266059SGregory Neil Shapiro errno = EFAULT; 82840266059SGregory Neil Shapiro return EX_SOFTWARE; 82940266059SGregory Neil Shapiro } 83040266059SGregory Neil Shapiro 83140266059SGregory Neil Shapiro /* Collect results */ 83240266059SGregory Neil Shapiro if (sid == -1) 83340266059SGregory Neil Shapiro { 83440266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 83540266059SGregory Neil Shapiro statp = EX_TEMPFAIL; 83640266059SGregory Neil Shapiro switch (save_errno) 83740266059SGregory Neil Shapiro { 83840266059SGregory Neil Shapiro #ifdef LDAP_SERVER_DOWN 83940266059SGregory Neil Shapiro case LDAP_SERVER_DOWN: 84040266059SGregory Neil Shapiro #endif /* LDAP_SERVER_DOWN */ 84140266059SGregory Neil Shapiro case LDAP_TIMEOUT: 84240266059SGregory Neil Shapiro case LDAP_UNAVAILABLE: 84340266059SGregory Neil Shapiro /* server disappeared, try reopen on next search */ 84440266059SGregory Neil Shapiro statp = EX_RESTART; 84540266059SGregory Neil Shapiro break; 84640266059SGregory Neil Shapiro } 84740266059SGregory Neil Shapiro errno = save_errno + E_LDAPBASE; 84840266059SGregory Neil Shapiro return statp; 84940266059SGregory Neil Shapiro } 85040266059SGregory Neil Shapiro 85140266059SGregory Neil Shapiro status = sm_ldap_results(lmap, sid, flags, delim, 85240266059SGregory Neil Shapiro rpool, result, recurse); 85340266059SGregory Neil Shapiro save_errno = errno; 85440266059SGregory Neil Shapiro if (status != EX_OK && status != EX_NOTFOUND) 85540266059SGregory Neil Shapiro { 85640266059SGregory Neil Shapiro errno = save_errno; 85740266059SGregory Neil Shapiro return status; 85840266059SGregory Neil Shapiro } 85940266059SGregory Neil Shapiro 86040266059SGregory Neil Shapiro /* Mark as done */ 86140266059SGregory Neil Shapiro rl->lr_type = LDAPMAP_ATTR_NORMAL; 86240266059SGregory Neil Shapiro } 86340266059SGregory Neil Shapiro } 86440266059SGregory Neil Shapiro return statp; 86540266059SGregory Neil Shapiro } 86640266059SGregory Neil Shapiro #endif /* _FFR_LDAP_RECURSION */ 86740266059SGregory Neil Shapiro 86840266059SGregory Neil Shapiro /* 86940266059SGregory Neil Shapiro ** SM_LDAP_CLOSE -- close LDAP connection 87040266059SGregory Neil Shapiro ** 87140266059SGregory Neil Shapiro ** Parameters: 87240266059SGregory Neil Shapiro ** lmap -- LDAP map information 87340266059SGregory Neil Shapiro ** 87440266059SGregory Neil Shapiro ** Returns: 87540266059SGregory Neil Shapiro ** None. 87640266059SGregory Neil Shapiro ** 87740266059SGregory Neil Shapiro */ 87840266059SGregory Neil Shapiro 87940266059SGregory Neil Shapiro void 88040266059SGregory Neil Shapiro sm_ldap_close(lmap) 88140266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 88240266059SGregory Neil Shapiro { 88340266059SGregory Neil Shapiro if (lmap->ldap_ld == NULL) 88440266059SGregory Neil Shapiro return; 88540266059SGregory Neil Shapiro 88640266059SGregory Neil Shapiro if (lmap->ldap_pid == getpid()) 88740266059SGregory Neil Shapiro ldap_unbind(lmap->ldap_ld); 88840266059SGregory Neil Shapiro lmap->ldap_ld = NULL; 88940266059SGregory Neil Shapiro lmap->ldap_pid = 0; 89040266059SGregory Neil Shapiro } 89140266059SGregory Neil Shapiro 89240266059SGregory Neil Shapiro /* 89340266059SGregory Neil Shapiro ** SM_LDAP_SETOPTS -- set LDAP options 89440266059SGregory Neil Shapiro ** 89540266059SGregory Neil Shapiro ** Parameters: 89640266059SGregory Neil Shapiro ** ld -- LDAP session handle 89740266059SGregory Neil Shapiro ** lmap -- LDAP map information 89840266059SGregory Neil Shapiro ** 89940266059SGregory Neil Shapiro ** Returns: 90040266059SGregory Neil Shapiro ** None. 90140266059SGregory Neil Shapiro ** 90240266059SGregory Neil Shapiro */ 90340266059SGregory Neil Shapiro 90440266059SGregory Neil Shapiro void 90540266059SGregory Neil Shapiro sm_ldap_setopts(ld, lmap) 90640266059SGregory Neil Shapiro LDAP *ld; 90740266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 90840266059SGregory Neil Shapiro { 90940266059SGregory Neil Shapiro # if USE_LDAP_SET_OPTION 91040266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); 91140266059SGregory Neil Shapiro if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) 91240266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); 91340266059SGregory Neil Shapiro else 91440266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 91540266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); 91640266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); 91740266059SGregory Neil Shapiro # else /* USE_LDAP_SET_OPTION */ 91840266059SGregory Neil Shapiro /* From here on in we can use ldap internal timelimits */ 91940266059SGregory Neil Shapiro ld->ld_deref = lmap->ldap_deref; 92040266059SGregory Neil Shapiro ld->ld_options = lmap->ldap_options; 92140266059SGregory Neil Shapiro ld->ld_sizelimit = lmap->ldap_sizelimit; 92240266059SGregory Neil Shapiro ld->ld_timelimit = lmap->ldap_timelimit; 92340266059SGregory Neil Shapiro # endif /* USE_LDAP_SET_OPTION */ 92440266059SGregory Neil Shapiro } 92540266059SGregory Neil Shapiro 92640266059SGregory Neil Shapiro /* 92740266059SGregory Neil Shapiro ** SM_LDAP_GETERRNO -- get ldap errno value 92840266059SGregory Neil Shapiro ** 92940266059SGregory Neil Shapiro ** Parameters: 93040266059SGregory Neil Shapiro ** ld -- LDAP session handle 93140266059SGregory Neil Shapiro ** 93240266059SGregory Neil Shapiro ** Returns: 93340266059SGregory Neil Shapiro ** LDAP errno. 93440266059SGregory Neil Shapiro ** 93540266059SGregory Neil Shapiro */ 93640266059SGregory Neil Shapiro 93740266059SGregory Neil Shapiro int 93840266059SGregory Neil Shapiro sm_ldap_geterrno(ld) 93940266059SGregory Neil Shapiro LDAP *ld; 94040266059SGregory Neil Shapiro { 94140266059SGregory Neil Shapiro int err = LDAP_SUCCESS; 94240266059SGregory Neil Shapiro 94340266059SGregory Neil Shapiro # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 94440266059SGregory Neil Shapiro (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); 94540266059SGregory Neil Shapiro # else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 94640266059SGregory Neil Shapiro # ifdef LDAP_OPT_SIZELIMIT 94740266059SGregory Neil Shapiro err = ldap_get_lderrno(ld, NULL, NULL); 94840266059SGregory Neil Shapiro # else /* LDAP_OPT_SIZELIMIT */ 94940266059SGregory Neil Shapiro err = ld->ld_errno; 95040266059SGregory Neil Shapiro 95140266059SGregory Neil Shapiro /* 95240266059SGregory Neil Shapiro ** Reset value to prevent lingering LDAP_DECODING_ERROR due to 95340266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see above) 95440266059SGregory Neil Shapiro */ 95540266059SGregory Neil Shapiro 95640266059SGregory Neil Shapiro ld->ld_errno = LDAP_SUCCESS; 95740266059SGregory Neil Shapiro # endif /* LDAP_OPT_SIZELIMIT */ 95840266059SGregory Neil Shapiro # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 95940266059SGregory Neil Shapiro return err; 96040266059SGregory Neil Shapiro } 96140266059SGregory Neil Shapiro # endif /* LDAPMAP */ 962