From b3ba0c85ffe08c39b9144b644b6aabca4ca17dfe Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Tue, 20 Sep 2016 04:25:34 +0000 Subject: [PATCH] rodc: Force all RODC add and delete to cause a referral Previously, you could add or delete and cause replication conflicts on an RODC. Modifies are already partly restricted in repl_meta_data and have more specific requirements, so they cannot be handled here. We still differ against Windows for modifies of non-replicated attributes over LDAP. Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett Pair-programmed-with: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=12008 --- selftest/knownfail | 3 +- source4/dsdb/samdb/ldb_modules/samldb.c | 70 +++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/selftest/knownfail b/selftest/knownfail index 7e204edcd01..571904a0009 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -326,6 +326,5 @@ ^samba4.blackbox.trust_ntlm.Test08.*client.*with.ADDOM.SAMBA.EXAMPLE.COM\\Administrator%locDCpass1\(fl2003dc:local\) ^samba4.blackbox.trust_ntlm.Test09.*client.*with.Administrator@ADDOMAIN%locDCpass1\(fl2003dc:local\) ^samba4.blackbox.trust_ntlm.Test10.*client.*with.Administrator@ADDOM.SAMBA.EXAMPLE.COM%locDCpass1\(fl2003dc:local\) -^samba4.ldap.rodc.python\(rodc\).__main__.RodcTests.test_add.* -^samba4.ldap.rodc.python\(rodc\).__main__.RodcTests.test_delete.* +# We currently don't send referrals for LDAP modify of non-replicated attrs ^samba4.ldap.rodc.python\(rodc\).__main__.RodcTests.test_modify_nonreplicated.* diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 48edc28967d..971048d455f 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -44,6 +44,7 @@ #include "param/param.h" #include "libds/common/flag_mapping.h" #include "system/network.h" +#include "librpc/gen_ndr/irpc.h" struct samldb_ctx; enum samldb_add_type { @@ -3380,6 +3381,58 @@ static int samldb_verify_subnet(struct samldb_ctx *ac) return LDB_SUCCESS; } +static char *refer_if_rodc(struct ldb_context *ldb, struct ldb_request *req, + struct ldb_dn *dn) +{ + bool rodc = false; + struct loadparm_context *lp_ctx; + char *referral; + int ret; + WERROR err; + + if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID) || + ldb_request_get_control(req, DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA)) { + return NULL; + } + + ret = samdb_rodc(ldb, &rodc); + if (ret != LDB_SUCCESS) { + DEBUG(4, (__location__ ": unable to tell if we are an RODC\n")); + return NULL; + } + + if (rodc) { + const char *domain = NULL; + struct ldb_dn *fsmo_role_dn; + struct ldb_dn *role_owner_dn; + ldb_set_errstring(ldb, "RODC modify is forbidden!"); + lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"), + struct loadparm_context); + + err = dsdb_get_fsmo_role_info(req, ldb, DREPL_PDC_MASTER, + &fsmo_role_dn, &role_owner_dn); + if (W_ERROR_IS_OK(err)) { + struct ldb_dn *server_dn = ldb_dn_copy(req, role_owner_dn); + if (server_dn != NULL) { + ldb_dn_remove_child_components(server_dn, 1); + + domain = samdb_dn_to_dnshostname(ldb, req, + server_dn); + } + } + if (domain == NULL) { + domain = lpcfg_dnsdomain(lp_ctx); + } + referral = talloc_asprintf(req, + "ldap://%s/%s", + domain, + ldb_dn_get_linearized(dn)); + return referral; + } + + return NULL; +} + /* add */ static int samldb_add(struct ldb_module *module, struct ldb_request *req) @@ -3388,6 +3441,7 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req) struct samldb_ctx *ac; struct ldb_message_element *el; int ret; + char *referral = NULL; ldb = ldb_module_get_ctx(module); ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n"); @@ -3397,6 +3451,12 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } + referral = refer_if_rodc(ldb, req, req->op.add.message->dn); + if (referral != NULL) { + ret = ldb_module_send_referral(req, referral); + return ret; + } + el = ldb_msg_find_element(req->op.add.message, "userParameters"); if (el != NULL && ldb_req_is_untrusted(req)) { const char *reason = "samldb_add: " @@ -3831,13 +3891,23 @@ static int samldb_prim_group_users_check(struct samldb_ctx *ac) static int samldb_delete(struct ldb_module *module, struct ldb_request *req) { struct samldb_ctx *ac; + char *referral = NULL; int ret; + struct ldb_context *ldb; if (ldb_dn_is_special(req->op.del.dn)) { /* do not manipulate our control entries */ return ldb_next_request(module, req); } + ldb = ldb_module_get_ctx(module); + + referral = refer_if_rodc(ldb, req, req->op.del.dn); + if (referral != NULL) { + ret = ldb_module_send_referral(req, referral); + return ret; + } + ac = samldb_ctx_init(module, req); if (ac == NULL) { return ldb_operr(ldb_module_get_ctx(module)); -- 2.11.4.GIT