/* * hasObjectClass - read an entry and check if it has a * particular object class value * Return: * 1 - the entry contains the object class value * 0 - the entry doesn't contain the object class value */ int entryHasObjectClass(Slapi_PBlock *pb, Slapi_Entry *e, const char *objectClass) { Slapi_Attr *attr; Slapi_Value *v; const struct berval *bv; int vhint; if ( slapi_entry_attr_find(e, "objectclass", &attr) ) { return 0; /* no objectclass values! */ } /* * Check each of the object class values in turn. */ for ( vhint = slapi_attr_first_value( attr, &v ); vhint != -1; vhint = slapi_attr_next_value( attr, vhint, &v )) { bv = slapi_value_get_berval(v); if ( NULL != bv && NULL != bv->bv_val && !strcasecmp(bv->bv_val, objectClass) ) { return 1; } } return 0; }
/* Pre-operation plug-in function */ int testpreop_add( Slapi_PBlock *pb ) { Slapi_Entry *e; Slapi_Attr *a; Slapi_Value *v; struct berval **bvals; int i, hint; char *tmp; const char *s; /* Get the entry that is about to be added. */ if ( slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e ) != 0 ) { slapi_log_err(SLAPI_LOG_PLUGIN, "testpreop_add", "Could not get entry\n" ); return( -1 ); } /* Prepend the name "BOB" to the value of the cn attribute in the entry. */ if ( slapi_entry_attr_find( e, "cn", &a ) == 0 ) { for ( hint = slapi_attr_first_value( a, &v ); hint != -1; hint = slapi_attr_next_value( a, hint, &v )) { s = slapi_value_get_string( v ); tmp = (char *) malloc( 5 + strlen( s )); strcpy( tmp, "BOB " ); strcat( tmp + 4, s ); slapi_value_set_string( v, tmp ); free( tmp ); } } return( 0 ); /* allow the operation to continue */ }
/* * search - search a subtree for entries with a named attribute matching * the list of values. An entry matching the 'target' DN is * not considered in the search. * * If 'attr' is NULL, the values are taken from 'values'. * If 'attr' is non-NULL, the values are taken from 'attr'. * * Return: * LDAP_SUCCESS - no matches, or the attribute matches the * target dn. * LDAP_CONSTRAINT_VIOLATION - an entry was found that already * contains the attribute value. * LDAP_OPERATIONS_ERROR - a server failure. */ static int search(Slapi_DN *baseDN, const char *attrName, Slapi_Attr *attr, struct berval **values, const char *requiredObjectClass, Slapi_DN *target) { int result; #ifdef DEBUG slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "SEARCH baseDN=%s attr=%s target=%s\n", slapi_sdn_get_dn(baseDN), attrName, target?slapi_sdn_get_dn(target):"None"); #endif result = LDAP_SUCCESS; /* If no values, can't possibly be a conflict */ if ( (Slapi_Attr *)NULL == attr && (struct berval **)NULL == values ) return result; /* * Perform the search for each value provided * * Another possibility would be to search for all the values at once. * However, this is more complex (for filter creation) and unique * attributes values are probably only changed one at a time anyway. */ if ( (Slapi_Attr *)NULL != attr ) { Slapi_Value *v = NULL; int vhint = -1; for ( vhint = slapi_attr_first_value( attr, &v ); vhint != -1 && LDAP_SUCCESS == result; vhint = slapi_attr_next_value( attr, vhint, &v )) { result = search_one_berval(baseDN, attrName, slapi_value_get_berval(v), requiredObjectClass, target); } } else { for (;*values != NULL && LDAP_SUCCESS == result; values++) { result = search_one_berval(baseDN, attrName, *values, requiredObjectClass, target); } } #ifdef DEBUG slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "SEARCH result = %d\n", result); #endif return( result ); }
LDAPWAStatus WindowsAuthentication( struct backentry *e, struct berval *cred ) { Slapi_Attr *a; Slapi_Value *sval = NULL; int iStatus; char szNTDomain[MAX_PATH], szNTUsername[MAX_PATH]; HANDLE hToken = NULL; BOOL bLogonStatus = FALSE; int i= -1; /* Get the NT Domain and username - if the entry has such an attribute */ if( !e || !e->ep_entry || slapi_entry_attr_find( e->ep_entry, "ntuserdomainid", &a ) != 0) { return( LDAPWA_NoDomainAttr ); } i= slapi_attr_first_value( a, &sval ); if(sval==NULL) { return( LDAPWA_NoDomainAttr ); } while(i != -1) { const struct berval *val = slapi_value_get_berval(sval); char * colon = NULL; if (!val->bv_val || (strlen(val->bv_val) > (MAX_PATH<<1))) { LDAPDebug( LDAP_DEBUG_TRACE, "WindowsAuthentication => validation FAILED for \"%s\" on NT Domain : " "ntuserdomainid attr value too long\n", val->bv_val, 0, 0); i= slapi_attr_next_value(a, i, &sval); continue; } colon = strchr( val->bv_val, ':' ); if (!colon || ((colon - val->bv_val)/sizeof(char) > MAX_PATH)) { if (!colon) { LDAPDebug( LDAP_DEBUG_TRACE, "WindowsAuthentication => validation FAILED for \"%s\" on NT Domain : " "a colon is missing in ntuserdomainid attr value\n", val->bv_val, 0, 0); } else { LDAPDebug( LDAP_DEBUG_TRACE, "WindowsAuthentication => validation FAILED for \"%s\" on NT Domain : " "domain in ntuserdomainid attr value too long\n", val->bv_val, 0, 0); } i= slapi_attr_next_value(a, i, &sval); continue; } if(( iStatus = GetDomainUsername( val->bv_val, szNTDomain, szNTUsername )) != 0) { i= slapi_attr_next_value(a, i, &sval); continue; } #if !defined( LOGON32_LOGON_NETWORK ) /* This is specified in the WIn32 LogonUser() documentation, but not defined in the Visual C++ 4.2 include file winbase.h. A search of the lastest version of this file at www.microsoft.com finds that LOGON32_LOGON_NETWORK == 3. */ #define LOGON32_LOGON_NETWORK 3 #endif /* Now do the Logon attempt */ bLogonStatus = LogonUser( szNTUsername, // string that specifies the user name szNTDomain, // string that specifies the domain or server cred->bv_val, // string that specifies the password LOGON32_LOGON_NETWORK, // the type of logon operation, LOGON32_PROVIDER_DEFAULT, // specifies the logon provider &hToken ); // pointer to variable to receive token handle if( bLogonStatus && hToken ) CloseHandle( hToken ); if( bLogonStatus ) { // Successful validation LDAPDebug( LDAP_DEBUG_TRACE, "WindowsAuthentication => validated \"%s\" on NT Domain \"%s\"\n", szNTUsername, szNTDomain, 0 ); return( LDAPWA_Success ); } else { LDAPDebug( LDAP_DEBUG_TRACE, "WindowsAuthentication => validation FAILED for \"%s\" on NT Domain \"%s\", reason %d\n", szNTUsername, szNTDomain, GetLastError() ); return( LDAPWA_InvalidCredentials ); } i= slapi_attr_next_value(a, i, &sval); } return( LDAPWA_Failure ); }
/*************************************************************************** * * __aclinit_handler * * For each entry, finds if there is any ACL in that entry. If there is * then the ACL is processed and stored in the ACL LIST. * * * Input: * * * Returns: * None. * * Error Handling: * If any error found during the ACL generation, the ACL is * logged. Also, set in the callback_data so that caller can act upon it. * **************************************************************************/ static int __aclinit_handler ( Slapi_Entry *e, void *callback_data) { Slapi_Attr *attr; aclinit_handler_callback_data_t *call_back_data = (aclinit_handler_callback_data_t*)callback_data; Slapi_DN *e_sdn; int rv; Slapi_Value *sval=NULL; call_back_data->retCode = 0; /* assume success--if there's an error we overwrite it */ if (e != NULL) { e_sdn = slapi_entry_get_sdn ( e ); /* * Take the write lock around all the mods--so that * other operations will see the acicache either before the whole mod * or after but not, as it was before, during the mod. * This is in line with the LDAP concept of the operation * on the whole entry being the atomic unit. * */ if ( call_back_data->op == ACL_ADD_ACIS ) { slapi_log_err(SLAPI_LOG_ACL, plugin_name, "Adding acis for entry '%s'\n", slapi_sdn_get_dn(e_sdn)); slapi_entry_attr_find ( e, aci_attr_type, &attr ); if ( attr ) { const struct berval *attrValue; int i; if ( call_back_data->lock_flag == DO_TAKE_ACLCACHE_WRITELOCK) { acllist_acicache_WRITE_LOCK(); } i= slapi_attr_first_value ( attr, &sval ); while(i != -1) { attrValue = slapi_value_get_berval(sval); if ( 0 != (rv=acllist_insert_aci_needsLock (e_sdn, attrValue))) { aclutil_print_err(rv, e_sdn, attrValue, NULL); /* We got an error; Log it and then march along */ slapi_log_err(SLAPI_LOG_ERR, plugin_name, "__aclinit_handler - This (%s) ACL will not be considered for evaluation" " because of syntax errors.\n", attrValue->bv_val ? attrValue->bv_val: "NULL"); call_back_data->retCode = rv; } i= slapi_attr_next_value( attr, i, &sval ); }/* while */ if ( call_back_data->lock_flag == DO_TAKE_ACLCACHE_WRITELOCK) { acllist_acicache_WRITE_UNLOCK(); } } } else if (call_back_data->op == ACL_REMOVE_ACIS) { /* Here we are deleting the acis. */ slapi_log_err(SLAPI_LOG_ACL, plugin_name, "__aclinit_handler - Removing acis\n"); if ( call_back_data->lock_flag == DO_TAKE_ACLCACHE_WRITELOCK) { acllist_acicache_WRITE_LOCK(); } if ( 0 != (rv=acllist_remove_aci_needsLock(e_sdn, NULL))) { aclutil_print_err(rv, e_sdn, NULL, NULL); /* We got an error; Log it and then march along */ slapi_log_err(SLAPI_LOG_ERR, plugin_name, "__aclinit_handler - ACLs not deleted from %s\n", slapi_sdn_get_dn(e_sdn)); call_back_data->retCode = rv; } if ( call_back_data->lock_flag == DO_TAKE_ACLCACHE_WRITELOCK) { acllist_acicache_WRITE_UNLOCK(); } } } /* * If we get here it's success. * The call_back_data->error is the error code that counts as it's the * one that the original caller will see--this routine is called off a callbacl. */ return ACL_FALSE; /* "local" error code--it's 0 */ }
/* * update multiple attribute values per _do_modify */ static int _update_all_per_mod(Slapi_DN *entrySDN, /* DN of the searched entry */ Slapi_Attr *attr, /* referred attribute */ char *attrName, Slapi_DN *origDN, /* original DN that was modified */ char *newRDN, /* new RDN from modrdn */ const char *newsuperior, /* new superior from modrdn */ Slapi_PBlock *mod_pb) { Slapi_Mods *smods = NULL; char *newDN = NULL; char **dnParts = NULL; char *sval = NULL; char *newvalue = NULL; char *p = NULL; size_t dnlen = 0; int rc = 0; int nval = 0; slapi_attr_get_numvalues(attr, &nval); if (NULL == newRDN && NULL == newsuperior) { /* in delete mode */ LDAPMod *mods[2]; char *values_del[2]; LDAPMod attribute1; /* delete old dn so set that up */ values_del[0] = (char *)slapi_sdn_get_dn(origDN); values_del[1] = NULL; attribute1.mod_type = attrName; attribute1.mod_op = LDAP_MOD_DELETE; attribute1.mod_values = values_del; mods[0] = &attribute1; /* terminate list of mods. */ mods[1] = NULL; rc = _do_modify(mod_pb, entrySDN, mods); if (rc) { slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "_update_all_per_mod: entry %s: deleting \"%s: %s\" failed (%d)" "\n", slapi_sdn_get_dn(entrySDN), attrName, slapi_sdn_get_dn(origDN), rc); } } else { /* in modrdn mode */ const char *superior = NULL; int nval = 0; Slapi_Value *v = NULL; if (NULL == origDN) { slapi_log_error(SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "_update_all_per_mod: NULL dn was passed\n"); goto bail; } /* need to put together rdn into a dn */ dnParts = slapi_ldap_explode_dn( slapi_sdn_get_dn(origDN), 0 ); if (NULL == dnParts) { slapi_log_error(SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "_update_all_per_mod: failed to explode dn %s\n", slapi_sdn_get_dn(origDN)); goto bail; } if (NULL == newRDN) { newRDN = dnParts[0]; } if (newsuperior) { superior = newsuperior; } else { /* do not free superior */ superior = slapi_dn_find_parent(slapi_sdn_get_dn(origDN)); } /* newRDN and superior are already normalized. */ newDN = slapi_ch_smprintf("%s,%s", newRDN, superior); slapi_dn_ignore_case(newDN); /* * Compare the modified dn with the value of * the target attribute of referint to find out * the modified dn is the ancestor (case 2) or * the value itself (case 1). * * E.g., * (case 1) * modrdn: uid=A,ou=B,o=C --> uid=A',ou=B',o=C * (origDN) (newDN) * member: uid=A,ou=B,ou=C --> uid=A',ou=B',ou=C * (sval) (newDN) * * (case 2) * modrdn: ou=B,o=C --> ou=B',o=C * (origDN) (newDN) * member: uid=A,ou=B,ou=C --> uid=A,ou=B',ou=C * (sval) (sval' + newDN) */ slapi_attr_get_numvalues(attr, &nval); smods = slapi_mods_new(); slapi_mods_init(smods, 2 * nval + 1); for (nval = slapi_attr_first_value(attr, &v); nval != -1; nval = slapi_attr_next_value(attr, nval, &v)) { p = NULL; dnlen = 0; /* DN syntax, which should be a string */ sval = slapi_ch_strdup(slapi_value_get_string(v)); rc = slapi_dn_normalize_case_ext(sval, 0, &p, &dnlen); if (rc == 0) { /* sval is passed in; not terminated */ *(p + dnlen) = '\0'; sval = p; } else if (rc > 0) { slapi_ch_free_string(&sval); sval = p; } /* else: (rc < 0) Ignore the DN normalization error for now. */ p = PL_strstr(sval, slapi_sdn_get_ndn(origDN)); if (p == sval) { /* (case 1) */ slapi_mods_add_string(smods, LDAP_MOD_DELETE, attrName, sval); slapi_mods_add_string(smods, LDAP_MOD_ADD, attrName, newDN); } else if (p) { /* (case 2) */ slapi_mods_add_string(smods, LDAP_MOD_DELETE, attrName, sval); *p = '\0'; newvalue = slapi_ch_smprintf("%s%s", sval, newDN); slapi_mods_add_string(smods, LDAP_MOD_ADD, attrName, newvalue); slapi_ch_free_string(&newvalue); } /* else: value does not include the modified DN. Ignore it. */ slapi_ch_free_string(&sval); } rc = _do_modify(mod_pb, entrySDN, slapi_mods_get_ldapmods_byref(smods)); if (rc) { slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "_update_all_per_mod: entry %s failed (%d)\n", slapi_sdn_get_dn(entrySDN), rc); } /* cleanup memory allocated for dnParts and newDN */ if (dnParts){ slapi_ldap_value_free(dnParts); dnParts = NULL; } slapi_ch_free_string(&newDN); slapi_mods_free(&smods); } bail: return rc; }
/* See if the given entry has an attribute with the given name and the given value; if value is NULL, just test for the presence of the given attribute; if value is an empty string (i.e. value[0] == 0), the first value in the attribute will be copied into the given buffer and returned */ static int entry_has_attr_and_value(Slapi_Entry *e, const char *attrname, char *value, size_t valuebufsize ) { int retval = 0; Slapi_Attr *attr = 0; if (!e || !attrname) return retval; /* see if the entry has the specified attribute name */ if (!slapi_entry_attr_find(e, attrname, &attr) && attr) { /* if value is not null, see if the attribute has that value */ if (!value) { retval = 1; } else { Slapi_Value *v = 0; int index = 0; for (index = slapi_attr_first_value(attr, &v); v && (index != -1); index = slapi_attr_next_value(attr, index, &v)) { const char *s = slapi_value_get_string(v); if (!s) continue; if (!*value) { size_t len = strlen(s); if ( len < valuebufsize ) { strcpy(value, s); retval = 1; } else { slapi_log_error( SLAPI_LOG_FATAL, "bootstrap config", "Ignoring extremely large value for" " configuration attribute %s" " (length=%ld, value=%40.40s...)\n", attrname, len, s ); retval = 0; /* value is too large: ignore it */ } break; } else if (!strcasecmp(s, value)) { retval = 1; break; } } } } return retval; }
/* * 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; } }
/* send a single attribute */ static int my_ber_printf_attr (BerElement *ber, Slapi_Attr *attr, PRBool deleted) { Slapi_Value *value; char *type; int i; const CSN *csn; /* First, send the type */ slapi_attr_get_type(attr, &type); BER_DEBUG("{s(type "); BER_DEBUG(type); BER_DEBUG(")"); if (ber_printf(ber, "{s", type) == -1) /* Begin sequence for this type */ { goto loser; } /* Send the attribute deletion CSN if present */ csn = attr_get_deletion_csn(attr); if (csn) { if (my_ber_printf_csn(ber, csn, CSN_TYPE_ATTRIBUTE_DELETED) == -1) { goto loser; } } /* only send "is deleted" flag for deleted attributes since it defaults to false */ if (deleted) { BER_DEBUG("b(del flag)"); if (ber_printf (ber, "b", PR_TRUE) == -1) { goto loser; } } /* * Iterate through all the values. */ BER_DEBUG("["); if (ber_printf(ber, "[") == -1) /* Begin set */ { goto loser; } /* * Process the non-deleted values first. */ i = slapi_attr_first_value(attr, &value); while (i != -1) { if (my_ber_printf_value(ber, type, value, PR_FALSE) == -1) { goto loser; } i= slapi_attr_next_value(attr, i, &value); } /* * Now iterate over all of the deleted values. */ i= attr_first_deleted_value(attr, &value); while (i != -1) { if (my_ber_printf_value(ber, type, value, PR_TRUE) == -1) { goto loser; } i= attr_next_deleted_value(attr, i, &value); } BER_DEBUG("]"); if (ber_printf(ber, "]") == -1) /* End set */ { goto loser; } BER_DEBUG("}"); if (ber_printf(ber, "}") == -1) /* End sequence for this type */ { goto loser; } return 0; loser: return -1; }