diff options
author | Stefan Metzmacher <metze@samba.org> | 2011-04-06 14:02:08 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2011-04-06 19:55:49 +0200 |
commit | b3bb983f256e3a48dafea309800fac1a42648157 (patch) | |
tree | eda38ec77625f5900ffb3ad4ca3144082106b53b | |
parent | 4d5a2955a1724d6b5ef95289704686d730bc7071 (diff) | |
download | samba-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.c | 128 |
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, |