From b6caa0de4cffb5ce2ea4aa6144901832ddbb9667 Mon Sep 17 00:00:00 2001 From: Günther Deschner <gd@samba.org> Date: Tue, 1 Jul 2008 20:19:10 +0200 Subject: netapi: support more infolevels in NetUserEnum. Guenther (This used to be commit 22bd3d401e47ffedf1169c0c74a329e9fdcac561) --- source3/lib/netapi/user.c | 274 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 245 insertions(+), 29 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c index 382704769d..8b1287e300 100644 --- a/source3/lib/netapi/user.c +++ b/source3/lib/netapi/user.c @@ -440,35 +440,229 @@ WERROR NetUserDel_l(struct libnetapi_ctx *ctx, /**************************************************************** ****************************************************************/ -static WERROR convert_samr_samarray_to_USER_INFO_buffer(TALLOC_CTX *mem_ctx, - struct samr_SamArray *sam_array, - uint32_t level, - uint8_t **buffer) +static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx, + struct rpc_pipe_client *pipe_cli, + struct policy_handle *domain_handle, + struct policy_handle *builtin_handle, + const char *user_name, + uint32_t rid, + uint32_t level, + struct samr_UserInfo21 **info21, + struct sec_desc_buf **sec_desc) { + NTSTATUS status; + + struct policy_handle user_handle; + union samr_UserInfo *user_info = NULL; + struct samr_RidWithAttributeArray *rid_array = NULL; + uint32_t access_mask = SEC_STD_READ_CONTROL | + SAMR_USER_ACCESS_GET_ATTRIBUTES | + SAMR_USER_ACCESS_GET_NAME_ETC; + + ZERO_STRUCT(user_handle); + + switch (level) { + case 0: + case 1: + case 2: + case 3: + case 10: + case 11: + case 20: + case 23: + break; + default: + return NT_STATUS_INVALID_LEVEL; + } + + if (level == 0) { + return NT_STATUS_OK; + } + + status = rpccli_samr_OpenUser(pipe_cli, mem_ctx, + domain_handle, + access_mask, + rid, + &user_handle); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = rpccli_samr_QueryUserInfo(pipe_cli, mem_ctx, + &user_handle, + 21, + &user_info); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = rpccli_samr_QuerySecurity(pipe_cli, mem_ctx, + &user_handle, + SECINFO_DACL, + sec_desc); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if (level == 1) { + status = rpccli_samr_GetGroupsForUser(pipe_cli, mem_ctx, + &user_handle, + &rid_array); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + +#if 0 + status = rpccli_samr_GetAliasMembership(pipe_cli, ctx, + &builtin_handle, + &sids, + &rids); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } +#endif + } + + *info21 = &user_info->info21; + + done: + if (is_valid_policy_hnd(&user_handle)) { + rpccli_samr_Close(pipe_cli, mem_ctx, &user_handle); + } + + return status; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx, + struct rpc_pipe_client *pipe_cli, + struct dom_sid *domain_sid, + struct policy_handle *domain_handle, + struct policy_handle *builtin_handle, + const char *user_name, + uint32_t rid, + uint32_t level, + uint8_t **buffer, + uint32_t *num_entries) +{ + NTSTATUS status; + + struct samr_UserInfo21 *info21 = NULL; + struct sec_desc_buf *sec_desc = NULL; + struct dom_sid sid; + struct USER_INFO_0 *info0 = NULL; - int i; + struct USER_INFO_10 *info10 = NULL; + struct USER_INFO_20 *info20 = NULL; + struct USER_INFO_23 *info23 = NULL; switch (level) { case 0: - info0 = TALLOC_ZERO_ARRAY(mem_ctx, struct USER_INFO_0, - sam_array->count); - W_ERROR_HAVE_NO_MEMORY(info0); - - for (i=0; i<sam_array->count; i++) { - info0[i].usri0_name = talloc_strdup(mem_ctx, - sam_array->entries[i].name.string); - W_ERROR_HAVE_NO_MEMORY(info0[i].usri0_name); + case 1: + case 2: + case 3: + case 10: + case 11: + case 20: + case 23: + break; + default: + return NT_STATUS_INVALID_LEVEL; + } + + if (level == 0) { + info0 = TALLOC_P(mem_ctx, struct USER_INFO_0); + NT_STATUS_HAVE_NO_MEMORY(info0); + + info0->usri0_name = talloc_strdup(mem_ctx, user_name); + NT_STATUS_HAVE_NO_MEMORY(info0->usri0_name); + + ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, *info0, + (struct USER_INFO_0 **)buffer, num_entries); + + return NT_STATUS_OK; + } + + status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli, + domain_handle, + builtin_handle, + user_name, + rid, + level, + &info21, + &sec_desc); + + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + switch (level) { + case 10: + info10 = TALLOC_P(mem_ctx, struct USER_INFO_10); + NT_STATUS_HAVE_NO_MEMORY(info10); + + info10->usri10_name = talloc_strdup(mem_ctx, user_name); + NT_STATUS_HAVE_NO_MEMORY(info10->usri10_name); + + info10->usri10_comment = talloc_strdup(mem_ctx, + info21->description.string); + + info10->usri10_full_name = talloc_strdup(mem_ctx, + info21->full_name.string); + + info10->usri10_usr_comment = talloc_strdup(mem_ctx, + info21->comment.string); + + ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, *info10, + (struct USER_INFO_10 **)buffer, num_entries); + + break; + + case 20: + info20 = TALLOC_P(mem_ctx, struct USER_INFO_20); + NT_STATUS_HAVE_NO_MEMORY(info20); + + info20->usri20_name = talloc_strdup(mem_ctx, user_name); + NT_STATUS_HAVE_NO_MEMORY(info20->usri20_name); + + info20->usri20_comment = talloc_strdup(mem_ctx, + info21->description.string); + + info20->usri20_flags = info21->acct_flags; + info20->usri20_user_id = rid; + + ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, *info20, + (struct USER_INFO_20 **)buffer, num_entries); + + break; + case 23: + info23 = TALLOC_P(mem_ctx, struct USER_INFO_23); + NT_STATUS_HAVE_NO_MEMORY(info23); + + info23->usri23_name = talloc_strdup(mem_ctx, user_name); + NT_STATUS_HAVE_NO_MEMORY(info23->usri23_name); + + info23->usri23_comment = talloc_strdup(mem_ctx, + info21->description.string); + + info23->usri23_flags = info21->acct_flags; + + if (!sid_compose(&sid, domain_sid, rid)) { + return NT_STATUS_NO_MEMORY; } - *buffer = (uint8_t *)talloc_memdup(mem_ctx, info0, - sizeof(struct USER_INFO_0) * sam_array->count); - W_ERROR_HAVE_NO_MEMORY(*buffer); + info23->usri23_user_sid = + (struct domsid *)sid_dup_talloc(mem_ctx, &sid); + + ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, *info23, + (struct USER_INFO_23 **)buffer, num_entries); break; - default: - return WERR_NOT_SUPPORTED; } - return WERR_OK; + done: + return status; } /**************************************************************** @@ -484,23 +678,32 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx, struct policy_handle domain_handle; struct samr_SamArray *sam = NULL; uint32_t filter = ACB_NORMAL; + int i; + uint32_t entries_read = 0; - NTSTATUS status; + NTSTATUS status = NT_STATUS_OK; WERROR werr; ZERO_STRUCT(connect_handle); ZERO_STRUCT(domain_handle); + if (!r->out.buffer) { + return WERR_INVALID_PARAM; + } + + *r->out.buffer = NULL; + *r->out.entries_read = 0; + switch (r->in.level) { case 0: + case 10: + case 20: + case 23: break; case 1: case 2: case 3: - case 10: case 11: - case 20: - case 23: default: return WERR_NOT_SUPPORTED; } @@ -555,15 +758,28 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx, filter, &sam, r->in.prefmaxlen, - r->out.entries_read); - if (!NT_STATUS_IS_OK(status)) { - werr = ntstatus_to_werror(status); + &entries_read); + werr = ntstatus_to_werror(status); + if (NT_STATUS_IS_ERR(status)) { goto done; } - werr = convert_samr_samarray_to_USER_INFO_buffer(ctx, sam, - r->in.level, - r->out.buffer); + for (i=0; i < sam->count; i++) { + + status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli, + domain_sid, + &domain_handle, + NULL, /*&builtin_handle, */ + sam->entries[i].name.string, + sam->entries[i].idx, + r->in.level, + r->out.buffer, + r->out.entries_read); + if (!NT_STATUS_IS_OK(status)) { + werr = ntstatus_to_werror(status); + goto done; + } + } done: if (!cli) { -- cgit