Пример #1
0
/*  writes the current cookie into dse.ldif under the replication agreement entry 
	returns: ldap result code of the operation. */
int 
windows_private_save_dirsync_cookie(const Repl_Agmt *ra)
{
	Dirsync_Private *dp = NULL;
    Slapi_PBlock *pb = NULL;
	Slapi_DN* sdn = NULL;
	int rc = 0;
	Slapi_Mods *mods = NULL;

    
  
	LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_save_dirsync_cookie\n" );
	PR_ASSERT(ra);

	dp = (Dirsync_Private *) agmt_get_priv(ra);
	PR_ASSERT (dp);


	pb = slapi_pblock_new ();
  
    mods = windows_private_get_cookie_mod(dp, LDAP_MOD_REPLACE);
    sdn = slapi_sdn_dup( agmt_get_dn_byref(ra) );

    slapi_modify_internal_set_pb_ext (pb, sdn, 
            slapi_mods_get_ldapmods_byref(mods), NULL, NULL, 
            repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
    slapi_modify_internal_pb (pb);

    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);

    if (rc == LDAP_NO_SUCH_ATTRIBUTE)
    {	/* try again, but as an add instead */
		slapi_mods_free(&mods);
		mods = windows_private_get_cookie_mod(dp, LDAP_MOD_ADD);
		slapi_modify_internal_set_pb_ext (pb, sdn,
		        slapi_mods_get_ldapmods_byref(mods), NULL, NULL, 
		        repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
		slapi_modify_internal_pb (pb);
	
		slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
    }

	slapi_pblock_destroy (pb);
	slapi_mods_free(&mods);
	slapi_sdn_free(&sdn);

	LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_save_dirsync_cookie\n" );
	return rc;
}
Пример #2
0
/*
  Plugin startup function, when this is called any other plugins should
  already be initialized, so it's safe to e.g. perform internal searches,
  which is needed to retrieve the plugin configuration
*/
int
acct_policy_start( Slapi_PBlock *pb )
{
	acctPluginCfg *cfg;
	void *plugin_id = get_identity();
	Slapi_DN *plugindn = NULL;
	char *config_area = NULL;

	if(slapi_plugin_running(pb)){
		return 0;
	}

	slapi_pblock_get(pb, SLAPI_TARGET_SDN, &plugindn);
	acct_policy_set_plugin_sdn(slapi_sdn_dup(plugindn));

	/* Set the alternate config area if one is defined. */
	slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_AREA, &config_area);
	if (config_area) {
		acct_policy_set_config_area(slapi_sdn_new_normdn_byval(config_area));
	}

	if(config_rwlock == NULL){
		if((config_rwlock = slapi_new_rwlock()) == NULL){
			return( CALLBACK_ERR );
		}
	}

	/* Load plugin configuration */
	if( acct_policy_load_config_startup( pb, plugin_id ) ) {
		slapi_log_err(SLAPI_LOG_ERR, PLUGIN_NAME,
			"acct_policy_start failed to load configuration\n" );
		return( CALLBACK_ERR );
	}

	/* Show the configuration */
	cfg = get_config();
	slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME, "acct_policy_start - config: "
		"stateAttrName=%s altStateAttrName=%s specAttrName=%s limitAttrName=%s "
		"alwaysRecordLogin=%d\n",
		cfg->state_attr_name, cfg->alt_state_attr_name?cfg->alt_state_attr_name:"not configured", cfg->spec_attr_name,
		cfg->limit_attr_name, cfg->always_record_login);

	return( CALLBACK_OK );
}
Пример #3
0
/*
 * op_shared_rename() -- common frontend code for modDN operations.
 *
 * Beware: this function resets the following pblock elements that were
 * set by the caller:
 *
 *	SLAPI_MODRDN_TARGET_SDN
 *	SLAPI_MODRDN_NEWRDN
 *	SLAPI_MODRDN_NEWSUPERIOR_SDN
 */
