int destroy_matchrule_indexer(Slapi_PBlock *pb) { Slapi_Value **keys = NULL; IFP mrDESTROY = NULL; if (!slapi_pblock_get (pb, SLAPI_PLUGIN_DESTROY_FN, &mrDESTROY)) { if (mrDESTROY != NULL) { mrDESTROY (pb); } } /* matching rule indexers which handle Slapi_Value** directly will own the keys, free them, and set SLAPI_PLUGIN_MR_KEYS to NULL in the destroy function - the old style matching rule indexers which only deal with struct berval ** will not free the Slapi_Value** wrappers so we have to free them here */ slapi_pblock_get(pb, SLAPI_PLUGIN_MR_KEYS, &keys); if (keys) { valuearray_free(&keys); slapi_pblock_set(pb, SLAPI_PLUGIN_MR_KEYS, NULL); } return 0; }
static void mr_private_indexer_done(struct mr_private *mrpriv) { if (mrpriv && mrpriv->sva) { valuearray_free(&mrpriv->sva); } if (mrpriv && mrpriv->bva) { ber_bvecfree(mrpriv->bva); mrpriv->bva = NULL; } }
void slapi_valueset_done(Slapi_ValueSet *vs) { if(vs!=NULL) { if(vs->va!=NULL) { valuearray_free(&vs->va); vs->va= NULL; } } }
/* * * Find value "v" using AVL tree "valuetree" * * returns LDAP_SUCCESS if "v" was found, LDAP_NO_SUCH_ATTRIBUTE * if "v" was not found and LDAP_OPERATIONS_ERROR if some unexpected error occurs. */ static int valuetree_find( const struct slapi_attr *a, const Slapi_Value *v, Avlnode *valuetree, int *index) { const Slapi_Value *oneval[2]; Slapi_Value **keyvals; valuetree_node *vaip, tmpvain; PR_ASSERT(a!=NULL); PR_ASSERT(a->a_plugin!=NULL); PR_ASSERT(v!=NULL); PR_ASSERT(valuetree!=NULL); PR_ASSERT(index!=NULL); if ( a == NULL || v == NULL || valuetree == NULL ) { return( LDAP_OPERATIONS_ERROR ); } keyvals = NULL; oneval[0] = v; oneval[1] = NULL; if ( slapi_attr_values2keys_sv( a, (Slapi_Value**)oneval, &keyvals, LDAP_FILTER_EQUALITY ) != 0 /* jcm cast */ || keyvals == NULL || keyvals[0] == NULL ) { LDAPDebug( LDAP_DEBUG_ANY, "valuetree_find_and_replace: " "slapi_attr_values2keys_sv failed for type %s\n", a->a_type, 0, 0 ); return( LDAP_OPERATIONS_ERROR ); } tmpvain.index = 0; tmpvain.sval = keyvals[0]; vaip = (valuetree_node *)avl_find( valuetree, &tmpvain, valuetree_node_cmp ); if ( keyvals != NULL ) { valuearray_free( &keyvals ); } if (vaip == NULL) { return( LDAP_NO_SUCH_ATTRIBUTE ); } else { *index= vaip->index; } return( LDAP_SUCCESS ); }
/* quickly throw away any old contents of this valueset, and stick in the * new ones. * * return value: LDAP_SUCCESS - OK * : LDAP_OPERATIONS_ERROR - duplicated values given */ int valueset_replace(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **valstoreplace) { int rc = LDAP_SUCCESS; int numberofvalstoreplace= valuearray_count(valstoreplace); /* verify the given values are not duplicated. if replacing with one value, no need to check. just replace it. */ if (numberofvalstoreplace > 1) { Avlnode *vtree = NULL; rc = valuetree_add_valuearray( a, valstoreplace, &vtree, NULL ); valuetree_free(&vtree); if ( LDAP_SUCCESS != rc && /* bz 247413: don't override LDAP_TYPE_OR_VALUE_EXISTS */ LDAP_TYPE_OR_VALUE_EXISTS != rc ) { /* There were already duplicate values in the value set */ rc = LDAP_OPERATIONS_ERROR; } } if ( rc == LDAP_SUCCESS ) { /* values look good - replace the values in the attribute */ if(!valuearray_isempty(vs->va)) { /* remove old values */ slapi_valueset_done(vs); } /* we now own valstoreplace */ vs->va = valstoreplace; } else { /* caller expects us to own valstoreplace - since we cannot use them, just delete them */ valuearray_free(&valstoreplace); } return rc; }
/* this function takes SLAPI_PLUGIN_MR_VALUES as struct berval ** and returns SLAPI_PLUGIN_MR_KEYS as struct berval ** */ static int mr_wrap_mr_index_fn(Slapi_PBlock* pb) { int rc = -1; struct berval **in_vals = NULL; struct berval **out_vals = NULL; struct mr_private *mrpriv = NULL; Slapi_Value **in_vals_sv = NULL; Slapi_Value **out_vals_sv = NULL; slapi_pblock_get(pb, SLAPI_PLUGIN_MR_VALUES, &in_vals); /* get bervals */ /* convert bervals to sv ary */ valuearray_init_bervalarray(in_vals, &in_vals_sv); slapi_pblock_set(pb, SLAPI_PLUGIN_MR_VALUES, in_vals_sv); /* use sv */ rc = mr_wrap_mr_index_sv_fn(pb); /* clean up in_vals_sv */ valuearray_free(&in_vals_sv); /* restore old in_vals */ slapi_pblock_set(pb, SLAPI_PLUGIN_MR_VALUES, in_vals); /* get result sv keys */ slapi_pblock_get(pb, SLAPI_PLUGIN_MR_KEYS, &out_vals_sv); /* convert to bvec */ valuearray_get_bervalarray(out_vals_sv, &out_vals); /* NOTE: mrpriv owns out_vals_sv (mpriv->sva) - will get freed by mr_private_indexer_done() */ /* we have to save out_vals to free next time or during destroy */ slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv); /* In case SLAPI_PLUGIN_OBJECT is not set * (e.g. custom index/filter create function did not initialize it */ if (mrpriv) { mr_private_indexer_done(mrpriv); /* free old vals, if any */ mrpriv->bva = out_vals; /* save pointer for later */ } /* set return value berval array for caller */ slapi_pblock_set(pb, SLAPI_PLUGIN_MR_KEYS, out_vals); return rc; }
/* Code shared between regular and internal add operation */ static void op_shared_add (Slapi_PBlock *pb) { Slapi_Operation *operation; Slapi_Entry *e, *pse; Slapi_Backend *be = NULL; int err; int internal_op, repl_op, legacy_op, lastmod; char *pwdtype = NULL; Slapi_Attr *attr = NULL; Slapi_Entry *referral; char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE]; struct slapdplugin *p = NULL; char *proxydn = NULL; char *proxystr = NULL; int proxy_err = LDAP_SUCCESS; char *errtext = NULL; Slapi_DN *sdn = NULL; passwdPolicy *pwpolicy; slapi_pblock_get (pb, SLAPI_OPERATION, &operation); slapi_pblock_get (pb, SLAPI_ADD_ENTRY, &e); slapi_pblock_get (pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op); slapi_pblock_get (pb, SLAPI_IS_LEGACY_REPLICATED_OPERATION, &legacy_op); internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL); pwpolicy = new_passwdPolicy(pb, slapi_entry_get_dn(e)); /* target spec is used to decide which plugins are applicable for the operation */ operation_set_target_spec (operation, slapi_entry_get_sdn (e)); if ((err = slapi_entry_add_rdn_values(e)) != LDAP_SUCCESS) { send_ldap_result(pb, err, NULL, "failed to add RDN values", 0, NULL); goto done; } /* get the proxy auth dn if the proxy auth control is present */ proxy_err = proxyauth_get_dn(pb, &proxydn, &errtext); if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_ACCESS)) { if (proxydn) { proxystr = slapi_ch_smprintf(" authzid=\"%s\"", proxydn); } if ( !internal_op ) { slapi_log_access(LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d ADD dn=\"%s\"%s\n", pb->pb_conn->c_connid, operation->o_opid, slapi_entry_get_dn_const(e), proxystr ? proxystr : ""); } else { slapi_log_access(LDAP_DEBUG_ARGS, "conn=%s op=%d ADD dn=\"%s\"\n", LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID, slapi_entry_get_dn_const(e)); } } /* If we encountered an error parsing the proxy control, return an error * to the client. We do this here to ensure that we log the operation first. */ if (proxy_err != LDAP_SUCCESS) { send_ldap_result(pb, proxy_err, NULL, errtext, 0, NULL); goto done; } /* * We could be serving multiple database backends. Select the * appropriate one. */ if ((err = slapi_mapping_tree_select(pb, &be, &referral, errorbuf, sizeof(errorbuf))) != LDAP_SUCCESS) { send_ldap_result(pb, err, NULL, errorbuf, 0, NULL); be = NULL; goto done; } if (referral) { int managedsait; slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait); if (managedsait) { send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "cannot update referral", 0, NULL); slapi_entry_free(referral); goto done; } slapi_pblock_set(pb, SLAPI_TARGET_SDN, (void*)operation_get_target_spec (operation)); send_referrals_from_entry(pb,referral); slapi_entry_free(referral); goto done; } if (!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)) { Slapi_Value **unhashed_password_vals = NULL; Slapi_Value **present_values = NULL; /* Setting unhashed password to the entry extension. */ if (repl_op) { /* replicated add ==> get unhashed pw from entry, if any. * set it to the extension */ slapi_entry_attr_find(e, PSEUDO_ATTR_UNHASHEDUSERPASSWORD, &attr); if (attr) { present_values = attr_get_present_values(attr); valuearray_add_valuearray(&unhashed_password_vals, present_values, 0); #if !defined(USE_OLD_UNHASHED) /* and remove it from the entry. */ slapi_entry_attr_delete(e, PSEUDO_ATTR_UNHASHEDUSERPASSWORD); #endif } } else { /* ordinary add ==> * get unhashed pw from userpassword before encrypting it */ /* look for user password attribute */ slapi_entry_attr_find(e, SLAPI_USERPWD_ATTR, &attr); if (attr) { Slapi_Value **vals = NULL; /* Set the backend in the pblock. * The slapi_access_allowed function * needs this set to work properly. */ slapi_pblock_set(pb, SLAPI_BACKEND, slapi_be_select(slapi_entry_get_sdn_const(e))); /* Check ACI before checking password syntax */ if ((err = slapi_access_allowed(pb, e, SLAPI_USERPWD_ATTR, NULL, SLAPI_ACL_ADD)) != LDAP_SUCCESS) { send_ldap_result(pb, err, NULL, "Insufficient 'add' privilege to the " "'userPassword' attribute", 0, NULL); goto done; } /* * Check password syntax, unless this is a pwd admin/rootDN */ present_values = attr_get_present_values(attr); if (!pw_is_pwp_admin(pb, pwpolicy) && check_pw_syntax(pb, slapi_entry_get_sdn_const(e), present_values, NULL, e, 0) != 0) { /* error result is sent from check_pw_syntax */ goto done; } /* pw syntax is valid */ valuearray_add_valuearray(&unhashed_password_vals, present_values, 0); valuearray_add_valuearray(&vals, present_values, 0); pw_encodevals_ext(pb, slapi_entry_get_sdn (e), vals); add_password_attrs(pb, operation, e); slapi_entry_attr_replace_sv(e, SLAPI_USERPWD_ATTR, vals); valuearray_free(&vals); #if defined(USE_OLD_UNHASHED) /* Add the unhashed password pseudo-attribute to the entry */ pwdtype = slapi_attr_syntax_normalize(PSEUDO_ATTR_UNHASHEDUSERPASSWORD); slapi_entry_add_values_sv(e, pwdtype, unhashed_password_vals); #endif } } if (unhashed_password_vals && (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch())) { /* unhashed_password_vals is consumed if successful. */ err = slapi_pw_set_entry_ext(e, unhashed_password_vals, SLAPI_EXT_SET_ADD); if (err) { valuearray_free(&unhashed_password_vals); } } #if defined(THISISTEST) { /* test code to retrieve an unhashed pw from the entry extention & * PSEUDO_ATTR_UNHASHEDUSERPASSWORD attribute */ char *test_str = slapi_get_first_clear_text_pw(e); if (test_str) { slapi_log_err(SLAPI_LOG_ERR, "Value from extension: %s\n", test_str); slapi_ch_free_string(&test_str); } #if defined(USE_OLD_UNHASHED) test_str = slapi_entry_attr_get_charptr(e, PSEUDO_ATTR_UNHASHEDUSERPASSWORD); if (test_str) { slapi_log_err(SLAPI_LOG_ERR, "Value from attr: %s\n", test_str); slapi_ch_free_string(&test_str); } #endif /* USE_OLD_UNHASHED */ } #endif /* THISISTEST */ /* look for multiple backend local credentials or replication local credentials */ for ( p = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); p != NULL && !repl_op; p = p->plg_next ) { char *L_attr = NULL; int i=0; /* Get the appropriate decoding function */ for ( L_attr = p->plg_argv[i]; i<p->plg_argc; L_attr = p->plg_argv[++i]) { /* look for multiple backend local credentials or replication local credentials */ char *L_normalized = slapi_attr_syntax_normalize(L_attr); slapi_entry_attr_find(e, L_normalized, &attr); if (attr) { Slapi_Value **present_values = NULL; Slapi_Value **vals = NULL; present_values= attr_get_present_values(attr); valuearray_add_valuearray(&vals, present_values, 0); pw_rever_encode(vals, L_normalized); slapi_entry_attr_replace_sv(e, L_normalized, vals); valuearray_free(&vals); } if (L_normalized) slapi_ch_free ((void**)&L_normalized); } } } slapi_pblock_set(pb, SLAPI_BACKEND, be); if (!repl_op) { /* can get lastmod only after backend is selected */ slapi_pblock_get(pb, SLAPI_BE_LASTMOD, &lastmod); if (lastmod && add_created_attrs(pb, e) != 0) { send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "cannot insert computed attributes", 0, NULL); goto done; } /* expand objectClass values to reflect the inheritance hierarchy */ slapi_schema_expand_objectclasses( e ); } /* uniqueid needs to be generated for entries added during legacy replication */ if (legacy_op){ if (add_uniqueid(e) != UID_SUCCESS) { send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "cannot insert computed attributes", 0, NULL); goto done; } } /* * call the pre-add plugins. if they succeed, call * the backend add function. then call the post-add * plugins. */ sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(e)); slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, (void *)sdn); if (plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN : SLAPI_PLUGIN_PRE_ADD_FN) == SLAPI_PLUGIN_SUCCESS) { int rc; Slapi_Entry *ec; Slapi_DN *add_target_sdn = NULL; Slapi_Entry *save_e = NULL; slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database); set_db_default_result_handlers(pb); /* because be_add frees the entry */ ec = slapi_entry_dup(e); add_target_sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(ec)); slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn); slapi_sdn_free(&sdn); slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, add_target_sdn); if (be->be_add != NULL) { rc = (*be->be_add)(pb); /* backend may change this if errors and not consumed */ slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &save_e); slapi_pblock_set(pb, SLAPI_ADD_ENTRY, ec); if (rc == 0) { /* acl is not enabled for internal operations */ /* don't update aci store for remote acis */ if ((!internal_op) && (!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA))) { plugin_call_acl_mods_update (pb, SLAPI_OPERATION_ADD); } if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_AUDIT)) { write_audit_log_entry(pb); /* Record the operation in the audit log */ } slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse); do_ps_service(pse, NULL, LDAP_CHANGETYPE_ADD, 0); /* * If be_add succeeded, then e is consumed except the resurrect case. * If it is resurrect, the corresponding tombstone entry is resurrected * and put into the cache. * Otherwise, we set e to NULL to prevent freeing it ourselves. */ if (operation_is_flag_set(operation,OP_FLAG_RESURECT_ENTRY) && save_e) { e = save_e; } else { e = NULL; } } else { /* PR_ASSERT(!save_e); save_e is supposed to be freed in the backend. */ e = save_e; if (rc == SLAPI_FAIL_DISKFULL) { operation_out_of_disk_space(); goto done; } /* If the disk is full we don't want to make it worse ... */ if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_AUDIT)) { write_auditfail_log_entry(pb); /* Record the operation in the audit log */ } } } else { send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Function not implemented", 0, NULL); } slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &rc); plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_POST_ADD_FN : SLAPI_PLUGIN_POST_ADD_FN); slapi_entry_free(ec); } slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn); slapi_sdn_free(&sdn); done: if (be) slapi_be_Unlock(be); slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse); slapi_entry_free(pse); slapi_ch_free((void **)&operation->o_params.p.p_add.parentuniqueid); slapi_entry_free(e); slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL); slapi_ch_free((void**)&pwdtype); slapi_ch_free_string(&proxydn); slapi_ch_free_string(&proxystr); }
/* * Remove an array of values from a value set. * The removed values are passed back in an array. * * Flags * SLAPI_VALUE_FLAG_PRESERVECSNSET - csnset in the value set is duplicated and * preserved in the matched element of the * array of values. * SLAPI_VALUE_FLAG_IGNOREERROR - ignore an error: Couldn't find the value to * be deleted. * SLAPI_VALUE_FLAG_USENEWVALUE - replace the value between the value set and * the matched element of the array of values * (used by entry_add_present_values_wsi). * * Returns * LDAP_SUCCESS - OK. * LDAP_NO_SUCH_ATTRIBUTE - A value to be deleted was not in the value set. * LDAP_OPERATIONS_ERROR - Something very bad happened. */ int valueset_remove_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestodelete, int flags, Slapi_Value ***va_out) { int rc= LDAP_SUCCESS; if(!valuearray_isempty(vs->va)) { int numberofvaluestodelete= valuearray_count(valuestodelete); struct valuearrayfast vaf_out; if ( va_out ) { valuearrayfast_init(&vaf_out,*va_out); } /* * If there are more then one values, build an AVL tree to check * the duplicated values. */ if ( numberofvaluestodelete > 1 ) { /* * Several values to delete: first build an AVL tree that * holds all of the existing values and use that to find * the values we want to delete. */ Avlnode *vtree = NULL; int numberofexistingvalues= slapi_valueset_count(vs); rc= valuetree_add_valuearray( a, vs->va, &vtree, NULL ); if ( rc!=LDAP_SUCCESS ) { /* * failed while constructing AVL tree of existing * values... something bad happened. */ rc= LDAP_OPERATIONS_ERROR; } else { int i; /* * find and mark all the values that are to be deleted */ for ( i = 0; rc == LDAP_SUCCESS && valuestodelete[i] != NULL; ++i ) { int index= 0; rc = valuetree_find( a, valuestodelete[i], vtree, &index ); if(rc==LDAP_SUCCESS) { if(vs->va[index]!=NULL) { /* Move the value to be removed to the out array */ if ( va_out ) { if (vs->va[index]->v_csnset && (flags & (SLAPI_VALUE_FLAG_PRESERVECSNSET| SLAPI_VALUE_FLAG_USENEWVALUE))) { valuestodelete[i]->v_csnset = csnset_dup (vs->va[index]->v_csnset); } if (flags & SLAPI_VALUE_FLAG_USENEWVALUE) { valuearrayfast_add_value_passin(&vaf_out,valuestodelete[i]); valuestodelete[i] = vs->va[index]; vs->va[index] = NULL; } else { valuearrayfast_add_value_passin(&vaf_out,vs->va[index]); vs->va[index] = NULL; } } else { if (flags & SLAPI_VALUE_FLAG_PRESERVECSNSET) { valuestodelete[i]->v_csnset = vs->va[index]->v_csnset; vs->va[index]->v_csnset = NULL; } slapi_value_free ( & vs->va[index] ); } } else { /* We already deleted this value... */ if((flags & SLAPI_VALUE_FLAG_IGNOREERROR) == 0) { /* ...that's an error. */ rc= LDAP_NO_SUCH_ATTRIBUTE; } } } else { /* Couldn't find the value to be deleted */ if(rc==LDAP_NO_SUCH_ATTRIBUTE && (flags & SLAPI_VALUE_FLAG_IGNOREERROR )) { rc= LDAP_SUCCESS; } } } valuetree_free( &vtree ); if ( rc != LDAP_SUCCESS ) { LDAPDebug( LDAP_DEBUG_ANY,"could not find value %d for attr %s (%s)\n", i-1, a->a_type, ldap_err2string( rc )); } else { /* Shunt up all the remaining values to cover the deleted ones. */ valuearray_compress(vs->va,numberofexistingvalues); } } } else { /* We delete one or no value, so we use brute force. */ int i; for ( i = 0; rc==LDAP_SUCCESS && valuestodelete[i] != NULL; ++i ) { Slapi_Value *found= valueset_remove_value(a, vs, valuestodelete[i]); if(found!=NULL) { if ( va_out ) { if (found->v_csnset && (flags & (SLAPI_VALUE_FLAG_PRESERVECSNSET| SLAPI_VALUE_FLAG_USENEWVALUE))) { valuestodelete[i]->v_csnset = csnset_dup (found->v_csnset); } if (flags & SLAPI_VALUE_FLAG_USENEWVALUE) { valuearrayfast_add_value_passin(&vaf_out,valuestodelete[i]); valuestodelete[i] = found; } else { valuearrayfast_add_value_passin(&vaf_out,found); } } else { if (flags & SLAPI_VALUE_FLAG_PRESERVECSNSET) { valuestodelete[i]->v_csnset = found->v_csnset; found->v_csnset = NULL; } slapi_value_free ( & found ); } } else { if((flags & SLAPI_VALUE_FLAG_IGNOREERROR) == 0) { LDAPDebug( LDAP_DEBUG_ARGS,"could not find value %d for attr %s\n", i-1, a->a_type, 0 ); rc= LDAP_NO_SUCH_ATTRIBUTE; } } } } if ( va_out ) { *va_out= vaf_out.va; if(rc!=LDAP_SUCCESS) { valuearray_free(va_out); } } } return rc; }