diff options
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 95 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/samldb.c | 5 | ||||
-rw-r--r-- | source4/dsdb/samdb/samdb.h | 5 | ||||
-rw-r--r-- | source4/torture/libnet/libnet_BecomeDC.c | 43 |
4 files changed, 126 insertions, 22 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index d9ad9d6e51..171af52eda 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -40,8 +40,11 @@ */ #include "includes.h" -#include "ldb/include/includes.h" +#include "lib/ldb/include/ldb.h" +#include "lib/ldb/include/ldb_errors.h" +#include "lib/ldb/include/ldb_private.h" #include "librpc/gen_ndr/ndr_misc.h" +#include "dsdb/samdb/samdb.h" static struct ldb_message_element *replmd_find_attribute(const struct ldb_message *msg, const char *name) { @@ -108,8 +111,24 @@ static int add_uint64_element(struct ldb_message *msg, const char *attr, uint64_ return 0; } -/* add_record: add objectGUID attribute */ -static int replmd_add(struct ldb_module *module, struct ldb_request *req) +static int replmd_add_replicated(struct ldb_module *module, struct ldb_request *req, struct ldb_control *ctrl) +{ + struct ldb_control **saved_ctrls; + int ret; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "replmd_add_replicated\n"); + + if (!save_controls(ctrl, req, &saved_ctrls)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_next_request(module, req); + req->controls = saved_ctrls; + + return ret; +} + +static int replmd_add_originating(struct ldb_module *module, struct ldb_request *req) { struct ldb_request *down_req; struct ldb_message_element *attribute; @@ -121,12 +140,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req) int ret; time_t t = time(NULL); - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "replmd_add_record\n"); - - /* do not manipulate our control entries */ - if (ldb_dn_is_special(req->op.add.message->dn)) { - return ldb_next_request(module, req); - } + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "replmd_add_originating\n"); if ((attribute = replmd_find_attribute(req->op.add.message, "objectGUID")) != NULL ) { return ldb_next_request(module, req); @@ -192,8 +206,42 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req) return ret; } -/* modify_record: update timestamps */ -static int replmd_modify(struct ldb_module *module, struct ldb_request *req) +static int replmd_add(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_control *ctrl; + + /* do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.add.message->dn)) { + return ldb_next_request(module, req); + } + + ctrl = get_control_from_list(req->controls, DSDB_CONTROL_REPLICATED_OBJECT_OID); + if (ctrl) { + /* handle replicated objects different */ + return replmd_add_replicated(module, req, ctrl); + } + + return replmd_add_originating(module, req); +} + +static int replmd_modify_replicated(struct ldb_module *module, struct ldb_request *req, struct ldb_control *ctrl) +{ + struct ldb_control **saved_ctrls; + int ret; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "replmd_modify_replicated\n"); + + if (!save_controls(ctrl, req, &saved_ctrls)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_next_request(module, req); + req->controls = saved_ctrls; + + return ret; +} + +static int replmd_modify_originating(struct ldb_module *module, struct ldb_request *req) { struct ldb_request *down_req; struct ldb_message *msg; @@ -201,12 +249,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) time_t t = time(NULL); uint64_t seq_num; - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "replmd_modify\n"); - - /* do not manipulate our control entries */ - if (ldb_dn_is_special(req->op.add.message->dn)) { - return ldb_next_request(module, req); - } + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "replmd_modify_originating\n"); down_req = talloc(req, struct ldb_request); if (down_req == NULL) { @@ -250,6 +293,24 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) return ret; } +static int replmd_modify(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_control *ctrl; + + /* do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.mod.message->dn)) { + return ldb_next_request(module, req); + } + + ctrl = get_control_from_list(req->controls, DSDB_CONTROL_REPLICATED_OBJECT_OID); + if (ctrl) { + /* handle replicated objects different */ + return replmd_modify_replicated(module, req, ctrl); + } + + return replmd_modify_originating(module, req); +} + static const struct ldb_module_ops replmd_ops = { .name = "repl_meta_data", .add = replmd_add, diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 1c1ff0ea6e..07d77ee3fc 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -680,6 +680,11 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } + if (get_control_from_list(req->controls, DSDB_CONTROL_REPLICATED_OBJECT_OID)) { + /* if it's a replicated object we have nothing to do */ + return ldb_next_request(module, req); + } + /* is user or computer? */ if ((samdb_find_attribute(module->ldb, msg, "objectclass", "user") != NULL) || (samdb_find_attribute(module->ldb, msg, "objectclass", "computer") != NULL)) { diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h index 8ff44f7554..7d16b2d380 100644 --- a/source4/dsdb/samdb/samdb.h +++ b/source4/dsdb/samdb/samdb.h @@ -29,6 +29,11 @@ struct drsuapi_DsReplicaObject; struct drsuapi_DsReplicaOIDMapping_Ctr; struct drsuapi_DsReplicaAttribute; +#define DSDB_CONTROL_REPLICATED_OBJECT_OID "1.3.6.1.4.1.7165.4.3.1" +struct dsdb_control_replicated_object { + uint8_t __dummy; +}; + #include "librpc/gen_ndr/security.h" #include "lib/ldb/include/ldb.h" #include "librpc/gen_ndr/samr.h" diff --git a/source4/torture/libnet/libnet_BecomeDC.c b/source4/torture/libnet/libnet_BecomeDC.c index 0d4114c170..f4f232d19b 100644 --- a/source4/torture/libnet/libnet_BecomeDC.c +++ b/source4/torture/libnet/libnet_BecomeDC.c @@ -182,16 +182,16 @@ static NTSTATUS test_become_dc_prepare_db(void *private_data, " \"server_sort\",\n" " \"extended_dn\",\n" " \"asq\",\n" - " //\"samldb\",should only handle originating changes...\n" + " \"samldb\",\n" " \"password_hash\",\n" " \"operational\",\n" " \"objectclass\",\n" " \"rdn_name\",\n" " \"partition\");\n" "subobj.MODULES_LIST = join(\",\", modules_list);\n" - "subobj.DOMAINDN_MOD = \"objectguid\";\n" - "subobj.CONFIGDN_MOD = \"objectguid\";\n" - "subobj.SCHEMADN_MOD = \"objectguid\";\n" + "subobj.DOMAINDN_MOD = \"repl_meta_data\";\n" + "subobj.CONFIGDN_MOD = \"repl_meta_data\";\n" + "subobj.SCHEMADN_MOD = \"repl_meta_data\";\n" "\n" "var paths = provision_default_paths(subobj);\n" "paths.samdb = \"%s\";\n" @@ -265,6 +265,9 @@ static WERROR test_object_to_ldb(struct test_become_dc_state *s, struct drsuapi_DsReplicaMetaData *name_d; struct replPropertyMetaData1 *rdn_m; struct drsuapi_DsReplicaObjMetaData *rdn_mc; + struct ldb_request *req; + struct ldb_control **ctrls; + struct dsdb_control_replicated_object *ctrl; int ret; if (!obj->object.identifier) { @@ -424,7 +427,37 @@ static WERROR test_object_to_ldb(struct test_become_dc_state *s, NDR_PRINT_DEBUG(drsuapi_DsReplicaObjMetaDataCtr, &mdc); } - ret = ldb_add(s->ldb, msg); + /* + * apply the record to the ldb + * using an ldb_control so indicate + * that it's a replicated change + */ + ret = ldb_msg_sanity_check(s->ldb, msg); + if (ret != LDB_SUCCESS) { + return WERR_FOOBAR; + } + ctrls = talloc_array(msg, struct ldb_control *, 2); + W_ERROR_HAVE_NO_MEMORY(ctrls); + ctrls[0] = talloc(ctrls, struct ldb_control); + W_ERROR_HAVE_NO_MEMORY(ctrls[0]); + ctrls[1] = NULL; + + ctrl = talloc(ctrls, struct dsdb_control_replicated_object); + W_ERROR_HAVE_NO_MEMORY(ctrl); + ctrls[0]->oid = DSDB_CONTROL_REPLICATED_OBJECT_OID; + ctrls[0]->critical = True; + ctrls[0]->data = ctrl; + + ret = ldb_build_add_req(&req, s->ldb, msg, msg, ctrls, NULL, NULL); + if (ret != LDB_SUCCESS) { + return WERR_FOOBAR; + } + ldb_set_timeout(s->ldb, req, 0); /* use default timeout */ + ret = ldb_request(s->ldb, req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + talloc_free(req); if (ret != LDB_SUCCESS) { if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { DEBUG(0,("record exists (ignored): %s: %d\n", |