[SCM] Samba Shared Repository - branch master updated
Kamen Mazdrashki
kamenim at samba.org
Wed May 11 13:04:02 MDT 2011
The branch, master has been updated
via a8798d8 s4/drepl_fsmo: Add an CR so that message is visible in the logs
via d4481be s4/getnc_exop: Initial implementation of a testsuite for GetNCChanges extended opeartion handling
via 647827d s4/getncchanges: Pre-mark extended requests as success in case a sub-function "forget" to do this
via 55916e2 s4/getncchanges: Implement placeholder for handling ex-op collection of objects
via 88a9f79 s4/getncchanges: Move the code that collects objects into separate function
via 41496e7 s4/getncchanges: Don't mask Extended operation result - callers need it
via 232a8df s4/getncchanges: Fail extended request rather than failing whole request
from f99d6f0 s3-printing: make cups_pull_comment_location() work again.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit a8798d8bce9a191ccd6e0692c75e38ffadba1011
Author: Kamen Mazdrashki <kamenim at samba.org>
Date: Wed May 11 21:05:42 2011 +0300
s4/drepl_fsmo: Add an CR so that message is visible in the logs
Autobuild-User: Kamen Mazdrashki <kamenim at samba.org>
Autobuild-Date: Wed May 11 21:03:59 CEST 2011 on sn-devel-104
commit d4481be95c0c22ab8dd66edfdd82d1e9312b137d
Author: Kamen Mazdrashki <kamenim at samba.org>
Date: Wed May 11 21:04:54 2011 +0300
s4/getnc_exop: Initial implementation of a testsuite for GetNCChanges extended opeartion handling
commit 647827d09ccba7bcfa6454119afc22de96397128
Author: Kamen Mazdrashki <kamenim at samba.org>
Date: Wed May 11 21:09:34 2011 +0300
s4/getncchanges: Pre-mark extended requests as success in case a sub-function "forget" to do this
commit 55916e273f0853084f5bc2171eefc86af69e27dc
Author: Kamen Mazdrashki <kamenim at samba.org>
Date: Wed May 11 20:49:42 2011 +0300
s4/getncchanges: Implement placeholder for handling ex-op collection of objects
Right now it is solely based on function that handles objects
in normal DsGetNCChanges calls.
commit 88a9f793aa3cc7d7be073eef618fded87420f0d3
Author: Kamen Mazdrashki <kamenim at samba.org>
Date: Wed May 11 20:48:53 2011 +0300
s4/getncchanges: Move the code that collects objects into separate function
commit 41496e782df028a0fc8619aed6ca7a1173750677
Author: Kamen Mazdrashki <kamenim at samba.org>
Date: Mon May 9 20:11:22 2011 +0300
s4/getncchanges: Don't mask Extended operation result - callers need it
commit 232a8dfb060dcac27801b51b9576d76fb2f93655
Author: Kamen Mazdrashki <kamenim at samba.org>
Date: Mon May 9 20:09:49 2011 +0300
s4/getncchanges: Fail extended request rather than failing whole request
in case that destination_dsa_guid is not valid
-----------------------------------------------------------------------
Summary of changes:
source4/dsdb/repl/drepl_fsmo.c | 2 +-
source4/rpc_server/drsuapi/getncchanges.c | 168 ++++++++++++++++++++---------
source4/torture/drs/python/getnc_exop.py | 136 +++++++++++++++++++++++
3 files changed, 252 insertions(+), 54 deletions(-)
create mode 100644 source4/torture/drs/python/getnc_exop.py
Changeset truncated at 500 lines:
diff --git a/source4/dsdb/repl/drepl_fsmo.c b/source4/dsdb/repl/drepl_fsmo.c
index f8f4769..db63853 100644
--- a/source4/dsdb/repl/drepl_fsmo.c
+++ b/source4/dsdb/repl/drepl_fsmo.c
@@ -111,7 +111,7 @@ NTSTATUS drepl_take_FSMO_role(struct irpc_message *msg,
if (fsmo_master_equal(ntds_dn, role_owner_dn) ||
(extended_op == DRSUAPI_EXOP_NONE)) {
- DEBUG(0,("FSMO role check failed for DN %s and owner %s ",
+ DEBUG(0,("FSMO role check failed for DN %s and owner %s \n",
ldb_dn_get_linearized(fsmo_role_dn),
ldb_dn_get_linearized(role_owner_dn)));
r->out.result = WERR_OK;
diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c
index 8ae5368..0c196aa 100644
--- a/source4/rpc_server/drsuapi/getncchanges.c
+++ b/source4/rpc_server/drsuapi/getncchanges.c
@@ -993,12 +993,14 @@ static WERROR getncchanges_change_master(struct drsuapi_bind_state *b_state,
msg->dn = drs_ObjectIdentifier_to_dn(msg, ldb, req10->naming_context);
W_ERROR_HAVE_NO_MEMORY(msg->dn);
+ /* TODO: make sure ntds_dn is a valid nTDSDSA object */
ret = dsdb_find_dn_by_guid(ldb, msg, &req10->destination_dsa_guid, &ntds_dn);
if (ret != LDB_SUCCESS) {
DEBUG(0, (__location__ ": Unable to find NTDS object for guid %s - %s\n",
GUID_string(mem_ctx, &req10->destination_dsa_guid), ldb_errstring(ldb)));
talloc_free(msg);
- return WERR_DS_DRA_INTERNAL_ERROR;
+ ctr6->extended_ret = DRSUAPI_EXOP_ERR_UNKNOWN_CALLER;
+ return WERR_OK;
}
ret = ldb_msg_add_string(msg, "fSMORoleOwner", ldb_dn_get_linearized(ntds_dn));
@@ -1161,6 +1163,91 @@ getncchanges_map_req8(TALLOC_CTX *mem_ctx,
}
+/**
+ * Collects object for normal replication cycle.
+ */
+static WERROR getncchanges_collect_objects(struct drsuapi_bind_state *b_state,
+ TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsGetNCChangesRequest10 *req10,
+ struct ldb_dn *search_dn,
+ const char *extra_filter,
+ struct ldb_result **search_res)
+{
+ int ret;
+ char* search_filter;
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ //const char *extra_filter;
+ struct drsuapi_getncchanges_state *getnc_state = b_state->getncchanges_state;
+ const char *attrs[] = { "uSNChanged",
+ "objectGUID" ,
+ NULL };
+
+ if (req10->extended_op == DRSUAPI_EXOP_REPL_OBJ ||
+ req10->extended_op == DRSUAPI_EXOP_REPL_SECRET) {
+ scope = LDB_SCOPE_BASE;
+ }
+
+ //extra_filter = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "object filter");
+
+ //getnc_state->min_usn = req10->highwatermark.highest_usn;
+
+ /* Construct response. */
+ search_filter = talloc_asprintf(mem_ctx,
+ "(uSNChanged>=%llu)",
+ (unsigned long long)(getnc_state->min_usn+1));
+
+ if (extra_filter) {
+ search_filter = talloc_asprintf(mem_ctx, "(&%s(%s))", search_filter, extra_filter);
+ }
+
+ if (req10->replica_flags & DRSUAPI_DRS_CRITICAL_ONLY) {
+ search_filter = talloc_asprintf(mem_ctx,
+ "(&%s(isCriticalSystemObject=TRUE))",
+ search_filter);
+ }
+
+ if (req10->replica_flags & DRSUAPI_DRS_ASYNC_REP) {
+ scope = LDB_SCOPE_BASE;
+ }
+
+ if (!search_dn) {
+ search_dn = getnc_state->ncRoot_dn;
+ }
+
+ DEBUG(2,(__location__ ": getncchanges on %s using filter %s\n",
+ ldb_dn_get_linearized(getnc_state->ncRoot_dn), search_filter));
+ ret = drsuapi_search_with_extended_dn(b_state->sam_ctx, getnc_state, search_res,
+ search_dn, scope, attrs,
+ search_filter);
+ if (ret != LDB_SUCCESS) {
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+
+ return WERR_OK;
+}
+
+/**
+ * Collects object for normal replication cycle.
+ */
+static WERROR getncchanges_collect_objects_exop(struct drsuapi_bind_state *b_state,
+ TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsGetNCChangesRequest10 *req10,
+ struct drsuapi_DsGetNCChangesCtr6 *ctr6,
+ struct ldb_dn *search_dn,
+ const char *extra_filter,
+ struct ldb_result **search_res)
+{
+ /* we have nothing to do in case of ex-op failure */
+ if (ctr6->extended_ret != DRSUAPI_EXOP_ERR_SUCCESS) {
+ return WERR_OK;
+ }
+
+ /* TODO: implement extended op specific collection
+ * of objects. Right now we just normal procedure
+ * for collecting objects */
+ return getncchanges_collect_objects(b_state, mem_ctx, req10, search_dn, extra_filter, search_res);
+}
+
/*
drsuapi_DsGetNCChanges
@@ -1177,9 +1264,6 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_
struct drsuapi_DsReplicaObjectListItemEx **currentObject;
NTSTATUS status;
DATA_BLOB session_key;
- const char *attrs[] = { "uSNChanged",
- "objectGUID" ,
- NULL };
WERROR werr;
struct dcesrv_handle *h;
struct drsuapi_bind_state *b_state;
@@ -1327,6 +1411,10 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_
ldb_get_schema_basedn(b_state->sam_ctx));
getnc_state->is_schema_nc = (0 == ret);
+ if (req10->extended_op != DRSUAPI_EXOP_NONE) {
+ r->out.ctr->ctr6.extended_ret = DRSUAPI_EXOP_ERR_SUCCESS;
+ }
+
/*
* This is the first replication cycle and it is
* a good place to handle extended operations
@@ -1391,64 +1479,39 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_
Work out if this is the start of a new cycle */
if (getnc_state->guids == NULL) {
- char* search_filter;
- enum ldb_scope scope = LDB_SCOPE_SUBTREE;
const char *extra_filter;
- struct ldb_result *search_res;
-
- if (req10->extended_op == DRSUAPI_EXOP_REPL_OBJ ||
- req10->extended_op == DRSUAPI_EXOP_REPL_SECRET) {
- scope = LDB_SCOPE_BASE;
- }
+ struct ldb_result *search_res = NULL;
extra_filter = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "object filter");
getnc_state->min_usn = req10->highwatermark.highest_usn;
- /* Construct response. */
- search_filter = talloc_asprintf(mem_ctx,
- "(uSNChanged>=%llu)",
- (unsigned long long)(getnc_state->min_usn+1));
-
- if (extra_filter) {
- search_filter = talloc_asprintf(mem_ctx, "(&%s(%s))", search_filter, extra_filter);
- }
-
- if (req10->replica_flags & DRSUAPI_DRS_CRITICAL_ONLY) {
- search_filter = talloc_asprintf(mem_ctx,
- "(&%s(isCriticalSystemObject=TRUE))",
- search_filter);
- }
-
- if (req10->replica_flags & DRSUAPI_DRS_ASYNC_REP) {
- scope = LDB_SCOPE_BASE;
- }
-
- if (!search_dn) {
- search_dn = getnc_state->ncRoot_dn;
- }
-
- DEBUG(2,(__location__ ": getncchanges on %s using filter %s\n",
- ldb_dn_get_linearized(getnc_state->ncRoot_dn), search_filter));
- ret = drsuapi_search_with_extended_dn(sam_ctx, getnc_state, &search_res,
- search_dn, scope, attrs,
- search_filter);
- if (ret != LDB_SUCCESS) {
- return WERR_DS_DRA_INTERNAL_ERROR;
- }
-
- if (req10->replica_flags & DRSUAPI_DRS_GET_ANC) {
- TYPESAFE_QSORT(search_res->msgs,
- search_res->count,
- site_res_cmp_parent_order);
+ if (req10->extended_op == DRSUAPI_EXOP_NONE) {
+ werr = getncchanges_collect_objects(b_state, mem_ctx, req10,
+ search_dn, extra_filter,
+ &search_res);
} else {
- TYPESAFE_QSORT(search_res->msgs,
- search_res->count,
- site_res_cmp_usn_order);
+ werr = getncchanges_collect_objects_exop(b_state, mem_ctx, req10,
+ &r->out.ctr->ctr6,
+ search_dn, extra_filter,
+ &search_res);
+ }
+ 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->count;
+ 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);
@@ -1705,7 +1768,6 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_
r->out.ctr->ctr6.uptodateness_vector = NULL;
r->out.ctr->ctr6.nc_object_count = 0;
ZERO_STRUCT(r->out.ctr->ctr6.new_highwatermark);
- r->out.ctr->ctr6.extended_ret = DRSUAPI_EXOP_ERR_SUCCESS;
}
DEBUG(r->out.ctr->ctr6.more_data?4:2,
diff --git a/source4/torture/drs/python/getnc_exop.py b/source4/torture/drs/python/getnc_exop.py
new file mode 100644
index 0000000..3aeb7e0
--- /dev/null
+++ b/source4/torture/drs/python/getnc_exop.py
@@ -0,0 +1,136 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Tests various schema replication scenarios
+#
+# Copyright (C) Kamen Mazdrashki <kamenim at samba.org> 2011
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+#
+# Usage:
+# export DC1=dc1_dns_name
+# export DC2=dc2_dns_name
+# export SUBUNITRUN=$samba4srcdir/scripting/bin/subunitrun
+# PYTHONPATH="$PYTHONPATH:$samba4srcdir/torture/drs/python" $SUBUNITRUN getnc_exop -U"$DOMAIN/$DC_USERNAME"%"$DC_PASSWORD"
+#
+
+import drs_base
+import samba.tests
+
+from ldb import SCOPE_BASE
+
+from samba.dcerpc import drsuapi, misc, drsblobs
+from samba.drs_utils import drs_DsBind
+
+
+class DrsReplicaSyncTestCase(drs_base.DrsBaseTestCase):
+ """Intended as a semi-black box test case for DsGetNCChanges
+ implementation for extended operations. It should be testing
+ how DsGetNCChanges handles different input params (mostly invalid).
+ Final goal is to make DsGetNCChanges as binary compatible to
+ Windows implementation as possible"""
+
+ def setUp(self):
+ super(DrsReplicaSyncTestCase, self).setUp()
+
+ def tearDown(self):
+ super(DrsReplicaSyncTestCase, self).tearDown()
+
+ def _exop_req8(self, dest_dsa, invocation_id, nc_dn_str, exop):
+ req8 = drsuapi.DsGetNCChangesRequest8()
+
+ req8.destination_dsa_guid = misc.GUID(dest_dsa)
+ req8.source_dsa_invocation_id = misc.GUID(invocation_id)
+ req8.naming_context = drsuapi.DsReplicaObjectIdentifier()
+ req8.naming_context.dn = unicode(nc_dn_str)
+ req8.highwatermark = drsuapi.DsReplicaHighWaterMark()
+ req8.highwatermark.tmp_highest_usn = 0
+ req8.highwatermark.reserved_usn = 0
+ req8.highwatermark.highest_usn = 0
+ req8.uptodateness_vector = None
+ req8.replica_flags = 0
+ req8.max_object_count = 0
+ req8.max_ndr_size = 402116
+ req8.extended_op = exop
+ req8.fsmo_info = 0
+ req8.partial_attribute_set = None
+ req8.partial_attribute_set_ex = None
+ req8.mapping_ctr.num_mappings = 0
+ req8.mapping_ctr.mappings = None
+
+ return req8
+
+ def _ds_bind(self, server_name):
+ binding_str = "ncacn_ip_tcp:%s[print,seal]" % server_name
+
+ drs = drsuapi.drsuapi(binding_str, self.get_loadparm(), self.get_credentials())
+ (drs_handle, supported_extensions) = drs_DsBind(drs)
+ return (drs, drs_handle)
+
+ def _determine_fSMORoleOwner(self, fsmo_obj_dn):
+ """Returns (owner, not_owner) pair where:
+ owner: dns name for FSMO owner
+ not_owner: dns name for DC not owning the FSMO"""
+ res = self.ldb_dc1.search(fsmo_obj_dn,
+ scope=SCOPE_BASE, attrs=["fSMORoleOwner"])
+ assert len(res) == 1, "Only one fSMORoleOwner value expected for %s!"%fsmo_obj_dn
+ fsmo_owner = res[0]["fSMORoleOwner"][0]
+ if fsmo_owner == self.info_dc1["dsServiceName"][0]:
+ return (self.dnsname_dc1, self.dnsname_dc2)
+ return (self.dnsname_dc2, self.dnsname_dc1)
+
+ def _check_exop_failed(self, ctr6, expected_failure):
+ c = drsuapi.DsGetNCChangesCtr6()
+ self.assertEqual(ctr6.extended_ret, expected_failure)
+ self.assertEqual(ctr6.object_count, 0)
+ self.assertEqual(ctr6.first_object, None)
+ self.aserrtEqual(ctr6.more_data, False)
+ self.assertEqual(ctr6.nc_object_count, 0)
+ self.assertEqual(ctr6.nc_linked_attributes_count, 0)
+ self.assertEqual(ctr6.linked_attributes_count, 0)
+ self.assertEqual(ctr6.linked_attributes, None)
+ self.assertEqual(ctr6.drs_error, 0)
+
+ def test_FSMONotOwner(self):
+ """Test role transfer with against DC not owner of the role"""
+ fsmo_dn = self.ldb_dc1.get_schema_basedn()
+ (fsmo_owner_dc, fsmo_not_owner_dc) = self._determine_fSMORoleOwner(fsmo_dn)
+
+ req8 = self._exop_req8(dest_dsa="9c637462-5b8c-4467-aef2-bdb1f57bc4ef",
+ invocation_id=self.ldb_dc1.get_invocation_id(),
+ nc_dn_str=fsmo_dn,
+ exop=drsuapi.DRSUAPI_EXOP_FSMO_REQ_ROLE)
+
+ (drs, drs_handle) = self._ds_bind(fsmo_not_owner_dc)
+ (level, ctr) = drs.DsGetNCChanges(drs_handle, 8, req8)
+ self.assertEqual(level, 6, "Expected level 6 response!")
+ self._check_exop_failed(ctr, drsuapi.DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER)
+
+ def test_InvalidDestDSA(self):
+ """Test role transfer with invalid destination DSA guid"""
+ fsmo_dn = self.ldb_dc1.get_schema_basedn()
+ (fsmo_owner_dc, fsmo_not_owner_dc) = self._determine_fSMORoleOwner(fsmo_dn)
+
+ req8 = self._exop_req8(dest_dsa="9c637462-5b8c-4467-aef2-bdb1f57bc4ef",
+ invocation_id=self.ldb_dc1.get_invocation_id(),
+ nc_dn_str=self.ldb_dc1.get_schema_basedn(),
+ exop=drsuapi.DRSUAPI_EXOP_FSMO_REQ_ROLE)
+
+ (drs, drs_handle) = self._ds_bind(fsmo_owner_dc)
+ (level, ctr) = drs.DsGetNCChanges(drs_handle, 8, req8)
+ self.assertEqual(level, 6, "Expected level 6 response!")
+ #ctr = drsuapi.DsGetNCChangesCtr6()
+ self._check_exop_failed(ctr, drsuapi.DRSUAPI_EXOP_ERR_UNKNOWN_CALLER)
--
Samba Shared Repository
More information about the samba-cvs
mailing list