Slapi_DN *slapi_sdn_set_parent( Slapi_DN *sdn, const Slapi_DN *parentdn ) { Slapi_RDN rdn; slapi_rdn_init_sdn( &rdn, sdn ); slapi_sdn_set_dn_byref( sdn, slapi_sdn_get_dn( parentdn ) ); slapi_sdn_add_rdn( sdn, &rdn ); slapi_rdn_done( &rdn ); return sdn; }
/* consumer connection extension destructor */ void consumer_connection_extension_destructor (void *ext, void *object, void *parent) { PRUint64 connid = 0; if (ext) { /* Check to see if this replication session has acquired * a replica. If so, release it here. */ consumer_connection_extension *connext = (consumer_connection_extension *)ext; if (NULL != connext->replica_acquired) { Replica *r = object_get_data ((Object*)connext->replica_acquired); /* If a total update was in progress, abort it */ if (REPL_PROTOCOL_50_TOTALUPDATE == connext->repl_protocol_version) { Slapi_PBlock *pb = slapi_pblock_new(); const Slapi_DN *repl_root_sdn = replica_get_root(r); PR_ASSERT(NULL != repl_root_sdn); if (NULL != repl_root_sdn) { slapi_pblock_set(pb, SLAPI_CONNECTION, connext->connection); slapi_pblock_set(pb, SLAPI_TARGET_SDN, (void*)repl_root_sdn); slapi_pblock_get(pb, SLAPI_CONN_ID, &connid); slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "Aborting total update in progress for replicated " "area %s connid=%" NSPRIu64 "\n", slapi_sdn_get_dn(repl_root_sdn), connid); slapi_stop_bulk_import(pb); } else { slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "consumer_connection_extension_destructor: can't determine root " "of replicated area.\n"); } slapi_pblock_destroy(pb); /* allow reaping again */ replica_set_tombstone_reap_stop(r, PR_FALSE); } replica_relinquish_exclusive_access(r, connid, -1); object_release ((Object*)connext->replica_acquired); connext->replica_acquired = NULL; } if (connext->supplier_ruv) { ruv_destroy ((RUV **)&connext->supplier_ruv); } connext->connection = NULL; slapi_ch_free((void **)&ext); } }
/* * Config. DSE callback for instance entry searches. */ int ldbm_instance_search_config_entry_callback(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg) { char buf[BUFSIZ]; struct berval *vals[2]; struct berval val; ldbm_instance *inst = (ldbm_instance *) arg; config_info *config; int x; const Slapi_DN *suffix; vals[0] = &val; vals[1] = NULL; returntext[0] = '\0'; /* show the suffixes */ attrlist_delete(&e->e_attrs, CONFIG_INSTANCE_SUFFIX); x = 0; do { suffix = slapi_be_getsuffix(inst->inst_be, x); if (suffix != NULL) { val.bv_val = (char *) slapi_sdn_get_dn(suffix); val.bv_len = strlen (val.bv_val); attrlist_merge( &e->e_attrs, CONFIG_INSTANCE_SUFFIX, vals ); } x++; } while(suffix!=NULL); PR_Lock(inst->inst_config_mutex); for(config = ldbm_instance_config; config->config_name != NULL; config++) { /* Go through the ldbm_config table and fill in the entry. */ if (!(config->config_flags & (CONFIG_FLAG_ALWAYS_SHOW | CONFIG_FLAG_PREVIOUSLY_SET))) { /* This config option shouldn't be shown */ continue; } ldbm_config_get((void *) inst, config, buf); val.bv_val = buf; val.bv_len = strlen(buf); slapi_entry_attr_replace(e, config->config_name, vals); } PR_Unlock(inst->inst_config_mutex); *returncode = LDAP_SUCCESS; return SLAPI_DSE_CALLBACK_OK; }
int value_dn_normalize_value(Slapi_Value *value) { Slapi_DN *sdn = NULL; int rc = 0; if (NULL == value) { return rc; } sdn = slapi_sdn_new_dn_passin(value->bv.bv_val); if (slapi_sdn_get_dn(sdn)) { value->bv.bv_val = slapi_ch_strdup(slapi_sdn_get_dn(sdn)); value->bv.bv_len = slapi_sdn_get_ndn_len(sdn); slapi_sdn_free(&sdn); slapi_value_set_flags(value, SLAPI_ATTR_FLAG_NORMALIZED_CES); } else { rc = 1; slapi_ch_free((void **)&sdn); /* free just Slapi_DN */ } return rc; }
static int handle_agmt_search(Slapi_Entry *e, void *callback_data) { int *agmtcount = (int *)callback_data; int rc; slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "Found replication agreement named \"%s\".\n", slapi_sdn_get_dn(slapi_entry_get_sdn(e))); rc = add_new_agreement(e); if (0 == rc) { (*agmtcount)++; } else { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "The replication " "agreement named \"%s\" could not be correctly parsed. No " "replication will occur with this replica.\n", slapi_sdn_get_dn(slapi_entry_get_sdn(e))); } return rc; }
static void print_suffixes(void) { void *cookie = NULL; Slapi_DN *sdn = NULL; slapi_log_err(SLAPI_LOG_INFO, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, "print_suffixes - The following is the list of valid suffixes to use with " PAMPT_EXCLUDES_ATTR " and " PAMPT_INCLUDES_ATTR ":\n"); for (sdn = slapi_get_first_suffix(&cookie, 1); sdn && cookie; sdn = slapi_get_next_suffix(&cookie, 1)) { slapi_log_err(SLAPI_LOG_INFO, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, "print_suffixes -\t%s\n", slapi_sdn_get_dn(sdn)); } }
/* For preop search we do two things: * 1) based on the search base, we preselect the acls. * 2) also get hold of a acl_pblock for use */ static int aclplugin_preop_search ( Slapi_PBlock *pb ) { int scope; const char *base = NULL; Slapi_DN *sdn = NULL; int optype; int isRoot; int isProxy = 0; int rc = 0; char *errtxt = NULL; char *proxy_dn = NULL; TNF_PROBE_0_DEBUG(aclplugin_preop_search_start ,"ACL",""); slapi_pblock_get ( pb, SLAPI_OPERATION_TYPE, &optype ); slapi_pblock_get ( pb, SLAPI_REQUESTOR_ISROOT, &isRoot ); if (LDAP_SUCCESS == proxyauth_get_dn(pb, &proxy_dn, &errtxt) && proxy_dn) { isProxy = 1; } slapi_ch_free_string(&proxy_dn); if ( isRoot && !isProxy) { TNF_PROBE_1_DEBUG(aclplugin_preop_search_end ,"ACL","", tnf_string,isroot,""); return rc; } slapi_pblock_get( pb, SLAPI_SEARCH_TARGET_SDN, &sdn ); base = slapi_sdn_get_dn(sdn); /* For anonymous client doing search nothing needs to be set up */ if ( optype == SLAPI_OPERATION_SEARCH && aclanom_is_client_anonymous ( pb ) && ! slapi_dn_issuffix( base, "cn=monitor") ) { TNF_PROBE_1_DEBUG(aclplugin_preop_search_end ,"ACL","", tnf_string,anon,""); return rc; } if ( 0 == ( rc = aclplugin_preop_common( pb ))) { slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope ); acllist_init_scan ( pb, scope, base ); } TNF_PROBE_0_DEBUG(aclplugin_preop_search_end ,"ACL",""); return rc; }
static int convert_to_string(Slapi_DN *dn, void *arg) { struct list_to_string_data *data = (struct list_to_string_data *)arg; int newlen = slapi_sdn_get_ndn_len(dn) + strlen(data->delimiter) + 1; if (data->string) { newlen += strlen(data->string); data->string = slapi_ch_realloc(data->string, newlen); } else { data->string = slapi_ch_calloc(1, newlen); } strcat(data->string, slapi_sdn_get_dn(dn)); strcat(data->string, data->delimiter); return 1; }
static int agmtlist_add_callback(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg) { int rc; slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmt_add: begin\n"); rc = add_new_agreement(e); if (0 != rc) { Slapi_DN *sdn = NULL; slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn); slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "agmtlist_add_callback: " "Can't start agreement \"%s\"\n", slapi_sdn_get_dn(sdn)); *returncode = LDAP_UNWILLING_TO_PERFORM; return SLAPI_DSE_CALLBACK_ERROR; } *returncode = LDAP_SUCCESS; return SLAPI_DSE_CALLBACK_OK; }
void ipa_topo_be_state_change(void *handle, char *be_name, int old_be_state, int new_be_state) { Slapi_Backend *be=NULL; const char *be_suffix; /* check if different backends require different actions */ be = slapi_be_select_by_instance_name(be_name); be_suffix = slapi_sdn_get_dn(slapi_be_getsuffix(be, 0)); if (0 == ipa_topo_cfg_plugin_suffix_is_managed(be_suffix)) { /* nothing to do */ return; } if (new_be_state == SLAPI_BE_STATE_ON) { /* backend came back online - check change in domain level */ slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_be_state_change - " "backend %s is coming online; " "checking domain level and init shared topology\n", be_name); ipa_topo_util_set_domain_level(); ipa_topo_util_check_plugin_active(); if (ipa_topo_get_plugin_active()) { ipa_topo_set_post_init(1); ipa_topo_util_start(1); } } else if (new_be_state == SLAPI_BE_STATE_OFFLINE) { /* backend is about to be taken down - inactivate plugin */ slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_be_state_change" "backend %s is going offline; inactivate plugin\n", be_name); } else if (new_be_state == SLAPI_BE_STATE_DELETE) { /* backend is about to be removed - disable replication */ if (old_be_state == SLAPI_BE_STATE_ON) { slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_be_state_change" "backend %s is about to be deleted; inactivate plugin\n", be_name); } } }
/* * If "dn" is passed, get_entry returns an entry which dn is "dn". * If "dn" is not passed, it returns an entry which dn is set in * SLAPI_TARGET_SDN in pblock. * Note: pblock is not mandatory for get_entry (e.g., new_passwdPolicy). */ Slapi_Entry *get_entry ( Slapi_PBlock *pb, const char *dn) { int search_result = 0; Slapi_Entry *retentry = NULL; Slapi_DN *target_sdn = NULL; const char *target_dn = dn; Slapi_DN sdn; if (pb) { slapi_pblock_get( pb, SLAPI_TARGET_SDN, &target_sdn ); if (target_dn == NULL) { target_dn = slapi_sdn_get_dn(target_sdn); } } if (target_dn == NULL) { LDAPDebug0Args(LDAP_DEBUG_TRACE, "WARNING: 'get_entry' - no dn specified.\n"); goto bail; } if (target_dn == dn) { /* target_dn is NOT from target_sdn */ slapi_sdn_init_dn_byref(&sdn, target_dn); target_sdn = &sdn; } search_result = slapi_search_internal_get_entry(target_sdn, NULL, &retentry, pw_get_componentID()); if (search_result != LDAP_SUCCESS) { LDAPDebug2Args(LDAP_DEBUG_TRACE, "WARNING: 'get_entry' can't find entry '%s', err %d\n", target_dn, search_result); } if (target_dn == dn) { /* target_dn is NOT from target_sdn */ slapi_sdn_done(&sdn); } bail: return retentry; }
int ipa_topo_check_entry_move(Slapi_PBlock *pb) { int rc = 0; int entry_type = TOPO_IGNORE_ENTRY; Slapi_Entry *modrdn_entry; slapi_pblock_get(pb,SLAPI_MODRDN_TARGET_ENTRY,&modrdn_entry); entry_type = ipa_topo_check_entry_type(modrdn_entry); switch (entry_type) { case TOPO_SEGMENT_ENTRY: case TOPO_CONFIG_ENTRY: { Slapi_DN *newsuperior = NULL; slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperior); if (newsuperior && slapi_sdn_get_dn(newsuperior)) rc = 1; break; } default: rc = 0; break; } return rc; }
int set_retry_cnt_mods(Slapi_PBlock *pb, Slapi_Mods *smods, int count) { char *timestr; time_t unlock_time; char retry_cnt[8]; /* 1-65535 */ const char *dn = NULL; Slapi_DN *sdn = NULL; passwdPolicy *pwpolicy = NULL; int rc = 0; slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn ); dn = slapi_sdn_get_dn(sdn); pwpolicy = new_passwdPolicy(pb, dn); if (smods) { sprintf ( retry_cnt, "%d", count ); slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "passwordRetryCount", retry_cnt); /* lock account if reache retry limit */ if ( count >= pwpolicy->pw_maxfailure ) { /* Remove lock_account function to perform all mods at once */ /* lock_account ( pb ); */ /* reach the retry limit, lock the account */ if ( pwpolicy->pw_unlock == 0 ) { /* lock until admin reset password */ unlock_time = NO_TIME; } else { unlock_time = time_plus_sec ( current_time(), pwpolicy->pw_lockduration ); } timestr= format_genTime ( unlock_time ); slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "accountUnlockTime", timestr); slapi_ch_free((void **)×tr); rc = LDAP_CONSTRAINT_VIOLATION; } } return rc; }
/* This function is now fully executed for internal and replicated ops. */ int plugin_call_acl_mods_update ( Slapi_PBlock *pb, int optype ) { struct slapdplugin *p; int rc = 0; void *change = NULL; void *mychange[2]; Slapi_Entry *te = NULL; Slapi_DN *sdn = NULL; Operation *operation; slapi_pblock_get (pb, SLAPI_OPERATION, &operation); (void)slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn ); switch ( optype ) { case SLAPI_OPERATION_MODIFY: (void)slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &change ); break; case SLAPI_OPERATION_ADD: (void)slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &change ); te = (Slapi_Entry *)change; if(!slapi_sdn_isempty(slapi_entry_get_sdn(te))) { sdn = slapi_entry_get_sdn(te); } break; case SLAPI_OPERATION_MODRDN: { char *newrdn = NULL; Slapi_DN *psdn = NULL; char *pdn = NULL; /* newrdn: "change" is normalized but not case-ignored */ /* The acl plugin expects normalized newrdn, but no need to be case- * ignored. */ (void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &newrdn ); (void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &psdn ); if (psdn) { pdn = (char *)slapi_sdn_get_dn(psdn); } else { (void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR, &pdn ); } mychange[0] = newrdn; mychange[1] = pdn; change = mychange; break; } } if (NULL == sdn) { slapi_log_err(SLAPI_LOG_ERR, "plugin_call_acl_mods_update", "NULL target DN\n"); return LDAP_INVALID_DN_SYNTAX; } /* call the global plugins first and then the backend specific */ for ( p = get_plugin_list(PLUGIN_LIST_ACL); p != NULL; p = p->plg_next ) { if (plugin_invoke_plugin_sdn(p, SLAPI_PLUGIN_ACL_MODS_UPDATE, pb, sdn)){ rc = (*p->plg_acl_mods_update)(pb, optype, sdn, change ); if ( rc != LDAP_SUCCESS ) break; } } return rc; }
static void op_shared_delete (Slapi_PBlock *pb) { char *rawdn = NULL; const char *dn = NULL; Slapi_Backend *be = NULL; int internal_op; Slapi_DN *sdn = NULL; Slapi_Operation *operation; Slapi_Entry *referral; Slapi_Entry *ecopy = NULL; char errorbuf[BUFSIZ]; int err; char *proxydn = NULL; char *proxystr = NULL; int proxy_err = LDAP_SUCCESS; char *errtext = NULL; slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET, &rawdn); slapi_pblock_get(pb, SLAPI_OPERATION, &operation); internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL); sdn = slapi_sdn_new_dn_byval(rawdn); dn = slapi_sdn_get_dn(sdn); slapi_pblock_set(pb, SLAPI_DELETE_TARGET_SDN, (void*)sdn); if (rawdn && (strlen(rawdn) > 0) && (NULL == dn)) { /* normalization failed */ op_shared_log_error_access(pb, "DEL", rawdn, "invalid dn"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid dn", 0, NULL); goto free_and_return; } /* target spec is used to decide which plugins are applicable for the operation */ operation_set_target_spec (operation, sdn); /* 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 DEL dn=\"%s\"%s\n", pb->pb_conn->c_connid, pb->pb_op->o_opid, slapi_sdn_get_dn(sdn), proxystr ? proxystr: ""); } else { slapi_log_access(LDAP_DEBUG_ARGS, "conn=%s op=%d DEL dn=\"%s\"%s\n", LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID, slapi_sdn_get_dn(sdn), proxystr ? proxystr: ""); } } /* 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 free_and_return; } /* * We could be serving multiple database backends. Select the * appropriate one. */ if ((err = slapi_mapping_tree_select(pb, &be, &referral, errorbuf)) != LDAP_SUCCESS) { send_ldap_result(pb, err, NULL, errorbuf, 0, NULL); be = NULL; goto free_and_return; } if (referral) { int managedsait; slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait); if (managedsait) { send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "cannot delete referral", 0, NULL); slapi_entry_free(referral); goto free_and_return; } send_referrals_from_entry(pb,referral); slapi_entry_free(referral); goto free_and_return; } slapi_pblock_set(pb, SLAPI_BACKEND, be); /* * call the pre-delete plugins. if they succeed, call * the backend delete function. then call the * post-delete plugins. */ if (plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN : SLAPI_PLUGIN_PRE_DELETE_FN) == 0) { int rc; slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database); set_db_default_result_handlers(pb); if (be->be_delete != NULL) { if ((rc = (*be->be_delete)(pb)) == 0) { /* we don't perform acl check for internal operations */ /* Dont 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_DELETE); 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_PRE_OP, &ecopy); do_ps_service(ecopy, NULL, LDAP_CHANGETYPE_DELETE, 0); } else { if (rc == SLAPI_FAIL_DISKFULL) { operation_out_of_disk_space(); goto free_and_return; } } } slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &rc); plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN : SLAPI_PLUGIN_POST_DELETE_FN); } free_and_return: if (be) { slapi_be_Unlock(be); } { char *coldn = NULL; Slapi_Entry *epre = NULL, *eparent = NULL; slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &epre); slapi_pblock_get(pb, SLAPI_DELETE_GLUE_PARENT_ENTRY, &eparent); slapi_pblock_set(pb, SLAPI_ENTRY_PRE_OP, NULL); slapi_pblock_set(pb, SLAPI_DELETE_GLUE_PARENT_ENTRY, NULL); if (epre == eparent) { eparent = NULL; } slapi_entry_free(epre); slapi_entry_free(eparent); slapi_pblock_get(pb, SLAPI_URP_NAMING_COLLISION_DN, &coldn); slapi_ch_free_string(&coldn); } slapi_pblock_get(pb, SLAPI_DELETE_TARGET_SDN, &sdn); slapi_sdn_free(&sdn); slapi_ch_free_string(&proxydn); slapi_ch_free_string(&proxystr); }
void do_compare( Slapi_PBlock *pb ) { BerElement *ber = pb->pb_op->o_ber; char *rawdn = NULL; const char *dn = NULL; struct ava ava = {0}; Slapi_Backend *be = NULL; int err; Slapi_DN sdn; Slapi_Entry *referral = NULL; char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE]; slapi_log_err(SLAPI_LOG_TRACE, "do_compare", "=>\n"); /* count the compare request */ slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsCompareOps); /* have to init this here so we can "done" it below if we short circuit */ slapi_sdn_init(&sdn); /* * Parse the compare request. It looks like this: * * CompareRequest := [APPLICATION 14] SEQUENCE { * entry DistinguishedName, * ava SEQUENCE { * type AttributeType, * value AttributeValue * } * } */ if ( ber_scanf( ber, "{a{ao}}", &rawdn, &ava.ava_type, &ava.ava_value ) == LBER_ERROR ) { slapi_log_err(SLAPI_LOG_ERR, "do_compare", "ber_scanf failed (op=Compare; params=DN,Type,Value)\n"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL ); goto free_and_return; } /* Check if we should be performing strict validation. */ if (config_get_dn_validate_strict()) { /* check that the dn is formatted correctly */ err = slapi_dn_syntax_check(pb, rawdn, 1); if (err) { /* syntax check failed */ op_shared_log_error_access(pb, "CMP", rawdn?rawdn:"", "strict: invalid dn"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid dn", 0, NULL); slapi_ch_free((void **) &rawdn); return; } } slapi_sdn_init_dn_passin(&sdn, rawdn); dn = slapi_sdn_get_dn(&sdn); if (rawdn && (strlen(rawdn) > 0) && (NULL == dn)) { /* normalization failed */ op_shared_log_error_access(pb, "CMP", rawdn, "invalid dn"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid dn", 0, NULL); slapi_sdn_done(&sdn); return; } /* * in LDAPv3 there can be optional control extensions on * the end of an LDAPMessage. we need to read them in and * pass them to the backend. */ if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) { send_ldap_result( pb, err, NULL, NULL, 0, NULL ); goto free_and_return; } /* target spec is used to decide which plugins are applicable for the operation */ operation_set_target_spec (pb->pb_op, &sdn); slapi_log_err(SLAPI_LOG_ARGS, "do_compare: dn (%s) attr (%s)\n", rawdn, ava.ava_type, 0 ); slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d CMP dn=\"%s\" attr=\"%s\"\n", pb->pb_conn->c_connid, pb->pb_op->o_opid, dn, ava.ava_type ); /* * 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 free_and_return; } if (referral) { int managedsait; slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait); if (managedsait) { send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "cannot compare referral", 0, NULL); slapi_entry_free(referral); goto free_and_return; } send_referrals_from_entry(pb,referral); slapi_entry_free(referral); goto free_and_return; } if ( be->be_compare != NULL ) { int isroot; slapi_pblock_set( pb, SLAPI_BACKEND, be ); isroot = pb->pb_op->o_isroot; slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &isroot ); /* EXCEPTION: compare target does not allocate memory. */ /* target never be modified by plugins. */ slapi_pblock_set( pb, SLAPI_COMPARE_TARGET_SDN, (void*)&sdn ); slapi_pblock_set( pb, SLAPI_COMPARE_TYPE, ava.ava_type); slapi_pblock_set( pb, SLAPI_COMPARE_VALUE, &ava.ava_value ); /* * call the pre-compare plugins. if they succeed, call * the backend compare function. then call the * post-compare plugins. */ if ( plugin_call_plugins( pb, SLAPI_PLUGIN_PRE_COMPARE_FN ) == 0 ) { int rc; slapi_pblock_set( pb, SLAPI_PLUGIN, be->be_database ); set_db_default_result_handlers(pb); rc = (*be->be_compare)( pb ); slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, &rc ); plugin_call_plugins( pb, SLAPI_PLUGIN_POST_COMPARE_FN ); } } else { send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Function not implemented", 0, NULL ); } free_and_return:; if (be) slapi_be_Unlock(be); slapi_sdn_done(&sdn); ava_done( &ava ); }
int _ger_generate_template_entry ( Slapi_PBlock *pb ) { Slapi_Entry *e = NULL; char **gerattrs = NULL; char **attrs = NULL; char **allowedattrs = NULL; char *templateentry = NULL; char *object = NULL; char *superior = NULL; char *p = NULL; const char *dn = NULL; Slapi_DN *sdn = NULL; char *dntype = NULL; int siz = 0; int len = 0; int i = 0; int notfirst = 0; int rc = LDAP_SUCCESS; slapi_pblock_get( pb, SLAPI_SEARCH_GERATTRS, &gerattrs ); if (NULL == gerattrs) { slapi_log_err(SLAPI_LOG_ERR, plugin_name, "_ger_generate_template_entry - Objectclass info is expected " "in the attr list, e.g., \"*@person\"\n"); rc = LDAP_SUCCESS; goto bailout; } for (i = 0; gerattrs && gerattrs[i]; i++) { object = strchr(gerattrs[i], '@'); if (NULL != object && '\0' != *(++object)) { break; } } if (NULL == object) { rc = LDAP_SUCCESS; /* no objectclass info; ok to return */ goto bailout; } /* * Either @objectclass or @objectclass:dntype is accepted. * If @objectclass, the first MUST attributetype (or the first MAY * attributetype if MUST does not exist) is used for the attribute * type in the leaf RDN. * If @objectclass:dntype, dntype is used for the attribute type in the * leaf RDN. */ dntype = strchr(object, ':'); if (dntype) { /* @objectclasse:dntype */ *dntype++ = '\0'; } attrs = slapi_schema_list_objectclass_attributes( (const char *)object, SLAPI_OC_FLAG_REQUIRED); allowedattrs = slapi_schema_list_objectclass_attributes( (const char *)object, SLAPI_OC_FLAG_ALLOWED); charray_merge(&attrs, allowedattrs, 0 /* no copy */); slapi_ch_free((void **)&allowedattrs); /* free just allowedattrs */ if (NULL == attrs) { rc = LDAP_SUCCESS; /* bogus objectclass info; ok to return */ goto bailout; } for (i = 0; attrs[i]; i++) { if (0 == strcasecmp(attrs[i], "objectclass")) { /* <*attrp>: <object>\n\0 */ siz += strlen(attrs[i]) + 4 + strlen(object); } else { /* <*attrp>: (template_attribute)\n\0 */ siz += strlen(attrs[i]) + 4 + 20; } } /* get the target dn where the template entry is located */ slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn ); dn = slapi_sdn_get_dn(sdn); if (dn) { /* dn: <attr>=<template_name>,<dn>\n\0 */ if (dntype) { siz += strlen(dntype) + 30 + strlen(object) + strlen(dn); } else { siz += strlen(attrs[0]) + 30 + strlen(object) + strlen(dn); } } else { /* dn: <attr>=<template_name>\n\0 */ if (dntype) { siz += strlen(dntype) + 30 + strlen(object); } else { siz += strlen(attrs[0]) + 30 + strlen(object); } } templateentry = (char *)slapi_ch_malloc(siz); if (NULL != dn && strlen(dn) > 0) { PR_snprintf(templateentry, siz, "dn: %s=template_%s_objectclass,%s\n", dntype?dntype:attrs[0], object, dn); } else { PR_snprintf(templateentry, siz, "dn: %s=template_%s_objectclass\n", dntype?dntype:attrs[0], object); } for (--i; i >= 0; i--) { len = strlen(templateentry); p = templateentry + len; if (0 == strcasecmp(attrs[i], "objectclass")) { PR_snprintf(p, siz - len, "%s: %s\n", attrs[i], object); } else { PR_snprintf(p, siz - len, "%s: (template_attribute)\n", attrs[i]); } } charray_free(attrs); while ((superior = slapi_schema_get_superior_name(object)) && (0 != strcasecmp(superior, "top"))) { if (notfirst) { slapi_ch_free_string(&object); } notfirst = 1; object = superior; attrs = slapi_schema_list_objectclass_attributes( (const char *)superior, SLAPI_OC_FLAG_REQUIRED); for (i = 0; attrs && attrs[i]; i++) { if (0 == strcasecmp(attrs[i], "objectclass")) { /* <*attrp>: <object>\n\0 */ siz += strlen(attrs[i]) + 4 + strlen(object); } } templateentry = (char *)slapi_ch_realloc(templateentry, siz); for (--i; i >= 0; i--) { len = strlen(templateentry); p = templateentry + len; if (0 == strcasecmp(attrs[i], "objectclass")) { PR_snprintf(p, siz - len, "%s: %s\n", attrs[i], object); } } charray_free(attrs); } if (notfirst) { slapi_ch_free_string(&object); } slapi_ch_free_string(&superior); siz += 18; /* objectclass: top\n\0 */ len = strlen(templateentry); templateentry = (char *)slapi_ch_realloc(templateentry, siz); p = templateentry + len; PR_snprintf(p, siz - len, "objectclass: top\n"); e = slapi_str2entry(templateentry, SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF); /* set the template entry to send the result to clients */ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, e); bailout: slapi_ch_free_string(&templateentry); return rc; }
static int _ger_g_permission_granted ( Slapi_PBlock *pb, Slapi_Entry *e, const char *subjectdn, char **errbuf ) { char *proxydn = NULL; Slapi_DN *requestor_sdn, *entry_sdn; char *errtext = NULL; int isroot; int rc; /* * Theorically, we should check if the entry has "g" * permission granted to the requestor. If granted, * allows the effective rights on that entry and its * attributes within the entry to be returned for * ANY subject. * * "G" permission granting has not been implemented yet, * the current release assumes that "g" permission be * granted to root and owner of any entry. */ /* * The requestor may be either the bind dn or a proxy dn */ if ((proxyauth_get_dn( pb, &proxydn, &errtext ) == LDAP_SUCCESS) && ( proxydn != NULL )) { requestor_sdn = slapi_sdn_new_dn_passin ( proxydn ); } else { slapi_ch_free_string(&proxydn); /* this could still have been set - free it */ requestor_sdn = &(pb->pb_op->o_sdn); } if ( slapi_sdn_get_dn (requestor_sdn) == NULL ) { slapi_log_err(SLAPI_LOG_ACL, plugin_name, "_ger_g_permission_granted - Anonymous has no g permission\n" ); rc = LDAP_INSUFFICIENT_ACCESS; goto bailout; } isroot = slapi_dn_isroot ( slapi_sdn_get_dn (requestor_sdn) ); if ( isroot ) { /* Root has "g" permission on any entry */ rc = LDAP_SUCCESS; goto bailout; } entry_sdn = slapi_entry_get_sdn ( e ); if ( entry_sdn == NULL || slapi_sdn_get_dn (entry_sdn) == NULL ) { rc = LDAP_SUCCESS; goto bailout; } if ( slapi_sdn_compare ( requestor_sdn, entry_sdn ) == 0 ) { /* Owner has "g" permission on his own entry */ rc = LDAP_SUCCESS; goto bailout; } /* if the requestor and the subject user are identical, let's grant it */ if ( strcasecmp ( slapi_sdn_get_ndn(requestor_sdn), subjectdn ) == 0) { /* Requestor should see his own permission rights on any entry */ rc = LDAP_SUCCESS; goto bailout; } aclutil_str_append ( errbuf, "get-effective-rights: requestor has no g permission on the entry" ); slapi_log_err(SLAPI_LOG_ACL, plugin_name, "_ger_g_permission_granted - %s\n", *errbuf); rc = LDAP_INSUFFICIENT_ACCESS; bailout: if ( proxydn ) { /* The ownership of proxydn has passed to requestor_sdn */ slapi_sdn_free ( &requestor_sdn ); } return rc; }
void slapi_rdn_set_sdn( Slapi_RDN *rdn, const Slapi_DN *sdn ) { slapi_rdn_set_dn( rdn, slapi_sdn_get_dn( sdn ) ); }
/* * op_shared_rename() -- common frontend code for modDN operations. * * Beware: this function resets the following pblock elements that were * set by the caller: * * SLAPI_MODRDN_TARGET_SDN * SLAPI_MODRDN_NEWRDN * SLAPI_MODRDN_NEWSUPERIOR_SDN */ static void op_shared_rename(Slapi_PBlock *pb, int passin_args) { char *dn, *newrdn, *newdn = NULL; const char *newsuperior; char **rdns; int deloldrdn; Slapi_Backend *be = NULL; Slapi_DN *origsdn = NULL; Slapi_Mods smods; int internal_op, repl_op, lastmod; Slapi_Operation *operation; Slapi_Entry *referral; char errorbuf[BUFSIZ]; int err; char *proxydn = NULL; char *proxystr = NULL; int proxy_err = LDAP_SUCCESS; char *errtext = NULL; Slapi_DN *sdn = NULL; Slapi_DN *newsuperiorsdn = NULL; slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET, &dn); slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn); slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperiorsdn); slapi_pblock_get(pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn); slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op); slapi_pblock_get (pb, SLAPI_OPERATION, &operation); slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &origsdn); internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL); /* * If ownership has not been passed to this function, we replace the * string input fields within the pblock with strdup'd copies. Why? * Because some pre- and post-op plugins may change them, and the * convention is that plugins should place a malloc'd string in the * pblock. Therefore, we need to be able to retrieve and free them * later. But the callers of the internal modrdn calls are promised * that we will not free these parameters... so if passin_args is * zero, we need to make copies. * * In the case of SLAPI_MODRDN_TARGET_SDN and SLAPI_MODRDN_NEWSUPERIOR_SDN, * we replace the existing values with normalized values (because plugins * expect these DNs to be normalized). */ if (NULL == origsdn) { sdn = slapi_sdn_new_dn_byval(dn); slapi_pblock_set(pb, SLAPI_MODRDN_TARGET_SDN, sdn); } if (passin_args) { if (NULL == sdn) { /* origsdn is not NULL, so use it. */ sdn = origsdn; } } else { if (NULL == sdn) { sdn = slapi_sdn_dup(origsdn); } newrdn = slapi_ch_strdup(newrdn); newsuperiorsdn = slapi_sdn_dup(newsuperiorsdn); slapi_pblock_set(pb, SLAPI_MODRDN_TARGET_SDN, sdn); slapi_pblock_set(pb, SLAPI_MODRDN_NEWRDN, (void *)newrdn); slapi_pblock_set(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, newsuperiorsdn); } /* normdn = slapi_sdn_get_dn(sdn); */ newsuperior = slapi_sdn_get_dn(newsuperiorsdn); /* get the proxy auth dn if the proxy auth control is present */ proxy_err = proxyauth_get_dn(pb, &proxydn, &errtext); /* * first, log the operation to the access log, * then check rdn and newsuperior, * and - if applicable - log reason of any error to the errors log */ 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 MODRDN dn=\"%s\" newrdn=\"%s\" newsuperior=\"%s\"%s\n", pb->pb_conn->c_connid, pb->pb_op->o_opid, dn, newrdn ? newrdn : "(null)", newsuperior ? newsuperior : "(null)", proxystr ? proxystr : ""); } else { slapi_log_access(LDAP_DEBUG_ARGS, "conn=%s op=%d MODRDN dn=\"%s\" newrdn=\"%s\" newsuperior=\"%s\"%s\n", LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID, dn, newrdn ? newrdn : "(null)", newsuperior ? newsuperior : "(null)", proxystr ? proxystr : ""); } } /* 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 free_and_return_nolock; } /* check that the rdn is formatted correctly */ if ((rdns = slapi_ldap_explode_rdn(newrdn, 0)) == NULL) { if ( !internal_op ) { slapi_log_error(SLAPI_LOG_ARGS, NULL, "conn=%" NSPRIu64 " op=%d MODRDN invalid new RDN (\"%s\")\n", pb->pb_conn->c_connid, pb->pb_op->o_opid, (NULL == newrdn) ? "(null)" : newrdn); } else { slapi_log_error(SLAPI_LOG_ARGS, NULL, "conn=%s op=%d MODRDN invalid new RDN (\"%s\")\n", LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID, (NULL == newrdn) ? "(null)" : newrdn); } send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid RDN", 0, NULL); goto free_and_return_nolock; } else { slapi_ldap_value_free(rdns); } /* check if created attributes are used in the new RDN */ /* check_rdn_for_created_attrs ignores the cases */ if (check_rdn_for_created_attrs((const char *)newrdn)) { send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid attribute in RDN", 0, NULL); goto free_and_return_nolock; } /* check that the dn is formatted correctly */ err = slapi_dn_syntax_check(pb, newsuperior, 1); if (err) { LDAPDebug0Args(LDAP_DEBUG_ARGS, "Syntax check of newSuperior failed\n"); if (!internal_op) { slapi_log_error(SLAPI_LOG_ARGS, NULL, "conn=%" NSPRIu64 " op=%d MODRDN invalid new superior (\"%s\")", pb->pb_conn->c_connid, pb->pb_op->o_opid, newsuperior ? newsuperior : "(null)"); } else { slapi_log_error(SLAPI_LOG_ARGS, NULL, "conn=%s op=%d MODRDN invalid new superior (\"%s\")", LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID, newsuperior ? newsuperior : "(null)"); } send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "newSuperior does not look like a DN", 0, NULL); goto free_and_return_nolock; } if (newsuperior != NULL) { LDAPDebug(LDAP_DEBUG_ARGS, "do_moddn: newsuperior (%s)\n", newsuperior, 0, 0); } /* target spec is used to decide which plugins are applicable for the operation */ operation_set_target_spec (pb->pb_op, sdn); /* * Construct the new DN (code sdn from backend * and modified to handle newsuperior) */ newdn = slapi_moddn_get_newdn(sdn, newrdn, newsuperior); /* * We could be serving multiple database backends. Select the * appropriate one, or send a referral to our "referral server" * if we don't hold it. */ /* slapi_mapping_tree_select_and_check ignores the case of newdn * which is generated using newrdn above. */ if ((err = slapi_mapping_tree_select_and_check(pb, newdn, &be, &referral, errorbuf)) != LDAP_SUCCESS) { send_ldap_result(pb, err, NULL, errorbuf, 0, NULL); goto free_and_return_nolock; } 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 free_and_return; } send_referrals_from_entry(pb,referral); slapi_entry_free(referral); goto free_and_return; } slapi_pblock_set(pb, SLAPI_BACKEND, be); /* can get lastmod only after backend is selected */ slapi_pblock_get(pb, SLAPI_BE_LASTMOD, &lastmod); /* if it is a replicated operation - leave lastmod attributes alone */ slapi_mods_init (&smods, 2); if (!repl_op && lastmod) { modify_update_last_modified_attr(pb, &smods); slapi_pblock_set(pb, SLAPI_MODIFY_MODS, (void*)slapi_mods_get_ldapmods_passout(&smods)); } else { slapi_mods_done (&smods); } /* * call the pre-modrdn plugins. if they succeed, call * the backend modrdn function. then call the * post-modrdn plugins. */ if (plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN : SLAPI_PLUGIN_PRE_MODRDN_FN) == 0) { int rc= LDAP_OPERATIONS_ERROR; slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database); set_db_default_result_handlers(pb); if (be->be_modrdn != NULL) { if ((rc = (*be->be_modrdn)(pb)) == 0) { Slapi_Entry *pse; Slapi_Entry *ecopy; /* we don't perform acl check for internal operations */ /* dont 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_MODRDN); 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); slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &ecopy); /* GGOODREPL persistent search system needs the changenumber, oops. */ do_ps_service(pse, ecopy, LDAP_CHANGETYPE_MODDN, 0); } } 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_MODRDN_FN : SLAPI_PLUGIN_POST_MODRDN_FN); } free_and_return: if (be) slapi_be_Unlock(be); free_and_return_nolock: { /* Free up everything left in the PBlock */ Slapi_Entry *pse; Slapi_Entry *ecopy; LDAPMod **mods; char *s; if (passin_args) { if (NULL == origsdn) { slapi_sdn_free(&sdn); } } else { slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &sdn); slapi_sdn_free(&sdn); /* get newrdn to free the string */ slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn); slapi_ch_free_string(&newrdn); slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperiorsdn); slapi_sdn_free(&newsuperiorsdn); } slapi_ch_free_string(&newdn); slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &ecopy); slapi_entry_free(ecopy); slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse); slapi_entry_free(pse); slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods ); ldap_mods_free( mods, 1 ); slapi_ch_free_string(&proxydn); slapi_ch_free_string(&proxystr); slapi_pblock_get(pb, SLAPI_URP_NAMING_COLLISION_DN, &s); slapi_ch_free((void **)&s); } }
int aclinit_main() { Slapi_PBlock *pb; int rv; Slapi_DN *sdn; void *node; if (acl_initialized) { /* There is no need to do anything more */ return 0; } /* Initialize the LIBACCESS ACL library */ if (ACL_Init() != 0) { slapi_log_err(SLAPI_LOG_ERR, plugin_name, "aclinit_main - ACL Library Initialization failed\n"); return 1; } /* register all the LASes supported by the DS */ if (ACL_ERR == __aclinit__RegisterLases()) { /* Error is already logged */ return 1; } /* Register all the Attrs */ if (ACL_ERR == __aclinit__RegisterAttributes()) { /* Error is already logged */ return 1; } /* * Register to get backend state changes so we can add/remove * acis from backends that come up and go down. */ slapi_register_backend_state_change((void *) NULL, acl_be_state_change_fnc); /* register the extensions */ /* ONREPL Moved to the acl_init function because extensions need to be registered before any operations are issued if ( 0 != acl_init_ext() ) { slapi_log_err(SLAPI_LOG_ERR, plugin_name, "Unable to initialize the extensions\n"); return 1; } */ /* create the mutex array */ if ( 0 != aclext_alloc_lockarray ( ) ) { slapi_log_err(SLAPI_LOG_ERR, plugin_name, "aclinit_main - Unable to create the mutext array\n"); return 1; } /* Allocate the pool */ if ( 0 != acl_create_aclpb_pool () ) { slapi_log_err(SLAPI_LOG_ERR, plugin_name, "aclinit_main - Unable to create the acl private pool\n"); return 1; } /* * Now read all the ACLs from all the backends and put it * in a list */ /* initialize the ACLLIST sub-system */ if ( 0 != (rv = acllist_init ( ))) { slapi_log_err(SLAPI_LOG_ERR, plugin_name, "aclinit_main - Unable to initialize the plugin:%d\n", rv ); return 1; } /* Initialize the anonymous profile i.e., generate it */ rv = aclanom_init (); pb = slapi_pblock_new(); /* * search for the aci_attr_type attributes of all entries. * * slapi_get_fist_suffix() and slapi_get_next_suffix() do not return the * rootdse entry so we search for acis in there explicitly here. */ sdn = slapi_sdn_new_ndn_byval(""); slapi_log_err(SLAPI_LOG_ACL, plugin_name, "aclinit_main - Searching for all acis(scope base) at suffix ''\n"); aclinit_search_and_update_aci ( 0, /* thisbeonly */ sdn, /* base */ NULL, /* be name*/ LDAP_SCOPE_BASE, ACL_ADD_ACIS, DO_TAKE_ACLCACHE_WRITELOCK); slapi_sdn_free(&sdn); sdn = slapi_get_first_suffix( &node, 1 ); while (sdn) { slapi_log_err(SLAPI_LOG_ACL, plugin_name, "aclinit_main - Searching for all acis(scope subtree) at suffix '%s'\n", slapi_sdn_get_dn(sdn) ); aclinit_search_and_update_aci ( 0, /* thisbeonly */ sdn, /* base */ NULL, /* be name*/ LDAP_SCOPE_SUBTREE, ACL_ADD_ACIS, DO_TAKE_ACLCACHE_WRITELOCK); sdn = slapi_get_next_suffix( &node, 1 ); } /* Initialize it. */ acl_initialized = 1; /* generate the signatures */ acl_set_aclsignature ( aclutil_gen_signature ( 100 ) ); /* Initialize the user-group cache */ rv = aclgroup_init ( ); aclanom_gen_anomProfile (DO_TAKE_ACLCACHE_READLOCK); /* Register both of the proxied authorization controls (version 1 and 2) */ slapi_register_supported_control( LDAP_CONTROL_PROXYAUTH, SLAPI_OPERATION_SEARCH | SLAPI_OPERATION_COMPARE | SLAPI_OPERATION_ADD | SLAPI_OPERATION_DELETE | SLAPI_OPERATION_MODIFY | SLAPI_OPERATION_MODDN | SLAPI_OPERATION_EXTENDED ); slapi_register_supported_control( LDAP_CONTROL_PROXIEDAUTH, SLAPI_OPERATION_SEARCH | SLAPI_OPERATION_COMPARE | SLAPI_OPERATION_ADD | SLAPI_OPERATION_DELETE | SLAPI_OPERATION_MODIFY | SLAPI_OPERATION_MODDN | SLAPI_OPERATION_EXTENDED ); slapi_pblock_destroy ( pb ); return 0; }
/*************************************************************************** * * __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 aclinit_search_and_update_aci ( int thisbeonly, const Slapi_DN *base, char *be_name, int scope, int op, acl_lock_flag_t lock_flag ) { char *attrs[2] = { "aci", NULL }; /* Tell __aclinit_handler whether it's an add or a delete */ Slapi_PBlock *aPb; LDAPControl **ctrls=NULL; struct berval *bval; aclinit_handler_callback_data_t call_back_data; PR_ASSERT( lock_flag == DONT_TAKE_ACLCACHE_WRITELOCK || lock_flag == DO_TAKE_ACLCACHE_WRITELOCK); if ( thisbeonly && be_name == NULL) { slapi_log_err(SLAPI_LOG_ERR, plugin_name, "aclinit_search_and_update_aci - be_name must be specified.\n"); return -1; } /* * We need to explicitly request (objectclass=ldapsubentry) * in order to get all the subentry acis too. * Note that subentries can be added under subentries (although its not * recommended) so that * there may be non-trivial acis under a subentry. */ /* Use new search internal API */ /* and never retrieve aci from a remote server */ aPb = slapi_pblock_new (); /* * Set up the control to say "Only get acis from this Backend-- * there may be more backends under this one. */ if ( thisbeonly ) { bval = (struct berval *)slapi_ch_malloc(sizeof(struct berval)); bval->bv_len = strlen(be_name) + 1; bval->bv_val = slapi_ch_strdup(be_name); ctrls = (LDAPControl **)slapi_ch_calloc( 2, sizeof(LDAPControl *)); ctrls[0] = NULL; ctrls[1] = NULL; slapi_build_control_from_berval( MTN_CONTROL_USE_ONE_BACKEND_OID, bval, 1 /* is critical */, ctrls); } slapi_search_internal_set_pb ( aPb, slapi_sdn_get_dn(base), scope, "(|(aci=*)(objectclass=ldapsubentry))", attrs, 0 /* attrsonly */, ctrls /* controls: SLAPI_ARGCONTROLS */, NULL /* uniqueid */, aclplugin_get_identity (ACL_PLUGIN_IDENTITY), SLAPI_OP_FLAG_NEVER_CHAIN /* actions : get local aci only */); if (thisbeonly) { slapi_pblock_set(aPb, SLAPI_REQCONTROLS, ctrls); } call_back_data.op = op; call_back_data.retCode = 0; call_back_data.lock_flag = lock_flag; slapi_search_internal_callback_pb(aPb, &call_back_data /* callback_data */, NULL/* result_callback */, __aclinit_handler, NULL /* referral_callback */); if (thisbeonly) { slapi_ch_free((void **)&bval); } /* * This frees the control oid, the bv_val and the control itself and the * ctrls array mem by caling ldap_controls_free()--so we * don't need to do it ourselves. */ slapi_pblock_destroy (aPb); return call_back_data.retCode; }
int update_integrity(char **argv, Slapi_DN *origSDN, char *newrDN, Slapi_DN *newsuperior, int logChanges) { Slapi_PBlock *search_result_pb = NULL; Slapi_PBlock *mod_pb = slapi_pblock_new(); Slapi_Entry **search_entries = NULL; Slapi_DN *sdn = NULL; Slapi_Attr *attr = NULL; void *node = NULL; const char *origDN = slapi_sdn_get_dn(origSDN); const char *search_base = NULL; char *attrName = NULL; char *filter = NULL; char *attrs[2]; int search_result; int nval = 0; int i, j; int rc; if ( argv == NULL ){ slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "referint_postop required config file arguments missing\n" ); rc = -1; goto free_and_return; } /* * For now, just putting attributes to keep integrity on in conf file, * until resolve the other timing mode issue */ search_result_pb = slapi_pblock_new(); /* Search each namingContext in turn */ for ( sdn = slapi_get_first_suffix( &node, 0 ); sdn != NULL; sdn = slapi_get_next_suffix( &node, 0 )) { Slapi_Backend *be = slapi_be_select(sdn); search_base = slapi_sdn_get_dn( sdn ); for(i = 3; argv[i] != NULL; i++){ filter = slapi_filter_sprintf("(%s=*%s%s)", argv[i], ESC_NEXT_VAL, origDN); if ( filter ) { /* Need only the current attribute and its subtypes */ attrs[0] = argv[i]; attrs[1] = NULL; /* Use new search API */ slapi_pblock_init(search_result_pb); slapi_pblock_set(search_result_pb, SLAPI_BACKEND, be); slapi_search_internal_set_pb(search_result_pb, search_base, LDAP_SCOPE_SUBTREE, filter, attrs, 0 /* attrs only */, NULL, NULL, referint_plugin_identity, 0); slapi_search_internal_pb(search_result_pb); slapi_pblock_get( search_result_pb, SLAPI_PLUGIN_INTOP_RESULT, &search_result); /* if search successfull then do integrity update */ if(search_result == LDAP_SUCCESS) { slapi_pblock_get(search_result_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &search_entries); for(j = 0; search_entries[j] != NULL; j++){ attr = NULL; attrName = NULL; /* * Loop over all the attributes of the entry and search * for the integrity attribute and its subtypes */ for (slapi_entry_first_attr(search_entries[j], &attr); attr; slapi_entry_next_attr(search_entries[j], attr, &attr)) { /* * Take into account only the subtypes of the attribute * in argv[i] having the necessary value - origDN */ slapi_attr_get_type(attr, &attrName); if (slapi_attr_type_cmp(argv[i], attrName, SLAPI_TYPE_CMP_SUBTYPE) == 0) { nval = 0; slapi_attr_get_numvalues(attr, &nval); /* * We want to reduce the "modify" call as much as * possible. But if an entry contains 1000s of * attributes which need to be updated by the * referint plugin (e.g., a group containing 1000s * of members), we want to avoid to allocate too * many mods * in one "modify" call. * This is a compromise: If an attribute type has * more than 128 values, we update the attribute * value one by one. Otherwise, update all values * in one "modify" call. */ if (nval > 128) { rc = _update_one_per_mod( slapi_entry_get_sdn(search_entries[j]), attr, attrName, origSDN, newrDN, slapi_sdn_get_dn(newsuperior), mod_pb); } else { rc = _update_all_per_mod( slapi_entry_get_sdn(search_entries[j]), attr, attrName, origSDN, newrDN, slapi_sdn_get_dn(newsuperior), mod_pb); } /* Should we stop if one modify returns an error? */ } } } } else { if (isFatalSearchError(search_result)){ slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "update_integrity search (base=%s filter=%s) returned " "error %d\n", search_base, filter, search_result); rc = -1; goto free_and_return; } } slapi_ch_free_string(&filter); } slapi_free_search_results_internal(search_result_pb); } } /* if got here, then everything good rc = 0 */ rc = 0; free_and_return: /* free filter and search_results_pb */ slapi_ch_free_string(&filter); slapi_pblock_destroy(mod_pb); if (search_result_pb) { slapi_free_search_results_internal(search_result_pb); slapi_pblock_destroy(search_result_pb); } return(rc); }
/* * 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; }
/* This function is called to process operation that come over external connections */ void do_add( Slapi_PBlock *pb ) { Slapi_Operation *operation; BerElement *ber; char *last; ber_len_t len = LBER_ERROR; ber_tag_t tag; Slapi_Entry *e = NULL; int err; int rc; PRBool searchsubentry=PR_TRUE; slapi_log_err(SLAPI_LOG_TRACE, "do_add", "==>\n"); slapi_pblock_get( pb, SLAPI_OPERATION, &operation); ber = operation->o_ber; /* count the add request */ slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps); /* * Parse the add request. It looks like this: * * AddRequest := [APPLICATION 14] SEQUENCE { * name DistinguishedName, * attrs SEQUENCE OF SEQUENCE { * type AttributeType, * values SET OF AttributeValue * } * } */ /* get the name */ { char *rawdn = NULL; Slapi_DN mysdn; if ( ber_scanf( ber, "{a", &rawdn ) == LBER_ERROR ) { slapi_ch_free_string(&rawdn); slapi_log_err(SLAPI_LOG_ERR, "do_add", "ber_scanf failed (op=Add; params=DN)\n"); op_shared_log_error_access (pb, "ADD", "???", "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0, NULL ); return; } /* Check if we should be performing strict validation. */ if (config_get_dn_validate_strict()) { /* check that the dn is formatted correctly */ rc = slapi_dn_syntax_check(pb, rawdn, 1); if (rc) { /* syntax check failed */ op_shared_log_error_access(pb, "ADD", rawdn?rawdn:"", "strict: invalid dn"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid dn", 0, NULL); slapi_ch_free_string(&rawdn); return; } } slapi_sdn_init_dn_passin(&mysdn, rawdn); if (rawdn && (strlen(rawdn) > 0) && (NULL == slapi_sdn_get_dn(&mysdn))) { /* normalization failed */ op_shared_log_error_access(pb, "ADD", rawdn, "invalid dn"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid dn", 0, NULL); slapi_sdn_done(&mysdn); return; } e = slapi_entry_alloc(); /* Responsibility for DN is passed to the Entry. */ slapi_entry_init_ext(e, &mysdn, NULL); slapi_sdn_done(&mysdn); } slapi_log_err(SLAPI_LOG_ARGS, "do_add", "dn (%s)\n", (char *)slapi_entry_get_dn_const(e)); /* get the attrs */ for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT && tag != LBER_END_OF_SEQORSET; tag = ber_next_element( ber, &len, last ) ) { char *type = NULL, *normtype = NULL; struct berval **vals = NULL; len = -1; /* reset - not used in loop */ if ( ber_scanf( ber, "{a{V}}", &type, &vals ) == LBER_ERROR ) { op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0, NULL ); slapi_ch_free_string(&type); ber_bvecfree( vals ); goto free_and_return; } if ( vals == NULL ) { slapi_log_err(SLAPI_LOG_ERR, "do_add - no values for type %s\n", type, 0, 0 ); op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "null value"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL ); slapi_ch_free_string(&type); goto free_and_return; } normtype = slapi_attr_syntax_normalize(type); if ( !normtype || !*normtype ) { char ebuf[SLAPI_DSE_RETURNTEXT_SIZE]; rc = LDAP_INVALID_SYNTAX; slapi_create_errormsg(ebuf, sizeof(ebuf), "invalid type '%s'", type); op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), ebuf); send_ldap_result( pb, rc, NULL, ebuf, 0, NULL ); slapi_ch_free_string(&type); slapi_ch_free( (void**)&normtype ); ber_bvecfree( vals ); goto free_and_return; } slapi_ch_free_string(&type); /* for now we just ignore attributes that client is not allowed to modify so not to break existing clients */ if (op_shared_is_allowed_attr (normtype, pb->pb_conn->c_isreplication_session)){ if (( rc = slapi_entry_add_values( e, normtype, vals )) != LDAP_SUCCESS ) { slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d ADD dn=\"%s\", add values for type %s failed\n", pb->pb_conn->c_connid, operation->o_opid, slapi_entry_get_dn_const(e), normtype ); send_ldap_result( pb, rc, NULL, NULL, 0, NULL ); slapi_ch_free( (void**)&normtype ); ber_bvecfree( vals ); goto free_and_return; } /* if this is uniqueid attribute, set uniqueid field of the entry */ if (strcasecmp (normtype, SLAPI_ATTR_UNIQUEID) == 0) { e->e_uniqueid = slapi_ch_strdup (vals[0]->bv_val); } if(searchsubentry) searchsubentry=check_oc_subentry(e,vals,normtype); } slapi_ch_free( (void**)&normtype ); ber_bvecfree( vals ); } /* Ensure that created attributes are not used in the RDN. */ if (check_rdn_for_created_attrs(e)) { op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn(slapi_entry_get_sdn_const(e)), "invalid DN"); send_ldap_result( pb, LDAP_INVALID_DN_SYNTAX, NULL, "illegal attribute in RDN", 0, NULL ); goto free_and_return; } /* len, is ber_len_t, which is uint. Can't be -1. May be better to remove (len != 0) check */ if ( (tag != LBER_END_OF_SEQORSET) && (len != -1) ) { op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0, NULL ); goto free_and_return; } /* * in LDAPv3 there can be optional control extensions on * the end of an LDAPMessage. we need to read them in and * pass them to the backend. */ if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) { op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "failed to decode LDAP controls"); send_ldap_result( pb, err, NULL, NULL, 0, NULL ); goto free_and_return; } slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &operation->o_isroot ); slapi_pblock_set( pb, SLAPI_ADD_ENTRY, e ); if (pb->pb_conn->c_flags & CONN_FLAG_IMPORT) { /* this add is actually part of a bulk import -- punt */ handle_fast_add(pb, e); } else { op_shared_add ( pb ); } /* make sure that we don't free entry if it is successfully added */ e = NULL; free_and_return:; if (e) slapi_entry_free (e); }
/* This function is called to process operation that come over external connections */ void do_modrdn( Slapi_PBlock *pb ) { Slapi_Operation *operation; BerElement *ber; char *rawdn = NULL, *rawnewsuperior = NULL; const char *dn = NULL, *newsuperior = NULL; char *newrdn = NULL; int err = 0, deloldrdn = 0; ber_len_t len = 0; char *newdn = NULL; char *parent = NULL; Slapi_DN sdn; Slapi_DN snewdn; Slapi_DN *snewsuperior = NULL; LDAPDebug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 ); /* count the modrdn request */ slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps); slapi_pblock_get( pb, SLAPI_OPERATION, &operation); ber = operation->o_ber; slapi_sdn_init(&sdn); slapi_sdn_init(&snewdn); /* * Parse the modrdn request. It looks like this: * * ModifyRDNRequest := SEQUENCE { * entry DistinguishedName, * newrdn RelativeDistinguishedName, * deleteoldrdn BOOLEAN, * newSuperior [0] LDAPDN OPTIONAL -- v3 only * } */ if (ber_scanf(ber, "{aab", &rawdn, &newrdn, &deloldrdn) == LBER_ERROR) { LDAPDebug( LDAP_DEBUG_ANY, "ber_scanf failed (op=ModRDN; params=DN,newRDN,deleteOldRDN)\n", 0, 0, 0 ); op_shared_log_error_access (pb, "MODRDN", "???", "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "unable to decode DN, newRDN, or deleteOldRDN parameters", 0, NULL ); goto free_and_return; } if ( ber_peek_tag( ber, &len ) == LDAP_TAG_NEWSUPERIOR ) { /* This "len" is not used... */ if ( pb->pb_conn->c_ldapversion < LDAP_VERSION3 ) { LDAPDebug( LDAP_DEBUG_ANY, "got newSuperior in LDAPv2 modrdn op\n", 0, 0, 0 ); op_shared_log_error_access (pb, "MODRDN", rawdn?rawdn:"", "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "received newSuperior in LDAPv2 modrdn", 0, NULL ); slapi_ch_free_string( &rawdn ); slapi_ch_free_string( &newrdn ); goto free_and_return; } if ( ber_scanf( ber, "a", &rawnewsuperior ) == LBER_ERROR ) { LDAPDebug( LDAP_DEBUG_ANY, "ber_scanf failed (op=ModRDN; params=newSuperior)\n", 0, 0, 0 ); op_shared_log_error_access (pb, "MODRDN", rawdn, "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "unable to decode newSuperior parameter", 0, NULL ); slapi_ch_free_string( &rawdn ); slapi_ch_free_string( &newrdn ); goto free_and_return; } } /* Check if we should be performing strict validation. */ if (config_get_dn_validate_strict()) { /* check that the dn is formatted correctly */ err = slapi_dn_syntax_check(pb, rawdn, 1); if (err) { /* syntax check failed */ op_shared_log_error_access(pb, "MODRDN", rawdn?rawdn:"", "strict: invalid dn"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid dn", 0, NULL); slapi_ch_free_string( &rawdn ); slapi_ch_free_string( &newrdn ); slapi_ch_free_string( &rawnewsuperior ); goto free_and_return; } /* check that the new rdn is formatted correctly */ err = slapi_dn_syntax_check(pb, newrdn, 1); if (err) { /* syntax check failed */ op_shared_log_error_access(pb, "MODRDN", newrdn?newrdn:"", "strict: invalid new rdn"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid new rdn", 0, NULL); slapi_ch_free_string( &rawdn ); slapi_ch_free_string( &newrdn ); slapi_ch_free_string( &rawnewsuperior ); goto free_and_return; } } slapi_sdn_init_dn_passin(&sdn, rawdn); dn = slapi_sdn_get_dn(&sdn); if (rawdn && (strlen(rawdn) > 0) && (NULL == dn)) { /* normalization failed */ op_shared_log_error_access(pb, "MODRDN", rawdn, "invalid dn"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid dn", 0, NULL); slapi_ch_free_string( &newrdn ); slapi_ch_free_string( &rawnewsuperior ); goto free_and_return; } if (rawnewsuperior) { if (config_get_dn_validate_strict()) { /* check that the dn is formatted correctly */ err = slapi_dn_syntax_check(pb, rawnewsuperior, 1); if (err) { /* syntax check failed */ op_shared_log_error_access(pb, "MODRDN", rawnewsuperior, "strict: invalid new superior"); send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid new superior", 0, NULL); slapi_ch_free_string( &rawnewsuperior ); goto free_and_return; } } snewsuperior = slapi_sdn_new_dn_passin(rawnewsuperior); newsuperior = slapi_sdn_get_dn(snewsuperior); } /* * If newsuperior is myself or my descendent, the modrdn should fail. * Note: need to check the case newrdn is given, and newsuperior * uses the newrdn, as well. */ parent = slapi_dn_parent(slapi_sdn_get_ndn(&sdn)); newdn = slapi_ch_smprintf("%s,%s", newrdn, parent); /* slapi_sdn_init_normdn_passin expects normalized but NOT * decapitalized dn */ slapi_sdn_init_dn_passin(&snewdn, newdn); if (0 == slapi_sdn_compare(&sdn, snewsuperior) || 0 == slapi_sdn_compare(&snewdn, snewsuperior)) { op_shared_log_error_access(pb, "MODRDN", newsuperior, "new superior is identical to the entry dn"); send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "new superior is identical to the entry dn", 0, NULL); goto free_and_return; } if (slapi_sdn_issuffix(snewsuperior, &sdn) || slapi_sdn_issuffix(snewsuperior, &snewdn)) { /* E.g., * newsuperior: ou=sub,ou=people,dc=example,dc=com * dn: ou=people,dc=example,dc=com */ op_shared_log_error_access(pb, "MODRDN", newsuperior, "new superior is descendent of the entry"); send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "new superior is descendent of the entry", 0, NULL); goto free_and_return; } /* * in LDAPv3 there can be optional control extensions on * the end of an LDAPMessage. we need to read them in and * pass them to the backend. */ if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) { op_shared_log_error_access (pb, "MODRDN", dn, "failed to decode LDAP controls"); send_ldap_result( pb, err, NULL, NULL, 0, NULL ); goto free_and_return; } LDAPDebug( LDAP_DEBUG_ARGS, "do_modrdn: dn (%s) newrdn (%s) deloldrdn (%d)\n", dn, newrdn, deloldrdn ); slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &pb->pb_op->o_isroot ); /* dn, newrdn and newsuperior are all normalized */ slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, (void *)slapi_sdn_get_udn(&sdn) ); slapi_pblock_set( pb, SLAPI_MODRDN_TARGET_SDN, &sdn ); slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN, (void *)newrdn ); slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, (void *)snewsuperior ); slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn ); op_shared_rename(pb, 0 /* do not pass in ownership of string arguments */ ); free_and_return: slapi_sdn_done(&sdn); slapi_ch_free_string(&newrdn); slapi_sdn_free(&snewsuperior); slapi_sdn_done(&snewdn); slapi_ch_free_string(&parent); return; }
Slapi_RDN *slapi_rdn_new_sdn( const Slapi_DN *sdn ) { return slapi_rdn_new_dn( slapi_sdn_get_dn( sdn ) ); }
/* * Write this record to the log file */ void writeintegritylog(Slapi_PBlock *pb, char *logfilename, Slapi_DN *sdn, char *newrdn, Slapi_DN *newsuperior, Slapi_DN *requestorsdn) { PRFileDesc *prfd; char buffer[MAX_LINE]; int len_to_write = 0; int rc; const char *requestordn = NULL; const char *newsuperiordn = NULL; size_t reqdn_len = 0; /* * Use this lock to protect file data when update integrity is occuring. * If betxn is enabled, this mutex is ignored; transaction itself takes * the role. */ referint_lock(); if (( prfd = PR_Open( logfilename, PR_WRONLY | PR_CREATE_FILE | PR_APPEND, REFERINT_DEFAULT_FILE_MODE )) == NULL ) { slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "referint_postop could not write integrity log \"%s\" " SLAPI_COMPONENT_NAME_NSPR " %d (%s)\n", logfilename, PR_GetError(), slapd_pr_strerror(PR_GetError()) ); PR_Unlock(referint_mutex); referint_unlock(); return; } /* * Make sure we have enough room in our buffer before trying to write it. * add length of dn + 5(three tabs, a newline, and terminating \0) */ len_to_write = slapi_sdn_get_ndn_len(sdn) + 5; if(newrdn == NULL){ /* add the length of "NULL" */ len_to_write += 4; } else { /* add the length of the newrdn */ len_to_write += strlen(newrdn); } newsuperiordn = slapi_sdn_get_dn(newsuperior); if(NULL == newsuperiordn) { /* add the length of "NULL" */ len_to_write += 4; } else { /* add the length of the newsuperior */ len_to_write += slapi_sdn_get_ndn_len(newsuperior); } slapi_pblock_get(pb, SLAPI_REQUESTOR_DN, &requestordn); if (requestorsdn && (requestordn = slapi_sdn_get_udn(requestorsdn)) && (reqdn_len = strlen(requestordn))) { len_to_write += reqdn_len; } else { len_to_write += 4; /* "NULL" */ } if(len_to_write > MAX_LINE ){ slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "referint_postop could not write integrity log:" " line length exceeded. It will not be able" " to update references to this entry.\n"); } else { PR_snprintf(buffer, MAX_LINE, "%s\t%s\t%s\t%s\t\n", slapi_sdn_get_dn(sdn), (newrdn != NULL) ? newrdn : "NULL", (newsuperiordn != NULL) ? newsuperiordn : "NULL", requestordn ? requestordn : "NULL"); if (PR_Write(prfd,buffer,strlen(buffer)) < 0){ slapi_log_error(SLAPI_LOG_FATAL,REFERINT_PLUGIN_SUBSYSTEM, " writeintegritylog: PR_Write failed : The disk" " may be full or the file is unwritable :: NSPR error - %d\n", PR_GetError()); } } /* If file descriptor is closed successfully, PR_SUCCESS */ rc = PR_Close(prfd); if (rc != PR_SUCCESS){ slapi_log_error(SLAPI_LOG_FATAL,REFERINT_PLUGIN_SUBSYSTEM, " writeintegritylog: failed to close the file descriptor prfd; NSPR error - %d\n", PR_GetError()); } referint_unlock(); }
static int add_created_attrs(Slapi_PBlock *pb, Slapi_Entry *e) { char buf[20]; char *binddn = NULL; char *plugin_dn = NULL; struct berval bv; struct berval *bvals[2]; time_t curtime; struct tm ltm; Operation *op; struct slapdplugin *plugin = NULL; struct slapi_componentid *cid = NULL; slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); slapi_log_err(SLAPI_LOG_TRACE, "add_created_attrs", "==>\n"); bvals[0] = &bv; bvals[1] = NULL; slapi_pblock_get(pb, SLAPI_OPERATION, &op); if(slapdFrontendConfig->plugin_track){ /* plugin bindDN tracking is enabled, grab the dn from thread local storage */ if(slapi_sdn_isempty(&op->o_sdn)){ bv.bv_val = ""; bv.bv_len = 0; } else { slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid); if (cid){ plugin=(struct slapdplugin *) cid->sci_plugin; } else { slapi_pblock_get (pb, SLAPI_PLUGIN, &plugin); } if(plugin) plugin_dn = plugin_get_dn (plugin); if(plugin_dn){ bv.bv_val = plugin_dn; bv.bv_len = strlen(bv.bv_val); } else { bv.bv_val = (char*)slapi_sdn_get_dn(&op->o_sdn); bv.bv_len = strlen(bv.bv_val); } } slapi_entry_attr_replace(e, "internalCreatorsName", bvals); slapi_entry_attr_replace(e, "internalModifiersName", bvals); slapi_ch_free_string(&plugin_dn); /* Grab the thread data(binddn) */ slapi_td_get_dn(&binddn); if(binddn == NULL){ /* anonymous bind */ bv.bv_val = ""; bv.bv_len = 0; } else { bv.bv_val = binddn; bv.bv_len = strlen(bv.bv_val); } } else { if (slapi_sdn_isempty(&op->o_sdn)) { bv.bv_val = ""; bv.bv_len = 0; } else { bv.bv_val = (char*)slapi_sdn_get_dn(&op->o_sdn); bv.bv_len = strlen(bv.bv_val); } } slapi_entry_attr_replace(e, "creatorsname", bvals); slapi_entry_attr_replace(e, "modifiersname", bvals); curtime = current_time(); gmtime_r(&curtime, <m); strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", <m); bv.bv_val = buf; bv.bv_len = strlen(bv.bv_val); slapi_entry_attr_replace(e, "createtimestamp", bvals); bv.bv_val = buf; bv.bv_len = strlen(bv.bv_val); slapi_entry_attr_replace(e, "modifytimestamp", bvals); if (add_uniqueid(e) != UID_SUCCESS ) { return( -1 ); } return( 0 ); }