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) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A * DESCRIPTION: Contains dit_access interface support functions. 2N/A * Returns 'map,domain.' 2N/A * Convert string to __nis_value_t 2N/A * Null strings or strings with length 0 are treated 2N/A * as empty strings with length 1 2N/A * Returns an array of rule-values corresponding to the 2N/A /* sf will be non NULL */ 2N/A /* Get the separator list */ 2N/A /* Initialize rule-value */ 2N/A /* Loop to check which format matches str */ 2N/A /* The format didn't match. Try the next one */ 2N/A * If we are here means we had a match. 2N/A * Each new set of values obtained from the match is 2N/A * added to a new rule-value. This is to preserve the 2N/A * the distinction between each set. 2N/A * Since we had a match, break out of this loop 2N/A * to parse remainder of str 2N/A /* Didn't find any match, so get out of the loop */ 2N/A /* Skip the separators before looping back */ 2N/A * Convert the datum to an array of RuleValues 2N/A /* At this point, 't' is always non NULL */ 2N/A /* Initialize rule-value */ 2N/A /* Add domainname to rule-value */ 2N/A /* Add field=value pair for N2LKEY */ 2N/A /* For readonly, add field=value pair for N2LSEARCHKEY */ 2N/A /* Add field=value pairs for IP addresses */ 2N/A /* If key is IPaddress, use preferred format */ 2N/A /* If not, use original value for N2LSEARCHIPKEY */ 2N/A /* Handle datum value */ 2N/A * Extract the comment, if any, and add it to 2N/A * We loop on value->dsize because value->dptr 2N/A * may not be NULL-terminated. 2N/A /* Skip trailing whitespaces */ 2N/A * At this point valueLen is the effective length of 2N/A * the data. Convert value into __nis_value_t so that 2N/A * we can use the matchMappingItem function to break it 2N/A /* Perform namefield match */ 2N/A /* We don't need val anymore, so free it */ 2N/A * Since matchMappingItem only returns us an array of 2N/A * __nis_value_t's, we need to associate each value 2N/A * in the array with the corresponding item name. 2N/A * This code assumes that numVals will be less than or 2N/A * equal to the number of item names associated with 2N/A * These name=value pairs are added to rvq. 2N/A * Check if splitField exists for the field. 2N/A * Since splitfields are also stored as mapping 2N/A * structures, we need to get the hash table entry 2N/A * corresponding to the splitfield name 2N/A * Process and add splitFields to rule-value rvq 2N/A /* statP would have been set */ 2N/A * We merge 'count' rule-values in rvq with 'nr' 2N/A * rule-values from subrvq to give us a whopping 2N/A * 'count * nr' rule-values 2N/A /* Initialize the new rule-value array */ 2N/A for (j = 0, l = 0; j <
nr; j++) {
2N/A /* We don't need valA anymore, so free it */ 2N/A * Generate name=values pairs for splitfield names 2N/A * nisLDAPnameFields club: 2N/A * ("%s %s %s", name, code, members) 2N/A * nisLDAPsplitField members: 2N/A * ("(%s,%s,%s)", host, user, domain), 2N/A * - rv is an array of numVals rule-values each containing 2N/A * name=value pairs for names occuring in nisLDAPsplitField. 2N/A * (i.e host, user, domain, group) 2N/A * - trv contains name=value pairs for names occuring in 2N/A * nisLDAPnameFields. (i.e name, code but not members) 2N/A * For every name in nisLDAPnamefields that is a splitfield, 2N/A * this function applies the data in rv to the corresponding 2N/A * splitfield formats (accessed thru t), to generate a single 2N/A * string value for the corresponding splitfield (members). 2N/A * This new name=value pair is then added to trv. 2N/A * Besides, any uninitialized namefield names are set to empty strings. 2N/A * - Check each name in nisLDAPnamefield 2N/A * - if it's a splifield, construct its value and add it to trv 2N/A * - if not, check if it has a value 2N/A * - if not, add empty string 2N/A * str will eventually contain the single string 2N/A * value for the corresponding splitfield. 2N/A * No point initializing str if rv == 0 because 2N/A * splitfield cannot be constructed without rv. 2N/A * So, only initialized here. 2N/A /* Check if it's a splitfield name */ 2N/A * Return only incase of memory allocation failure. 2N/A * The other error case (MAP_NO_MAPPING_EXISTS), 2N/A * indicates that the item name is not a splitfieldname 2N/A * i.e it's a namefieldname. This case is handled by 2N/A * the following if (sf == 0) 2N/A * Not a splitfield name. Verify if it has a value 2N/A /* if not, use empty string */ 2N/A * If rv == 0 then sf == 0 so we will continue here 2N/A * i.e. does not matter that str is not yet set up. 2N/A /* Code to construct a single value */ 2N/A /* Use the first separator character as the delimiter */ 2N/A /* sf->numSplits is zero-based */ 2N/A * Updates 'rv' with NIS name=value pairs suitable to 2N/A * construct datum from namefield information. 2N/A * This code assumes that from a given LDAP entry, applying the 2N/A * mapping rules, would give us one or more NIS entries, differing 2N/A /* Initialize default base */ 2N/A /* Initialize rule-value rvq */ 2N/A /* Add domainname to rule-value */ 2N/A /* Set escapeFlag if RHS is "dn" to remove escape chars */ 2N/A /* Reset escapeFlag */ 2N/A /* Treat as invalid */ 2N/A /* This will take care of numItems == 0 */ 2N/A /* Set splitname if splitfield names are specified */ 2N/A * Put every value of splitfieldname in a new 2N/A * rule-value. Helps generating splitfields. 2N/A /* If we run out of values, use empty strings */ 2N/A }
/* for r < t->numRulesFromLDAP */ 2N/A}
/* end of buildNISRuleValue */ 2N/A * Convert rule-value to datum using namefield information 2N/A /* Return empty datum if no namefield information available */ 2N/A /* Strip trailing whitespaces */ 2N/A for (j = 0; j < *
nv; j++) {
2N/A for (--j; j >= 0; j--)
2N/A /* transliterate key to lowercase */ 2N/A * entries, skip over 2N/A * "YP_MULTI_" prefix. 2N/A * Get the mapping structure corresponding to `map,domain.' 2N/A /* Construct map,domain. */ 2N/A /* Get the hash table entry for the mapPath */ 2N/A * Verify at least one key value obtained from DIT matches the search key 2N/A * Read (i.e get and map) a single NIS entry from the LDAP DIT 2N/A /* Get the mapping information for the map */ 2N/A * No problem. We don't handle this map and domain. Maybe it's 2N/A * handled by a service other than NIS. 2N/A /* NULL-terminated version of datum key for logging */ 2N/A /* For each alternate mapping */ 2N/A /* Verify objName */ 2N/A /* Verify if key matches the index */ 2N/A /* Check if rulesFromLDAP are provided */ 2N/A "%s: No rulesFromLDAP information available " 2N/A /* Convert key into rule-value */ 2N/A "%s: Conversion error %d (NIS to name=value " 2N/A "pairs) for NIS key (%s) for %s (%s)",
2N/A /* Convert rule-value into ldap request */ 2N/A "%s: Failed to create ldapSearch " 2N/A "NIS key (%s) for %s (%s) " 2N/A /* Entry does not exist in */ 2N/A /* the ldap server */ 2N/A /* if result > 1, first match will be returned */ 2N/A "%s: %d ldapSearch results " 2N/A "for %s (%s) for base %s. " 2N/A "First match will be returned ",
2N/A for (i = 0; i <
nr; i++) {
2N/A /* Convert LDAP data to NIS equivalents */ 2N/A "%s: Conversion error %d (LDAP to " 2N/A "name=value pairs) for NIS key (%s) " 2N/A * Check if 'key' from the ldap result matches the key 2N/A * provided by our caller 2N/A "%s: Cannot verify key from ldap " 2N/A "result for NIS key (%s) for %s (%s) " 2N/A "%s: Conversion error %d " 2N/A "(name=value pairs to NIS) " 2N/A "for NIS key (%s) for %s (%s)" 2N/A /* Free full map name */ 2N/A }
/* end of for over objectDN */ 2N/A /* Free full map name */ 2N/A * Maps and writes a single NIS entry to the LDAP DIT 2N/A /* Return SUCCESS for empty or whitespace key */ 2N/A /* Get the mapping information for the map */ 2N/A * No problem. We don't handle this map and domain. Maybe it's 2N/A * handled by a service other than NIS. 2N/A /* NULL-terminated version of key and value for logging */ 2N/A /* For each alternate mapping */ 2N/A /* Verify objName */ 2N/A /* Verify if key matches the index */ 2N/A /* Check the writespecs */ 2N/A "%s: No baseDN in writespec. Write disabled " 2N/A /* Check if rulesToLDAP are provided */ 2N/A "%s: No rulesToLDAP. Write disabled for " 2N/A /* Set flag to indicate write is enabled */ 2N/A /* Convert key and value into an array of rule-values */ 2N/A "%s: Conversion error %d (NIS to name=value " 2N/A "pairs) for NIS data (key=%s, value=%s) " 2N/A /* Free full map name */ 2N/A /* Convert NIS data to LDAP equivalents for each rule-value */ 2N/A for (i = 0; i <
nv; i++) {
2N/A /* Verify indexlist with name=value pairs */ 2N/A /* Create LDAP request and LDAP name=value pairs */ 2N/A "%s: Conversion error (name=value pairs" 2N/A " to LDAP) for NIS data " 2N/A "(key=%s, value=%s) for %s (%s)",
2N/A /* Free full map name */ 2N/A /* printRuleValue(&rv[i]); */ 2N/A /* If i < nv then this alternate mapping isn't the one */ 2N/A * Merge rule-values with the same DN so that we have 2N/A * one ldap write request for each DN 2N/A "%s: Unable to merge LDAP write " 2N/A "requests to same DN for NIS data " 2N/A "(key=%s, value=%s) for %s (%s)",
2N/A "%s: Cannot generate write DN due to " 2N/A "missing information for NIS data " 2N/A "(key=%s, value=%s) for %s (%s)",
2N/A /* Free full map name */ 2N/A /* Write to the LDAP server */ 2N/A /* ldap modify with addFirst set */ 2N/A /* if we get err=20, collapse and try again */ 2N/A "%s: Ignoring values differing " 2N/A "in case from NIS data (key=%s," 2N/A " value=%s) for (dn: %s) for " 2N/A "%s: %s error %d (%s) for " 2N/A "(dn: %s) for NIS data " 2N/A "(key=%s, value=%s) " 2N/A "ldapModify" :
"ldapAdd",
rc,
2N/A /* Dumping failed call may be useful */ 2N/A /* printRuleValue(&frv[i]); */ 2N/A * Return the error code and let wrapper 2N/A * sort out if mapping should continue 2N/A /* Free full map name */ 2N/A /* Free full map name */ 2N/A for (k = 0; k < j; k++) {
2N/A /* Order needs to be maintained */ 2N/A/* ObjectClass lookup table */ 2N/A {
"o",
"objectclass=organization"},
2N/A {
"organizationname",
"objectclass=organization"},
2N/A {
"2.5.4.10",
"objectclass=organization"},
2N/A {
"ou",
"objectclass=organizationalunit"},
2N/A {
"organizationalunitname",
"objectclass=organizationalunit"},
2N/A {
"2.5.4.11",
"objectclass=organizationalunit"},
2N/A {
"c",
"objectclass=country"},
2N/A {
"countryname",
"objectclass=country"},
2N/A {
"2.5.4.6",
"objectclass=country"},
2N/A {
"dc",
"objectclass=domain"},
2N/A {
"domaincomponent",
"objectclass=domain"},
2N/A {
"0.9.2342.19200300.100.1.25",
"objectclass=domain"},
2N/A {
"nismapname",
"objectclass=nismap"},
2N/A {
"1.3.6.1.1.1.1.26",
"objectclass=nismap"},
2N/A {
"automountmapname",
"objectclass=automountmap"},
2N/A {
"1.3.6.1.1.1.1.31",
"objectclass=automountmap"},
2N/A * Returns the name of the objectclass to which the object 2N/A * represented by the given 'rdn' will most likely belong to. 2N/A * The return value is in static memory so it should not be 2N/A /* Skip leading whitespaces */ 2N/A for (p =
rdn; *p ==
' ' || *p ==
'\t'; p++);
2N/A * Skip trailing whitespaces in attrtype 2N/A * Don't worry, p won't decrease beyond attrtype 2N/A for (--p; *p ==
' ' || *p ==
'\t'; p--);
2N/A /* Check length is right */ 2N/A * Split 'dn' into rdn and parentdn based on the first 2N/A * occurrence of unescaped 'comma' or 'semicolon'. rdn 2N/A * lies on the LHS while parentdn lies on the RHS of the 2N/A * split. If none found, then an empty string ("") is 2N/A * assigned to parentdn 2N/A * FUNCTION : makeNISObject() 2N/A * DESCRIPTION: Sets up a nis Object in the DIT. 2N/A * Case 1: Both 'domain' and 'dn' are non-NULL 2N/A * Create nisDomainObject with the given information 2N/A * Case 2: Only 'domain' is non-NULL 2N/A * Obtain the 'dn' from the nisLDAPdomainContext list 2N/A * Create nisDomainObject with the above information 2N/A * Case 3: Only 'dn' is non-NULL 2N/A * Create an object with the 'dn' 2N/A * Here we guess the objectclass attribute, based on 2N/A * Case 4: Both 'domain' and 'dn' are NULL 2N/A * RETURNS : SUCCESS = It worked 2N/A * FAILURE = There was a problem. 2N/A * If only 'domain' name is provided, then 2N/A * try to find dn from the nisLDAPdomainContext 2N/A * list generated by the parser 2N/A * If only 'dn' is given, then it means that the 2N/A * caller simply wants to a create an entry for 2N/A * If 'domain' is given, then check if the 'dn' 2N/A * has already been set up as a nis domain object. 2N/A * If not, see if we can make it become one. 2N/A * Check to see if the nis domain object has 2N/A * already been set up 2N/A "objectclass=*", 0, 0, 0);
2N/A "%s: Unable to create ldapSearch " 2N/A * Yes, nis domain object found. Check 2N/A * to see if the domain names match. 2N/A * If so, we are done. If not, log 2N/A * a warning message, and return SUCCESS. 2N/A "%s: Entry (dn: %s) already " 2N/A "contains a nis domain name " 2N/A "(%s). The domain name (%s) " 2N/A * Entry for the 'dn' exists, but it 2N/A * is not a nis domain object yet. 2N/A * Add the nisDoamin attribute and 2N/A * the nisDomainObject objectclass to 2N/A "objectclass=nisDomainObject",
2N/A "%s: entry (dn: %s) " 2N/A "modified to be an " 2N/A "nis domain object",
2N/A "%s: unable to modify " 2N/A "entry (dn: %s) to be " 2N/A "a nis domain object: " 2N/A "ldapModify error %d (%s)",
2N/A }
else {
/* search for 'dn' failed */ 2N/A * It is OK if no such object, otherwise 2N/A "%s: unable to retrieve " 2N/A "ldapSearch error %d (%s)",
2N/A * If the 'dn' is actually the naming context of 2N/A * the DIT, we should be able to make it a nis domain 2N/A * object without worrying about missing parent 2N/A * entries. If unable to add the entry for the 'dn' 2N/A * due to missing parent entries, fall through 2N/A * to create them and then add the nis domain object. 2N/A /* Obtain parentdn */ 2N/A /* Check if parentdn exists */ 2N/A "objectclass=*", 0, 0, 0);
2N/A "%s: Unable to create ldapSearch request for " 2N/A "parent (dn: %s) of (dn: %s)",
2N/A /* Create parent if it doesn't exists */ 2N/A "%s: Unable to create parent (dn: %s) of " 2N/A * FUNCTION : is_fatal_error() 2N/A * DESCRIPTION: Works out if a failed mapping operation should be retried. 2N/A * INPUTS : Result code from operation 2N/A * OUTPUTS : TRUE = Fatal error, don't retry. 2N/A * FALSE = Temporary error, retry. 2N/A /* An internal mapping error. Not going to go away. */ 2N/A /* Probably worth a retry */ 2N/A * FUNCTION : addNISObject() 2N/A * DESCRIPTION: Add a nis Object in the DIT. 2N/A * Case 1: 'dn' is NULL 2N/A * Case 2: 'domain' is non-NULL 2N/A * Create nisDomainObject with the given information 2N/A * Case 3: 'domain' is NULL 2N/A * Create an object with the 'dn' 2N/A * Here we guess the objectclass attribute, based on 2N/A * RETURNS : SUCCESS = It worked 2N/A * FAILURE = There was a problem. If the ldap add 2N/A * operation failed, ldap_rc will be set 2N/A * to the ldap error code. 2N/A * Add name=value pairs from RDN. Although this is not required 2N/A * for SunOne Directory Server, during openldap interoperabilty 2N/A * tests, it was found out that openldap server returned object 2N/A * class violation errors if MUST attributes were not specified 2N/A * RDN can be composed of multiple name=value pairs 2N/A * concatenated by '+'. Hence, we need to determine each 2N/A * pair and add it to 'rv' 2N/A /* Make sure it's not escaped */ 2N/A * We are at the start of the new 2N/A * pair. 'svalue' now contains the 2N/A * value for the previous pair. Add 2N/A * the previous pair to 'rv' 2N/A * 'rdn' now contains the name. 2N/A * Whatever follows till the next 2N/A * unescaped '+' or '\0' is the 2N/A * value for this pair. 2N/A * End of String. Add the previous name=value pair to 'rv' 2N/A }
else /* rdn == NULL */ 2N/A /* Create the entry */ 2N/A "%s: Entry (dn: %s) added to DIT",
2N/A /* Treat this as success */ 2N/A "%s: ldapAdd error %d (%s) for (dn: %s)",