1N/A * Copyright (c) 2001-2009 Sendmail, Inc. and its suppliers. 1N/A * All rights reserved. 1N/A * By using this file, you agree to the terms and conditions set 1N/A * forth in the LICENSE file which can be found at the top level of 1N/A * the sendmail distribution. 1N/A/* some "deprecated" calls are used, e.g., ldap_get_values() */ 1N/A "@(#)$Debug: sm_trace_ldap - trace LDAP operations $");
1N/A** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT 1N/A** lmap -- pointer to SM_LDAP_STRUCT to clear 1N/A#
endif /* defined(LDAP_VERSION_MAX) && _FFR_LDAP_VERSION > LDAP_VERSION_MAX */ 1N/A#
endif /* defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN */ 1N/A#
else /* _FFR_LDAP_VERSION */ 1N/A#
endif /* _FFR_LDAP_VERSION */ 1N/A#
else /* LDAP_REFERRALS */ 1N/A#
endif /* LDAP_REFERRALS */ 1N/A** SM_LDAP_START -- actually connect to an LDAP server 1N/A** name -- name of map for debug output. 1N/A** lmap -- the LDAP map being opened. 1N/A** true if connection is successful, false otherwise. 1N/A** Populates lmap->ldap_ld. 1N/A /* Don't print a port number for LDAP URIs */ 1N/A /* LDAP server supports URIs so use them directly */ 1N/A#
else /* SM_CONF_LDAP_INITIALIZE */ 1N/A#
endif /* SM_CONF_LDAP_INITIALIZE */ 1N/A#
else /* USE_LDAP_INIT */ 1N/A ** If using ldap_open(), the actual connection to the server 1N/A ** happens now so we need the timeout here. For ldap_init(), 1N/A ** the connection happens at bind time. 1N/A /* clear the event if it has not sprung */ 1N/A#
endif /* USE_LDAP_INIT */ 1N/A ** If using ldap_init(), the actual connection to the server 1N/A ** happens at ldap_bind_s() so we need the timeout here. 1N/A#
endif /* USE_LDAP_INIT */ 1N/A ** Need to put ticket in environment here instead of 1N/A ** during parseargs as there may be different tickets 1N/A ** for different LDAP connections. 1N/A#
endif /* LDAP_AUTH_KRBV4 */ 1N/A /* clear the event if it has not sprung */ 1N/A#
endif /* USE_LDAP_INIT */ 1N/A /* Save PID to make sure only this PID closes the LDAP connection */ 1N/A ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 1N/A ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 1N/A** SM_LDAP_SEARCH_M -- initiate multi-key LDAP search 1N/A** Initiate an LDAP search, return the msgid. 1N/A** The calling function must collect the results. 1N/A** lmap -- LDAP map information 1N/A** argv -- key vector of substitutions in LDAP filter 1N/A** NOTE: argv must have SM_LDAP_ARGS elements to prevent 1N/A** out of bound array references 1N/A** <0 on failure (SM_LDAP_ERR*), msgid on success 1N/A#
endif /* SM_LDAP_ARGS < 10 */ 1N/A else if (q[
1] >=
'0' && q[
1] <=
'9')
1N/A#
else /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 1N/A#
endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 1N/A "%.*s%s", (
int) (q - p), p,
key);
1N/A else if (q[
1] ==
'0' ||
1N/A "%.*s", (
int) (q - p), p);
1N/A /* Properly escape LDAP special characters */ 1N/A if (*k ==
'*' || *k ==
'(' ||
1N/A *k ==
')' || *k ==
'\\')
1N/A (*k ==
'*' ?
"\\2A" :
1N/A (*k ==
'(' ?
"\\28" :
1N/A (*k ==
')' ?
"\\29" :
1N/A (*k ==
'\\' ?
"\\5C" :
1N/A "%.*s", (
int) (q - p +
1), p);
1N/A p = q + (q[
1] ==
'%' ?
2 :
1);
1N/A** SM_LDAP_SEARCH -- initiate LDAP search 1N/A** Initiate an LDAP search, return the msgid. 1N/A** The calling function must collect the results. 1N/A** Note this is just a wrapper into sm_ldap_search_m() 1N/A** lmap -- LDAP map information 1N/A** key -- key to substitute in LDAP filter 1N/A** <0 on failure, msgid on success 1N/A** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a 1N/A** particular objectClass 1N/A** lmap -- pointer to SM_LDAP_STRUCT in use 1N/A** entry -- current LDAP entry struct 1N/A** ocvalue -- particular objectclass in question. 1N/A** may be of form (fee|foo|fum) meaning 1N/A** any entry can be part of either fee, 1N/A** foo or fum objectclass 1N/A** true if item has that objectClass 1N/A while (*p !=
'\0' && *p !=
'|')
1N/A** SM_LDAP_RESULTS -- return results from an LDAP lookup in result 1N/A** lmap -- pointer to SM_LDAP_STRUCT in use 1N/A** msgid -- msgid returned by sm_ldap_search() 1N/A** flags -- flags for the lookup 1N/A** delim -- delimiter for result concatenation 1N/A** rpool -- memory pool for storage 1N/A** result -- return string 1N/A** recurse -- recursion list 1N/A ** This code will maintain a list of 1N/A ** SM_LDAP_RECURSE_ENTRY structures 1N/A ** in ascending order. 1N/A /* Allocate an initial SM_LDAP_RECURSE_LIST struct */ 1N/A /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */ 1N/A ** Return current entry pointer if already exists. 1N/A ** Not found in list, make room 1N/A ** at insert point and add it. 1N/A /* Are we the top top level of the search? */ 1N/A /* If we don't want multiple values and we have one, break */ 1N/A /* Cycle through all entries */ 1N/A ** If matching only and found an entry, 1N/A ** no need to spin through attributes 1N/A /* only wanted one match */ 1N/A#
endif /* _FFR_LDAP_SINGLEDN */ 1N/A /* record completed DN's to prevent loops */ 1N/A /* already on list, skip it */ 1N/A ** Reset value to prevent lingering 1N/A ** LDAP_DECODING_ERROR due to 1N/A ** OpenLDAP 1.X's hack (see below) 1N/A#
endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 1N/A /* URL lookups specify attrs to use */ 1N/A /* attribute not requested */ 1N/A ** For recursion on a particular attribute, 1N/A ** we may need to see if this entry is 1N/A ** part of a particular objectclass. 1N/A ** Also, ignore objectClass attribute. 1N/A ** Otherwise we just ignore this attribute. 1N/A /* Must be an error */ 1N/A ** Reset value to prevent lingering 1N/A ** LDAP_DECODING_ERROR due to 1N/A ** OpenLDAP 1.X's hack (see below) 1N/A#
endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 1N/A ** If matching only, 1N/A ** no need to spin through entries 1N/A ** If we don't want multiple values, 1N/A ** return first found. 1N/A /* already have a value */ 1N/A /* only wanted one match */ 1N/A /* attributes only */ 1N/A /* only wanted one match */ 1N/A ** If there is more than one, munge then 1N/A ** into a map_coldelim separated string. 1N/A ** If we are recursing we may have an entry 1N/A ** with no 'normal' values to put in the 1N/A ** This is not an error. 1N/A /* only wanted one match */ 1N/A /* add to recursion */ 1N/A ** attribute values. Otherwise, just free 1N/A ** memory and move on to the next 1N/A ** attribute in this entry. 1N/A /* Grow result string if needed */ 1N/A /* Internal error: buffer too small for LDAP values */ 1N/A ** We check save_errno != LDAP_DECODING_ERROR since 1N/A ** OpenLDAP 1.X has a very ugly *undocumented* 1N/A ** hack of returning this error code from 1N/A ** ldap_next_attribute() if the library freed the 1N/A ** ber attribute. See: 1N/A /* Must be an error */ 1N/A /* mark this DN as done */ 1N/A /* We don't want multiple values and we have one */ 1N/A /* Must be an error */ 1N/A ** We may have gotten an LDAP_RES_SEARCH_RESULT response 1N/A ** with an error inside it, so we have to extract that 1N/A ** with ldap_parse_result(). This can happen when talking 1N/A ** to an LDAP proxy whose backend has gone down. 1N/A#
endif /* LDAP_SERVER_DOWN */ 1N/A ** server disappeared, 1N/A ** try reopen on next search 1N/A ** Spin through the built-up recurse list at the top 1N/A ** of the recursion. Since new items are added at the 1N/A ** end of the shared list, we actually only ever get 1N/A ** one level of recursion before things pop back to the 1N/A ** top. Any items added to the list during that recursion 1N/A ** will be expanded by the top level. 1N/A /* already expanded */ 1N/A /* We need to add objectClass */ 1N/A "objectClass") == 0)
1N/A /* already requested */ 1N/A ** Use the existing connection 1N/A ** for this search. It really 1N/A ** should use lud_scheme://lud_host:lud_port/ 1N/A ** instead but that would require 1N/A ** opening a new connection. 1N/A ** This should be fixed ASAP. 1N/A /* Use the attributes specified by URL */ 1N/A /* unknown or illegal attribute type */ 1N/A /* Collect results */ 1N/A#
endif /* LDAP_SERVER_DOWN */ 1N/A ** server disappeared, 1N/A ** try reopen on next search 1N/A /* Reset rlidx as new items may have been added */ 1N/A** SM_LDAP_CLOSE -- close LDAP connection 1N/A** lmap -- LDAP map information 1N/A** SM_LDAP_SETOPTS -- set LDAP options 1N/A** ld -- LDAP session handle 1N/A** lmap -- LDAP map information 1N/A#
endif /* _FFR_LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) */ 1N/A#
endif /* LDAP_OPT_RESTART */ 1N/A#
else /* USE_LDAP_SET_OPTION */ 1N/A /* From here on in we can use ldap internal timelimits */ 1N/A#
endif /* USE_LDAP_SET_OPTION */ 1N/A** SM_LDAP_GETERRNO -- get ldap errno value 1N/A** ld -- LDAP session handle 1N/A#
else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 1N/A#
else /* LDAP_OPT_SIZELIMIT */ 1N/A ** Reset value to prevent lingering LDAP_DECODING_ERROR due to 1N/A ** OpenLDAP 1.X's hack (see above) 1N/A#
endif /* LDAP_OPT_SIZELIMIT */ 1N/A#
endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 1N/A#
endif /* LDAPMAP */