diff options
Diffstat (limited to 'source4/librpc/ndr')
-rw-r--r-- | source4/librpc/ndr/libndr.h | 21 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr.c | 14 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_basic.c | 20 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_lsa.c | 12 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_lsa.h | 3 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_sec.c | 111 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_sec.h | 17 |
7 files changed, 176 insertions, 22 deletions
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 { |