예제 #1
0
/*
 * detect if the plugin should handle this entry and return the entry type
 */
int
ipa_topo_check_entry_type(Slapi_Entry *entry)
{
    int ret = TOPO_IGNORE_ENTRY;
    Slapi_DN *add_dn = NULL;
    char **ocs;

    add_dn = slapi_entry_get_sdn(entry);
    if (slapi_sdn_issuffix(add_dn,ipa_topo_get_plugin_shared_topo_dn())) {
        /* check if it is a toplogy or a segment */
        /* check if segment's left or right node is the local server*/
        int i;
        ocs = slapi_entry_attr_get_charray(entry,"objectclass");

        for (i=0; ocs && ocs[i]; i++) {
            if (strcasecmp(ocs[i],"ipaReplTopoConf") == 0) {
		ret = TOPO_CONFIG_ENTRY;
                break;
            } else if (strcasecmp(ocs[i],"ipaReplTopoSegment") == 0) {
		ret = TOPO_SEGMENT_ENTRY;
                break;
            }
        }
    } else if (slapi_sdn_isparent(ipa_topo_get_plugin_shared_hosts_dn(),add_dn)) {
        ret = TOPO_HOST_ENTRY;
    } else if (slapi_sdn_issuffix(add_dn,ipa_topo_get_domain_level_entry_dn())) {
        ret = TOPO_DOMLEVEL_ENTRY;
    }

    return ret;
}
예제 #2
0
int slapi_sdn_scope_test( const Slapi_DN *dn, const Slapi_DN *base, int scope )
{
	int rc;

	switch ( scope ) {
	case LDAP_SCOPE_BASE:
		rc = ( slapi_sdn_compare( dn, base ) == 0 );
		break;
	case LDAP_SCOPE_ONELEVEL:
		rc = slapi_sdn_isparent( base, dn );
		break;
	case LDAP_SCOPE_SUBTREE:
		rc = slapi_sdn_issuffix( dn, base );
		break;
	default:
		rc = 0;
		break;
	}

	return rc;
}
예제 #3
0
파일: config.c 프로젝트: leto/389-ds
/*
  Extract just the configuration information we need for bootstrapping
  purposes
  1) set up error logging
  2) disable syntax checking
  3) load the syntax plugins
  etc.
*/
int
slapd_bootstrap_config(const char *configdir)
{
	char configfile[MAXPATHLEN+1];
    PRFileInfo prfinfo;
    int rc = 0; /* Fail */
	int done = 0;
    PRInt32 nr = 0;
	PRFileDesc *prfd = 0;
	char *buf = 0;
	char *lastp = 0;
	char *entrystr = 0;

	if (NULL == configdir) {
		slapi_log_error(SLAPI_LOG_FATAL,
						"startup", "Passed null config directory\n");
		return rc; /* Fail */
	}
	PR_snprintf(configfile, sizeof(configfile), "%s/%s", configdir,
				CONFIG_FILENAME);
	if ( (rc = PR_GetFileInfo( configfile, &prfinfo )) != PR_SUCCESS )
	{
		/* the "real" file does not exist; see if there is a tmpfile */
		char tmpfile[MAXPATHLEN+1];
		slapi_log_error(SLAPI_LOG_FATAL, "config",
					"The configuration file %s does not exist\n", configfile);
		PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.tmp", configdir,
					CONFIG_FILENAME);
		if ( PR_GetFileInfo( tmpfile, &prfinfo ) == PR_SUCCESS ) {
			rc = PR_Rename(tmpfile, configfile);
			if (rc == PR_SUCCESS) {
				slapi_log_error(SLAPI_LOG_FATAL, "config",
								"The configuration file %s was restored from backup %s\n",
								configfile, tmpfile);
			} else {
				slapi_log_error(SLAPI_LOG_FATAL, "config",
								"The configuration file %s was not restored from backup %s, error %d\n",
								configfile, tmpfile, rc);
				return rc; /* Fail */
			}
		} else {
			slapi_log_error(SLAPI_LOG_FATAL, "config",
				"The backup configuration file %s does not exist, either.\n",
				tmpfile);
			return rc; /* Fail */
		}
	}
	if ( (rc = PR_GetFileInfo( configfile, &prfinfo )) != PR_SUCCESS )
	{
		PRErrorCode prerr = PR_GetError();
		slapi_log_error(SLAPI_LOG_FATAL, "config", "The given config file %s could not be accessed, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
						configfile, prerr, slapd_pr_strerror(prerr));
		return rc;
	}
	else if (( prfd = PR_Open( configfile, PR_RDONLY,
							   SLAPD_DEFAULT_FILE_MODE )) == NULL )
	{
		PRErrorCode prerr = PR_GetError();
		slapi_log_error(SLAPI_LOG_FATAL, "config", "The given config file %s could not be opened for reading, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
						configfile, prerr, slapd_pr_strerror(prerr));
		return rc; /* Fail */
	}
	else
	{
		/* read the entire file into core */
		buf = slapi_ch_malloc( prfinfo.size + 1 );
		if (( nr = slapi_read_buffer( prfd, buf, prfinfo.size )) < 0 )
		{
			slapi_log_error(SLAPI_LOG_FATAL, "config", "Could only read %d of %d bytes from config file %s\n",
							nr, prfinfo.size, configfile);
			rc = 0; /* Fail */
			done= 1;
		}
                          
		(void)PR_Close(prfd);
		buf[ nr ] = '\0';

		if(!done)
		{
			char workpath[MAXPATHLEN+1];
			char loglevel[BUFSIZ];
			char maxdescriptors[BUFSIZ];
			char val[BUFSIZ];
			char _localuser[BUFSIZ];
			char logenabled[BUFSIZ];
			char schemacheck[BUFSIZ];
			char syntaxcheck[BUFSIZ];
			char syntaxlogging[BUFSIZ];
			char plugintracking[BUFSIZ];
			char dn_validate_strict[BUFSIZ];
			Slapi_DN plug_dn;

			workpath[0] = loglevel[0] = maxdescriptors[0] = '\0';
			val[0] = logenabled[0] = schemacheck[0] = syntaxcheck[0] = '\0';
			syntaxlogging[0] = _localuser[0] = '\0';
			plugintracking [0] = dn_validate_strict[0] = '\0';

			/* Convert LDIF to entry structures */
			slapi_sdn_init_ndn_byref(&plug_dn, PLUGIN_BASE_DN);
			while ((entrystr = dse_read_next_entry(buf, &lastp)) != NULL)
			{
				char errorbuf[BUFSIZ];
				/*
				 * XXXmcs: it would be better to also pass
				 * SLAPI_STR2ENTRY_REMOVEDUPVALS in the flags, but
				 * duplicate value checking requires that the syntax
				 * and schema subsystems be initialized... and they
				 * are not yet.
				 */
				Slapi_Entry	*e = slapi_str2entry(entrystr,
							SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF);
				if (e == NULL)
				{
					  LDAPDebug(LDAP_DEBUG_ANY, "The entry [%s] in the configfile %s was empty or could not be parsed\n",
								entrystr, configfile, 0);
					continue;
				}
				/* increase file descriptors */
#if !defined(_WIN32) && !defined(AIX)
				if (!maxdescriptors[0] &&
					entry_has_attr_and_value(e, CONFIG_MAXDESCRIPTORS_ATTRIBUTE,
									 maxdescriptors, sizeof(maxdescriptors)))
				{
					if (config_set_maxdescriptors(
									CONFIG_MAXDESCRIPTORS_ATTRIBUTE,
									maxdescriptors, errorbuf, CONFIG_APPLY)
						!= LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
								  CONFIG_MAXDESCRIPTORS_ATTRIBUTE, errorbuf);
					}
				}
#endif /* !defined(_WIN32) && !defined(AIX) */

				/* see if we need to enable error logging */
				if (!logenabled[0] &&
					entry_has_attr_and_value(e,
											 CONFIG_ERRORLOG_LOGGING_ENABLED_ATTRIBUTE,
											 logenabled, sizeof(logenabled)))
				{
					if (log_set_logging(
						CONFIG_ERRORLOG_LOGGING_ENABLED_ATTRIBUTE,
						logenabled, SLAPD_ERROR_LOG, errorbuf, CONFIG_APPLY)
						!= LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
								  CONFIG_ERRORLOG_LOGGING_ENABLED_ATTRIBUTE, errorbuf);
					}
				}

#ifndef _WIN32
				/* set the local user name; needed to set up error log */
				if (!_localuser[0] &&
					entry_has_attr_and_value(e, CONFIG_LOCALUSER_ATTRIBUTE,
								_localuser, sizeof(_localuser)))
				{
					if (config_set_localuser(CONFIG_LOCALUSER_ATTRIBUTE,
						_localuser, errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s. \n", configfile,
								  CONFIG_LOCALUSER_ATTRIBUTE, errorbuf);
					}
				}
#endif
				
				/* set the log file name */
				workpath[0] = '\0';
				if (!workpath[0] &&
					entry_has_attr_and_value(e, CONFIG_ERRORLOG_ATTRIBUTE,
								workpath, sizeof(workpath)))
				{
					if (config_set_errorlog(CONFIG_ERRORLOG_ATTRIBUTE,
						workpath, errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s. \n", configfile,
								  CONFIG_ERRORLOG_ATTRIBUTE, errorbuf);
					}
				}
				/* set the error log level */
				if (!loglevel[0] &&
					entry_has_attr_and_value(e, CONFIG_LOGLEVEL_ATTRIBUTE,
						loglevel, sizeof(loglevel)))
				{
					if (should_detach || !config_get_errorlog_level())
					{ /* -d wasn't on command line */
						if (config_set_errorlog_level(CONFIG_LOGLEVEL_ATTRIBUTE,
							loglevel, errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
						{
							LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s. \n", configfile,
									  CONFIG_LOGLEVEL_ATTRIBUTE, errorbuf);
						}
					}
					else
					{
						LDAPDebug(LDAP_DEBUG_ANY,
								  "%s: ignoring %s (since -d %d was given on "
								  "the command line)\n",
								  CONFIG_LOGLEVEL_ATTRIBUTE, loglevel,
								  config_get_errorlog_level());
					}
				}

				/* set the cert dir; needed in slapd_nss_init */
				workpath[0] = '\0';
				if (entry_has_attr_and_value(e, CONFIG_CERTDIR_ATTRIBUTE,
						workpath, sizeof(workpath)))
				{
					if (config_set_certdir(CONFIG_CERTDIR_ATTRIBUTE,
							workpath, errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s. \n", configfile,
									  CONFIG_CERTDIR_ATTRIBUTE, errorbuf);
					}
				}

				/* set the sasl path; needed in main */
				 workpath[0] = '\0';
				if (entry_has_attr_and_value(e, CONFIG_SASLPATH_ATTRIBUTE,
						workpath, sizeof(workpath)))
				{
					if (config_set_saslpath(CONFIG_SASLPATH_ATTRIBUTE,
							workpath, errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s. \n", configfile,
									  CONFIG_SASLPATH_ATTRIBUTE, errorbuf);
					}
				}
#if defined(ENABLE_LDAPI)
				/* set the ldapi file path; needed in main */
				workpath[0] = '\0';
				if (entry_has_attr_and_value(e, CONFIG_LDAPI_FILENAME_ATTRIBUTE,
						workpath, sizeof(workpath)))
				{
					if (config_set_ldapi_filename(CONFIG_LDAPI_FILENAME_ATTRIBUTE,
							workpath, errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s. \n", configfile,
									  CONFIG_LDAPI_FILENAME_ATTRIBUTE, errorbuf);
					}
				}

				/* set the ldapi switch; needed in main */
				workpath[0] = '\0';
				if (entry_has_attr_and_value(e, CONFIG_LDAPI_SWITCH_ATTRIBUTE,
						workpath, sizeof(workpath)))
				{
					if (config_set_ldapi_switch(CONFIG_LDAPI_SWITCH_ATTRIBUTE,
							workpath, errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s. \n", configfile,
									  CONFIG_LDAPI_SWITCH_ATTRIBUTE, errorbuf);
					}
				}
#endif
				/* see if the entry is a child of the plugin base dn */
				if (slapi_sdn_isparent(&plug_dn,
									   slapi_entry_get_sdn_const(e)))
				{
					if (entry_has_attr_and_value(e, "objectclass",
												 "nsSlapdPlugin", 0) &&
						(entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE,
												 "syntax", 0) ||
						 entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE,
												  "matchingrule", 0)))
					{
						/* add the syntax/matching scheme rule plugin */
						if (plugin_setup(e, 0, 0, 1))
						{
							LDAPDebug(LDAP_DEBUG_ANY, "The plugin entry [%s] in the configfile %s was invalid\n", slapi_entry_get_dn(e), configfile, 0);
							rc = 0;
							slapi_sdn_done(&plug_dn);
							goto bail;
						}
					}
				}

				/* see if the entry is a grand child of the plugin base dn */
				if (slapi_sdn_isgrandparent(&plug_dn,
											slapi_entry_get_sdn_const(e)))
				{
					if (entry_has_attr_and_value(e, "objectclass",
												 "nsSlapdPlugin", 0) &&
						(	entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE,
												"pwdstoragescheme", 0) ||
							entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE,
												"reverpwdstoragescheme", 0)	) )
					{
						/* add the pwd storage scheme rule plugin */
						if (plugin_setup(e, 0, 0, 1))
						{
							LDAPDebug(LDAP_DEBUG_ANY, "The plugin entry [%s] in the configfile %s was invalid\n", slapi_entry_get_dn(e), configfile, 0);
							rc = 0;
							slapi_sdn_done(&plug_dn);
							goto bail;
						}
					}
				}

				/* see if we need to disable schema checking */
				if (!schemacheck[0] &&
					entry_has_attr_and_value(e, CONFIG_SCHEMACHECK_ATTRIBUTE,
											 schemacheck, sizeof(schemacheck)))
				{
					if (config_set_schemacheck(CONFIG_SCHEMACHECK_ATTRIBUTE,
								schemacheck, errorbuf, CONFIG_APPLY)
								!= LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
								  CONFIG_SCHEMACHECK_ATTRIBUTE, errorbuf);
					}
				}

				/* see if we need to enable plugin binddn tracking */
				if (!plugintracking[0] &&
					entry_has_attr_and_value(e, CONFIG_PLUGIN_BINDDN_TRACKING_ATTRIBUTE,
											 plugintracking, sizeof(plugintracking)))
				{
					if (config_set_plugin_tracking(CONFIG_PLUGIN_BINDDN_TRACKING_ATTRIBUTE,
							plugintracking, errorbuf, CONFIG_APPLY)
								!= LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
								CONFIG_PLUGIN_BINDDN_TRACKING_ATTRIBUTE, errorbuf);
					}
				}

				/* see if we need to enable syntax checking */
				if (!syntaxcheck[0] &&
				    entry_has_attr_and_value(e, CONFIG_SYNTAXCHECK_ATTRIBUTE,
				    syntaxcheck, sizeof(syntaxcheck)))
				{
					if (config_set_syntaxcheck(CONFIG_SYNTAXCHECK_ATTRIBUTE,
					                           syntaxcheck, errorbuf, CONFIG_APPLY)
						                   != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
						          CONFIG_SYNTAXCHECK_ATTRIBUTE, errorbuf);
					}
				}

				/* see if we need to enable syntax warnings */
				if (!syntaxlogging[0] &&
				    entry_has_attr_and_value(e, CONFIG_SYNTAXLOGGING_ATTRIBUTE,
				    syntaxlogging, sizeof(syntaxlogging)))
				{
					if (config_set_syntaxlogging(CONFIG_SYNTAXLOGGING_ATTRIBUTE,
					                          syntaxlogging, errorbuf, CONFIG_APPLY)
					                          != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
						          CONFIG_SYNTAXLOGGING_ATTRIBUTE, errorbuf);
					}
				}

				/* see if we need to enable strict dn validation */
				if (!dn_validate_strict[0] &&
				    entry_has_attr_and_value(e, CONFIG_DN_VALIDATE_STRICT_ATTRIBUTE,
				    dn_validate_strict, sizeof(dn_validate_strict)))
				{
					if (config_set_dn_validate_strict(CONFIG_DN_VALIDATE_STRICT_ATTRIBUTE,
					                           dn_validate_strict, errorbuf, CONFIG_APPLY)
					                           != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
						          CONFIG_DN_VALIDATE_STRICT_ATTRIBUTE, errorbuf);
					}
				}

				/* see if we need to expect quoted schema values */
				if (entry_has_attr_and_value(e, CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE,
											 val, sizeof(val)))
				{
					if (config_set_enquote_sup_oc(
								CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE, val, errorbuf, 
								CONFIG_APPLY) != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
								  CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE, errorbuf);
					}
					val[0] = 0;
				}

				/* see if we need to maintain case in AT and OC names */
				if (entry_has_attr_and_value(e,
						CONFIG_RETURN_EXACT_CASE_ATTRIBUTE, val, sizeof(val)))
				{
					if (config_set_return_exact_case(
								CONFIG_RETURN_EXACT_CASE_ATTRIBUTE, val,
								errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
								  CONFIG_RETURN_EXACT_CASE_ATTRIBUTE, errorbuf);
					}
					val[0] = 0;
				}

				/* see if we should allow attr. name exceptions, e.g. '_'s */
				if (entry_has_attr_and_value(e,
						CONFIG_ATTRIBUTE_NAME_EXCEPTION_ATTRIBUTE,
						val, sizeof(val)))
				{
					if (config_set_attrname_exceptions(
								CONFIG_ATTRIBUTE_NAME_EXCEPTION_ATTRIBUTE, val,
								errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
								  CONFIG_ATTRIBUTE_NAME_EXCEPTION_ATTRIBUTE,
								  errorbuf);
					}
					val[0] = 0;
				}

				/* see if we need to maintain schema compatibility with 4.x */
				if (entry_has_attr_and_value(e,
						CONFIG_DS4_COMPATIBLE_SCHEMA_ATTRIBUTE, val, sizeof(val)))
				{
					if (config_set_ds4_compatible_schema(
								CONFIG_DS4_COMPATIBLE_SCHEMA_ATTRIBUTE, val,
								errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
								  CONFIG_DS4_COMPATIBLE_SCHEMA_ATTRIBUTE,
								  errorbuf);
					}
					val[0] = 0;
				}

				/* see if we need to allow trailing spaces in OC and AT names */
				if (entry_has_attr_and_value(e,
						CONFIG_SCHEMA_IGNORE_TRAILING_SPACES, val, sizeof(val)))
				{
					if (config_set_schema_ignore_trailing_spaces(
								CONFIG_SCHEMA_IGNORE_TRAILING_SPACES, val,
								errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
								  CONFIG_SCHEMA_IGNORE_TRAILING_SPACES,
								  errorbuf);
					}
					val[0] = 0;
				}

				/* rfc1274-rewrite */
				if (entry_has_attr_and_value(e, 
							     CONFIG_REWRITE_RFC1274_ATTRIBUTE,
							     val, sizeof(val))) {
				  if (config_set_rewrite_rfc1274(
								 CONFIG_REWRITE_RFC1274_ATTRIBUTE, val, 
								 errorbuf, CONFIG_APPLY) != LDAP_SUCCESS) {
				    LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", 
					      configfile,
					      CONFIG_REWRITE_RFC1274_ATTRIBUTE, 
					      errorbuf);
				  }
				  val[0] = 0;
				}

				/* what is our localhost name */
				if (entry_has_attr_and_value(e, CONFIG_LOCALHOST_ATTRIBUTE,
											 val, sizeof(val)))
				{
					if (config_set_localhost(
								CONFIG_LOCALHOST_ATTRIBUTE, val, errorbuf, 
								CONFIG_APPLY) != LDAP_SUCCESS)
					{
						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
								  CONFIG_LOCALHOST_ATTRIBUTE, errorbuf);
					}
					val[0] = 0;
				}

				if (e)
					slapi_entry_free(e);
			}
			/* kexcoff: initialize rootpwstoragescheme and pw_storagescheme
			 *			if not explicilty set in the config file
			 */
			if ( config_set_storagescheme() ) {		/* default scheme plugin not loaded */
				slapi_log_error(SLAPI_LOG_FATAL, "startup",
								"The default password storage scheme SSHA could not be read or was not found in the file %s. It is mandatory.\n",
								configfile);
				exit (1);
			}
			else {
				slapi_sdn_done(&plug_dn);
				rc= 1; /* OK */
			}
		}

		slapi_ch_free_string(&buf);
	}

