Ejemplo n.º 1
0
static int
agmt_dn_cmp(Object *ro, const void *arg)
{
	Repl_Agmt *ra;
	Slapi_DN *sdn = (Slapi_DN *)arg;

	ra = object_get_data(ro);
	return(slapi_sdn_compare(sdn, agmt_get_dn_byref(ra)));
}
Ejemplo n.º 2
0
int slapi_sdn_isparent( const Slapi_DN *parent, const Slapi_DN *child )
{
	Slapi_DN child_parent;

	slapi_sdn_get_ndn( child );

	slapi_sdn_init( &child_parent );
	dnParent( (struct berval *)&child->ndn, &child_parent.ndn );

	return ( slapi_sdn_compare( parent, &child_parent ) == 0 );
}
Ejemplo n.º 3
0
int slapi_sdn_isgrandparent( const Slapi_DN *parent, const Slapi_DN *child )
{
	Slapi_DN child_grandparent;

	slapi_sdn_get_ndn( child );

	slapi_sdn_init( &child_grandparent );
	dnParent( (struct berval *)&child->ndn, &child_grandparent.ndn );
	if ( child_grandparent.ndn.bv_len == 0 ) {
		return 0;
	}

	dnParent( &child_grandparent.ndn, &child_grandparent.ndn );

	return ( slapi_sdn_compare( parent, &child_grandparent ) == 0 );
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
Object* agmtlist_get_next_agreement_for_replica (Replica *r, Object *prev)
{
    const Slapi_DN *replica_root;
    Slapi_DN *agmt_root;
    Object *obj;
    Repl_Agmt *agmt;

    if (r == NULL)
    {
        /* ONREPL - log error */
        return NULL;
    }

    replica_root = replica_get_root(r);  

    if (prev)
        obj = objset_next_obj(agmt_set, prev);   
    else
        obj = objset_first_obj(agmt_set);
        
    while (obj)
    {
        agmt = (Repl_Agmt*)object_get_data (obj);
        PR_ASSERT (agmt);

        agmt_root = agmt_get_replarea(agmt);
        PR_ASSERT (agmt_root);

        if (slapi_sdn_compare (replica_root, agmt_root) == 0)
        {
            slapi_sdn_free (&agmt_root);
            return obj;
        }

        slapi_sdn_free (&agmt_root);
        obj = objset_next_obj(agmt_set, obj);
    }

    return NULL;
}
Ejemplo n.º 6
0
static int
_ger_g_permission_granted (
	Slapi_PBlock *pb,
	Slapi_Entry *e,
	const char *subjectdn,
	char **errbuf
	)
{
	char *proxydn = NULL;
	Slapi_DN *requestor_sdn, *entry_sdn;
	char *errtext = NULL;
	int isroot;
	int rc;

	/*
	 * Theorically, we should check if the entry has "g"
	 * permission granted to the requestor. If granted,
	 * allows the effective rights on that entry and its
	 * attributes within the entry to be returned for
	 * ANY subject.
	 *
	 * "G" permission granting has not been implemented yet,
	 * the current release assumes that "g" permission be 
	 * granted to root and owner of any entry.
	 */

	/*
	 * The requestor may be either the bind dn or a proxy dn
	 */
	if ((proxyauth_get_dn( pb, &proxydn, &errtext ) == LDAP_SUCCESS) && ( proxydn != NULL ))
	{
		requestor_sdn = slapi_sdn_new_dn_passin ( proxydn );
	}
	else
	{
		slapi_ch_free_string(&proxydn); /* this could still have been set - free it */
		requestor_sdn = &(pb->pb_op->o_sdn);
	}
	if ( slapi_sdn_get_dn (requestor_sdn) == NULL )
	{
		slapi_log_err(SLAPI_LOG_ACL, plugin_name,
				"_ger_g_permission_granted - Anonymous has no g permission\n" );
		rc = LDAP_INSUFFICIENT_ACCESS;
		goto bailout;
	}
	isroot = slapi_dn_isroot ( slapi_sdn_get_dn (requestor_sdn) );
	if ( isroot )
	{
		/* Root has "g" permission on any entry */
		rc = LDAP_SUCCESS;
		goto bailout;
	}

	entry_sdn = slapi_entry_get_sdn ( e );
	if ( entry_sdn == NULL || slapi_sdn_get_dn (entry_sdn) == NULL )
	{
		rc = LDAP_SUCCESS;
		goto bailout;
	}

	if ( slapi_sdn_compare ( requestor_sdn, entry_sdn ) == 0 )
	{
		/* Owner has "g" permission on his own entry */
		rc = LDAP_SUCCESS;
		goto bailout;
	}

	/* if the requestor and the subject user are identical, let's grant it */
	if ( strcasecmp ( slapi_sdn_get_ndn(requestor_sdn), subjectdn ) == 0)
	{
		/* Requestor should see his own permission rights on any entry */
		rc = LDAP_SUCCESS;
		goto bailout;
	}

	aclutil_str_append ( errbuf, "get-effective-rights: requestor has no g permission on the entry" );
	slapi_log_err(SLAPI_LOG_ACL, plugin_name,
				"_ger_g_permission_granted - %s\n", *errbuf);
	rc = LDAP_INSUFFICIENT_ACCESS;

bailout:
	if ( proxydn )
	{
		/* The ownership of proxydn has passed to requestor_sdn */ 
		slapi_sdn_free ( &requestor_sdn );
	}
	return rc;
}
Ejemplo n.º 7
0
/* This function is called to process operation that come over external connections */
void
do_modrdn( Slapi_PBlock *pb )
{
	Slapi_Operation *operation;
	BerElement	*ber;
	char		*rawdn = NULL, *rawnewsuperior = NULL;
	const char	*dn = NULL, *newsuperior = NULL;
	char		*newrdn = NULL;
	int		err = 0, deloldrdn = 0;
	ber_len_t	len = 0;
	char		*newdn = NULL;
	char		*parent = NULL;
	Slapi_DN	sdn;
	Slapi_DN	snewdn;
	Slapi_DN	*snewsuperior = NULL;

	LDAPDebug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );

	/* count the modrdn request */
	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps);

	slapi_pblock_get( pb, SLAPI_OPERATION, &operation);
	ber = operation->o_ber;

	slapi_sdn_init(&sdn);
	slapi_sdn_init(&snewdn);

	/*
	 * Parse the modrdn request.  It looks like this:
	 *
	 *	ModifyRDNRequest := SEQUENCE {
	 *		entry		    DistinguishedName,
	 *		newrdn		    RelativeDistinguishedName,
	 *		deleteoldrdn	    BOOLEAN,
	 *		newSuperior	[0] LDAPDN OPTIONAL -- v3 only
	 *	}
	 */

	if (ber_scanf(ber, "{aab", &rawdn, &newrdn, &deloldrdn) == LBER_ERROR) {
		LDAPDebug( LDAP_DEBUG_ANY,
		    "ber_scanf failed (op=ModRDN; params=DN,newRDN,deleteOldRDN)\n",
		    0, 0, 0 );
		op_shared_log_error_access (pb, "MODRDN", "???", "decoding error");
		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
		    "unable to decode DN, newRDN, or deleteOldRDN parameters",
		    0, NULL );
        goto free_and_return;
	}

	if ( ber_peek_tag( ber, &len ) == LDAP_TAG_NEWSUPERIOR ) {
		/* This "len" is not used... */
		if ( pb->pb_conn->c_ldapversion < LDAP_VERSION3 ) {
			LDAPDebug( LDAP_DEBUG_ANY,
			    "got newSuperior in LDAPv2 modrdn op\n", 0, 0, 0 );
			op_shared_log_error_access (pb, "MODRDN",
										rawdn?rawdn:"", "decoding error");
			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
			    "received newSuperior in LDAPv2 modrdn", 0, NULL );
			slapi_ch_free_string( &rawdn );
			slapi_ch_free_string( &newrdn );
			goto free_and_return;
		}
		if ( ber_scanf( ber, "a", &rawnewsuperior ) == LBER_ERROR ) {
			LDAPDebug( LDAP_DEBUG_ANY,
			    "ber_scanf failed (op=ModRDN; params=newSuperior)\n",
			    0, 0, 0 );
			op_shared_log_error_access (pb, "MODRDN", rawdn, "decoding error");
			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
			    "unable to decode newSuperior parameter", 0, NULL );
			slapi_ch_free_string( &rawdn );
			slapi_ch_free_string( &newrdn );
			goto free_and_return;
		}
	}

	/* Check if we should be performing strict validation. */
	if (config_get_dn_validate_strict()) {
		/* check that the dn is formatted correctly */
		err = slapi_dn_syntax_check(pb, rawdn, 1);
		if (err) { /* syntax check failed */
			op_shared_log_error_access(pb, "MODRDN", rawdn?rawdn:"",
							"strict: invalid dn");
			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
							 NULL, "invalid dn", 0, NULL);
			slapi_ch_free_string( &rawdn );
			slapi_ch_free_string( &newrdn );
			slapi_ch_free_string( &rawnewsuperior );
			goto free_and_return;
		}
		/* check that the new rdn is formatted correctly */
		err = slapi_dn_syntax_check(pb, newrdn, 1);
		if (err) { /* syntax check failed */
			op_shared_log_error_access(pb, "MODRDN", newrdn?newrdn:"", 
							"strict: invalid new rdn");
			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
							 NULL, "invalid new rdn", 0, NULL);
			slapi_ch_free_string( &rawdn );
			slapi_ch_free_string( &newrdn );
			slapi_ch_free_string( &rawnewsuperior );
			goto free_and_return;
		}
	}
	slapi_sdn_init_dn_passin(&sdn, rawdn);
	dn = slapi_sdn_get_dn(&sdn);
	if (rawdn && (strlen(rawdn) > 0) && (NULL == dn)) {
		/* normalization failed */
		op_shared_log_error_access(pb, "MODRDN", rawdn, "invalid dn");
		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, 
		                 "invalid dn", 0, NULL);
		slapi_ch_free_string( &newrdn );
		slapi_ch_free_string( &rawnewsuperior );
		goto free_and_return;
	}

	if (rawnewsuperior) {
		if (config_get_dn_validate_strict()) {
			/* check that the dn is formatted correctly */
			err = slapi_dn_syntax_check(pb, rawnewsuperior, 1);
			if (err) { /* syntax check failed */
				op_shared_log_error_access(pb, "MODRDN", rawnewsuperior,
							"strict: invalid new superior");
				send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
								 NULL, "invalid new superior", 0, NULL);
				slapi_ch_free_string( &rawnewsuperior );
				goto free_and_return;
			}
		}
		snewsuperior = slapi_sdn_new_dn_passin(rawnewsuperior);
		newsuperior = slapi_sdn_get_dn(snewsuperior);
	}

	/*
	 * If newsuperior is myself or my descendent, the modrdn should fail.
	 * Note: need to check the case newrdn is given, and newsuperior
	 * uses the newrdn, as well.
	 */ 
	parent = slapi_dn_parent(slapi_sdn_get_ndn(&sdn));
	newdn = slapi_ch_smprintf("%s,%s", newrdn, parent);
	/* slapi_sdn_init_normdn_passin expects normalized but NOT
	 * decapitalized dn */
	slapi_sdn_init_dn_passin(&snewdn, newdn);
	if (0 == slapi_sdn_compare(&sdn, snewsuperior) ||
	    0 == slapi_sdn_compare(&snewdn, snewsuperior)) {
		op_shared_log_error_access(pb, "MODRDN", newsuperior,
						 "new superior is identical to the entry dn");
		send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
						 "new superior is identical to the entry dn", 0, NULL);
		goto free_and_return;
	}
	if (slapi_sdn_issuffix(snewsuperior, &sdn) ||
	    slapi_sdn_issuffix(snewsuperior, &snewdn)) {
		/* E.g.,
		 * newsuperior: ou=sub,ou=people,dc=example,dc=com
		 * dn: ou=people,dc=example,dc=com
		 */
		op_shared_log_error_access(pb, "MODRDN", newsuperior,
						 "new superior is descendent of the entry");
		send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
						 "new superior is descendent of the entry", 0, NULL);
		goto free_and_return;
	}

	/*
	 * in LDAPv3 there can be optional control extensions on
	 * the end of an LDAPMessage. we need to read them in and
	 * pass them to the backend.
	 */
	if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) {
		op_shared_log_error_access (pb, "MODRDN", dn, "failed to decode LDAP controls");
		send_ldap_result( pb, err, NULL, NULL, 0, NULL );
		goto free_and_return;
	}

	LDAPDebug( LDAP_DEBUG_ARGS,
			   "do_modrdn: dn (%s) newrdn (%s) deloldrdn (%d)\n", dn, newrdn,
			   deloldrdn );

	slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &pb->pb_op->o_isroot );
	/* dn, newrdn and newsuperior are all normalized */
	slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET,
	                  (void *)slapi_sdn_get_udn(&sdn) );
	slapi_pblock_set( pb, SLAPI_MODRDN_TARGET_SDN, &sdn );
	slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN, (void *)newrdn );
	slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, (void *)snewsuperior );
	slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn );

	op_shared_rename(pb, 0 /* do not pass in ownership of string arguments */ );

