From 3fa8da4d26d9a880a2a4911a32f222fbc5d2eeaa Mon Sep 17 00:00:00 2001
From: Andrew Tridgell <tridge@samba.org>
Date: Sun, 9 Nov 2003 11:01:39 +0000
Subject: - fixed lsa_EnumTrustDom

- added lsa_OpenAccount

- handle STATUS_SOME_UNMAPPED
(This used to be commit e5d93cf996b3e9647ef0ca45f6aab7601369936b)
---
 source4/librpc/idl/lsa.idl   |  36 +++++++++++----
 source4/librpc/ndr/ndr_lsa.c | 108 ++++++++++++++++++++++++++++++++++---------
 source4/librpc/ndr/ndr_lsa.h |  29 +++++++++---
 source4/librpc/rpc/dcerpc.c  |   4 ++
 source4/librpc/rpc/rpc_lsa.c |   8 ++--
 source4/torture/rpc/lsa.c    |  56 +++++++++++++++++-----
 6 files changed, 190 insertions(+), 51 deletions(-)

diff --git a/source4/librpc/idl/lsa.idl b/source4/librpc/idl/lsa.idl
index 4582470980..f604534a78 100644
--- a/source4/librpc/idl/lsa.idl
+++ b/source4/librpc/idl/lsa.idl
@@ -10,7 +10,7 @@
 	/******************/
 	/* Function: 0x00 */
 	NTSTATUS lsa_Close (
-		[in,ref]     policy_handle *handle
+		[in,out,ref]     policy_handle *handle
 		);
 	
 
@@ -136,19 +136,18 @@
 	typedef struct {
 		lsa_Name name;
 		dom_sid2 *sid;
-	} lsa_TrustInformation;
+	} lsa_DomainInformation;
 
 	typedef struct {
 		uint32 count;
-		[size_is(count)] lsa_TrustInformation *domains;
-		uint32 max_count;
-	} lsa_RefDomainList;
+		[size_is(count)] lsa_DomainInformation *domains;
+	} lsa_DomainList;
 
 	NTSTATUS lsa_EnumTrustDom (
 		[in,ref]     policy_handle *handle,
 		[in,out,ref] uint32 *resume_handle,
 		[in]         uint32 num_entries,
-		[out]        lsa_RefDomainList *domains
+		[out,ref]    lsa_DomainList *domains
 		);
 
 
@@ -166,6 +165,17 @@
 		[size_is(count)] lsa_TranslatedSid *sids;
 	} lsa_TransSidArray;
 