static void
op_shared_rename(Slapi_PBlock *pb, int passin_args)
{
	char			*dn, *newrdn, *newdn = NULL;
	const char		*newsuperior;
	char			**rdns;
	int				deloldrdn;
	Slapi_Backend	*be = NULL;
	Slapi_DN		*origsdn = NULL;
	Slapi_Mods		smods;
	int				internal_op, repl_op, lastmod;
	Slapi_Operation *operation;
	Slapi_Entry *referral;
	char errorbuf[BUFSIZ];
	int			err;
	char			*proxydn = NULL;
	char			*proxystr = NULL;
	int			proxy_err = LDAP_SUCCESS;
	char			*errtext = NULL;
	Slapi_DN *sdn = NULL;
	Slapi_DN *newsuperiorsdn = NULL;

	slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET, &dn);
	slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
	slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperiorsdn);
	slapi_pblock_get(pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn);
	slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op);
	slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
	slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &origsdn);
	internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL);

	/*
	 * If ownership has not been passed to this function, we replace the
	 * string input fields within the pblock with strdup'd copies.  Why?
	 * Because some pre- and post-op plugins may change them, and the
	 * convention is that plugins should place a malloc'd string in the
	 * pblock.  Therefore, we need to be able to retrieve and free them
	 * later.  But the callers of the internal modrdn calls are promised
	 * that we will not free these parameters... so if passin_args is
	 * zero, we need to make copies.
	 *
	 * In the case of SLAPI_MODRDN_TARGET_SDN and SLAPI_MODRDN_NEWSUPERIOR_SDN,
	 * we replace the existing values with normalized values (because plugins
	 * expect these DNs to be normalized).
	 */

	if (NULL == origsdn) {
		sdn = slapi_sdn_new_dn_byval(dn);
		slapi_pblock_set(pb, SLAPI_MODRDN_TARGET_SDN, sdn);
    }
	if (passin_args) {
		if (NULL == sdn) { /* origsdn is not NULL, so use it. */
			sdn = origsdn;
		}
	} else {
		if (NULL == sdn) {
			sdn = slapi_sdn_dup(origsdn);
		}
		newrdn = slapi_ch_strdup(newrdn);
		newsuperiorsdn = slapi_sdn_dup(newsuperiorsdn);
		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, newsuperiorsdn);
	}
	/* normdn = slapi_sdn_get_dn(sdn); */
	newsuperior = slapi_sdn_get_dn(newsuperiorsdn);

	/* get the proxy auth dn if the proxy auth control is present */
	proxy_err = proxyauth_get_dn(pb, &proxydn, &errtext);

	/*
	 * first, log the operation to the access log,
	 * then check rdn and newsuperior,
	 * and - if applicable - log reason of any error to the errors log
	 */
	if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_ACCESS))
	{
		if (proxydn)
		{
			proxystr = slapi_ch_smprintf(" authzid=\"%s\"", proxydn);
		}

		if ( !internal_op )
		{
			slapi_log_access(LDAP_DEBUG_STATS,
					 "conn=%" NSPRIu64 " op=%d MODRDN dn=\"%s\" newrdn=\"%s\" newsuperior=\"%s\"%s\n",
					 pb->pb_conn->c_connid, 
					 pb->pb_op->o_opid,
					 dn,
					 newrdn ? newrdn : "(null)",
					 newsuperior ? newsuperior : "(null)",
					 proxystr ? proxystr : "");
		}
		else
		{
			slapi_log_access(LDAP_DEBUG_ARGS,
					 "conn=%s op=%d MODRDN dn=\"%s\" newrdn=\"%s\" newsuperior=\"%s\"%s\n",
					 LOG_INTERNAL_OP_CON_ID,
					 LOG_INTERNAL_OP_OP_ID,
					 dn,
					 newrdn ? newrdn : "(null)",
					 newsuperior ? newsuperior : "(null)",
					 proxystr ? proxystr : "");
		}
	}

	/* If we encountered an error parsing the proxy control, return an error
	 * to the client.  We do this here to ensure that we log the operation first. */
	if (proxy_err != LDAP_SUCCESS)
	{
		send_ldap_result(pb, proxy_err, NULL, errtext, 0, NULL);
		goto free_and_return_nolock;
	}

	/* check that the rdn is formatted correctly */
	if ((rdns = slapi_ldap_explode_rdn(newrdn, 0)) == NULL) 
	{
		if ( !internal_op ) {
			slapi_log_error(SLAPI_LOG_ARGS, NULL, 
				 "conn=%" NSPRIu64 " op=%d MODRDN invalid new RDN (\"%s\")\n",
				 pb->pb_conn->c_connid,
				 pb->pb_op->o_opid,
				 (NULL == newrdn) ? "(null)" : newrdn);
		} else {
			slapi_log_error(SLAPI_LOG_ARGS, NULL, 
				 "conn=%s op=%d MODRDN invalid new RDN (\"%s\")\n",
				 LOG_INTERNAL_OP_CON_ID,
				 LOG_INTERNAL_OP_OP_ID,
				 (NULL == newrdn) ? "(null)" : newrdn);
		}
		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid RDN", 0, NULL);
		goto free_and_return_nolock;
	} 
	else 
	{
		slapi_ldap_value_free(rdns);
	}

	/* check if created attributes are used in the new RDN */
	/* check_rdn_for_created_attrs ignores the cases */
	if (check_rdn_for_created_attrs((const char *)newrdn)) {
		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid attribute in RDN", 0, NULL);
		goto free_and_return_nolock;
	}

	/* check that the dn is formatted correctly */
	err = slapi_dn_syntax_check(pb, newsuperior, 1);
	if (err)
	{
		LDAPDebug0Args(LDAP_DEBUG_ARGS, "Syntax check of newSuperior failed\n");
		if (!internal_op) {
			slapi_log_error(SLAPI_LOG_ARGS, NULL,
				 "conn=%" NSPRIu64 " op=%d MODRDN invalid new superior (\"%s\")",
				 pb->pb_conn->c_connid,
				 pb->pb_op->o_opid,
				 newsuperior ? newsuperior : "(null)");
		} else {
			slapi_log_error(SLAPI_LOG_ARGS, NULL,
				 "conn=%s op=%d MODRDN invalid new superior (\"%s\")",
				 LOG_INTERNAL_OP_CON_ID,
				 LOG_INTERNAL_OP_OP_ID,
				 newsuperior ? newsuperior : "(null)");
		}
		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL,
						 "newSuperior does not look like a DN", 0, NULL);
		goto free_and_return_nolock;
	} 

	if (newsuperior != NULL) 
	{
		LDAPDebug(LDAP_DEBUG_ARGS, "do_moddn: newsuperior (%s)\n", newsuperior, 0, 0);
	}

	/* target spec is used to decide which plugins are applicable for the operation */
	operation_set_target_spec (pb->pb_op, sdn);

	/*
	 * Construct the new DN (code sdn from backend
	 * and modified to handle newsuperior)
	 */
	newdn = slapi_moddn_get_newdn(sdn, newrdn, newsuperior);

	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one, or send a referral to our "referral server"
	 * if we don't hold it.
	 */
	/* slapi_mapping_tree_select_and_check ignores the case of newdn
	 * which is generated using newrdn above. */
	if ((err = slapi_mapping_tree_select_and_check(pb, newdn, &be, &referral, errorbuf)) != LDAP_SUCCESS)
	{
		send_ldap_result(pb, err, NULL, errorbuf, 0, NULL);
		goto free_and_return_nolock;
	}

	if (referral)
	{
		int managedsait;

		slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
		if (managedsait)
		{
			send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
					"cannot update referral", 0, NULL);
			slapi_entry_free(referral);
			goto free_and_return;
		}
	
		send_referrals_from_entry(pb,referral);
		slapi_entry_free(referral);
		goto free_and_return;
	}

	slapi_pblock_set(pb, SLAPI_BACKEND, be);

	/* can get lastmod only after backend is selected */	
	slapi_pblock_get(pb, SLAPI_BE_LASTMOD, &lastmod);

	/* if it is a replicated operation - leave lastmod attributes alone */
	slapi_mods_init (&smods, 2);
	if (!repl_op && lastmod)
	{
		modify_update_last_modified_attr(pb, &smods);
		slapi_pblock_set(pb, SLAPI_MODIFY_MODS, (void*)slapi_mods_get_ldapmods_passout(&smods));
	}
	else {
		slapi_mods_done (&smods);
	}

	/*
	 * call the pre-modrdn plugins. if they succeed, call
	 * the backend modrdn function. then call the
	 * post-modrdn plugins.
	 */
	if (plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN :
							SLAPI_PLUGIN_PRE_MODRDN_FN) == 0)
	{
		int	rc= LDAP_OPERATIONS_ERROR;
		slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
		set_db_default_result_handlers(pb);
		if (be->be_modrdn != NULL)
		{
			if ((rc = (*be->be_modrdn)(pb)) == 0)
			{
				Slapi_Entry	*pse;
				Slapi_Entry	*ecopy;
				/* we don't perform acl check for internal operations */
				/* dont update aci store for remote acis              */
				if ((!internal_op) &&
					(!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)))
					plugin_call_acl_mods_update (pb, SLAPI_OPERATION_MODRDN);

				if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_AUDIT))
					write_audit_log_entry(pb); /* Record the operation in the audit log */

				slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse);
				slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &ecopy);
				/* GGOODREPL persistent search system needs the changenumber, oops. */
				do_ps_service(pse, ecopy, LDAP_CHANGETYPE_MODDN, 0);
			}
		}
		else
		{
			send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Function not implemented", 0, NULL);
		}

		slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &rc);
		plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN : 
							SLAPI_PLUGIN_POST_MODRDN_FN);
	}

free_and_return:
	if (be)
		slapi_be_Unlock(be);