free_and_return:
	slapi_sdn_done(&sdn);
	slapi_ch_free_string(&newrdn);
	slapi_sdn_free(&snewsuperior);
	slapi_sdn_done(&snewdn);
	slapi_ch_free_string(&parent);

	return;
}
Ejemplo n.º 8
0
/*
 * Read and load configuration.  Validation will also
 * be performed unless skip_validate is set to non-0.
 * Returns PAM_PASSTHRU_SUCCESS if all is well.
 */
int
pam_passthru_load_config(int skip_validate)
{
    int status = PAM_PASSTHRU_SUCCESS;
    int result;
    int i;
    int alternate = 0;
    Slapi_PBlock *search_pb;
    Slapi_Entry **entries = NULL;

    slapi_log_err(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                     "=> pam_passthru_load_config\n");

    pam_passthru_write_lock();
    pam_passthru_delete_config();

    search_pb = slapi_pblock_new();

    /* Find all entries in the active config area. */
    slapi_search_internal_set_pb(search_pb, slapi_sdn_get_ndn(pam_passthru_get_config_area()),
                                 LDAP_SCOPE_SUBTREE, "objectclass=*",
                                 NULL, 0, NULL, NULL,
                                 pam_passthruauth_get_plugin_identity(), 0);
    slapi_search_internal_pb(search_pb);
    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);

    if (LDAP_SUCCESS != result) {
        status = PAM_PASSTHRU_FAILURE;
        goto cleanup;
    }

    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
                     &entries);
    if (NULL == entries || NULL == entries[0]) {
        status = PAM_PASSTHRU_FAILURE;
        goto cleanup;
    }

    /* Check if we are using an alternate config area.  We do this here
     * so we don't have to check each every time in the loop below. */
    if (slapi_sdn_compare(pam_passthru_get_config_area(),
            pam_passthruauth_get_plugin_sdn()) != 0) {
        alternate = 1;
    }

    /* Validate and apply config if valid.  If skip_validate is set, we skip
     * validation and just apply the config.  This should only be done if the
     * configuration has already been validated. */
    for (i = 0; (entries[i] != NULL); i++) {
        /* If this is the alternate config container, skip it since
         * we don't consider it to be an actual config entry. */
        if (alternate && (slapi_sdn_compare(pam_passthru_get_config_area(),
                slapi_entry_get_sdn(entries[i])) == 0)) {
            continue;
        }

        if (skip_validate || (PAM_PASSTHRU_SUCCESS == pam_passthru_validate_config(entries[i], NULL))) {
            if (PAM_PASSTHRU_FAILURE == pam_passthru_apply_config(entries[i])) {
                slapi_log_err(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                                 "pam_passthru_load_config - Unable to apply config "
                                 "for entry \"%s\"\n", slapi_entry_get_ndn(entries[i]));
            }
        } else {
            slapi_log_err(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                             "pam_passthru_load_config - Skipping invalid config "
                             "entry \"%s\"\n", slapi_entry_get_ndn(entries[i]));
        }
    }

  cleanup:
    slapi_free_search_results_internal(search_pb);
    slapi_pblock_destroy(search_pb);
    pam_passthru_unlock();
    slapi_log_err(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                    "<= pam_passthru_load_config\n");

    return status;
}
Ejemplo n.º 9
0
/*
 * Check if we are modifying the config, or changing the shared config entry
 */
