[SCM] Samba Shared Repository - branch master updated

Matthieu Patou mat at samba.org
Mon Dec 19 06:33:02 MST 2011


The branch, master has been updated
       via  f39426c s4-dsdb: Relax the conditions where we can't do a subtree delete
       via  b2bace6 s4:drsuapi/getncchanges: return WERR_NOMEM if talloc_array() fails
       via  3164d7b s4-drs: introduce a timeout in the getncchanges processing to always return something in less than x seconds
       via  55af1a7 s4-drs: avoid calling unecesserly ldb_msg_find_attr_as_* as this call in unefficient
       via  e34fe4d s4-becomedc: replicate first with DRS_CRITICAL_ONLY and DRS_GET_ANC objects for the base dn partition
       via  f6435b7 s4-join: replicate first with DRS_CRITICAL_ONLY and DRS_GET_ANC objects for the base dn partition
      from  b644945 tdb: be more careful on 4G files.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit f39426c8ae6dc6a64acbdbe6087f0f0c359a4a96
Author: Matthieu Patou <mat at matws.net>
Date:   Tue Nov 15 11:32:33 2011 +0100

    s4-dsdb: Relax the conditions where we can't do a subtree delete
    
    If the parent object is a SAM object (as defined in 3.1.1.5.2.3
    Special Classes and Attributes of MS-ADTS) then we can use the subtree
    delete control even if the object is a critical one.
    
    Autobuild-User: Matthieu Patou <mat at samba.org>
    Autobuild-Date: Mon Dec 19 14:32:19 CET 2011 on sn-devel-104

commit b2bace63d38690a32abcf2f82059dba6c1148d44
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Nov 15 11:47:42 2011 +0100

    s4:drsuapi/getncchanges: return WERR_NOMEM if talloc_array() fails
    
    metze

commit 3164d7bdd5e329ad15711d04da4813df7a39a547
Author: Matthieu Patou <mat at matws.net>
Date:   Thu Nov 10 11:23:40 2011 +0100

    s4-drs: introduce a timeout in the getncchanges processing to always return something in less than x seconds
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

commit 55af1a7cf78c2a04ec82dc5a3bdcaedd846dd3fc
Author: Matthieu Patou <mat at matws.net>
Date:   Mon Nov 14 18:53:30 2011 +0100

    s4-drs: avoid calling unecesserly ldb_msg_find_attr_as_* as this call in unefficient
    
    Current implementation of ldb_msg_find_attr_as_* iterate on the list of
    attributes returned by the search and make a string comparison. As we
    sorting the array of messages / guids we tend to call this function many
    times. By storing the GUID and the USN in a separate structure we are
    sure to call this function only once per attribute and object.
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit e34fe4dcb60d2fbf7d805fc348d3a25d2d8950b7
Author: Matthieu Patou <mat at matws.net>
Date:   Sat Nov 5 00:22:47 2011 +0100

    s4-becomedc: replicate first with DRS_CRITICAL_ONLY and DRS_GET_ANC objects for the base dn partition
    
    Windows dcpromo do the same: getncchanges with DRS_GET_ANC and
    DRS_CRITICAL_ONLY, then it does a getncchanges without those flags for
    the rest.
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

commit f6435b734ab50b623350b107d014095c49e48e20
Author: Matthieu Patou <mat at matws.net>
Date:   Tue Oct 25 20:13:00 2011 +0200

    s4-join: replicate first with DRS_CRITICAL_ONLY and DRS_GET_ANC objects for the base dn partition
    
    Windows dcpromo do the same: getncchanges with DRS_GET_ANC and
    DRS_CRITICAL_ONLY, then it does a getncchanges without those flags for
    the rest.
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source4/dsdb/samdb/ldb_modules/objectclass.c |   20 +++++-
 source4/libnet/libnet_become_dc.c            |   13 +++
 source4/rpc_server/drsuapi/getncchanges.c    |  107 ++++++++++++++++++--------
 source4/scripting/python/samba/join.py       |   10 +++
 4 files changed, 117 insertions(+), 33 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c
