summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/librpc/idl/lsa.idl6
-rw-r--r--source4/librpc/ndr/libndr.h21
-rw-r--r--source4/librpc/ndr/ndr.c14
-rw-r--r--source4/librpc/ndr/ndr_basic.c20
-rw-r--r--source4/librpc/ndr/ndr_lsa.c12
-rw-r--r--source4/librpc/ndr/ndr_lsa.h3
-rw-r--r--source4/librpc/ndr/ndr_sec.c111
-rw-r--r--source4/librpc/ndr/ndr_sec.h17
-rw-r--r--source4/torture/rpc/lsa.c29
9 files changed, 210 insertions, 23 deletions
diff --git a/source4/librpc/idl/lsa.idl b/source4/librpc/idl/lsa.idl
index 9e703d6c26..622d34eef3 100644
--- a/source4/librpc/idl/lsa.idl
+++ b/source4/librpc/idl/lsa.idl
@@ -51,7 +51,11 @@
/******************/
/* Function: 0x03 */
- NTSTATUS lsa_QuerySecObj ();
+ NTSTATUS lsa_QuerySecObj (
+ [in,ref] policy_handle *handle,
+ [in] uint32 sec_info,
+ [out] sec_desc_buf *sd
+ );
/******************/
diff --git a/source4/librpc/ndr/libndr.h b/source4/librpc/ndr/libndr.h
index 287046ad20..a7c63f7e13 100644
--- a/source4/librpc/ndr/libndr.h
+++ b/source4/librpc/ndr/libndr.h
@@ -88,6 +88,27 @@ enum ndr_err_code {
#define NDR_SCALARS 1
#define NDR_BUFFERS 2
+#define NDR_PULL_NEED_BYTES(ndr, n) do { \
+ if ((n) > ndr->data_size || ndr->offset + (n) > ndr->data_size) { \
+ return NT_STATUS_BUFFER_TOO_SMALL; \
+ } \
+} while(0)
+
+#define NDR_PULL_ALIGN(ndr, n) do { \
+ ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \
+ if (ndr->offset >= ndr->data_size) { \
+ return NT_STATUS_BUFFER_TOO_SMALL; \
+ } \
+} while(0)
+
+#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, ndr->offset+(n)))
+
+#define NDR_PUSH_ALIGN(ndr, n) do { \
+ uint32 _pad = (ndr->offset & (n-1)); \
+ while (_pad--) NDR_CHECK(ndr_push_uint8(ndr, 0)); \
+} while(0)
+
+
/* these are used to make the error checking on each element in libndr
less tedious, hopefully making the code more readable */
#define NDR_CHECK(call) do { NTSTATUS _status; \
diff --git a/source4/librpc/ndr/ndr.c b/source4/librpc/ndr/ndr.c
index 3c2ed6e55b..5add5112e7 100644
--- a/source4/librpc/ndr/ndr.c
+++ b/source4/librpc/ndr/ndr.c
@@ -50,6 +50,20 @@ struct ndr_pull *ndr_pull_init_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
return ndr;
}
+/*
+ create an ndr sub-context based on an existing context. The new context starts
+ at the current offset, with the given size limit
+*/
+NTSTATUS ndr_pull_subcontext(struct ndr_pull *ndr, struct ndr_pull *ndr2, uint32 size)
+{
+ NDR_PULL_NEED_BYTES(ndr, size);
+ *ndr2 = *ndr;
+ ndr2->data += ndr2->offset;
+ ndr2->offset = 0;
+ ndr2->data_size = size;
+ return NT_STATUS_OK;
+}
+
/* limit the remaining size of the current ndr parse structure to the
given size, starting at the given offset
diff --git a/source4/librpc/ndr/ndr_basic.c b/source4/librpc/ndr/ndr_basic.c
index b50b614b92..89c16ca76a 100644
--- a/source4/librpc/ndr/ndr_basic.c
+++ b/source4/librpc/ndr/ndr_basic.c
@@ -22,19 +22,6 @@
#include "includes.h"
-#define NDR_PULL_NEED_BYTES(ndr, n) do { \
- if ((n) > ndr->data_size || ndr->offset + (n) > ndr->data_size) { \
- return NT_STATUS_BUFFER_TOO_SMALL; \
- } \
-} while(0)
-
-#define NDR_PULL_ALIGN(ndr, n) do { \
- ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \
- if (ndr->offset >= ndr->data_size) { \
- return NT_STATUS_BUFFER_TOO_SMALL; \
- } \
-} while(0)
-
/*
parse a uint8
*/
@@ -152,13 +139,6 @@ NTSTATUS ndr_pull_GUID(struct ndr_pull *ndr, int ndr_flags, GUID *guid)
}
-#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, ndr->offset+(n)))
-
-#define NDR_PUSH_ALIGN(ndr, n) do { \
- uint32 _pad = (ndr->offset & (n-1)); \
- while (_pad--) NDR_CHECK(ndr_push_uint8(ndr, 0)); \
-} while(0)
-
/*
push a uint8
*/
diff --git a/source4/librpc/ndr/ndr_lsa.c b/source4/librpc/ndr/ndr_lsa.c
index a480e9ca62..587093ed69 100644
--- a/source4/librpc/ndr/ndr_lsa.c
+++ b/source4/librpc/ndr/ndr_lsa.c
@@ -43,6 +43,8 @@ NTSTATUS ndr_push_lsa_EnumPrivs(struct ndr_push *ndr, struct lsa_EnumPrivs *r)
NTSTATUS ndr_push_lsa_QuerySecObj(struct ndr_push *ndr, struct lsa_QuerySecObj *r)
{
+ NDR_CHECK(ndr_push_policy_handle(ndr, r->in.handle));
+ NDR_CHECK(ndr_push_uint32(ndr, r->in.sec_info));
return NT_STATUS_OK;
}
@@ -582,6 +584,16 @@ NTSTATUS ndr_pull_lsa_EnumPrivs(struct ndr_pull *ndr, struct lsa_EnumPrivs *r)
NTSTATUS ndr_pull_lsa_QuerySecObj(struct ndr_pull *ndr, struct lsa_QuerySecObj *r)
{
+ uint32 _ptr_sd;
+ NDR_CHECK(ndr_pull_uint32(ndr, &_ptr_sd));
+ if (_ptr_sd) {
+ NDR_ALLOC(ndr, r->out.sd);
+ } else {
+ r->out.sd = NULL;
+ }
+ if (r->out.sd) {
+ NDR_CHECK(ndr_pull_sec_desc_buf(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.sd));
+ }
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 109e88c84f..22a2451442 100644
--- a/source4/librpc/ndr/ndr_lsa.h
+++ b/source4/librpc/ndr/ndr_lsa.h
@@ -57,9 +57,12 @@ struct lsa_EnumPrivs {
struct lsa_QuerySecObj {
struct {
+ struct policy_handle *handle;
+ uint32 sec_info;
} in;
struct {
+ struct sec_desc_buf *sd;
NTSTATUS result;
} out;
diff --git a/source4/librpc/ndr/ndr_sec.c b/source4/librpc/ndr/ndr_sec.c
index 0341d92951..5e4afe31a5 100644
--- a/source4/librpc/ndr/ndr_sec.c
+++ b/source4/librpc/ndr/ndr_sec.c
@@ -50,6 +50,8 @@ NTSTATUS ndr_pull_security_ace(struct ndr_pull *ndr, struct security_ace *ace)
if (ace->obj->flags & SEC_ACE_OBJECT_INHERITED_PRESENT) {
NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &ace->obj->inherit_guid));
}
+ } else {
+ ace->obj = NULL;
}
@@ -354,6 +356,44 @@ void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, struct dom_sid2
ndr_print_dom_sid(ndr, name, sid);
}
+
+/*
+ print a security_ace
+*/
+void ndr_print_security_ace(struct ndr_print *ndr, const char *name, struct security_ace *ace)
+{
+ ndr_print_struct(ndr, name, "security_ace");
+ ndr->depth++;
+ ndr_print_uint8(ndr, "type", ace->type);
+ ndr_print_uint8(ndr, "flags", ace->flags);
+ ndr_print_uint32(ndr, "access_mask", ace->access_mask);
+ if (ace->obj) {
+ ndr_print_struct(ndr, name, "security_ace_obj");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "flags", ace->obj->flags);
+ ndr_print_GUID(ndr, "object_guid", &ace->obj->object_guid);
+ ndr_print_GUID(ndr, "inherit_guid", &ace->obj->inherit_guid);
+ ndr->depth--;
+ }
+ ndr_print_dom_sid(ndr, "trustee", &ace->trustee);
+ ndr->depth--;
+}
+
+/*
+ print a security_acl
+*/
+void ndr_print_security_acl(struct ndr_print *ndr, const char *name, struct security_acl *acl)
+{
+ ndr_print_struct(ndr, name, "security_acl");
+ ndr->depth++;
+ ndr_print_uint16(ndr, "revision", acl->revision);
+ ndr_print_uint32(ndr, "num_aces", acl->num_aces);
+ ndr_print_array(ndr, "aces", acl->aces,
+ sizeof(acl->aces[0]), acl->num_aces,
+ (ndr_print_fn_t) ndr_print_security_ace);
+ ndr->depth--;
+}
+
/*
print a security descriptor
*/
@@ -361,8 +401,75 @@ void ndr_print_security_descriptor(struct ndr_print *ndr,
const char *name,
struct security_descriptor *sd)
{
- ndr->print(ndr, "%-25s: ndr_print_security_descriptor not implemented",
- name);
+ ndr_print_struct(ndr, name, "security_descriptor");
+ ndr->depth++;
+ ndr_print_uint8(ndr, "revision", sd->revision);
+ ndr_print_uint16(ndr, "type", sd->type);
+ ndr_print_ptr(ndr, "owner_sid", sd->owner_sid);
+ if (sd->owner_sid) {
+ ndr_print_dom_sid(ndr, "owner_sid", sd->owner_sid);
+ }
+ ndr_print_ptr(ndr, "group_sid", sd->group_sid);
+ if (sd->group_sid) {
+ ndr_print_dom_sid(ndr, "group_sid", sd->group_sid);
+ }
+ ndr_print_ptr(ndr, "sacl", sd->sacl);
+ if (sd->sacl) {
+ ndr_print_security_acl(ndr, "sacl", sd->sacl);
+ }
+ ndr_print_ptr(ndr, "dacl", sd->dacl);
+ if (sd->dacl) {
+ ndr_print_security_acl(ndr, "dacl", sd->dacl);
+ }
+ ndr->depth--;
+}
+
+
+
+/*
+ implementation of sec_desc_buf - an encapsulated security descriptor
+*/
+NTSTATUS ndr_pull_sec_desc_buf(struct ndr_pull *ndr, int ndr_flags,
+ struct sec_desc_buf *sdbuf)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ uint32 _ptr;
+ NDR_CHECK(ndr_pull_uint32(ndr, &sdbuf->size));
+ NDR_CHECK(ndr_pull_uint32(ndr, &_ptr));
+ if (_ptr) {
+ NDR_ALLOC(ndr, sdbuf->sd);
+ } else {
+ sdbuf->sd = NULL;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (sdbuf->sd) {
+ struct ndr_pull ndr2;
+ uint32 size;
+ NDR_CHECK(ndr_pull_uint32(ndr, &size));
+ if (size != sdbuf->size) {
+ return NT_STATUS_INFO_LENGTH_MISMATCH;
+ }
+ NDR_CHECK(ndr_pull_subcontext(ndr, &ndr2, sdbuf->size));
+ NDR_CHECK(ndr_pull_security_descriptor(&ndr2, sdbuf->sd));
+ NDR_CHECK(ndr_pull_advance(ndr, sdbuf->size));
+ }
+ }
+ return NT_STATUS_OK;
}
+/*
+ print a sec_desc_buf
+*/
+void ndr_print_sec_desc_buf(struct ndr_print *ndr, const char *name,
+ struct sec_desc_buf *sdbuf)
+{
+ ndr_print_struct(ndr, name, "sec_desc_buf");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "size", sdbuf->size);
+ ndr_print_ptr(ndr, "sd", sdbuf->sd);
+ if (sdbuf->sd) {
+ ndr_print_security_descriptor(ndr, "sd", sdbuf->sd);
+ }
+}
diff --git a/source4/librpc/ndr/ndr_sec.h b/source4/librpc/ndr/ndr_sec.h
index 79ba5b1564..81a3d6a944 100644
--- a/source4/librpc/ndr/ndr_sec.h
+++ b/source4/librpc/ndr/ndr_sec.h
@@ -72,6 +72,23 @@ struct security_descriptor {
struct security_acl *dacl; /* user (discretionary) ACL */
};
+
+/*
+ a security descriptor encapsulated in a buffer.
+ It is like this IDL:
+ typedef struct {
+ uint32 size;
+ [size_is(size)] uint8 *buf;
+ } sec_desc_buf;
+*/
+struct sec_desc_buf {
+ uint32 size; /* the sd wire size - auto-generated */
+ struct security_descriptor *sd;
+};
+
+
+
+
/* query security descriptor */
struct smb_query_secdesc {
struct {
diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index 5b3844396e..726281e0d6 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -332,6 +332,31 @@ static BOOL test_EnumAccountRights(struct dcerpc_pipe *p,
return True;
}
+
+static BOOL test_QuerySecObj(struct dcerpc_pipe *p,
+ TALLOC_CTX *mem_ctx,
+ struct policy_handle *acct_handle,
+ struct dom_sid *sid)
+{
+ NTSTATUS status;
+ struct lsa_QuerySecObj r;
+
+ printf("Testing QuerySecObj\n");
+
+ r.in.handle = acct_handle;
+ r.in.sec_info = 7;
+
+ status = dcerpc_lsa_QuerySecObj(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("QuerySecObj failed - %s\n", nt_errstr(status));
+ return False;
+ }
+
+ NDR_PRINT_DEBUG(sec_desc_buf, r.out.sd);
+
+ return True;
+}
+
static BOOL test_OpenAccount(struct dcerpc_pipe *p,
TALLOC_CTX *mem_ctx,
struct policy_handle *handle,
@@ -358,6 +383,10 @@ static BOOL test_OpenAccount(struct dcerpc_pipe *p,
return False;
}
+ if (!test_QuerySecObj(p, mem_ctx, handle, &acct_handle)) {
+ return False;
+ }
+
return True;
}