int
memberof_shared_config_validate(Slapi_PBlock *pb)
{
	Slapi_Entry *e = 0;
	Slapi_Entry *resulting_e = 0;
	Slapi_Entry *config_entry = NULL;
	Slapi_DN *sdn = NULL;
	Slapi_DN *config_sdn = NULL;
	Slapi_Mods *smods = 0;
	Slapi_Mod *smod = NULL, *nextmod = NULL;
	LDAPMod **mods = NULL;
	char returntext[SLAPI_DSE_RETURNTEXT_SIZE];
	char *configarea_dn = NULL;
	int ret = SLAPI_PLUGIN_SUCCESS;

	slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);

	if (slapi_sdn_compare(sdn, memberof_get_plugin_area()) == 0 ||
	    slapi_sdn_compare(sdn, memberof_get_config_area()) == 0)
	{
		slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &e);
		if(e){
			/*
			 * Create a copy of the entry and apply the
			 * mods to create the resulting entry.
			 */
			slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
			smods = slapi_mods_new();
			slapi_mods_init_byref(smods, mods);
			resulting_e = slapi_entry_dup(e);
			if (mods && (slapi_entry_apply_mods(resulting_e, mods) != LDAP_SUCCESS)) {
				/* we don't care about this, the update is invalid and will be caught later */
				goto bail;
			}

			if (slapi_sdn_compare(sdn, memberof_get_plugin_area())){
				/*
				 * This entry is a plugin config area entry, validate it.
				 */
				if( SLAPI_DSE_CALLBACK_ERROR == memberof_validate_config (pb, NULL, resulting_e, &ret, returntext,0)) {
					ret = LDAP_UNWILLING_TO_PERFORM;
				}
			} else {
				/*
				 * This is the memberOf plugin entry, check if we are adding/replacing the
				 * plugin config area.
				 */
				nextmod = slapi_mod_new();
				for (smod = slapi_mods_get_first_smod(smods, nextmod);
					 smod != NULL;
					 smod = slapi_mods_get_next_smod(smods, nextmod) )
				{
					if ( PL_strcasecmp(SLAPI_PLUGIN_SHARED_CONFIG_AREA, slapi_mod_get_type(smod)) == 0 )
					{
						/*
						 * Okay, we are modifying the plugin config area, we only care about
						 * adds and replaces.
						 */
						if(SLAPI_IS_MOD_REPLACE(slapi_mod_get_operation(smod)) ||
						   SLAPI_IS_MOD_ADD(slapi_mod_get_operation(smod)))
						{
						    struct berval *bv = NULL;
						    int rc = 0;

							bv = slapi_mod_get_first_value(smod);
							configarea_dn = slapi_ch_strdup(bv->bv_val);
							if(configarea_dn){
								/* Check the DN syntax */
								rc = slapi_dn_syntax_check(pb, configarea_dn, 1);
								if (rc) { /* syntax check failed */
									PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
										"%s does not contain a valid DN (%s)",
										SLAPI_PLUGIN_SHARED_CONFIG_AREA, configarea_dn);
									ret = LDAP_UNWILLING_TO_PERFORM;
									goto bail;
								}

								/* Check if the plugin config area entry exists */
								if((config_sdn = slapi_sdn_new_dn_byval(configarea_dn))){
									rc = slapi_search_internal_get_entry(config_sdn, NULL, &config_entry,
										memberof_get_plugin_id());
									if(config_entry){
										int err = 0;
										/*
										 * Validate the settings from the new config area.
										 */
										if ( memberof_validate_config(pb, NULL, config_entry, &err, returntext,0)
											 == SLAPI_DSE_CALLBACK_ERROR )
										{
											ret = LDAP_UNWILLING_TO_PERFORM;
											goto bail;

										}
									} else {
										/* The config area does not exist */
										PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
											"Unable to locate shared config entry (%s) error %d",
											slapi_sdn_get_dn(memberof_get_config_area()), rc);
										ret = LDAP_UNWILLING_TO_PERFORM;
										goto bail;
									}
								}
							}
							slapi_ch_free_string(&configarea_dn);
							slapi_sdn_free(&config_sdn);
						}
					}
				}
			}
		} else {
			PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,"Unable to locate shared config entry (%s)",
				slapi_sdn_get_dn(memberof_get_config_area()));
			ret = LDAP_UNWILLING_TO_PERFORM;
		}
   	}

