The branch, master has been updated via 233e3c9 selftest: Remove print_smbtorture4_version and smbtorture4_possible check via d3cd9f1 dsdb: Do checks for invalid renames in samldb, before repl_meta_data from a7df00c s3-nmbd: reset debug settings after reading config file (bug #10239)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 233e3c96318db8111d8a7f5f649265cc9ecb5b27 Author: Andrew Bartlett <abart...@samba.org> Date: Fri Mar 21 12:42:46 2014 +1300 selftest: Remove print_smbtorture4_version and smbtorture4_possible check smbtorture is now always the same version as the rest of Samba, and is strictly required. Andrew Bartlett Change-Id: I89d9c52275477177fa8a89050920ff8a2fec9288 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-By: Jelmer Vernooij <jel...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Wed Mar 26 04:20:16 CET 2014 on sn-devel-104 commit d3cd9f1575af18a6765a6b6a31811c9976f9c11e Author: Andrew Bartlett <abart...@samba.org> Date: Mon Mar 24 17:15:19 2014 +1300 dsdb: Do checks for invalid renames in samldb, before repl_meta_data This ensures that conflict objects can be created in CN=System, and that we do not stop replication just because some other DC allowed a rename we do not like. This is achived by doing the work in the samldb module, which is above repl_meta_data in the stack. Andrew Bartlett Change-Id: I8c1a7d3e0fbd5a470cf1326cc055044ca885f7d9 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Guenter Kukkukk <ku...@samba.org> Tested-by: Guenter Kukkukk <ku...@samba.org> ----------------------------------------------------------------------- Summary of changes: selftest/selftesthelpers.py | 15 -- source3/selftest/tests.py | 9 +- source4/dsdb/samdb/ldb_modules/samldb.c | 261 ++++++++++++++++++++++- source4/dsdb/samdb/ldb_modules/subtree_rename.c | 248 +-------------------- source4/selftest/tests.py | 2 - 5 files changed, 273 insertions(+), 262 deletions(-) Changeset truncated at 500 lines: diff --git a/selftest/selftesthelpers.py b/selftest/selftesthelpers.py index cdbe975..40e38aa 100644 --- a/selftest/selftesthelpers.py +++ b/selftest/selftesthelpers.py @@ -210,21 +210,6 @@ smbtorture4_options = [ ] + get_env_torture_options() -def print_smbtorture4_version(): - """Print the version of Samba smbtorture4 comes from. - - :return: Whether smbtorture4 was successfully run - """ - try: - sub = subprocess.Popen([smbtorture4, "-V"], stdout=sys.stderr) - except OSError, e: - if e.errno == errno.ENOENT: - return False - raise - sub.communicate("") - return (sub.returncode == 0) - - def plansmbtorture4testsuite(name, env, options, target, modname=None): if modname is None: modname = "samba4.%s" % name diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index b8f477a..19e3066 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -29,19 +29,14 @@ smbtorture4_options.extend([ '--option=torture:writetimeupdatedelay=500000', ]) -smbtorture4_possible = print_smbtorture4_version() - def plansmbtorture4testsuite(name, env, options, description=''): if description == '': modname = "samba3.%s" % (name, ) else: modname = "samba3.%s %s" % (name, description) - if smbtorture4_possible: - selftesthelpers.plansmbtorture4testsuite( - name, env, options, target='samba3', modname=modname) - else: - skiptestsuite(name, "smbtorture4 is not available") + selftesthelpers.plansmbtorture4testsuite( + name, env, options, target='samba3', modname=modname) plantestsuite("samba3.blackbox.success", "s3dc:local", [os.path.join(samba3srcdir, "script/tests/test_success.sh")]) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 144d5a5..42a729c 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -1,7 +1,7 @@ /* SAM ldb module - Copyright (C) Andrew Bartlett <abart...@samba.org> 2005 + Copyright (C) Andrew Bartlett <abart...@samba.org> 2005-2014 Copyright (C) Simo Sorce 2004-2008 Copyright (C) Matthias Dieter Wallnöfer 2009-2011 Copyright (C) Matthieu Patou 2012 @@ -2600,6 +2600,264 @@ static int samldb_delete(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } +/* rename */ + +static int check_rename_constraints(struct ldb_message *msg, + struct samldb_ctx *ac, + struct ldb_dn *olddn, struct ldb_dn *newdn) +{ + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + struct ldb_dn *dn1, *dn2, *nc_root; + int32_t systemFlags; + bool move_op = false; + bool rename_op = false; + int ret; + + /* Skip the checks if old and new DN are the same, or if we have the + * relax control specified or if the returned objects is already + * deleted and needs only to be moved for consistency. */ + + if (ldb_dn_compare(olddn, newdn) == 0) { + return LDB_SUCCESS; + } + if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) != NULL) { + return LDB_SUCCESS; + } + if (ldb_msg_find_attr_as_bool(msg, "isDeleted", false)) { + return LDB_SUCCESS; + } + + /* Objects under CN=System */ + + dn1 = ldb_dn_copy(ac, ldb_get_default_basedn(ldb)); + if (dn1 == NULL) return ldb_oom(ldb); + + if ( ! ldb_dn_add_child_fmt(dn1, "CN=System")) { + talloc_free(dn1); + return LDB_ERR_OPERATIONS_ERROR; + } + + if ((ldb_dn_compare_base(dn1, olddn) == 0) && + (ldb_dn_compare_base(dn1, newdn) != 0)) { + talloc_free(dn1); + ldb_asprintf_errstring(ldb, + "subtree_rename: Cannot move/rename %s. Objects under CN=System have to stay under it!", + ldb_dn_get_linearized(olddn)); + return LDB_ERR_OTHER; + } + + talloc_free(dn1); + + /* LSA objects */ + + if ((samdb_find_attribute(ldb, msg, "objectClass", "secret") != NULL) || + (samdb_find_attribute(ldb, msg, "objectClass", "trustedDomain") != NULL)) { + ldb_asprintf_errstring(ldb, + "subtree_rename: Cannot move/rename %s. It's an LSA-specific object!", + ldb_dn_get_linearized(olddn)); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + /* systemFlags */ + + dn1 = ldb_dn_get_parent(ac, olddn); + if (dn1 == NULL) return ldb_oom(ldb); + dn2 = ldb_dn_get_parent(ac, newdn); + if (dn2 == NULL) return ldb_oom(ldb); + + if (ldb_dn_compare(dn1, dn2) == 0) { + rename_op = true; + } else { + move_op = true; + } + + talloc_free(dn1); + talloc_free(dn2); + + systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0); + + /* Fetch name context */ + + ret = dsdb_find_nc_root(ldb, ac, olddn, &nc_root); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) { + if (move_op) { + ldb_asprintf_errstring(ldb, + "subtree_rename: Cannot move %s within schema partition", + ldb_dn_get_linearized(olddn)); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + if (rename_op && + (systemFlags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) != 0) { + ldb_asprintf_errstring(ldb, + "subtree_rename: Cannot rename %s within schema partition", + ldb_dn_get_linearized(olddn)); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) { + if (move_op && + (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_MOVE) == 0) { + /* Here we have to do more: control the + * "ALLOW_LIMITED_MOVE" flag. This means that the + * grand-grand-parents of two objects have to be equal + * in order to perform the move (this is used for + * moving "server" objects in the "sites" container). */ + bool limited_move = + systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE; + + if (limited_move) { + dn1 = ldb_dn_copy(ac, olddn); + if (dn1 == NULL) return ldb_oom(ldb); + dn2 = ldb_dn_copy(ac, newdn); + if (dn2 == NULL) return ldb_oom(ldb); + + limited_move &= ldb_dn_remove_child_components(dn1, 3); + limited_move &= ldb_dn_remove_child_components(dn2, 3); + limited_move &= ldb_dn_compare(dn1, dn2) == 0; + + talloc_free(dn1); + talloc_free(dn2); + } + + if (!limited_move) { + ldb_asprintf_errstring(ldb, + "subtree_rename: Cannot move %s to %s in config partition", + ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn)); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + } + if (rename_op && + (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_RENAME) == 0) { + ldb_asprintf_errstring(ldb, + "subtree_rename: Cannot rename %s to %s within config partition", + ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn)); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) { + if (move_op && + (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE) != 0) { + ldb_asprintf_errstring(ldb, + "subtree_rename: Cannot move %s to %s - DISALLOW_MOVE set", + ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn)); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + if (rename_op && + (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME) != 0) { + ldb_asprintf_errstring(ldb, + "subtree_rename: Cannot rename %s to %s - DISALLOW_RENAME set", + ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn)); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + } + + talloc_free(nc_root); + + return LDB_SUCCESS; +} + + +static int samldb_rename_search_base_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct ldb_request *rename_req; + struct samldb_ctx *ac; + int ret; + + ac = talloc_get_type(req->context, struct samldb_ctx); + + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + /* + * This is the root entry of the originating move + * respectively rename request. It has been already + * stored in the list using "subtree_rename_search()". + * Only this one is subject to constraint checking. + */ + ret = check_rename_constraints(ares->message, ac, + ac->req->op.rename.olddn, + ac->req->op.rename.newdn); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, + ret); + } + break; + + case LDB_REPLY_REFERRAL: + /* ignore */ + break; + + case LDB_REPLY_DONE: + + /* + * Great, no problem with the rename, so go ahead as + * if we never were here + */ + ret = ldb_next_request(ac->module, ac->req); + talloc_free(ares); + return ret; + } + + talloc_free(ares); + return LDB_SUCCESS; +} + + +/* rename */ +static int samldb_rename(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + static const char * const attrs[] = { "objectClass", "systemFlags", + "isDeleted", NULL }; + struct ldb_request *search_req; + struct samldb_ctx *ac; + int ret; + + if (ldb_dn_is_special(req->op.rename.olddn)) { /* do not manipulate our control entries */ + return ldb_next_request(module, req); + } + + ldb = ldb_module_get_ctx(module); + + ac = samldb_ctx_init(module, req); + if (!ac) { + return ldb_oom(ldb); + } + + ret = ldb_build_search_req(&search_req, ldb, ac, + req->op.rename.olddn, + LDB_SCOPE_BASE, + "(objectClass=*)", + attrs, + NULL, + ac, + samldb_rename_search_base_callback, + req); + LDB_REQ_SET_LOCATION(search_req); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID, + true, NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + return ldb_next_request(ac->module, search_req); +} + /* extended */ static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req) @@ -2639,6 +2897,7 @@ static const struct ldb_module_ops ldb_samldb_module_ops = { .add = samldb_add, .modify = samldb_modify, .del = samldb_delete, + .rename = samldb_rename, .extended = samldb_extended }; diff --git a/source4/dsdb/samdb/ldb_modules/subtree_rename.c b/source4/dsdb/samdb/ldb_modules/subtree_rename.c index d26dabe..b9ecb3f 100644 --- a/source4/dsdb/samdb/ldb_modules/subtree_rename.c +++ b/source4/dsdb/samdb/ldb_modules/subtree_rename.c @@ -91,166 +91,11 @@ static int subtree_rename_callback(struct ldb_request *req, return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS); } -static int check_constraints(struct ldb_message *msg, - struct subtree_rename_context *ac, - struct ldb_dn *olddn, struct ldb_dn *newdn) -{ - struct ldb_context *ldb = ldb_module_get_ctx(ac->module); - struct ldb_dn *dn1, *dn2, *nc_root; - int32_t systemFlags; - bool move_op = false; - bool rename_op = false; - int ret; - - /* Skip the checks if old and new DN are the same, or if we have the - * relax control specified or if the returned objects is already - * deleted and needs only to be moved for consistency. */ - - if (ldb_dn_compare(olddn, newdn) == 0) { - return LDB_SUCCESS; - } - if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) != NULL) { - return LDB_SUCCESS; - } - if (ldb_msg_find_attr_as_bool(msg, "isDeleted", false)) { - return LDB_SUCCESS; - } - - /* Objects under CN=System */ - - dn1 = ldb_dn_copy(ac, ldb_get_default_basedn(ldb)); - if (dn1 == NULL) return ldb_oom(ldb); - - if ( ! ldb_dn_add_child_fmt(dn1, "CN=System")) { - talloc_free(dn1); - return LDB_ERR_OPERATIONS_ERROR; - } - - if ((ldb_dn_compare_base(dn1, olddn) == 0) && - (ldb_dn_compare_base(dn1, newdn) != 0)) { - talloc_free(dn1); - ldb_asprintf_errstring(ldb, - "subtree_rename: Cannot move/rename %s. Objects under CN=System have to stay under it!", - ldb_dn_get_linearized(olddn)); - return LDB_ERR_OTHER; - } - - talloc_free(dn1); - - /* LSA objects */ - - if ((samdb_find_attribute(ldb, msg, "objectClass", "secret") != NULL) || - (samdb_find_attribute(ldb, msg, "objectClass", "trustedDomain") != NULL)) { - ldb_asprintf_errstring(ldb, - "subtree_rename: Cannot move/rename %s. It's an LSA-specific object!", - ldb_dn_get_linearized(olddn)); - return LDB_ERR_UNWILLING_TO_PERFORM; - } - - /* systemFlags */ - - dn1 = ldb_dn_get_parent(ac, olddn); - if (dn1 == NULL) return ldb_oom(ldb); - dn2 = ldb_dn_get_parent(ac, newdn); - if (dn2 == NULL) return ldb_oom(ldb); - - if (ldb_dn_compare(dn1, dn2) == 0) { - rename_op = true; - } else { - move_op = true; - } - - talloc_free(dn1); - talloc_free(dn2); - - systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0); - - /* Fetch name context */ - - ret = dsdb_find_nc_root(ldb, ac, olddn, &nc_root); - if (ret != LDB_SUCCESS) { - return ret; - } - - if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) { - if (move_op) { - ldb_asprintf_errstring(ldb, - "subtree_rename: Cannot move %s within schema partition", - ldb_dn_get_linearized(olddn)); - return LDB_ERR_UNWILLING_TO_PERFORM; - } - if (rename_op && - (systemFlags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) != 0) { - ldb_asprintf_errstring(ldb, - "subtree_rename: Cannot rename %s within schema partition", - ldb_dn_get_linearized(olddn)); - return LDB_ERR_UNWILLING_TO_PERFORM; - } - } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) { - if (move_op && - (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_MOVE) == 0) { - /* Here we have to do more: control the - * "ALLOW_LIMITED_MOVE" flag. This means that the - * grand-grand-parents of two objects have to be equal - * in order to perform the move (this is used for - * moving "server" objects in the "sites" container). */ - bool limited_move = - systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE; - - if (limited_move) { - dn1 = ldb_dn_copy(ac, olddn); - if (dn1 == NULL) return ldb_oom(ldb); - dn2 = ldb_dn_copy(ac, newdn); - if (dn2 == NULL) return ldb_oom(ldb); - - limited_move &= ldb_dn_remove_child_components(dn1, 3); - limited_move &= ldb_dn_remove_child_components(dn2, 3); - limited_move &= ldb_dn_compare(dn1, dn2) == 0; - - talloc_free(dn1); - talloc_free(dn2); - } - - if (!limited_move) { - ldb_asprintf_errstring(ldb, - "subtree_rename: Cannot move %s to %s in config partition", - ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn)); - return LDB_ERR_UNWILLING_TO_PERFORM; - } - } - if (rename_op && - (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_RENAME) == 0) { - ldb_asprintf_errstring(ldb, - "subtree_rename: Cannot rename %s to %s within config partition", - ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn)); - return LDB_ERR_UNWILLING_TO_PERFORM; - } - } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) { - if (move_op && - (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE) != 0) { - ldb_asprintf_errstring(ldb, - "subtree_rename: Cannot move %s to %s - DISALLOW_MOVE set", - ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn)); - return LDB_ERR_UNWILLING_TO_PERFORM; - } - if (rename_op && - (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME) != 0) { - ldb_asprintf_errstring(ldb, - "subtree_rename: Cannot rename %s to %s - DISALLOW_RENAME set", - ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn)); - return LDB_ERR_UNWILLING_TO_PERFORM; - } - } - - talloc_free(nc_root); - - return LDB_SUCCESS; -- Samba Shared Repository