index 89dd6ef..6f239d2 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass.c
@@ -1549,10 +1549,28 @@ static int objectclass_do_delete(struct oc_context *ac)
 		isCriticalSystemObject = ldb_msg_find_attr_as_bool(ac->search_res->message,
 								   "isCriticalSystemObject", false);
 		if (isCriticalSystemObject) {
-			ldb_asprintf_errstring(ldb,
+			/*
+			 * Following the explaination from Microsoft
+			 * https://lists.samba.org/archive/cifs-protocol/2011-August/002046.html
+			 * "I finished the investigation on this behavior.
+			 * As per MS-ADTS 3.1.5.5.7.2 , when a tree deletion is performed ,
+			 * every object in the tree will be checked to see if it has isCriticalSystemObject
+			 * set to TRUE, including the root node on which the delete operation is performed
+			 * But there is an exception  if the root object is a SAM specific objects(3.1.1.5.2.3 MS-ADTS)
+			 * Its deletion is done through SAM manger and isCriticalSystemObject attribute is not checked
+			 * The root node of the tree delete in your case is CN=ARES,OU=Domain Controllers,DC=w2k8r2,DC=home,DC=matws,DC=net
+			 * which is a SAM object  with  user class.  Therefore the tree deletion is performed without any error
+			 */
+
+			if (samdb_find_attribute(ldb, ac->search_res->message, "objectClass", "group") == NULL &&
+			    samdb_find_attribute(ldb, ac->search_res->message, "objectClass", "samDomain") == NULL &&
+			    samdb_find_attribute(ldb, ac->search_res->message, "objectClass", "samServer") == NULL &&
+			    samdb_find_attribute(ldb, ac->search_res->message, "objectClass", "user") == NULL) {
+					ldb_asprintf_errstring(ldb,
 					       "objectclass: Cannot tree-delete %s, it's a critical system object!",
 					       ldb_dn_get_linearized(ac->req->op.del.dn));
 			return LDB_ERR_UNWILLING_TO_PERFORM;
+			}
 		}
 	}
 
diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c
index f0f57d6..c7d0b30 100644
--- a/source4/libnet/libnet_become_dc.c
+++ b/source4/libnet/libnet_become_dc.c
@@ -735,6 +735,7 @@ struct libnet_BecomeDC_state {
 	struct libnet_BecomeDC_Callbacks callbacks;
 
 	bool rodc_join;
+	bool critical_only;
 };
 
 static int32_t get_dc_function_level(struct loadparm_context *lp_ctx)
@@ -2867,6 +2868,9 @@ static void becomeDC_drsuapi3_pull_domain_send(struct libnet_BecomeDC_state *s)
 					| DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS
 					| DRSUAPI_DRS_NEVER_SYNCED
 					| DRSUAPI_DRS_USE_COMPRESSION;
+	if (s->critical_only) {
+		s->domain_part.replica_flags |= DRSUAPI_DRS_CRITICAL_ONLY | DRSUAPI_DRS_GET_ANC;
+	}
 	if (s->rodc_join) {
 	    s->schema_part.replica_flags &= ~DRSUAPI_DRS_WRIT_REP;
 	}
@@ -2912,6 +2916,14 @@ static void becomeDC_drsuapi3_pull_domain_recv(struct tevent_req *subreq)
 		return;
 	}
 
+	if (s->critical_only) {
+		/* Remove the critical and ANC */
+		s->domain_part.replica_flags ^= DRSUAPI_DRS_CRITICAL_ONLY | DRSUAPI_DRS_GET_ANC;
+		s->critical_only = false;
+		becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->domain_part,
+						     becomeDC_drsuapi3_pull_domain_recv);
+		return;
+	}
 	becomeDC_drsuapi_update_refs_send(s, &s->drsuapi2, &s->schema_part,
 					  becomeDC_drsuapi2_update_refs_schema_recv);
 }
@@ -3135,6 +3147,7 @@ static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s)
 	c->status = becomeDC_ldap2_move_computer(s);
 	if (!composite_is_ok(c)) return;
 
+	s->critical_only = true;
 	becomeDC_drsuapi3_pull_domain_send(s);
 }
 
diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c
index 4217e22..f6e4573 100644
--- a/source4/rpc_server/drsuapi/getncchanges.c
+++ b/source4/rpc_server/drsuapi/getncchanges.c
@@ -119,7 +119,8 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem
 					  uint32_t replica_flags,
 					  struct drsuapi_DsPartialAttributeSet *partial_attribute_set,
 					  struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector,
