Beispiel #1
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;
	}
}
Beispiel #2
0
/*
 * memberof_apply_config()
 *
 * Apply the pending changes in the e entry to our config struct.
 * memberof_validate_config()  must have already been called.
 */
int
memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, 
	int *returncode, char *returntext, void *arg)
{
	Slapi_Entry *config_entry = NULL;
	Slapi_DN *config_sdn = NULL;
	char **groupattrs = NULL;
	char *memberof_attr = NULL;
	char *filter_str = NULL;
	int num_groupattrs = 0;
	int groupattr_name_len = 0;
	char *allBackends = NULL;
	char **entryScopes = NULL;
	char **entryScopeExcludeSubtrees = NULL;
	char *sharedcfg = NULL;
	char *skip_nested = NULL;
	char *auto_add_oc = NULL;
	int num_vals = 0;

	*returncode = LDAP_SUCCESS;

	/*
	 * Check if this is a shared config entry
	 */
	sharedcfg = slapi_entry_attr_get_charptr(e, SLAPI_PLUGIN_SHARED_CONFIG_AREA);
	if(sharedcfg){
		if((config_sdn = slapi_sdn_new_dn_byval(sharedcfg))){
			slapi_search_internal_get_entry(config_sdn, NULL, &config_entry, memberof_get_plugin_id());
			if(config_entry){
				/* Set the entry to be the shared config entry.  Validation was done in preop */
				e = config_entry;
			} else {
				/* This should of been checked in preop validation */
				PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
					"memberof_apply_config - Failed to locate shared config entry (%s)",
					sharedcfg);
				slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM,"%s\n",returntext);
				*returncode = LDAP_UNWILLING_TO_PERFORM;
				goto done;
			}
		}
	}

	/*
	 * Apply the config settings
	 */
	groupattrs = slapi_entry_attr_get_charray(e, MEMBEROF_GROUP_ATTR);
	memberof_attr = slapi_entry_attr_get_charptr(e, MEMBEROF_ATTR);
	allBackends = slapi_entry_attr_get_charptr(e, MEMBEROF_BACKEND_ATTR);
	skip_nested = slapi_entry_attr_get_charptr(e, MEMBEROF_SKIP_NESTED_ATTR);
	auto_add_oc = slapi_entry_attr_get_charptr(e, MEMBEROF_AUTO_ADD_OC);

	/*
	 * We want to be sure we don't change the config in the middle of
	 * a memberOf operation, so we obtain an exclusive lock here
	 */
	memberof_wlock_config();

	if (groupattrs)
	{
		int i = 0;

		slapi_ch_array_free(theConfig.groupattrs);
		theConfig.groupattrs = groupattrs;
		groupattrs = NULL; /* config now owns memory */

		/*
		 * We allocate a list of Slapi_Attr using the groupattrs for
		 * convenience in our memberOf comparison functions
		 */
		for (i = 0; theConfig.group_slapiattrs && theConfig.group_slapiattrs[i]; i++)
		{
			slapi_attr_free(&theConfig.group_slapiattrs[i]);
		}

		/* Count the number of groupattrs. */
		for (num_groupattrs = 0; theConfig.groupattrs && theConfig.groupattrs[num_groupattrs]; num_groupattrs++)
		{
			/*
			 * Add up the total length of all attribute names.  We need
			 * to know this for building the group check filter later.
			 */
			groupattr_name_len += strlen(theConfig.groupattrs[num_groupattrs]);
		}

		/* Realloc the list of Slapi_Attr if necessary. */
		if (i < num_groupattrs)
		{
			theConfig.group_slapiattrs = (Slapi_Attr **)slapi_ch_realloc((char *)theConfig.group_slapiattrs,
							sizeof(Slapi_Attr *) * (num_groupattrs + 1));
		}

		/* Build the new list */
		for (i = 0; theConfig.groupattrs[i]; i++)
		{
			theConfig.group_slapiattrs[i] = slapi_attr_new();
			slapi_attr_init(theConfig.group_slapiattrs[i], theConfig.groupattrs[i]);
		}

		/* Terminate the list. */
		theConfig.group_slapiattrs[i] = NULL;

		/* The filter is based off of the groupattr, so we update it here too. */
		slapi_filter_free(theConfig.group_filter, 1);

		if (num_groupattrs > 1)
		{
			int bytes_out = 0;
			int filter_str_len = groupattr_name_len + (num_groupattrs * 4) + 4;

			/* Allocate enough space for the filter */
			filter_str = slapi_ch_malloc(filter_str_len);

			/* Add beginning of filter. */
			bytes_out = snprintf(filter_str, filter_str_len - bytes_out, "(|");

			/* Add filter section for each groupattr. */
			for (i = 0; theConfig.groupattrs[i]; i++)
			{
				bytes_out += snprintf(filter_str + bytes_out, filter_str_len - bytes_out, "(%s=*)", theConfig.groupattrs[i]);
			}

			/* Add end of filter. */
			snprintf(filter_str + bytes_out, filter_str_len - bytes_out, ")");
		}
		else
		{
			filter_str = slapi_ch_smprintf("(%s=*)", theConfig.groupattrs[0]);
		}

		/*
		 * Log an error if we were unable to build the group filter for some
		 * reason.  If this happens, the memberOf plugin will not be able to
		 * check if an entry is a group, causing it to not catch changes.  This
		 * shouldn't happen, but there may be some garbage configuration that
		 * could trigger this.
		 */
		if ((theConfig.group_filter = slapi_str2filter(filter_str)) == NULL)
		{
			slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM,
				"memberof_apply_config - Unable to create the group check filter.  The memberOf "
				"plug-in will not operate on changes to groups.  Please check "
				"your %s configuration settings. (filter: %s)\n",
				MEMBEROF_GROUP_ATTR, filter_str );
		}

		slapi_ch_free_string(&filter_str);
	}

	if (memberof_attr)
	{
		slapi_ch_free_string(&theConfig.memberof_attr);
		theConfig.memberof_attr = memberof_attr;
		memberof_attr = NULL; /* config now owns memory */
	}

	if (skip_nested){
		if(strcasecmp(skip_nested,"on") == 0){
			theConfig.skip_nested = 1;
		} else {
			theConfig.skip_nested = 0;
		}
	}

	if (allBackends)
	{
		if(strcasecmp(allBackends,"on")==0){
			theConfig.allBackends = 1;
		} else {
			theConfig.allBackends = 0;
		}
	} else {
		theConfig.allBackends = 0;
	}

	theConfig.auto_add_oc = auto_add_oc;

	/*
	 * Check and process the entry scopes
	 */
	memberof_free_scope(theConfig.entryScopes, &theConfig.entryScopeCount);
	entryScopes = slapi_entry_attr_get_charray_ext(e, MEMBEROF_ENTRY_SCOPE_ATTR, &num_vals);
	if(entryScopes){
		int i = 0;

		/* Validation has already been performed in preop, just build the DN's */
		theConfig.entryScopes = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *), num_vals+1);
		for (i = 0;i < num_vals; i++){
			theConfig.entryScopes[i] = slapi_sdn_new_dn_passin(entryScopes[i]);
		}
		theConfig.entryScopeCount = num_vals; /* shortcut for config copy */
	}
	/*
	 * Check and process the entry exclude scopes
	 */
	memberof_free_scope(theConfig.entryScopeExcludeSubtrees,
	                    &theConfig.entryExcludeScopeCount);
	entryScopeExcludeSubtrees =
	    slapi_entry_attr_get_charray_ext(e, MEMBEROF_ENTRY_SCOPE_EXCLUDE_SUBTREE, &num_vals);
	if(entryScopeExcludeSubtrees){
		int i = 0;

		/* Validation has already been performed in preop, just build the DN's */
		theConfig.entryScopeExcludeSubtrees =
				(Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),num_vals+1);
		for (i = 0;i < num_vals; i++){
			theConfig.entryScopeExcludeSubtrees[i] =
				slapi_sdn_new_dn_passin(entryScopeExcludeSubtrees[i]);
		}
		theConfig.entryExcludeScopeCount = num_vals; /* shortcut for config copy */
	}

	/* release the lock */
	memberof_unlock_config();