free_and_return_nolock:
	{
		/* Free up everything left in the PBlock */
		Slapi_Entry	*pse;
		Slapi_Entry	*ecopy;
		LDAPMod **mods;
		char	*s;

		if (passin_args) {
			if (NULL == origsdn) {
				slapi_sdn_free(&sdn);
			}
		} else {
			slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &sdn);
			slapi_sdn_free(&sdn);
			/* get newrdn to free the string */
			slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
			slapi_ch_free_string(&newrdn);
			slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperiorsdn);
			slapi_sdn_free(&newsuperiorsdn);
		}
		slapi_ch_free_string(&newdn);

		slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &ecopy);
		slapi_entry_free(ecopy);
		slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse);
		slapi_entry_free(pse);
		slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
		ldap_mods_free( mods, 1 );
		slapi_ch_free_string(&proxydn);
		slapi_ch_free_string(&proxystr);

		slapi_pblock_get(pb, SLAPI_URP_NAMING_COLLISION_DN, &s);
		slapi_ch_free((void **)&s);
	}
}
Пример #4
0
Файл: add.c Проект: Firstyear/ds
/* Code shared between regular and internal add operation */
static void op_shared_add (Slapi_PBlock *pb)
{
	Slapi_Operation *operation;
	Slapi_Entry	*e, *pse;
	Slapi_Backend *be = NULL;
	int	err;
	int internal_op, repl_op, legacy_op, lastmod;
	char *pwdtype = NULL;
	Slapi_Attr *attr = NULL;
	Slapi_Entry *referral;
	char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE];
	struct slapdplugin  *p = NULL;
	char *proxydn = NULL;
	char *proxystr = NULL;
	int proxy_err = LDAP_SUCCESS;
	char *errtext = NULL;
	Slapi_DN *sdn = NULL;
	passwdPolicy *pwpolicy;

	slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
	slapi_pblock_get (pb, SLAPI_ADD_ENTRY, &e);
	slapi_pblock_get (pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op);	
	slapi_pblock_get (pb, SLAPI_IS_LEGACY_REPLICATED_OPERATION, &legacy_op);
	internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL);
	pwpolicy = new_passwdPolicy(pb, slapi_entry_get_dn(e));

	/* target spec is used to decide which plugins are applicable for the operation */
	operation_set_target_spec (operation, slapi_entry_get_sdn (e));

	if ((err = slapi_entry_add_rdn_values(e)) != LDAP_SUCCESS) 
	{
	  send_ldap_result(pb, err, NULL, "failed to add RDN values", 0, NULL);
	  goto done;
	}

	/* get the proxy auth dn if the proxy auth control is present */
	proxy_err = proxyauth_get_dn(pb, &proxydn, &errtext);

	if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_ACCESS))
	{
		if (proxydn)
		{
			proxystr = slapi_ch_smprintf(" authzid=\"%s\"", proxydn);
		}

		if ( !internal_op )
		{
			slapi_log_access(LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d ADD dn=\"%s\"%s\n",
							 pb->pb_conn->c_connid,
							 operation->o_opid,
							 slapi_entry_get_dn_const(e),
							 proxystr ? proxystr : "");
		}
		else
		{
			slapi_log_access(LDAP_DEBUG_ARGS, "conn=%s op=%d ADD dn=\"%s\"\n",
							 LOG_INTERNAL_OP_CON_ID,
							 LOG_INTERNAL_OP_OP_ID,
							 slapi_entry_get_dn_const(e));
		}
	}

	/* If we encountered an error parsing the proxy control, return an error
	 * to the client.  We do this here to ensure that we log the operation first. */
	if (proxy_err != LDAP_SUCCESS)
	{
		send_ldap_result(pb, proxy_err, NULL, errtext, 0, NULL);
		goto done;
	}

	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one.
	 */
	if ((err = slapi_mapping_tree_select(pb, &be, &referral, errorbuf, sizeof(errorbuf))) != LDAP_SUCCESS) {
		send_ldap_result(pb, err, NULL, errorbuf, 0, NULL);
		be = NULL;
		goto done;
	}

	if (referral)
	{
		int managedsait;

		slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
		if (managedsait)
		{
			send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
							 "cannot update referral", 0, NULL);
			slapi_entry_free(referral);
			goto done;
		}
	
		slapi_pblock_set(pb, SLAPI_TARGET_SDN, (void*)operation_get_target_spec (operation));
		send_referrals_from_entry(pb,referral);
		slapi_entry_free(referral);
		goto done;
	}

	if (!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)) {
		Slapi_Value **unhashed_password_vals = NULL;
		Slapi_Value **present_values = NULL;

		/* Setting unhashed password to the entry extension. */
		if (repl_op) {
			/* replicated add ==> get unhashed pw from entry, if any.
			 * set it to the extension */
			slapi_entry_attr_find(e, PSEUDO_ATTR_UNHASHEDUSERPASSWORD, &attr);
			if (attr) {
				present_values = attr_get_present_values(attr);
				valuearray_add_valuearray(&unhashed_password_vals,
				                          present_values, 0);
#if !defined(USE_OLD_UNHASHED)
			 	/* and remove it from the entry. */
				slapi_entry_attr_delete(e, PSEUDO_ATTR_UNHASHEDUSERPASSWORD);
#endif
			}
		} else {
			/* ordinary add ==>
			 * get unhashed pw from userpassword before encrypting it */
			/* look for user password attribute */
			slapi_entry_attr_find(e, SLAPI_USERPWD_ATTR, &attr);
			if (attr) {
				Slapi_Value **vals = NULL;

				/* Set the backend in the pblock. 
				 * The slapi_access_allowed function
				 * needs this set to work properly. */
				slapi_pblock_set(pb, SLAPI_BACKEND,
				                 slapi_be_select(slapi_entry_get_sdn_const(e)));

				/* Check ACI before checking password syntax */
				if ((err = slapi_access_allowed(pb, e, SLAPI_USERPWD_ATTR, NULL,
				                              SLAPI_ACL_ADD)) != LDAP_SUCCESS) {
					send_ldap_result(pb, err, NULL,
					                 "Insufficient 'add' privilege to the "
					                 "'userPassword' attribute", 0, NULL);
					goto done;
				}

				/*
				 * Check password syntax, unless this is a pwd admin/rootDN
				 */
				present_values = attr_get_present_values(attr);
				if (!pw_is_pwp_admin(pb, pwpolicy) &&
				    check_pw_syntax(pb, slapi_entry_get_sdn_const(e),
				                    present_values, NULL, e, 0) != 0) {
					/* error result is sent from check_pw_syntax */
					goto done;
				}
				/* pw syntax is valid */
				valuearray_add_valuearray(&unhashed_password_vals,
				                          present_values, 0);
				valuearray_add_valuearray(&vals, present_values, 0);
				pw_encodevals_ext(pb, slapi_entry_get_sdn (e), vals);
				add_password_attrs(pb, operation, e);
				slapi_entry_attr_replace_sv(e, SLAPI_USERPWD_ATTR, vals);
				valuearray_free(&vals);
#if defined(USE_OLD_UNHASHED)
				/* Add the unhashed password pseudo-attribute to the entry */
				pwdtype = 
				  slapi_attr_syntax_normalize(PSEUDO_ATTR_UNHASHEDUSERPASSWORD);
				slapi_entry_add_values_sv(e, pwdtype, unhashed_password_vals);
#endif
			}
		}
		if (unhashed_password_vals &&
		    (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch())) {
			/* unhashed_password_vals is consumed if successful. */
			err = slapi_pw_set_entry_ext(e, unhashed_password_vals,
			                             SLAPI_EXT_SET_ADD);
			if (err) {
				valuearray_free(&unhashed_password_vals);
			}
		}

#if defined(THISISTEST)
		{
			/* test code to retrieve an unhashed pw from the entry extention &
			 * PSEUDO_ATTR_UNHASHEDUSERPASSWORD attribute */
			char *test_str = slapi_get_first_clear_text_pw(e);
			if (test_str) {
				slapi_log_err(SLAPI_LOG_ERR,
				              "Value from extension: %s\n", test_str);
				slapi_ch_free_string(&test_str);
			}
#if defined(USE_OLD_UNHASHED)
			test_str = slapi_entry_attr_get_charptr(e,
			                                  PSEUDO_ATTR_UNHASHEDUSERPASSWORD);
			if (test_str) {
				slapi_log_err(SLAPI_LOG_ERR,
				              "Value from attr: %s\n", test_str);
				slapi_ch_free_string(&test_str);
			}
#endif /* USE_OLD_UNHASHED */
		}
#endif /* THISISTEST */

        /* look for multiple backend local credentials or replication local credentials */
        for ( p = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); p != NULL && !repl_op;
            p = p->plg_next )
        {
            char *L_attr = NULL;
            int i=0;

            /* Get the appropriate decoding function */
            for ( L_attr = p->plg_argv[i]; i<p->plg_argc; L_attr = p->plg_argv[++i])
            {
                /* look for multiple backend local credentials or replication local credentials */
                char *L_normalized = slapi_attr_syntax_normalize(L_attr);
                slapi_entry_attr_find(e, L_normalized, &attr);
                if (attr)
                {
                    Slapi_Value **present_values = NULL;
                    Slapi_Value **vals = NULL;

                    present_values= attr_get_present_values(attr);

                    valuearray_add_valuearray(&vals, present_values, 0);
                    pw_rever_encode(vals, L_normalized);
                    slapi_entry_attr_replace_sv(e, L_normalized, vals);
                    valuearray_free(&vals);
                }
                if (L_normalized)
                    slapi_ch_free ((void**)&L_normalized);
            }
        }
    }

	slapi_pblock_set(pb, SLAPI_BACKEND, be);

	if (!repl_op)
	{
		/* can get lastmod only after backend is selected */
		slapi_pblock_get(pb, SLAPI_BE_LASTMOD, &lastmod);

		if (lastmod && add_created_attrs(pb, e) != 0)
		{
			send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
				"cannot insert computed attributes", 0, NULL);
			goto done;
		}
		/* expand objectClass values to reflect the inheritance hierarchy */
		slapi_schema_expand_objectclasses( e );
	}

    /* uniqueid needs to be generated for entries added during legacy replication */
    if (legacy_op){
    	if (add_uniqueid(e) != UID_SUCCESS)
    	{
    		send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
    				"cannot insert computed attributes", 0, NULL);
    		goto done;
    	}
    }

	/*
	 * call the pre-add plugins. if they succeed, call
	 * the backend add function. then call the post-add
	 * plugins.
	 */
	
	sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(e));
	slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, (void *)sdn);
	if (plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN :
	                        SLAPI_PLUGIN_PRE_ADD_FN) == SLAPI_PLUGIN_SUCCESS)
	{
		int	rc;
		Slapi_Entry	*ec;
		Slapi_DN *add_target_sdn = NULL;
		Slapi_Entry *save_e = NULL;

		slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
		set_db_default_result_handlers(pb);
		/* because be_add frees the entry */
		ec = slapi_entry_dup(e);
		add_target_sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(ec));
		slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn);
		slapi_sdn_free(&sdn);
		slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, add_target_sdn);
		
		if (be->be_add != NULL)
		{
			rc = (*be->be_add)(pb);
			/* backend may change this if errors and not consumed */
			slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &save_e);
			slapi_pblock_set(pb, SLAPI_ADD_ENTRY, ec);
			if (rc == 0)
			{
				/* acl is not enabled for internal operations */
				/* don't update aci store for remote acis     */
				if ((!internal_op) && 
					(!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)))
				{
					plugin_call_acl_mods_update (pb, SLAPI_OPERATION_ADD);
				}

				if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_AUDIT))
				{ 
					write_audit_log_entry(pb); /* Record the operation in the audit log */
				}

				slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse);
				do_ps_service(pse, NULL, LDAP_CHANGETYPE_ADD, 0);
				/* 
				 * If be_add succeeded, then e is consumed except the resurrect case.
				 * If it is resurrect, the corresponding tombstone entry is resurrected
				 * and put into the cache.
				 * Otherwise, we set e to NULL to prevent freeing it ourselves.
				 */
				if (operation_is_flag_set(operation,OP_FLAG_RESURECT_ENTRY) && save_e) {
					e = save_e;
				} else {
					e = NULL;
				}
			}
			else
			{
				/* PR_ASSERT(!save_e); save_e is supposed to be freed in the backend.  */
				e = save_e;
				if (rc == SLAPI_FAIL_DISKFULL)
				{
					operation_out_of_disk_space();
					goto done;
				}
				/* If the disk is full we don't want to make it worse ... */
				if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_AUDIT))
				{ 
					write_auditfail_log_entry(pb); /* Record the operation in the audit log */
				}
			}
		}
		else
		{
			send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
							 "Function not implemented", 0, NULL);
		}
		slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &rc);
		plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_POST_ADD_FN : 
							SLAPI_PLUGIN_POST_ADD_FN);
		slapi_entry_free(ec);
	}
	slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn);
	slapi_sdn_free(&sdn);