-					  enum drsuapi_DsExtendedOperation extended_op)
+					  enum drsuapi_DsExtendedOperation extended_op,
+					  bool force_object_return)
 {
 	const struct ldb_val *md_value;
 	uint32_t i, n;
@@ -260,9 +261,17 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem
 
 	/* ignore it if its an empty change. Note that renames always
 	 * change the 'name' attribute, so they won't be ignored by
-	 * this */
+	 * this
+
+	 * the force_object_return check is used to force an empty
+	 * object return when we timeout in the getncchanges loop.
+	 * This allows us to return an empty object, which keeps the
+	 * client happy while preventing timeouts
+	 */
 	if (n == 0 ||
-	    (n == 1 && attids[0] == DRSUAPI_ATTID_instanceType)) {
+	    (n == 1 &&
+	     attids[0] == DRSUAPI_ATTID_instanceType &&
+	     !force_object_return)) {
 		talloc_free(obj->meta_data_ctr);
 		obj->meta_data_ctr = NULL;
 		return WERR_OK;
@@ -274,6 +283,9 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem
 	obj->object.attribute_ctr.num_attributes = obj->meta_data_ctr->count;
 	obj->object.attribute_ctr.attributes = talloc_array(obj, struct drsuapi_DsReplicaAttribute,
 							    obj->object.attribute_ctr.num_attributes);
+	if (obj->object.attribute_ctr.attributes == NULL) {
+		return WERR_NOMEM;
+	}
 
 	/*
 	 * Note that the meta_data array and the attributes array must
@@ -328,7 +340,6 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem
 	return WERR_OK;
 }
 
-
 /*
   add one linked attribute from an object to the list of linked
   attributes in a getncchanges request
@@ -627,29 +638,37 @@ static int linked_attribute_compare(const struct drsuapi_DsReplicaLinkedAttribut
 	return GUID_compare(&guid1, &guid2);
 }
 
+struct drsuapi_changed_objects {
+	struct ldb_dn *dn;
+	struct GUID guid;
+	uint64_t usn;
+};
 
 /*
   sort the objects we send by tree order
  */
-static int site_res_cmp_parent_order(struct ldb_message **m1, struct ldb_message **m2)
+static int site_res_cmp_parent_order(struct drsuapi_changed_objects *m1,
+					struct drsuapi_changed_objects *m2)
 {
-	return ldb_dn_compare((*m2)->dn, (*m1)->dn);
+	return ldb_dn_compare(m2->dn, m1->dn);
 }
 
 /*
   sort the objects we send first by uSNChanged
  */
-static int site_res_cmp_usn_order(struct ldb_message **m1, struct ldb_message **m2)
+static int site_res_cmp_dn_usn_order(struct drsuapi_changed_objects *m1,
+					struct drsuapi_changed_objects *m2)
 {
 	unsigned usnchanged1, usnchanged2;
 	unsigned cn1, cn2;
-	cn1 = ldb_dn_get_comp_num((*m1)->dn);
-	cn2 = ldb_dn_get_comp_num((*m2)->dn);
+
+	cn1 = ldb_dn_get_comp_num(m1->dn);
+	cn2 = ldb_dn_get_comp_num(m2->dn);
 	if (cn1 != cn2) {
 		return cn1 > cn2 ? 1 : -1;
 	}
-	usnchanged1 = ldb_msg_find_attr_as_uint(*m1, "uSNChanged", 0);
-	usnchanged2 = ldb_msg_find_attr_as_uint(*m2, "uSNChanged", 0);
+	usnchanged1 = m1->usn;
+	usnchanged2 = m2->usn;
 	if (usnchanged1 == usnchanged2) {
 		return 0;
 	}
@@ -1417,6 +1436,10 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_
 	struct dom_sid *user_sid;
 	bool is_secret_request;
 	bool is_gc_pas_request;
+	struct drsuapi_changed_objects *changes;
+	time_t max_wait;
+	time_t start = time(NULL);
+	bool max_wait_reached = false;
 
 	DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
 	b_state = h->data;
@@ -1653,33 +1676,31 @@ allowed:
 		}
 		W_ERROR_NOT_OK_RETURN(werr);
 
-		if (search_res) {
-			if (req10->replica_flags & DRSUAPI_DRS_GET_ANC) {
-				TYPESAFE_QSORT(search_res->msgs,
-					       search_res->count,
-					       site_res_cmp_parent_order);
-			} else {
-				TYPESAFE_QSORT(search_res->msgs,
-					       search_res->count,
-					       site_res_cmp_usn_order);
-			}
-		}
-
 		/* extract out the GUIDs list */
 		getnc_state->num_records = search_res ? search_res->count : 0;
 		getnc_state->guids = talloc_array(getnc_state, struct GUID, getnc_state->num_records);
 		W_ERROR_HAVE_NO_MEMORY(getnc_state->guids);
 
+		changes = talloc_array(getnc_state,
+				       struct drsuapi_changed_objects,
+				       getnc_state->num_records);
+		W_ERROR_HAVE_NO_MEMORY(changes);
+
 		for (i=0; i<getnc_state->num_records; i++) {
-			getnc_state->guids[i] = samdb_result_guid(search_res->msgs[i], "objectGUID");
-			if (GUID_all_zero(&getnc_state->guids[i])) {
-				DEBUG(2,("getncchanges: bad objectGUID from %s\n", ldb_dn_get_linearized(search_res->msgs[i]->dn)));
-				return WERR_DS_DRA_INTERNAL_ERROR;
-			}
+			changes[i].dn = search_res->msgs[i]->dn;
+			changes[i].guid = samdb_result_guid(search_res->msgs[i], "objectGUID");
+			changes[i].usn = ldb_msg_find_attr_as_uint64(search_res->msgs[i], "uSNChanged", 0);
 		}
 
-
-		talloc_free(search_res);
+		if (req10->replica_flags & DRSUAPI_DRS_GET_ANC) {
+			TYPESAFE_QSORT(changes,
+				       getnc_state->num_records,
+				       site_res_cmp_parent_order);
+		} else {
+			TYPESAFE_QSORT(changes,
+				       getnc_state->num_records,
+				       site_res_cmp_dn_usn_order);
+		}
 
 		getnc_state->uptodateness_vector = talloc_steal(getnc_state, req10->uptodateness_vector);
 		if (getnc_state->uptodateness_vector) {
@@ -1688,6 +1709,18 @@ allowed:
 				       getnc_state->uptodateness_vector->count,
 				       drsuapi_DsReplicaCursor_compare);
 		}
+
+		for (i=0; i < getnc_state->num_records; i++) {
+			getnc_state->guids[i] = changes[i].guid;
+			if (GUID_all_zero(&getnc_state->guids[i])) {
+				DEBUG(2,("getncchanges: bad objectGUID from %s\n",
+					 ldb_dn_get_linearized(search_res->msgs[i]->dn)));
+				return WERR_DS_DRA_INTERNAL_ERROR;
+			}
+		}
+
+		talloc_free(search_res);
+		talloc_free(changes);
 	}
 
 	/* Prefix mapping */