bail:

	if (ret){
		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ret);
		slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, returntext);
		slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_shared_config_validate - %s/n",
			returntext);
	}
	slapi_sdn_free(&config_sdn);
	if(nextmod)
		slapi_mod_free(&nextmod);
	slapi_mods_free(&smods);
	slapi_entry_free(resulting_e);
	slapi_entry_free(config_entry);
	slapi_ch_free_string(&configarea_dn);

	return ret;
}
Ejemplo n.º 10
0
/*
 * memberof_validate_config()
 *
 * Validate the pending changes in the e entry.
 */
int
memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, 
	int *returncode, char *returntext, void *arg)
{
	Slapi_Attr *memberof_attr = NULL;
	Slapi_Attr *group_attr = NULL;
	Slapi_DN *config_sdn = NULL;
	Slapi_DN **include_dn = NULL;
	Slapi_DN **exclude_dn = NULL;
	char *syntaxoid = NULL;
	char *config_dn = NULL;
	char *skip_nested = NULL;
	char *auto_add_oc = NULL;
	char **entry_scopes = NULL;
	char **entry_exclude_scopes = NULL;
	int not_dn_syntax = 0;
	int num_vals = 0;

	*returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */

	/* Make sure both the group attr and the memberOf attr
	 * config atributes are supplied.  We don't care about &attr
	 * here, but slapi_entry_attr_find() requires us to pass it. */
	if (!slapi_entry_attr_find(e, MEMBEROF_GROUP_ATTR, &group_attr) &&
		!slapi_entry_attr_find(e, MEMBEROF_ATTR, &memberof_attr))
	{
		Slapi_Attr *test_attr = NULL;
		Slapi_Value *value = NULL;
		int hint = 0;

		/* Loop through each group attribute to see if the syntax is correct. */
		hint = slapi_attr_first_value(group_attr, &value);
		while (value && (not_dn_syntax == 0))
		{
			/* We need to create an attribute to find the syntax. */
			test_attr = slapi_attr_new();
			slapi_attr_init(test_attr, slapi_value_get_string(value));

			/* Get the syntax OID and see if it's the Distinguished Name or
			 * Name and Optional UID syntax. */
			slapi_attr_get_syntax_oid_copy(test_attr, &syntaxoid );
			not_dn_syntax = strcmp(syntaxoid, DN_SYNTAX_OID) & strcmp(syntaxoid, NAME_OPT_UID_SYNTAX_OID);
			slapi_ch_free_string(&syntaxoid);

			/* Print an error if the current attribute is not using the Distinguished
			 * Name syntax, otherwise get the next group attribute. */
			if (not_dn_syntax)
			{
				PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
					"The %s configuration attribute must be set to "
					"an attribute defined to use either the Distinguished "
					"Name or Name and Optional UID syntax. (illegal value: %s)",
					slapi_value_get_string(value), MEMBEROF_GROUP_ATTR);
			}
			else
			{
				hint = slapi_attr_next_value(group_attr, hint, &value);
			}

			/* Free the group attribute. */
			slapi_attr_free(&test_attr);
		}

		if (not_dn_syntax == 0)
		{
			/* Check the syntax of the memberof attribute. */
			slapi_attr_first_value(memberof_attr, &value);
			test_attr = slapi_attr_new();
			slapi_attr_init(test_attr, slapi_value_get_string(value));
			slapi_attr_get_syntax_oid_copy(test_attr, &syntaxoid );
			not_dn_syntax = strcmp(syntaxoid, DN_SYNTAX_OID);
			slapi_ch_free_string(&syntaxoid);
			slapi_attr_free(&test_attr);

			if (not_dn_syntax)
			{
				PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
					"The %s configuration attribute must be set to "
					"an attribute defined to use the Distinguished "
					"Name syntax.  (illegal value: %s)",
					slapi_value_get_string(value), MEMBEROF_ATTR);
				goto done;
			}
			else
			{
				*returncode = LDAP_SUCCESS;
			}
		}
	} else {
		PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
			"The %s and %s configuration attributes must be provided",
			MEMBEROF_GROUP_ATTR, MEMBEROF_ATTR); 
		goto done;
	}

	if ((skip_nested = slapi_entry_attr_get_charptr(e, MEMBEROF_SKIP_NESTED_ATTR))){
		if(strcasecmp(skip_nested, "on") != 0 && strcasecmp(skip_nested, "off") != 0){
			PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
				"The %s configuration attribute must be set to "
				"\"on\" or \"off\".  (illegal value: %s)",
				MEMBEROF_SKIP_NESTED_ATTR, skip_nested);
			goto done;
		}
	}

	if ((auto_add_oc = slapi_entry_attr_get_charptr(e, MEMBEROF_AUTO_ADD_OC))){
		char *sup = NULL;

		/* Check if the objectclass exists by looking for its superior oc */
		if((sup = slapi_schema_get_superior_name(auto_add_oc)) == NULL){
			PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
				"The %s configuration attribute must be set to "
				"to an existing objectclass  (unknown: %s)",
				MEMBEROF_AUTO_ADD_OC, auto_add_oc);
			*returncode = LDAP_UNWILLING_TO_PERFORM;
			goto done;
		} else {
			slapi_ch_free_string(&sup);
		}
	}

	if ((config_dn = slapi_entry_attr_get_charptr(e, SLAPI_PLUGIN_SHARED_CONFIG_AREA))){
		/* Now check the shared config attribute, validate it now */

		Slapi_Entry *e = NULL;
		int rc = 0;

		rc = slapi_dn_syntax_check(pb, config_dn, 1);
		if (rc) { /* syntax check failed */
			slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_validate_config - "
					"%s does not contain a valid DN (%s)\n",
					SLAPI_PLUGIN_SHARED_CONFIG_AREA, config_dn);
			*returncode = LDAP_INVALID_DN_SYNTAX;
			goto done;
		}
		config_sdn = slapi_sdn_new_dn_byval(config_dn);

		slapi_search_internal_get_entry(config_sdn, NULL, &e, memberof_get_plugin_id());
		if(e){
			slapi_entry_free(e);
			*returncode = LDAP_SUCCESS;
		} else {
			/* config area does not exist! */
			PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
								"The %s configuration attribute points to an entry that  "
								"can not be found.  (%s)",
								SLAPI_PLUGIN_SHARED_CONFIG_AREA, config_dn);
			*returncode = LDAP_UNWILLING_TO_PERFORM;
		}
	}
	/*
	 * Check the entry scopes
	 */
	entry_scopes = slapi_entry_attr_get_charray_ext(e, MEMBEROF_ENTRY_SCOPE_ATTR, &num_vals);
	if(entry_scopes){
		int i = 0;

		/* Validate the syntax before we create our DN array */
		for (i = 0;i < num_vals; i++){
			if(slapi_dn_syntax_check(pb, entry_scopes[i], 1)){
				/* invalid dn syntax */
				PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
					"%s: Invalid DN (%s) for include suffix.",
					MEMBEROF_PLUGIN_SUBSYSTEM, entry_scopes[i]);
				slapi_ch_array_free(entry_scopes);
				entry_scopes = NULL;
				theConfig.entryScopeCount = 0;
				*returncode = LDAP_UNWILLING_TO_PERFORM;
				goto done;
			}
		}
		/* Now create our SDN array for conflict checking */
		include_dn = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *), num_vals+1);
		for (i = 0;i < num_vals; i++){
			include_dn[i] = slapi_sdn_new_dn_passin(entry_scopes[i]);
		}
	}
	/*
	 * Check and process the entry exclude scopes
	 */
	entry_exclude_scopes =
		slapi_entry_attr_get_charray_ext(e, MEMBEROF_ENTRY_SCOPE_EXCLUDE_SUBTREE, &num_vals);
	if(entry_exclude_scopes){
		int i = 0;

		/* Validate the syntax before we create our DN array */
		for (i = 0;i < num_vals; i++){
			if(slapi_dn_syntax_check(pb, entry_exclude_scopes[i], 1)){
				/* invalid dn syntax */
				PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
					"%s: Invalid DN (%s) for exclude suffix.",
					MEMBEROF_PLUGIN_SUBSYSTEM, entry_exclude_scopes[i]);
				slapi_ch_array_free(entry_exclude_scopes);
				entry_exclude_scopes = NULL;
				*returncode = LDAP_UNWILLING_TO_PERFORM;
				goto done;
			}
		}
		/* Now create our SDN array for conflict checking */
		exclude_dn = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),num_vals+1);
		for (i = 0;i < num_vals; i++){
			exclude_dn[i] = slapi_sdn_new_dn_passin(entry_exclude_scopes[i]);
		}
	}
	/*
	 * Need to do conflict checking
	 */
	if(include_dn && exclude_dn){
		/*
		 * Make sure we haven't mixed the same suffix, and there are no
		 * conflicts between the includes and excludes
		 */
		int i = 0;

		while(include_dn[i]){
			int x = 0;
			while(exclude_dn[x]){
				if(slapi_sdn_compare(include_dn[i], exclude_dn[x] ) == 0)
				{
					/* we have a conflict */
					PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
						"%s: include suffix (%s) is also listed as an exclude suffix list",
						MEMBEROF_PLUGIN_SUBSYSTEM, slapi_sdn_get_dn(include_dn[i]));
					*returncode = LDAP_UNWILLING_TO_PERFORM;
					goto done;
			   }
			   x++;
			}
			i++;
		}

		/* Check for parent/child conflicts */
		i = 0;
		while(include_dn[i]){
			int x = 0;
			while(exclude_dn[x]){
				if(slapi_sdn_issuffix(include_dn[i], exclude_dn[x]))
				{
					/* we have a conflict */
					PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
						"%s: include suffix (%s) is a child of the exclude suffix(%s)",
						MEMBEROF_PLUGIN_SUBSYSTEM,
						slapi_sdn_get_dn(include_dn[i]),
						slapi_sdn_get_dn(exclude_dn[i]));
					*returncode = LDAP_UNWILLING_TO_PERFORM;
					goto done;
			   }
			   x++;
			}
			i++;
		}
	}

