From b3bb983f256e3a48dafea309800fac1a42648157 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 6 Apr 2011 14:02:08 +0200 Subject: s4:dsdb/repl_meta_data: update replPropertyMetaData on originating renames The version of the "name" attribute needs to change even if the value is the same. This also normalizes the rdn attribute name based on the schema. metze Autobuild-User: Stefan Metzmacher Autobuild-Date: Wed Apr 6 19:55:50 CEST 2011 on sn-devel-104 --- source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 128 ++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 6 deletions(-) (limited to 'source4/dsdb') diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index f5cdcf6361..646abeb771 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -2364,8 +2364,13 @@ static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *are struct replmd_replicated_request *ac; struct ldb_request *down_req; struct ldb_message *msg; + const struct dsdb_attribute *rdn_attr; + const char *rdn_name; + const struct ldb_val *rdn_val; + const char *attrs[4] = { NULL, }; time_t t = time(NULL); int ret; + bool is_urgent = false; ac = talloc_get_type(req->context, struct replmd_replicated_request); ldb = ldb_module_get_ctx(ac->module); @@ -2383,12 +2388,6 @@ static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *are LDB_ERR_OPERATIONS_ERROR); } - /* Get a sequence number from the backend */ - ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ac->seq_num); - if (ret != LDB_SUCCESS) { - return ret; - } - /* TODO: * - replace the old object with the newly constructed one */ @@ -2401,6 +2400,123 @@ static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *are msg->dn = ac->req->op.rename.newdn; + rdn_name = ldb_dn_get_rdn_name(msg->dn); + if (rdn_name == NULL) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_operr(ldb)); + } + + /* normalize the rdn attribute name */ + rdn_attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, rdn_name); + if (rdn_attr == NULL) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_operr(ldb)); + } + rdn_name = rdn_attr->lDAPDisplayName; + + rdn_val = ldb_dn_get_rdn_val(msg->dn); + if (rdn_val == NULL) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_operr(ldb)); + } + + if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_oom(ldb)); + } + if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_oom(ldb)); + } + if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_oom(ldb)); + } + if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_oom(ldb)); + } + + /* + * here we let replmd_update_rpmd() only search for + * the existing "replPropertyMetaData" and rdn_name attributes. + * + * We do not want the existing "name" attribute as + * the "name" attribute needs to get the version + * updated on rename even if the rdn value hasn't changed. + * + * This is the diff of the meta data, for a moved user + * on a w2k8r2 server: + * + * # record 1 + * -dn: CN=sdf df,CN=Users,DC=bla,DC=base + * +dn: CN=sdf df,OU=TestOU,DC=bla,DC=base + * replPropertyMetaData: NDR: struct replPropertyMetaDataBlob + * version : 0x00000001 (1) + * reserved : 0x00000000 (0) + * @@ -66,11 +66,11 @@ replPropertyMetaData: NDR: struct re + * local_usn : 0x00000000000037a5 (14245) + * array: struct replPropertyMetaData1 + * attid : DRSUAPI_ATTID_name (0x90001) + * - version : 0x00000001 (1) + * - originating_change_time : Wed Feb 9 17:20:49 2011 CET + * + version : 0x00000002 (2) + * + originating_change_time : Wed Apr 6 15:21:01 2011 CEST + * originating_invocation_id: 0d36ca05-5507-4e62-aca3-354bab0d39e1 + * - originating_usn : 0x00000000000037a5 (14245) + * - local_usn : 0x00000000000037a5 (14245) + * + originating_usn : 0x0000000000003834 (14388) + * + local_usn : 0x0000000000003834 (14388) + * array: struct replPropertyMetaData1 + * attid : DRSUAPI_ATTID_userAccountControl (0x90008) + * version : 0x00000004 (4) + */ + attrs[0] = "replPropertyMetaData"; + attrs[1] = "objectClass"; + attrs[2] = rdn_name; + attrs[3] = NULL; + + ret = replmd_update_rpmd(ac->module, ac->schema, req, attrs, + msg, &ac->seq_num, t, &is_urgent); + if (ret == LDB_ERR_REFERRAL) { + struct ldb_dn *olddn = ac->req->op.rename.olddn; + struct loadparm_context *lp_ctx; + const char *referral; + + lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"), + struct loadparm_context); + + referral = talloc_asprintf(req, + "ldap://%s/%s", + lpcfg_dnsdomain(lp_ctx), + ldb_dn_get_linearized(olddn)); + ret = ldb_module_send_referral(req, referral); + talloc_free(ac); + return ldb_module_done(req, NULL, NULL, ret); + } + + if (ret != LDB_SUCCESS) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_error(ldb, ret, + "failed to call replmd_update_rpmd()")); + } + + if (ac->seq_num == 0) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_error(ldb, ret, + "internal error seq_num == 0")); + } + ac->is_urgent = is_urgent; + ret = ldb_build_mod_req(&down_req, ldb, ac, msg, req->controls, -- cgit