bail:
	slapi_ch_free_string(&buf);
	return rc;
}
예제 #4
0
파일: urp.c 프로젝트: ohamada/389ds
static int
urp_add_resolve_parententry (Slapi_PBlock *pb, char *sessionid, Slapi_Entry *entry, Slapi_Entry *parententry, CSN *opcsn)
{
	Slapi_DN *parentdn = NULL;
	Slapi_RDN *add_rdn = NULL;
	char *newdn = NULL;
	int ldap_rc;
	int rc = 0;
	Slapi_DN *sdn = NULL;

	if( is_suffix_entry (pb, entry, &parentdn) )
	{
		/* It's OK for the suffix entry's parent to be absent */ 
		rc= 0;
		PROFILE_POINT; /* Add Conflict; Suffix Entry */
		goto bailout;
	}

	/* The entry is not a suffix. */
	if(parententry==NULL) /* The parent entry was not found. */
	{
		/* Create a glue entry to stand in for the absent parent */
		slapi_operation_parameters *op_params;
		slapi_pblock_get( pb, SLAPI_OPERATION_PARAMETERS, &op_params );
		ldap_rc = create_glue_entry (pb, sessionid, parentdn, op_params->p.p_add.parentuniqueid, opcsn);
		if ( LDAP_SUCCESS == ldap_rc )
		{
			/* The backend code should now search for the parent again. */
			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY);
			PROFILE_POINT; /* Add Conflict; Orphaned Entry; Glue Parent */
		}
		else
		{
			/*
			 * Error. The parent can't be created as a glue entry.
			 * This will cause replication divergence and will
			 * require admin intercession
			 */
			ldap_rc= LDAP_OPERATIONS_ERROR;
			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_rc);
			rc= -1; /* Abort this Operation */
			PROFILE_POINT; /* Add Conflict; Orphaned Entry; Impossible to create parent; Refuse Change. */
		}
		goto bailout;
	}

	if(is_tombstone_entry(parententry)) /* The parent is a tombstone */
	{
		/* The parent entry must be resurected from the dead. */
		ldap_rc = tombstone_to_glue (pb, sessionid, parententry, parentdn, REASON_RESURRECT_ENTRY, opcsn);
		if ( ldap_rc != LDAP_SUCCESS )
		{
			ldap_rc= LDAP_OPERATIONS_ERROR;
			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_rc);
			rc = -1; /* Abort the operation */
		}
		else
		{
			/* The backend add code should now search for the parent again. */
			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY);
		}
		PROFILE_POINT; /* Add Conflict; Orphaned Entry; Parent Was Tombstone */
		goto bailout;
	}

	/* The parent is healthy */
	/* Now we need to check that the parent has the correct DN */
	if (slapi_sdn_isparent(slapi_entry_get_sdn(parententry), slapi_entry_get_sdn(entry)))
	{
		rc= 0; /* OK, Add the entry */
		PROFILE_POINT; /* Add Conflict; Parent Exists */
		goto bailout;
	}

	/* 
	 * Parent entry doesn't have a DN parent to the entry.
	 * This can happen if parententry was renamed due to
	 * conflict and the child entry was created before
	 * replication occured. See defect 530942.
	 * We need to rename the entry to be child of its parent.
	 */
	add_rdn = slapi_rdn_new_dn(slapi_entry_get_dn_const (entry));
	newdn = slapi_dn_plus_rdn(slapi_entry_get_dn_const (parententry), slapi_rdn_get_rdn(add_rdn));
	slapi_entry_set_normdn ( entry, newdn );

	/* slapi_pblock_get(pb, SLAPI_ADD_TARGET, &dn); */
	slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn);
	slapi_sdn_free(&sdn);

	sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(entry));
	slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, sdn);

	slapi_log_error ( slapi_log_urp, sessionid,
			"Parent was renamed. Renamed the child to %s\n", newdn );
	rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
	PROFILE_POINT; /* Add Conflict; Parent Renamed; Rename Operation Entry */

bailout:
	if (parentdn)
		slapi_sdn_free(&parentdn);
	slapi_rdn_free(&add_rdn);
	return rc;
}