summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2011-04-06 14:02:08 +0200
committerStefan Metzmacher <metze@samba.org>2011-04-06 19:55:49 +0200
commitb3bb983f256e3a48dafea309800fac1a42648157 (patch)
treeeda38ec77625f5900ffb3ad4ca3144082106b53b
parent4d5a2955a1724d6b5ef95289704686d730bc7071 (diff)
downloadsamba-b3bb983f256e3a48dafea309800fac1a42648157.tar.gz
samba-b3bb983f256e3a48dafea309800fac1a42648157.tar.bz2
samba-b3bb983f256e3a48dafea309800fac1a42648157.zip
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 <metze@samba.org> Autobuild-Date: Wed Apr 6 19:55:50 CEST 2011 on sn-devel-104
-rw-r--r--source4/dsdb/samdb/ldb_modules/repl_meta_data.c128
1 files changed, 122 insertions, 6 deletions
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,