done:
	if (be)
		slapi_be_Unlock(be);
	slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse);
	slapi_entry_free(pse);
	slapi_ch_free((void **)&operation->o_params.p.p_add.parentuniqueid);
	slapi_entry_free(e);
	slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL);
	slapi_ch_free((void**)&pwdtype);
	slapi_ch_free_string(&proxydn);
	slapi_ch_free_string(&proxystr);
}
Пример #5
0
/*
 * memberof_copy_config()
 *
 * Makes a copy of the config in src.  This function will free the
 * elements of dest if they already exist.  This should only be called
 * if you hold the memberof config lock if src was obtained with
 * memberof_get_config().
 */
void
memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src)
{
	if (dest && src)
	{
		/* Check if the copy is already up to date */
		if (src->groupattrs)
		{
			int i = 0, j = 0;

			/* Copy group attributes string list. */
			slapi_ch_array_free(dest->groupattrs);
			dest->groupattrs = slapi_ch_array_dup(src->groupattrs);

			/* Copy group check filter. */
			slapi_filter_free(dest->group_filter, 1);
			dest->group_filter = slapi_filter_dup(src->group_filter);

			/* Copy group attributes Slapi_Attr list.
			 * First free the old list. */
			for (i = 0; dest->group_slapiattrs && dest->group_slapiattrs[i]; i++)
			{
				slapi_attr_free(&dest->group_slapiattrs[i]);
			}

			/* Count how many values we have in the source list. */
			for (j = 0; src->group_slapiattrs[j]; j++)
			{
				/* Do nothing. */
			}

			/* Realloc dest if necessary. */
			if (i < j)
			{
				dest->group_slapiattrs = (Slapi_Attr **)slapi_ch_realloc((char *)dest->group_slapiattrs, sizeof(Slapi_Attr *) * (j + 1));
			}

			/* Copy the attributes. */
			for (i = 0; src->group_slapiattrs[i]; i++)
			{
				dest->group_slapiattrs[i] = slapi_attr_dup(src->group_slapiattrs[i]);
			}

			/* Terminate the array. */
			dest->group_slapiattrs[i] = NULL;
		}

		if (src->memberof_attr)
		{
			slapi_ch_free_string(&dest->memberof_attr);
			dest->memberof_attr = slapi_ch_strdup(src->memberof_attr);
		}

		if(src->skip_nested){
			dest->skip_nested = src->skip_nested;
		}

		if(src->allBackends)
		{
			dest->allBackends = src->allBackends;
		}

		slapi_ch_free_string(&dest->auto_add_oc);
		dest->auto_add_oc = slapi_ch_strdup(src->auto_add_oc);

		if(src->entryScopes){
			int num_vals = 0;

			dest->entryScopes = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),src->entryScopeCount+1);
			for(num_vals = 0; src->entryScopes[num_vals]; num_vals++){
				dest->entryScopes[num_vals] = slapi_sdn_dup(src->entryScopes[num_vals]);
			}
		}
		if(src->entryScopeExcludeSubtrees){
			int num_vals = 0;

			dest->entryScopeExcludeSubtrees = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),src->entryExcludeScopeCount+1);
			for(num_vals = 0; src->entryScopeExcludeSubtrees[num_vals]; num_vals++){
				dest->entryScopeExcludeSubtrees[num_vals] = slapi_sdn_dup(src->entryScopeExcludeSubtrees[num_vals]);
			}
		}
	}
}
Пример #6
0
/*
 * Perform the agreement/domain specific configuration.
 * IPA stores its configuration in the tree.  We use the
 * ds_subtree to search for the domain/realm specific
 * configuration entries.
 */
