/* writes the current cookie into dse.ldif under the replication agreement entry returns: ldap result code of the operation. */ int windows_private_save_dirsync_cookie(const Repl_Agmt *ra) { Dirsync_Private *dp = NULL; Slapi_PBlock *pb = NULL; Slapi_DN* sdn = NULL; int rc = 0; Slapi_Mods *mods = NULL; LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_save_dirsync_cookie\n" ); PR_ASSERT(ra); dp = (Dirsync_Private *) agmt_get_priv(ra); PR_ASSERT (dp); pb = slapi_pblock_new (); mods = windows_private_get_cookie_mod(dp, LDAP_MOD_REPLACE); sdn = slapi_sdn_dup( agmt_get_dn_byref(ra) ); slapi_modify_internal_set_pb_ext (pb, sdn, slapi_mods_get_ldapmods_byref(mods), NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0); slapi_modify_internal_pb (pb); slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); if (rc == LDAP_NO_SUCH_ATTRIBUTE) { /* try again, but as an add instead */ slapi_mods_free(&mods); mods = windows_private_get_cookie_mod(dp, LDAP_MOD_ADD); slapi_modify_internal_set_pb_ext (pb, sdn, slapi_mods_get_ldapmods_byref(mods), NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0); slapi_modify_internal_pb (pb); slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); } slapi_pblock_destroy (pb); slapi_mods_free(&mods); slapi_sdn_free(&sdn); LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_save_dirsync_cookie\n" ); return rc; }
/* Plugin startup function, when this is called any other plugins should already be initialized, so it's safe to e.g. perform internal searches, which is needed to retrieve the plugin configuration */ int acct_policy_start( Slapi_PBlock *pb ) { acctPluginCfg *cfg; void *plugin_id = get_identity(); Slapi_DN *plugindn = NULL; char *config_area = NULL; if(slapi_plugin_running(pb)){ return 0; } slapi_pblock_get(pb, SLAPI_TARGET_SDN, &plugindn); acct_policy_set_plugin_sdn(slapi_sdn_dup(plugindn)); /* Set the alternate config area if one is defined. */ slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_AREA, &config_area); if (config_area) { acct_policy_set_config_area(slapi_sdn_new_normdn_byval(config_area)); } if(config_rwlock == NULL){ if((config_rwlock = slapi_new_rwlock()) == NULL){ return( CALLBACK_ERR ); } } /* Load plugin configuration */ if( acct_policy_load_config_startup( pb, plugin_id ) ) { slapi_log_err(SLAPI_LOG_ERR, PLUGIN_NAME, "acct_policy_start failed to load configuration\n" ); return( CALLBACK_ERR ); } /* Show the configuration */ cfg = get_config(); slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME, "acct_policy_start - config: " "stateAttrName=%s altStateAttrName=%s specAttrName=%s limitAttrName=%s " "alwaysRecordLogin=%d\n", cfg->state_attr_name, cfg->alt_state_attr_name?cfg->alt_state_attr_name:"not configured", cfg->spec_attr_name, cfg->limit_attr_name, cfg->always_record_login); return( CALLBACK_OK ); }
/* * 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); } }
/* 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); }
/* * memberof_copy_config() * * Makes a copy of the config in src. This function will free the * elements of dest if they already exist. This should only be called * if you hold the memberof config lock if src was obtained with * memberof_get_config(). */ void memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src) { if (dest && src) { /* Check if the copy is already up to date */ if (src->groupattrs) { int i = 0, j = 0; /* Copy group attributes string list. */ slapi_ch_array_free(dest->groupattrs); dest->groupattrs = slapi_ch_array_dup(src->groupattrs); /* Copy group check filter. */ slapi_filter_free(dest->group_filter, 1); dest->group_filter = slapi_filter_dup(src->group_filter); /* Copy group attributes Slapi_Attr list. * First free the old list. */ for (i = 0; dest->group_slapiattrs && dest->group_slapiattrs[i]; i++) { slapi_attr_free(&dest->group_slapiattrs[i]); } /* Count how many values we have in the source list. */ for (j = 0; src->group_slapiattrs[j]; j++) { /* Do nothing. */ } /* Realloc dest if necessary. */ if (i < j) { dest->group_slapiattrs = (Slapi_Attr **)slapi_ch_realloc((char *)dest->group_slapiattrs, sizeof(Slapi_Attr *) * (j + 1)); } /* Copy the attributes. */ for (i = 0; src->group_slapiattrs[i]; i++) { dest->group_slapiattrs[i] = slapi_attr_dup(src->group_slapiattrs[i]); } /* Terminate the array. */ dest->group_slapiattrs[i] = NULL; } if (src->memberof_attr) { slapi_ch_free_string(&dest->memberof_attr); dest->memberof_attr = slapi_ch_strdup(src->memberof_attr); } if(src->skip_nested){ dest->skip_nested = src->skip_nested; } if(src->allBackends) { dest->allBackends = src->allBackends; } slapi_ch_free_string(&dest->auto_add_oc); dest->auto_add_oc = slapi_ch_strdup(src->auto_add_oc); if(src->entryScopes){ int num_vals = 0; dest->entryScopes = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),src->entryScopeCount+1); for(num_vals = 0; src->entryScopes[num_vals]; num_vals++){ dest->entryScopes[num_vals] = slapi_sdn_dup(src->entryScopes[num_vals]); } } if(src->entryScopeExcludeSubtrees){ int num_vals = 0; dest->entryScopeExcludeSubtrees = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),src->entryExcludeScopeCount+1); for(num_vals = 0; src->entryScopeExcludeSubtrees[num_vals]; num_vals++){ dest->entryScopeExcludeSubtrees[num_vals] = slapi_sdn_dup(src->entryScopeExcludeSubtrees[num_vals]); } } } }
/* * Perform the agreement/domain specific configuration. * IPA stores its configuration in the tree. We use the * ds_subtree to search for the domain/realm specific * configuration entries. */ void ipa_winsync_config_refresh_domain( void *cbdata, const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree ) { IPA_WinSync_Domain_Config *iwdc = (IPA_WinSync_Domain_Config *)cbdata; Slapi_DN *config_dn = slapi_sdn_dup(ds_subtree); char *realm_filter = NULL; char *realm_attr = NULL; char *new_entry_filter = NULL; char *new_user_oc_attr = NULL; /* don't care about groups for now */ char *homedir_prefix_attr = NULL; char *login_shell_attr = NULL; char *default_group_attr = NULL; char *default_group_filter = NULL; char *default_group_name = NULL; char *real_group_filter = NULL; char *default_gid = NULL; Slapi_ValueSet *new_user_objclasses = NULL; /* don't care about groups for now */ int loopdone = 0; int search_scope = LDAP_SCOPE_SUBTREE; int ret = LDAP_SUCCESS; int acct_disable; char *inactivated_filter = NULL; char *activated_filter = NULL; char *inactivated_group_dn = NULL; char *activated_group_dn = NULL; int upg = -1; slapi_lock_mutex(theConfig.lock); realm_filter = slapi_ch_strdup(theConfig.realm_filter); realm_attr = slapi_ch_strdup(theConfig.realm_attr); new_entry_filter = slapi_ch_strdup(theConfig.new_entry_filter); new_user_oc_attr = slapi_ch_strdup(theConfig.new_user_oc_attr); homedir_prefix_attr = slapi_ch_strdup(theConfig.homedir_prefix_attr); if (theConfig.login_shell_attr) { login_shell_attr = slapi_ch_strdup(theConfig.login_shell_attr); } default_group_attr = slapi_ch_strdup(theConfig.default_group_attr); default_group_filter = slapi_ch_strdup(theConfig.default_group_filter); acct_disable = theConfig.acct_disable; if (acct_disable != ACCT_DISABLE_NONE) { if (theConfig.inactivated_filter) { inactivated_filter = slapi_ch_strdup(theConfig.inactivated_filter); } if (theConfig.activated_filter) { activated_filter = slapi_ch_strdup(theConfig.activated_filter); } } slapi_unlock_mutex(theConfig.lock); /* starting at ds_subtree, search for the entry containing the Kerberos realm to use */ slapi_ch_free_string(&iwdc->realm_name); while(!loopdone && !slapi_sdn_isempty(config_dn)) { ret = internal_find_entry_get_attr_val(config_dn, search_scope, realm_filter, realm_attr, NULL, &iwdc->realm_name); if ((0 == ret) && iwdc->realm_name) { loopdone = 1; } else if ((LDAP_NO_SUCH_OBJECT == ret) && !iwdc->realm_name) { /* try again */ Slapi_DN *parent_dn = slapi_sdn_new(); slapi_sdn_get_parent(config_dn, parent_dn); slapi_sdn_free(&config_dn); config_dn = parent_dn; } else { /* error */ goto out; } } if (!iwdc->realm_name) { /* error - could not find the IPA config entry with the realm name */ LOG_FATAL("Error: could not find the entry containing the realm name " "[%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), realm_filter, realm_attr); goto out; } /* look for the entry containing the default objectclasses to add to new entries */ ret = internal_find_entry_get_attr_val(config_dn, search_scope, new_entry_filter, new_user_oc_attr, &new_user_objclasses, NULL); if (!new_user_objclasses) { /* error - could not find the entry containing list of objectclasses */ LOG_FATAL("Error: could not find the entry containing the new user objectclass list " "[%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, new_user_oc_attr); goto out; } /* get the home directory prefix value */ /* note - this is in the same entry as the new entry template, so use the same filter */ slapi_ch_free_string(&iwdc->homedir_prefix); ret = internal_find_entry_get_attr_val(config_dn, search_scope, new_entry_filter, homedir_prefix_attr, NULL, &iwdc->homedir_prefix); if (!iwdc->homedir_prefix) { /* error - could not find the home dir prefix */ LOG_FATAL("Error: could not find the entry containing the home directory prefix " "[%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, homedir_prefix_attr); goto out; } /* get the login shell value */ /* note - this is in the same entry as the new entry template, so use the same filter */ slapi_ch_free_string(&iwdc->login_shell); if (login_shell_attr) { ret = internal_find_entry_get_attr_val(config_dn, search_scope, new_entry_filter, login_shell_attr, NULL, &iwdc->login_shell); if (!iwdc->login_shell) { LOG("Warning: could not find the entry containing the login shell " "attribute [%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, login_shell_attr); } } if (!iwdc->login_shell) { /* could not find the login shell or was not configured */ LOG("Warning: no login shell configured!"); } /* find the default group - the entry above contains the group name, but we need the gidNumber for posixAccount - so first find the entry and attr value which has the group name, then lookup the group number from the group name */ ret = internal_find_entry_get_attr_val(config_dn, search_scope, new_entry_filter, default_group_attr, NULL, &default_group_name); if (!default_group_name) { /* error - could not find the default group name */ LOG_FATAL("Error: could not find the entry containing the default group name " "[%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, default_group_attr); goto out; } /* check if User Private Groups are enabled */ upg = ipa_winsync_upg_enabled(ds_subtree); /* next, find the group whose name is default_group_name - construct the filter based on the filter attribute value - assumes the group name is stored in the cn attribute value, and the gidNumber in the gidNumber attribute value */ real_group_filter = slapi_ch_smprintf("(&(cn=%s)%s)", default_group_name, default_group_filter); ret = internal_find_entry_get_attr_val(config_dn, search_scope, real_group_filter, "gidNumber", NULL, &default_gid); if (!default_gid) { /* error - could not find the default gidNumber This is not a fatal error if User Private Groups (UPG) are enabled. */ if (upg) { LOG_FATAL("Error: could not find the entry containing the default gidNumber " "UPG [%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, "gidNumber"); goto out; } else { ret = LDAP_SUCCESS; } } /* If we are syncing account disable, we need to find the groups used to denote active and inactive users e.g. dn: cn=inactivated,cn=account inactivation,cn=accounts,$SUFFIX dn: cn=Activated,cn=Account Inactivation,cn=accounts,$SUFFIX */ if (acct_disable != ACCT_DISABLE_NONE) { if (inactivated_filter) { ret = internal_find_entry_get_attr_val(config_dn, search_scope, inactivated_filter, "dn", NULL, &inactivated_group_dn); if (!inactivated_group_dn) { /* error - could not find the inactivated group dn */ LOG("Could not find the DN of the inactivated users group " "[%d] ds subtree [%s] filter [%s]. Ignoring\n", ret, slapi_sdn_get_dn(ds_subtree), inactivated_filter); goto out; } } if (activated_filter) { ret = internal_find_entry_get_attr_val(config_dn, search_scope, activated_filter, "dn", NULL, &activated_group_dn); if (!activated_group_dn) { /* error - could not find the activated group dn */ LOG("Could not find the DN of the activated users group " "[%d] ds subtree [%s] filter [%s]. Ignoring\n", ret, slapi_sdn_get_dn(ds_subtree), activated_filter); goto out; } } } /* ok, we have our values */ /* first, clear out the old domain config */ slapi_entry_free(iwdc->domain_e); iwdc->domain_e = NULL; /* next, copy the global attr config */ slapi_lock_mutex(theConfig.lock); iwdc->domain_e = slapi_entry_dup(theConfig.config_e); slapi_unlock_mutex(theConfig.lock); /* set the objectclasses in the domain_e */ slapi_entry_attr_delete(iwdc->domain_e, "objectclass"); /* this copies new_user_objclasses */ slapi_entry_add_valueset(iwdc->domain_e, "objectclass", new_user_objclasses); /* When UPG is disabled, set the default gid number */ if (upg && default_gid) { slapi_entry_attr_set_charptr(iwdc->domain_e, "gidNumber", default_gid); } slapi_ch_free_string(&iwdc->inactivated_group_dn); iwdc->inactivated_group_dn = inactivated_group_dn; inactivated_group_dn = NULL; slapi_ch_free_string(&iwdc->activated_group_dn); iwdc->activated_group_dn = activated_group_dn; activated_group_dn = NULL; out: slapi_valueset_free(new_user_objclasses); slapi_sdn_free(&config_dn); slapi_ch_free_string(&realm_filter); slapi_ch_free_string(&realm_attr); slapi_ch_free_string(&new_entry_filter); slapi_ch_free_string(&new_user_oc_attr); slapi_ch_free_string(&homedir_prefix_attr); slapi_ch_free_string(&login_shell_attr); slapi_ch_free_string(&default_group_attr); slapi_ch_free_string(&default_group_filter); slapi_ch_free_string(&default_group_name); slapi_ch_free_string(&real_group_filter); slapi_ch_free_string(&default_gid); slapi_ch_free_string(&inactivated_filter); slapi_ch_free_string(&inactivated_group_dn); slapi_ch_free_string(&activated_filter); slapi_ch_free_string(&activated_group_dn); if (LDAP_SUCCESS != ret) { slapi_ch_free_string(&iwdc->realm_name); slapi_ch_free_string(&iwdc->homedir_prefix); slapi_ch_free_string(&iwdc->login_shell); slapi_entry_free(iwdc->domain_e); iwdc->domain_e = NULL; } return; }
static int urp_add_resolve_parententry (Slapi_PBlock *pb, char *sessionid, Slapi_Entry *entry, Slapi_Entry *parententry, CSN *opcsn) { Slapi_DN *parentdn = NULL; Slapi_RDN *add_rdn = NULL; char *newdn = NULL; int ldap_rc; int rc = 0; Slapi_DN *sdn = NULL; if( is_suffix_entry (pb, entry, &parentdn) ) { /* It's OK for the suffix entry's parent to be absent */ rc= 0; PROFILE_POINT; /* Add Conflict; Suffix Entry */ goto bailout; } /* The entry is not a suffix. */ if(parententry==NULL) /* The parent entry was not found. */ { /* Create a glue entry to stand in for the absent parent */ slapi_operation_parameters *op_params; slapi_pblock_get( pb, SLAPI_OPERATION_PARAMETERS, &op_params ); ldap_rc = create_glue_entry (pb, sessionid, parentdn, op_params->p.p_add.parentuniqueid, opcsn); if ( LDAP_SUCCESS == ldap_rc ) { /* The backend code should now search for the parent again. */ rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY); rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY); PROFILE_POINT; /* Add Conflict; Orphaned Entry; Glue Parent */ } else { /* * Error. The parent can't be created as a glue entry. * This will cause replication divergence and will * require admin intercession */ ldap_rc= LDAP_OPERATIONS_ERROR; slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_rc); rc= -1; /* Abort this Operation */ PROFILE_POINT; /* Add Conflict; Orphaned Entry; Impossible to create parent; Refuse Change. */ } goto bailout; } if(is_tombstone_entry(parententry)) /* The parent is a tombstone */ { /* The parent entry must be resurected from the dead. */ ldap_rc = tombstone_to_glue (pb, sessionid, parententry, parentdn, REASON_RESURRECT_ENTRY, opcsn); if ( ldap_rc != LDAP_SUCCESS ) { ldap_rc= LDAP_OPERATIONS_ERROR; slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_rc); rc = -1; /* Abort the operation */ } else { /* The backend add code should now search for the parent again. */ rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY); rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY); } PROFILE_POINT; /* Add Conflict; Orphaned Entry; Parent Was Tombstone */ goto bailout; } /* The parent is healthy */ /* Now we need to check that the parent has the correct DN */ if (slapi_sdn_isparent(slapi_entry_get_sdn(parententry), slapi_entry_get_sdn(entry))) { rc= 0; /* OK, Add the entry */ PROFILE_POINT; /* Add Conflict; Parent Exists */ goto bailout; } /* * Parent entry doesn't have a DN parent to the entry. * This can happen if parententry was renamed due to * conflict and the child entry was created before * replication occured. See defect 530942. * We need to rename the entry to be child of its parent. */ add_rdn = slapi_rdn_new_dn(slapi_entry_get_dn_const (entry)); newdn = slapi_dn_plus_rdn(slapi_entry_get_dn_const (parententry), slapi_rdn_get_rdn(add_rdn)); slapi_entry_set_normdn ( entry, newdn ); /* slapi_pblock_get(pb, SLAPI_ADD_TARGET, &dn); */ slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn); slapi_sdn_free(&sdn); sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(entry)); slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, sdn); slapi_log_error ( slapi_log_urp, sessionid, "Parent was renamed. Renamed the child to %s\n", newdn ); rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY); PROFILE_POINT; /* Add Conflict; Parent Renamed; Rename Operation Entry */ bailout: if (parentdn) slapi_sdn_free(&parentdn); slapi_rdn_free(&add_rdn); return rc; }
/* * Return 0 for OK, * -1 for Ignore or Error depending on SLAPI_RESULT_CODE, * >0 for action code * Action Code Bit 0: Fetch existing entry. * Action Code Bit 1: Fetch parent entry. * The function is called as a be pre-op on consumers. */ int urp_add_operation( Slapi_PBlock *pb ) { Slapi_Entry *existing_uniqueid_entry; Slapi_Entry *existing_dn_entry; Slapi_Entry *addentry; const char *adduniqueid; CSN *opcsn; const char *basedn; char sessionid[REPL_SESSION_ID_SIZE]; int r; int op_result= 0; int rc= 0; /* OK */ Slapi_DN *sdn = NULL; if ( slapi_op_abandoned(pb) ) { return rc; } get_repl_session_id (pb, sessionid, &opcsn); slapi_pblock_get( pb, SLAPI_ADD_EXISTING_UNIQUEID_ENTRY, &existing_uniqueid_entry ); if (existing_uniqueid_entry!=NULL) { /* * An entry with this uniqueid already exists. * - It could be a replay of the same Add, or * - It could be a UUID generation collision, or */ /* * This operation won't be replayed. That is, this CSN won't update * the max csn in RUV. The CSN is left uncommitted in RUV unless an * error is set to op_result. Just to get rid of this CSN from RUV, * setting an error to op_result */ /* op_result = LDAP_SUCCESS; */ slapi_log_error(slapi_log_urp, sessionid, "urp_add (%s): an entry with this uniqueid already exists.\n", slapi_entry_get_dn_const(existing_uniqueid_entry)); op_result= LDAP_UNWILLING_TO_PERFORM; slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result); rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */ PROFILE_POINT; /* Add Conflict; UniqueID Exists; Ignore */ goto bailout; } slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &addentry ); slapi_pblock_get( pb, SLAPI_ADD_EXISTING_DN_ENTRY, &existing_dn_entry ); if (existing_dn_entry==NULL) /* The target DN does not exist */ { /* Check for parent entry... this could be an orphan. */ Slapi_Entry *parententry; slapi_pblock_get( pb, SLAPI_ADD_PARENT_ENTRY, &parententry ); rc = urp_add_resolve_parententry (pb, sessionid, addentry, parententry, opcsn); PROFILE_POINT; /* Add Entry */ goto bailout; } /* * Naming conflict: an entry with the target DN already exists. * Compare the DistinguishedNameCSN of the existing entry * and the OperationCSN. The smaller CSN wins. The loser changes * its RDN to uniqueid+baserdn, and adds operational attribute * ATTR_NSDS5_REPLCONFLIC. */ basedn = slapi_entry_get_ndn (addentry); adduniqueid = slapi_entry_get_uniqueid (addentry); r = csn_compare (entry_get_dncsn(existing_dn_entry), opcsn); if (r<0) { /* Entry to be added is a loser */ char *newdn= get_dn_plus_uniqueid (sessionid, basedn, adduniqueid); if(newdn==NULL) { op_result= LDAP_OPERATIONS_ERROR; slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result); rc = SLAPI_PLUGIN_NOOP; /* Abort this Operation */ slapi_log_error(slapi_log_urp, sessionid, "urp_add (%s): Add conflict; Unique ID (%s) already in RDN\n", basedn, adduniqueid); PROFILE_POINT; /* Add Conflict; Entry Exists; Unique ID already in RDN - Abort this update. */ } else { /* Add the nsds5ReplConflict attribute in the mods */ Slapi_Attr *attr = NULL; Slapi_Value **vals = NULL; Slapi_RDN *rdn; char buf[BUFSIZ]; PR_snprintf(buf, BUFSIZ, "%s %s", REASON_ANNOTATE_DN, basedn); if (slapi_entry_attr_find (addentry, ATTR_NSDS5_REPLCONFLICT, &attr) == 0) { /* ATTR_NSDS5_REPLCONFLICT exists */ slapi_log_error(SLAPI_LOG_FATAL, sessionid, "urp_add: New entry has nsds5ReplConflict already\n"); vals = attr_get_present_values (attr); /* this returns a pointer to the contents */ } if ( vals == NULL || *vals == NULL ) { /* Add new attribute */ slapi_entry_add_string (addentry, ATTR_NSDS5_REPLCONFLICT, buf); } else { /* * Replace old attribute. We don't worry about the index * change here since the entry is yet to be added. */ slapi_value_set_string (*vals, buf); } /* slapi_pblock_get(pb, SLAPI_ADD_TARGET, &dn); */ slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn); slapi_sdn_free(&sdn); slapi_entry_set_normdn(addentry, newdn); /* dn: passin */ sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(addentry)); slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, sdn); rdn = slapi_rdn_new_sdn ( slapi_entry_get_sdn_const(addentry) ); slapi_log_error (slapi_log_urp, sessionid, "urp_add: Naming conflict ADD. Add %s instead\n", slapi_rdn_get_rdn(rdn)); slapi_rdn_free(&rdn); rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY); PROFILE_POINT; /* Add Conflict; Entry Exists; Rename Operation Entry */ } } else if(r>0) { /* Existing entry is a loser */ if (!urp_annotate_dn(sessionid, existing_dn_entry, opcsn, "ADD")) { op_result= LDAP_OPERATIONS_ERROR; slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result); slapi_log_error(slapi_log_urp, sessionid, "urp_add (%s): Entry to be added is a loser; " "urp_annotate_dn failed.\n", basedn); rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */ } else { /* The backend add code should now search for the existing entry again. */ rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY); rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY); } PROFILE_POINT; /* Add Conflict; Entry Exists; Rename Existing Entry */ } else /* r==0 */ { /* The CSN of the Operation and the Entry DN are the same. * This could only happen if: * a) There are two replicas with the same ReplicaID. * b) We've seen the Operation before. * Let's go with (b) and ignore the little bastard. */ /* * This operation won't be replayed. That is, this CSN won't update * the max csn in RUV. The CSN is left uncommitted in RUV unless an * error is set to op_result. Just to get rid of this CSN from RUV, * setting an error to op_result */ /* op_result = LDAP_SUCCESS; */ slapi_log_error(slapi_log_urp, sessionid, "urp_add (%s): The CSN of the Operation and the Entry DN are the same.", slapi_entry_get_dn_const(existing_dn_entry)); op_result= LDAP_UNWILLING_TO_PERFORM; slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result); rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */ PROFILE_POINT; /* Add Conflict; Entry Exists; Same CSN */ } bailout: return rc; }
/* reads the cookie in dse.ldif to the replication agreement entry returns: ldap result code of ldap operation, or LDAP_NO_SUCH_ATTRIBUTE. (this is the equilivent of a null cookie) */ int windows_private_load_dirsync_cookie(const Repl_Agmt *ra) { Dirsync_Private *dp = NULL; Slapi_PBlock *pb = NULL; Slapi_DN* sdn = NULL; int rc = 0; Slapi_Entry *entry = NULL; Slapi_Attr *attr = NULL; LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_load_dirsync_cookie\n" ); PR_ASSERT(ra); dp = (Dirsync_Private *) agmt_get_priv(ra); PR_ASSERT (dp); pb = slapi_pblock_new (); sdn = slapi_sdn_dup( agmt_get_dn_byref(ra) ); rc = slapi_search_internal_get_entry(sdn, NULL, &entry, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION)); if (rc == 0) { rc= slapi_entry_attr_find( entry, type_nsds7DirsyncCookie, &attr ); if (attr) { struct berval **vals; rc = slapi_attr_get_bervals_copy(attr, &vals ); if (vals) { dp->dirsync_cookie_len = (int) (vals[0])->bv_len; slapi_ch_free_string(&dp->dirsync_cookie); dp->dirsync_cookie = ( char* ) slapi_ch_malloc(dp->dirsync_cookie_len + 1); memcpy(dp->dirsync_cookie,(vals[0]->bv_val), (vals[0])->bv_len+1); } ber_bvecfree(vals); /* we do not free attr */ } else { rc = LDAP_NO_SUCH_ATTRIBUTE; } } if (entry) { slapi_entry_free(entry); } slapi_sdn_free( &sdn); slapi_pblock_destroy (pb); LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_load_dirsync_cookie\n" ); return rc; }
/* * Depending on the context, this routine may need to take the * acicache read lock. */ void aclanom_gen_anomProfile (acl_lock_flag_t lock_flag) { aci_t *aci = NULL; int i; Targetattr **srcattrArray; Targetattr *attr; struct anom_profile *a_profile; PRUint32 cookie; PR_ASSERT( lock_flag == DO_TAKE_ACLCACHE_READLOCK || lock_flag == DONT_TAKE_ACLCACHE_READLOCK); /* * This routine requires two locks: * the one for the global cache in acllist_acicache_READ_LOCK() and * the one for the anom profile. * They _must_ be taken in the order presented here or there * is a deadlock scenario with acllist_remove_aci_needsLock() which * takes them is this order. */ if ( lock_flag == DO_TAKE_ACLCACHE_READLOCK ) { acllist_acicache_READ_LOCK(); } ANOM_LOCK_WRITE (); a_profile = acl_anom_profile; if ( (!acl_get_aclsignature()) || ( !a_profile) || (a_profile->anom_signature == acl_get_aclsignature()) ) { ANOM_UNLOCK_WRITE (); if ( lock_flag == DO_TAKE_ACLCACHE_READLOCK ) { acllist_acicache_READ_UNLOCK(); } return; } /* D0 we have one already. If we do, then clean it up */ aclanom__del_profile(0); /* We have a new signature now */ a_profile->anom_signature = acl_get_aclsignature(); slapi_log_err(SLAPI_LOG_ACL, plugin_name, "aclanom_gen_anomProfile - GENERATING ANOM USER PROFILE\n"); /* ** Go thru the ACL list and find all the ACLs which apply to the ** anonymous user i.e anyone. we can generate a profile for that. ** We will llok at the simple case i.e it matches ** cases not handled: ** 1) When there is a mix if rule types ( allows & denies ) ** */ aci = acllist_get_first_aci ( NULL, &cookie ); while ( aci ) { int a_numacl; struct slapi_filter *f; char **destattrArray; /* * We must not have a rule like: deny ( all ) userdn != "xyz" * or groupdn != */ if ( (aci->aci_type & ACI_HAS_DENY_RULE) && ( (aci->aci_type & ACI_CONTAIN_NOT_USERDN ) || (aci->aci_type & ACI_CONTAIN_NOT_GROUPDN) || (aci->aci_type & ACI_CONTAIN_NOT_ROLEDN)) ){ slapi_log_err(SLAPI_LOG_ACL, plugin_name, "aclanom_gen_anomProfile - CANCELLING ANOM USER PROFILE BECAUSE OF DENY RULE\n"); goto cleanup; } /* Must be a anyone rule */ if ( aci->aci_elevel != ACI_ELEVEL_USERDN_ANYONE ) { aci = acllist_get_next_aci ( NULL, aci, &cookie); continue; } if (! (aci->aci_access & ( SLAPI_ACL_READ | SLAPI_ACL_SEARCH)) ) { aci = acllist_get_next_aci ( NULL, aci, &cookie); continue; } /* If the rule has anything other than userdn = "ldap:///anyone" ** let's not consider complex rules - let's make this lean. */ if ( aci->aci_ruleType & ~ACI_USERDN_RULE ){ slapi_log_err(SLAPI_LOG_ACL, plugin_name, "aclanom_gen_anomProfile - CANCELLING ANOM USER PROFILE BECAUSE OF COMPLEX RULE\n"); goto cleanup; } /* Must not be a or have a ** 1 ) DENY RULE 2) targetfilter ** 3) no target pattern ( skip monitor acl ) */ if ( aci->aci_type & ( ACI_HAS_DENY_RULE | ACI_TARGET_PATTERN | ACI_TARGET_NOT | ACI_TARGET_FILTER_NOT )) { const char *dn = slapi_sdn_get_dn ( aci->aci_sdn ); /* see if this is a monitor acl */ if (( strcasecmp ( dn, "cn=monitor") == 0 ) || /* cn=monitor,cn=ldbm: No such object */ ( strcasecmp ( dn, "cn=monitor,cn=ldbm") == 0 )) { aci = acllist_get_next_aci ( NULL, aci, &cookie); continue; } else { /* clean up before leaving */ slapi_log_err(SLAPI_LOG_ACL, plugin_name, "aclanom_gen_anomProfile - CANCELLING ANOM USER PROFILE 1\n"); goto cleanup; } } /* Now we have an ALLOW ACL which applies to anyone */ a_numacl = a_profile->anom_numacls++; if ( a_profile->anom_numacls == ACL_ANOM_MAX_ACL ) { slapi_log_err(SLAPI_LOG_ACL, plugin_name, "aclanom_gen_anomProfile - CANCELLING ANOM USER PROFILE 2\n"); goto cleanup; } if ( (f = aci->target) != NULL ) { char *avaType; struct berval *avaValue; slapi_filter_get_ava ( f, &avaType, &avaValue ); a_profile->anom_targetinfo[a_numacl].anom_target = slapi_sdn_new_dn_byval ( avaValue->bv_val ); } else { a_profile->anom_targetinfo[a_numacl].anom_target = slapi_sdn_dup ( aci->aci_sdn ); } a_profile->anom_targetinfo[a_numacl].anom_filter = NULL; if ( aci->targetFilterStr ) { a_profile->anom_targetinfo[a_numacl].anom_filter = slapi_str2filter ( aci->targetFilterStr ); if (NULL == a_profile->anom_targetinfo[a_numacl].anom_filter) { const char *dn = slapi_sdn_get_dn ( aci->aci_sdn ); slapi_log_err(SLAPI_LOG_ERR, plugin_name, "aclanom_gen_anomProfile - Invalid filter [%s] in anonymous aci in entry [%s]\n", aci->targetFilterStr, dn); goto cleanup; } } i = 0; srcattrArray = aci->targetAttr; while ( srcattrArray[i]) i++; a_profile->anom_targetinfo[a_numacl].anom_targetAttrs = (char **) slapi_ch_calloc ( 1, (i+1) * sizeof(char *)); srcattrArray = aci->targetAttr; destattrArray = a_profile->anom_targetinfo[a_numacl].anom_targetAttrs; i = 0; while ( srcattrArray[i] ) { attr = srcattrArray[i]; if ( attr->attr_type & ACL_ATTR_FILTER ) { /* Do'nt want to support these kind now */ destattrArray[i] = NULL; /* clean up before leaving */ aclanom__del_profile (0); slapi_log_err(SLAPI_LOG_ACL, plugin_name, "aclanom_gen_anomProfile - CANCELLING ANOM USER PROFILE 3\n"); goto cleanup; } destattrArray[i] = slapi_ch_strdup ( attr->u.attr_str ); i++; } destattrArray[i] = NULL; aclutil_print_aci ( aci, "anom" ); /* Here we are storing att the info from the acls. However ** we are only interested in a few things like ACI_TARGETATTR_NOT. */ a_profile->anom_targetinfo[a_numacl].anom_type = aci->aci_type; a_profile->anom_targetinfo[a_numacl].anom_access = aci->aci_access; aci = acllist_get_next_aci ( NULL, aci, &cookie); } ANOM_UNLOCK_WRITE (); if ( lock_flag == DO_TAKE_ACLCACHE_READLOCK ) { acllist_acicache_READ_UNLOCK(); } return; cleanup: aclanom__del_profile (0); ANOM_UNLOCK_WRITE (); if ( lock_flag == DO_TAKE_ACLCACHE_READLOCK ) { acllist_acicache_READ_UNLOCK(); } }