done:
	memberof_free_scope(exclude_dn, &num_vals);
	memberof_free_scope(include_dn,	&num_vals);
	slapi_ch_free((void**)&entry_scopes);
	slapi_ch_free((void**)&entry_exclude_scopes);
	slapi_sdn_free(&config_sdn);
	slapi_ch_free_string(&config_dn);
	slapi_ch_free_string(&skip_nested);
	slapi_ch_free_string(&auto_add_oc);

	if (*returncode != LDAP_SUCCESS)
	{
		return SLAPI_DSE_CALLBACK_ERROR;
	}
	else
	{
		return SLAPI_DSE_CALLBACK_OK;
	}
}
Ejemplo n.º 11
0
static int
updatedn_compare_dns(const void *d1, const void *d2)
{
	return (0 == slapi_sdn_compare((const Slapi_DN *)d1, (const Slapi_DN *)d2));
}
Ejemplo n.º 12
0
Archivo: uid.c Proyecto: ohamada/389ds
static int
search_one_berval(Slapi_DN *baseDN, const char *attrName,
		const struct berval *value, const char *requiredObjectClass,
		Slapi_DN *target)
{
	int result;
    char *filter;
    Slapi_PBlock *spb;

	result = LDAP_SUCCESS;

	/* If no value, can't possibly be a conflict */
	if ( (struct berval *)NULL == value )
		return result;

    filter = 0;
    spb = 0;

    BEGIN
      int err;
      int sres;
      Slapi_Entry **entries;
      static char *attrs[] = { "1.1", 0 };

      /* Create the filter - this needs to be freed */
      filter = create_filter(attrName, value, requiredObjectClass);

#ifdef DEBUG
      slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name,
        "SEARCH filter=%s\n", filter);