void
ipa_winsync_config_refresh_domain(
    void *cbdata, const Slapi_DN *ds_subtree,
    const Slapi_DN *ad_subtree
)
{
    IPA_WinSync_Domain_Config *iwdc =
        (IPA_WinSync_Domain_Config *)cbdata;
    Slapi_DN *config_dn = slapi_sdn_dup(ds_subtree);
    char *realm_filter = NULL;
    char *realm_attr = NULL;
    char *new_entry_filter = NULL;
    char *new_user_oc_attr = NULL; /* don't care about groups for now */
    char *homedir_prefix_attr = NULL;
    char *login_shell_attr = NULL;
    char *default_group_attr = NULL;
    char *default_group_filter = NULL;
    char *default_group_name = NULL;
    char *real_group_filter = NULL;
    char *default_gid = NULL;
    Slapi_ValueSet *new_user_objclasses = NULL; /* don't care about groups for now */
    int loopdone = 0;
    int search_scope = LDAP_SCOPE_SUBTREE;
    int ret = LDAP_SUCCESS;
    int acct_disable;
    char *inactivated_filter = NULL;
    char *activated_filter = NULL;
    char *inactivated_group_dn = NULL;
    char *activated_group_dn = NULL;
    int upg = -1;

    slapi_lock_mutex(theConfig.lock);
    realm_filter = slapi_ch_strdup(theConfig.realm_filter);
    realm_attr = slapi_ch_strdup(theConfig.realm_attr);
    new_entry_filter = slapi_ch_strdup(theConfig.new_entry_filter);
    new_user_oc_attr = slapi_ch_strdup(theConfig.new_user_oc_attr);
    homedir_prefix_attr = slapi_ch_strdup(theConfig.homedir_prefix_attr);
    if (theConfig.login_shell_attr) {
        login_shell_attr = slapi_ch_strdup(theConfig.login_shell_attr);
    }
    default_group_attr = slapi_ch_strdup(theConfig.default_group_attr);
    default_group_filter = slapi_ch_strdup(theConfig.default_group_filter);
    acct_disable = theConfig.acct_disable;
    if (acct_disable != ACCT_DISABLE_NONE) {
        if (theConfig.inactivated_filter) {
            inactivated_filter = slapi_ch_strdup(theConfig.inactivated_filter);
        }
        if (theConfig.activated_filter) {
            activated_filter = slapi_ch_strdup(theConfig.activated_filter);
        }
    }
    slapi_unlock_mutex(theConfig.lock);

    /* starting at ds_subtree, search for the entry
       containing the Kerberos realm to use */
    slapi_ch_free_string(&iwdc->realm_name);
    while(!loopdone && !slapi_sdn_isempty(config_dn)) {
        ret = internal_find_entry_get_attr_val(config_dn, search_scope,
                                               realm_filter, realm_attr,
                                               NULL, &iwdc->realm_name);

        if ((0 == ret) && iwdc->realm_name) {
            loopdone = 1;
        } else if ((LDAP_NO_SUCH_OBJECT == ret) && !iwdc->realm_name) {
            /* try again */
            Slapi_DN *parent_dn = slapi_sdn_new();
            slapi_sdn_get_parent(config_dn, parent_dn);
            slapi_sdn_free(&config_dn);
            config_dn = parent_dn;
        } else { /* error */
            goto out;
        }
    }

    if (!iwdc->realm_name) {
        /* error - could not find the IPA config entry with the realm name */
        LOG_FATAL("Error: could not find the entry containing the realm name "
                  "[%d] ds subtree [%s] filter [%s] attr [%s]\n",
                  ret, slapi_sdn_get_dn(ds_subtree), realm_filter, realm_attr);
        goto out;
    }

    /* look for the entry containing the default objectclasses
       to add to new entries */
    ret = internal_find_entry_get_attr_val(config_dn, search_scope,
                                           new_entry_filter, new_user_oc_attr,
                                           &new_user_objclasses, NULL);
    if (!new_user_objclasses) {
        /* error - could not find the entry containing list of objectclasses */
        LOG_FATAL("Error: could not find the entry containing the new user objectclass list "
                  "[%d] ds subtree [%s] filter [%s] attr [%s]\n",
                  ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, new_user_oc_attr);
        goto out;
    }

    /* get the home directory prefix value */
    /* note - this is in the same entry as the new entry template, so
       use the same filter */
    slapi_ch_free_string(&iwdc->homedir_prefix);
    ret = internal_find_entry_get_attr_val(config_dn, search_scope,
                                           new_entry_filter, homedir_prefix_attr,
                                           NULL, &iwdc->homedir_prefix);
    if (!iwdc->homedir_prefix) {
        /* error - could not find the home dir prefix */
        LOG_FATAL("Error: could not find the entry containing the home directory prefix "
                  "[%d] ds subtree [%s] filter [%s] attr [%s]\n",
                  ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, homedir_prefix_attr);
        goto out;
    }

    /* get the login shell value */
    /* note - this is in the same entry as the new entry template, so
       use the same filter */
    slapi_ch_free_string(&iwdc->login_shell);
    if (login_shell_attr) {
        ret = internal_find_entry_get_attr_val(config_dn, search_scope,
                                               new_entry_filter,
                                               login_shell_attr,
                                               NULL, &iwdc->login_shell);
        if (!iwdc->login_shell) {
            LOG("Warning: could not find the entry containing the login shell "
                "attribute [%d] ds subtree [%s] filter [%s] attr [%s]\n",
                ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter,
                login_shell_attr);
        }
    }
    if (!iwdc->login_shell) {
        /* could not find the login shell or was not configured */
        LOG("Warning: no login shell configured!");
    }

    /* find the default group - the entry above contains the group name, but
       we need the gidNumber for posixAccount - so first find the entry
       and attr value which has the group name, then lookup the group
       number from the group name */
    ret = internal_find_entry_get_attr_val(config_dn, search_scope,
                                           new_entry_filter, default_group_attr,
                                           NULL, &default_group_name);
    if (!default_group_name) {
        /* error - could not find the default group name */
        LOG_FATAL("Error: could not find the entry containing the default group name "
                  "[%d] ds subtree [%s] filter [%s] attr [%s]\n",
                  ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, default_group_attr);
        goto out;
    }

    /* check if User Private Groups are enabled */
    upg = ipa_winsync_upg_enabled(ds_subtree);

    /* next, find the group whose name is default_group_name - construct the filter
       based on the filter attribute value - assumes the group name is stored
       in the cn attribute value, and the gidNumber in the gidNumber attribute value */
    real_group_filter = slapi_ch_smprintf("(&(cn=%s)%s)", default_group_name,
                                          default_group_filter);
    ret = internal_find_entry_get_attr_val(config_dn, search_scope,
                                           real_group_filter, "gidNumber",
                                           NULL, &default_gid);
    if (!default_gid) {
        /* error - could not find the default gidNumber
           This is not a fatal error if User Private Groups (UPG) are enabled.
         */
        if (upg) {
            LOG_FATAL("Error: could not find the entry containing the default gidNumber "
                      "UPG [%d] ds subtree [%s] filter [%s] attr [%s]\n",
                      ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, "gidNumber");
            goto out;
        } else {
            ret = LDAP_SUCCESS;
        }
    }

    /* If we are syncing account disable, we need to find the groups used
       to denote active and inactive users e.g.
       dn: cn=inactivated,cn=account inactivation,cn=accounts,$SUFFIX

       dn: cn=Activated,cn=Account Inactivation,cn=accounts,$SUFFIX

    */
    if (acct_disable != ACCT_DISABLE_NONE) {
        if (inactivated_filter) {
            ret = internal_find_entry_get_attr_val(config_dn, search_scope,
                                                   inactivated_filter, "dn",
                                                   NULL, &inactivated_group_dn);
            if (!inactivated_group_dn) {
                /* error - could not find the inactivated group dn */
                LOG("Could not find the DN of the inactivated users group "
                    "[%d] ds subtree [%s] filter [%s]. Ignoring\n",
                    ret, slapi_sdn_get_dn(ds_subtree), inactivated_filter);
                goto out;
            }
        }
        if (activated_filter) {
            ret = internal_find_entry_get_attr_val(config_dn, search_scope,
                                                   activated_filter, "dn",
                                                   NULL, &activated_group_dn);
            if (!activated_group_dn) {
                /* error - could not find the activated group dn */
                LOG("Could not find the DN of the activated users group "
                    "[%d] ds subtree [%s] filter [%s]. Ignoring\n",
                    ret, slapi_sdn_get_dn(ds_subtree), activated_filter);
                goto out;
            }
        }
    }

    /* ok, we have our values */
    /* first, clear out the old domain config */
    slapi_entry_free(iwdc->domain_e);
    iwdc->domain_e = NULL;

    /* next, copy the global attr config */
    slapi_lock_mutex(theConfig.lock);
    iwdc->domain_e = slapi_entry_dup(theConfig.config_e);
    slapi_unlock_mutex(theConfig.lock);

    /* set the objectclasses in the domain_e */
    slapi_entry_attr_delete(iwdc->domain_e, "objectclass");
    /* this copies new_user_objclasses */
    slapi_entry_add_valueset(iwdc->domain_e, "objectclass", new_user_objclasses);

    /* When UPG is disabled, set the default gid number */
    if (upg && default_gid) {
        slapi_entry_attr_set_charptr(iwdc->domain_e,  "gidNumber", default_gid);
    }

    slapi_ch_free_string(&iwdc->inactivated_group_dn);
    iwdc->inactivated_group_dn = inactivated_group_dn;
    inactivated_group_dn = NULL;
    slapi_ch_free_string(&iwdc->activated_group_dn);
    iwdc->activated_group_dn = activated_group_dn;
    activated_group_dn = NULL;

out:
    slapi_valueset_free(new_user_objclasses);
    slapi_sdn_free(&config_dn);
    slapi_ch_free_string(&realm_filter);
    slapi_ch_free_string(&realm_attr);
    slapi_ch_free_string(&new_entry_filter);
    slapi_ch_free_string(&new_user_oc_attr);
    slapi_ch_free_string(&homedir_prefix_attr);
    slapi_ch_free_string(&login_shell_attr);
    slapi_ch_free_string(&default_group_attr);
    slapi_ch_free_string(&default_group_filter);
    slapi_ch_free_string(&default_group_name);
    slapi_ch_free_string(&real_group_filter);
    slapi_ch_free_string(&default_gid);
    slapi_ch_free_string(&inactivated_filter);
    slapi_ch_free_string(&inactivated_group_dn);
    slapi_ch_free_string(&activated_filter);
    slapi_ch_free_string(&activated_group_dn);

    if (LDAP_SUCCESS != ret) {
        slapi_ch_free_string(&iwdc->realm_name);
        slapi_ch_free_string(&iwdc->homedir_prefix);
        slapi_ch_free_string(&iwdc->login_shell);
        slapi_entry_free(iwdc->domain_e);
        iwdc->domain_e = NULL;
    }

    return;
}
Пример #7
0
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;
}
Пример #8
0
/*
 * Return 0 for OK,
 *       -1 for Ignore or Error depending on SLAPI_RESULT_CODE,
 *       >0 for action code
 * Action Code Bit 0: Fetch existing entry.
 * Action Code Bit 1: Fetch parent entry.
 * The function is called as a be pre-op on consumers.
 */
