/* * 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; }
/* * Check if we are modifying the config, or changing the shared config entry */ int memberof_shared_config_validate(Slapi_PBlock *pb) { Slapi_Entry *e = 0; Slapi_Entry *resulting_e = 0; Slapi_Entry *config_entry = NULL; Slapi_DN *sdn = NULL; Slapi_DN *config_sdn = NULL; Slapi_Mods *smods = 0; Slapi_Mod *smod = NULL, *nextmod = NULL; LDAPMod **mods = NULL; char returntext[SLAPI_DSE_RETURNTEXT_SIZE]; char *configarea_dn = NULL; int ret = SLAPI_PLUGIN_SUCCESS; slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn); if (slapi_sdn_compare(sdn, memberof_get_plugin_area()) == 0 || slapi_sdn_compare(sdn, memberof_get_config_area()) == 0) { slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &e); if(e){ /* * Create a copy of the entry and apply the * mods to create the resulting entry. */ slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods); smods = slapi_mods_new(); slapi_mods_init_byref(smods, mods); resulting_e = slapi_entry_dup(e); if (mods && (slapi_entry_apply_mods(resulting_e, mods) != LDAP_SUCCESS)) { /* we don't care about this, the update is invalid and will be caught later */ goto bail; } if (slapi_sdn_compare(sdn, memberof_get_plugin_area())){ /* * This entry is a plugin config area entry, validate it. */ if( SLAPI_DSE_CALLBACK_ERROR == memberof_validate_config (pb, NULL, resulting_e, &ret, returntext,0)) { ret = LDAP_UNWILLING_TO_PERFORM; } } else { /* * This is the memberOf plugin entry, check if we are adding/replacing the * plugin config area. */ nextmod = slapi_mod_new(); for (smod = slapi_mods_get_first_smod(smods, nextmod); smod != NULL; smod = slapi_mods_get_next_smod(smods, nextmod) ) { if ( PL_strcasecmp(SLAPI_PLUGIN_SHARED_CONFIG_AREA, slapi_mod_get_type(smod)) == 0 ) { /* * Okay, we are modifying the plugin config area, we only care about * adds and replaces. */ if(SLAPI_IS_MOD_REPLACE(slapi_mod_get_operation(smod)) || SLAPI_IS_MOD_ADD(slapi_mod_get_operation(smod))) { struct berval *bv = NULL; int rc = 0; bv = slapi_mod_get_first_value(smod); configarea_dn = slapi_ch_strdup(bv->bv_val); if(configarea_dn){ /* Check the DN syntax */ rc = slapi_dn_syntax_check(pb, configarea_dn, 1); if (rc) { /* syntax check failed */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s does not contain a valid DN (%s)", SLAPI_PLUGIN_SHARED_CONFIG_AREA, configarea_dn); ret = LDAP_UNWILLING_TO_PERFORM; goto bail; } /* Check if the plugin config area entry exists */ if((config_sdn = slapi_sdn_new_dn_byval(configarea_dn))){ rc = slapi_search_internal_get_entry(config_sdn, NULL, &config_entry, memberof_get_plugin_id()); if(config_entry){ int err = 0; /* * Validate the settings from the new config area. */ if ( memberof_validate_config(pb, NULL, config_entry, &err, returntext,0) == SLAPI_DSE_CALLBACK_ERROR ) { ret = LDAP_UNWILLING_TO_PERFORM; goto bail; } } else { /* The config area does not exist */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Unable to locate shared config entry (%s) error %d", slapi_sdn_get_dn(memberof_get_config_area()), rc); ret = LDAP_UNWILLING_TO_PERFORM; goto bail; } } } slapi_ch_free_string(&configarea_dn); slapi_sdn_free(&config_sdn); } } } } } else { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,"Unable to locate shared config entry (%s)", slapi_sdn_get_dn(memberof_get_config_area())); ret = LDAP_UNWILLING_TO_PERFORM; } } bail: if (ret){ slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ret); slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, returntext); slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_shared_config_validate - %s/n", returntext); } slapi_sdn_free(&config_sdn); if(nextmod) slapi_mod_free(&nextmod); slapi_mods_free(&smods); slapi_entry_free(resulting_e); slapi_entry_free(config_entry); slapi_ch_free_string(&configarea_dn); return ret; }
/* * preop_modify - pre-operation plug-in for modify */ static int preop_modify(Slapi_PBlock *pb) { int result = LDAP_SUCCESS; Slapi_PBlock *spb = NULL; LDAPMod **checkmods = NULL; int checkmodsCapacity = 0; char *errtext = NULL; char *attrName = NULL; #ifdef DEBUG slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "MODIFY begin\n"); #endif BEGIN int err; char *markerObjectClass=NULL; char *requiredObjectClass=NULL; LDAPMod **mods; int modcount = 0; int ii; LDAPMod *mod; Slapi_DN *sdn = NULL; int isupdatedn; int argc; char **argv = NULL; /* * If this is a replication update, just be a noop. */ err = slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &isupdatedn); if (err) { result = uid_op_error(60); break; } if (isupdatedn) { break; } /* * Get the arguments */ result = getArguments(pb, &attrName, &markerObjectClass, &requiredObjectClass); if (UNTAGGED_PARAMETER == result) { result = LDAP_SUCCESS; /* Statically defined subtrees to monitor */ err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc); if (err) { result = uid_op_error(53); break; } err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv); if (err) { result = uid_op_error(54); break; } argc--; /* First argument was attribute name */ argv++; } else if (0 != result) { break; } err = slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods); if (err) { result = uid_op_error(61); break; } /* There may be more than one mod that matches e.g. changetype: modify delete: uid uid: balster1950 - add: uid uid: scottg So, we need to first find all mods that contain the attribute which are add or replace ops and are bvalue encoded */ /* find out how many mods meet this criteria */ for(;*mods;mods++) { mod = *mods; if ((slapi_attr_type_cmp(mod->mod_type, attrName, 1) == 0) && /* mod contains target attr */ (mod->mod_op & LDAP_MOD_BVALUES) && /* mod is bval encoded (not string val) */ (mod->mod_bvalues && mod->mod_bvalues[0]) && /* mod actually contains some values */ (SLAPI_IS_MOD_ADD(mod->mod_op) || /* mod is add */ SLAPI_IS_MOD_REPLACE(mod->mod_op))) /* mod is replace */ { addMod(&checkmods, &checkmodsCapacity, &modcount, mod); } } if (modcount == 0) { break; /* no mods to check, we are done */ } /* Get the target DN */ err = slapi_pblock_get(pb, SLAPI_MODIFY_TARGET_SDN, &sdn); if (err) { result = uid_op_error(11); break; } /* * Check if it has the required object class */ if (requiredObjectClass && !(spb = dnHasObjectClass(sdn, requiredObjectClass))) { break; } /* * Passed all the requirements - this is an operation we * need to enforce uniqueness on. Now find all parent entries * with the marker object class, and do a search for each one. */ /* * stop checking at first mod that fails the check */ for (ii = 0; (result == 0) && (ii < modcount); ++ii) { mod = checkmods[ii]; if (NULL != markerObjectClass) { /* Subtree defined by location of marker object class */ result = findSubtreeAndSearch(sdn, attrName, NULL, mod->mod_bvalues, requiredObjectClass, sdn, markerObjectClass); } else { /* Subtrees listed on invocation line */ result = searchAllSubtrees(argc, argv, attrName, NULL, mod->mod_bvalues, requiredObjectClass, sdn); } } END slapi_ch_free((void **)&checkmods); freePblock(spb); if (result) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "MODIFY result %d\n", result); if (result == LDAP_CONSTRAINT_VIOLATION) { errtext = slapi_ch_smprintf(moreInfo, attrName); } else { errtext = slapi_ch_strdup("Error checking for attribute uniqueness."); } slapi_send_ldap_result(pb, result, 0, errtext, 0, 0); slapi_ch_free_string(&errtext); } return (result==LDAP_SUCCESS)?0:-1; }