diff options
-rw-r--r-- | source4/librpc/idl/samr.idl | 33 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_samr.c | 116 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_samr.h | 37 | ||||
-rw-r--r-- | source4/librpc/rpc/rpc_samr.c | 24 | ||||
-rw-r--r-- | source4/torture/rpc/samr.c | 94 |
5 files changed, 275 insertions, 29 deletions
diff --git a/source4/librpc/idl/samr.idl b/source4/librpc/idl/samr.idl index ee910361e9..c703f99817 100644 --- a/source4/librpc/idl/samr.idl +++ b/source4/librpc/idl/samr.idl @@ -223,7 +223,13 @@ /************************/ /* Function 0x0f */ - NTSTATUS samr_ENUM_DOM_ALIASES(); + NTSTATUS samr_EnumDomainAliases( + [in,ref] policy_handle *handle, + [in,out,ref] uint32 *resume_handle, + [in] uint32 max_size, + [out] samr_SamArray *sam, + [out,ref] uint32 num_entries + ); /************************/ /* Function 0x10 */ @@ -299,7 +305,12 @@ /************************/ /* Function 0x22 */ - NTSTATUS samr_OPEN_USER(); + NTSTATUS samr_OpenUser( + [in,ref] policy_handle *handle, + [in] uint32 access_mask, + [in] uint32 rid, + [out,ref] policy_handle *acct_handle + ); /************************/ /* Function 0x23 */ @@ -307,7 +318,23 @@ /************************/ /* Function 0x24 */ - NTSTATUS samr_QUERY_USERINFO(); + typedef struct { + samr_Name username; + samr_Name full_name; + uint32 primary_group_rid; + samr_Name description; + samr_Name comment; + } samr_UserInfo1; + + typedef union { + case(1) samr_UserInfo1 info1; + } samr_UserInfo; + + NTSTATUS samr_QueryUserInfo( + [in,ref] policy_handle *handle, + [in] uint16 level, + [out,switch_is(level)] samr_UserInfo *info + ); /************************/ /* Function 0x25 */ diff --git a/source4/librpc/ndr/ndr_samr.c b/source4/librpc/ndr/ndr_samr.c index b7a515d62c..95c38e70c1 100644 --- a/source4/librpc/ndr/ndr_samr.c +++ b/source4/librpc/ndr/ndr_samr.c @@ -130,8 +130,11 @@ NTSTATUS ndr_push_samr_CREATE_DOM_ALIAS(struct ndr_push *ndr, struct samr_CREATE return NT_STATUS_OK; } -NTSTATUS ndr_push_samr_ENUM_DOM_ALIASES(struct ndr_push *ndr, struct samr_ENUM_DOM_ALIASES *r) +NTSTATUS ndr_push_samr_EnumDomainAliases(struct ndr_push *ndr, struct samr_EnumDomainAliases *r) { + NDR_CHECK(ndr_push_policy_handle(ndr, r->in.handle)); + NDR_CHECK(ndr_push_uint32(ndr, *r->in.resume_handle)); + NDR_CHECK(ndr_push_uint32(ndr, r->in.max_size)); return NT_STATUS_OK; } @@ -244,8 +247,11 @@ NTSTATUS ndr_push_samr_GET_MEMBERS_IN_ALIAS(struct ndr_push *ndr, struct samr_GE return NT_STATUS_OK; } -NTSTATUS ndr_push_samr_OPEN_USER(struct ndr_push *ndr, struct samr_OPEN_USER *r) +NTSTATUS ndr_push_samr_OpenUser(struct ndr_push *ndr, struct samr_OpenUser *r) { + NDR_CHECK(ndr_push_policy_handle(ndr, r->in.handle)); + NDR_CHECK(ndr_push_uint32(ndr, r->in.access_mask)); + NDR_CHECK(ndr_push_uint32(ndr, r->in.rid)); return NT_STATUS_OK; } @@ -256,8 +262,10 @@ NTSTATUS ndr_push_samr_DELETE_DOM_USER(struct ndr_push *ndr, struct samr_DELETE_ return NT_STATUS_OK; } -NTSTATUS ndr_push_samr_QUERY_USERINFO(struct ndr_push *ndr, struct samr_QUERY_USERINFO *r) +NTSTATUS ndr_push_samr_QueryUserInfo(struct ndr_push *ndr, struct samr_QueryUserInfo *r) { + NDR_CHECK(ndr_push_policy_handle(ndr, r->in.handle)); + NDR_CHECK(ndr_push_uint16(ndr, r->in.level)); return NT_STATUS_OK; } @@ -972,8 +980,20 @@ NTSTATUS ndr_pull_samr_CREATE_DOM_ALIAS(struct ndr_pull *ndr, struct samr_CREATE return NT_STATUS_OK; } -NTSTATUS ndr_pull_samr_ENUM_DOM_ALIASES(struct ndr_pull *ndr, struct samr_ENUM_DOM_ALIASES *r) +NTSTATUS ndr_pull_samr_EnumDomainAliases(struct ndr_pull *ndr, struct samr_EnumDomainAliases *r) { + uint32 _ptr_sam; + NDR_CHECK(ndr_pull_uint32(ndr, r->out.resume_handle)); + NDR_CHECK(ndr_pull_uint32(ndr, &_ptr_sam)); + if (_ptr_sam) { + NDR_ALLOC(ndr, r->out.sam); + } else { + r->out.sam = NULL; + } + if (r->out.sam) { + NDR_CHECK(ndr_pull_samr_SamArray(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.sam)); + } + NDR_CHECK(ndr_pull_uint32(ndr, &r->out.num_entries)); NDR_CHECK(ndr_pull_NTSTATUS(ndr, &r->out.result)); return NT_STATUS_OK; @@ -1105,8 +1125,9 @@ NTSTATUS ndr_pull_samr_GET_MEMBERS_IN_ALIAS(struct ndr_pull *ndr, struct samr_GE return NT_STATUS_OK; } -NTSTATUS ndr_pull_samr_OPEN_USER(struct ndr_pull *ndr, struct samr_OPEN_USER *r) +NTSTATUS ndr_pull_samr_OpenUser(struct ndr_pull *ndr, struct samr_OpenUser *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; @@ -1119,8 +1140,66 @@ NTSTATUS ndr_pull_samr_DELETE_DOM_USER(struct ndr_pull *ndr, struct samr_DELETE_ return NT_STATUS_OK; } -NTSTATUS ndr_pull_samr_QUERY_USERINFO(struct ndr_pull *ndr, struct samr_QUERY_USERINFO *r) +static NTSTATUS ndr_pull_samr_UserInfo1(struct ndr_pull *ndr, int ndr_flags, struct samr_UserInfo1 *r) +{ + if (!(ndr_flags & NDR_SCALARS)) goto buffers; + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_samr_Name(ndr, NDR_SCALARS, &r->username)); + NDR_CHECK(ndr_pull_samr_Name(ndr, NDR_SCALARS, &r->full_name)); + NDR_CHECK(ndr_pull_uint32(ndr, &r->primary_group_rid)); + NDR_CHECK(ndr_pull_samr_Name(ndr, NDR_SCALARS, &r->description)); + NDR_CHECK(ndr_pull_samr_Name(ndr, NDR_SCALARS, &r->comment)); +buffers: + if (!(ndr_flags & NDR_BUFFERS)) goto done; + NDR_CHECK(ndr_pull_samr_Name(ndr, NDR_BUFFERS, &r->username)); + NDR_CHECK(ndr_pull_samr_Name(ndr, NDR_BUFFERS, &r->full_name)); + NDR_CHECK(ndr_pull_samr_Name(ndr, NDR_BUFFERS, &r->description)); + NDR_CHECK(ndr_pull_samr_Name(ndr, NDR_BUFFERS, &r->comment)); +done: + return NT_STATUS_OK; +} + +static NTSTATUS ndr_pull_samr_UserInfo(struct ndr_pull *ndr, int ndr_flags, uint16 *level, union samr_UserInfo *r) +{ + if (!(ndr_flags & NDR_SCALARS)) goto buffers; + NDR_CHECK(ndr_pull_uint16(ndr, level)); + switch (*level) { + case 1: { + NDR_CHECK(ndr_pull_samr_UserInfo1(ndr, NDR_SCALARS, &r->info1)); + break; } + + default: + return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", *level); + } +buffers: + if (!(ndr_flags & NDR_BUFFERS)) goto done; + switch (*level) { + case 1: + NDR_CHECK(ndr_pull_samr_UserInfo1(ndr, NDR_BUFFERS, &r->info1)); + break; + + default: + return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", *level); + } +done: + return NT_STATUS_OK; +} + +NTSTATUS ndr_pull_samr_QueryUserInfo(struct ndr_pull *ndr, struct samr_QueryUserInfo *r) { + uint32 _ptr_info; + NDR_CHECK(ndr_pull_uint32(ndr, &_ptr_info)); + if (_ptr_info) { + NDR_ALLOC(ndr, r->out.info); + } else { + r->out.info = NULL; + } + if (r->out.info) { + { uint16 _level; + NDR_CHECK(ndr_pull_samr_UserInfo(ndr, NDR_SCALARS|NDR_BUFFERS, &_level, r->out.info)); + if (((NDR_SCALARS|NDR_BUFFERS) & NDR_SCALARS) && (_level != r->in.level)) return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u in info"); + } + } NDR_CHECK(ndr_pull_NTSTATUS(ndr, &r->out.result)); return NT_STATUS_OK; @@ -1568,3 +1647,28 @@ void ndr_print_samr_DomainInfo(struct ndr_print *ndr, const char *name, uint16 l } } +void ndr_print_samr_UserInfo1(struct ndr_print *ndr, const char *name, struct samr_UserInfo1 *r) +{ + ndr_print_struct(ndr, name, "samr_UserInfo1"); + ndr->depth++; + ndr_print_samr_Name(ndr, "username", &r->username); + ndr_print_samr_Name(ndr, "full_name", &r->full_name); + ndr_print_uint32(ndr, "primary_group_rid", r->primary_group_rid); + ndr_print_samr_Name(ndr, "description", &r->description); + ndr_print_samr_Name(ndr, "comment", &r->comment); + ndr->depth--; +} + +void ndr_print_samr_UserInfo(struct ndr_print *ndr, const char *name, uint16 level, union samr_UserInfo *r) +{ + ndr_print_union(ndr, name, level, "samr_UserInfo"); + switch (level) { + case 1: + ndr_print_samr_UserInfo1(ndr, "info1", &r->info1); + break; + + default: + ndr_print_bad_level(ndr, name, level); + } +} + diff --git a/source4/librpc/ndr/ndr_samr.h b/source4/librpc/ndr/ndr_samr.h index bd2feac860..79dcc861e1 100644 --- a/source4/librpc/ndr/ndr_samr.h +++ b/source4/librpc/ndr/ndr_samr.h @@ -294,11 +294,17 @@ struct samr_CREATE_DOM_ALIAS { }; -struct samr_ENUM_DOM_ALIASES { +struct samr_EnumDomainAliases { struct { + struct policy_handle *handle; + uint32 *resume_handle; + uint32 max_size; } in; struct { + uint32 *resume_handle; + struct samr_SamArray *sam; + uint32 num_entries; NTSTATUS result; } out; @@ -484,11 +490,15 @@ struct samr_GET_MEMBERS_IN_ALIAS { }; -struct samr_OPEN_USER { +struct samr_OpenUser { struct { + struct policy_handle *handle; + uint32 access_mask; + uint32 rid; } in; struct { + struct policy_handle *acct_handle; NTSTATUS result; } out; @@ -504,11 +514,26 @@ struct samr_DELETE_DOM_USER { }; -struct samr_QUERY_USERINFO { +struct samr_UserInfo1 { + struct samr_Name username; + struct samr_Name full_name; + uint32 primary_group_rid; + struct samr_Name description; + struct samr_Name comment; +}; + +union samr_UserInfo { +/* [case(1)] */ struct samr_UserInfo1 info1; +}; + +struct samr_QueryUserInfo { struct { + struct policy_handle *handle; + uint16 level; } in; struct { + union samr_UserInfo *info; NTSTATUS result; } out; @@ -843,7 +868,7 @@ struct samr_VALIDATE_PASSWORD { #define DCERPC_SAMR_CREATE_USER_IN_DOMAIN 12 #define DCERPC_SAMR_ENUMDOMAINUSERS 13 #define DCERPC_SAMR_CREATE_DOM_ALIAS 14 -#define DCERPC_SAMR_ENUM_DOM_ALIASES 15 +#define DCERPC_SAMR_ENUMDOMAINALIASES 15 #define DCERPC_SAMR_GET_ALIAS_MEMBERSHIP 16 #define DCERPC_SAMR_LOOKUP_NAMES 17 #define DCERPC_SAMR_LOOKUP_RIDS 18 @@ -862,9 +887,9 @@ struct samr_VALIDATE_PASSWORD { #define DCERPC_SAMR_ADD_ALIASMEM 31 #define DCERPC_SAMR_DEL_ALIASMEM 32 #define DCERPC_SAMR_GET_MEMBERS_IN_ALIAS 33 -#define DCERPC_SAMR_OPEN_USER 34 +#define DCERPC_SAMR_OPENUSER 34 #define DCERPC_SAMR_DELETE_DOM_USER 35 -#define DCERPC_SAMR_QUERY_USERINFO 36 +#define DCERPC_SAMR_QUERYUSERINFO 36 #define DCERPC_SAMR_SET_USERINFO 37 #define DCERPC_SAMR_CHANGE_PASSWORD_USER 38 #define DCERPC_SAMR_GET_GROUPS_FOR_USER 39 diff --git a/source4/librpc/rpc/rpc_samr.c b/source4/librpc/rpc/rpc_samr.c index e361de23b5..97298ffa06 100644 --- a/source4/librpc/rpc/rpc_samr.c +++ b/source4/librpc/rpc/rpc_samr.c @@ -213,12 +213,12 @@ NTSTATUS dcerpc_samr_CREATE_DOM_ALIAS(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx return r->out.result; } -NTSTATUS dcerpc_samr_ENUM_DOM_ALIASES(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct samr_ENUM_DOM_ALIASES *r) +NTSTATUS dcerpc_samr_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct samr_EnumDomainAliases *r) { NTSTATUS status; - status = dcerpc_ndr_request(p, DCERPC_SAMR_ENUM_DOM_ALIASES, mem_ctx, - (ndr_push_fn_t) ndr_push_samr_ENUM_DOM_ALIASES, - (ndr_pull_fn_t) ndr_pull_samr_ENUM_DOM_ALIASES, + status = dcerpc_ndr_request(p, DCERPC_SAMR_ENUMDOMAINALIASES, mem_ctx, + (ndr_push_fn_t) ndr_push_samr_EnumDomainAliases, + (ndr_pull_fn_t) ndr_pull_samr_EnumDomainAliases, r); if (!NT_STATUS_IS_OK(status)) { return status; @@ -479,12 +479,12 @@ NTSTATUS dcerpc_samr_GET_MEMBERS_IN_ALIAS(struct dcerpc_pipe *p, TALLOC_CTX *mem return r->out.result; } -NTSTATUS dcerpc_samr_OPEN_USER(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct samr_OPEN_USER *r) +NTSTATUS dcerpc_samr_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct samr_OpenUser *r) { NTSTATUS status; - status = dcerpc_ndr_request(p, DCERPC_SAMR_OPEN_USER, mem_ctx, - (ndr_push_fn_t) ndr_push_samr_OPEN_USER, - (ndr_pull_fn_t) ndr_pull_samr_OPEN_USER, + status = dcerpc_ndr_request(p, DCERPC_SAMR_OPENUSER, mem_ctx, + (ndr_push_fn_t) ndr_push_samr_OpenUser, + (ndr_pull_fn_t) ndr_pull_samr_OpenUser, r); if (!NT_STATUS_IS_OK(status)) { return status; @@ -507,12 +507,12 @@ NTSTATUS dcerpc_samr_DELETE_DOM_USER(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return r->out.result; } -NTSTATUS dcerpc_samr_QUERY_USERINFO(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct samr_QUERY_USERINFO *r) +NTSTATUS dcerpc_samr_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct samr_QueryUserInfo *r) { NTSTATUS status; - status = dcerpc_ndr_request(p, DCERPC_SAMR_QUERY_USERINFO, mem_ctx, - (ndr_push_fn_t) ndr_push_samr_QUERY_USERINFO, - (ndr_pull_fn_t) ndr_pull_samr_QUERY_USERINFO, + status = dcerpc_ndr_request(p, DCERPC_SAMR_QUERYUSERINFO, mem_ctx, + (ndr_push_fn_t) ndr_push_samr_QueryUserInfo, + (ndr_pull_fn_t) ndr_pull_samr_QueryUserInfo, r); if (!NT_STATUS_IS_OK(status)) { return status; diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c index d4827e2504..21e2005d96 100644 --- a/source4/torture/rpc/samr.c +++ b/source4/torture/rpc/samr.c @@ -21,12 +21,63 @@ #include "includes.h" +static BOOL test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, + struct policy_handle *handle) +{ + NTSTATUS status; + struct samr_QueryUserInfo r; + + printf("Testing QueryUserInfo\n"); + + r.in.handle = handle; + r.in.level = 1; + + status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("QueryUserInfo failed - %s\n", nt_errstr(status)); + return False; + } + + NDR_PRINT_UNION_DEBUG(samr_UserInfo, r.in.level, r.out.info); + + return True; +} + +static BOOL test_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, + struct policy_handle *handle, uint32 rid) +{ + NTSTATUS status; + struct samr_OpenUser r; + struct policy_handle acct_handle; + + printf("Testing OpenUser(%u)\n", rid); + + r.in.handle = handle; + r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED; + r.in.rid = rid; + r.out.acct_handle = &acct_handle; + + status = dcerpc_samr_OpenUser(p, mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status)); + return False; + } + + if (!test_QueryUserInfo(p, mem_ctx, &acct_handle)) { + return False; + } + + return True; +} + static BOOL test_EnumDomainUsers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle) { NTSTATUS status; struct samr_EnumDomainUsers r; uint32 resume_handle=0; + int i; + BOOL ret = True; printf("Testing EnumDomainUsers\n"); @@ -44,7 +95,17 @@ static BOOL test_EnumDomainUsers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, NDR_PRINT_DEBUG(samr_SamArray, r.out.sam); - return True; + if (!r.out.sam) { + return False; + } + + for (i=0;i<r.out.sam->count;i++) { + if (!test_OpenUser(p, mem_ctx, handle, r.out.sam->entries[i].idx)) { + ret = False; + } + } + + return ret; } static BOOL test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, @@ -72,6 +133,31 @@ static BOOL test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return True; } +static BOOL test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, + struct policy_handle *handle) +{ + NTSTATUS status; + struct samr_EnumDomainAliases r; + uint32 resume_handle=0; + + printf("Testing EnumDomainAliases\n"); + + r.in.handle = handle; + r.in.resume_handle = &resume_handle; + r.in.max_size = (uint32)-1; + r.out.resume_handle = &resume_handle; + + status = dcerpc_samr_EnumDomainAliases(p, mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("EnumDomainAliases failed - %s\n", nt_errstr(status)); + return False; + } + + NDR_PRINT_DEBUG(samr_SamArray, r.out.sam); + + return True; +} + static BOOL test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle) { @@ -125,11 +211,15 @@ static BOOL test_OpenDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return False; } + if (!test_EnumDomainUsers(p, mem_ctx, &domain_handle)) { + return False; + } + if (!test_EnumDomainGroups(p, mem_ctx, &domain_handle)) { return False; } - if (!test_EnumDomainUsers(p, mem_ctx, &domain_handle)) { + if (!test_EnumDomainAliases(p, mem_ctx, &domain_handle)) { return False; } |