summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/torture/rpc/lsa.c51
1 files changed, 45 insertions, 6 deletions
diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index 9cee4e2f0c..710f4c53d2 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -2026,20 +2026,39 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p,
{
struct lsa_EnumTrustDom r;
NTSTATUS enum_status;
- uint32_t resume_handle = 0;
+ uint32_t in_resume_handle = 0;
+ uint32_t out_resume_handle;
struct lsa_DomainList domains;
bool ret = true;
torture_comment(tctx, "\nTesting EnumTrustDom\n");
r.in.handle = handle;
- r.in.resume_handle = &resume_handle;
+ r.in.resume_handle = &in_resume_handle;
r.in.max_size = 0;
r.out.domains = &domains;
- r.out.resume_handle = &resume_handle;
+ r.out.resume_handle = &out_resume_handle;
enum_status = dcerpc_lsa_EnumTrustDom(p, tctx, &r);
+ /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
+ * always be larger than the previous input resume handle, in
+ * particular when hitting the last query it is vital to set the
+ * resume handle correctly to avoid infinite client loops, as
+ * seen e.g. with Windows XP SP3 when resume handle is 0 and
+ * status is NT_STATUS_OK - gd */
+
+ if (NT_STATUS_IS_OK(enum_status) ||
+ NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES) ||
+ NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES))
+ {
+ if (out_resume_handle <= in_resume_handle) {
+ torture_comment(tctx, "EnumTrustDom failed - should have returned output resume_handle (0x%08x) larger than input resume handle (0x%08x)\n",
+ out_resume_handle, in_resume_handle);
+ return false;
+ }
+ }
+
if (NT_STATUS_IS_OK(enum_status)) {
if (domains.count == 0) {
torture_comment(tctx, "EnumTrustDom failed - should have returned 'NT_STATUS_NO_MORE_ENTRIES' for 0 trusted domains\n");
@@ -2051,17 +2070,35 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p,
}
/* Start from the bottom again */
- resume_handle = 0;
+ in_resume_handle = 0;
do {
r.in.handle = handle;
- r.in.resume_handle = &resume_handle;
+ r.in.resume_handle = &in_resume_handle;
r.in.max_size = LSA_ENUM_TRUST_DOMAIN_MULTIPLIER * 3;
r.out.domains = &domains;
- r.out.resume_handle = &resume_handle;
+ r.out.resume_handle = &out_resume_handle;
enum_status = dcerpc_lsa_EnumTrustDom(p, tctx, &r);
+ /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
+ * always be larger than the previous input resume handle, in
+ * particular when hitting the last query it is vital to set the
+ * resume handle correctly to avoid infinite client loops, as
+ * seen e.g. with Windows XP SP3 when resume handle is 0 and
+ * status is NT_STATUS_OK - gd */
+
+ if (NT_STATUS_IS_OK(enum_status) ||
+ NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES) ||
+ NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES))
+ {
+ if (out_resume_handle <= in_resume_handle) {
+ torture_comment(tctx, "EnumTrustDom failed - should have returned output resume_handle (0x%08x) larger than input resume handle (0x%08x)\n",
+ out_resume_handle, in_resume_handle);
+ return false;
+ }
+ }
+
/* NO_MORE_ENTRIES is allowed */
if (NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES)) {
if (domains.count == 0) {
@@ -2090,6 +2127,8 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p,
ret &= test_query_each_TrustDom(p, tctx, handle, &domains);
+ in_resume_handle = out_resume_handle;
+
} while ((NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)));
return ret;