done:
	slapi_sdn_free(&config_sdn);
	slapi_entry_free(config_entry);
	slapi_ch_array_free(groupattrs);
	slapi_ch_free_string(&sharedcfg);
	slapi_ch_free_string(&memberof_attr);
	slapi_ch_free_string(&allBackends);
	slapi_ch_free_string(&skip_nested);
	slapi_ch_free((void **)&entryScopes);
	slapi_ch_free((void **)&entryScopeExcludeSubtrees);

	if (*returncode != LDAP_SUCCESS)
	{
		return SLAPI_DSE_CALLBACK_ERROR;
	}
	else
	{
		return SLAPI_DSE_CALLBACK_OK;
	}
}
Beispiel #3
0
static int 
my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted)
{
    char *attrtype = NULL;
    CSN *attr_deletion_csn = NULL;
    PRBool val_deleted;
    char *lasti;
    ber_len_t len;
    ber_tag_t tag;
    char *str = NULL;
    int rc;
    Slapi_Value *value = NULL;

    if (attr == NULL)
    {
        goto loser;
    }

    PR_ASSERT (ber && attr && deleted);

    /* allocate the attribute */
    *attr = slapi_attr_new ();
    if (*attr == NULL)
    {
        goto loser;
    }

	if (ber_scanf(ber, "{a", &attrtype) == LBER_ERROR) /* Begin sequence for this attr */
	{
		goto loser;
	}


    slapi_attr_init(*attr, attrtype);
    slapi_ch_free ((void **)&attrtype);

	/* The attribute deletion CSN is next and is optional? */
    if (ber_peek_tag(ber, &len) == LBER_OCTETSTRING)
    {
	    if (ber_scanf(ber, "a", &str) == LBER_ERROR)
	    {
		    goto loser;
	    }
	    attr_deletion_csn = csn_new_by_string(str);
	    slapi_ch_free((void **)&str);
    }

    if (attr_deletion_csn)
	{
		rc = attr_set_deletion_csn(*attr, attr_deletion_csn);
        csn_free (&attr_deletion_csn);
        if (rc != 0)
        {
            goto loser;
        }
	}

	/* The "attribute deleted" flag is next, and is optional */
	if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
	{
		if (ber_scanf(ber, "b", deleted) == LBER_DEFAULT)
		{
			goto loser;
		}
	} 
    else /* default is present */
    {
		*deleted = PR_FALSE;
	}
	
    /* loop over the list of attribute values */
	for (tag = ber_first_element(ber, &len, &lasti);
		tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
		tag = ber_next_element(ber, &len, lasti))
	{

		value = NULL;		
		if (my_ber_scanf_value(ber, &value, &val_deleted) == -1)
		{
			goto loser;
		}

        if (val_deleted)
        {
			/* Add the value to the attribute */
			if (attr_add_deleted_value(*attr, value) == -1) /* attr has ownership of value */
			{
				goto loser;
			}
        }
        else
        {
            /* Add the value to the attribute */
			if (slapi_attr_add_value(*attr, value) == -1) /* attr has ownership of value */
			{
				goto loser;
			}
        }
		if (value)
			slapi_value_free(&value);
	}	

	if (ber_scanf(ber, "}") == LBER_ERROR) /* End sequence for this attribute */
	{
		goto loser;
	}

    return 0;
loser:
    if (attr && *attr)
        slapi_attr_free (attr);
    if (value)
        slapi_value_free (&value);

    slapi_ch_free_string(&attrtype);
    slapi_ch_free_string(&str);

    return -1;    
}