/* * memberof_free_config() * * Free's the contents of a config structure. */ void memberof_free_config(MemberOfConfig *config) { if (config) { int i = 0; slapi_ch_array_free(config->groupattrs); slapi_filter_free(config->group_filter, 1); for (i = 0; config->group_slapiattrs && config->group_slapiattrs[i]; i++) { slapi_attr_free(&config->group_slapiattrs[i]); } slapi_ch_free((void **)&config->group_slapiattrs); slapi_ch_free_string(&config->auto_add_oc); slapi_ch_free_string(&config->memberof_attr); memberof_free_scope(config->entryScopes, &config->entryScopeCount); memberof_free_scope(config->entryScopeExcludeSubtrees, &config->entryExcludeScopeCount); } }
/* * 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]); } } } }
/* * 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; } }
/* * 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; } }
/* Validate the pending changes in the e entry. */ static int ipa_winsync_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg) { char **attrsvals = NULL; int ii; Slapi_Attr *testattr = NULL; char *strattr = NULL; int acct_disable; *returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */ /* get realm filter */ if (slapi_entry_attr_find(e, IPA_WINSYNC_REALM_FILTER_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_REALM_FILTER_ATTR); goto done2; } /* get realm attr */ if (slapi_entry_attr_find(e, IPA_WINSYNC_REALM_ATTR_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_REALM_ATTR_ATTR); goto done2; } /* get new_entry_filter */ if (slapi_entry_attr_find(e, IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR); goto done2; } /* get new_user_oc_attr */ if (slapi_entry_attr_find(e, IPA_WINSYNC_NEW_USER_OC_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_NEW_USER_OC_ATTR); goto done2; } /* get homedir_prefix_attr */ if (slapi_entry_attr_find(e, IPA_WINSYNC_HOMEDIR_PREFIX_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_HOMEDIR_PREFIX_ATTR); goto done2; } /* get login_shell_attr */ if (slapi_entry_attr_find(e, IPA_WINSYNC_LOGIN_SHELL_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Warning: no value given for %s", IPA_WINSYNC_LOGIN_SHELL_ATTR); } /* get default_group_attr */ if (slapi_entry_attr_find(e, IPA_WINSYNC_DEFAULTGROUP_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_DEFAULTGROUP_ATTR); goto done2; } /* get default_group_filter */ if (slapi_entry_attr_find(e, IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR); goto done2; } /* get the list of attributes & values */ /* get new_user_oc_attr */ if (!(attrsvals = slapi_entry_attr_get_charray( e, IPA_WINSYNC_NEW_USER_ATTRS_VALS))) { LOG("Info: no default attributes and values given in [%s]\n", IPA_WINSYNC_NEW_USER_ATTRS_VALS); } /* format of *attrsvals is "attrname value" */ /* attrname <space> value */ /* value may contain spaces - attrname is everything up to the first space - value is everything after the first space */ for (ii = 0; attrsvals && attrsvals[ii]; ++ii) { Slapi_Attr *attr = NULL; char *oidp = NULL; char *val = strchr(attrsvals[ii], ' '); if (!val || !*(val+1)) { /* incorrect format or no value */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value or incorrect value given for [%s] " "value [%s] index [%d] - correct format is attrname SPACE value", IPA_WINSYNC_NEW_USER_ATTRS_VALS, attrsvals[ii], ii); goto done2; } *val = '\0'; /* separate attr from val */ /* check to make sure attribute is in the schema */ attr = slapi_attr_new(); slapi_attr_set_type(attr, attrsvals[ii]); slapi_attr_get_oid_copy(attr, &oidp); slapi_attr_free(&attr); if (oidp == NULL) { /* no such attribute */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: invalid attribute name [%s] given for [%s] " "at index [%d] - attribute is not in server schema", attrsvals[ii], IPA_WINSYNC_NEW_USER_ATTRS_VALS, ii); goto done2; } /* attribute is valid - continue */ slapi_ch_free_string(&oidp); } /* get account disable sync direction */ if (!(strattr = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_ACCT_DISABLE))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_ACCT_DISABLE); goto done2; } acct_disable = parse_acct_disable(strattr); if (ACCT_DISABLE_INVALID == acct_disable) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: invalid value [%s] given for [%s] - valid " "values are " IPA_WINSYNC_ACCT_DISABLE_NONE ", " IPA_WINSYNC_ACCT_DISABLE_TO_AD ", " IPA_WINSYNC_ACCT_DISABLE_TO_DS ", or " IPA_WINSYNC_ACCT_DISABLE_BOTH, strattr, IPA_WINSYNC_ACCT_DISABLE); goto done2; } /* if using acct disable sync, must have the attributes IPA_WINSYNC_INACTIVATED_FILTER and IPA_WINSYNC_ACTIVATED_FILTER */ if (acct_disable != ACCT_DISABLE_NONE) { if (slapi_entry_attr_find(e, IPA_WINSYNC_INACTIVATED_FILTER, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "No value given for %s - required for account " "disable sync, ignoring", IPA_WINSYNC_INACTIVATED_FILTER); } if (slapi_entry_attr_find(e, IPA_WINSYNC_ACTIVATED_FILTER, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "No value given for %s - required for account " "disable sync, ignoring", IPA_WINSYNC_ACTIVATED_FILTER); } } /* success */ *returncode = LDAP_SUCCESS; done2: slapi_ch_free_string(&strattr); slapi_ch_array_free(attrsvals); attrsvals = NULL; if (*returncode != LDAP_SUCCESS) { return SLAPI_DSE_CALLBACK_ERROR; } else { return SLAPI_DSE_CALLBACK_OK; } }
/* * Extract the payload from a total update extended operation, * decode it, and produce a Slapi_Entry structure representing a new * entry to be added to the local database. */ static int decode_total_update_extop(Slapi_PBlock *pb, Slapi_Entry **ep) { BerElement *tmp_bere = NULL; Slapi_Entry *e = NULL; Slapi_Attr *attr = NULL; char *str = NULL; struct berval *extop_value = NULL; char *extop_oid = NULL; ber_len_t len; char *lasto; ber_tag_t tag; int rc; PRBool deleted; PR_ASSERT(NULL != pb); PR_ASSERT(NULL != ep); slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid); slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value); if ((NULL == extop_oid) || ((strcmp(extop_oid, REPL_NSDS50_REPLICATION_ENTRY_REQUEST_OID) != 0) && (strcmp(extop_oid, REPL_NSDS71_REPLICATION_ENTRY_REQUEST_OID) != 0)) || !BV_HAS_DATA(extop_value)) { /* Bogus */ goto loser; } if ((tmp_bere = ber_init(extop_value)) == NULL) { goto loser; } if ((e = slapi_entry_alloc()) == NULL) { goto loser; } if (ber_scanf(tmp_bere, "{") == LBER_ERROR) /* Begin outer sequence */ { goto loser; } /* The entry's uniqueid is first */ if (ber_scanf(tmp_bere, "a", &str) == LBER_ERROR) { goto loser; } slapi_entry_set_uniqueid(e, str); str = NULL; /* Slapi_Entry now owns the uniqueid */ /* The entry's DN is next */ if (ber_scanf(tmp_bere, "a", &str) == LBER_ERROR) { goto loser; } slapi_entry_set_dn(e, str); str = NULL; /* Slapi_Entry now owns the dn */ /* Get the attributes */ for ( tag = ber_first_element( tmp_bere, &len, &lasto ); tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET; tag = ber_next_element( tmp_bere, &len, lasto ) ) { if (my_ber_scanf_attr (tmp_bere, &attr, &deleted) != 0) { goto loser; } /* Add the attribute to the entry */ if (deleted) entry_add_deleted_attribute_wsi(e, attr); /* entry now owns attr */ else entry_add_present_attribute_wsi(e, attr); /* entry now owns attr */ attr = NULL; } if (ber_scanf(tmp_bere, "}") == LBER_ERROR) /* End sequence for this entry */ { goto loser; } /* Check for ldapsubentries and tombstone entries to set flags properly */ slapi_entry_attr_find(e, "objectclass", &attr); if (attr != NULL) { struct berval bv; bv.bv_val = "ldapsubentry"; bv.bv_len = strlen(bv.bv_val); if (slapi_attr_value_find(attr, &bv) == 0) { slapi_entry_set_flag(e, SLAPI_ENTRY_LDAPSUBENTRY); } bv.bv_val = SLAPI_ATTR_VALUE_TOMBSTONE; bv.bv_len = strlen(bv.bv_val); if (slapi_attr_value_find(attr, &bv) == 0) { slapi_entry_set_flag(e, SLAPI_ENTRY_FLAG_TOMBSTONE); } } /* If we get here, the entry is properly constructed. Return it. */ rc = 0; *ep = e; goto free_and_return; loser: rc = -1; /* slapi_ch_free accepts NULL pointer */ slapi_ch_free((void **)&str); if (attr != NULL) { slapi_attr_free (&attr); } if (NULL != e) { slapi_entry_free (e); } *ep = NULL; slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Error: could not decode extended " "operation containing entry for total update.\n"); free_and_return: if (NULL != tmp_bere) { ber_free(tmp_bere, 1); tmp_bere = NULL; } return rc; }
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; }