+	typedef struct {
+		lsa_Name name;
+		dom_sid2 *sid;
+	} lsa_TrustInformation;
+
+	typedef struct {
+		uint32 count;
+		[size_is(count)] lsa_TrustInformation *domains;
+		uint32 max_count;
+	} lsa_RefDomainList;
+
 	NTSTATUS lsa_LookupNames (
 		[in,ref]     policy_handle *handle,
 		[in]         uint32 num_names,
@@ -203,8 +213,18 @@
 
 	/* Function:        0x10 */
 	NTSTATUS CREATESECRET ();
-	/* Function:     0x11 */
-	NTSTATUS OPENACCOUNT ();
+
+
+	/*****************************************/
+	/* Function:     0x11                    */
+	NTSTATUS lsa_OpenAccount (
+		[in,ref]     policy_handle *handle,
+		[in,ref]     dom_sid2 *sid,
+		[in]         uint32 desired_access,
+		[out,ref]    policy_handle *acct_handle
+		);
+
+
 	/* Function:    0x12 */
 	NTSTATUS ENUMPRIVSACCOUNT ();
 	/* Function:            0x13 */
diff --git a/source4/librpc/ndr/ndr_lsa.c b/source4/librpc/ndr/ndr_lsa.c
index c3ad9ab26f..37850fbf19 100644
--- a/source4/librpc/ndr/ndr_lsa.c
+++ b/source4/librpc/ndr/ndr_lsa.c
@@ -11,6 +11,7 @@ NTSTATUS ndr_push_lsa_Close(struct ndr_push *ndr, struct lsa_Close *r)
 
 NTSTATUS ndr_pull_lsa_Close(struct ndr_pull *ndr, struct lsa_Close *r)
 {
+	NDR_CHECK(ndr_pull_policy_handle(ndr, r->out.handle));
 	NDR_CHECK(ndr_pull_NTSTATUS(ndr, &r->out.result));
 
 	return NT_STATUS_OK;
@@ -486,7 +487,7 @@ NTSTATUS ndr_pull_lsa_CreateTrustDom(struct ndr_pull *ndr, struct lsa_CreateTrus
 	return NT_STATUS_OK;
 }
 
-static NTSTATUS ndr_push_lsa_TrustInformation(struct ndr_push *ndr, int ndr_flags, struct lsa_TrustInformation *r)
+static NTSTATUS ndr_push_lsa_DomainInformation(struct ndr_push *ndr, int ndr_flags, struct lsa_DomainInformation *r)
 {
 	if (!(ndr_flags & NDR_SCALARS)) goto buffers;
 	NDR_CHECK(ndr_push_lsa_Name(ndr, NDR_SCALARS, &r->name));
@@ -501,7 +502,7 @@ done:
 	return NT_STATUS_OK;
 }
 
-static NTSTATUS ndr_pull_lsa_TrustInformation(struct ndr_pull *ndr, int ndr_flags, struct lsa_TrustInformation *r)
+static NTSTATUS ndr_pull_lsa_DomainInformation(struct ndr_pull *ndr, int ndr_flags, struct lsa_DomainInformation *r)
 {
 	uint32 _ptr_sid;
 	if (!(ndr_flags & NDR_SCALARS)) goto buffers;
@@ -522,22 +523,21 @@ done:
 	return NT_STATUS_OK;
 }
 
-static NTSTATUS ndr_push_lsa_RefDomainList(struct ndr_push *ndr, int ndr_flags, struct lsa_RefDomainList *r)
+static NTSTATUS ndr_push_lsa_DomainList(struct ndr_push *ndr, int ndr_flags, struct lsa_DomainList *r)
 {
 	if (!(ndr_flags & NDR_SCALARS)) goto buffers;
 	NDR_CHECK(ndr_push_uint32(ndr, r->count));
 	NDR_CHECK(ndr_push_ptr(ndr, r->domains));
-	NDR_CHECK(ndr_push_uint32(ndr, r->max_count));
 buffers:
 	if (!(ndr_flags & NDR_BUFFERS)) goto done;
 	if (r->domains) {
-		NDR_CHECK(ndr_push_array(ndr, ndr_flags, r->domains, sizeof(r->domains[0]), r->count, (ndr_push_flags_fn_t)ndr_push_lsa_TrustInformation));
+		NDR_CHECK(ndr_push_array(ndr, ndr_flags, r->domains, sizeof(r->domains[0]), r->count, (ndr_push_flags_fn_t)ndr_push_lsa_DomainInformation));
 	}
 done:
 	return NT_STATUS_OK;
 }
 
-static NTSTATUS ndr_pull_lsa_RefDomainList(struct ndr_pull *ndr, int ndr_flags, struct lsa_RefDomainList *r)
+static NTSTATUS ndr_pull_lsa_DomainList(struct ndr_pull *ndr, int ndr_flags, struct lsa_DomainList *r)
 {
 	uint32 _ptr_domains;
 	if (!(ndr_flags & NDR_SCALARS)) goto buffers;
@@ -548,12 +548,11 @@ static NTSTATUS ndr_pull_lsa_RefDomainList(struct ndr_pull *ndr, int ndr_flags,
 	} else {
 		r->domains = NULL;
 	}
-	NDR_CHECK(ndr_pull_uint32(ndr, &r->max_count));
 buffers:
 	if (!(ndr_flags & NDR_BUFFERS)) goto done;
 	if (r->domains) {
 		NDR_ALLOC_N_SIZE(ndr, r->domains, r->count, sizeof(r->domains[0]));
-		NDR_CHECK(ndr_pull_array(ndr, ndr_flags, (void **)r->domains, sizeof(r->domains[0]), r->count, (ndr_pull_flags_fn_t)ndr_pull_lsa_TrustInformation));
+		NDR_CHECK(ndr_pull_array(ndr, ndr_flags, (void **)r->domains, sizeof(r->domains[0]), r->count, (ndr_pull_flags_fn_t)ndr_pull_lsa_DomainInformation));
 	}
 done:
 	return NT_STATUS_OK;
@@ -570,18 +569,8 @@ NTSTATUS ndr_push_lsa_EnumTrustDom(struct ndr_push *ndr, struct lsa_EnumTrustDom
 
 NTSTATUS ndr_pull_lsa_EnumTrustDom(struct ndr_pull *ndr, struct lsa_EnumTrustDom *r)
 {
-	uint32 _ptr_domains;
 	NDR_CHECK(ndr_pull_uint32(ndr, r->out.resume_handle));
-	NDR_ALLOC(ndr, r->out.domains);
-	NDR_CHECK(ndr_pull_uint32(ndr, &_ptr_domains));
-	if (_ptr_domains) {
-		NDR_ALLOC(ndr, r->out.domains);
-	} else {
-		r->out.domains = NULL;
-	}
-	if (r->out.domains) {
-		NDR_CHECK(ndr_pull_lsa_RefDomainList(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.domains));
-	}
+	NDR_CHECK(ndr_pull_lsa_DomainList(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.domains));
 	NDR_CHECK(ndr_pull_NTSTATUS(ndr, &r->out.result));
 
 	return NT_STATUS_OK;
@@ -646,6 +635,79 @@ done:
 	return NT_STATUS_OK;
 }
 
+static NTSTATUS ndr_push_lsa_TrustInformation(struct ndr_push *ndr, int ndr_flags, struct lsa_TrustInformation *r)
+{
+	if (!(ndr_flags & NDR_SCALARS)) goto buffers;
+	NDR_CHECK(ndr_push_lsa_Name(ndr, NDR_SCALARS, &r->name));
+	NDR_CHECK(ndr_push_ptr(ndr, r->sid));
+buffers:
+	if (!(ndr_flags & NDR_BUFFERS)) goto done;
+		NDR_CHECK(ndr_push_lsa_Name(ndr, ndr_flags, &r->name));
+	if (r->sid) {
+		NDR_CHECK(ndr_push_dom_sid2(ndr, r->sid));
+	}
+done:
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_pull_lsa_TrustInformation(struct ndr_pull *ndr, int ndr_flags, struct lsa_TrustInformation *r)
+{
+	uint32 _ptr_sid;
+	if (!(ndr_flags & NDR_SCALARS)) goto buffers;
+	NDR_CHECK(ndr_pull_lsa_Name(ndr, NDR_SCALARS, &r->name));
+	NDR_CHECK(ndr_pull_uint32(ndr, &_ptr_sid));
+	if (_ptr_sid) {
+		NDR_ALLOC(ndr, r->sid);
+	} else {
+		r->sid = NULL;
+	}
+buffers:
+	if (!(ndr_flags & NDR_BUFFERS)) goto done;
+		NDR_CHECK(ndr_pull_lsa_Name(ndr, ndr_flags, &r->name));
+	if (r->sid) {
+		NDR_CHECK(ndr_pull_dom_sid2(ndr, r->sid));
+	}
+done:
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_push_lsa_RefDomainList(struct ndr_push *ndr, int ndr_flags, struct lsa_RefDomainList *r)
+{
+	if (!(ndr_flags & NDR_SCALARS)) goto buffers;
+	NDR_CHECK(ndr_push_uint32(ndr, r->count));
+	NDR_CHECK(ndr_push_ptr(ndr, r->domains));
+	NDR_CHECK(ndr_push_uint32(ndr, r->max_count));
+buffers:
+	if (!(ndr_flags & NDR_BUFFERS)) goto done;
+	if (r->domains) {
+		NDR_CHECK(ndr_push_array(ndr, ndr_flags, r->domains, sizeof(r->domains[0]), r->count, (ndr_push_flags_fn_t)ndr_push_lsa_TrustInformation));
+	}
+done:
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_pull_lsa_RefDomainList(struct ndr_pull *ndr, int ndr_flags, struct lsa_RefDomainList *r)
+{
+	uint32 _ptr_domains;
+	if (!(ndr_flags & NDR_SCALARS)) goto buffers;
+	NDR_CHECK(ndr_pull_uint32(ndr, &r->count));
+	NDR_CHECK(ndr_pull_uint32(ndr, &_ptr_domains));
+	if (_ptr_domains) {
+		NDR_ALLOC(ndr, r->domains);
+	} else {
+		r->domains = NULL;
+	}
+	NDR_CHECK(ndr_pull_uint32(ndr, &r->max_count));
+buffers:
+	if (!(ndr_flags & NDR_BUFFERS)) goto done;
+	if (r->domains) {
+		NDR_ALLOC_N_SIZE(ndr, r->domains, r->count, sizeof(r->domains[0]));
+		NDR_CHECK(ndr_pull_array(ndr, ndr_flags, (void **)r->domains, sizeof(r->domains[0]), r->count, (ndr_pull_flags_fn_t)ndr_pull_lsa_TrustInformation));
+	}
+done:
+	return NT_STATUS_OK;
+}
+
 NTSTATUS ndr_push_lsa_LookupNames(struct ndr_push *ndr, struct lsa_LookupNames *r)
 {
 	NDR_CHECK(ndr_push_policy_handle(ndr, r->in.handle));
@@ -786,14 +848,18 @@ NTSTATUS ndr_pull_CREATESECRET(struct ndr_pull *ndr, struct CREATESECRET *r)
 	return NT_STATUS_OK;
 }
 
-NTSTATUS ndr_push_OPENACCOUNT(struct ndr_push *ndr, struct OPENACCOUNT *r)
+NTSTATUS ndr_push_lsa_OpenAccount(struct ndr_push *ndr, struct lsa_OpenAccount *r)
 {
+	NDR_CHECK(ndr_push_policy_handle(ndr, r->in.handle));
+	NDR_CHECK(ndr_push_dom_sid2(ndr, r->in.sid));
+	NDR_CHECK(ndr_push_uint32(ndr, r->in.desired_access));
 
 	return NT_STATUS_OK;
 }
 
-NTSTATUS ndr_pull_OPENACCOUNT(struct ndr_pull *ndr, struct OPENACCOUNT *r)
+NTSTATUS ndr_pull_lsa_OpenAccount(struct ndr_pull *ndr, struct lsa_OpenAccount *r)
 {
+	NDR_CHECK(ndr_pull_policy_handle(ndr, r->out.acct_handle));
 	NDR_CHECK(ndr_pull_NTSTATUS(ndr, &r->out.result));
 
 	return NT_STATUS_OK;
diff --git a/source4/librpc/ndr/ndr_lsa.h b/source4/librpc/ndr/ndr_lsa.h
index 784ff1b2a4..473cf370c6 100644
--- a/source4/librpc/ndr/ndr_lsa.h
+++ b/source4/librpc/ndr/ndr_lsa.h
@@ -6,6 +6,7 @@ struct lsa_Close {
 	} in;
 
 	struct {
+		struct policy_handle *handle;
 		NTSTATUS result;
 	} out;
 
@@ -186,15 +187,14 @@ struct lsa_CreateTrustDom {
 
 };
 
-struct lsa_TrustInformation {
+struct lsa_DomainInformation {
 	struct lsa_Name name;
 	struct dom_sid2 *sid;
 };
 
-struct lsa_RefDomainList {
+struct lsa_DomainList {
 	uint32 count;
-	struct lsa_TrustInformation *domains;
-	uint32 max_count;
+	struct lsa_DomainInformation *domains;
 };
 
 struct lsa_EnumTrustDom {
@@ -206,7 +206,7 @@ struct lsa_EnumTrustDom {
 
 	struct {
 		uint32 *resume_handle;
-		struct lsa_RefDomainList *domains;
+		struct lsa_DomainList *domains;
 		NTSTATUS result;
 	} out;
 
@@ -223,6 +223,17 @@ struct lsa_TransSidArray {
 	struct lsa_TranslatedSid *sids;
 };
 
+struct lsa_TrustInformation {
+	struct lsa_Name name;
+	struct dom_sid2 *sid;
+};
+
+struct lsa_RefDomainList {
+	uint32 count;
+	struct lsa_TrustInformation *domains;
+	uint32 max_count;
+};
+
 struct lsa_LookupNames {
 	struct {
 		struct policy_handle *handle;
@@ -281,11 +292,15 @@ struct CREATESECRET {
 
 };
 
-struct OPENACCOUNT {
+struct lsa_OpenAccount {
 	struct {
+		struct policy_handle *handle;
+		struct dom_sid2 *sid;
+		uint32 desired_access;
 	} in;
 
 	struct {
+		struct policy_handle *acct_handle;
 		NTSTATUS result;
 	} out;
 
@@ -602,7 +617,7 @@ struct QUERYINFO2 {
 #define DCERPC_LSA_LOOKUPNAMES 14
 #define DCERPC_LSA_LOOKUPSIDS 15
 #define DCERPC_CREATESECRET 16
-#define DCERPC_OPENACCOUNT 17
+#define DCERPC_LSA_OPENACCOUNT 17
 #define DCERPC_ENUMPRIVSACCOUNT 18
 #define DCERPC_ADDPRIVS 19
 #define DCERPC_REMOVEPRIVS 20
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index 9e6c05e7ae..682735c000 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -798,6 +798,10 @@ NTSTATUS dcerpc_ndr_request(struct dcerpc_pipe *p,
 		goto failed;
 	}
 
+	if (pull->offset != pull->data_size) {
+		DEBUG(0,("Warning! %d unread bytes\n", pull->data_size - pull->offset));
+	}
+
 failed:
 	ndr_push_free(push);
 	return status;
diff --git a/source4/librpc/rpc/rpc_lsa.c b/source4/librpc/rpc/rpc_lsa.c
index bc2f00c33d..c5c18fe7ea 100644
--- a/source4/librpc/rpc/rpc_lsa.c
+++ b/source4/librpc/rpc/rpc_lsa.c
@@ -241,12 +241,12 @@ NTSTATUS dcerpc_CREATESECRET(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct
 	return r->out.result;
 }
 
-NTSTATUS dcerpc_OPENACCOUNT(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct OPENACCOUNT *r)
+NTSTATUS dcerpc_lsa_OpenAccount(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct lsa_OpenAccount *r)
 {
 	NTSTATUS status;
-	status = dcerpc_ndr_request(p, DCERPC_OPENACCOUNT, mem_ctx,
-				    (ndr_push_fn_t) ndr_push_OPENACCOUNT,
-				    (ndr_pull_fn_t) ndr_pull_OPENACCOUNT,
+	status = dcerpc_ndr_request(p, DCERPC_LSA_OPENACCOUNT, mem_ctx,
+				    (ndr_push_fn_t) ndr_push_lsa_OpenAccount,
+				    (ndr_pull_fn_t) ndr_pull_lsa_OpenAccount,
 				    r);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index 90db819a33..df095aca6e 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -183,7 +183,7 @@ static BOOL test_LookupNames(struct dcerpc_pipe *p,
 	r.out.sids = &sids;
 
 	status = dcerpc_lsa_LookupNames(p, mem_ctx, &r);
-	if (!NT_STATUS_IS_OK(status)) {
+	if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
 		printf("LookupNames failed - %s\n", nt_errstr(status));
 		return False;
 	}
@@ -238,7 +238,7 @@ static BOOL test_LookupSids(struct dcerpc_pipe *p,
 	r.out.names = &names;
 
 	status = dcerpc_lsa_LookupSids(p, mem_ctx, &r);
-	if (!NT_STATUS_IS_OK(status)) {
+	if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
 		printf("LookupSids failed - %s\n", nt_errstr(status));
 		return False;
 	}
@@ -271,6 +271,31 @@ static BOOL test_LookupSids(struct dcerpc_pipe *p,
 	return True;
 }
 
+static BOOL test_OpenAccount(struct dcerpc_pipe *p, 
+			     TALLOC_CTX *mem_ctx, 
+			     struct policy_handle *handle,
+			     struct dom_sid *sid)
+{
+	NTSTATUS status;
+	struct lsa_OpenAccount r;
+	struct policy_handle acct_handle;
+
+	printf("Testing account %s\n", lsa_sid_string_talloc(mem_ctx, sid));
+
+	r.in.handle = handle;
+	r.in.sid = sid;
+	r.in.desired_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
+	r.out.acct_handle = &acct_handle;
+
+	status = dcerpc_lsa_OpenAccount(p, mem_ctx, &r);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("OpenAccount failed - %s\n", nt_errstr(status));
+		return False;
+	}
+
+	return True;
+}
+
 static BOOL test_EnumAccounts(struct dcerpc_pipe *p, 
 			  TALLOC_CTX *mem_ctx, 
 			  struct policy_handle *handle)
@@ -305,6 +330,12 @@ static BOOL test_EnumAccounts(struct dcerpc_pipe *p,
 	if (!test_LookupSids(p, mem_ctx, handle, &sids1)) {
 		return False;
 	}
+
+	printf("testing all accounts\n");
+	for (i=0;i<sids1.num_sids;i++) {
+		test_OpenAccount(p, mem_ctx, handle, sids1.sids[i].sid);
+	}
+	printf("\n");
 	
 	if (sids1.num_sids < 3) {
 		return True;
@@ -376,12 +407,14 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p,
 	NTSTATUS status;
 	int i;
 	uint32 resume_handle = 0;
+	struct lsa_RefDomainList domains;
 
 	printf("\nTesting EnumTrustDom\n");
 
 	r.in.handle = handle;
 	r.in.resume_handle = &resume_handle;
 	r.in.num_entries = 1000;
+	r.out.domains = &domains;
 	r.out.resume_handle = &resume_handle;
 
 	status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r);
@@ -390,15 +423,13 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p,
 		return False;
 	}
 
-	if (r.out.domains) {
-		printf("lookup gave %d domains (max_count=%d)\n", 
-		       r.out.domains->count,
-		       r.out.domains->max_count);
-		for (i=0;i<r.out.domains->count;i++) {
-			printf("name='%s' sid=%s\n", 
-			       r.out.domains->domains[i].name.name,
-			       lsa_sid_string_talloc(mem_ctx, r.out.domains->domains[i].sid));
-		}
+	printf("lookup gave %d domains (max_count=%d)\n", 
+	       domains.count,
+	       domains.max_count);
+	for (i=0;i<r.out.domains->count;i++) {
+		printf("name='%s' sid=%s\n", 
+		       domains.domains[i].name.name,
+		       lsa_sid_string_talloc(mem_ctx, domains.domains[i].sid));
 	}
 
 	return True;
@@ -431,10 +462,13 @@ static BOOL test_Close(struct dcerpc_pipe *p,
 {
 	NTSTATUS status;
 	struct lsa_Close r;
+	struct policy_handle handle2;
 
 	printf("\ntesting Close\n");
 
 	r.in.handle = handle;
+	r.out.handle = &handle2;
+
 	status = dcerpc_lsa_Close(p, mem_ctx, &r);
 	if (!NT_STATUS_IS_OK(status)) {
 		printf("Close failed - %s\n", nt_errstr(status));
-- 
cgit