[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