[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Wed Nov 21 00:51:03 UTC 2018


The branch, master has been updated
       via  ad57cac7db0 source4 samr: Tidy DBG_WARNING calls
       via  1719f8b9cd9 s4-samr: Use GUID_buf_string() in dcesrv_samr_EnumDomainUsers()
       via  53c20e1096d s4-samr: Use dom_sid_split_rid() to get the RID in dcesrv_samr_EnumDomainUsers
       via  64007aa3825 source4 samr: cache samr_EnumDomainUsers results
       via  fa3ea1cfc18 tests samr: Extra tests for samr_EnumDomainUserss
       via  8d8303b0aec s4-samr: Use GUID_buf_string() in dcesrv_samr_EnumDomainGroups()
       via  b6241852937 s4-samr: Use dom_sid_split_rid() to get the RID in dcesrv_samr_EnumDomainGroups
       via  564813b5883 source4 samr: cache samr_EnumDomainGroups results
       via  7dd7800a88e test samr: Extra tests for samr_EnumDomainGroups
       via  fc1a16ff61a s4-samr: Use dom_sid_split_rid() to get the RID in dcesrv_samr_QueryDisplayInfo
       via  10efdac356d source4 samr: cache samr_QueryDisplayInfo results
       via  d9f7b6d63f9 tests samr: remove PEP8 warnings
       via  9a1277c1ecd tests samr: Extra tests for samr_QueryDisplayInfo
       via  ad8bb6fcd08 ldb_controls: Add some talloc error checking for controls
       via  ac90c9faa78 sync_passwords: Remove dirsync cookie logging for continuous operation
       via  b7a0d3b1106 dirsync: Allow arbitrary length cookies
      from  8b47443b871 replmd: Cache recycle-bin state to avoid DB lookup

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


- Log -----------------------------------------------------------------
commit ad57cac7db0873cbe1c42173ed36ad41a75ed9a4
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Wed Nov 21 10:02:43 2018 +1300

    source4 samr: Tidy DBG_WARNING calls
    
    Move the calls to GUID_buf_string and dom_sid_str_buf into the
    coresponding DBG_WARNING call, instead of using an intermediate variable.
    While this violates the coding guidelines, doing this makes the code less
    cluttred and means the functions are only called if the debug message is
    printed.
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Wed Nov 21 01:50:11 CET 2018 on sn-devel-144

commit 1719f8b9cd98cf54a297ef59c68db68945bf6f0f
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Nov 15 13:44:29 2018 +1300

    s4-samr: Use GUID_buf_string() in dcesrv_samr_EnumDomainUsers()
    
    This avoids memory allocation.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit 53c20e1096d8aa4879ddf22df3cc3651eb73f8f7
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Nov 15 12:48:15 2018 +1300

    s4-samr: Use dom_sid_split_rid() to get the RID in dcesrv_samr_EnumDomainUsers
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit 64007aa3825be8a3c5678cbc636efa8ecb09c4b1
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Thu Oct 18 13:54:31 2018 +1300

    source4 samr: cache samr_EnumDomainUsers results
    
    Add a cache of GUID's that matched the last samr_EnunDomainUsers made on a
    domain handle.  The cache is cleared if resume_handle is zero, and when the
    final results are returned to the caller.
    
    The existing code repeated the database query for each chunk requested.
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit fa3ea1cfc181dc9119c5fb0c6a1a12a7d31bfac2
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Thu Oct 18 13:53:55 2018 +1300

    tests samr: Extra tests for samr_EnumDomainUserss
    
    Add extra tests to test the content returned by samr_EnumDomainUsers,
    and tests for the result caching added in the following commit.
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 8d8303b0aecb472de33f7dbd87c80e939e98034a
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Nov 15 13:44:23 2018 +1300

    s4-samr: Use GUID_buf_string() in dcesrv_samr_EnumDomainGroups()
    
    This avoids memory allocation
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit b6241852937e7e2d6254b3e9bba221d34edc5571
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Thu Oct 18 13:54:31 2018 +1300

    s4-samr: Use dom_sid_split_rid() to get the RID in dcesrv_samr_EnumDomainGroups
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit 564813b58830142699edb4f82539f0834434c2e4
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Thu Oct 18 10:16:24 2018 +1300

    source4 samr: cache samr_EnumDomainGroups results
    
    Add a cache of GUID's that matched the last samr_EnunDomainGroups made on a
    domain handle.  The cache is cleared if resume_handle is zero, and when the
    final results are returned to the caller.
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 7dd7800a88e6ece0606d6d94718318e2dc067d58
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Fri Oct 12 11:21:10 2018 +1300

    test samr: Extra tests for samr_EnumDomainGroups
    
    Add extra tests to test the content returned by samr_EnumDomainGroups,
    and tests for the result caching added in the following commit.
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit fc1a16ff61ac57079d7e31fc2266b35b2fdeaae0
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Nov 15 09:53:25 2018 +1300

    s4-samr: Use dom_sid_split_rid() to get the RID in dcesrv_samr_QueryDisplayInfo
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit 10efdac356dcb15c7ab233412bafc5853effc31a
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Wed Oct 10 09:20:25 2018 +1300

    source4 samr: cache samr_QueryDisplayInfo results
    
    Add a cache of GUID's that matched the last samr_QueryDisplayInfo made on a
    domain handle.  The cache is cleared if the requested start index is
    zero, or if the level does not match that in the cache.
    
    The cache is maintained in the guid_caches array of the dcesrv_handle.
    
    Note: that currently this cache exists for the lifetime of the RPC
          handle.
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d9f7b6d63f9c3622c857ccb80092f6f1c21d1431
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Tue Oct 9 11:11:12 2018 +1300

    tests samr: remove PEP8 warnings
    
    Remove PEP8 warnings from the samr tests.
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 9a1277c1ecd76ab50ef0c509f6834ae9311c8daf
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Tue Oct 9 11:09:20 2018 +1300

    tests samr: Extra tests for samr_QueryDisplayInfo
    
    Add extra tests to test the content returned by samr_QueryDisplayInfo,
    which is not tested for the ADDC.  Also adds tests for the result
    caching added in the following commit.
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ad8bb6fcd08be28c40f2522d640333e9e69b7852
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Wed Nov 14 10:29:01 2018 +1300

    ldb_controls: Add some talloc error checking for controls
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13686
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ac90c9faa783fc133229e7c163471d96440ff30e
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Mon Nov 19 11:05:59 2018 +1300

    sync_passwords: Remove dirsync cookie logging for continuous operation
    
    Under normal operation, users shouldn't see giant cookies in their logs.
    We still log the initial cookie retrieved from the cache database, which
    should still be helpful for identifying corrupt cookies.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13686
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit b7a0d3b110697923a31e353905d3b1bd9385ea9b
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Fri Oct 26 13:38:02 2018 +1300

    dirsync: Allow arbitrary length cookies
    
    The length of the cookie is proportional to the number of DCs ever in
    the domain (as it stores the uptodateness vector which has stale
    invocationID).
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13686
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

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

Summary of changes:
 lib/ldb/common/ldb_controls.c         | 108 +++-
 python/samba/netcmd/user.py           |   3 +-
 python/samba/tests/dcerpc/sam.py      | 709 ++++++++++++++++++++++++-
 source4/rpc_server/samr/dcesrv_samr.c | 974 +++++++++++++++++++++++++---------
 source4/rpc_server/samr/dcesrv_samr.h |  17 +
 5 files changed, 1549 insertions(+), 262 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/ldb/common/ldb_controls.c b/lib/ldb/common/ldb_controls.c
index a83768a352c..e0f0eb48f3a 100644
--- a/lib/ldb/common/ldb_controls.c
+++ b/lib/ldb/common/ldb_controls.c
@@ -520,6 +520,7 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 							   control->ctxid_len);
 			if (control->contextId == NULL) {
 				ldb_oom(ldb);
+				talloc_free(ctrl);
 				return NULL;
 			}
 		} else {
@@ -534,13 +535,20 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 	if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DIRSYNC_NAME) == 0) {
 		struct ldb_dirsync_control *control;
 		const char *p;
-		char cookie[1024];
+		char *cookie = NULL;
 		int crit, max_attrs, ret;
 		uint32_t flags;
 
-		cookie[0] = '\0';
+		cookie = talloc_zero_array(ctrl, char,
+					   strlen(control_strings) + 1);
+		if (cookie == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
+
 		p = &(control_strings[sizeof(LDB_CONTROL_DIRSYNC_NAME)]);
-		ret = sscanf(p, "%d:%u:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
+		ret = sscanf(p, "%d:%u:%d:%[^$]", &crit, &flags, &max_attrs, cookie);
 
 		if ((ret < 3) || (crit < 0) || (crit > 1) || (max_attrs < 0)) {
 			ldb_set_errstring(ldb,
@@ -561,6 +569,11 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 		ctrl->oid = LDB_CONTROL_DIRSYNC_OID;
 		ctrl->critical = crit;
 		control = talloc(ctrl, struct ldb_dirsync_control);
+		if (control == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
 		control->flags = flags;
 		control->max_attributes = max_attrs;
 		if (*cookie) {
@@ -575,6 +588,7 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 			control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
 			if (control->cookie == NULL) {
 				ldb_oom(ldb);
+				talloc_free(ctrl);
 				return NULL;
 			}
 		} else {
@@ -582,17 +596,25 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 			control->cookie_len = 0;
 		}
 		ctrl->data = control;
+		TALLOC_FREE(cookie);
 
 		return ctrl;
 	}
 	if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DIRSYNC_EX_NAME) == 0) {
 		struct ldb_dirsync_control *control;
 		const char *p;
-		char cookie[1024];
+		char *cookie = NULL;
 		int crit, max_attrs, ret;
 		uint32_t flags;
 
-		cookie[0] = '\0';
+		cookie = talloc_zero_array(ctrl, char,
+					   strlen(control_strings) + 1);
+		if (cookie == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
+
 		p = &(control_strings[sizeof(LDB_CONTROL_DIRSYNC_EX_NAME)]);
 		ret = sscanf(p, "%d:%u:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
 
@@ -615,6 +637,11 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 		ctrl->oid = LDB_CONTROL_DIRSYNC_EX_OID;
 		ctrl->critical = crit;
 		control = talloc(ctrl, struct ldb_dirsync_control);
+		if (control == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
 		control->flags = flags;
 		control->max_attributes = max_attrs;
 		if (*cookie) {
@@ -630,6 +657,7 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 			control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
 			if (control->cookie == NULL) {
 				ldb_oom(ldb);
+				talloc_free(ctrl);
 				return NULL;
 			}
 		} else {
@@ -637,6 +665,7 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 			control->cookie_len = 0;
 		}
 		ctrl->data = control;
+		TALLOC_FREE(cookie);
 
 		return ctrl;
 	}
@@ -662,6 +691,11 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 		ctrl->oid = LDB_CONTROL_ASQ_OID;
 		ctrl->critical = crit;
 		control = talloc(ctrl, struct ldb_asq_control);
+		if (control == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
 		control->request = 1;
 		control->source_attribute = talloc_strdup(control, attr);
 		control->src_attr_len = strlen(attr);
@@ -693,6 +727,11 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 			control = NULL;
 		} else {
 			control = talloc(ctrl, struct ldb_extended_dn_control);
+			if (control == NULL) {
+				ldb_oom(ldb);
+				talloc_free(ctrl);
+				return NULL;
+			}
 			control->type = type;
 		}
 
@@ -723,6 +762,12 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 		ctrl->oid = LDB_CONTROL_SD_FLAGS_OID;
 		ctrl->critical = crit;
 		control = talloc(ctrl, struct ldb_sd_flags_control);
+		if (control == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
+
 		control->secinfo_flags = secinfo_flags;
 		ctrl->data = control;
 
@@ -749,6 +794,12 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 		ctrl->oid = LDB_CONTROL_SEARCH_OPTIONS_OID;
 		ctrl->critical = crit;
 		control = talloc(ctrl, struct ldb_search_options_control);
+		if (control == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
+
 		control->search_options = search_options;
 		ctrl->data = control;
 
@@ -865,6 +916,12 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 		ctrl->oid = LDB_CONTROL_PAGED_RESULTS_OID;
 		ctrl->critical = crit;
 		control = talloc(ctrl, struct ldb_paged_control);
+		if (control == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
+
 		control->size = size;
 		if (cookie[0] != '\0') {
 			int len = ldb_base64_decode(cookie);
@@ -879,6 +936,7 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 			control->cookie = talloc_memdup(control, cookie, control->cookie_len);
 			if (control->cookie == NULL) {
 				ldb_oom(ldb);
+				talloc_free(ctrl);
 				return NULL;
 			}
 		} else {
@@ -912,12 +970,36 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 		ctrl->oid = LDB_CONTROL_SERVER_SORT_OID;
 		ctrl->critical = crit;
 		control = talloc_array(ctrl, struct ldb_server_sort_control *, 2);
+		if (control == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
+
 		control[0] = talloc(control, struct ldb_server_sort_control);
+		if (control[0] == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
+
 		control[0]->attributeName = talloc_strdup(control, attr);
-		if (rule[0])
+		if (control[0]->attributeName == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
+
+		if (rule[0]) {
 			control[0]->orderingRule = talloc_strdup(control, rule);
-		else
+			if (control[0]->orderingRule == NULL) {
+				ldb_oom(ldb);
+				talloc_free(ctrl);
+				return NULL;
+			}
+		} else {
 			control[0]->orderingRule = NULL;
+		}
 		control[0]->reverse = rev;
 		control[1] = NULL;
 		ctrl->data = control;
@@ -1179,7 +1261,19 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
 		ctrl->oid = LDB_CONTROL_VERIFY_NAME_OID;
 		ctrl->critical = crit;
 		control = talloc(ctrl, struct ldb_verify_name_control);
+		if (control == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
+
 		control->gc = talloc_strdup(control, gc);
+		if (control->gc == NULL) {
+			ldb_oom(ldb);
+			talloc_free(ctrl);
+			return NULL;
+		}
+
 		control->gc_len = strlen(gc);
 		control->flags = flags;
 		ctrl->data = control;
diff --git a/python/samba/netcmd/user.py b/python/samba/netcmd/user.py
index 447f1a345f6..b3af8fffd6a 100644
--- a/python/samba/netcmd/user.py
+++ b/python/samba/netcmd/user.py
@@ -2121,7 +2121,8 @@ samba-tool user syncpasswords --terminate \\
             assert res_controls[0].oid == "1.2.840.113556.1.4.841"
             res_controls[0].critical = True
             self.dirsync_controls = [str(res_controls[0]), "extended_dn:1:0"]
-            log_msg("dirsyncControls: %r\n" % self.dirsync_controls)
+            # This cookie can be extremely long
+            # log_msg("dirsyncControls: %r\n" % self.dirsync_controls)
 
             modify_ldif = "dn: %s\n" % (self.cache_dn)
             modify_ldif += "changetype: modify\n"
diff --git a/python/samba/tests/dcerpc/sam.py b/python/samba/tests/dcerpc/sam.py
index 9c432e3a37e..ab710861383 100644
--- a/python/samba/tests/dcerpc/sam.py
+++ b/python/samba/tests/dcerpc/sam.py
@@ -19,8 +19,21 @@
 
 """Tests for samba.dcerpc.sam."""
 
-from samba.dcerpc import samr, security
+from samba.dcerpc import samr, security, lsa
 from samba.tests import RpcInterfaceTestCase
+from samba.tests import env_loadparm, delete_force
+
+from samba.credentials import Credentials
+from samba.auth import system_session
+from samba.samdb import SamDB
+from samba.dsdb import (
+    ATYPE_NORMAL_ACCOUNT,
+    ATYPE_WORKSTATION_TRUST,
+    GTYPE_SECURITY_UNIVERSAL_GROUP,
+    GTYPE_SECURITY_GLOBAL_GROUP)
+from samba import generate_random_password
+from samba.ndr import ndr_unpack
+import os
 
 
 # FIXME: Pidl should be doing this for us
@@ -28,14 +41,71 @@ def toArray(handle, array, num_entries):
     return [(entry.idx, entry.name) for entry in array.entries[:num_entries]]
 
 
+# Extract the rid from an ldb message, assumes that the message has a
+# objectSID attribute
+#
+def rid(msg):
+    sid = ndr_unpack(security.dom_sid, msg["objectSID"][0])
+    (_, rid) = sid.split()
+    return rid
+
+
+# Calculate the request size for EnumDomainUsers and EnumDomainGroups calls
+# to hold the specified number of entries.
+# We use the w2k3 element size value of 54, code under test
+# rounds this up i.e. (1+(max_size/SAMR_ENUM_USERS_MULTIPLIER))
+#
+def calc_max_size(num_entries):
+    return (num_entries - 1) * 54
+
+
 class SamrTests(RpcInterfaceTestCase):
 
     def setUp(self):
         super(SamrTests, self).setUp()
         self.conn = samr.samr("ncalrpc:", self.get_loadparm())
+        self.open_samdb()
+        self.open_domain_handle()
+
+    #
+    # Open the samba database
+    #
+    def open_samdb(self):
+        self.lp = env_loadparm()
+        self.domain = os.environ["DOMAIN"]
+        self.creds = Credentials()
+        self.creds.guess(self.lp)
+        self.session = system_session()
+        self.samdb = SamDB(
+            session_info=self.session, credentials=self.creds, lp=self.lp)
+
+    #
+    # Open a SAMR Domain handle
+    def open_domain_handle(self):
+        self.handle = self.conn.Connect2(
+            None, security.SEC_FLAG_MAXIMUM_ALLOWED)
+
+        self.domain_sid = self.conn.LookupDomain(
+            self.handle, lsa.String(self.domain))
+
+        self.domain_handle = self.conn.OpenDomain(
+            self.handle, security.SEC_FLAG_MAXIMUM_ALLOWED, self.domain_sid)
+
+    # Filter a list of records, removing those that are not part of the
+    # current domain.
+    #
+    def filter_domain(self, unfiltered):
+        def sid(msg):
+            sid = ndr_unpack(security.dom_sid, msg["objectSID"][0])
+            (x, _) = sid.split()
+            return x
+
+        dom_sid = security.dom_sid(self.samdb.get_domain_sid())
+        return [x for x in unfiltered if sid(x) == dom_sid]
 
     def test_connect5(self):
-        (level, info, handle) = self.conn.Connect5(None, 0, 1, samr.ConnectInfo1())
+        (level, info, handle) =\
+            self.conn.Connect5(None, 0, 1, samr.ConnectInfo1())
 
     def test_connect2(self):
         handle = self.conn.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
@@ -43,5 +113,638 @@ class SamrTests(RpcInterfaceTestCase):
 
     def test_EnumDomains(self):
         handle = self.conn.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
-        domains = toArray(*self.conn.EnumDomains(handle, 0, 4294967295))
+        toArray(*self.conn.EnumDomains(handle, 0, 4294967295))
         self.conn.Close(handle)
+
+    # Create groups based on the id list supplied, the id is used to
+    # form a unique name and description.
+    #
+    # returns a list of the created dn's, which can be passed to delete_dns
+    # to clean up after the test has run.
+    def create_groups(self, ids):
+        dns = []
+        for i in ids:
+            name = "SAMR_GRP%d" % i
+            dn = "cn=%s,cn=Users,%s" % (name, self.samdb.domain_dn())
+            delete_force(self.samdb, dn)
+
+            self.samdb.newgroup(name)
+            dns.append(dn)
+        return dns
+
+    # Create user accounts based on the id list supplied, the id is used to
+    # form a unique name and description.
+    #
+    # returns a list of the created dn's, which can be passed to delete_dns
+    # to clean up after the test has run.
+    def create_users(self, ids):
+        dns = []
+        for i in ids:
+            name = "SAMR_USER%d" % i
+            dn = "cn=%s,CN=USERS,%s" % (name, self.samdb.domain_dn())
+            delete_force(self.samdb, dn)
+
+            # We only need the user to exist, we don't need a password
+            self.samdb.newuser(
+                name,
+                password=None,
+                setpassword=False,
+                description="Description for " + name,
+                givenname="given%dname" % i,
+                surname="surname%d" % i)
+            dns.append(dn)
+        return dns
+
+    # Create computer accounts based on the id list supplied, the id is used to
+    # form a unique name and description.
+    #
+    # returns a list of the created dn's, which can be passed to delete_dns
+    # to clean up after the test has run.
+    def create_computers(self, ids):
+        dns = []
+        for i in ids:
+            name = "SAMR_CMP%d" % i
+            dn = "cn=%s,cn=COMPUTERS,%s" % (name, self.samdb.domain_dn())
+            delete_force(self.samdb, dn)
+
+            self.samdb.newcomputer(name, description="Description of " + name)
+            dns.append(dn)
+        return dns
+
+    # Delete the specified dn's.
+    #
+    # Used to clean up entries created by individual tests.
+    #
+    def delete_dns(self, dns):
+        for dn in dns:
+            delete_force(self.samdb, dn)
+
+    # Common tests for QueryDisplayInfo
+    #
+    def _test_QueryDisplayInfo(
+            self, level, check_results, select, attributes, add_elements):
+        #
+        # Get the expected results by querying the samdb database directly.
+        # We do this rather than use a list of expected results as this runs
+        # with other tests so we do not have a known fixed list of elements
+        expected = self.samdb.search(expression=select, attrs=attributes)
+        self.assertTrue(len(expected) > 0)
+
+        #
+        # Perform QueryDisplayInfo with max results greater than the expected
+        # number of results.
+        (ts, rs, actual) = self.conn.QueryDisplayInfo(
+            self.domain_handle, level, 0, 1024, 4294967295)
+
+        self.assertEquals(len(expected), ts)
+        self.assertEquals(len(expected), rs)
+        check_results(expected, actual.entries)
+
+        #
+        # Perform QueryDisplayInfo with max results set to the number of
+        # results returned from the first query, should return the same results
+        (ts1, rs1, actual1) = self.conn.QueryDisplayInfo(
+            self.domain_handle, level, 0, rs, 4294967295)
+        self.assertEquals(ts, ts1)
+        self.assertEquals(rs, rs1)
+        check_results(expected, actual1.entries)
+
+        #
+        # Perform QueryDisplayInfo and get the last two results.
+        # Note: We are assuming there are at least three entries
+        self.assertTrue(ts > 2)
+        (ts2, rs2, actual2) = self.conn.QueryDisplayInfo(
+            self.domain_handle, level, (ts - 2), 2, 4294967295)
+        self.assertEquals(ts, ts2)
+        self.assertEquals(2, rs2)
+        check_results(list(expected)[-2:], actual2.entries)
+
+        #
+        # Perform QueryDisplayInfo and get the first two results.
+        # Note: We are assuming there are at least three entries
+        self.assertTrue(ts > 2)
+        (ts2, rs2, actual2) = self.conn.QueryDisplayInfo(
+            self.domain_handle, level, 0, 2, 4294967295)
+        self.assertEquals(ts, ts2)
+        self.assertEquals(2, rs2)
+        check_results(list(expected)[:2], actual2.entries)
+
+        #
+        # Perform QueryDisplayInfo and get two results in the middle of the
+        # list i.e. not the first or the last entry.
+        # Note: We are assuming there are at least four entries
+        self.assertTrue(ts > 3)
+        (ts2, rs2, actual2) = self.conn.QueryDisplayInfo(
+            self.domain_handle, level, 1, 2, 4294967295)
+        self.assertEquals(ts, ts2)
+        self.assertEquals(2, rs2)
+        check_results(list(expected)[1:2], actual2.entries)
+
+        #
+        # To check that cached values are being returned rather than the
+        # results being re-read from disk we add elements, and request all
+        # but the first result.
+        #
+        dns = add_elements([1000, 1002, 1003, 1004])
+
+        #
+        # Perform QueryDisplayInfo and get all but the first result.
+        # We should be using the cached results so the entries we just added
+        # should not be present
+        (ts3, rs3, actual3) = self.conn.QueryDisplayInfo(


-- 
Samba Shared Repository



More information about the samba-cvs mailing list