/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/*
* DESCRIPTION: Contains dit_access interface support functions.
*/
#include <sys/systeminfo.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/systeminfo.h>
#include <unistd.h>
#include <stdlib.h>
#include <syslog.h>
#include <ndbm.h>
#include <strings.h>
#include <errno.h>
#include "../ldap_util.h"
#include "../ldap_map.h"
#include "../ldap_parse.h"
#include "../ldap_structs.h"
#include "../ldap_val.h"
#include "../ldap_ruleval.h"
#include "../ldap_op.h"
#include "../ldap_attr.h"
#include "../ldap_nisdbquery.h"
#include "../nisdb_mt.h"
#include "shim.h"
#include "yptol.h"
#include "dit_access_utils.h"
/*
* Returns 'map,domain.'
*/
char *
char *objPath;
return (0);
}
return (objPath);
}
/*
* Convert string to __nis_value_t
*/
return (0);
}
return (0);
}
/*
* Null strings or strings with length 0 are treated
* as empty strings with length 1
*/
dsize = 1;
}
}
return (0);
}
return (val);
}
/*
* Returns an array of rule-values corresponding to the
* splitfields.
*/
char *sepset;
/* sf will be non NULL */
*statP = MAP_PARAM_ERROR;
return (0);
}
/* Get the separator list */
/* Initialize rule-value */
rvq = 0;
count = 0;
*statP = MAP_NO_MEMORY;
return (0);
}
while (str) {
/* Loop to check which format matches str */
if (valA == 0) {
/* The format didn't match. Try the next one */
continue;
}
/*
* If we are here means we had a match.
* Each new set of values obtained from the match is
* added to a new rule-value. This is to preserve the
* the distinction between each set.
*/
if (rvq == 0) {
for (j = 0; j < numVals; j++)
return (0);
}
count++;
for (j = 0; j < numVals; j++) {
if (res == -1) {
for (; j < numVals; j++)
return (0);
}
}
/*
* Since we had a match, break out of this loop
* to parse remainder of str
*/
break;
}
/* Didn't find any match, so get out of the loop */
str = 0;
break;
}
/* Skip the separators before looping back */
if (str) {
if (*str == '\0')
break;
}
}
if (str == 0) {
return (0);
}
if (nv != 0)
return (rvq);
}
/*
* Convert the datum to an array of RuleValues
*/
int i, j, k, l, af;
/* At this point, 't' is always non NULL */
/* Initialize rule-value */
return (0);
}
/* Add domainname to rule-value */
rvq)) {
return (0);
}
/* Handle key */
if (key != 0) {
/* Add field=value pair for N2LKEY */
rvq);
/* For readonly, add field=value pair for N2LSEARCHKEY */
}
if (i) {
return (0);
}
/* Add field=value pairs for IP addresses */
/* If key is IPaddress, use preferred format */
} else {
/* If not, use original value for N2LSEARCHIPKEY */
ipaddr = 0;
i = 0;
}
}
if (i) {
return (0);
}
}
/* Handle datum value */
if (value != 0 && t->e) {
/*
* Extract the comment, if any, and add it to
* the rule-value.
*/
if (t->commentChar != '\0') {
/*
* We loop on value->dsize because value->dptr
* may not be NULL-terminated.
*/
if (dptr[i] == t->commentChar) {
valueLen = i;
if (comLen == 0)
break;
return (0);
}
break;
}
}
}
/* Skip trailing whitespaces */
/*
* At this point valueLen is the effective length of
* the data. Convert value into __nis_value_t so that
* we can use the matchMappingItem function to break it
* into fields.
*/
*statP = MAP_NO_MEMORY;
return (0);
}
/* Perform namefield match */
&numVals, 0, 0);
if (valA == 0) {
return (0);
}
/* We don't need val anymore, so free it */
/*
* Since matchMappingItem only returns us an array of
* __nis_value_t's, we need to associate each value
* in the array with the corresponding item name.
* This code assumes that numVals will be less than or
* equal to the number of item names associated with
* the format.
* These name=value pairs are added to rvq.
*/
for (j = 0; j < count; j++) {
break;
}
}
if (*statP == MAP_INTERNAL_ERROR)
break;
/*
* Check if splitField exists for the field.
* Since splitfields are also stored as mapping
* structures, we need to get the hash table entry
* corresponding to the splitfield name
*/
if (*statP == MAP_NO_MEMORY)
break;
if (sf == 0)
continue;
/*
* Process and add splitFields to rule-value rvq
*/
if (subrvq == 0) {
/* statP would have been set */
break;
}
/*
* We merge 'count' rule-values in rvq with 'nr'
* rule-values from subrvq to give us a whopping
* 'count * nr' rule-values
*/
/* Initialize the new rule-value array */
break;
}
for (j = 0, l = 0; j < nr; j++) {
for (k = 0; k < count; k++, l++) {
if ((mergeRuleValue(&newrvq[l],
&rvq[k]) == -1) ||
&newrvq[l],
&subrvq[j]) == -1)) {
for (i = 0; i < numVals; i++)
return (0);
}
}
}
count = l;
}
/* We don't need valA anymore, so free it */
for (i = 0; i < numVals; i++)
return (0);
}
} /* if value */
if (nv != 0)
return (rvq);
}
/*
* Generate name=values pairs for splitfield names
*
* Consider Example:
* nisLDAPnameFields club:
* ("%s %s %s", name, code, members)
* nisLDAPsplitField members:
* ("(%s,%s,%s)", host, user, domain),
* ("%s", group)
* On entry,
* - rv is an array of numVals rule-values each containing
* name=value pairs for names occuring in nisLDAPsplitField.
* (i.e host, user, domain, group)
* - trv contains name=value pairs for names occuring in
* nisLDAPnameFields. (i.e name, code but not members)
*
* For every name in nisLDAPnamefields that is a splitfield,
* this function applies the data in rv to the corresponding
* splitfield formats (accessed thru t), to generate a single
* string value for the corresponding splitfield (members).
* This new name=value pair is then added to trv.
* Besides, any uninitialized namefield names are set to empty strings.
*/
if (trv == 0)
return (MAP_INTERNAL_ERROR);
if (t->e == 0)
return (SUCCESS);
/*
* Procedure:
* - Check each name in nisLDAPnamefield
* - if it's a splifield, construct its value and add it to trv
* - if not, check if it has a value
* - if not, add empty string
*/
if (rv) {
/*
* str will eventually contain the single string
* value for the corresponding splitfield.
* No point initializing str if rv == 0 because
* splitfield cannot be constructed without rv.
* So, only initialized here.
*/
str = 0;
/* Check if it's a splitfield name */
/*
* Return only incase of memory allocation failure.
* The other error case (MAP_NO_MAPPING_EXISTS),
* indicates that the item name is not a splitfieldname
* i.e it's a namefieldname. This case is handled by
* the following if (sf == 0)
*/
if (statP == MAP_NO_MEMORY)
return (statP);
}
if (sf == 0) {
/*
* Not a splitfield name. Verify if it has a value
*/
/* if not, use empty string */
if (res == -1) {
return (MAP_INTERNAL_ERROR);
}
}
/*
* If rv == 0 then sf == 0 so we will continue here
* i.e. does not matter that str is not yet set up.
*/
continue;
}
/* Code to construct a single value */
/* Use the first separator character as the delimiter */
for (j = 0; j < numVals; j++) {
/* sf->numSplits is zero-based */
if (val == 0)
continue;
if (str) {
if (tempstr)
else {
return (MAP_NO_MEMORY);
}
}
if (tempstr)
else {
return (MAP_NO_MEMORY);
}
}
}
}
if (str == 0)
if (res == -1) {
return (MAP_INTERNAL_ERROR);
}
}
return (SUCCESS);
}
/*
* Updates 'rv' with NIS name=value pairs suitable to
* construct datum from namefield information.
* Some part based on createNisPlusEntry (from ldap_nisdbquery.c)
* This code assumes that from a given LDAP entry, applying the
* mapping rules, would give us one or more NIS entries, differing
* only in key.
*/
char *domain) {
/* Initialize default base */
/* Initialize rule-value rvq */
rvq = 0;
count = 0;
/* Add domainname to rule-value */
rv)) {
return (MAP_INTERNAL_ERROR);
}
for (r = 0; r < t->numRulesFromLDAP; r++) {
rl = t->ruleFromLDAP[r];
/* Set escapeFlag if RHS is "dn" to remove escape chars */
== 0) {
}
/* Reset escapeFlag */
if (rval == 0) {
continue;
}
/* Treat as invalid */
continue;
}
if (litem == 0) {
/* This will take care of numItems == 0 */
continue;
}
else
nrq = 1;
} else
nrq = 1;
/* Set splitname if splitfield names are specified */
for (i = 0; i < numItems; i++) {
continue;
for (j = 0; j < t->numColumns; j++) {
break;
}
if (j == t->numColumns)
break;
}
for (j = 0; j < nrq; j++) {
if (splitname == 1) {
/*
* Put every value of splitfieldname in a new
* rule-value. Helps generating splitfields.
*/
if (rvq == 0) {
return (MAP_INTERNAL_ERROR);
}
count++;
}
/* If we run out of values, use empty strings */
len = 0;
} else {
}
if (res != -1)
if (res == -1) {
return (MAP_INTERNAL_ERROR);
}
}
}
rval = 0;
litem = 0;
numItems = 0;
} /* for r < t->numRulesFromLDAP */
if (rvq)
if (verifyIndexMatch(t, 0, rv, 0, 0) == 0)
return (MAP_INDEXLIST_ERROR);
return (statP);
} /* end of buildNISRuleValue */
/*
* Convert rule-value to datum using namefield information
*/
datum *
/* No error yet */
*statP = 0;
/* Return empty datum if no namefield information available */
if (t->e == 0) {
*statP = MAP_NO_MEMORY;
return (value);
}
*statP = MAP_NO_MEMORY;
return (0);
}
/* Strip trailing whitespaces */
if (t->commentChar != '\0' &&
*str != '\0') {
if (cstr) {
}
} else {
}
return (value);
} else {
*statP = MAP_NO_MEMORY;
return (0);
}
}
return (0);
}
datum *
{
int i, j, k;
char *dptr;
char *str;
/* No error yet */
*statP = 0;
return (0);
for (i = 0; i < rv->numColumns; i++) {
continue;
return (0);
*statP = MAP_NO_MEMORY;
return (0);
}
for (j = 0; j < *nv; j++) {
} else {
if (verifyIndexMatch(t, 0, 0,
continue;
}
*statP = MAP_NO_MEMORY;
for (--j; j >= 0; j--)
return (0);
}
/* transliterate key to lowercase */
if (xlate_to_lcase == TRUE) {
/*
* For multi-homed
* entries, skip over
* "YP_MULTI_" prefix.
*/
k = 0;
YPMULTISZ) == 0) {
k = YPMULTISZ;
}
dptr[k] =
(char)tolower(
(int)(uchar_t)
str[k]);
k++;
}
} else {
}
}
}
return (key);
}
}
return (0);
}
/*
* Get the mapping structure corresponding to `map,domain.'
*/
char *mapPath;
/* No error yet */
*statP = 0;
/* Construct map,domain. */
*statP = MAP_NO_MEMORY;
return (0);
}
/* Get the hash table entry for the mapPath */
== 0) {
}
return (t);
}
/*
* Verify at least one key value obtained from DIT matches the search key
* RETURNS: 1 MATCH
* 0 NO MATCH
* -1 NO KEY FOUND
*/
static int
int i, j;
for (i = 0; i < rv->numColumns; i++) {
continue;
return (0);
return (1);
}
return (0);
return (0);
return (1);
}
}
}
return (0);
}
}
return (-1);
}
/*
* Read (i.e get and map) a single NIS entry from the LDAP DIT
*/
int *statP) {
*statP = MAP_PARAM_ERROR;
return (FALSE);
}
/* Get the mapping information for the map */
/*
* No problem. We don't handle this map and domain. Maybe it's
* handled by a service other than NIS.
*/
return (FALSE);
}
/* NULL-terminated version of datum key for logging */
*statP = MAP_NO_MEMORY;
return (FALSE);
}
*statP = MAP_NO_MEMORY;
return (FALSE);
}
/* For each alternate mapping */
for (; t != 0; t = t->next) {
/* Verify objName */
continue;
}
/* Verify if key matches the index */
continue;
/* Check if rulesFromLDAP are provided */
if (t->numRulesFromLDAP == 0) {
"%s: No rulesFromLDAP information available "
continue;
}
/* Convert key into rule-value */
statP)) == 0) {
"%s: Conversion error %d (NIS to name=value "
"pairs) for NIS key (%s) for %s (%s)",
continue;
}
/* Convert rule-value into ldap request */
objectDN);
if (ls == 0) {
"%s: Failed to create ldapSearch "
"request for "
"NIS key (%s) for %s (%s) "
"for base %s",
continue;
}
/* Query LDAP */
if (rv_result == 0) {
if (*statP == LDAP_NO_SUCH_OBJECT) {
/* Entry does not exist in */
/* the ldap server */
}
continue;
}
rv_request = 0;
/* if result > 1, first match will be returned */
if (nr > 1) {
"%s: %d ldapSearch results "
"for NIS key (%s) "
"for %s (%s) for base %s. "
"First match will be returned ",
}
for (i = 0; i < nr; i++) {
/* Convert LDAP data to NIS equivalents */
domain);
if (*statP == MAP_INDEXLIST_ERROR)
continue;
"%s: Conversion error %d (LDAP to "
"name=value pairs) for NIS key (%s) "
"for %s (%s) for base %s", myself,
continue;
}
/*
* Check if 'key' from the ldap result matches the key
* provided by our caller
*/
== -1) {
"%s: Cannot verify key from ldap "
"result for NIS key (%s) for %s (%s) "
"for base %s",
continue;
}
if (rc == 1) {
datval = ruleValueToDatum(t,
if (datval == 0) {
"%s: Conversion error %d "
"(name=value pairs to NIS) "
"for NIS key (%s) for %s (%s)"
" for base %s",
continue;
}
if (value) {
}
rv_result = 0;
/* Free full map name */
return (TRUE);
}
}
rv_result = 0;
} /* end of for over objectDN */
if (rv_request != 0) {
rv_request = 0;
}
if (rv_result != 0) {
rv_result = 0;
}
}
/* Free full map name */
return (FALSE);
}
/*
* Maps and writes a single NIS entry to the LDAP DIT
*/
int
char *dptr;
return (MAP_PARAM_ERROR);
}
/* Return SUCCESS for empty or whitespace key */
return (SUCCESS);
/* Get the mapping information for the map */
/*
* No problem. We don't handle this map and domain. Maybe it's
* handled by a service other than NIS.
*/
return (statP);
}
/* NULL-terminated version of key and value for logging */
return (MAP_NO_MEMORY);
return (MAP_NO_MEMORY);
}
return (MAP_NO_MEMORY);
}
/* For each alternate mapping */
/* Verify objName */
continue;
}
/* Verify if key matches the index */
continue;
/* Check the writespecs */
"%s: No baseDN in writespec. Write disabled "
continue;
}
/* Check if rulesToLDAP are provided */
if (t->numRulesToLDAP == 0) {
"%s: No rulesToLDAP. Write disabled for "
continue;
}
/* Set flag to indicate write is enabled */
flag = 1;
/* Convert key and value into an array of rule-values */
&statP)) == 0) {
"%s: Conversion error %d (NIS to name=value "
"pairs) for NIS data (key=%s, value=%s) "
"for %s (%s)",
/* Free full map name */
return (statP);
}
/* Convert NIS data to LDAP equivalents for each rule-value */
for (i = 0; i < nv; i++) {
/* Verify indexlist with name=value pairs */
if (verifyIndexMatch(t, 0, &rv[i], 0, 0) == 0)
break;
/* Create LDAP request and LDAP name=value pairs */
"%s: Conversion error (name=value pairs"
" to LDAP) for NIS data "
"(key=%s, value=%s) for %s (%s)",
/* Free full map name */
return (MAP_CREATE_LDAP_REQUEST_ERROR);
}
/* printRuleValue(&rv[i]); */
}
/* If i < nv then this alternate mapping isn't the one */
if (i < nv)
continue;
/*
* Merge rule-values with the same DN so that we have
* one ldap write request for each DN
*/
if (frv == 0) {
if (nr == -1) {
"%s: Unable to merge LDAP write "
"requests to same DN for NIS data "
"(key=%s, value=%s) for %s (%s)",
} else if (nr == 0) {
"%s: Cannot generate write DN due to "
"missing information for NIS data "
"(key=%s, value=%s) for %s (%s)",
}
/* Free full map name */
return (statP);
}
/* Write to the LDAP server */
/* ldap add */
} else {
/* ldap modify with addFirst set */
}
/* if we get err=20, collapse and try again */
if (!collapse &&
(rc == LDAP_TYPE_OR_VALUE_EXISTS) &&
"%s: Ignoring values differing "
"in case from NIS data (key=%s,"
" value=%s) for (dn: %s) for "
collapse = 1;
i--;
continue;
}
collapse = 0;
if (rc != LDAP_SUCCESS) {
/* Log error */
"%s: %s error %d (%s) for "
"(dn: %s) for NIS data "
"(key=%s, value=%s) "
"for %s (%s)",
/* Dumping failed call may be useful */
/* printRuleValue(&frv[i]); */
/*
* Return the error code and let wrapper
* sort out if mapping should continue
* or abort.
*/
/* Free full map name */
return (statP);
}
}
}
}
/* Free full map name */
}
int i, j, k, flag;
for (k = 0; k < j; k++) {
continue;
continue;
continue;
flag = 1;
#ifdef ORDER_NOT_IMPORTANT
#else
/* Order needs to be maintained */
j--;
#endif
break;
}
}
}
return (flag);
}
/* ObjectClass lookup table */
static struct {
const char *attrType;
const char *objectClass;
} oc_lookup[] = {
{ "o", "objectclass=organization"},
{ "organizationname", "objectclass=organization"},
{ "2.5.4.10", "objectclass=organization"},
{ "ou", "objectclass=organizationalunit"},
{ "organizationalunitname", "objectclass=organizationalunit"},
{ "2.5.4.11", "objectclass=organizationalunit"},
{ "c", "objectclass=country"},
{ "countryname", "objectclass=country"},
{ "2.5.4.6", "objectclass=country"},
{ "dc", "objectclass=domain"},
{ "domaincomponent", "objectclass=domain"},
{ "0.9.2342.19200300.100.1.25", "objectclass=domain"},
{ "nismapname", "objectclass=nismap"},
{ "1.3.6.1.1.1.1.26", "objectclass=nismap"},
{ "automountmapname", "objectclass=automountmap"},
{ "1.3.6.1.1.1.1.31", "objectclass=automountmap"},
{ 0, 0}
};
/*
* Returns the name of the objectclass to which the object
* represented by the given 'rdn' will most likely belong to.
* The return value is in static memory so it should not be
* freed
*/
const char *
char *attrtype, *p;
int len, i;
/* Skip leading whitespaces */
if (*p == '\0')
return (0);
attrtype = p;
/* Find '=' */
*(p - 1) == '\\')
return (0);
/*
* Skip trailing whitespaces in attrtype
* Don't worry, p won't decrease beyond attrtype
*/
for (--p; *p == ' ' || *p == '\t'; p--);
/* Check length is right */
return (oc_lookup[i].objectClass);
return (0);
}
/*
* Split 'dn' into rdn and parentdn based on the first
* occurrence of unescaped 'comma' or 'semicolon'. rdn
* lies on the LHS while parentdn lies on the RHS of the
* split. If none found, then an empty string ("") is
* assigned to parentdn
*/
int
return (-1);
break;
}
if (*value != '\0') {
*value = '\0';
value++;
} else
value = 0;
if (parentdn) {
return (-1);
}
}
if (rdn)
else
return (1);
}
/*
* FUNCTION : makeNISObject()
*
* DESCRIPTION: Sets up a nis Object in the DIT.
*
* GIVEN :
* Case 1: Both 'domain' and 'dn' are non-NULL
* Create nisDomainObject with the given information
* Case 2: Only 'domain' is non-NULL
* Obtain the 'dn' from the nisLDAPdomainContext list
* Create nisDomainObject with the above information
* Case 3: Only 'dn' is non-NULL
* Create an object with the 'dn'
* Here we guess the objectclass attribute, based on
* oc_lookup table
* Case 4: Both 'domain' and 'dn' are NULL
* Error
*
* RETURNS : SUCCESS = It worked
* FAILURE = There was a problem.
*/
char *val;
return (FAILURE);
/*
* If only 'domain' name is provided, then
* try to find dn from the nisLDAPdomainContext
* list generated by the parser
*/
if (!dn) {
for (i = 0; i < ypDomains.numDomains; i++) {
if (ypDomains.domainLabels[i] == 0)
continue;
== 0) {
break;
}
}
if (!dn)
return (FAILURE);
}
/*
* If only 'dn' is given, then it means that the
* caller simply wants to a create an entry for
* that 'dn'.
*
* If 'domain' is given, then check if the 'dn'
* has already been set up as a nis domain object.
* If not, see if we can make it become one.
*/
if (domain) {
/*
* Check to see if the nis domain object has
* already been set up
*/
"objectclass=*", 0, 0, 0);
if (ls == 0) {
"%s: Unable to create ldapSearch "
return (FAILURE);
}
nr = -1;
if (rc == LDAP_SUCCESS) {
/*
* Yes, nis domain object found. Check
* to see if the domain names match.
* If so, we are done. If not, log
* a warning message, and return SUCCESS.
*/
return (SUCCESS);
} else {
"%s: Entry (dn: %s) already "
"contains a nis domain name "
"(%s). The domain name (%s) "
"is not added.",
return (SUCCESS);
}
} else {
/*
* Entry for the 'dn' exists, but it
* is not a nis domain object yet.
* Add the nisDoamin attribute and
* the nisDomainObject objectclass to
* the entry.
*/
return (FAILURE);
if (addSAttr2RuleValue("nisDomain",
return (FAILURE);
}
"objectclass=nisDomainObject",
0);
if (rc == LDAP_SUCCESS) {
"%s: entry (dn: %s) "
"modified to be an "
"nis domain object",
return (SUCCESS);
} else {
"%s: unable to modify "
"entry (dn: %s) to be "
"a nis domain object: "
"ldapModify error %d (%s)",
return (FAILURE);
}
}
} else { /* search for 'dn' failed */
/*
* It is OK if no such object, otherwise
* log an error.
*/
if (rc != LDAP_NO_SUCH_OBJECT) {
"%s: unable to retrieve "
"entry (dn: %s): "
"ldapSearch error %d (%s)",
return (FAILURE);
}
}
/*
* If the 'dn' is actually the naming context of
* the DIT, we should be able to make it a nis domain
* object without worrying about missing parent
* entries. If unable to add the entry for the 'dn'
* due to missing parent entries, fall through
* to create them and then add the nis domain object.
*/
return (SUCCESS);
else if (add_rc != LDAP_NO_SUCH_OBJECT)
return (FAILURE);
}
/* Create parent */
return (FAILURE);
return (FAILURE);
return (SUCCESS);
}
/* Obtain parentdn */
return (FAILURE);
if (!parentdn) {
return (FAILURE);
}
/* Check if parentdn exists */
"objectclass=*", 0, 0, 0);
if (ls == 0) {
"%s: Unable to create ldapSearch request for "
"parent (dn: %s) of (dn: %s)",
return (FAILURE);
}
nr = -1;
/* Create parent if it doesn't exists */
if (rc == LDAP_NO_SUCH_OBJECT) {
"%s: Unable to create parent (dn: %s) of "
return (FAILURE);
}
}
return (SUCCESS);
}
/*
* FUNCTION : is_fatal_error()
*
* DESCRIPTION: Works out if a failed mapping operation should be retried.
*
* INPUTS : Result code from operation
*
* OUTPUTS : TRUE = Fatal error, don't retry.
* FALSE = Temporary error, retry.
*/
{
if (0 > res)
/* An internal mapping error. Not going to go away. */
return (TRUE);
switch (res) {
case (LDAP_PROTOCOL_ERROR):
case (LDAP_TIMELIMIT_EXCEEDED):
case (LDAP_PARTIAL_RESULTS):
case (LDAP_BUSY):
case (LDAP_UNAVAILABLE):
case (LDAP_UNWILLING_TO_PERFORM):
case (LDAP_OTHER):
case (LDAP_SERVER_DOWN):
case (LDAP_LOCAL_ERROR):
case (LDAP_TIMEOUT):
case (LDAP_NO_MEMORY):
/* Probably worth a retry */
return (FALSE);
default:
return (TRUE);
}
}
/*
* FUNCTION : addNISObject()
*
* DESCRIPTION: Add a nis Object in the DIT.
*
* GIVEN :
* Case 1: 'dn' is NULL
* Error
* Case 2: 'domain' is non-NULL
* Create nisDomainObject with the given information
* Case 3: 'domain' is NULL
* Create an object with the 'dn'
* Here we guess the objectclass attribute, based on
* oc_lookup table
*
* RETURNS : SUCCESS = It worked
* FAILURE = There was a problem. If the ldap add
* operation failed, ldap_rc will be set
* to the ldap error code.
*/
int rc;
if (!dn)
return (FAILURE);
return (FAILURE);
if (ldap_rc)
*ldap_rc = -1;
/*
* Add name=value pairs from RDN. Although this is not required
* for SunOne Directory Server, during openldap interoperabilty
* tests, it was found out that openldap server returned object
* class violation errors if MUST attributes were not specified
* explicitly.
*/
return (FAILURE);
if (objClassAttrs == NULL) {
return (FAILURE);
}
/*
* RDN can be composed of multiple name=value pairs
* concatenated by '+'. Hence, we need to determine each
* pair and add it to 'rv'
*/
if (*value == '+') {
/* Make sure it's not escaped */
/*
* We are at the start of the new
* pair. 'svalue' now contains the
* value for the previous pair. Add
* the previous pair to 'rv'
*/
*value = '\0';
if (svalue &&
== -1) {
return (FAILURE);
}
continue;
}
}
if (*value == '=') {
/*
* 'rdn' now contains the name.
* Whatever follows till the next
* unescaped '+' or '\0' is the
* value for this pair.
*/
*value = '\0';
continue;
}
}
}
/*
* End of String. Add the previous name=value pair to 'rv'
*/
return (FAILURE);
}
} else /* rdn == NULL */
return (FAILURE);
/* Create the entry */
if (domain) {
return (FAILURE);
}
if (!attrs) {
return (FAILURE);
}
} else {
}
if (rc == LDAP_SUCCESS)
"%s: Entry (dn: %s) added to DIT",
else if (rc == LDAP_ALREADY_EXISTS)
/* Treat this as success */
rc = LDAP_SUCCESS;
else
"%s: ldapAdd error %d (%s) for (dn: %s)",
if (ldap_rc)
}