The branch, master has been updated via 576ea40 samba-tool: allow dbcheck to correct the originating_change_time of the deleted object container via 85af1ed s4-dsdb: initialize correctly the value of originating_change_time for the Deleted Object Container via b8a0772 s4-drs: check if we have a domain level >= 2k8r2 as before the isRecycled do not exists and so is always False via a6686b9 samba-tool: dbcheck avoid problems with deleted objects from 691fb36 s4: Simple test script to create lots of contacts to stress the LDB
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 576ea40ece6adb156b4de23c737ada5e80b7946a Author: Matthieu Patou <m...@matws.net> Date: Sun Nov 13 14:09:24 2011 +0100 samba-tool: allow dbcheck to correct the originating_change_time of the deleted object container Autobuild-User: Matthieu Patou <m...@samba.org> Autobuild-Date: Sun Nov 13 15:47:53 CET 2011 on sn-devel-104 commit 85af1ed9b8e5593b91fd5efb5e97c5abbc9feddc Author: Matthieu Patou <m...@matws.net> Date: Sun Nov 13 14:08:32 2011 +0100 s4-dsdb: initialize correctly the value of originating_change_time for the Deleted Object Container commit b8a077296ac666cf45cafe7e86edc390dce0e511 Author: Matthieu Patou <m...@matws.net> Date: Wed Oct 5 16:23:37 2011 +0200 s4-drs: check if we have a domain level >= 2k8r2 as before the isRecycled do not exists and so is always False Having a false value cause the link on removed attribute to be always returned which is what we try to avoid. commit a6686b9f9893c67534c7eec73a6c301f1ebe41da Author: Matthieu Patou <m...@matws.net> Date: Sun Nov 13 13:15:47 2011 +0100 samba-tool: dbcheck avoid problems with deleted objects We have to search for deleted objects as well as the previous search might have been done with the show_deleted control. If not samba-tool fails with no such DN error while fetching the object. ----------------------------------------------------------------------- Summary of changes: source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 54 ++++++++++++++++++++++- source4/rpc_server/drsuapi/getncchanges.c | 31 ++++++++++--- source4/scripting/python/samba/dbchecker.py | 36 +++++++++++++++- 3 files changed, 111 insertions(+), 10 deletions(-) Changeset truncated at 500 lines: diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index 194498e..b7a6a70 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -50,6 +50,7 @@ #include "lib/util/binsearch.h" #include "lib/util/tsort.h" +static const uint64_t DELETED_OBJECT_CONTAINER_CHANGE_TIME = 253402127999L; struct replmd_private { TALLOC_CTX *la_ctx; struct la_entry *la_list; @@ -917,7 +918,32 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req) m->attid = sa->attributeID_id; m->version = 1; - m->originating_change_time = now; + if (m->attid == 0x20030) { + const struct ldb_val *rdn_val = ldb_dn_get_rdn_val(msg->dn); + const char* rdn; + + if (rdn_val == NULL) { + ldb_oom(ldb); + talloc_free(ac); + return LDB_ERR_OPERATIONS_ERROR; + } + + rdn = (const char*)rdn_val->data; + if (strcmp(rdn, "Deleted Objects") == 0) { + /* + * Set the originating_change_time to 29/12/9999 at 23:59:59 + * as specified in MS-ADTS 7.1.1.4.2 Deleted Objects Container + */ + NTTIME deleted_obj_ts; + + unix_to_nt_time(&deleted_obj_ts, DELETED_OBJECT_CONTAINER_CHANGE_TIME); + m->originating_change_time = deleted_obj_ts; + } else { + m->originating_change_time = now; + } + } else { + m->originating_change_time = now; + } m->originating_invocation_id = *our_invocation_id; m->originating_usn = ac->seq_num; m->local_usn = ac->seq_num; @@ -1118,7 +1144,31 @@ static int replmd_update_rpmd_element(struct ldb_context *ldb, md1 = &omd->ctr.ctr1.array[i]; md1->version++; md1->attid = a->attributeID_id; - md1->originating_change_time = now; + if (md1->attid == 0x20030) { + const struct ldb_val *rdn_val = ldb_dn_get_rdn_val(msg->dn); + const char* rdn; + + if (rdn_val == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + rdn = (const char*)rdn_val->data; + if (strcmp(rdn, "Deleted Objects") == 0) { + /* + * Set the originating_change_time to 29/12/9999 at 23:59:59 + * as specified in MS-ADTS 7.1.1.4.2 Deleted Objects Container + */ + NTTIME deleted_obj_ts; + + unix_to_nt_time(&deleted_obj_ts, DELETED_OBJECT_CONTAINER_CHANGE_TIME); + md1->originating_change_time = deleted_obj_ts; + } else { + md1->originating_change_time = now; + } + } else { + md1->originating_change_time = now; + } md1->originating_invocation_id = *our_invocation_id; md1->originating_usn = *seq_num; md1->local_usn = *seq_num; diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 61a6002..4217e22 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -366,14 +366,31 @@ static WERROR get_nc_changes_add_la(TALLOC_CTX *mem_ctx, v = ldb_msg_find_attr_as_string(msg, "isDeleted", "false"); if (strncasecmp(v, "true", 4) == 0) { - v = ldb_msg_find_attr_as_string(msg, "isRecycled", "false"); /* - * Do not skip link when the object is just deleted (isRecycled not present) - * Do it for tomstones or recycled ones - */ - if (strncasecmp(v, "true", 4) == 0) { - DEBUG(2, (" object %s is deleted, not returning linked attribute !\n", - ldb_dn_get_linearized(msg->dn))); + * Note: we skip the transmition of the deleted link even if the other part used to + * know about it because when we transmit the deletion of the object, the link will + * be deleted too due to deletion of object where link points and Windows do so. + */ + if (dsdb_functional_level(sam_ctx) >= DS_DOMAIN_FUNCTION_2008_R2) { + v = ldb_msg_find_attr_as_string(msg, "isRecycled", "true"); + /* + * On Windows 2008R2 isRecycled is always present even if FL or DL are < FL 2K8R2 + * if it join an existing domain with deleted objets, it firsts impose to have a + * schema with the is-Recycled object and for all deleted objects it adds the isRecycled + * either during initial replication or after the getNCChanges. + * Behavior of samba has been changed to always have this attribute if it's present in the schema. + * + * So if FL <2K8R2 isRecycled might be here or not but we don't care, it's meaning less. + * If FL >=2K8R2 we are sure that this attribute will be here. + * For this kind of forest level we do not return the link if the object is recycled + * (isRecycled = true). + */ + if (strncasecmp(v, "true", 4) == 0) { + DEBUG(2, (" object %s is recycled, not returning linked attribute !\n", + ldb_dn_get_linearized(msg->dn))); + return WERR_OK; + } + } else { return WERR_OK; } } diff --git a/source4/scripting/python/samba/dbchecker.py b/source4/scripting/python/samba/dbchecker.py index 7d85adf..6792538 100644 --- a/source4/scripting/python/samba/dbchecker.py +++ b/source4/scripting/python/samba/dbchecker.py @@ -45,6 +45,7 @@ class dbcheck(object): self.remove_all_deleted_DN_links = False self.fix_all_target_mismatch = False self.fix_all_metadata = False + self.fix_time_metadata = False self.fix_all_missing_backlinks = False self.fix_all_orphaned_backlinks = False @@ -368,6 +369,22 @@ class dbcheck(object): return error_count + def get_originating_time(self, val, attid): + '''Read metadata properties and return the originating time for + a given attributeId. + + :return: the originating time or 0 if not found + ''' + + repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, str(val)) + obj = repl.ctr + + for o in repl.ctr.array: + if o.attid == attid: + return o.originating_change_time + + return 0 + def process_metadata(self, val): '''Read metadata properties and list attributes in it''' @@ -407,7 +424,7 @@ class dbcheck(object): attrs.append("replPropertyMetaData") res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE, - controls=["extended_dn:1:1", "show_recycled:1"], + controls=["extended_dn:1:1", "show_recycled:1", "show_deleted:1"], attrs=attrs) if len(res) != 1: self.report("Object %s disappeared during check" % dn) @@ -465,6 +482,23 @@ class dbcheck(object): show_dn = True if got_repl_property_meta_data: + rdn = (str(dn).split(","))[0] + if rdn == "CN=Deleted Objects": + isDeletedAttId = 131120 + # It's 29/12/9999 at 23:59:59 UTC as specified in MS-ADTS 7.1.1.4.2 Deleted Objects Container + + expectedTimeDo = 2650466015990000000 + originating = self.get_originating_time(obj["replPropertyMetaData"], isDeletedAttId) + if originating != expectedTimeDo: + if self.confirm_all("Fix isDeleted originating_change_time on '%s'" % str(dn), 'fix_time_metadata'): + nmsg = ldb.Message() + nmsg.dn = dn + nmsg["isDeleted"] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_REPLACE, "isDeleted") + error_count += 1 + self.samdb.modify(nmsg, controls=["provision:0"]) + + else: + self.report("Not fixing isDeleted originating_change_time on '%s'" % str(dn)) for att in list_attrs_seen: if not att in list_attrs_from_md: if show_dn: -- Samba Shared Repository