/* Handles the parsing of the config entry for an ldbm instance. Returns 0 * on success. */ static int parse_ldbm_instance_config_entry(ldbm_instance *inst, Slapi_Entry *e, config_info *config_array) { Slapi_Attr *attr = NULL; for (slapi_entry_first_attr(e, &attr); attr; slapi_entry_next_attr(e, attr, &attr)) { char *attr_name = NULL; Slapi_Value *sval = NULL; struct berval *bval; char err_buf[BUFSIZ]; slapi_attr_get_type(attr, &attr_name); /* There are some attributes that we don't care about, * like objectclass. */ if (ldbm_config_ignored_attr(attr_name)) { continue; } /* We have to handle suffix attributes a little differently */ if (strcasecmp(attr_name, CONFIG_INSTANCE_SUFFIX) == 0) { Slapi_DN suffix; slapi_attr_first_value(attr, &sval); bval = (struct berval *) slapi_value_get_berval(sval); slapi_sdn_init_dn_byref(&suffix, bval->bv_val); if (!slapi_be_issuffix(inst->inst_be, &suffix)) { be_addsuffix(inst->inst_be, &suffix); } slapi_sdn_done(&suffix); continue; } /* We are assuming that each of these attributes are to have * only one value. If they have more than one value, like * the nsslapd-suffix attribute, then they need to be * handled differently. */ slapi_attr_first_value(attr, &sval); bval = (struct berval *) slapi_value_get_berval(sval); if (ldbm_config_set((void *) inst, attr_name, config_array, bval, err_buf, CONFIG_PHASE_STARTUP, 1 /* apply */, LDAP_MOD_REPLACE) != LDAP_SUCCESS) { LDAPDebug(LDAP_DEBUG_ANY, "Error with config attribute %s : %s\n", attr_name, err_buf, 0); return 1; } } /* Read the index entries */ read_instance_index_entries(inst); /* Read the attribute encryption entries */ read_instance_attrcrypt_entries(inst); 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 */ }
/* * ************************************************************************** * Helper functions * ************************************************************************** */ static int _csngen_parse_state (CSNGen *gen, Slapi_Attr *state) { int rc; Slapi_Value *val; const struct berval *bval; ReplicaId rid = gen->state.rid; PR_ASSERT (gen && state); rc = slapi_attr_first_value(state, &val); if (rc != 0) { slapi_log_err(SLAPI_LOG_ERR, "_csngen_parse_state", "Invalid state format\n"); return CSN_INVALID_FORMAT; } bval = slapi_value_get_berval(val); memcpy (&gen->state, bval->bv_val, bval->bv_len); /* replicaid does not match */ if (rid != gen->state.rid) { slapi_log_err(SLAPI_LOG_ERR, "_csngen_parse_state", "Replica id" " mismatch; current id - %d, replica id in the state - %d\n", rid, gen->state.rid); return CSN_INVALID_FORMAT; } return CSN_SUCCESS; }
/* * 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; }
Token *oath_token_from_entry(Token *token, Slapi_Entry *e) { if (e != NULL && token != NULL) { Slapi_Attr *seed; token->serial = slapi_entry_attr_get_charptr(e, "tokenSerial"); token->pin = slapi_entry_attr_get_charptr(e, "tokenPIN"); token->counter = slapi_entry_attr_get_long(e, "tokenCounter"); slapi_entry_attr_find(e, "tokenSeed", &seed); if (seed != NULL) { struct berval *bval; Slapi_Value *sval; slapi_attr_first_value(seed, &sval); bval = slapi_value_get_berval(sval); token->seed = ber_bvdup(bval); } } return token; }
/* * 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 ); }
static const char *fetch_attr(Slapi_Entry *e, const char *attrname, const char *default_val) { Slapi_Attr *attr; Slapi_Value *val = NULL; if (slapi_entry_attr_find(e, attrname, &attr) != 0) return default_val; slapi_attr_first_value(attr, &val); return slapi_value_get_string(val); }
static int ldbm_attrcrypt_parse_entry(ldbm_instance *inst, Slapi_Entry *e, char **attribute_name, int *cipher) { Slapi_Attr *attr; const struct berval *attrValue; Slapi_Value *sval; *cipher = 0; *attribute_name = NULL; /* Get the name of the attribute to index which will be the value * of the cn attribute. */ if (slapi_entry_attr_find(e, "cn", &attr) != 0) { slapi_log_err(SLAPI_LOG_ERR, "ldbm_attrcrypt_parse_entry - Malformed attribute encryption entry %s\n", slapi_entry_get_dn(e), 0, 0); return LDAP_OPERATIONS_ERROR; } slapi_attr_first_value(attr, &sval); attrValue = slapi_value_get_berval(sval); *attribute_name = slapi_ch_strdup(attrValue->bv_val); /* Get the list of index types from the entry. */ if (0 == slapi_entry_attr_find(e, "nsEncryptionAlgorithm", &attr)) { slapi_attr_first_value(attr, &sval); if (sval) { attrValue = slapi_value_get_berval(sval); *cipher = ldbm_attrcrypt_parse_cipher(attrValue->bv_val); if (0 == *cipher) slapi_log_err(SLAPI_LOG_WARNING, "ldbm_attrcrypt_parse_entry - " "Attempt to configure unrecognized cipher %s in encrypted attribute config entry %s\n", attrValue->bv_val, slapi_entry_get_dn(e), 0); } } return LDAP_SUCCESS; }
static int parse_ldbm_instance_entry(Slapi_Entry *e, char **instance_name) { Slapi_Attr *attr = NULL; for (slapi_entry_first_attr(e, &attr); attr; slapi_entry_next_attr(e, attr, &attr)) { char *attr_name = NULL; slapi_attr_get_type(attr, &attr_name); if (strcasecmp(attr_name, "cn") == 0) { Slapi_Value *sval = NULL; struct berval *bval; slapi_attr_first_value(attr, &sval); bval = (struct berval *) slapi_value_get_berval(sval); *instance_name = slapi_ch_strdup((char *)bval->bv_val); } } return 0; }
static char* sync_get_attr_value_from_entry( Slapi_Entry *cl_entry, char *attrtype) { Slapi_Value *sval=NULL; const struct berval *value; char *strvalue = NULL; if ( NULL != cl_entry ) { Slapi_Attr *chattr = NULL; sval = NULL; value = NULL; if ( slapi_entry_attr_find( cl_entry, attrtype, &chattr ) == 0 ) { slapi_attr_first_value( chattr,&sval ); if ( NULL != sval ) { value = slapi_value_get_berval ( sval ); if( NULL != value && NULL != value->bv_val && '\0' != value->bv_val[0]) { strvalue = slapi_ch_strdup( value->bv_val); } } } } return (strvalue); }
/* 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; }
static struct ipapwd_krbcfg *ipapwd_getConfig(void) { krb5_error_code krberr; struct ipapwd_krbcfg *config = NULL; krb5_keyblock *kmkey = NULL; Slapi_Entry *realm_entry = NULL; Slapi_Entry *config_entry = NULL; Slapi_Attr *a; Slapi_Value *v; BerElement *be = NULL; ber_tag_t tag, tvno; ber_int_t ttype; const struct berval *bval; struct berval *mkey = NULL; char **encsalts; char **tmparray; char *tmpstr; int i, ret; config = calloc(1, sizeof(struct ipapwd_krbcfg)); if (!config) { LOG_OOM(); goto free_and_error; } kmkey = calloc(1, sizeof(krb5_keyblock)); if (!kmkey) { LOG_OOM(); goto free_and_error; } config->kmkey = kmkey; krberr = krb5_init_context(&config->krbctx); if (krberr) { LOG_FATAL("krb5_init_context failed\n"); goto free_and_error; } ret = krb5_get_default_realm(config->krbctx, &config->realm); if (ret) { LOG_FATAL("Failed to get default realm?!\n"); goto free_and_error; } /* get the Realm Container entry */ ret = ipapwd_getEntry(ipa_realm_dn, &realm_entry, NULL); if (ret != LDAP_SUCCESS) { LOG_FATAL("No realm Entry?\n"); goto free_and_error; } /*** get the Kerberos Master Key ***/ ret = slapi_entry_attr_find(realm_entry, "krbMKey", &a); if (ret == -1) { LOG_FATAL("No master key??\n"); goto free_and_error; } /* there should be only one value here */ ret = slapi_attr_first_value(a, &v); if (ret == -1) { LOG_FATAL("No master key??\n"); goto free_and_error; } bval = slapi_value_get_berval(v); if (!bval) { LOG_FATAL("Error retrieving master key berval\n"); goto free_and_error; } be = ber_init(discard_const(bval)); if (!be) { LOG_FATAL("ber_init() failed!\n"); goto free_and_error; } tag = ber_scanf(be, "{i{iO}}", &tvno, &ttype, &mkey); if (tag == LBER_ERROR) { LOG_FATAL("Bad Master key encoding ?!\n"); goto free_and_error; } config->mkvno = tvno; kmkey->magic = KV5M_KEYBLOCK; kmkey->enctype = ttype; kmkey->length = mkey->bv_len; kmkey->contents = malloc(mkey->bv_len); if (!kmkey->contents) { LOG_OOM(); goto free_and_error; } memcpy(kmkey->contents, mkey->bv_val, mkey->bv_len); ber_bvfree(mkey); ber_free(be, 1); mkey = NULL; be = NULL; /*** get the Supported Enc/Salt types ***/ encsalts = slapi_entry_attr_get_charray(realm_entry, "krbSupportedEncSaltTypes"); if (encsalts) { for (i = 0; encsalts[i]; i++) /* count */ ; ret = parse_bval_key_salt_tuples(config->krbctx, (const char * const *)encsalts, i, &config->supp_encsalts, &config->num_supp_encsalts); slapi_ch_array_free(encsalts); } else { LOG("No configured salt types use defaults\n"); for (i = 0; ipapwd_def_encsalts[i]; i++) /* count */ ; ret = parse_bval_key_salt_tuples(config->krbctx, ipapwd_def_encsalts, i, &config->supp_encsalts, &config->num_supp_encsalts); } if (ret) { LOG_FATAL("Can't get Supported EncSalt Types\n"); goto free_and_error; } /*** get the Preferred Enc/Salt types ***/ encsalts = slapi_entry_attr_get_charray(realm_entry, "krbDefaultEncSaltTypes"); if (encsalts) { for (i = 0; encsalts[i]; i++) /* count */ ; ret = parse_bval_key_salt_tuples(config->krbctx, (const char * const *)encsalts, i, &config->pref_encsalts, &config->num_pref_encsalts); slapi_ch_array_free(encsalts); } else { LOG("No configured salt types use defaults\n"); for (i = 0; ipapwd_def_encsalts[i]; i++) /* count */ ; ret = parse_bval_key_salt_tuples(config->krbctx, ipapwd_def_encsalts, i, &config->pref_encsalts, &config->num_pref_encsalts); } if (ret) { LOG_FATAL("Can't get Preferred EncSalt Types\n"); goto free_and_error; } slapi_entry_free(realm_entry); /* get the Realm Container entry */ ret = ipapwd_getEntry(ipa_pwd_config_dn, &config_entry, NULL); if (ret != LDAP_SUCCESS) { LOG_FATAL("No config Entry? Impossible!\n"); goto free_and_error; } config->passsync_mgrs = slapi_entry_attr_get_charray(config_entry, "passSyncManagersDNs"); /* now add Directory Manager, it is always added by default */ tmpstr = slapi_ch_strdup("cn=Directory Manager"); slapi_ch_array_add(&config->passsync_mgrs, tmpstr); if (config->passsync_mgrs == NULL) { LOG_OOM(); goto free_and_error; } for (i = 0; config->passsync_mgrs[i]; i++) /* count */ ; config->num_passsync_mgrs = i; slapi_entry_free(config_entry); /* get the ipa etc/ipaConfig entry */ config->allow_nt_hash = false; ret = ipapwd_getEntry(ipa_etc_config_dn, &config_entry, NULL); if (ret != LDAP_SUCCESS) { LOG_FATAL("No config Entry?\n"); goto free_and_error; } else { tmparray = slapi_entry_attr_get_charray(config_entry, "ipaConfigString"); for (i = 0; tmparray && tmparray[i]; i++) { if (strcasecmp(tmparray[i], "AllowNThash") == 0) { config->allow_nt_hash = true; continue; } } if (tmparray) slapi_ch_array_free(tmparray); } slapi_entry_free(config_entry); return config; free_and_error: if (mkey) ber_bvfree(mkey); if (be) ber_free(be, 1); if (kmkey) { free(kmkey->contents); free(kmkey); } if (config) { if (config->krbctx) { if (config->realm) krb5_free_default_realm(config->krbctx, config->realm); krb5_free_context(config->krbctx); } free(config->pref_encsalts); free(config->supp_encsalts); slapi_ch_array_free(config->passsync_mgrs); free(config); } slapi_entry_free(config_entry); slapi_entry_free(realm_entry); return NULL; }
/* Given an entry, provide the account policy in effect for that entry. Returns non-0 if function fails. If account policy comes back NULL, it's not an error; the entry is simply not covered by a policy. */ int get_acctpolicy( Slapi_PBlock *pb, Slapi_Entry *target_entry, void *plugin_id, acctPolicy **policy ) { Slapi_DN *sdn = NULL; Slapi_Entry *policy_entry = NULL; Slapi_Attr *attr; Slapi_Value *sval = NULL; int ldrc; char *attr_name; char *policy_dn = NULL; acctPluginCfg *cfg; int rc = 0; if( policy == NULL ) { /* Bad parameter */ return( -1 ); } *policy = NULL; config_rd_lock(); cfg = get_config(); /* Return success and NULL policy */ policy_dn = get_attr_string_val( target_entry, cfg->spec_attr_name ); if( policy_dn == NULL ) { slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME, "get_acctpolicy - \"%s\" is not governed by an account inactivity " "policy subentry\n", slapi_entry_get_ndn( target_entry ) ); if (cfg->inactivitylimit != ULONG_MAX) { goto dopolicy; } slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME, "get_acctpolicy - \"%s\" is not governed by an account inactivity " "global policy\n", slapi_entry_get_ndn( target_entry ) ); config_unlock(); return rc; } sdn = slapi_sdn_new_dn_byref( policy_dn ); ldrc = slapi_search_internal_get_entry( sdn, NULL, &policy_entry, plugin_id ); slapi_sdn_free( &sdn ); /* There should be a policy but it can't be retrieved; fatal error */ if( policy_entry == NULL ) { if( ldrc != LDAP_NO_SUCH_OBJECT ) { slapi_log_err(SLAPI_LOG_ERR, PLUGIN_NAME, "get_acctpolicy - Error retrieving policy entry \"%s\": %d\n", policy_dn, ldrc ); } else { slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME, "get_acctpolicy - Policy entry \"%s\" is missing: %d\n", policy_dn, ldrc ); } rc = -1; goto done; } dopolicy: *policy = (acctPolicy *)slapi_ch_calloc( 1, sizeof( acctPolicy ) ); if ( !policy_entry ) { /* global policy */ (*policy)->inactivitylimit = cfg->inactivitylimit; goto done; } for( slapi_entry_first_attr( policy_entry, &attr ); attr != NULL; slapi_entry_next_attr( policy_entry, attr, &attr ) ) { slapi_attr_get_type(attr, &attr_name); if( !strcasecmp( attr_name, cfg->limit_attr_name ) ) { if( slapi_attr_first_value( attr, &sval ) == 0 ) { (*policy)->inactivitylimit = slapi_value_get_ulong( sval ); } } } done: config_unlock(); slapi_ch_free_string( &policy_dn ); slapi_entry_free( policy_entry ); return( rc ); }
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 */ }
int parent_update_on_childchange(modify_context *mc,int op, size_t *new_sub_count ) { int ret = 0; int mod_op = 0; Slapi_Attr *read_attr = NULL; size_t current_sub_count = 0; int already_present = 0; int repl_op = 0; Slapi_Mods *smods = NULL; char value_buffer[20]; /* enough digits for 2^64 children */ if (new_sub_count) *new_sub_count = 0; repl_op = PARENTUPDATE_TOMBSTONE_MASK & op; op &= PARENTUPDATE_MASK; /* Check nobody is trying to use op == 3, it's not implemented yet */ PR_ASSERT( (op == PARENTUPDATE_ADD) || (op == PARENTUPDATE_DEL)); /* We want to invent a mods set to be passed to modify_apply_mods() */ /* For now, we're only interested in subordinatecount. We first examine the present value for the attribute. If it isn't present and we're adding, we assign value 1 to the attribute and add it. If it is present, we increment or decrement depending upon whether we're adding or deleting. If the value after decrementing is zero, we remove it. */ smods = slapi_mods_new(); /* Get the present value of the subcount attr, or 0 if not present */ ret = slapi_entry_attr_find(mc->old_entry->ep_entry,numsubordinates,&read_attr); if (0 == ret) { /* decode the value */ Slapi_Value *sval; slapi_attr_first_value( read_attr, &sval ); if (sval!=NULL) { const struct berval *bval = slapi_value_get_berval(sval); if(NULL != bval) { already_present = 1; current_sub_count = atol(bval->bv_val); } } } if (PARENTUPDATE_DELETE_TOMBSTONE != repl_op) { /* are we adding ? */ if ( (PARENTUPDATE_ADD == op) && !already_present) { /* If so, and the parent entry does not already have a subcount * attribute, we need to add it */ mod_op = LDAP_MOD_ADD; } else if (PARENTUPDATE_DEL == op) { if (!already_present) { /* This means that something is wrong---deleting a child but no subcount present on parent */ LDAPDebug0Args( LDAP_DEBUG_ANY, "numsubordinates assertion failure\n" ); slapi_mods_free(&smods); return -1; } else { if (current_sub_count == 1) { mod_op = LDAP_MOD_DELETE; } else { mod_op = LDAP_MOD_REPLACE; } } } else { /* (PARENTUPDATE_ADD == op) && already_present */ mod_op = LDAP_MOD_REPLACE; } /* Now compute the new value */ if (PARENTUPDATE_ADD == op) { current_sub_count++; } else { current_sub_count--; } if (mod_op == LDAP_MOD_DELETE) { slapi_mods_add(smods, mod_op | LDAP_MOD_BVALUES, numsubordinates, 0, NULL); } else { sprintf(value_buffer,"%lu", current_sub_count); slapi_mods_add(smods, mod_op | LDAP_MOD_BVALUES, numsubordinates, strlen(value_buffer), value_buffer); } if (new_sub_count) { *new_sub_count = current_sub_count; } } /* tombstoneNumSubordinates is needed only when this is repl op * and a child is being deleted */ if (repl_op && (PARENTUPDATE_DEL == op)) { current_sub_count = LDAP_MAXINT; ret = slapi_entry_attr_find(mc->old_entry->ep_entry, tombstone_numsubordinates, &read_attr); if (0 == ret) { /* decode the value */ Slapi_Value *sval; slapi_attr_first_value( read_attr, &sval ); if (sval!=NULL) { const struct berval *bval = slapi_value_get_berval(sval); if(NULL != bval) { current_sub_count = atol(bval->bv_val); } } } if (PARENTUPDATE_DELETE_TOMBSTONE == repl_op) { /* deleting a tombstone entry: * reaping or manually deleting it */ if ((current_sub_count != LDAP_MAXINT) && (current_sub_count > 0)) { current_sub_count--; mod_op = LDAP_MOD_REPLACE; sprintf(value_buffer,"%lu", current_sub_count); slapi_mods_add(smods, mod_op | LDAP_MOD_BVALUES, tombstone_numsubordinates, strlen(value_buffer), value_buffer); } } if (PARENTUPDATE_CREATE_TOMBSTONE == repl_op) { /* creating a tombstone entry */ if (current_sub_count != LDAP_MAXINT) { current_sub_count++; } else { /* tombstonenumsubordinates does not exist */ current_sub_count = 1; } mod_op = LDAP_MOD_REPLACE; sprintf(value_buffer,"%lu", current_sub_count); slapi_mods_add(smods, mod_op | LDAP_MOD_BVALUES, tombstone_numsubordinates, strlen(value_buffer), value_buffer); } } ret = modify_apply_mods(mc, smods); /* smods passed in */ return ret; }
/* * 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; }
/* * Config DSE callback for index entry changes. * * this function is huge! */ int ldbm_instance_attrcrypt_config_modify_callback(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg) { ldbm_instance *inst = (ldbm_instance *)arg; Slapi_Attr *attr; Slapi_Value *sval; const struct berval *attrValue; struct attrinfo *ainfo = NULL; LDAPMod **mods; int i = 0; int j = 0; returntext[0] = '\0'; *returncode = LDAP_SUCCESS; slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods); slapi_entry_attr_find(e, "cn", &attr); slapi_attr_first_value(attr, &sval); attrValue = slapi_value_get_berval(sval); ainfo_get(inst->inst_be, attrValue->bv_val, &ainfo); if (NULL == ainfo) { return SLAPI_DSE_CALLBACK_ERROR; } for (i = 0; (mods != NULL) && (mods[i] != NULL); i++) { char *config_attr = (char *)mods[i]->mod_type; /* There are basically three cases in the modify: * 1. The attribute was added * 2. The attribute was deleted * 3. The attribute was modified (deleted and added). * Now, of these three, only #3 is legal. * This is because the attribute is mandatory and single-valued in the schema. * We handle this as follows: an add will always replace what's there (if anything). * a delete will remove what's there as long as it matches what's being deleted. * this is to avoid ordering problems with the adds and deletes. */ if (strcasecmp(config_attr, "nsEncryptionAlgorithm") == 0) { if (SLAPI_IS_MOD_ADD(mods[i]->mod_op)) { for (j = 0; mods[i]->mod_bvalues[j] != NULL; j++) { int cipher = ldbm_attrcrypt_parse_cipher(mods[i]->mod_bvalues[j]->bv_val); if (0 == cipher) { /* Tried to configure an invalid cipher */ } ldbm_instance_attrcrypt_enable(ainfo,cipher); } continue; } if (SLAPI_IS_MOD_DELETE(mods[i]->mod_op)) { if ((mods[i]->mod_bvalues == NULL) || (mods[i]->mod_bvalues[0] == NULL)) { /* Not legal */ return SLAPI_DSE_CALLBACK_ERROR; } else { for (j = 0; mods[i]->mod_bvalues[j] != NULL; j++) { /* Code before here should ensure that we only ever delete something that was already here */ ldbm_instance_attrcrypt_disable(ainfo); } } continue; } } } return SLAPI_DSE_CALLBACK_OK; }
/* 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; } }