#endif

      /* Perform the search using the new internal API */
      spb = slapi_pblock_new();
      if (!spb) { result = uid_op_error(2); break; }

      slapi_search_internal_set_pb_ext(spb, baseDN, LDAP_SCOPE_SUBTREE,
      	filter, attrs, 0 /* attrs only */, NULL, NULL, plugin_identity, 0 /* actions */);
      slapi_search_internal_pb(spb);

      err = slapi_pblock_get(spb, SLAPI_PLUGIN_INTOP_RESULT, &sres);
      if (err) { result = uid_op_error(3); break; }
    
      /* Allow search to report that there is nothing in the subtree */
      if (sres == LDAP_NO_SUCH_OBJECT) break;

      /* Other errors are bad */
      if (sres) { result = uid_op_error(3); break; }

      err = slapi_pblock_get(spb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
              &entries);
      if (err) { result = uid_op_error(4); break; }

      /*
       * Look at entries returned.  Any entry found must be the
       * target entry or the constraint fails.
       */
      for(;*entries;entries++)
      {
#ifdef DEBUG
        slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name,
                        "SEARCH entry dn=%s\n", slapi_entry_get_dn(*entries));
#endif

        /*
         * It is a Constraint Violation if any entry is found, unless
         * the entry is the target entry (if any).
         */
        if (!target || slapi_sdn_compare(slapi_entry_get_sdn(*entries), target) != 0)
        {
          result = LDAP_CONSTRAINT_VIOLATION;
          break;
        }
      }

#ifdef DEBUG
      slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name,
        "SEARCH complete result=%d\n", result);
#endif
    END

    /* Clean-up */
    if (spb) {
	slapi_free_search_results_internal(spb);
	slapi_pblock_destroy(spb);
    }

    slapi_ch_free((void**)&filter);

  return result;
}
Ejemplo n.º 13
0
Archivo: urp.c Proyecto: ohamada/389ds
/*
 * Return 0 for OK, -1 for Error, >0 for action code
 * Action Code Bit 0: Fetch existing entry.
 * Action Code Bit 1: Fetch parent entry.
 */
