140266059SGregory Neil Shapiro /* 2ffb83623SGregory Neil Shapiro * Copyright (c) 2001-2007 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 10d0cef73dSGregory Neil Shapiro /* some "deprecated" calls are used, e.g., ldap_get_values() */ 11d0cef73dSGregory Neil Shapiro #define LDAP_DEPRECATED 1 12d0cef73dSGregory Neil Shapiro 1340266059SGregory Neil Shapiro #include <sm/gen.h> 14ffb83623SGregory Neil Shapiro SM_RCSID("@(#)$Id: ldap.c,v 1.80 2007/10/12 00:19:44 ca Exp $") 1540266059SGregory Neil Shapiro 1640266059SGregory Neil Shapiro #if LDAPMAP 1740266059SGregory Neil Shapiro # include <sys/types.h> 1840266059SGregory Neil Shapiro # include <errno.h> 1940266059SGregory Neil Shapiro # include <setjmp.h> 2040266059SGregory Neil Shapiro # include <stdlib.h> 2140266059SGregory Neil Shapiro # include <unistd.h> 2240266059SGregory Neil Shapiro 2340266059SGregory Neil Shapiro # include <sm/bitops.h> 2440266059SGregory Neil Shapiro # include <sm/clock.h> 2540266059SGregory Neil Shapiro # include <sm/conf.h> 2640266059SGregory Neil Shapiro # include <sm/debug.h> 2740266059SGregory Neil Shapiro # include <sm/errstring.h> 2840266059SGregory Neil Shapiro # include <sm/ldap.h> 2940266059SGregory Neil Shapiro # include <sm/string.h> 30605302a5SGregory Neil Shapiro # ifdef EX_OK 31605302a5SGregory Neil Shapiro # undef EX_OK /* for SVr4.2 SMP */ 32605302a5SGregory Neil Shapiro # endif /* EX_OK */ 3340266059SGregory Neil Shapiro # include <sm/sysexits.h> 3440266059SGregory Neil Shapiro 3540266059SGregory Neil Shapiro SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap", 3640266059SGregory Neil Shapiro "@(#)$Debug: sm_trace_ldap - trace LDAP operations $"); 3740266059SGregory Neil Shapiro 3840266059SGregory Neil Shapiro static void ldaptimeout __P((int)); 39b6bacd31SGregory Neil Shapiro static bool sm_ldap_has_objectclass __P((SM_LDAP_STRUCT *, LDAPMessage *, char *)); 40b6bacd31SGregory Neil Shapiro static SM_LDAP_RECURSE_ENTRY *sm_ldap_add_recurse __P((SM_LDAP_RECURSE_LIST **, char *, int, SM_RPOOL_T *)); 4140266059SGregory Neil Shapiro 4240266059SGregory Neil Shapiro /* 4340266059SGregory Neil Shapiro ** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT 4440266059SGregory Neil Shapiro ** 4540266059SGregory Neil Shapiro ** Parameters: 4640266059SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT to clear 4740266059SGregory Neil Shapiro ** 4840266059SGregory Neil Shapiro ** Returns: 4940266059SGregory Neil Shapiro ** None. 5040266059SGregory Neil Shapiro ** 5140266059SGregory Neil Shapiro */ 5240266059SGregory Neil Shapiro 534e4196cbSGregory Neil Shapiro #if _FFR_LDAP_VERSION 544e4196cbSGregory Neil Shapiro # if defined(LDAP_VERSION_MAX) && _FFR_LDAP_VERSION > LDAP_VERSION_MAX 554e4196cbSGregory Neil Shapiro ERROR FFR_LDAP_VERSION > _LDAP_VERSION_MAX 564e4196cbSGregory Neil Shapiro # endif /* defined(LDAP_VERSION_MAX) && _FFR_LDAP_VERSION > LDAP_VERSION_MAX */ 574e4196cbSGregory Neil Shapiro # if defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN 584e4196cbSGregory Neil Shapiro ERROR FFR_LDAP_VERSION < _LDAP_VERSION_MIN 594e4196cbSGregory Neil Shapiro # endif /* defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN */ 604e4196cbSGregory Neil Shapiro # define SM_LDAP_VERSION_DEFAULT _FFR_LDAP_VERSION 614e4196cbSGregory Neil Shapiro #else /* _FFR_LDAP_VERSION */ 624e4196cbSGregory Neil Shapiro # define SM_LDAP_VERSION_DEFAULT 0 634e4196cbSGregory Neil Shapiro #endif /* _FFR_LDAP_VERSION */ 644e4196cbSGregory Neil Shapiro 6540266059SGregory Neil Shapiro void 6640266059SGregory Neil Shapiro sm_ldap_clear(lmap) 6740266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 6840266059SGregory Neil Shapiro { 6940266059SGregory Neil Shapiro if (lmap == NULL) 7040266059SGregory Neil Shapiro return; 7140266059SGregory Neil Shapiro 72e92d3f3fSGregory Neil Shapiro lmap->ldap_host = NULL; 7340266059SGregory Neil Shapiro lmap->ldap_port = LDAP_PORT; 74e92d3f3fSGregory Neil Shapiro lmap->ldap_uri = NULL; 754e4196cbSGregory Neil Shapiro lmap->ldap_version = SM_LDAP_VERSION_DEFAULT; 7640266059SGregory Neil Shapiro lmap->ldap_deref = LDAP_DEREF_NEVER; 7740266059SGregory Neil Shapiro lmap->ldap_timelimit = LDAP_NO_LIMIT; 7840266059SGregory Neil Shapiro lmap->ldap_sizelimit = LDAP_NO_LIMIT; 7940266059SGregory Neil Shapiro # ifdef LDAP_REFERRALS 8040266059SGregory Neil Shapiro lmap->ldap_options = LDAP_OPT_REFERRALS; 8140266059SGregory Neil Shapiro # else /* LDAP_REFERRALS */ 8240266059SGregory Neil Shapiro lmap->ldap_options = 0; 8340266059SGregory Neil Shapiro # endif /* LDAP_REFERRALS */ 8440266059SGregory Neil Shapiro lmap->ldap_attrsep = '\0'; 8540266059SGregory Neil Shapiro lmap->ldap_binddn = NULL; 8640266059SGregory Neil Shapiro lmap->ldap_secret = NULL; 8740266059SGregory Neil Shapiro lmap->ldap_method = LDAP_AUTH_SIMPLE; 8840266059SGregory Neil Shapiro lmap->ldap_base = NULL; 8940266059SGregory Neil Shapiro lmap->ldap_scope = LDAP_SCOPE_SUBTREE; 9040266059SGregory Neil Shapiro lmap->ldap_attrsonly = LDAPMAP_FALSE; 9140266059SGregory Neil Shapiro lmap->ldap_timeout.tv_sec = 0; 9240266059SGregory Neil Shapiro lmap->ldap_timeout.tv_usec = 0; 9340266059SGregory Neil Shapiro lmap->ldap_ld = NULL; 9440266059SGregory Neil Shapiro lmap->ldap_filter = NULL; 9540266059SGregory Neil Shapiro lmap->ldap_attr[0] = NULL; 96605302a5SGregory Neil Shapiro lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE; 97605302a5SGregory Neil Shapiro lmap->ldap_attr_needobjclass[0] = NULL; 9840266059SGregory Neil Shapiro lmap->ldap_res = NULL; 9940266059SGregory Neil Shapiro lmap->ldap_next = NULL; 10040266059SGregory Neil Shapiro lmap->ldap_pid = 0; 101d0cef73dSGregory Neil Shapiro lmap->ldap_multi_args = false; 10240266059SGregory Neil Shapiro } 10340266059SGregory Neil Shapiro 10440266059SGregory Neil Shapiro /* 10540266059SGregory Neil Shapiro ** SM_LDAP_START -- actually connect to an LDAP server 10640266059SGregory Neil Shapiro ** 10740266059SGregory Neil Shapiro ** Parameters: 10840266059SGregory Neil Shapiro ** name -- name of map for debug output. 10940266059SGregory Neil Shapiro ** lmap -- the LDAP map being opened. 11040266059SGregory Neil Shapiro ** 11140266059SGregory Neil Shapiro ** Returns: 11240266059SGregory Neil Shapiro ** true if connection is successful, false otherwise. 11340266059SGregory Neil Shapiro ** 11440266059SGregory Neil Shapiro ** Side Effects: 11540266059SGregory Neil Shapiro ** Populates lmap->ldap_ld. 11640266059SGregory Neil Shapiro */ 11740266059SGregory Neil Shapiro 11840266059SGregory Neil Shapiro static jmp_buf LDAPTimeout; 11940266059SGregory Neil Shapiro 12040266059SGregory Neil Shapiro #define SM_LDAP_SETTIMEOUT(to) \ 12140266059SGregory Neil Shapiro do \ 12240266059SGregory Neil Shapiro { \ 12340266059SGregory Neil Shapiro if (to != 0) \ 12440266059SGregory Neil Shapiro { \ 12540266059SGregory Neil Shapiro if (setjmp(LDAPTimeout) != 0) \ 12640266059SGregory Neil Shapiro { \ 12740266059SGregory Neil Shapiro errno = ETIMEDOUT; \ 12840266059SGregory Neil Shapiro return false; \ 12940266059SGregory Neil Shapiro } \ 13040266059SGregory Neil Shapiro ev = sm_setevent(to, ldaptimeout, 0); \ 13140266059SGregory Neil Shapiro } \ 13240266059SGregory Neil Shapiro } while (0) 13340266059SGregory Neil Shapiro 13440266059SGregory Neil Shapiro #define SM_LDAP_CLEARTIMEOUT() \ 13540266059SGregory Neil Shapiro do \ 13640266059SGregory Neil Shapiro { \ 13740266059SGregory Neil Shapiro if (ev != NULL) \ 13840266059SGregory Neil Shapiro sm_clrevent(ev); \ 13940266059SGregory Neil Shapiro } while (0) 14040266059SGregory Neil Shapiro 14140266059SGregory Neil Shapiro bool 14240266059SGregory Neil Shapiro sm_ldap_start(name, lmap) 14340266059SGregory Neil Shapiro char *name; 14440266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 14540266059SGregory Neil Shapiro { 14640266059SGregory Neil Shapiro int bind_result; 147b6bacd31SGregory Neil Shapiro int save_errno = 0; 148e92d3f3fSGregory Neil Shapiro char *id; 14940266059SGregory Neil Shapiro SM_EVENT *ev = NULL; 150e92d3f3fSGregory Neil Shapiro LDAP *ld = NULL; 15140266059SGregory Neil Shapiro 15240266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 2)) 15340266059SGregory Neil Shapiro sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name); 15440266059SGregory Neil Shapiro 155e92d3f3fSGregory Neil Shapiro if (lmap->ldap_host != NULL) 156e92d3f3fSGregory Neil Shapiro id = lmap->ldap_host; 157e92d3f3fSGregory Neil Shapiro else if (lmap->ldap_uri != NULL) 158e92d3f3fSGregory Neil Shapiro id = lmap->ldap_uri; 159605302a5SGregory Neil Shapiro else 160e92d3f3fSGregory Neil Shapiro id = "localhost"; 161e92d3f3fSGregory Neil Shapiro 162e92d3f3fSGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 9)) 163e92d3f3fSGregory Neil Shapiro { 164e92d3f3fSGregory Neil Shapiro /* Don't print a port number for LDAP URIs */ 165e92d3f3fSGregory Neil Shapiro if (lmap->ldap_uri != NULL) 166e92d3f3fSGregory Neil Shapiro sm_dprintf("ldapmap_start(%s)\n", id); 167e92d3f3fSGregory Neil Shapiro else 168e92d3f3fSGregory Neil Shapiro sm_dprintf("ldapmap_start(%s, %d)\n", id, 169e92d3f3fSGregory Neil Shapiro lmap->ldap_port); 170e92d3f3fSGregory Neil Shapiro } 171e92d3f3fSGregory Neil Shapiro 172e92d3f3fSGregory Neil Shapiro if (lmap->ldap_uri != NULL) 173e92d3f3fSGregory Neil Shapiro { 174e92d3f3fSGregory Neil Shapiro #if SM_CONF_LDAP_INITIALIZE 175e92d3f3fSGregory Neil Shapiro /* LDAP server supports URIs so use them directly */ 176e92d3f3fSGregory Neil Shapiro save_errno = ldap_initialize(&ld, lmap->ldap_uri); 177e92d3f3fSGregory Neil Shapiro #else /* SM_CONF_LDAP_INITIALIZE */ 178e92d3f3fSGregory Neil Shapiro int err; 179e92d3f3fSGregory Neil Shapiro LDAPURLDesc *ludp = NULL; 180e92d3f3fSGregory Neil Shapiro 181e92d3f3fSGregory Neil Shapiro /* Blast apart URL and use the ldap_init/ldap_open below */ 182e92d3f3fSGregory Neil Shapiro err = ldap_url_parse(lmap->ldap_uri, &ludp); 183e92d3f3fSGregory Neil Shapiro if (err != 0) 184e92d3f3fSGregory Neil Shapiro { 185e92d3f3fSGregory Neil Shapiro errno = err + E_LDAPURLBASE; 186e92d3f3fSGregory Neil Shapiro return false; 187e92d3f3fSGregory Neil Shapiro } 188e92d3f3fSGregory Neil Shapiro lmap->ldap_host = sm_strdup_x(ludp->lud_host); 189e92d3f3fSGregory Neil Shapiro if (lmap->ldap_host == NULL) 190e92d3f3fSGregory Neil Shapiro { 191e92d3f3fSGregory Neil Shapiro save_errno = errno; 192e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(ludp); 193e92d3f3fSGregory Neil Shapiro errno = save_errno; 194e92d3f3fSGregory Neil Shapiro return false; 195e92d3f3fSGregory Neil Shapiro } 196e92d3f3fSGregory Neil Shapiro lmap->ldap_port = ludp->lud_port; 197e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(ludp); 198e92d3f3fSGregory Neil Shapiro #endif /* SM_CONF_LDAP_INITIALIZE */ 199e92d3f3fSGregory Neil Shapiro } 200e92d3f3fSGregory Neil Shapiro 201e92d3f3fSGregory Neil Shapiro if (ld == NULL) 202e92d3f3fSGregory Neil Shapiro { 203e92d3f3fSGregory Neil Shapiro # if USE_LDAP_INIT 204e92d3f3fSGregory Neil Shapiro ld = ldap_init(lmap->ldap_host, lmap->ldap_port); 20540266059SGregory Neil Shapiro save_errno = errno; 20640266059SGregory Neil Shapiro # else /* USE_LDAP_INIT */ 20740266059SGregory Neil Shapiro /* 20840266059SGregory Neil Shapiro ** If using ldap_open(), the actual connection to the server 20940266059SGregory Neil Shapiro ** happens now so we need the timeout here. For ldap_init(), 21040266059SGregory Neil Shapiro ** the connection happens at bind time. 21140266059SGregory Neil Shapiro */ 21240266059SGregory Neil Shapiro 21340266059SGregory Neil Shapiro SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); 214e92d3f3fSGregory Neil Shapiro ld = ldap_open(lmap->ldap_host, lmap->ldap_port); 21540266059SGregory Neil Shapiro save_errno = errno; 21640266059SGregory Neil Shapiro 21740266059SGregory Neil Shapiro /* clear the event if it has not sprung */ 21840266059SGregory Neil Shapiro SM_LDAP_CLEARTIMEOUT(); 21940266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 220e92d3f3fSGregory Neil Shapiro } 22140266059SGregory Neil Shapiro 22240266059SGregory Neil Shapiro errno = save_errno; 22340266059SGregory Neil Shapiro if (ld == NULL) 22440266059SGregory Neil Shapiro return false; 22540266059SGregory Neil Shapiro 22640266059SGregory Neil Shapiro sm_ldap_setopts(ld, lmap); 22740266059SGregory Neil Shapiro 22840266059SGregory Neil Shapiro # if USE_LDAP_INIT 22940266059SGregory Neil Shapiro /* 23040266059SGregory Neil Shapiro ** If using ldap_init(), the actual connection to the server 23140266059SGregory Neil Shapiro ** happens at ldap_bind_s() so we need the timeout here. 23240266059SGregory Neil Shapiro */ 23340266059SGregory Neil Shapiro 23440266059SGregory Neil Shapiro SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); 23540266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 23640266059SGregory Neil Shapiro 23740266059SGregory Neil Shapiro # ifdef LDAP_AUTH_KRBV4 23840266059SGregory Neil Shapiro if (lmap->ldap_method == LDAP_AUTH_KRBV4 && 23940266059SGregory Neil Shapiro lmap->ldap_secret != NULL) 24040266059SGregory Neil Shapiro { 24140266059SGregory Neil Shapiro /* 24240266059SGregory Neil Shapiro ** Need to put ticket in environment here instead of 24340266059SGregory Neil Shapiro ** during parseargs as there may be different tickets 24440266059SGregory Neil Shapiro ** for different LDAP connections. 24540266059SGregory Neil Shapiro */ 24640266059SGregory Neil Shapiro 24740266059SGregory Neil Shapiro (void) putenv(lmap->ldap_secret); 24840266059SGregory Neil Shapiro } 24940266059SGregory Neil Shapiro # endif /* LDAP_AUTH_KRBV4 */ 25040266059SGregory Neil Shapiro 25140266059SGregory Neil Shapiro bind_result = ldap_bind_s(ld, lmap->ldap_binddn, 25240266059SGregory Neil Shapiro lmap->ldap_secret, lmap->ldap_method); 25340266059SGregory Neil Shapiro 25440266059SGregory Neil Shapiro # if USE_LDAP_INIT 25540266059SGregory Neil Shapiro /* clear the event if it has not sprung */ 25640266059SGregory Neil Shapiro SM_LDAP_CLEARTIMEOUT(); 25740266059SGregory Neil Shapiro # endif /* USE_LDAP_INIT */ 25840266059SGregory Neil Shapiro 25940266059SGregory Neil Shapiro if (bind_result != LDAP_SUCCESS) 26040266059SGregory Neil Shapiro { 26140266059SGregory Neil Shapiro errno = bind_result + E_LDAPBASE; 26240266059SGregory Neil Shapiro return false; 26340266059SGregory Neil Shapiro } 26440266059SGregory Neil Shapiro 26540266059SGregory Neil Shapiro /* Save PID to make sure only this PID closes the LDAP connection */ 26640266059SGregory Neil Shapiro lmap->ldap_pid = getpid(); 26740266059SGregory Neil Shapiro lmap->ldap_ld = ld; 26840266059SGregory Neil Shapiro return true; 26940266059SGregory Neil Shapiro } 27040266059SGregory Neil Shapiro 27140266059SGregory Neil Shapiro /* ARGSUSED */ 27240266059SGregory Neil Shapiro static void 27340266059SGregory Neil Shapiro ldaptimeout(unused) 27440266059SGregory Neil Shapiro int unused; 27540266059SGregory Neil Shapiro { 27640266059SGregory Neil Shapiro /* 27740266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 27840266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 27940266059SGregory Neil Shapiro ** DOING. 28040266059SGregory Neil Shapiro */ 28140266059SGregory Neil Shapiro 28240266059SGregory Neil Shapiro errno = ETIMEDOUT; 28340266059SGregory Neil Shapiro longjmp(LDAPTimeout, 1); 28440266059SGregory Neil Shapiro } 28540266059SGregory Neil Shapiro 28640266059SGregory Neil Shapiro /* 287d0cef73dSGregory Neil Shapiro ** SM_LDAP_SEARCH_M -- initiate multi-key LDAP search 28840266059SGregory Neil Shapiro ** 28940266059SGregory Neil Shapiro ** Initiate an LDAP search, return the msgid. 29040266059SGregory Neil Shapiro ** The calling function must collect the results. 29140266059SGregory Neil Shapiro ** 29240266059SGregory Neil Shapiro ** Parameters: 29340266059SGregory Neil Shapiro ** lmap -- LDAP map information 294d0cef73dSGregory Neil Shapiro ** argv -- key vector of substitutions in LDAP filter 295d0cef73dSGregory Neil Shapiro ** NOTE: argv must have SM_LDAP_ARGS elements to prevent 296d0cef73dSGregory Neil Shapiro ** out of bound array references 29740266059SGregory Neil Shapiro ** 29840266059SGregory Neil Shapiro ** Returns: 299d0cef73dSGregory Neil Shapiro ** <0 on failure (SM_LDAP_ERR*), msgid on success 30040266059SGregory Neil Shapiro ** 30140266059SGregory Neil Shapiro */ 30240266059SGregory Neil Shapiro 30340266059SGregory Neil Shapiro int 304d0cef73dSGregory Neil Shapiro sm_ldap_search_m(lmap, argv) 30540266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 306d0cef73dSGregory Neil Shapiro char **argv; 30740266059SGregory Neil Shapiro { 30840266059SGregory Neil Shapiro int msgid; 30940266059SGregory Neil Shapiro char *fp, *p, *q; 31040266059SGregory Neil Shapiro char filter[LDAPMAP_MAX_FILTER + 1]; 31140266059SGregory Neil Shapiro 312d0cef73dSGregory Neil Shapiro SM_REQUIRE(lmap != NULL); 313d0cef73dSGregory Neil Shapiro SM_REQUIRE(argv != NULL); 314d0cef73dSGregory Neil Shapiro SM_REQUIRE(argv[0] != NULL); 315d0cef73dSGregory Neil Shapiro 31640266059SGregory Neil Shapiro memset(filter, '\0', sizeof filter); 31740266059SGregory Neil Shapiro fp = filter; 31840266059SGregory Neil Shapiro p = lmap->ldap_filter; 31940266059SGregory Neil Shapiro while ((q = strchr(p, '%')) != NULL) 32040266059SGregory Neil Shapiro { 321d0cef73dSGregory Neil Shapiro char *key; 322d0cef73dSGregory Neil Shapiro 323d0cef73dSGregory Neil Shapiro if (lmap->ldap_multi_args) 324d0cef73dSGregory Neil Shapiro { 325d0cef73dSGregory Neil Shapiro #if SM_LDAP_ARGS < 10 326d0cef73dSGregory Neil Shapiro # ERROR _SM_LDAP_ARGS must be 10 327d0cef73dSGregory Neil Shapiro #endif /* SM_LDAP_ARGS < 10 */ 328d0cef73dSGregory Neil Shapiro if (q[1] == 's') 329d0cef73dSGregory Neil Shapiro key = argv[0]; 330d0cef73dSGregory Neil Shapiro else if (q[1] >= '0' && q[1] <= '9') 331d0cef73dSGregory Neil Shapiro { 332d0cef73dSGregory Neil Shapiro key = argv[q[1] - '0']; 333d0cef73dSGregory Neil Shapiro if (key == NULL) 334d0cef73dSGregory Neil Shapiro { 335d0cef73dSGregory Neil Shapiro # if SM_LDAP_ERROR_ON_MISSING_ARGS 336d0cef73dSGregory Neil Shapiro return SM_LDAP_ERR_ARG_MISS; 337d0cef73dSGregory Neil Shapiro # else /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 338d0cef73dSGregory Neil Shapiro key = ""; 339d0cef73dSGregory Neil Shapiro # endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 340d0cef73dSGregory Neil Shapiro } 341d0cef73dSGregory Neil Shapiro } 342d0cef73dSGregory Neil Shapiro else 343d0cef73dSGregory Neil Shapiro key = NULL; 344d0cef73dSGregory Neil Shapiro } 345d0cef73dSGregory Neil Shapiro else 346d0cef73dSGregory Neil Shapiro key = argv[0]; 347d0cef73dSGregory Neil Shapiro 34840266059SGregory Neil Shapiro if (q[1] == 's') 34940266059SGregory Neil Shapiro { 35040266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 35140266059SGregory Neil Shapiro "%.*s%s", (int) (q - p), p, key); 35240266059SGregory Neil Shapiro fp += strlen(fp); 35340266059SGregory Neil Shapiro p = q + 2; 35440266059SGregory Neil Shapiro } 355d0cef73dSGregory Neil Shapiro else if (q[1] == '0' || 356d0cef73dSGregory Neil Shapiro (lmap->ldap_multi_args && q[1] >= '0' && q[1] <= '9')) 35740266059SGregory Neil Shapiro { 35840266059SGregory Neil Shapiro char *k = key; 35940266059SGregory Neil Shapiro 36040266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 36140266059SGregory Neil Shapiro "%.*s", (int) (q - p), p); 36240266059SGregory Neil Shapiro fp += strlen(fp); 36340266059SGregory Neil Shapiro p = q + 2; 36440266059SGregory Neil Shapiro 36540266059SGregory Neil Shapiro /* Properly escape LDAP special characters */ 36640266059SGregory Neil Shapiro while (SPACELEFT(filter, fp) > 0 && 36740266059SGregory Neil Shapiro *k != '\0') 36840266059SGregory Neil Shapiro { 36940266059SGregory Neil Shapiro if (*k == '*' || *k == '(' || 37040266059SGregory Neil Shapiro *k == ')' || *k == '\\') 37140266059SGregory Neil Shapiro { 37240266059SGregory Neil Shapiro (void) sm_strlcat(fp, 37340266059SGregory Neil Shapiro (*k == '*' ? "\\2A" : 37440266059SGregory Neil Shapiro (*k == '(' ? "\\28" : 37540266059SGregory Neil Shapiro (*k == ')' ? "\\29" : 37640266059SGregory Neil Shapiro (*k == '\\' ? "\\5C" : 37740266059SGregory Neil Shapiro "\00")))), 37840266059SGregory Neil Shapiro SPACELEFT(filter, fp)); 37940266059SGregory Neil Shapiro fp += strlen(fp); 38040266059SGregory Neil Shapiro k++; 38140266059SGregory Neil Shapiro } 38240266059SGregory Neil Shapiro else 38340266059SGregory Neil Shapiro *fp++ = *k++; 38440266059SGregory Neil Shapiro } 38540266059SGregory Neil Shapiro } 38640266059SGregory Neil Shapiro else 38740266059SGregory Neil Shapiro { 38840266059SGregory Neil Shapiro (void) sm_snprintf(fp, SPACELEFT(filter, fp), 38940266059SGregory Neil Shapiro "%.*s", (int) (q - p + 1), p); 39040266059SGregory Neil Shapiro p = q + (q[1] == '%' ? 2 : 1); 39140266059SGregory Neil Shapiro fp += strlen(fp); 39240266059SGregory Neil Shapiro } 39340266059SGregory Neil Shapiro } 39440266059SGregory Neil Shapiro (void) sm_strlcpy(fp, p, SPACELEFT(filter, fp)); 39540266059SGregory Neil Shapiro if (sm_debug_active(&SmLDAPTrace, 20)) 39640266059SGregory Neil Shapiro sm_dprintf("ldap search filter=%s\n", filter); 39740266059SGregory Neil Shapiro 39840266059SGregory Neil Shapiro lmap->ldap_res = NULL; 399605302a5SGregory Neil Shapiro msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, 400605302a5SGregory Neil Shapiro lmap->ldap_scope, filter, 40140266059SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? NULL : 40240266059SGregory Neil Shapiro lmap->ldap_attr), 40340266059SGregory Neil Shapiro lmap->ldap_attrsonly); 40440266059SGregory Neil Shapiro return msgid; 40540266059SGregory Neil Shapiro } 40640266059SGregory Neil Shapiro 40740266059SGregory Neil Shapiro /* 408d0cef73dSGregory Neil Shapiro ** SM_LDAP_SEARCH -- initiate LDAP search 409d0cef73dSGregory Neil Shapiro ** 410d0cef73dSGregory Neil Shapiro ** Initiate an LDAP search, return the msgid. 411d0cef73dSGregory Neil Shapiro ** The calling function must collect the results. 412d0cef73dSGregory Neil Shapiro ** Note this is just a wrapper into sm_ldap_search_m() 413d0cef73dSGregory Neil Shapiro ** 414d0cef73dSGregory Neil Shapiro ** Parameters: 415d0cef73dSGregory Neil Shapiro ** lmap -- LDAP map information 416d0cef73dSGregory Neil Shapiro ** key -- key to substitute in LDAP filter 417d0cef73dSGregory Neil Shapiro ** 418d0cef73dSGregory Neil Shapiro ** Returns: 419d0cef73dSGregory Neil Shapiro ** <0 on failure, msgid on success 420d0cef73dSGregory Neil Shapiro ** 421d0cef73dSGregory Neil Shapiro */ 422d0cef73dSGregory Neil Shapiro 423d0cef73dSGregory Neil Shapiro int 424d0cef73dSGregory Neil Shapiro sm_ldap_search(lmap, key) 425d0cef73dSGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 426d0cef73dSGregory Neil Shapiro char *key; 427d0cef73dSGregory Neil Shapiro { 428d0cef73dSGregory Neil Shapiro char *argv[SM_LDAP_ARGS]; 429d0cef73dSGregory Neil Shapiro 430d0cef73dSGregory Neil Shapiro memset(argv, '\0', sizeof argv); 431d0cef73dSGregory Neil Shapiro argv[0] = key; 432d0cef73dSGregory Neil Shapiro return sm_ldap_search_m(lmap, argv); 433d0cef73dSGregory Neil Shapiro } 434d0cef73dSGregory Neil Shapiro 435d0cef73dSGregory Neil Shapiro /* 436605302a5SGregory Neil Shapiro ** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a 437605302a5SGregory Neil Shapiro ** particular objectClass 438605302a5SGregory Neil Shapiro ** 439605302a5SGregory Neil Shapiro ** Parameters: 440605302a5SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT in use 441605302a5SGregory Neil Shapiro ** entry -- current LDAP entry struct 442605302a5SGregory Neil Shapiro ** ocvalue -- particular objectclass in question. 443605302a5SGregory Neil Shapiro ** may be of form (fee|foo|fum) meaning 444605302a5SGregory Neil Shapiro ** any entry can be part of either fee, 445605302a5SGregory Neil Shapiro ** foo or fum objectclass 446605302a5SGregory Neil Shapiro ** 447605302a5SGregory Neil Shapiro ** Returns: 448605302a5SGregory Neil Shapiro ** true if item has that objectClass 449605302a5SGregory Neil Shapiro */ 450605302a5SGregory Neil Shapiro 451605302a5SGregory Neil Shapiro static bool 452605302a5SGregory Neil Shapiro sm_ldap_has_objectclass(lmap, entry, ocvalue) 453605302a5SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 454605302a5SGregory Neil Shapiro LDAPMessage *entry; 455605302a5SGregory Neil Shapiro char *ocvalue; 456605302a5SGregory Neil Shapiro { 457605302a5SGregory Neil Shapiro char **vals = NULL; 458605302a5SGregory Neil Shapiro int i; 459605302a5SGregory Neil Shapiro 460605302a5SGregory Neil Shapiro if (ocvalue == NULL) 461605302a5SGregory Neil Shapiro return false; 462605302a5SGregory Neil Shapiro 463605302a5SGregory Neil Shapiro vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass"); 464605302a5SGregory Neil Shapiro if (vals == NULL) 465605302a5SGregory Neil Shapiro return false; 466605302a5SGregory Neil Shapiro 467605302a5SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 468605302a5SGregory Neil Shapiro { 469605302a5SGregory Neil Shapiro char *p; 470605302a5SGregory Neil Shapiro char *q; 471605302a5SGregory Neil Shapiro 472605302a5SGregory Neil Shapiro p = q = ocvalue; 473605302a5SGregory Neil Shapiro while (*p != '\0') 474605302a5SGregory Neil Shapiro { 475605302a5SGregory Neil Shapiro while (*p != '\0' && *p != '|') 476605302a5SGregory Neil Shapiro p++; 477605302a5SGregory Neil Shapiro 478605302a5SGregory Neil Shapiro if ((p - q) == strlen(vals[i]) && 479605302a5SGregory Neil Shapiro sm_strncasecmp(vals[i], q, p - q) == 0) 480605302a5SGregory Neil Shapiro { 481605302a5SGregory Neil Shapiro ldap_value_free(vals); 482605302a5SGregory Neil Shapiro return true; 483605302a5SGregory Neil Shapiro } 484605302a5SGregory Neil Shapiro 485605302a5SGregory Neil Shapiro while (*p == '|') 486605302a5SGregory Neil Shapiro p++; 487605302a5SGregory Neil Shapiro q = p; 488605302a5SGregory Neil Shapiro } 489605302a5SGregory Neil Shapiro } 490605302a5SGregory Neil Shapiro 491605302a5SGregory Neil Shapiro ldap_value_free(vals); 492605302a5SGregory Neil Shapiro return false; 493605302a5SGregory Neil Shapiro } 494605302a5SGregory Neil Shapiro 495605302a5SGregory Neil Shapiro /* 49640266059SGregory Neil Shapiro ** SM_LDAP_RESULTS -- return results from an LDAP lookup in result 49740266059SGregory Neil Shapiro ** 49840266059SGregory Neil Shapiro ** Parameters: 49940266059SGregory Neil Shapiro ** lmap -- pointer to SM_LDAP_STRUCT in use 50040266059SGregory Neil Shapiro ** msgid -- msgid returned by sm_ldap_search() 50140266059SGregory Neil Shapiro ** flags -- flags for the lookup 50240266059SGregory Neil Shapiro ** delim -- delimiter for result concatenation 50340266059SGregory Neil Shapiro ** rpool -- memory pool for storage 50440266059SGregory Neil Shapiro ** result -- return string 50540266059SGregory Neil Shapiro ** recurse -- recursion list 50640266059SGregory Neil Shapiro ** 50740266059SGregory Neil Shapiro ** Returns: 50840266059SGregory Neil Shapiro ** status (sysexit) 50940266059SGregory Neil Shapiro */ 51040266059SGregory Neil Shapiro 511605302a5SGregory Neil Shapiro # define SM_LDAP_ERROR_CLEANUP() \ 51240266059SGregory Neil Shapiro { \ 51340266059SGregory Neil Shapiro if (lmap->ldap_res != NULL) \ 51440266059SGregory Neil Shapiro { \ 51540266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); \ 51640266059SGregory Neil Shapiro lmap->ldap_res = NULL; \ 51740266059SGregory Neil Shapiro } \ 51840266059SGregory Neil Shapiro (void) ldap_abandon(lmap->ldap_ld, msgid); \ 51940266059SGregory Neil Shapiro } 52040266059SGregory Neil Shapiro 521605302a5SGregory Neil Shapiro static SM_LDAP_RECURSE_ENTRY * 522605302a5SGregory Neil Shapiro sm_ldap_add_recurse(top, item, type, rpool) 52340266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST **top; 52440266059SGregory Neil Shapiro char *item; 52540266059SGregory Neil Shapiro int type; 52640266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 52740266059SGregory Neil Shapiro { 528605302a5SGregory Neil Shapiro int n; 529605302a5SGregory Neil Shapiro int m; 530605302a5SGregory Neil Shapiro int p; 531605302a5SGregory Neil Shapiro int insertat; 532605302a5SGregory Neil Shapiro int moveb; 533605302a5SGregory Neil Shapiro int oldsizeb; 534605302a5SGregory Neil Shapiro int rc; 535605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY *newe; 536605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY **olddata; 53740266059SGregory Neil Shapiro 538605302a5SGregory Neil Shapiro /* 539605302a5SGregory Neil Shapiro ** This code will maintain a list of 540605302a5SGregory Neil Shapiro ** SM_LDAP_RECURSE_ENTRY structures 541605302a5SGregory Neil Shapiro ** in ascending order. 542605302a5SGregory Neil Shapiro */ 543605302a5SGregory Neil Shapiro 544605302a5SGregory Neil Shapiro if (*top == NULL) 54540266059SGregory Neil Shapiro { 546605302a5SGregory Neil Shapiro /* Allocate an initial SM_LDAP_RECURSE_LIST struct */ 547605302a5SGregory Neil Shapiro *top = sm_rpool_malloc_x(rpool, sizeof **top); 548d0cef73dSGregory Neil Shapiro (*top)->lrl_cnt = 0; 549d0cef73dSGregory Neil Shapiro (*top)->lrl_size = 0; 550d0cef73dSGregory Neil Shapiro (*top)->lrl_data = NULL; 55140266059SGregory Neil Shapiro } 55240266059SGregory Neil Shapiro 553d0cef73dSGregory Neil Shapiro if ((*top)->lrl_cnt >= (*top)->lrl_size) 554605302a5SGregory Neil Shapiro { 555605302a5SGregory Neil Shapiro /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */ 556d0cef73dSGregory Neil Shapiro olddata = (*top)->lrl_data; 557d0cef73dSGregory Neil Shapiro if ((*top)->lrl_size == 0) 558605302a5SGregory Neil Shapiro { 559605302a5SGregory Neil Shapiro oldsizeb = 0; 560d0cef73dSGregory Neil Shapiro (*top)->lrl_size = 256; 561605302a5SGregory Neil Shapiro } 56240266059SGregory Neil Shapiro else 563605302a5SGregory Neil Shapiro { 564d0cef73dSGregory Neil Shapiro oldsizeb = (*top)->lrl_size * sizeof *((*top)->lrl_data); 565d0cef73dSGregory Neil Shapiro (*top)->lrl_size *= 2; 566605302a5SGregory Neil Shapiro } 567d0cef73dSGregory Neil Shapiro (*top)->lrl_data = sm_rpool_malloc_x(rpool, 568d0cef73dSGregory Neil Shapiro (*top)->lrl_size * sizeof *((*top)->lrl_data)); 569605302a5SGregory Neil Shapiro if (oldsizeb > 0) 570d0cef73dSGregory Neil Shapiro memcpy((*top)->lrl_data, olddata, oldsizeb); 571605302a5SGregory Neil Shapiro } 572605302a5SGregory Neil Shapiro 573605302a5SGregory Neil Shapiro /* 574605302a5SGregory Neil Shapiro ** Binary search/insert item:type into list. 575605302a5SGregory Neil Shapiro ** Return current entry pointer if already exists. 576605302a5SGregory Neil Shapiro */ 577605302a5SGregory Neil Shapiro 578605302a5SGregory Neil Shapiro n = 0; 579d0cef73dSGregory Neil Shapiro m = (*top)->lrl_cnt - 1; 580605302a5SGregory Neil Shapiro if (m < 0) 581605302a5SGregory Neil Shapiro insertat = 0; 582605302a5SGregory Neil Shapiro else 583605302a5SGregory Neil Shapiro insertat = -1; 584605302a5SGregory Neil Shapiro 585605302a5SGregory Neil Shapiro while (insertat == -1) 586605302a5SGregory Neil Shapiro { 587605302a5SGregory Neil Shapiro p = (m + n) / 2; 588605302a5SGregory Neil Shapiro 589d0cef73dSGregory Neil Shapiro rc = sm_strcasecmp(item, (*top)->lrl_data[p]->lr_search); 590605302a5SGregory Neil Shapiro if (rc == 0) 591d0cef73dSGregory Neil Shapiro rc = type - (*top)->lrl_data[p]->lr_type; 592605302a5SGregory Neil Shapiro 593605302a5SGregory Neil Shapiro if (rc < 0) 594605302a5SGregory Neil Shapiro m = p - 1; 595605302a5SGregory Neil Shapiro else if (rc > 0) 596605302a5SGregory Neil Shapiro n = p + 1; 597605302a5SGregory Neil Shapiro else 598d0cef73dSGregory Neil Shapiro return (*top)->lrl_data[p]; 599605302a5SGregory Neil Shapiro 600605302a5SGregory Neil Shapiro if (m == -1) 601605302a5SGregory Neil Shapiro insertat = 0; 602d0cef73dSGregory Neil Shapiro else if (n >= (*top)->lrl_cnt) 603d0cef73dSGregory Neil Shapiro insertat = (*top)->lrl_cnt; 604605302a5SGregory Neil Shapiro else if (m < n) 605605302a5SGregory Neil Shapiro insertat = m + 1; 606605302a5SGregory Neil Shapiro } 607605302a5SGregory Neil Shapiro 608605302a5SGregory Neil Shapiro /* 609605302a5SGregory Neil Shapiro ** Not found in list, make room 610605302a5SGregory Neil Shapiro ** at insert point and add it. 611605302a5SGregory Neil Shapiro */ 612605302a5SGregory Neil Shapiro 613605302a5SGregory Neil Shapiro newe = sm_rpool_malloc_x(rpool, sizeof *newe); 614605302a5SGregory Neil Shapiro if (newe != NULL) 615605302a5SGregory Neil Shapiro { 616d0cef73dSGregory Neil Shapiro moveb = ((*top)->lrl_cnt - insertat) * sizeof *((*top)->lrl_data); 617605302a5SGregory Neil Shapiro if (moveb > 0) 618d0cef73dSGregory Neil Shapiro memmove(&((*top)->lrl_data[insertat + 1]), 619d0cef73dSGregory Neil Shapiro &((*top)->lrl_data[insertat]), 620605302a5SGregory Neil Shapiro moveb); 621605302a5SGregory Neil Shapiro 622605302a5SGregory Neil Shapiro newe->lr_search = sm_rpool_strdup_x(rpool, item); 623605302a5SGregory Neil Shapiro newe->lr_type = type; 624e92d3f3fSGregory Neil Shapiro newe->lr_ludp = NULL; 625e92d3f3fSGregory Neil Shapiro newe->lr_attrs = NULL; 626605302a5SGregory Neil Shapiro newe->lr_done = false; 627605302a5SGregory Neil Shapiro 628d0cef73dSGregory Neil Shapiro ((*top)->lrl_data)[insertat] = newe; 629d0cef73dSGregory Neil Shapiro (*top)->lrl_cnt++; 630605302a5SGregory Neil Shapiro } 631605302a5SGregory Neil Shapiro return newe; 63240266059SGregory Neil Shapiro } 63340266059SGregory Neil Shapiro 63440266059SGregory Neil Shapiro int 635605302a5SGregory Neil Shapiro sm_ldap_results(lmap, msgid, flags, delim, rpool, result, 636605302a5SGregory Neil Shapiro resultln, resultsz, recurse) 63740266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 63840266059SGregory Neil Shapiro int msgid; 63940266059SGregory Neil Shapiro int flags; 640605302a5SGregory Neil Shapiro int delim; 64140266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 64240266059SGregory Neil Shapiro char **result; 643605302a5SGregory Neil Shapiro int *resultln; 644605302a5SGregory Neil Shapiro int *resultsz; 64540266059SGregory Neil Shapiro SM_LDAP_RECURSE_LIST *recurse; 64640266059SGregory Neil Shapiro { 64740266059SGregory Neil Shapiro bool toplevel; 64840266059SGregory Neil Shapiro int i; 64940266059SGregory Neil Shapiro int statp; 65040266059SGregory Neil Shapiro int vsize; 65140266059SGregory Neil Shapiro int ret; 65240266059SGregory Neil Shapiro int save_errno; 65340266059SGregory Neil Shapiro char *p; 654605302a5SGregory Neil Shapiro SM_LDAP_RECURSE_ENTRY *rl; 65540266059SGregory Neil Shapiro 65640266059SGregory Neil Shapiro /* Are we the top top level of the search? */ 65740266059SGregory Neil Shapiro toplevel = (recurse == NULL); 65840266059SGregory Neil Shapiro 65940266059SGregory Neil Shapiro /* Get results */ 66040266059SGregory Neil Shapiro statp = EX_NOTFOUND; 66140266059SGregory Neil Shapiro while ((ret = ldap_result(lmap->ldap_ld, msgid, 0, 66240266059SGregory Neil Shapiro (lmap->ldap_timeout.tv_sec == 0 ? NULL : 66340266059SGregory Neil Shapiro &(lmap->ldap_timeout)), 66440266059SGregory Neil Shapiro &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) 66540266059SGregory Neil Shapiro { 66640266059SGregory Neil Shapiro LDAPMessage *entry; 66740266059SGregory Neil Shapiro 66840266059SGregory Neil Shapiro /* If we don't want multiple values and we have one, break */ 66913d88268SGregory Neil Shapiro if ((char) delim == '\0' && 67013d88268SGregory Neil Shapiro !bitset(SM_LDAP_SINGLEMATCH, flags) && 67113d88268SGregory Neil Shapiro *result != NULL) 67240266059SGregory Neil Shapiro break; 67340266059SGregory Neil Shapiro 67440266059SGregory Neil Shapiro /* Cycle through all entries */ 67540266059SGregory Neil Shapiro for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); 67640266059SGregory Neil Shapiro entry != NULL; 67740266059SGregory Neil Shapiro entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) 67840266059SGregory Neil Shapiro { 67940266059SGregory Neil Shapiro BerElement *ber; 68040266059SGregory Neil Shapiro char *attr; 68140266059SGregory Neil Shapiro char **vals = NULL; 68240266059SGregory Neil Shapiro char *dn; 68340266059SGregory Neil Shapiro 68440266059SGregory Neil Shapiro /* 68540266059SGregory Neil Shapiro ** If matching only and found an entry, 68640266059SGregory Neil Shapiro ** no need to spin through attributes 68740266059SGregory Neil Shapiro */ 68840266059SGregory Neil Shapiro 689323f6dcbSGregory Neil Shapiro if (bitset(SM_LDAP_MATCHONLY, flags)) 690323f6dcbSGregory Neil Shapiro { 691323f6dcbSGregory Neil Shapiro statp = EX_OK; 69240266059SGregory Neil Shapiro continue; 693323f6dcbSGregory Neil Shapiro } 69440266059SGregory Neil Shapiro 6954e4196cbSGregory Neil Shapiro #if _FFR_LDAP_SINGLEDN 6964e4196cbSGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEDN, flags) && *result != NULL) 6974e4196cbSGregory Neil Shapiro { 6984e4196cbSGregory Neil Shapiro /* only wanted one match */ 6994e4196cbSGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 7004e4196cbSGregory Neil Shapiro errno = ENOENT; 7014e4196cbSGregory Neil Shapiro return EX_NOTFOUND; 7024e4196cbSGregory Neil Shapiro } 7034e4196cbSGregory Neil Shapiro #endif /* _FFR_LDAP_SINGLEDN */ 7044e4196cbSGregory Neil Shapiro 70540266059SGregory Neil Shapiro /* record completed DN's to prevent loops */ 70640266059SGregory Neil Shapiro dn = ldap_get_dn(lmap->ldap_ld, entry); 70740266059SGregory Neil Shapiro if (dn == NULL) 70840266059SGregory Neil Shapiro { 70940266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 71040266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 711605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 71240266059SGregory Neil Shapiro errno = save_errno; 713a7ec597cSGregory Neil Shapiro return EX_TEMPFAIL; 71440266059SGregory Neil Shapiro } 71540266059SGregory Neil Shapiro 716605302a5SGregory Neil Shapiro rl = sm_ldap_add_recurse(&recurse, dn, 717605302a5SGregory Neil Shapiro SM_LDAP_ATTR_DN, 718605302a5SGregory Neil Shapiro rpool); 719605302a5SGregory Neil Shapiro 720605302a5SGregory Neil Shapiro if (rl == NULL) 72140266059SGregory Neil Shapiro { 72240266059SGregory Neil Shapiro ldap_memfree(dn); 723605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 72440266059SGregory Neil Shapiro errno = ENOMEM; 72540266059SGregory Neil Shapiro return EX_OSERR; 726605302a5SGregory Neil Shapiro } 727605302a5SGregory Neil Shapiro else if (rl->lr_done) 728605302a5SGregory Neil Shapiro { 72940266059SGregory Neil Shapiro /* already on list, skip it */ 73040266059SGregory Neil Shapiro ldap_memfree(dn); 73140266059SGregory Neil Shapiro continue; 73240266059SGregory Neil Shapiro } 73340266059SGregory Neil Shapiro ldap_memfree(dn); 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 for (attr = ldap_first_attribute(lmap->ldap_ld, entry, 74640266059SGregory Neil Shapiro &ber); 74740266059SGregory Neil Shapiro attr != NULL; 74840266059SGregory Neil Shapiro attr = ldap_next_attribute(lmap->ldap_ld, entry, 74940266059SGregory Neil Shapiro ber)) 75040266059SGregory Neil Shapiro { 75140266059SGregory Neil Shapiro char *tmp, *vp_tmp; 75240266059SGregory Neil Shapiro int type; 753605302a5SGregory Neil Shapiro char *needobjclass = NULL; 75440266059SGregory Neil Shapiro 755605302a5SGregory Neil Shapiro type = SM_LDAP_ATTR_NONE; 75640266059SGregory Neil Shapiro for (i = 0; lmap->ldap_attr[i] != NULL; i++) 75740266059SGregory Neil Shapiro { 75840266059SGregory Neil Shapiro if (sm_strcasecmp(lmap->ldap_attr[i], 75940266059SGregory Neil Shapiro attr) == 0) 76040266059SGregory Neil Shapiro { 76140266059SGregory Neil Shapiro type = lmap->ldap_attr_type[i]; 762605302a5SGregory Neil Shapiro needobjclass = lmap->ldap_attr_needobjclass[i]; 76340266059SGregory Neil Shapiro break; 76440266059SGregory Neil Shapiro } 76540266059SGregory Neil Shapiro } 766605302a5SGregory Neil Shapiro 767605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_USE_ALLATTR, flags) && 768605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_NONE) 769605302a5SGregory Neil Shapiro { 770605302a5SGregory Neil Shapiro /* URL lookups specify attrs to use */ 771605302a5SGregory Neil Shapiro type = SM_LDAP_ATTR_NORMAL; 772605302a5SGregory Neil Shapiro needobjclass = NULL; 773605302a5SGregory Neil Shapiro } 774605302a5SGregory Neil Shapiro 775605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NONE) 77640266059SGregory Neil Shapiro { 77740266059SGregory Neil Shapiro /* attribute not requested */ 77840266059SGregory Neil Shapiro ldap_memfree(attr); 779605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 78040266059SGregory Neil Shapiro errno = EFAULT; 78140266059SGregory Neil Shapiro return EX_SOFTWARE; 78240266059SGregory Neil Shapiro } 78340266059SGregory Neil Shapiro 784605302a5SGregory Neil Shapiro /* 785605302a5SGregory Neil Shapiro ** For recursion on a particular attribute, 786605302a5SGregory Neil Shapiro ** we may need to see if this entry is 787605302a5SGregory Neil Shapiro ** part of a particular objectclass. 788605302a5SGregory Neil Shapiro ** Also, ignore objectClass attribute. 789605302a5SGregory Neil Shapiro ** Otherwise we just ignore this attribute. 790605302a5SGregory Neil Shapiro */ 791605302a5SGregory Neil Shapiro 792605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_OBJCLASS || 793605302a5SGregory Neil Shapiro (needobjclass != NULL && 794605302a5SGregory Neil Shapiro !sm_ldap_has_objectclass(lmap, entry, 795605302a5SGregory Neil Shapiro needobjclass))) 796605302a5SGregory Neil Shapiro { 797605302a5SGregory Neil Shapiro ldap_memfree(attr); 798605302a5SGregory Neil Shapiro continue; 799605302a5SGregory Neil Shapiro } 800605302a5SGregory Neil Shapiro 80140266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 80240266059SGregory Neil Shapiro { 80340266059SGregory Neil Shapiro vals = ldap_get_values(lmap->ldap_ld, 80440266059SGregory Neil Shapiro entry, 80540266059SGregory Neil Shapiro attr); 80640266059SGregory Neil Shapiro if (vals == NULL) 80740266059SGregory Neil Shapiro { 80840266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 80940266059SGregory Neil Shapiro if (save_errno == LDAP_SUCCESS) 81040266059SGregory Neil Shapiro { 81140266059SGregory Neil Shapiro ldap_memfree(attr); 81240266059SGregory Neil Shapiro continue; 81340266059SGregory Neil Shapiro } 81440266059SGregory Neil Shapiro 81540266059SGregory Neil Shapiro /* Must be an error */ 81640266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 81740266059SGregory Neil Shapiro ldap_memfree(attr); 818605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 81940266059SGregory Neil Shapiro errno = save_errno; 82040266059SGregory Neil Shapiro return EX_TEMPFAIL; 82140266059SGregory Neil Shapiro } 82240266059SGregory Neil Shapiro } 82340266059SGregory Neil Shapiro 82440266059SGregory Neil Shapiro statp = EX_OK; 82540266059SGregory Neil Shapiro 82640266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 82740266059SGregory Neil Shapiro /* 82840266059SGregory Neil Shapiro ** Reset value to prevent lingering 82940266059SGregory Neil Shapiro ** LDAP_DECODING_ERROR due to 83040266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see below) 83140266059SGregory Neil Shapiro */ 83240266059SGregory Neil Shapiro 83340266059SGregory Neil Shapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 83440266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 83540266059SGregory Neil Shapiro 83640266059SGregory Neil Shapiro /* 83740266059SGregory Neil Shapiro ** If matching only, 83840266059SGregory Neil Shapiro ** no need to spin through entries 83940266059SGregory Neil Shapiro */ 84040266059SGregory Neil Shapiro 84140266059SGregory Neil Shapiro if (bitset(SM_LDAP_MATCHONLY, flags)) 84240266059SGregory Neil Shapiro { 84340266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 84440266059SGregory Neil Shapiro ldap_value_free(vals); 84540266059SGregory Neil Shapiro ldap_memfree(attr); 84640266059SGregory Neil Shapiro continue; 84740266059SGregory Neil Shapiro } 84840266059SGregory Neil Shapiro 84940266059SGregory Neil Shapiro /* 85040266059SGregory Neil Shapiro ** If we don't want multiple values, 85140266059SGregory Neil Shapiro ** return first found. 85240266059SGregory Neil Shapiro */ 85340266059SGregory Neil Shapiro 854605302a5SGregory Neil Shapiro if ((char) delim == '\0') 85540266059SGregory Neil Shapiro { 856605302a5SGregory Neil Shapiro if (*result != NULL) 857605302a5SGregory Neil Shapiro { 858605302a5SGregory Neil Shapiro /* already have a value */ 859605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEMATCH, 86013d88268SGregory Neil Shapiro flags)) 861605302a5SGregory Neil Shapiro { 862605302a5SGregory Neil Shapiro /* only wanted one match */ 863605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 864605302a5SGregory Neil Shapiro errno = ENOENT; 865605302a5SGregory Neil Shapiro return EX_NOTFOUND; 866605302a5SGregory Neil Shapiro } 86713d88268SGregory Neil Shapiro break; 86813d88268SGregory Neil Shapiro } 869605302a5SGregory Neil Shapiro 87040266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 87140266059SGregory Neil Shapiro { 87240266059SGregory Neil Shapiro *result = sm_rpool_strdup_x(rpool, 87340266059SGregory Neil Shapiro attr); 87440266059SGregory Neil Shapiro ldap_memfree(attr); 87540266059SGregory Neil Shapiro break; 87640266059SGregory Neil Shapiro } 87740266059SGregory Neil Shapiro 87840266059SGregory Neil Shapiro if (vals[0] == NULL) 87940266059SGregory Neil Shapiro { 88040266059SGregory Neil Shapiro ldap_value_free(vals); 88140266059SGregory Neil Shapiro ldap_memfree(attr); 88240266059SGregory Neil Shapiro continue; 88340266059SGregory Neil Shapiro } 88440266059SGregory Neil Shapiro 88540266059SGregory Neil Shapiro vsize = strlen(vals[0]) + 1; 88640266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 88740266059SGregory Neil Shapiro vsize += strlen(attr) + 1; 88840266059SGregory Neil Shapiro *result = sm_rpool_malloc_x(rpool, 88940266059SGregory Neil Shapiro vsize); 89040266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 89140266059SGregory Neil Shapiro sm_snprintf(*result, vsize, 89240266059SGregory Neil Shapiro "%s%c%s", 89340266059SGregory Neil Shapiro attr, 89440266059SGregory Neil Shapiro lmap->ldap_attrsep, 89540266059SGregory Neil Shapiro vals[0]); 89640266059SGregory Neil Shapiro else 89740266059SGregory Neil Shapiro sm_strlcpy(*result, vals[0], 89840266059SGregory Neil Shapiro vsize); 89940266059SGregory Neil Shapiro ldap_value_free(vals); 90040266059SGregory Neil Shapiro ldap_memfree(attr); 90140266059SGregory Neil Shapiro break; 90240266059SGregory Neil Shapiro } 90340266059SGregory Neil Shapiro 90440266059SGregory Neil Shapiro /* attributes only */ 90540266059SGregory Neil Shapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 90640266059SGregory Neil Shapiro { 90740266059SGregory Neil Shapiro if (*result == NULL) 90840266059SGregory Neil Shapiro *result = sm_rpool_strdup_x(rpool, 90940266059SGregory Neil Shapiro attr); 91040266059SGregory Neil Shapiro else 91140266059SGregory Neil Shapiro { 912605302a5SGregory Neil Shapiro if (bitset(SM_LDAP_SINGLEMATCH, 913605302a5SGregory Neil Shapiro flags) && 914605302a5SGregory Neil Shapiro *result != NULL) 915605302a5SGregory Neil Shapiro { 916605302a5SGregory Neil Shapiro /* only wanted one match */ 917605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 918605302a5SGregory Neil Shapiro errno = ENOENT; 919605302a5SGregory Neil Shapiro return EX_NOTFOUND; 920605302a5SGregory Neil Shapiro } 921605302a5SGregory Neil Shapiro 92240266059SGregory Neil Shapiro vsize = strlen(*result) + 92340266059SGregory Neil Shapiro strlen(attr) + 2; 92440266059SGregory Neil Shapiro tmp = sm_rpool_malloc_x(rpool, 92540266059SGregory Neil Shapiro vsize); 92640266059SGregory Neil Shapiro (void) sm_snprintf(tmp, 92740266059SGregory Neil Shapiro vsize, "%s%c%s", 928605302a5SGregory Neil Shapiro *result, (char) delim, 92940266059SGregory Neil Shapiro attr); 93040266059SGregory Neil Shapiro *result = tmp; 93140266059SGregory Neil Shapiro } 93240266059SGregory Neil Shapiro ldap_memfree(attr); 93340266059SGregory Neil Shapiro continue; 93440266059SGregory Neil Shapiro } 93540266059SGregory Neil Shapiro 93640266059SGregory Neil Shapiro /* 937605302a5SGregory Neil Shapiro ** If there is more than one, munge then 938605302a5SGregory Neil Shapiro ** into a map_coldelim separated string. 939605302a5SGregory Neil Shapiro ** If we are recursing we may have an entry 940605302a5SGregory Neil Shapiro ** with no 'normal' values to put in the 941605302a5SGregory Neil Shapiro ** string. 942605302a5SGregory Neil Shapiro ** This is not an error. 94340266059SGregory Neil Shapiro */ 94440266059SGregory Neil Shapiro 945605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NORMAL && 946605302a5SGregory Neil Shapiro bitset(SM_LDAP_SINGLEMATCH, flags) && 947605302a5SGregory Neil Shapiro *result != NULL) 948605302a5SGregory Neil Shapiro { 949605302a5SGregory Neil Shapiro /* only wanted one match */ 950605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 951605302a5SGregory Neil Shapiro errno = ENOENT; 952605302a5SGregory Neil Shapiro return EX_NOTFOUND; 953605302a5SGregory Neil Shapiro } 954605302a5SGregory Neil Shapiro 95540266059SGregory Neil Shapiro vsize = 0; 95640266059SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 95740266059SGregory Neil Shapiro { 958605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_DN || 959605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_FILTER || 960605302a5SGregory Neil Shapiro type == SM_LDAP_ATTR_URL) 96140266059SGregory Neil Shapiro { 962605302a5SGregory Neil Shapiro /* add to recursion */ 963605302a5SGregory Neil Shapiro if (sm_ldap_add_recurse(&recurse, 96440266059SGregory Neil Shapiro vals[i], 965605302a5SGregory Neil Shapiro type, 966605302a5SGregory Neil Shapiro rpool) == NULL) 96740266059SGregory Neil Shapiro { 968605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 96940266059SGregory Neil Shapiro errno = ENOMEM; 97040266059SGregory Neil Shapiro return EX_OSERR; 97140266059SGregory Neil Shapiro } 97240266059SGregory Neil Shapiro continue; 97340266059SGregory Neil Shapiro } 974605302a5SGregory Neil Shapiro 97540266059SGregory Neil Shapiro vsize += strlen(vals[i]) + 1; 97640266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 97740266059SGregory Neil Shapiro vsize += strlen(attr) + 1; 97840266059SGregory Neil Shapiro } 979605302a5SGregory Neil Shapiro 980605302a5SGregory Neil Shapiro /* 981605302a5SGregory Neil Shapiro ** Create/Append to string any normal 982605302a5SGregory Neil Shapiro ** attribute values. Otherwise, just free 983605302a5SGregory Neil Shapiro ** memory and move on to the next 984605302a5SGregory Neil Shapiro ** attribute in this entry. 985605302a5SGregory Neil Shapiro */ 986605302a5SGregory Neil Shapiro 987605302a5SGregory Neil Shapiro if (type == SM_LDAP_ATTR_NORMAL && vsize > 0) 988605302a5SGregory Neil Shapiro { 989605302a5SGregory Neil Shapiro char *pe; 990605302a5SGregory Neil Shapiro 991605302a5SGregory Neil Shapiro /* Grow result string if needed */ 992605302a5SGregory Neil Shapiro if ((*resultln + vsize) >= *resultsz) 993605302a5SGregory Neil Shapiro { 994605302a5SGregory Neil Shapiro while ((*resultln + vsize) >= *resultsz) 995605302a5SGregory Neil Shapiro { 996605302a5SGregory Neil Shapiro if (*resultsz == 0) 997605302a5SGregory Neil Shapiro *resultsz = 1024; 998605302a5SGregory Neil Shapiro else 999605302a5SGregory Neil Shapiro *resultsz *= 2; 1000605302a5SGregory Neil Shapiro } 1001605302a5SGregory Neil Shapiro 1002605302a5SGregory Neil Shapiro vp_tmp = sm_rpool_malloc_x(rpool, *resultsz); 100340266059SGregory Neil Shapiro *vp_tmp = '\0'; 100440266059SGregory Neil Shapiro 1005605302a5SGregory Neil Shapiro if (*result != NULL) 1006605302a5SGregory Neil Shapiro sm_strlcpy(vp_tmp, 1007605302a5SGregory Neil Shapiro *result, 1008605302a5SGregory Neil Shapiro *resultsz); 1009605302a5SGregory Neil Shapiro *result = vp_tmp; 1010605302a5SGregory Neil Shapiro } 1011605302a5SGregory Neil Shapiro 1012605302a5SGregory Neil Shapiro p = *result + *resultln; 1013605302a5SGregory Neil Shapiro pe = *result + *resultsz; 1014605302a5SGregory Neil Shapiro 101540266059SGregory Neil Shapiro for (i = 0; vals[i] != NULL; i++) 101640266059SGregory Neil Shapiro { 1017959366dcSGregory Neil Shapiro if (*resultln > 0 && 1018959366dcSGregory Neil Shapiro p < pe) 1019605302a5SGregory Neil Shapiro *p++ = (char) delim; 1020605302a5SGregory Neil Shapiro 102140266059SGregory Neil Shapiro if (lmap->ldap_attrsep != '\0') 102240266059SGregory Neil Shapiro { 102340266059SGregory Neil Shapiro p += sm_strlcpy(p, attr, 1024605302a5SGregory Neil Shapiro pe - p); 1025605302a5SGregory Neil Shapiro if (p < pe) 102640266059SGregory Neil Shapiro *p++ = lmap->ldap_attrsep; 102740266059SGregory Neil Shapiro } 1028605302a5SGregory Neil Shapiro 102940266059SGregory Neil Shapiro p += sm_strlcpy(p, vals[i], 1030605302a5SGregory Neil Shapiro pe - p); 1031605302a5SGregory Neil Shapiro *resultln = p - (*result); 1032605302a5SGregory Neil Shapiro if (p >= pe) 103340266059SGregory Neil Shapiro { 103440266059SGregory Neil Shapiro /* Internal error: buffer too small for LDAP values */ 1035605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 103640266059SGregory Neil Shapiro errno = ENOMEM; 103740266059SGregory Neil Shapiro return EX_OSERR; 103840266059SGregory Neil Shapiro } 1039605302a5SGregory Neil Shapiro } 104040266059SGregory Neil Shapiro } 104140266059SGregory Neil Shapiro 104240266059SGregory Neil Shapiro ldap_value_free(vals); 104340266059SGregory Neil Shapiro ldap_memfree(attr); 104440266059SGregory Neil Shapiro } 104540266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 104640266059SGregory Neil Shapiro 104740266059SGregory Neil Shapiro /* 104840266059SGregory Neil Shapiro ** We check save_errno != LDAP_DECODING_ERROR since 104940266059SGregory Neil Shapiro ** OpenLDAP 1.X has a very ugly *undocumented* 105040266059SGregory Neil Shapiro ** hack of returning this error code from 105140266059SGregory Neil Shapiro ** ldap_next_attribute() if the library freed the 105240266059SGregory Neil Shapiro ** ber attribute. See: 105340266059SGregory Neil Shapiro ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 105440266059SGregory Neil Shapiro */ 105540266059SGregory Neil Shapiro 105640266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS && 105740266059SGregory Neil Shapiro save_errno != LDAP_DECODING_ERROR) 105840266059SGregory Neil Shapiro { 105940266059SGregory Neil Shapiro /* Must be an error */ 106040266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 1061605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 106240266059SGregory Neil Shapiro errno = save_errno; 106340266059SGregory Neil Shapiro return EX_TEMPFAIL; 106440266059SGregory Neil Shapiro } 106540266059SGregory Neil Shapiro 1066605302a5SGregory Neil Shapiro /* mark this DN as done */ 1067605302a5SGregory Neil Shapiro rl->lr_done = true; 1068e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp != NULL) 1069e92d3f3fSGregory Neil Shapiro { 1070e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1071e92d3f3fSGregory Neil Shapiro rl->lr_ludp = NULL; 1072e92d3f3fSGregory Neil Shapiro } 1073e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs != NULL) 1074e92d3f3fSGregory Neil Shapiro { 1075e92d3f3fSGregory Neil Shapiro free(rl->lr_attrs); 1076e92d3f3fSGregory Neil Shapiro rl->lr_attrs = NULL; 1077e92d3f3fSGregory Neil Shapiro } 1078605302a5SGregory Neil Shapiro 107940266059SGregory Neil Shapiro /* We don't want multiple values and we have one */ 108013d88268SGregory Neil Shapiro if ((char) delim == '\0' && 108113d88268SGregory Neil Shapiro !bitset(SM_LDAP_SINGLEMATCH, flags) && 108213d88268SGregory Neil Shapiro *result != NULL) 108340266059SGregory Neil Shapiro break; 108440266059SGregory Neil Shapiro } 108540266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 108640266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS && 108740266059SGregory Neil Shapiro save_errno != LDAP_DECODING_ERROR) 108840266059SGregory Neil Shapiro { 108940266059SGregory Neil Shapiro /* Must be an error */ 109040266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 1091605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 109240266059SGregory Neil Shapiro errno = save_errno; 109340266059SGregory Neil Shapiro return EX_TEMPFAIL; 109440266059SGregory Neil Shapiro } 109540266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); 109640266059SGregory Neil Shapiro lmap->ldap_res = NULL; 109740266059SGregory Neil Shapiro } 109840266059SGregory Neil Shapiro 109940266059SGregory Neil Shapiro if (ret == 0) 110040266059SGregory Neil Shapiro save_errno = ETIMEDOUT; 110140266059SGregory Neil Shapiro else 110240266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 110340266059SGregory Neil Shapiro if (save_errno != LDAP_SUCCESS) 110440266059SGregory Neil Shapiro { 110540266059SGregory Neil Shapiro statp = EX_TEMPFAIL; 110640266059SGregory Neil Shapiro switch (save_errno) 110740266059SGregory Neil Shapiro { 110840266059SGregory Neil Shapiro #ifdef LDAP_SERVER_DOWN 110940266059SGregory Neil Shapiro case LDAP_SERVER_DOWN: 111040266059SGregory Neil Shapiro #endif /* LDAP_SERVER_DOWN */ 111140266059SGregory Neil Shapiro case LDAP_TIMEOUT: 1112ffb83623SGregory Neil Shapiro case ETIMEDOUT: 111340266059SGregory Neil Shapiro case LDAP_UNAVAILABLE: 1114605302a5SGregory Neil Shapiro 1115605302a5SGregory Neil Shapiro /* 1116605302a5SGregory Neil Shapiro ** server disappeared, 1117605302a5SGregory Neil Shapiro ** try reopen on next search 1118605302a5SGregory Neil Shapiro */ 1119605302a5SGregory Neil Shapiro 112040266059SGregory Neil Shapiro statp = EX_RESTART; 112140266059SGregory Neil Shapiro break; 112240266059SGregory Neil Shapiro } 1123ffb83623SGregory Neil Shapiro if (ret != 0) 112440266059SGregory Neil Shapiro save_errno += E_LDAPBASE; 1125605302a5SGregory Neil Shapiro SM_LDAP_ERROR_CLEANUP(); 112640266059SGregory Neil Shapiro errno = save_errno; 112740266059SGregory Neil Shapiro return statp; 112840266059SGregory Neil Shapiro } 112940266059SGregory Neil Shapiro 113040266059SGregory Neil Shapiro if (lmap->ldap_res != NULL) 113140266059SGregory Neil Shapiro { 113240266059SGregory Neil Shapiro ldap_msgfree(lmap->ldap_res); 113340266059SGregory Neil Shapiro lmap->ldap_res = NULL; 113440266059SGregory Neil Shapiro } 113540266059SGregory Neil Shapiro 113640266059SGregory Neil Shapiro if (toplevel) 113740266059SGregory Neil Shapiro { 1138605302a5SGregory Neil Shapiro int rlidx; 113940266059SGregory Neil Shapiro 114040266059SGregory Neil Shapiro /* 114140266059SGregory Neil Shapiro ** Spin through the built-up recurse list at the top 114240266059SGregory Neil Shapiro ** of the recursion. Since new items are added at the 114340266059SGregory Neil Shapiro ** end of the shared list, we actually only ever get 114440266059SGregory Neil Shapiro ** one level of recursion before things pop back to the 114540266059SGregory Neil Shapiro ** top. Any items added to the list during that recursion 114640266059SGregory Neil Shapiro ** will be expanded by the top level. 114740266059SGregory Neil Shapiro */ 114840266059SGregory Neil Shapiro 1149d0cef73dSGregory Neil Shapiro for (rlidx = 0; recurse != NULL && rlidx < recurse->lrl_cnt; 1150d0cef73dSGregory Neil Shapiro rlidx++) 115140266059SGregory Neil Shapiro { 1152605302a5SGregory Neil Shapiro int newflags; 115340266059SGregory Neil Shapiro int sid; 115440266059SGregory Neil Shapiro int status; 115540266059SGregory Neil Shapiro 1156d0cef73dSGregory Neil Shapiro rl = recurse->lrl_data[rlidx]; 1157605302a5SGregory Neil Shapiro 1158605302a5SGregory Neil Shapiro newflags = flags; 1159605302a5SGregory Neil Shapiro if (rl->lr_done) 116040266059SGregory Neil Shapiro { 116140266059SGregory Neil Shapiro /* already expanded */ 116240266059SGregory Neil Shapiro continue; 116340266059SGregory Neil Shapiro } 1164605302a5SGregory Neil Shapiro 1165605302a5SGregory Neil Shapiro if (rl->lr_type == SM_LDAP_ATTR_DN) 116640266059SGregory Neil Shapiro { 116740266059SGregory Neil Shapiro /* do DN search */ 116840266059SGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 116940266059SGregory Neil Shapiro rl->lr_search, 117040266059SGregory Neil Shapiro lmap->ldap_scope, 117140266059SGregory Neil Shapiro "(objectClass=*)", 1172605302a5SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? 1173605302a5SGregory Neil Shapiro NULL : lmap->ldap_attr), 117440266059SGregory Neil Shapiro lmap->ldap_attrsonly); 117540266059SGregory Neil Shapiro } 1176605302a5SGregory Neil Shapiro else if (rl->lr_type == SM_LDAP_ATTR_FILTER) 117740266059SGregory Neil Shapiro { 117840266059SGregory Neil Shapiro /* do new search */ 117940266059SGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 118040266059SGregory Neil Shapiro lmap->ldap_base, 118140266059SGregory Neil Shapiro lmap->ldap_scope, 118240266059SGregory Neil Shapiro rl->lr_search, 1183605302a5SGregory Neil Shapiro (lmap->ldap_attr[0] == NULL ? 1184605302a5SGregory Neil Shapiro NULL : lmap->ldap_attr), 118540266059SGregory Neil Shapiro lmap->ldap_attrsonly); 118640266059SGregory Neil Shapiro } 1187605302a5SGregory Neil Shapiro else if (rl->lr_type == SM_LDAP_ATTR_URL) 118840266059SGregory Neil Shapiro { 1189e92d3f3fSGregory Neil Shapiro /* Parse URL */ 1190e92d3f3fSGregory Neil Shapiro sid = ldap_url_parse(rl->lr_search, 1191e92d3f3fSGregory Neil Shapiro &rl->lr_ludp); 1192e92d3f3fSGregory Neil Shapiro 1193e92d3f3fSGregory Neil Shapiro if (sid != 0) 1194e92d3f3fSGregory Neil Shapiro { 1195e92d3f3fSGregory Neil Shapiro errno = sid + E_LDAPURLBASE; 1196e92d3f3fSGregory Neil Shapiro return EX_TEMPFAIL; 1197e92d3f3fSGregory Neil Shapiro } 1198e92d3f3fSGregory Neil Shapiro 1199e92d3f3fSGregory Neil Shapiro /* We need to add objectClass */ 1200e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp->lud_attrs != NULL) 1201e92d3f3fSGregory Neil Shapiro { 1202e92d3f3fSGregory Neil Shapiro int attrnum = 0; 1203e92d3f3fSGregory Neil Shapiro 1204e92d3f3fSGregory Neil Shapiro while (rl->lr_ludp->lud_attrs[attrnum] != NULL) 1205e92d3f3fSGregory Neil Shapiro { 1206e92d3f3fSGregory Neil Shapiro if (strcasecmp(rl->lr_ludp->lud_attrs[attrnum], 1207e92d3f3fSGregory Neil Shapiro "objectClass") == 0) 1208e92d3f3fSGregory Neil Shapiro { 1209e92d3f3fSGregory Neil Shapiro /* already requested */ 1210e92d3f3fSGregory Neil Shapiro attrnum = -1; 1211e92d3f3fSGregory Neil Shapiro break; 1212e92d3f3fSGregory Neil Shapiro } 1213e92d3f3fSGregory Neil Shapiro attrnum++; 1214e92d3f3fSGregory Neil Shapiro } 1215e92d3f3fSGregory Neil Shapiro 1216e92d3f3fSGregory Neil Shapiro if (attrnum >= 0) 1217e92d3f3fSGregory Neil Shapiro { 1218e92d3f3fSGregory Neil Shapiro int i; 1219e92d3f3fSGregory Neil Shapiro 1220e92d3f3fSGregory Neil Shapiro rl->lr_attrs = (char **)malloc(sizeof(char *) * (attrnum + 2)); 1221e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs == NULL) 1222e92d3f3fSGregory Neil Shapiro { 1223e92d3f3fSGregory Neil Shapiro save_errno = errno; 1224e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1225e92d3f3fSGregory Neil Shapiro errno = save_errno; 1226e92d3f3fSGregory Neil Shapiro return EX_TEMPFAIL; 1227e92d3f3fSGregory Neil Shapiro } 1228e92d3f3fSGregory Neil Shapiro for (i = 0 ; i < attrnum; i++) 1229e92d3f3fSGregory Neil Shapiro { 1230e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i] = rl->lr_ludp->lud_attrs[i]; 1231e92d3f3fSGregory Neil Shapiro } 1232e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i++] = "objectClass"; 1233e92d3f3fSGregory Neil Shapiro rl->lr_attrs[i++] = NULL; 1234e92d3f3fSGregory Neil Shapiro } 1235e92d3f3fSGregory Neil Shapiro } 1236e92d3f3fSGregory Neil Shapiro 1237e92d3f3fSGregory Neil Shapiro /* 1238e92d3f3fSGregory Neil Shapiro ** Use the existing connection 1239e92d3f3fSGregory Neil Shapiro ** for this search. It really 1240e92d3f3fSGregory Neil Shapiro ** should use lud_scheme://lud_host:lud_port/ 1241e92d3f3fSGregory Neil Shapiro ** instead but that would require 1242e92d3f3fSGregory Neil Shapiro ** opening a new connection. 1243e92d3f3fSGregory Neil Shapiro ** This should be fixed ASAP. 1244e92d3f3fSGregory Neil Shapiro */ 1245e92d3f3fSGregory Neil Shapiro 1246e92d3f3fSGregory Neil Shapiro sid = ldap_search(lmap->ldap_ld, 1247e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_dn, 1248e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_scope, 1249e92d3f3fSGregory Neil Shapiro rl->lr_ludp->lud_filter, 1250e92d3f3fSGregory Neil Shapiro rl->lr_attrs, 125140266059SGregory Neil Shapiro lmap->ldap_attrsonly); 1252e92d3f3fSGregory Neil Shapiro 1253e92d3f3fSGregory Neil Shapiro /* Use the attributes specified by URL */ 1254605302a5SGregory Neil Shapiro newflags |= SM_LDAP_USE_ALLATTR; 125540266059SGregory Neil Shapiro } 125640266059SGregory Neil Shapiro else 125740266059SGregory Neil Shapiro { 125840266059SGregory Neil Shapiro /* unknown or illegal attribute type */ 125940266059SGregory Neil Shapiro errno = EFAULT; 126040266059SGregory Neil Shapiro return EX_SOFTWARE; 126140266059SGregory Neil Shapiro } 126240266059SGregory Neil Shapiro 126340266059SGregory Neil Shapiro /* Collect results */ 126440266059SGregory Neil Shapiro if (sid == -1) 126540266059SGregory Neil Shapiro { 126640266059SGregory Neil Shapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 126740266059SGregory Neil Shapiro statp = EX_TEMPFAIL; 126840266059SGregory Neil Shapiro switch (save_errno) 126940266059SGregory Neil Shapiro { 127040266059SGregory Neil Shapiro #ifdef LDAP_SERVER_DOWN 127140266059SGregory Neil Shapiro case LDAP_SERVER_DOWN: 127240266059SGregory Neil Shapiro #endif /* LDAP_SERVER_DOWN */ 127340266059SGregory Neil Shapiro case LDAP_TIMEOUT: 1274ffb83623SGregory Neil Shapiro case ETIMEDOUT: 127540266059SGregory Neil Shapiro case LDAP_UNAVAILABLE: 1276605302a5SGregory Neil Shapiro 1277605302a5SGregory Neil Shapiro /* 1278605302a5SGregory Neil Shapiro ** server disappeared, 1279605302a5SGregory Neil Shapiro ** try reopen on next search 1280605302a5SGregory Neil Shapiro */ 1281605302a5SGregory Neil Shapiro 128240266059SGregory Neil Shapiro statp = EX_RESTART; 128340266059SGregory Neil Shapiro break; 128440266059SGregory Neil Shapiro } 128540266059SGregory Neil Shapiro errno = save_errno + E_LDAPBASE; 128640266059SGregory Neil Shapiro return statp; 128740266059SGregory Neil Shapiro } 128840266059SGregory Neil Shapiro 1289605302a5SGregory Neil Shapiro status = sm_ldap_results(lmap, sid, newflags, delim, 1290605302a5SGregory Neil Shapiro rpool, result, resultln, 1291605302a5SGregory Neil Shapiro resultsz, recurse); 129240266059SGregory Neil Shapiro save_errno = errno; 129340266059SGregory Neil Shapiro if (status != EX_OK && status != EX_NOTFOUND) 129440266059SGregory Neil Shapiro { 129540266059SGregory Neil Shapiro errno = save_errno; 129640266059SGregory Neil Shapiro return status; 129740266059SGregory Neil Shapiro } 129840266059SGregory Neil Shapiro 129940266059SGregory Neil Shapiro /* Mark as done */ 1300605302a5SGregory Neil Shapiro rl->lr_done = true; 1301e92d3f3fSGregory Neil Shapiro if (rl->lr_ludp != NULL) 1302e92d3f3fSGregory Neil Shapiro { 1303e92d3f3fSGregory Neil Shapiro ldap_free_urldesc(rl->lr_ludp); 1304e92d3f3fSGregory Neil Shapiro rl->lr_ludp = NULL; 1305e92d3f3fSGregory Neil Shapiro } 1306e92d3f3fSGregory Neil Shapiro if (rl->lr_attrs != NULL) 1307e92d3f3fSGregory Neil Shapiro { 1308e92d3f3fSGregory Neil Shapiro free(rl->lr_attrs); 1309e92d3f3fSGregory Neil Shapiro rl->lr_attrs = NULL; 1310e92d3f3fSGregory Neil Shapiro } 1311605302a5SGregory Neil Shapiro 1312605302a5SGregory Neil Shapiro /* Reset rlidx as new items may have been added */ 1313605302a5SGregory Neil Shapiro rlidx = -1; 131440266059SGregory Neil Shapiro } 131540266059SGregory Neil Shapiro } 131640266059SGregory Neil Shapiro return statp; 131740266059SGregory Neil Shapiro } 131840266059SGregory Neil Shapiro 131940266059SGregory Neil Shapiro /* 132040266059SGregory Neil Shapiro ** SM_LDAP_CLOSE -- close LDAP connection 132140266059SGregory Neil Shapiro ** 132240266059SGregory Neil Shapiro ** Parameters: 132340266059SGregory Neil Shapiro ** lmap -- LDAP map information 132440266059SGregory Neil Shapiro ** 132540266059SGregory Neil Shapiro ** Returns: 132640266059SGregory Neil Shapiro ** None. 132740266059SGregory Neil Shapiro ** 132840266059SGregory Neil Shapiro */ 132940266059SGregory Neil Shapiro 133040266059SGregory Neil Shapiro void 133140266059SGregory Neil Shapiro sm_ldap_close(lmap) 133240266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 133340266059SGregory Neil Shapiro { 133440266059SGregory Neil Shapiro if (lmap->ldap_ld == NULL) 133540266059SGregory Neil Shapiro return; 133640266059SGregory Neil Shapiro 133740266059SGregory Neil Shapiro if (lmap->ldap_pid == getpid()) 133840266059SGregory Neil Shapiro ldap_unbind(lmap->ldap_ld); 133940266059SGregory Neil Shapiro lmap->ldap_ld = NULL; 134040266059SGregory Neil Shapiro lmap->ldap_pid = 0; 134140266059SGregory Neil Shapiro } 134240266059SGregory Neil Shapiro 134340266059SGregory Neil Shapiro /* 134440266059SGregory Neil Shapiro ** SM_LDAP_SETOPTS -- set LDAP options 134540266059SGregory Neil Shapiro ** 134640266059SGregory Neil Shapiro ** Parameters: 134740266059SGregory Neil Shapiro ** ld -- LDAP session handle 134840266059SGregory Neil Shapiro ** lmap -- LDAP map information 134940266059SGregory Neil Shapiro ** 135040266059SGregory Neil Shapiro ** Returns: 135140266059SGregory Neil Shapiro ** None. 135240266059SGregory Neil Shapiro ** 135340266059SGregory Neil Shapiro */ 135440266059SGregory Neil Shapiro 135540266059SGregory Neil Shapiro void 135640266059SGregory Neil Shapiro sm_ldap_setopts(ld, lmap) 135740266059SGregory Neil Shapiro LDAP *ld; 135840266059SGregory Neil Shapiro SM_LDAP_STRUCT *lmap; 135940266059SGregory Neil Shapiro { 136040266059SGregory Neil Shapiro # if USE_LDAP_SET_OPTION 1361605302a5SGregory Neil Shapiro if (lmap->ldap_version != 0) 1362605302a5SGregory Neil Shapiro { 1363605302a5SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, 1364605302a5SGregory Neil Shapiro &lmap->ldap_version); 1365605302a5SGregory Neil Shapiro } 136640266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); 136740266059SGregory Neil Shapiro if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) 136840266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); 136940266059SGregory Neil Shapiro else 137040266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 137140266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); 137240266059SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); 1373ffb83623SGregory Neil Shapiro # if _FFR_LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) 1374ffb83623SGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &lmap->ldap_networktmo); 1375ffb83623SGregory Neil Shapiro # endif /* _FFR_LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) */ 1376959366dcSGregory Neil Shapiro # ifdef LDAP_OPT_RESTART 1377959366dcSGregory Neil Shapiro ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); 1378959366dcSGregory Neil Shapiro # endif /* LDAP_OPT_RESTART */ 137940266059SGregory Neil Shapiro # else /* USE_LDAP_SET_OPTION */ 138040266059SGregory Neil Shapiro /* From here on in we can use ldap internal timelimits */ 138140266059SGregory Neil Shapiro ld->ld_deref = lmap->ldap_deref; 138240266059SGregory Neil Shapiro ld->ld_options = lmap->ldap_options; 138340266059SGregory Neil Shapiro ld->ld_sizelimit = lmap->ldap_sizelimit; 138440266059SGregory Neil Shapiro ld->ld_timelimit = lmap->ldap_timelimit; 138540266059SGregory Neil Shapiro # endif /* USE_LDAP_SET_OPTION */ 138640266059SGregory Neil Shapiro } 138740266059SGregory Neil Shapiro 138840266059SGregory Neil Shapiro /* 138940266059SGregory Neil Shapiro ** SM_LDAP_GETERRNO -- get ldap errno value 139040266059SGregory Neil Shapiro ** 139140266059SGregory Neil Shapiro ** Parameters: 139240266059SGregory Neil Shapiro ** ld -- LDAP session handle 139340266059SGregory Neil Shapiro ** 139440266059SGregory Neil Shapiro ** Returns: 139540266059SGregory Neil Shapiro ** LDAP errno. 139640266059SGregory Neil Shapiro ** 139740266059SGregory Neil Shapiro */ 139840266059SGregory Neil Shapiro 139940266059SGregory Neil Shapiro int 140040266059SGregory Neil Shapiro sm_ldap_geterrno(ld) 140140266059SGregory Neil Shapiro LDAP *ld; 140240266059SGregory Neil Shapiro { 140340266059SGregory Neil Shapiro int err = LDAP_SUCCESS; 140440266059SGregory Neil Shapiro 140540266059SGregory Neil Shapiro # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 140640266059SGregory Neil Shapiro (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); 140740266059SGregory Neil Shapiro # else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 140840266059SGregory Neil Shapiro # ifdef LDAP_OPT_SIZELIMIT 140940266059SGregory Neil Shapiro err = ldap_get_lderrno(ld, NULL, NULL); 141040266059SGregory Neil Shapiro # else /* LDAP_OPT_SIZELIMIT */ 141140266059SGregory Neil Shapiro err = ld->ld_errno; 141240266059SGregory Neil Shapiro 141340266059SGregory Neil Shapiro /* 141440266059SGregory Neil Shapiro ** Reset value to prevent lingering LDAP_DECODING_ERROR due to 141540266059SGregory Neil Shapiro ** OpenLDAP 1.X's hack (see above) 141640266059SGregory Neil Shapiro */ 141740266059SGregory Neil Shapiro 141840266059SGregory Neil Shapiro ld->ld_errno = LDAP_SUCCESS; 141940266059SGregory Neil Shapiro # endif /* LDAP_OPT_SIZELIMIT */ 142040266059SGregory Neil Shapiro # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 142140266059SGregory Neil Shapiro return err; 142240266059SGregory Neil Shapiro } 142340266059SGregory Neil Shapiro # endif /* LDAPMAP */ 1424