int 
urp_add_operation( Slapi_PBlock *pb )
{
	Slapi_Entry	*existing_uniqueid_entry;
	Slapi_Entry	*existing_dn_entry;
	Slapi_Entry	*addentry;
	const char *adduniqueid;
	CSN *opcsn;
	const char *basedn;
	char sessionid[REPL_SESSION_ID_SIZE];
	int r;
	int op_result= 0;
	int rc= 0; /* OK */
	Slapi_DN *sdn = NULL;

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

	get_repl_session_id (pb, sessionid, &opcsn);
	slapi_pblock_get( pb, SLAPI_ADD_EXISTING_UNIQUEID_ENTRY, &existing_uniqueid_entry );
	if (existing_uniqueid_entry!=NULL)
	{
		/* 
		 * An entry with this uniqueid already exists.
		 * - It could be a replay of the same Add, or
		 * - It could be a UUID generation collision, or
		 */
		/* 
		 * 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
		 */
		/* op_result = LDAP_SUCCESS; */
		slapi_log_error(slapi_log_urp, sessionid,
		          "urp_add (%s): an entry with this uniqueid already exists.\n",
		          slapi_entry_get_dn_const(existing_uniqueid_entry));
		op_result= LDAP_UNWILLING_TO_PERFORM;
		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
		rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
		PROFILE_POINT; /* Add Conflict; UniqueID Exists;  Ignore */
		goto bailout;
	}

	slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &addentry );
	slapi_pblock_get( pb, SLAPI_ADD_EXISTING_DN_ENTRY, &existing_dn_entry );
	if (existing_dn_entry==NULL) /* The target DN does not exist */
	{
		/* Check for parent entry... this could be an orphan. */
		Slapi_Entry *parententry;
		slapi_pblock_get( pb, SLAPI_ADD_PARENT_ENTRY, &parententry );
		rc = urp_add_resolve_parententry (pb, sessionid, addentry, parententry, opcsn);
		PROFILE_POINT; /* Add Entry */
		goto bailout;
	}

	/*
	 * Naming conflict: an entry with the target DN already exists.
	 * Compare the DistinguishedNameCSN of the existing entry
	 * and the OperationCSN. The smaller CSN wins. The loser changes
	 * its RDN to uniqueid+baserdn, and adds operational attribute
	 * ATTR_NSDS5_REPLCONFLIC.
	 */
	basedn = slapi_entry_get_ndn (addentry);
	adduniqueid = slapi_entry_get_uniqueid (addentry);
	r = csn_compare (entry_get_dncsn(existing_dn_entry), opcsn);
	if (r<0)
	{
		/* Entry to be added is a loser */
		char *newdn= get_dn_plus_uniqueid (sessionid, basedn, adduniqueid);
		if(newdn==NULL)
		{
			op_result= LDAP_OPERATIONS_ERROR;
			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
			rc = SLAPI_PLUGIN_NOOP; /* Abort this Operation */
			slapi_log_error(slapi_log_urp, sessionid,
			      "urp_add (%s): Add conflict; Unique ID (%s) already in RDN\n",
			      basedn, adduniqueid);
			PROFILE_POINT; /* Add Conflict; Entry Exists; Unique ID already in RDN - Abort this update. */
		}
		else
		{
			/* Add the nsds5ReplConflict attribute in the mods */
			Slapi_Attr *attr = NULL;
			Slapi_Value **vals = NULL;
			Slapi_RDN *rdn;
			char buf[BUFSIZ];

			PR_snprintf(buf, BUFSIZ, "%s %s", REASON_ANNOTATE_DN, basedn);
			if (slapi_entry_attr_find (addentry, ATTR_NSDS5_REPLCONFLICT, &attr) == 0)
			{
				/* ATTR_NSDS5_REPLCONFLICT exists */
				slapi_log_error(SLAPI_LOG_FATAL, sessionid,
				          "urp_add: New entry has nsds5ReplConflict already\n");
				vals = attr_get_present_values (attr); /* this returns a pointer to the contents */
			}
			if ( vals == NULL || *vals == NULL )
			{
				/* Add new attribute */
				slapi_entry_add_string (addentry, ATTR_NSDS5_REPLCONFLICT, buf);
			}
			else
			{
				/*
				 * Replace old attribute. We don't worry about the index
				 * change here since the entry is yet to be added.
				 */
				slapi_value_set_string (*vals, buf);
			}
			/* slapi_pblock_get(pb, SLAPI_ADD_TARGET, &dn); */
			slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn);
			slapi_sdn_free(&sdn);

			slapi_entry_set_normdn(addentry, newdn); /* dn: passin */

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

			rdn = slapi_rdn_new_sdn ( slapi_entry_get_sdn_const(addentry) );
			slapi_log_error (slapi_log_urp, sessionid,
			                 "urp_add: Naming conflict ADD. Add %s instead\n",
			                 slapi_rdn_get_rdn(rdn));
			slapi_rdn_free(&rdn);

			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
			PROFILE_POINT; /* Add Conflict; Entry Exists; Rename Operation Entry */
		}
	}
	else if(r>0)
	{
		/* Existing entry is a loser */
		if (!urp_annotate_dn(sessionid, existing_dn_entry, opcsn, "ADD"))
		{
			op_result= LDAP_OPERATIONS_ERROR;
			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
			slapi_log_error(slapi_log_urp, sessionid,
			                "urp_add (%s): Entry to be added is a loser; "
			                "urp_annotate_dn failed.\n", basedn);
			rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
		}
		else
		{
			/* The backend add code should now search for the existing entry 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; Entry Exists; Rename Existing Entry */
	}
	else /* r==0 */
	{
		/* The CSN of the Operation and the Entry DN are the same.
		 * This could only happen if:
		 * a) There are two replicas with the same ReplicaID.
		 * b) We've seen the Operation before.
		 * Let's go with (b) and ignore the little bastard.
		 */
		/* 
		 * 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
		 */
		/* op_result = LDAP_SUCCESS; */
		slapi_log_error(slapi_log_urp, sessionid,
		"urp_add (%s): The CSN of the Operation and the Entry DN are the same.",
		slapi_entry_get_dn_const(existing_dn_entry));
		op_result= LDAP_UNWILLING_TO_PERFORM;
		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
		rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
		PROFILE_POINT; /* Add Conflict; Entry Exists; Same CSN */
	}

bailout:
	return rc;
}
Пример #9
0
/*  reads the cookie in dse.ldif to the replication agreement entry
	returns: ldap result code of ldap operation, or 
			 LDAP_NO_SUCH_ATTRIBUTE. (this is the equilivent of a null cookie) */
