2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. 2N/A * The following are from libldap. Used to check if an attribute value 2N/A * should be base64-encoded when displayed by tools such as ldaplist. 2N/A * If requested, convert attribute type in a RDN that has an attribute 2N/A * mapping to the original mappped type. Either way, the DN will be 2N/A * normalized (i.e., remove unnecessary spaces). 2N/A * cn<->cn-st and iphostnumber<->iphostnumber-st 2N/A * cn-st= aaa + iphostnumber-st= 10.10.01.01 2N/A * cn=aaa+iphostnumber=10.10.01.01 2N/A * Input - service: e.g. hosts, passwd etc. 2N/A * map_attr: if TRUE, map attribute 2N/A * Return: NULL - No attribute mapping in the RDN 2N/A * Non-NULL - The attribute type(s) in the RDN are mapped and 2N/A * the memory is allocated for the new rdn. 2N/A /* Break down "type = value\0" pairs. */ 2N/A /* Parse type=value pair */ 2N/A /* Reverse map: e.g. cn-sm -> cn */ 2N/A /* The attribute mapping is found */ 2N/A /* "type=value\0" */ 2N/A /* Reconstruct type=value pair. A string is allocated */ 2N/A * No attribute mapping. attrs[i] is going to be copied 2N/A * later. Restore "type\0value\0" back to 2N/A /* Reconstruct RDN from type=value pairs */ 2N/A * If requested, convert attribute type in a DN that has an attribute 2N/A * mapping to the original mappped type. Either way, the DN will be 2N/A * normalized (i.e., remove unnecessary spaces). 2N/A * The mappings are cn<->cn-sm, iphostnumber<->iphostnumber-sm 2N/A * dn: cn-sm=aaa + iphostnumber-sm= 9.9.9.9,dc=central,dc=sun,dc=com 2N/A * dn: cn=aaa+iphostnumber=9.9.9.9,dc=central,dc=sun,dc=com 2N/A * Input - service: e.g. hosts, passwd etc. 2N/A * dn: the value of a distinguished name 2N/A * map_attr: if TRUE, map attribute 2N/A * Return - NULL: error 2N/A * non-NULL: A converted DN and the memory is allocated 2N/A /* Attribute mapping requires 'service' */ 2N/A /* attribute mapping not needed and no space in DN, done */ 2N/A /* Break down RDNs in a DN */ 2N/A * Reconstruct dn from RDNs. 2N/A * Calculate the length first. 2N/A * Checks which ones of the internal operational attributes 2N/A * (cookie->i_extra_info_attr) are requested and returns 2N/A * the values. Currently only NS_LDAP_OP_ATTR_SERVER_TYPE 2N/A * Free the data structure used to track the processing of attributes 2N/A * with range option, such as member. 2N/A * machine to collect the next range of the attribute values. 2N/A * 'first' indicates if the attribute range option has 2N/A * just be detected and if the control structure should 2N/A * be created and added to the range_attr list in the 2N/A * range info control structure, *info_p. If it's not 2N/A * TRUE, the control structure will be updated to have 2N/A * the attribute's range value for the next search. Either 2N/A * way, 'attr_type' should always contain the attribute 2N/A * name and the range option specification. The updated 2N/A * attr_and_range string will also have the attribute 2N/A * name and range info together, so that it can be 2N/A * readily used in the attribute list for the next 2N/A * ns_ldap_range_attr_t and ns_ldap_range_info_t 2N/A * when used for processing attributes with range 2N/A * Attribute type with range option has the form: 2N/A * <attr type>;range=n1-n2, where n2 may be '*' (last) 2N/A /* get end of range */ 2N/A /* ignore the range setting */ 2N/A * End of range reached and first search result ? 2N/A * No more to be done. 2N/A /* ignore the range setting */ 2N/A * generate the "attribute type + option" for the next search: 2N/A * <attr type>;range=start-end 2N/A /* ignore this attribute type */ 2N/A * Take a binary value and return the base64 encoded string. 2N/A * Tag the output string with NS_LDAP_BASE64_TAG, "\1{base64}". 2N/A /* Encode 'value', output looks like "\1{base64}:: <encoded string>" */ 2N/A * change "\1{base64}:: <encoded string>" into 2N/A * "\1{base64}<encoded string> 2N/A /* remove the newline character at the end */ 2N/A * Convert a single ldap entry from a LDAPMessage 2N/A * into an ns_ldap_entry structure. 2N/A * Schema map the entry if specified in flags 2N/A * see if schema mapping existed for the given service 2N/A * If service == auto_* and no 2N/A * schema mapping found 2N/A * then try automount 2N/A * There is certain case that schema mapping exist 2N/A * but __ns_ldap_getOrigAttribute(service, 2N/A * NS_HASH_SCHEMA_MAPPING_EXISTED); 2N/A * NS_LDAP_ATTRIBUTEMAP = automount:automountMapName=AAA 2N/A * NS_LDAP_OBJECTCLASSMAP = automount:automountMap=MynisMap 2N/A * NS_LDAP_OBJECTCLASSMAP = automount:automount=MynisObject 2N/A * Make a check for schema_mapping_existed here 2N/A * so later on __s_api_convert_automountmapname won't be called 2N/A * unnecessarily. It is also used for attribute mapping 2N/A * and objectclass mapping. 2N/A nAttrs =
1;
/* start with 1, 0 is for the DN attr */ 2N/A * add 1 for "gecos" 1 to N attribute mapping, 2N/A * just in case it is needed. 2N/A * ep->attr_count will be updated later if that is true. 2N/A /* attribute-map and normalize the entry DN if needed */ 2N/A * To speed up group member DN processing, we need to 2N/A * normalize the entry DN of a passwd or group entry. 2N/A * Such DNs will later be stored in cache if needed. 2N/A /* other attributes */ 2N/A /* allocate new attr name */ 2N/A * Range result ? Not all values returned ? Then 2N/A * attr should looks like: <attr type>;range=n1-n2 2N/A * where n2 may be '*', i.e., end of range. 2N/A * For now, ra->received_ranges will 2N/A * have the first range of values. For 2N/A * subsequent range searches, values 2N/A * found in ra->current_range will be 2N/A * appended to it in __s_api_getEntry. 2N/A * So it would represent the 2N/A * accumulation of all of the ranges 2N/A /* copy attribute type + range */ 2N/A /* no need for the range part now */ 2N/A * if service == auto_* and no schema mapping found 2N/A * and schema_mapping_existed is TRUE and NS_LDAP_NOMAP 2N/A * is not set then try automount e.g. 2N/A * NS_LDAP_ATTRIBUTEMAP = automount:automountMapName=AAA 2N/A * for "gecos" 1 to N mapping, 2N/A * do not remove the mapped attribute, 2N/A * just create a new gecos attribute 2N/A * and append it to the end of the attribute list 2N/A * 1 to N attribute mapping processing 2N/A * is only done for "gecos" 2N/A * get attribute mapping for "gecos", 2N/A * need to know the number and order of the 2N/A * this should never happens, 2N/A "Attribute mapping " 2N/A "found for attributes " 2N/A * is this attribute the 1st, 2nd, or 2N/A * 3rd attr in the mapping list? 2N/A * This should never happens, 2N/A "Attribute mapping " 2N/A "found for attributes " 2N/A * Need to process group member or memberof in DN format ? 2N/A /* check for binary data if length not zero */ 2N/A /* encode the data in base64 */ 2N/A /* map object classes if necessary */ 2N/A * if service == auto_* and no 2N/A * schema mapping found 2N/A * then try automount 2N/A * Normalize group member or memberof 2N/A * DN but don't map attributes. 2N/A }
/* end of other attributes loop */ 2N/A /* special processing for gecos 1 to up to 3 attribute mapping */ 2N/A for (i = 0; i <
3; i++) {
2N/A * f is the index of the first returned 2N/A * attribute which "gecos" attribute mapped to 2N/A if (k != -
1 && f == -
1)
2N/A * Create and fill in the last reserved 2N/A * ap with the data from the "gecos" 2N/A * mapping attributes 2N/A 2,
sizeof (
char *));
2N/A /* add 1 more for a possible "," */ 2N/A * realloc to add "," and 2N/A * ap[k]->attrvalue[0] 2N/A * The ns_ldap_entry_t generated by __s_api_cvtEntry() may contain 2N/A * duplicate attributes for an range attribute. These duplicate 2N/A * ones are caused by libldap when it returns attributes such 2N/A * as "member" and "member;range=0-1499" together. This function 2N/A * keeps the short one and removes the one with option. 2N/A * Remove duplicate empty attributes, such as member or memberof, 2N/A * in the result ns_ldap_entry_t entry. 2N/A * Attribute name in entry may be mapped to a different name 2N/A * due to attribute mapping. The one containing range 2N/A * option info is an unmapped one, so use the mapped 2N/A * one saved in ns_ldap_range attr_t to find duplicate. 2N/A /* No need for the range option info now */ 2N/A for (j = i; j <
cnt -
1; j++) {
2N/A /* restore the range option info if needed */ 2N/A * If just gotten the first range, remove duplicate attribute types, 2N/A * i.e., keep "member" and not "member;range=0-1499". Otherwise, 2N/A * merge this range of values with the previous ones. 2N/A * Reallocate the received_ranges value array and add the 2N/A * current one to the end of it. 2N/A * Free the current (not first) ns_ldap_entry. 2N/A * The attribute value array itself needs to be 2N/A * freed, but not the value strings. Since the 2N/A * pointers to these strings have just been 2N/A * copied into the first ns_ldap_entry's value 2N/A /* clean up the range control info if last range */ 2N/A * Generate only once the extra infomation 2N/A * (operational attributes) if requested. 2N/A * Then exit with NS_LDAP_SUCCESS. 2N/A * set up the attributes (with updated range numbers) 2N/A * for the next search of the same DN 2N/A * We are not going to perform DN to domain mapping 2N/A * in the Standalone mode 2N/A * We are not going to perform DN to domain mapping 2N/A * in the Standalone mode 2N/A /* if no space(s) to remove, return */ 2N/A /* if no '=' separator, return */ 2N/A /* now two strings, type and value */ 2N/A /* remove type's leading spaces */ 2N/A /* remove type's trailing spaces */ 2N/A /* add '=' separator back */ 2N/A /* remove value's leading spaces */ 2N/A /* remove value's trailing spaces */ 2N/A /* move value up if necessary */ 2N/A /* assign other state variables */ 2N/A * count the number of '=' char 2N/A * See if schema mapping existed for the given service. 2N/A * If not, just return success. 2N/A * if service == auto_* and no 2N/A * schema mapping found 2N/A * then try automount 2N/A * no '=' sign, just say OK and return nothing 2N/A * Make a copy of the filter string 2N/A * for saving the name of the objectclasses or 2N/A * attributes that need to be passed to the 2N/A * objectclass or attribute mapping functions. 2N/A * pointer "info->from_name" points to the locations 2N/A * within this string. 2N/A * The input filter string, filter, will be used 2N/A * to indicate where these names start and end. 2N/A * pointers "info->name_start" and "info->name_end" 2N/A * point to locations within the input filter string, 2N/A * and are used at the end of this function to 2N/A * merge the original filter data with the 2N/A * mapped objectclass or attribute names. 2N/A * get memory for info arrays 2N/A * find valid '=' for further processing, 2N/A * ignore the "escaped =" (.i.e. "\="), or 2N/A * "=" in quoted string 2N/A * remember the location of this "=" 2N/A * skip until the end of the attribute value 2N/A * mark the end of the attribute value 2N/A * ignore escape characters 2N/A * don't skip if next char is '\0' 2N/A * for each valid "=" found, get the name to 2N/A * look at the left side of "=" to see 2N/A * if assertion is "objectclass=<ocname>" 2N/A * or "<attribute name>=<attribute value>" 2N/A * first skip spaces before "=". 2N/A * Note that filter_c_next may not point to the 2N/A * start of the filter string. For i > 0, 2N/A * it points to the end of the last name processed + 2 2N/A * mark the end of the left side string (the key) 2N/A * find the start of the key 2N/A /* OPARATOK is '(' */ 2N/A * assertion is "objectclass=ocname", 2N/A * ocname is the one needs to be mapped 2N/A * skip spaces after "=" to find start 2N/A /* ignore empty ocname */ 2N/A * now find the end of the ocname 2N/A /* CPARATOK is ')' */ 2N/A * assertion is not "objectclass=ocname", 2N/A * assume assertion is "<key> = <value>", 2N/A * <key> is the one needs to be mapped 2N/A /* perform schema mapping */ 2N/A * and service == auto* 2N/A * try to find automount's 2N/A "Multiple attribute or objectclass " 2N/A "mapping for '%s' in filter " 2N/A "'%s' not allowed."),
2N/A * copy the original filter data 2N/A * between the last name and current 2N/A /* the data is copied */ 2N/A * replace the name with 2N/A /* copy the filter data after the last name */ 2N/A * get_mapped_filter returns 2N/A * NULL filter pointer, if 2N/A * no mapping was done 2N/A * validate filter to make sure it's legal 2N/A * [remove redundant ()'s] 2N/A * If password control attached in *cookie->errorp, 2N/A * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 2N/A * free the error structure (we do not need 2N/A * the sec_to_expired info). 2N/A * Reset rc to NS_LDAP_SUCCESS. 2N/A * If using an MT connection, return the connection; 2N/A * otherwise, reset the connection user to get ready 2N/A * to use a new connection. 2N/A * If password control attached in *cookie->errorp, 2N/A * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 2N/A * free the error structure (we do not need 2N/A * the sec_to_expired info). 2N/A * Reset rc to NS_LDAP_SUCCESS. 2N/A /* set it up to use a connection opened for referral */ 2N/A /* If using a MT connection, return it. */ 2N/A /* Find a referral ref that works */ 2N/A * If password control attached in *cookie->errorp, 2N/A * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 2N/A * free the error structure (we do not need 2N/A * the sec_to_expired info). 2N/A * Reset rc to NS_LDAP_SUCCESS. 2N/A * Only follow one level of referrals, i.e. 2N/A * if already in referral mode, do nothing 2N/A /* add to referral list */ 2N/A * Only follow one level of referrals, i.e. 2N/A * if already in referral mode, do nothing 2N/A /* add to referral list */ 2N/A /* free allocated storage */ 2N/A /* add to referral list */ 2N/A * AD does not return valid target_posp 2N/A /* add to referral list */ 2N/A * clear_results(ns_ldap_cookie_t): 2N/A * Attempt to obtain remnants of ldap responses and free them. If remnants are 2N/A * not obtained within a certain time period tell the server we wish to abandon 2N/A * Note that we do not initially tell the server to abandon the request as that 2N/A * can be an expensive operation for the server, while it is cheap for us to 2N/A * just flush the input. 2N/A * If something was to remain in libldap queue as a result of some error then 2N/A * it would be freed later during drop connection call or when no other 2N/A * requests share the connection. 2N/A * We need to cleanup the rest of response (if there is such) 2N/A * and LDAP abandon is too heavy for LDAP servers, so we will 2N/A * wait for the rest of response till timeout and "process" it. 2N/A * If there was timeout then we will send ABANDON request to 2N/A * LDAP server to decrease load. 2N/A /* Disassociate cookie with msgId */ 2N/A * This state machine performs one or more LDAP searches to a given 2N/A * directory server using service search descriptors and schema 2N/A * mapping as appropriate. The approximate pseudocode for 2N/A * this routine is the following: 2N/A * Given the current configuration [set/reset connection etc.] 2N/A * and the current service search descriptor list 2N/A * or default search filter parameters 2N/A * foreach (service search filter) { 2N/A * initialize the filter [via filter_init if appropriate] 2N/A * Recover if the connection is lost 2N/A * perform the search 2N/A * foreach (result entry) { 2N/A * process result [via callback if appropriate] 2N/A * save result for caller if accepted. 2N/A * exit and return all collected if allResults found; 2N/A * return collected results and exit 2N/A * Set the flag to get ldap account management controls. 2N/A /* Check if we've reached MAX retries. */ 2N/A * Even if we still have retries left, check 2N/A * if retry is possible. 2N/A * Free results if any, reset to the first 2N/A * search descriptor and start a new session. 2N/A /* get next search descriptor */ 2N/A * error occurred when using the connection. On entry, 2N/A * cookie->err_rc must be set to the ldap error code, 2N/A * on exit, cookie->new_state will be set to the next 2N/A * state to go, LDAP_ERROR, REINIT, or NEXT_SESSION. 2N/A /* Close the connection, if a shared one */ 2N/A /* retry if allowed */ 2N/A /* Shared connection, close it. */ 2N/A * Remove the server from ldap_cachemgr's list, 2N/A * if rc is not LDAP_SERVER_DOWN. We assume 2N/A * LDAP SERVER_DOWN is due to idle timeout or 2N/A * clean server shutdown, so reconnect should 2N/A * NS_LDAP_NEW_CONN indicates that the 2N/A * connection should be deleted, not 2N/A /* setup referrals search if necessary */ 2N/A * Do search if more range of values to get. 2N/A * Otherwise, restore search related data in 2N/A * cookie and go to the NEXT_RESULT state to 2N/A * remove the last LDAP_RES_SEARCH_RESULT 2N/A * of this range search and have the result 2N/A * get the next range of values. 2N/A /* Server no good, may need to unwind request & retry */ 2N/A * drop session then reinit 2N/A * Redo the search in 2N/A * next session only if 2N/A * it was the first search, 2N/A * i.e., no result entries 2N/A * saved in the cookie. 2N/A * no drop session, just get 2N/A * Drop session then get 2N/A * next session. New state 2N/A * is already DROP_SESSION. 2N/A * If all range of attribute values 2N/A * have been retrieved, go back to 2N/A * normal result processing. Otherwise, 2N/A * get the next range. 2N/A * RESULT_ERROR expects the return code from ldap_result() 2N/A * be saved in cookie->err_rc. The ldap result rc is 2N/A * converted to ldap error code to see if it's a retry-able 2N/A * error, if so, go to REINIT or NEXT_SESSION to retry. 2N/A * Otherwise, go to DROP_SESSION then return to LDAP_ERROR 2N/A * to exit the state machine. 2N/A /* retryable error */ 2N/A * Server no good, may need to unwind 2N/A * Caller (e.g. __ns_ldap_list_batch_add) 2N/A * does not want to block on ldap_result(). 2N/A * Therefore we execute ldap_result() with 2N/A /* check and process referrals info */ 2N/A /* handle referrals if necessary */ 2N/A /* else LDAP_RES_SEARCH_ENTRY */ 2N/A /* get account management response control */ 2N/A * If not all values of certain attributes, 2N/A * such as member or memberof, are returned, 2N/A * as indicated by the 'range' option attached 2N/A * to the attribute type, then search the 2N/A * same DN entry again to get the entire 2N/A * range of the attribute values. If this 2N/A * is not the first such search, then go 2N/A * to the NEXT_RESULT state to remove the 2N/A * remaining LDAP_RES_SEARCH_RESULT from the 2N/A * result message to prevent memory leaks. 2N/A /* Try old "cn uid" server side sort */ 2N/A /* handle referrals if necessary */ 2N/A /* else LDAP_RES_SEARCH_ENTRY */ 2N/A * If VLV search was successfull save the server 2N/A * side sort type tried. 2N/A * If not all values of certain attributes, 2N/A * such as member or memberof, are returned, 2N/A * as indicated by the 'range' option attached 2N/A * to the attribute type, then search the 2N/A * same entry again to get the rest of the 2N/A /* NOTE THIS STATE MAY BE PROCESSED BY CALLER */ 2N/A /* cb doesn't want any more data */ 2N/A /* invalid return code */ 2N/A /* NOTE PREVIOUS STATE SPECIFIES NEXT STATE */ 2N/A * XXX DO WE NEED THIS CASE? 2N/A * if (search is complete) { 2N/A * cookie->new_state = EXIT; 2N/A * entering referral mode if necessary 2N/A /* get next referral info */ 2N/A /* check see if done with all referrals */ 2N/A "Error occurred during" 2N/A " receiving results. " 2N/A "Connection to server lost."),
2N/A "Error occurred during" 2N/A " receiving results. %s" 2N/A * For a lookup of shadow data, if shadow update is enabled, 2N/A * check the calling process' privilege to ensure it's 2N/A * allowed to perform such operation. 2N/A * If service is "shadow", we may need 2N/A * to use privilege credentials. 2N/A * Since we release admin credentials after 2N/A * connection is closed and we do not cache 2N/A * them, we allow any root or all zone 2N/A * privilege process to read shadow data. 2N/A * We do not want to reuse connection (hence 2N/A * keep it open) with admin credentials. 2N/A * If NS_LDAP_KEEP_CONN is set, reject the 2N/A * internal function for __ns_ldap_list 2N/A * Sanity check - NS_LDAP_READ_SHADOW is for our 2N/A /* Initialize State machine cookie */ 2N/A /* see if need to follow referrals */ 2N/A /* get the service descriptor - or create a default one */ 2N/A /* Create default service Desc */ 2N/A * use VLV/PAGE control only if NS_LDAP_PAGE_CTRL is set 2N/A /* Set up other arguments */ 2N/A /* check_shadow() may add extra value to cookie->i_flags */ 2N/A * If given, use the credential given by the caller, and 2N/A * skip the credential check required for shadow update. 2N/A * Here rc == NS_LDAP_SUCCESS means that the state 2N/A * machine init'ed successfully. The actual status 2N/A * of the search will be determined by 2N/A * __ns_ldap_list_batch_end(). Add the cookie to our 2N/A * If state machine init failed then copy error to the caller 2N/A * and delete the cookie. 2N/A /* Copy results back to user */ 2N/A * __ns_ldap_list performs one or more LDAP searches to a given 2N/A * directory server using service search descriptors and schema 2N/A * mapping as appropriate. The operation may be retried a 2N/A * couple of times in error situations. 2N/A * Strip the NS_LDAP_PAGE_CTRL option as this interface does not 2N/A * support this. If you want to use this option call the API 2N/A * __ns_ldap_list_sort() which has the sort attribute. 2N/A * This function performs the same processing as __ns_ldap_list, but 2N/A * handles 'extra_info_attr' and returns 'extra_info'. This is to allow 2N/A * Strip the NS_LDAP_PAGE_CTRL option as this interface does not 2N/A * support this. If you want to use this option call the API 2N/A * __ns_ldap_list_sort() which has the sort attribute. 2N/A * __ns_ldap_list_sort performs one or more LDAP searches to a given 2N/A * directory server using service search descriptors and schema 2N/A * mapping as appropriate. The operation may be retried a 2N/A * couple of times in error situations. 2N/A * internal function for __ns_ldap_read_dn 2N/A * Sanity check - NS_LDAP_READ_SHADOW is for our 2N/A /* Initialize State machine cookie */ 2N/A /* see if need to follow referrals */ 2N/A /* Create default service Desc */ 2N/A /* search base is dn */ 2N/A /* search scope is base */ 2N/A /* Set up other arguments */ 2N/A /* no need to perform attribute mapping on the DN */ 2N/A /* Copy results back to user */ 2N/A * __ns_ldap_read_dn reads a specific DN using LDAP search to a given 2N/A * directory server with service search descriptors and schema 2N/A * mapping as appropriate. The operation may be retried a 2N/A * couple of times in error situations. 2N/A * Create and initialize batch for native LDAP lookups 2N/A * Add a LDAP search request to the batch. 2N/A * Strip the NS_LDAP_PAGE_CTRL option as the batch interface does not 2N/A * Free the conn_user if the cookie was not batched. If the cookie 2N/A * was batched then __ns_ldap_list_batch_end or release will free the 2N/A * conn_user. The batch API instructs the search_state_machine 2N/A * to reinit and retry (max 3 times) on retriable LDAP errors. 2N/A * Process batch. Everytime this function is called it selects an 2N/A * active cookie from the batch and single steps through the 2N/A * search_state_machine for the selected cookie. If lookup associated 2N/A * with the cookie is complete (success or error) then the cookie is 2N/A * removed from the batch and its memory freed. 2N/A * Returns 1 (if batch still has active cookies) 2N/A * 0 (if batch has no more active cookies) 2N/A * -1 (on errors, *rcp will contain the error code) 2N/A * The caller should call this function in a loop as long as it returns 1 2N/A * to process all the requests added to the batch. The results (and errors) 2N/A * will be available in the locations provided by the caller at the time of 2N/A * __ns_ldap_list_batch_add(). 2N/A /* Check if are already done */ 2N/A /* Get the next cookie from the batch */ 2N/A * Checks the status of the cookie's connection if it needs 2N/A * to use that connection for ldap_search_ext or ldap_result. 2N/A * If the connection is no longer good but worth retrying 2N/A * then reinit the search_state_machine for this cookie 2N/A * starting from the first search descriptor. REINIT will 2N/A * clear any leftover results if max retries have not been 2N/A * reached and redo the search (which may also involve 2N/A * following referrals again). 2N/A * Note that each cookie in the batch will make this 2N/A * determination when it reaches one of the LD_USING_STATES. 2N/A * MT connection is not usable, 2N/A * close it before REINIT. 2N/A /* Single step through the search_state_machine */ 2N/A /* Remove the cookie from the batch */ 2N/A /* Delete cookie and decrement active cookie count */ 2N/A * This means that search_state_machine needs to do 2N/A * another ldap_result() for the cookie in question. 2N/A * We only do at most one ldap_result() per call in 2N/A * this function and therefore we return. This allows 2N/A * the caller to process results from other cookies 2N/A * in the batch without getting tied up on just one 2N/A * This includes states that follow NEXT_RESULT or 2N/A * MULTI_RESULT such as PROCESS_RESULT and 2N/A * END_PROCESS_RESULT. We continue processing 2N/A * this cookie till we reach either the error, exit 2N/A * or the result states. 2N/A /* Return 0 if no more cookies left otherwise 1 */ 2N/A * Process all the active cookies in the batch and when none 2N/A * remains finalize the batch. 2N/A * find_domainname performs one or more LDAP searches to 2N/A * find the value of the nisdomain attribute associated with 2N/A * the input DN (with no retry). 2N/A /* Initialize State machine cookie */ 2N/A /* see if need to follow referrals */ 2N/A /* Create default service Desc */ 2N/A /* search base is dn */ 2N/A /* search scope is base */ 2N/A /* search filter is "nisdomain=*" */ 2N/A /* Process search */ 2N/A /* Copy domain name if found */ 2N/A * __s_api_find_domainname performs one or more LDAP searches to 2N/A * find the value of the nisdomain attribute associated with 2N/A * the input DN (with retry). 2N/A * Sanity check - NS_LDAP_READ_SHADOW is for our 2N/A /* get the service descriptor - or create a default one */ 2N/A /* Create default service Desc */ 2N/A /* Initialize State machine cookie */ 2N/A /* identify self as a getent user */ 2N/A /* see if need to follow referrals */ 2N/A * use VLV/PAGE control only if NS_LDAP_NO_PAGE_CTRL is not set 2N/A /* Set up other arguments */ 2N/A /* check_shadow() may add extra value to cookie->i_flags */ 2N/A * If given, use the credential given by the caller, and 2N/A * skip the credential check required for shadow update. 2N/A * This function performs the same processing as __ns_ldap_firstEntry, but 2N/A * handles 'extra_info_attr' and returns 'extra_info'. This is to allow 2N/A /* Complete search */ 2N/A /* Copy results back to user */ 2N/A * we want to retrieve the DN as it appears in LDAP 2N/A * hence the use of NS_LDAP_NOT_CVT_DN in flags 2N/A * the domain parameter needs to be used in case domain is not local, if 2N/A * this routine is to support multi domain setups, it needs lots of work... 2N/A * we want to retrieve the DN as it appears in LDAP 2N/A * hence the use of NS_LDAP_NOT_CVT_DN in flags 2N/A * break dn into rdns 2N/A /* construct a semi-normalized dn, newdn */ 2N/A /* remove the last ',' */ 2N/A * loop and find the domain name associated with newdn, 2N/A * removing rdn one by one from left to right 2N/A * try cache manager first 2N/A * try ldap server second 2N/A * skip the last one, 2N/A * since it is already cached by ldap_cachemgr 2N/A * If it's nscd, ask cache manager to save the 2N/A * dn to domain mapping(s) 2N/A for (j = 0; j <= i; j++) {
2N/A "serviceAuthenticationMethod: %s.\n"),
srv);
2N/A * This routine is called when certain scenario occurs 2N/A * service == auto_home 2N/A * SSD = automount: ou = mytest, 2N/A * NS_LDAP_MAPATTRIBUTE= auto_home: automountMapName=AAA 2N/A * NS_LDAP_OBJECTCLASSMAP= auto_home:automountMap=MynisMap 2N/A * NS_LDAP_OBJECTCLASSMAP= auto_home:automount=MynisObject 2N/A * The automountMapName is prepended implicitely but is mapped 2N/A * to AAA. So dn could appers as 2N/A * dn: AAA=auto_home,ou=bar,dc=foo,dc=com 2N/A * dn: automountKey=user_01,AAA=auto_home,ou=bar,dc=foo,dc=com 2N/A * dn: automountKey=user_02,AAA=auto_home,ou=bar,dc=foo,dc=com 2N/A * This function is called to covert the mapped attr back to 2N/A * orig attr when the entries are searched and returned 2N/A * Check to see if there is a mapped attribute for auto_xxx 2N/A * if no mapped attribute for auto_xxx, try automount 2N/A * if no mapped attribute is found, return SUCCESS (no op) 2N/A * if the mapped attribute is found and attr is not empty, 2N/A "empty string.\n"));
2N/A * Locate the mapped attribute in the dn 2N/A * and replace it if it exists 2N/A * If mapped attr is found(buffer != NULL) 2N/A * a new dn is returned 2N/A * If no mapped attribute is in dn, 2N/A * return NS_LDAP_SUCCESS (no op) 2N/A * return NS_LDAP_MEMORY (no op) 2N/A * If the mapped attr is found in the dn, 2N/A * return NS_LDAP_SUCCESS and a new_dn. 2N/A * If no mapped attr is found, 2N/A * return NS_LDAP_SUCCESS and *new_dn == NULL 2N/A * If there is not enough memory, 2N/A * return NS_LDAP_MEMORY and *new_dn == NULL 2N/A * separate dn into individual components 2N/A * "automountKey=user_01" , "automountMapName_test=auto_home", ... 2N/A * This will find "mapped attr=value" in dn. 2N/A * It won't find match if mapped attr appears 2N/A * This function is called when reading from 2N/A * the directory so assume each component has "=". 2N/A * Any ill formatted dn should be rejected 2N/A * before adding to the directory 2N/A * The new length is *dn length + (difference between 2N/A * orig attr and mapped attr) + 1 ; 2N/A * automountKey=aa,automountMapName_test=auto_home,dc=foo,dc=com 2N/A * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com 2N/A * Locate the mapped attr in the dn. 2N/A * Use dnArray[i] instead of mapped_attr 2N/A * because mapped_attr could appear in 2N/A /* copy the portion before mapped attr in dn */ 2N/A * Copy the orig_attr. e.g. automountMapName 2N/A * This replaces mapped attr with orig attr 2N/A * Copy the portion after mapped attr in dn 2N/A * Validate Filter functions 2N/A/* ***** Start of modified libldap.so.5 filter parser ***** */ 2N/A/* filter parsing routine forward references */ 2N/A * assumes string manipulation is in-line 2N/A * and all strings are sufficient in size 2N/A * return value is the position after 'c' 2N/A * We have (x(filter)...) with str sitting on 2N/A * the x. We have to find the paren matching 2N/A * the one before the x and put the intervening 2N/A * filters by calling adj_filter_list(). 2N/A /* illegal ((case - generated by conversion */ 2N/A /* find missing close) */ 2N/A /* error if not found */ 2N/A /* remove redundant (and) */ 2N/A /* re-start test at original ( */ 2N/A default:
/* assume it's a simple type=value filter */ 2N/A * Put a list of filters like this "(filter1)(filter2)..." 2N/A /* now we have "(filter)" with str pointing to it */ 2N/A * is_valid_attr - returns 1 if a is a syntactically valid left-hand side 2N/A * of a filter expression, 0 otherwise. A valid string may contain only 2N/A * letters, numbers, hyphens, semicolons, colons and periods. examples: 2N/A * 1.2.3.4;binary;dynamic 2N/A * For compatibility with older servers, we also allow underscores in 2N/A * attribute types, even through they are not allowed by the LDAPv3 RFCs. 2N/A rc = -
1;
/* pessimistic */ 2N/A case '<':
/* LDAP_FILTER_LE */ 2N/A case '>':
/* LDAP_FILTER_GE */ 2N/A case '~':
/* LDAP_FILTER_APPROX */ 2N/A case ':':
/* extended filter - v3 only */ 2N/A * extended filter looks like this: 2N/A * [type][':dn'][':'oid]':='value 2N/A * where one of type or :oid is required. 2N/A if (
ftype != 0) {
/* == LDAP_FILTER_PRESENT */ 2N/A * Check in place both LDAPv2 (RFC-1960) and LDAPv3 (hexadecimal) escape 2N/A * sequences within the null-terminated string 'val'. 2N/A * If 'val' contains invalid escape sequences we return -1. 2N/A * Otherwise return 1 2N/A * first try LDAPv3 escape (hexadecimal) sequence 2N/A * LDAPv2 (RFC1960) escape sequence 2N/A }
else if (*s !=
'\\') {
2N/A * convert character 'c' that represents a hexadecimal digit to an integer. 2N/A * if 'c' is not a hexidecimal digit [0-9A-Fa-f], -1 is returned. 2N/A * otherwise the converted value is returned. 2N/A if (c >=
'0' && c <=
'9') {
2N/A if (c >=
'A' && c <=
'F') {
2N/A return (c -
'A' +
10);
2N/A if (c >=
'a' && c <=
'f') {
2N/A return (c -
'a' +
10);
2N/A * Walk filter, remove redundant parentheses in-line 2N/A * verify that the filter is reasonable 2N/A /* Parse filter looking for illegal values */ 2N/A /* end of filter checking */ 2N/A * Set the account management request control that needs to be sent to server. 2N/A * This control is required to get the account management information of 2N/A * a user to do local account checking. 2N/A /* fill in the fields of this new control */ 2N/A * int get_new_acct_more_info(BerElement *ber, 2N/A * AcctUsableResponse_t *acctResp) 2N/A * Decode the more_info data from an Account Management control response, 2N/A * when the account is not usable and when code style is from recent LDAP 2N/A * servers (see below comments for parse_acct_cont_resp_msg() to get more 2N/A * details on coding styles and ASN1 description). 2N/A * Expected BER encoding: {tbtbtbtiti} 2N/A * +b: TRUE if inactive due to account inactivation 2N/A * +b: TRUE if password has been reset 2N/A * +b: TRUE if password is expired 2N/A * +i: contains num of remaining grace, 0 means no grace 2N/A * +i: contains num of seconds before auto-unlock. -1 means acct is locked 2N/A * forever (i.e. until reset) 2N/A * - acctResp is not null and is initialized with default values for the 2N/A * fields in its AcctUsableResp.more_info structure 2N/A * - the ber stream is received in the correct order, per the ASN1 description. 2N/A * We do not check this order and make the asumption that it is correct. 2N/A * Note that the ber stream may not (and will not in most cases) contain 2N/A * Look at what more_info BER element is/are left to be decoded. 2N/A * look at each of them 1 by 1, without checking on their order 2N/A * and possible multi values. 2N/A /* remaining grace */ 2N/A /* seconds before unlock */ 2N/A /* exit the for loop */ 2N/A * int get_old_acct_opt_more_info(BerElement *ber, 2N/A * AcctUsableResponse_t *acctResp) 2N/A * Decode the optional more_info data from an Account Management control 2N/A * response, when the account is not usable and when code style is from LDAP 2N/A * server 5.2p4 (see below comments for parse_acct_cont_resp_msg() to get more 2N/A * details on coding styles and ASN1 description). 2N/A * Expected BER encoding: titi} 2N/A * +i: contains num of remaining grace, 0 means no grace 2N/A * +i: contains num of seconds before auto-unlock. -1 means acct is locked 2N/A * forever (i.e. until reset) 2N/A * - ber is a valid BER element 2N/A * - acctResp is initialized for the fields in its AcctUsableResp.more_info 2N/A /* decode and maybe 3 is following */ 2N/A /* this is a success case, break to exit */ 2N/A }
else {
/* unknown tag */ 2N/A "sec_b4_unlock - 2nd case"));
2N/A default:
/* unknown tag */ 2N/A * **** This function needs to be moved to libldap library **** 2N/A * parse_acct_cont_resp_msg() parses the message received by server according to 2N/A * following format (ASN1 notation): 2N/A * ACCOUNT_USABLE_RESPONSE::= CHOICE { 2N/A * is_available [0] INTEGER, 2N/A * ** seconds before expiration ** 2N/A * is_not_available [1] more_info 2N/A * more_info::= SEQUENCE { 2N/A * inactive [0] BOOLEAN DEFAULT FALSE, 2N/A * reset [1] BOOLEAN DEFAULT FALSE, 2N/A * expired [2] BOOLEAN DEFAULT FALSE, 2N/A * remaining_grace [3] INTEGER OPTIONAL, 2N/A * seconds_before_unlock [4] INTEGER OPTIONAL 2N/A * #define used to make the difference between coding style as done 2N/A * by LDAP server 5.2p4 and newer LDAP servers. There are 4 values: 2N/A * - DS52p4_USABLE: 5.2p4 coding style, account is usable 2N/A * - DS52p4_NOT_USABLE: 5.2p4 coding style, account is not usable 2N/A * - NEW_USABLE: newer LDAP servers coding style, account is usable 2N/A * - NEW_NOT_USABLE: newer LDAP servers coding style, account is not usable 2N/A * An account would be considered not usable if for instance: 2N/A * - it's been made inactive in the LDAP server 2N/A * - or its password was reset in the LDAP server database 2N/A * - or its password expired 2N/A * - or the account has been locked, possibly forever 2N/A /* used for any coding style when account is usable */ 2N/A /* used for 5.2p4 coding style when account is not usable */ 2N/A /* Ldap control is not found */ 2N/A /* Allocate a BER element from the control value and parse it. */ 2N/A /* Ldap decoding error */ 2N/A /* Ldap decoding error */ 2N/A "seconds_before_expiry"));
2N/A /* ber_scanf() succeeded */ 2N/A /* Ldap decoding error */ 2N/A /* ber_scanf() succeeded */ 2N/A /* this is a success case, break to exit */ 2N/A * Look at what optional more_info BER element is/are 2N/A * left to be decoded. 2N/A * Recent LDAP servers won't code more_info data for default 2N/A * values (see above comments on ASN1 description for what 2N/A * fields have default values & what fields are optional). 2N/A * Nothing else to decode; this is valid and we 2N/A * use default values set above. 2N/A "empty, using default values"));
2N/A * Look at what more_info BER element is/are left to 2N/A * internal function for __ns_ldap_getAcctMgmt() 2N/A /* Initialize State machine cookie */ 2N/A /* see if need to follow referrals */ 2N/A /* get the service descriptor - or create a default one */ 2N/A /* Create default service Desc */ 2N/A /* search for entries for this particular uid */ 2N/A /* create the control request */ 2N/A /* Process search */ 2N/A /* Copy results back to user */ 2N/A * __ns_ldap_getAcctMgmt() is called from pam account management stack 2N/A * for retrieving accounting information of users with no user password - 2N/A * eg. rlogin, rsh, etc. This function uses the account management control 2N/A * request to do a search on the server for the user in question. The 2N/A * response control returned from the server is got from the cookie. 2N/A * Input params: username of whose account mgmt information is to be got 2N/A * pointer to hold the parsed account management information 2N/A * Return values: NS_LDAP_SUCCESS on success or appropriate error