@@ -1734,10 +1767,17 @@ allowed:
 	 */
 	max_links = lpcfg_parm_int(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "max link sync", 1500);
 
+	/*
+	 * Maximum time that we can spend in a getncchanges
+	 * in order to avoid timeout of the other part.
+	 * 10 seconds by default.
+	 */
+	max_wait = lpcfg_parm_int(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "max work time", 10);
 	for (i=getnc_state->num_processed;
 	     i<getnc_state->num_records &&
 		     !null_scope &&
-		     (r->out.ctr->ctr6.object_count < max_objects);
+		     (r->out.ctr->ctr6.object_count < max_objects)
+		     && !max_wait_reached;
 	    i++) {
 		int uSN;
 		struct drsuapi_DsReplicaObjectListItemEx *obj;
@@ -1776,6 +1816,8 @@ allowed:
 
 		msg = msg_res->msgs[0];
 
+		max_wait_reached = (time(NULL) - start > max_wait);
+
 		werr = get_nc_changes_build_object(obj, msg,
 						   sam_ctx, getnc_state->ncRoot_dn,
 						   getnc_state->is_schema_nc,
@@ -1783,7 +1825,8 @@ allowed:
 						   req10->replica_flags,
 						   req10->partial_attribute_set,
 						   getnc_state->uptodateness_vector,
-						   req10->extended_op);
+						   req10->extended_op,
+						   max_wait_reached);
 		if (!W_ERROR_IS_OK(werr)) {
 			return werr;
 		}
diff --git a/source4/scripting/python/samba/join.py b/source4/scripting/python/samba/join.py
index 3e3d217..818e0ce 100644
--- a/source4/scripting/python/samba/join.py
+++ b/source4/scripting/python/samba/join.py
@@ -658,6 +658,16 @@ class dc_join(object):
                     destination_dsa_guid, rodc=ctx.RODC,
                     replica_flags=ctx.replica_flags)
             if not ctx.subdomain:
+                # Replicate first the critical object for the basedn
+                if not ctx.domain_replica_flags & drsuapi.DRSUAPI_DRS_CRITICAL_ONLY:
+                    print "Replicating critical objects from the base DN of the domain"
+                    ctx.domain_replica_flags |= drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC
+                    repl.replicate(ctx.base_dn, source_dsa_invocation_id,
+                                destination_dsa_guid, rodc=ctx.RODC,
+                                replica_flags=ctx.domain_replica_flags)
+                    ctx.domain_replica_flags ^= drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC
+                else:
+                    ctx.domain_replica_flags |= drsuapi.DRSUAPI_DRS_GET_ANC
                 repl.replicate(ctx.base_dn, source_dsa_invocation_id,
                                destination_dsa_guid, rodc=ctx.RODC,
                                replica_flags=ctx.domain_replica_flags)


-- 
Samba Shared Repository


More information about the samba-cvs mailing list