int windows_private_load_dirsync_cookie(const Repl_Agmt *ra)
{
	Dirsync_Private *dp = NULL;
    Slapi_PBlock *pb = NULL;
  
	Slapi_DN* sdn = NULL;
	int rc = 0;
	Slapi_Entry *entry = NULL;
	Slapi_Attr *attr = NULL;

	LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_load_dirsync_cookie\n" );
	PR_ASSERT(ra);

	dp = (Dirsync_Private *) agmt_get_priv(ra);
	PR_ASSERT (dp);


	pb = slapi_pblock_new ();
	sdn = slapi_sdn_dup( agmt_get_dn_byref(ra) );
	

	rc  = slapi_search_internal_get_entry(sdn, NULL, &entry, 
		                                  repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION));

	if (rc == 0)
	{
		rc= slapi_entry_attr_find( entry, type_nsds7DirsyncCookie, &attr );
		if (attr)
		{
			struct berval **vals;
			rc = slapi_attr_get_bervals_copy(attr, &vals );
		
			if (vals)
			{
				dp->dirsync_cookie_len = (int)  (vals[0])->bv_len;
				slapi_ch_free_string(&dp->dirsync_cookie);

				dp->dirsync_cookie = ( char* ) slapi_ch_malloc(dp->dirsync_cookie_len + 1);
				memcpy(dp->dirsync_cookie,(vals[0]->bv_val), (vals[0])->bv_len+1);

			}

			ber_bvecfree(vals);
			/* we do not free attr */

		}
		else
		{
			rc = LDAP_NO_SUCH_ATTRIBUTE;
		}
	}

	if (entry)
	{
		 slapi_entry_free(entry);
	}
	
	slapi_sdn_free( &sdn);
	slapi_pblock_destroy (pb);

	LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_load_dirsync_cookie\n" );

	return rc;
}
Пример #10
0
/*
 * Depending on the context, this routine may need to take the
 * acicache read lock.
*/
void
aclanom_gen_anomProfile (acl_lock_flag_t lock_flag)
{
	aci_t					*aci = NULL;
	int						i;
	Targetattr				**srcattrArray;
	Targetattr				*attr;
	struct	anom_profile	*a_profile;
	PRUint32				cookie;

	PR_ASSERT( lock_flag == DO_TAKE_ACLCACHE_READLOCK ||
				lock_flag == DONT_TAKE_ACLCACHE_READLOCK);

	/*
	 * This routine requires two locks:
	 * the one for the global cache in acllist_acicache_READ_LOCK() and
	 * the one for the anom profile.
	 * They _must_ be taken in the order presented here or there
	 * is a deadlock scenario with acllist_remove_aci_needsLock() which
	 * takes them is this order.
	*/

	if ( lock_flag == DO_TAKE_ACLCACHE_READLOCK ) {
		acllist_acicache_READ_LOCK();
	}
	ANOM_LOCK_WRITE  ();
	a_profile = acl_anom_profile;

	if ( (!acl_get_aclsignature()) || ( !a_profile) ||
			(a_profile->anom_signature ==  acl_get_aclsignature()) ) {
		ANOM_UNLOCK_WRITE ();
		if ( lock_flag == DO_TAKE_ACLCACHE_READLOCK ) {
			acllist_acicache_READ_UNLOCK();
		}
		return;
	}

	/* D0 we have one already. If we do, then clean it up */
	aclanom__del_profile(0);

	/* We have a new signature now */
	a_profile->anom_signature =  acl_get_aclsignature();

	slapi_log_err(SLAPI_LOG_ACL, plugin_name, "aclanom_gen_anomProfile - GENERATING ANOM USER PROFILE\n");
	/*
	** Go thru the ACL list and find all the ACLs  which apply to the 
	** anonymous user i.e anyone. we can generate a profile for that.
	** We will llok at the simple case i.e it matches 
	** cases not handled:
	**  1) When there is a mix if rule types ( allows & denies )
	**
	*/

	aci = acllist_get_first_aci ( NULL, &cookie );	
	while ( aci ) {
		int			a_numacl;
		struct slapi_filter	*f;
		char			**destattrArray;


		/* 
		 * We must not have a  rule like:  deny ( all )  userdn != "xyz" 
		 * or groupdn !=
		*/
		if ( (aci->aci_type &  ACI_HAS_DENY_RULE) &&
			( (aci->aci_type & ACI_CONTAIN_NOT_USERDN ) ||
			  (aci->aci_type & ACI_CONTAIN_NOT_GROUPDN)	||
				(aci->aci_type & ACI_CONTAIN_NOT_ROLEDN)) ){
			slapi_log_err(SLAPI_LOG_ACL, plugin_name, 
				"aclanom_gen_anomProfile - CANCELLING ANOM USER PROFILE BECAUSE OF DENY RULE\n");
			goto cleanup;
		}

		/* Must be a anyone rule */
		if ( aci->aci_elevel != ACI_ELEVEL_USERDN_ANYONE ) {
			aci =  acllist_get_next_aci ( NULL, aci, &cookie);
			continue;
		}
		if (! (aci->aci_access &  ( SLAPI_ACL_READ | SLAPI_ACL_SEARCH)) ) {
			aci =  acllist_get_next_aci ( NULL, aci, &cookie);
			continue;
		}
		/* If the rule has anything other than userdn = "ldap:///anyone"
		** let's not consider complex rules - let's make this lean.
		*/
		if ( aci->aci_ruleType & ~ACI_USERDN_RULE ){
			slapi_log_err(SLAPI_LOG_ACL, plugin_name, 
				"aclanom_gen_anomProfile - CANCELLING ANOM USER PROFILE BECAUSE OF COMPLEX RULE\n");
			goto cleanup;
		}

		/* Must not be a or have a 
		** 1 ) DENY RULE   2) targetfilter
		** 3) no target pattern ( skip monitor acl  )
		*/
		if ( aci->aci_type & ( ACI_HAS_DENY_RULE  | ACI_TARGET_PATTERN |
					ACI_TARGET_NOT | ACI_TARGET_FILTER_NOT )) {
			const char	*dn = slapi_sdn_get_dn ( aci->aci_sdn );

			/* see if this is a monitor acl */
			if (( strcasecmp ( dn, "cn=monitor") == 0 )  ||
			    /* cn=monitor,cn=ldbm: No such object */
			    ( strcasecmp ( dn, "cn=monitor,cn=ldbm") == 0 )) {
				aci =  acllist_get_next_aci ( NULL, aci, &cookie);
				continue;
			} else {
				/* clean up before leaving */
				slapi_log_err(SLAPI_LOG_ACL, plugin_name, 
					"aclanom_gen_anomProfile - CANCELLING ANOM USER PROFILE 1\n");
				goto cleanup;
			}

		}

		/* Now we have an ALLOW ACL which applies to anyone */
		a_numacl = a_profile->anom_numacls++;

		if ( a_profile->anom_numacls == ACL_ANOM_MAX_ACL ) {
			slapi_log_err(SLAPI_LOG_ACL, plugin_name, "aclanom_gen_anomProfile - CANCELLING ANOM USER PROFILE 2\n");
			goto cleanup;
		}

		if ( (f = aci->target) != NULL ) {
			char            *avaType;
			struct berval   *avaValue;
			slapi_filter_get_ava ( f, &avaType, &avaValue );

			a_profile->anom_targetinfo[a_numacl].anom_target = 
						slapi_sdn_new_dn_byval ( avaValue->bv_val );
		} else {
			a_profile->anom_targetinfo[a_numacl].anom_target = 
						slapi_sdn_dup ( aci->aci_sdn );
		}

		a_profile->anom_targetinfo[a_numacl].anom_filter =  NULL;
		if ( aci->targetFilterStr ) {
			a_profile->anom_targetinfo[a_numacl].anom_filter =  slapi_str2filter ( aci->targetFilterStr );
			if (NULL == a_profile->anom_targetinfo[a_numacl].anom_filter) {
				const char	*dn = slapi_sdn_get_dn ( aci->aci_sdn );
				slapi_log_err(SLAPI_LOG_ERR, plugin_name,
								"aclanom_gen_anomProfile - Invalid filter [%s] in anonymous aci in entry [%s]\n",
								aci->targetFilterStr, dn);
				goto cleanup;
			}
		}				

		i = 0;
		srcattrArray = aci->targetAttr;
		while ( srcattrArray[i])
			i++;

		a_profile->anom_targetinfo[a_numacl].anom_targetAttrs = 
					(char **) slapi_ch_calloc ( 1, (i+1) * sizeof(char *));

		srcattrArray = aci->targetAttr;
		destattrArray = a_profile->anom_targetinfo[a_numacl].anom_targetAttrs;

		i = 0;
		while ( srcattrArray[i] ) {
			attr = srcattrArray[i];
			if ( attr->attr_type & ACL_ATTR_FILTER ) {
				/* Do'nt want to support these kind now */
				destattrArray[i] = NULL;
				/* clean up before leaving */
				aclanom__del_profile (0);
				slapi_log_err(SLAPI_LOG_ACL, plugin_name, 
					"aclanom_gen_anomProfile - CANCELLING ANOM USER PROFILE 3\n");
				goto cleanup;
			}

			destattrArray[i] = slapi_ch_strdup ( attr->u.attr_str );
			i++;
		}	

		destattrArray[i] = NULL;

		aclutil_print_aci ( aci, "anom" );	
		/*  Here we are storing att the info from the acls. However
		** we are only interested in a few things like ACI_TARGETATTR_NOT.
		*/
		a_profile->anom_targetinfo[a_numacl].anom_type = aci->aci_type;
		a_profile->anom_targetinfo[a_numacl].anom_access = aci->aci_access;
		
		aci =  acllist_get_next_aci ( NULL, aci, &cookie);
	}

	ANOM_UNLOCK_WRITE ();
	if ( lock_flag == DO_TAKE_ACLCACHE_READLOCK ) {
		acllist_acicache_READ_UNLOCK();
	}
	return;

cleanup:
	aclanom__del_profile (0);
	ANOM_UNLOCK_WRITE ();
	if ( lock_flag == DO_TAKE_ACLCACHE_READLOCK ) {
		acllist_acicache_READ_UNLOCK();
	}
}