diff options
author | Andrew Tridgell <tridge@samba.org> | 2003-11-08 11:21:57 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2003-11-08 11:21:57 +0000 |
commit | 7d212460a5c00b4039440c2db0dde56e7d519d66 (patch) | |
tree | 7c14238930104c5edc8711f480b3ba0095d8d687 | |
parent | 4e4a63d5185d1567c115e7cbf15022b0fbcbc870 (diff) | |
download | samba-7d212460a5c00b4039440c2db0dde56e7d519d66.tar.gz samba-7d212460a5c00b4039440c2db0dde56e7d519d66.tar.bz2 samba-7d212460a5c00b4039440c2db0dde56e7d519d66.zip |
- corrected some lsa idl
- updated lsa parse code from pidl
(This used to be commit 3983b2aee77b0e093847bfc02e02b83ab281f5dd)
-rw-r--r-- | source4/libcli/raw/rawacl.c | 6 | ||||
-rw-r--r-- | source4/librpc/idl/lsa.idl | 79 | ||||
-rw-r--r-- | source4/librpc/ndr/libndr.h | 14 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr.c | 50 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_basic.c | 26 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_lsa.c | 319 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_lsa.h | 15 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_sec.c | 25 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_sec.h | 3 | ||||
-rw-r--r-- | source4/librpc/rpc/rpc_lsa.c | 14 | ||||
-rw-r--r-- | source4/torture/rpc/lsa.c | 56 |
11 files changed, 465 insertions, 142 deletions
diff --git a/source4/libcli/raw/rawacl.c b/source4/libcli/raw/rawacl.c index c45152381d..067189d987 100644 --- a/source4/libcli/raw/rawacl.c +++ b/source4/libcli/raw/rawacl.c @@ -78,7 +78,11 @@ NTSTATUS smb_raw_query_secdesc_recv(struct cli_request *req, return NT_STATUS_INVALID_PARAMETER; } - status = ndr_pull_security_descriptor(ndr, &query->out.sd); + query->out.sd = talloc(mem_ctx, sizeof(query->out.sd)); + if (!query->out.sd) { + return NT_STATUS_NO_MEMORY; + } + status = ndr_pull_security_descriptor(ndr, query->out.sd); return NT_STATUS_OK; } diff --git a/source4/librpc/idl/lsa.idl b/source4/librpc/idl/lsa.idl index 566b78f34d..6b72d19d85 100644 --- a/source4/librpc/idl/lsa.idl +++ b/source4/librpc/idl/lsa.idl @@ -7,42 +7,51 @@ pointer_default(unique) ] interface lsarpc { + + typedef struct { + [struct_len] uint32 _len; + uint16 impersonation_level; + uint8 context_mode; + uint8 effective_only; + } lsa_QosInfo; + + typedef struct { + [struct_len] uint32 _len; + uint8 *root_dir; + unistr *object_name; + uint32 attributes; + security_descriptor *sec_desc; + lsa_QosInfo *sec_qos; + } lsa_ObjectAttribute; + + NTSTATUS lsa_OpenPolicy ( + [in] uint16 *system_name, + [in,ref] lsa_ObjectAttribute *attr, + [in] uint32 desired_access, + [out] policy_handle *handle + ); + + NTSTATUS lsa_OpenPolicy2 ( + [in] unistr *system_name, + [in,ref] lsa_ObjectAttribute *attr, + [in] uint32 desired_access, + [out,ref] policy_handle *handle + ); - typedef struct { - [struct_len] uint32 _len; - uint16 impersonation_level; - uint8 context_mode; - uint8 effective_only; - } lsa_QosInfo; + typedef struct { + dom_sid2 *sid; + } lsa_SidPtr; + + typedef struct { + uint32 num_sids; + [size_is(num_sids)] lsa_SidPtr *sids; + } lsa_SidArray; - typedef struct { - [struct_len] uint32 _len; - uint8 *root_dir; - unistr *object_name; - uint32 attributes; - security_descriptor *sec_desc; - lsa_QosInfo *sec_qos; - } lsa_ObjectAttribute; - - NTSTATUS lsa_OpenPolicy ( - [in] uint16 *system_name, - [in] [ref] lsa_ObjectAttribute *attr, - [in] uint32 desired_access, - [out] policy_handle *handle - ); - - NTSTATUS lsa_OpenPolicy2 ( - [in] unistr *system_name, - [in] [ref] lsa_ObjectAttribute *attr, - [in] uint32 desired_access, - [out] [ref] policy_handle *handle - ); - - NTSTATUS lsa_EnumSids( - [in] [ref] policy_handle *handle, - [in] uint32 start_at, - [in] [out] [ref] uint32 *num_entries, - [out] dom_sid **sids - ); + NTSTATUS lsa_EnumSids ( + [in,ref] policy_handle *handle, + [in,out,ref] uint32 *resume_handle, + [in] uint32 num_entries, + [out,ref] lsa_SidArray *sids + ); } diff --git a/source4/librpc/ndr/libndr.h b/source4/librpc/ndr/libndr.h index 0d28783a6d..870500d169 100644 --- a/source4/librpc/ndr/libndr.h +++ b/source4/librpc/ndr/libndr.h @@ -61,6 +61,12 @@ struct ndr_push_save { #define LIBNDR_FLAG_BIGENDIAN 1 +/* + flags passed to control parse flow +*/ +#define NDR_SCALARS 1 +#define NDR_BUFFERS 2 + /* 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; \ @@ -75,19 +81,23 @@ struct ndr_push_save { if (!(s)) return NT_STATUS_NO_MEMORY; \ } while (0) -#define NDR_ALLOC_N(ndr, s, n) do { \ +#define NDR_ALLOC_N_SIZE(ndr, s, n, elsize) do { \ if ((n) == 0) { \ (s) = NULL; \ } else { \ - (s) = talloc(ndr->mem_ctx, (n) * sizeof(*(s))); \ + (s) = talloc(ndr->mem_ctx, (n) * elsize); \ if (!(s)) return NT_STATUS_NO_MEMORY; \ } \ } while (0) +#define NDR_ALLOC_N(ndr, s, n) NDR_ALLOC_N_SIZE(ndr, s, n, sizeof(*(s))) /* these are used when generic fn pointers are needed for ndr push/pull fns */ typedef NTSTATUS (*ndr_push_fn_t)(struct ndr_push *, void *); typedef NTSTATUS (*ndr_pull_fn_t)(struct ndr_pull *, void *); +typedef NTSTATUS (*ndr_push_flags_fn_t)(struct ndr_push *, int ndr_flags, void *); +typedef NTSTATUS (*ndr_pull_flags_fn_t)(struct ndr_pull *, int ndr_flags, void *); + /* now pull in the individual parsers */ #include "librpc/ndr/ndr_sec.h" #include "librpc/ndr/ndr_misc.h" diff --git a/source4/librpc/ndr/ndr.c b/source4/librpc/ndr/ndr.c index 4e5f199835..dabe75d5ac 100644 --- a/source4/librpc/ndr/ndr.c +++ b/source4/librpc/ndr/ndr.c @@ -185,3 +185,53 @@ NTSTATUS ndr_push_set_offset(struct ndr_push *ndr, uint32 ofs) ndr->offset = ofs; return NT_STATUS_OK; } + +/* + push a generic array +*/ +NTSTATUS ndr_push_array(struct ndr_push *ndr, int ndr_flags, void *base, + size_t elsize, uint32 count, + NTSTATUS (*push_fn)(struct ndr_push *, int, void *)) +{ + int i; + char *p = base; + NDR_CHECK(ndr_push_uint32(ndr, count)); + for (i=0;i<count;i++) { + NDR_CHECK(push_fn(ndr, ndr_flags, p)); + p += elsize; + } + return NT_STATUS_OK; +} + +/* + pull a generic array +*/ +NTSTATUS ndr_pull_array(struct ndr_pull *ndr, int ndr_flags, void **base, + size_t elsize, uint32 count, + NTSTATUS (*pull_fn)(struct ndr_pull *, int, void *)) +{ + int i; + uint32 max_count; + char *p; + NDR_ALLOC_N_SIZE(ndr, *base, count, elsize); + p = *base; + NDR_CHECK(ndr_pull_uint32(ndr, &max_count)); + if (max_count != count) { + /* maybe we can cope with this? */ + return NT_STATUS_INVALID_PARAMETER; + } + if (!(ndr_flags & NDR_SCALARS)) goto buffers; + for (i=0;i<count;i++) { + NDR_CHECK(pull_fn(ndr, NDR_SCALARS, p)); + p += elsize; + } + if (!(ndr_flags & NDR_BUFFERS)) goto done; +buffers: + p = *base; + for (i=0;i<count;i++) { + NDR_CHECK(pull_fn(ndr, NDR_BUFFERS, p)); + p += elsize; + } +done: + return NT_STATUS_OK; +} diff --git a/source4/librpc/ndr/ndr_basic.c b/source4/librpc/ndr/ndr_basic.c index 3bd75e7c0d..0597bcab00 100644 --- a/source4/librpc/ndr/ndr_basic.c +++ b/source4/librpc/ndr/ndr_basic.c @@ -243,6 +243,32 @@ NTSTATUS ndr_push_unistr(struct ndr_push *ndr, const char *s) } /* + pull a comformant, variable ucs2 string from the wire into a C string +*/ +NTSTATUS ndr_pull_unistr(struct ndr_pull *ndr, const char **s) +{ + char *ws, *as=NULL; + uint32 len1, ofs, len2; + + NDR_CHECK(ndr_pull_uint32(ndr, &len1)); + NDR_CHECK(ndr_pull_uint32(ndr, &ofs)); + NDR_CHECK(ndr_pull_uint32(ndr, &len2)); + if (len2 > len1) { + return NT_STATUS_INVALID_PARAMETER; + } + NDR_ALLOC_N(ndr, ws, (len1+1)*2); + NDR_CHECK(ndr_pull_bytes(ndr, ws, len1*2)); + SSVAL(ws, len1*2, 0); + SSVAL(ws, len2*2, 0); + pull_ucs2_talloc(ndr->mem_ctx, &as, (const smb_ucs2_t *)ws); + if (!as) { + return NT_STATUS_INVALID_PARAMETER; + } + *s = as; + return NT_STATUS_OK; +} + +/* push a 4 byte offset pointer, remembering where we are so we can later fill in the correct value */ diff --git a/source4/librpc/ndr/ndr_lsa.c b/source4/librpc/ndr/ndr_lsa.c index bde450687e..ff395f5699 100644 --- a/source4/librpc/ndr/ndr_lsa.c +++ b/source4/librpc/ndr/ndr_lsa.c @@ -23,95 +23,63 @@ #include "includes.h" -/* - parse a openpolicy -*/ -NTSTATUS ndr_pull_lsa_OpenPolicy(struct ndr_pull *ndr, - struct lsa_OpenPolicy *r) -{ - NDR_ALLOC(ndr, r->out.handle); - NDR_CHECK(ndr_pull_policy_handle(ndr, r->out.handle)); - NDR_CHECK(ndr_pull_status(ndr, &r->out.result)); - return NT_STATUS_OK; -} - -/* - parse a openpolicy2 -*/ -NTSTATUS ndr_pull_lsa_OpenPolicy2(struct ndr_pull *ndr, - struct lsa_OpenPolicy2 *r) -{ - NDR_ALLOC(ndr, r->out.handle); - NDR_CHECK(ndr_pull_policy_handle(ndr, r->out.handle)); - NDR_CHECK(ndr_pull_status(ndr, &r->out.result)); - return NT_STATUS_OK; -} - - -/* - pull a EnumSids -*/ -NTSTATUS ndr_pull_lsa_EnumSids(struct ndr_pull *ndr, - struct lsa_EnumSids *r) -{ - uint32 nptrs, asize, i, ptr; - - NDR_CHECK(ndr_pull_uint32(ndr, &r->out.num_entries)); - NDR_CHECK(ndr_pull_uint32(ndr, &nptrs)); - NDR_CHECK(ndr_pull_uint32(ndr, &ptr)); - if (!ptr) goto done; - - NDR_CHECK(ndr_pull_uint32(ndr, &asize)); - NDR_ALLOC_N(ndr, r->out.sids, nptrs); - for (i=0;i<nptrs;i++) { - NDR_CHECK(ndr_pull_uint32(ndr, &ptr)); - if (ptr) { - NDR_ALLOC(ndr, r->out.sids[i]); - } else { - r->out.sids[i] = NULL; - } - } - for (i=0;i<nptrs;i++) { - if (r->out.sids[i]) NDR_CHECK(ndr_pull_dom_sid2(ndr, r->out.sids[i])); - } - -done: - NDR_CHECK(ndr_pull_status(ndr, &r->out.result)); - return NT_STATUS_OK; -} - - /* parser auto-generated by pidl */ -static NTSTATUS ndr_push_lsa_QosInfo(struct ndr_push *ndr, struct lsa_QosInfo *r) +static NTSTATUS ndr_push_lsa_QosInfo(struct ndr_push *ndr, int ndr_flags, struct lsa_QosInfo *r) { - struct ndr_push_save len_save1, len_save2, len_save3; - ndr_push_save(ndr, &len_save1); + struct ndr_push_save _save1, _save2, _save3; + ndr_push_save(ndr, &_save1); + if (!(ndr_flags & NDR_SCALARS)) goto buffers; NDR_CHECK(ndr_push_align_uint32(ndr)); - ndr_push_save(ndr, &len_save2); + ndr_push_save(ndr, &_save2); NDR_CHECK(ndr_push_uint32(ndr, 0)); NDR_CHECK(ndr_push_uint16(ndr, r->impersonation_level)); NDR_CHECK(ndr_push_uint8(ndr, r->context_mode)); NDR_CHECK(ndr_push_uint8(ndr, r->effective_only)); - ndr_push_save(ndr, &len_save3); - ndr_push_restore(ndr, &len_save2); - NDR_CHECK(ndr_push_uint32(ndr, len_save3.offset - len_save1.offset)); - ndr_push_restore(ndr, &len_save3); +buffers: + if (!(ndr_flags & NDR_BUFFERS)) goto done; + ndr_push_save(ndr, &_save3); + ndr_push_restore(ndr, &_save2); + NDR_CHECK(ndr_push_uint32(ndr, _save3.offset - _save1.offset)); + ndr_push_restore(ndr, &_save3); +done: return NT_STATUS_OK; } -static NTSTATUS ndr_push_lsa_ObjectAttribute(struct ndr_push *ndr, struct lsa_ObjectAttribute *r) +static NTSTATUS ndr_pull_lsa_QosInfo(struct ndr_pull *ndr, int ndr_flags, struct lsa_QosInfo *r) { - struct ndr_push_save len_save1, len_save2, len_save3; - ndr_push_save(ndr, &len_save1); + uint32 _size; + struct ndr_pull_save _save; + ndr_pull_save(ndr, &_save); + if (!(ndr_flags & NDR_SCALARS)) goto buffers; + NDR_CHECK(ndr_pull_uint32(ndr, &_size)); + NDR_CHECK(ndr_pull_limit_size(ndr, _size, 4)); + NDR_CHECK(ndr_pull_uint16(ndr, &r->impersonation_level)); + NDR_CHECK(ndr_pull_uint8(ndr, &r->context_mode)); + NDR_CHECK(ndr_pull_uint8(ndr, &r->effective_only)); +buffers: + if (!(ndr_flags & NDR_BUFFERS)) goto done; + ndr_pull_restore(ndr, &_save); + NDR_CHECK(ndr_pull_advance(ndr, _size)); +done: + return NT_STATUS_OK; +} + +static NTSTATUS ndr_push_lsa_ObjectAttribute(struct ndr_push *ndr, int ndr_flags, struct lsa_ObjectAttribute *r) +{ + struct ndr_push_save _save1, _save2, _save3; + ndr_push_save(ndr, &_save1); + if (!(ndr_flags & NDR_SCALARS)) goto buffers; NDR_CHECK(ndr_push_align_uint32(ndr)); - ndr_push_save(ndr, &len_save2); + ndr_push_save(ndr, &_save2); NDR_CHECK(ndr_push_uint32(ndr, 0)); NDR_CHECK(ndr_push_ptr(ndr, r->root_dir)); NDR_CHECK(ndr_push_ptr(ndr, r->object_name)); NDR_CHECK(ndr_push_uint32(ndr, r->attributes)); NDR_CHECK(ndr_push_ptr(ndr, r->sec_desc)); NDR_CHECK(ndr_push_ptr(ndr, r->sec_qos)); +buffers: + if (!(ndr_flags & NDR_BUFFERS)) goto done; if (r->root_dir) { NDR_CHECK(ndr_push_uint8(ndr, *r->root_dir)); } @@ -122,12 +90,70 @@ static NTSTATUS ndr_push_lsa_ObjectAttribute(struct ndr_push *ndr, struct lsa_Ob NDR_CHECK(ndr_push_security_descriptor(ndr, r->sec_desc)); } if (r->sec_qos) { - NDR_CHECK(ndr_push_lsa_QosInfo(ndr, r->sec_qos)); + NDR_CHECK(ndr_push_lsa_QosInfo(ndr, ndr_flags, r->sec_qos)); } - ndr_push_save(ndr, &len_save3); - ndr_push_restore(ndr, &len_save2); - NDR_CHECK(ndr_push_uint32(ndr, len_save3.offset - len_save1.offset)); - ndr_push_restore(ndr, &len_save3); + ndr_push_save(ndr, &_save3); + ndr_push_restore(ndr, &_save2); + NDR_CHECK(ndr_push_uint32(ndr, _save3.offset - _save1.offset)); + ndr_push_restore(ndr, &_save3); +done: + return NT_STATUS_OK; +} + +static NTSTATUS ndr_pull_lsa_ObjectAttribute(struct ndr_pull *ndr, int ndr_flags, struct lsa_ObjectAttribute *r) +{ + uint32 _ptr_root_dir; + uint32 _ptr_object_name; + uint32 _ptr_sec_desc; + uint32 _ptr_sec_qos; + uint32 _size; + struct ndr_pull_save _save; + ndr_pull_save(ndr, &_save); + if (!(ndr_flags & NDR_SCALARS)) goto buffers; + NDR_CHECK(ndr_pull_uint32(ndr, &_size)); + NDR_CHECK(ndr_pull_limit_size(ndr, _size, 4)); + NDR_CHECK(ndr_pull_uint32(ndr, &_ptr_root_dir)); + if (_ptr_root_dir) { + NDR_ALLOC(ndr, r->root_dir); + } else { + r->root_dir = NULL; + } + NDR_CHECK(ndr_pull_uint32(ndr, &_ptr_object_name)); + if (_ptr_object_name) { + NDR_ALLOC(ndr, r->object_name); + } else { + r->object_name = NULL; + } + NDR_CHECK(ndr_pull_uint32(ndr, &r->attributes)); + NDR_CHECK(ndr_pull_uint32(ndr, &_ptr_sec_desc)); + if (_ptr_sec_desc) { + NDR_ALLOC(ndr, r->sec_desc); + } else { + r->sec_desc = NULL; + } + NDR_CHECK(ndr_pull_uint32(ndr, &_ptr_sec_qos)); + if (_ptr_sec_qos) { + NDR_ALLOC(ndr, r->sec_qos); + } else { + r->sec_qos = NULL; + } +buffers: + if (!(ndr_flags & NDR_BUFFERS)) goto done; + if (r->root_dir) { + NDR_CHECK(ndr_pull_uint8(ndr, r->root_dir)); + } + if (r->object_name) { + NDR_CHECK(ndr_pull_unistr(ndr, &r->object_name)); + } + if (r->sec_desc) { + NDR_CHECK(ndr_pull_security_descriptor(ndr, r->sec_desc)); + } + if (r->sec_qos) { + NDR_CHECK(ndr_pull_lsa_QosInfo(ndr, ndr_flags, r->sec_qos)); + } + ndr_pull_restore(ndr, &_save); + NDR_CHECK(ndr_pull_advance(ndr, _size)); +done: return NT_STATUS_OK; } @@ -137,7 +163,7 @@ NTSTATUS ndr_push_lsa_OpenPolicy(struct ndr_push *ndr, struct lsa_OpenPolicy *r) if (r->in.system_name) { NDR_CHECK(ndr_push_uint16(ndr, *r->in.system_name)); } - NDR_CHECK(ndr_push_lsa_ObjectAttribute(ndr, r->in.attr)); + NDR_CHECK(ndr_push_lsa_ObjectAttribute(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.attr)); NDR_CHECK(ndr_push_uint32(ndr, r->in.desired_access)); return NT_STATUS_OK; @@ -149,19 +175,156 @@ NTSTATUS ndr_push_lsa_OpenPolicy2(struct ndr_push *ndr, struct lsa_OpenPolicy2 * if (r->in.system_name) { NDR_CHECK(ndr_push_unistr(ndr, r->in.system_name)); } - NDR_CHECK(ndr_push_lsa_ObjectAttribute(ndr, r->in.attr)); + NDR_CHECK(ndr_push_lsa_ObjectAttribute(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.attr)); NDR_CHECK(ndr_push_uint32(ndr, r->in.desired_access)); return NT_STATUS_OK; } +static NTSTATUS ndr_push_lsa_SidPtr(struct ndr_push *ndr, int ndr_flags, struct lsa_SidPtr *r) +{ + if (!(ndr_flags & NDR_SCALARS)) goto buffers; + NDR_CHECK(ndr_push_ptr(ndr, r->sid)); +buffers: + if (!(ndr_flags & NDR_BUFFERS)) goto done; + if (r->sid) { + NDR_CHECK(ndr_push_dom_sid2(ndr, r->sid)); + } +done: + return NT_STATUS_OK; +} + +static NTSTATUS ndr_pull_lsa_SidPtr(struct ndr_pull *ndr, int ndr_flags, struct lsa_SidPtr *r) +{ + uint32 _ptr_sid; + if (!(ndr_flags & NDR_SCALARS)) goto buffers; + 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; + if (r->sid) { + NDR_CHECK(ndr_pull_dom_sid2(ndr, r->sid)); + } +done: + return NT_STATUS_OK; +} + +static NTSTATUS ndr_push_lsa_SidArray(struct ndr_push *ndr, int ndr_flags, struct lsa_SidArray *r) +{ + if (!(ndr_flags & NDR_SCALARS)) goto buffers; + NDR_CHECK(ndr_push_uint32(ndr, r->num_sids)); + NDR_CHECK(ndr_push_ptr(ndr, r->sids)); +buffers: + if (!(ndr_flags & NDR_BUFFERS)) goto done; + if (r->sids) { + NDR_CHECK(ndr_push_array(ndr, ndr_flags, r->sids, sizeof(r->sids[0]), r->num_sids, (ndr_push_flags_fn_t)ndr_push_lsa_SidPtr)); + } +done: + return NT_STATUS_OK; +} + +static NTSTATUS ndr_pull_lsa_SidArray(struct ndr_pull *ndr, int ndr_flags, struct lsa_SidArray *r) +{ + uint32 _ptr_sids; + if (!(ndr_flags & NDR_SCALARS)) goto buffers; + NDR_CHECK(ndr_pull_uint32(ndr, &r->num_sids)); + NDR_CHECK(ndr_pull_uint32(ndr, &_ptr_sids)); + if (_ptr_sids) { + NDR_ALLOC(ndr, r->sids); + } else { + r->sids = NULL; + } +buffers: + if (!(ndr_flags & NDR_BUFFERS)) goto done; + if (r->sids) { + NDR_CHECK(ndr_pull_array(ndr, ndr_flags, (void **)&r->sids, sizeof(r->sids[0]), r->num_sids, (ndr_pull_flags_fn_t)ndr_pull_lsa_SidPtr)); + } +done: + return NT_STATUS_OK; +} + NTSTATUS ndr_push_lsa_EnumSids(struct ndr_push *ndr, struct lsa_EnumSids *r) { NDR_CHECK(ndr_push_policy_handle(ndr, r->in.handle)); - NDR_CHECK(ndr_push_uint32(ndr, r->in.start_at)); + NDR_CHECK(ndr_push_uint32(ndr, r->in.resume_handle)); NDR_CHECK(ndr_push_uint32(ndr, r->in.num_entries)); return NT_STATUS_OK; } +/* + parse a openpolicy +*/ +NTSTATUS ndr_pull_lsa_OpenPolicy(struct ndr_pull *ndr, + struct lsa_OpenPolicy *r) +{ + NDR_ALLOC(ndr, r->out.handle); + NDR_CHECK(ndr_pull_policy_handle(ndr, r->out.handle)); + NDR_CHECK(ndr_pull_status(ndr, &r->out.result)); + return NT_STATUS_OK; +} + +/* + parse a openpolicy2 +*/ +NTSTATUS ndr_pull_lsa_OpenPolicy2(struct ndr_pull *ndr, + struct lsa_OpenPolicy2 *r) +{ + NDR_ALLOC(ndr, r->out.handle); + NDR_CHECK(ndr_pull_policy_handle(ndr, r->out.handle)); + NDR_CHECK(ndr_pull_status(ndr, &r->out.result)); + return NT_STATUS_OK; +} + +#if 0 +/* + pull a lsa_SidArray +*/ +static NTSTATUS ndr_pull_lsa_SidArray(struct ndr_pull *ndr, + struct lsa_SidArray *r) +{ + uint32 ptr; + + NDR_CHECK(ndr_pull_uint32(ndr, &r->num_sids)); + NDR_CHECK(ndr_pull_uint32(ndr, &ptr)); + if (ptr) { + uint32 asize, i; + + NDR_CHECK(ndr_pull_uint32(ndr, &asize)); + NDR_ALLOC_N(ndr, r->sids, asize); + for (i=0;i<asize;i++) { + NDR_CHECK(ndr_pull_uint32(ndr, &ptr)); + if (ptr) { + NDR_ALLOC(ndr, r->sids[i]); + } else { + r->sids[i] = NULL; + } + } + + for (i=0;i<asize;i++) { + if (r->sids[i]) { + NDR_CHECK(ndr_pull_dom_sid2(ndr, r->sids[i])); + } + } + } + return NT_STATUS_OK; +} +#endif + +/* + pull a EnumSids +*/ +NTSTATUS ndr_pull_lsa_EnumSids(struct ndr_pull *ndr, + struct lsa_EnumSids *r) +{ + NDR_CHECK(ndr_pull_uint32(ndr, &r->out.resume_handle)); + NDR_ALLOC(ndr, r->out.sids); + NDR_CHECK(ndr_pull_lsa_SidArray(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.sids)); + NDR_CHECK(ndr_pull_status(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 402227a8bf..ab9b0ea164 100644 --- a/source4/librpc/ndr/ndr_lsa.h +++ b/source4/librpc/ndr/ndr_lsa.h @@ -64,16 +64,25 @@ struct lsa_OpenPolicy2 { }; +struct lsa_SidPtr { + struct dom_sid2 *sid; +}; + +struct lsa_SidArray { + uint32 num_sids; + struct lsa_SidPtr *sids; +}; + struct lsa_EnumSids { struct { struct policy_handle *handle; - uint32 start_at; + uint32 resume_handle; uint32 num_entries; } in; struct { - uint32 num_entries; - struct dom_sid **sids; + uint32 resume_handle; + struct lsa_SidArray *sids; NTSTATUS result; } out; diff --git a/source4/librpc/ndr/ndr_sec.c b/source4/librpc/ndr/ndr_sec.c index 31cf823e0d..b83bf87771 100644 --- a/source4/librpc/ndr/ndr_sec.c +++ b/source4/librpc/ndr/ndr_sec.c @@ -174,16 +174,14 @@ NTSTATUS ndr_pull_dom_sid_ofs(struct ndr_pull *ndr, struct dom_sid **sid) parse a security descriptor */ NTSTATUS ndr_pull_security_descriptor(struct ndr_pull *ndr, - struct security_descriptor **sd) + struct security_descriptor *sd) { - NDR_ALLOC(ndr, *sd); - - NDR_CHECK(ndr_pull_uint8(ndr, &(*sd)->revision)); - NDR_CHECK(ndr_pull_uint16(ndr, &(*sd)->type)); - NDR_CHECK(ndr_pull_dom_sid_ofs(ndr, &(*sd)->owner_sid)); - NDR_CHECK(ndr_pull_dom_sid_ofs(ndr, &(*sd)->group_sid)); - NDR_CHECK(ndr_pull_security_acl_ofs(ndr, &(*sd)->sacl)); - NDR_CHECK(ndr_pull_security_acl_ofs(ndr, &(*sd)->dacl)); + NDR_CHECK(ndr_pull_uint8(ndr, &sd->revision)); + NDR_CHECK(ndr_pull_uint16(ndr, &sd->type)); + NDR_CHECK(ndr_pull_dom_sid_ofs(ndr, &sd->owner_sid)); + NDR_CHECK(ndr_pull_dom_sid_ofs(ndr, &sd->group_sid)); + NDR_CHECK(ndr_pull_security_acl_ofs(ndr, &sd->sacl)); + NDR_CHECK(ndr_pull_security_acl_ofs(ndr, &sd->dacl)); return NT_STATUS_OK; } @@ -265,6 +263,15 @@ NTSTATUS ndr_push_dom_sid(struct ndr_push *ndr, struct dom_sid *sid) return NT_STATUS_OK; } +/* + parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field +*/ +NTSTATUS ndr_push_dom_sid2(struct ndr_push *ndr, struct dom_sid *sid) +{ + NDR_CHECK(ndr_push_uint32(ndr, sid->num_auths)); + return ndr_push_dom_sid(ndr, sid); +} + /* generate a ndr security descriptor diff --git a/source4/librpc/ndr/ndr_sec.h b/source4/librpc/ndr/ndr_sec.h index 0c9d542006..79ba5b1564 100644 --- a/source4/librpc/ndr/ndr_sec.h +++ b/source4/librpc/ndr/ndr_sec.h @@ -31,6 +31,9 @@ struct dom_sid { uint32 *sub_auths; }; +/* use the same structure for dom_sid2 as dom_sid */ +#define dom_sid2 dom_sid + /* an access control element */ struct security_ace { uint8 type; /* xxxx_xxxx_ACE_TYPE - e.g allowed / denied etc */ diff --git a/source4/librpc/rpc/rpc_lsa.c b/source4/librpc/rpc/rpc_lsa.c index 2aa3f78730..8a627aa562 100644 --- a/source4/librpc/rpc/rpc_lsa.c +++ b/source4/librpc/rpc/rpc_lsa.c @@ -118,17 +118,17 @@ done: NTSTATUS dcerpc_lsa_EnumSids(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle, - uint32 resume_handle, - uint32 *num_entries, - struct dom_sid ***sids) + uint32 *resume_handle, + uint32 num_entries, + struct lsa_SidArray *sids) { struct lsa_EnumSids r; NTSTATUS status; /* fill the .in side of the call */ r.in.handle = handle; - r.in.start_at = 0; - r.in.num_entries = *num_entries; + r.in.resume_handle = *resume_handle; + r.in.num_entries = num_entries; /* make the call */ status = dcerpc_ndr_request(p, LSA_ENUM_ACCOUNTS, mem_ctx, @@ -140,8 +140,8 @@ NTSTATUS dcerpc_lsa_EnumSids(struct dcerpc_pipe *p, } /* and extract the .out parameters */ - *num_entries = r.out.num_entries; - *sids = r.out.sids; + *resume_handle = r.out.resume_handle; + *sids = *r.out.sids; status = r.out.result; done: diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index a542cad636..5cf56acd30 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -22,7 +22,7 @@ #include "includes.h" /* - this really shouldn't be here .... + these really shouldn't be here .... */ static char *lsa_sid_string_talloc(TALLOC_CTX *mem_ctx, struct dom_sid *sid) { @@ -53,6 +53,31 @@ static char *lsa_sid_string_talloc(TALLOC_CTX *mem_ctx, struct dom_sid *sid) return ret; } +static int dom_sid_compare(struct dom_sid *sid1, struct dom_sid *sid2) +{ + int i; + + if (sid1 == sid2) return 0; + if (!sid1) return -1; + if (!sid2) return 1; + + /* Compare most likely different rids, first: i.e start at end */ + if (sid1->num_auths != sid2->num_auths) + return sid1->num_auths - sid2->num_auths; + + for (i = sid1->num_auths-1; i >= 0; --i) + if (sid1->sub_auths[i] != sid2->sub_auths[i]) + return sid1->sub_auths[i] - sid2->sub_auths[i]; + + if (sid1->sid_rev_num != sid2->sid_rev_num) + return sid1->sid_rev_num - sid2->sid_rev_num; + + for (i = 0; i < 6; i++) + if (sid1->id_auth[i] != sid2->id_auth[i]) + return sid1->id_auth[i] - sid2->id_auth[i]; + + return 0; +} static BOOL test_OpenPolicy(struct dcerpc_pipe *p) { @@ -124,24 +149,41 @@ static BOOL test_EnumSids(struct dcerpc_pipe *p, struct policy_handle *handle) { NTSTATUS status; - struct dom_sid **sids; - uint32 num_entries = 100; + struct lsa_SidArray sids1, sids2; + uint32 resume_handle; int i; printf("\ntesting EnumSids\n"); - status = dcerpc_lsa_EnumSids(p, mem_ctx, handle, 0, &num_entries, &sids); + resume_handle = 0; + status = dcerpc_lsa_EnumSids(p, mem_ctx, handle, &resume_handle, 100, &sids1); if (!NT_STATUS_IS_OK(status)) { printf("EnumSids failed - %s\n", nt_errstr(status)); return False; } - printf("Got %d sids\n", num_entries); + printf("Got %d sids resume_handle=%u\n", sids1.num_sids, resume_handle); - for (i=0;i<num_entries;i++) { - printf("%s\n", lsa_sid_string_talloc(mem_ctx, sids[i])); + for (i=0;i<sids1.num_sids;i++) { + printf("%s\n", lsa_sid_string_talloc(mem_ctx, sids1.sids[i].sid)); + } + + if (sids1.num_sids < 3) { + return True; } + printf("trying partial listing (asking for 1 at 2)\n"); + resume_handle = 2; + status = dcerpc_lsa_EnumSids(p, mem_ctx, handle, &resume_handle, 1, &sids2); + if (!NT_STATUS_IS_OK(status)) { + printf("EnumSids failed - %s\n", nt_errstr(status)); + return False; + } + + if (sids2.num_sids != 1) { + printf("Returned wrong number of entries (%d)\n", sids2.num_sids); + return False; + } return True; } |