int
urp_modrdn_operation( Slapi_PBlock *pb )
{
	slapi_operation_parameters *op_params = NULL;
	Slapi_Entry *parent_entry;
	Slapi_Entry *new_parent_entry;
	Slapi_DN *newsuperior = NULL;
	Slapi_DN *parentdn = NULL;
	const Slapi_Entry *target_entry;
	Slapi_Entry *existing_entry;
	const CSN *target_entry_dncsn;
	CSN *opcsn= NULL;
	char *op_uniqueid = NULL;
	const char *existing_uniqueid = NULL;
	const Slapi_DN *target_sdn;
	const Slapi_DN *existing_sdn;
	char *newrdn;
	char sessionid[REPL_SESSION_ID_SIZE];
	int r;
	int op_result= 0;
	int rc= 0; /* OK */
	int del_old_replconflict_attr = 0;

	if ( slapi_op_abandoned(pb) )
	{
		return rc;
	}

	slapi_pblock_get (pb, SLAPI_MODRDN_TARGET_ENTRY, &target_entry);
	if(target_entry==NULL)
	{
		/* An entry can't be found for the Unique Identifier */
		op_result= LDAP_NO_SUCH_OBJECT;
		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
		rc= -1; /* No entry to modrdn */
		PROFILE_POINT; /* ModRDN Conflict; Entry does not Exist; Discard ModRDN */
		goto bailout;
	}

	get_repl_session_id (pb, sessionid, &opcsn);
	target_entry_dncsn = entry_get_dncsn (target_entry);
	if ( csn_compare (target_entry_dncsn, opcsn) >= 0 )
	{
		/*
		 * The Operation CSN is not newer than the DN CSN.
		 * Either we're beaten by another ModRDN or we've applied the op.
		 */
		/* op_result= LDAP_SUCCESS; */
		/* 
		 * This operation won't be replayed.  That is, this CSN won't update
		 * the max csn in RUV. The CSN is left uncommitted in RUV unless an
		 * error is set to op_result.  Just to get rid of this CSN from RUV,
		 * setting an error to op_result
		 */
		slapi_log_error(slapi_log_urp, sessionid,
		           "urp_modrdn (%s): operation CSN is newer than the DN CSN.\n",
		           slapi_entry_get_dn_const(target_entry));
		op_result= LDAP_UNWILLING_TO_PERFORM;
		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
		rc = SLAPI_PLUGIN_NOOP; /* Ignore the modrdn */
		PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists; OPCSN is not newer. */
		goto bailout;
	}

	/* The DN CSN is older than the Operation CSN. Apply the operation */
	target_sdn = slapi_entry_get_sdn_const (target_entry);
	/* newrdn is no need to be case-ignored (get_rdn_plus_uniqueid) */
	slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
	slapi_pblock_get(pb, SLAPI_TARGET_UNIQUEID, &op_uniqueid);
	slapi_pblock_get(pb, SLAPI_MODRDN_PARENT_ENTRY, &parent_entry);
	slapi_pblock_get(pb, SLAPI_MODRDN_NEWPARENT_ENTRY, &new_parent_entry);
	slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperior);

	if ( is_tombstone_entry (target_entry) )
	{
		/*
		 * It is a non-trivial task to rename a tombstone.
		 * This op has been ignored so far by 
		 * setting SLAPI_RESULT_CODE to LDAP_NO_SUCH_OBJECT
		 * and rc to -1.
		 */

		/* Turn the tombstone to glue before rename it */
		/*
		op_result = tombstone_to_glue (pb, sessionid, target_entry,
			slapi_entry_get_sdn (target_entry), "renameTombstone", opcsn);
		*/
		op_result = LDAP_NO_SUCH_OBJECT;
		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
		if (op_result == 0)
		{
			/*
			 * Remember to turn this entry back to tombstone in post op.
			 * We'll just borrow an obsolete pblock type here.
			 */
			slapi_pblock_set (pb, SLAPI_URP_TOMBSTONE_UNIQUEID, slapi_ch_strdup(op_uniqueid));
			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_TARGET_ENTRY);
			rc = 0;
		}
		else
		{
			slapi_log_error(slapi_log_urp, sessionid,
			                "urp_modrdn (%s): target entry is a tombstone.\n",
			                slapi_entry_get_dn_const(target_entry));
			rc = SLAPI_PLUGIN_NOOP; /* Ignore the modrdn */
		}
		PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists; OPCSN is not newer. */
		goto bailout;
	}

	slapi_pblock_get(pb, SLAPI_MODRDN_EXISTING_ENTRY, &existing_entry);
	if(existing_entry!=NULL) 
	{
	    /*
	     * An entry with the target DN already exists.
	     * The smaller dncsn wins. The loser changes its RDN to
	     * uniqueid+baserdn, and adds operational attribute
	     * ATTR_NSDS5_REPLCONFLIC
	     */

		existing_uniqueid = slapi_entry_get_uniqueid (existing_entry);
		existing_sdn = slapi_entry_get_sdn_const ( existing_entry);

		/*
		 * It used to dismiss the operation if the existing entry is 
		 * the same as the target one.
		 * But renaming the RDN with the one which only cases are different,
		 * cn=ABC --> cn=Abc, this case matches.  We should go forward the op.
		 */
		if (strcmp(op_uniqueid, existing_uniqueid) == 0) {
			op_result= LDAP_SUCCESS;
			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
			rc = 0; /* Don't ignore the op */
			PROFILE_POINT; /* ModRDN Replay */
			goto bailout;
		}

		r= csn_compare ( entry_get_dncsn (existing_entry), opcsn);
		if (r == 0)
		{
			/*
			 * The CSN of the Operation and the Entry DN are the same
			 * but the uniqueids are not.
			 * There might be two replicas with the same ReplicaID.
			 */
			slapi_log_error(slapi_log_urp, sessionid,
				"urp_modrdn: Duplicated CSN for different uniqueids [%s][%s]",
				existing_uniqueid, op_uniqueid);
			op_result= LDAP_OPERATIONS_ERROR;
			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
			rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
			PROFILE_POINT; /* ModRDN Conflict; Duplicated CSN for Different Entries */
			goto bailout;
		}

		if(r<0)
		{
			/* The target entry is a loser */

			char *newrdn_with_uniqueid;
			newrdn_with_uniqueid= get_rdn_plus_uniqueid (sessionid, newrdn, op_uniqueid);
			if(newrdn_with_uniqueid==NULL)
			{
				op_result= LDAP_OPERATIONS_ERROR;
				slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
				rc= -1; /* Ignore this Operation */
				PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists;
								  Unique ID already in RDN - Change to Lost and Found entry */
				goto bailout;
			}
			mod_namingconflict_attr (op_uniqueid, target_sdn, existing_sdn, opcsn);
			slapi_pblock_set(pb, SLAPI_MODRDN_NEWRDN, newrdn_with_uniqueid); 
			slapi_log_error(slapi_log_urp, sessionid,
			  "urp_modrdn: Naming conflict MODRDN. Rename target entry to %s\n",
			  newrdn_with_uniqueid );

			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
			PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists; Rename Operation Entry */
			goto bailout;
		}

		if ( r>0 )
		{
			/* The existing entry is a loser */

			int resolve = urp_annotate_dn (sessionid, existing_entry, opcsn, "MODRDN");
			if(!resolve)
			{
				op_result= LDAP_OPERATIONS_ERROR;
				slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
				rc= -1; /* Abort this Operation */
				goto bailout;
			}
			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_NEWPARENT_ENTRY);
			if (LDAP_NO_SUCH_OBJECT == resolve) {
				/* This means that existing_dn_entry did not really exist!!!
				 * This indicates that a get_copy_of_entry -> dn2entry returned 
				 * an entry (existing_dn_entry) that was already removed from the ldbm.
				 * This is bad, because it indicates a dn cache or DB corruption.
				 * However, as far as the conflict is concerned, this error is harmless:
				 * if the existing_dn_entry did not exist in the first place, there was no
				 * conflict!! Return 0 for success to break the ldbm_back_modrdn loop 
				 * and get out of this inexistent conflict resolution ASAP.
				 */
				rc = 0;
			}
			/* Set flag to remove possible old naming conflict */
			del_old_replconflict_attr = 1;
			PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists; Rename Entry with Target DN */
			goto bailout;
		}
	}
	else
	{
		/*
		 * No entry with the target DN exists.
		 */

		/* Set flag to remove possible old naming conflict */
		del_old_replconflict_attr = 1;

		if(new_parent_entry!=NULL)
		{
			/* The new superior entry exists */
			rc= 0; /* OK, Apply the ModRDN */
			PROFILE_POINT; /* ModRDN Conflict; OK */
			goto bailout;
		}

		/* The new superior entry doesn't exist */

		slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperior);
		if(newsuperior == NULL)
		{
			/* (new_parent_entry==NULL && newsuperiordn==NULL)
			 * This is ok - SLAPI_MODRDN_NEWPARENT_ENTRY will
			 * only be set if SLAPI_MODRDN_NEWSUPERIOR_SDN was
			 * suplied by the client. If it wasn't, we're just
			 * changing the RDN of the entry. In that case,
			 * if the entry exists, its parent won't change
			 * when it's renamed, and therefore we can assume
			 * its parent exists.
			 */
			rc=0;
			PROFILE_POINT; /* ModRDN OK */
			goto bailout;
		}

		if((0 == slapi_sdn_compare(slapi_entry_get_sdn(parent_entry),
		                           newsuperior)) || 
		   is_suffix_dn (pb, newsuperior, &parentdn) )
		{
			/*
			 * The new superior is the same as the current one, or
			 * this entry is a suffix whose parent can be absent.
			 */ 
			rc= 0; /* OK, Move the entry */
			PROFILE_POINT; /* ModRDN Conflict; Absent Target Parent; Create Suffix Entry */
			goto bailout;
		}

		/*
		 * This entry is not a suffix entry, so the parent entry should exist.
		 * (This shouldn't happen in a ds5 server)
		 */
		slapi_pblock_get ( pb, SLAPI_OPERATION_PARAMETERS, &op_params );
		op_result = create_glue_entry (pb, sessionid, newsuperior,
			op_params->p.p_modrdn.modrdn_newsuperior_address.uniqueid, opcsn);
		if (LDAP_SUCCESS != op_result)
		{
			/* 
			 * FATAL ERROR 
			 * We should probably just abort the rename
			 * this will cause replication divergence requiring
			 * admin intercession
			 */
			slapi_log_error( SLAPI_LOG_FATAL, sessionid,
				 "urp_modrdn: Parent %s couldn't be found, nor recreated as a glue entry\n",
				 slapi_sdn_get_dn(newsuperior) );
			op_result= LDAP_OPERATIONS_ERROR;
			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
			rc = SLAPI_PLUGIN_FAILURE; /* Ignore this Operation */
			PROFILE_POINT;
			goto bailout;
		}

		/* The backend add code should now search for the parent again. */
		rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_NEWPARENT_ENTRY);
		PROFILE_POINT; /* ModRDN Conflict; Absent Target Parent - Change to Lost and Found entry */
		goto bailout;
	}

bailout:
	if ( del_old_replconflict_attr && rc == 0 )
	{
		del_replconflict_attr (target_entry, opcsn, 0);
	}
	if ( parentdn )
		slapi_sdn_free(&parentdn);
    return rc;
}