mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
r24053: Ensure we filter EnumDomainUsers with the supplied mask.
Should fix another part (list of domains in usrmgr incorrectly including accounts) of bug #4815 by mwallnoefer@yahoo.de. Andrew Bartlett
This commit is contained in:
parent
9475d94a61
commit
7f7e4fe298
@ -1428,9 +1428,9 @@ static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call,
|
||||
struct dcesrv_handle *h;
|
||||
struct samr_domain_state *d_state;
|
||||
struct ldb_message **res;
|
||||
int count, i, first;
|
||||
int count, num_filtered_entries, i, first;
|
||||
struct samr_SamEntry *entries;
|
||||
const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
|
||||
const char * const attrs[] = { "objectSid", "sAMAccountName", "userAccountControl", NULL };
|
||||
|
||||
*r->out.resume_handle = 0;
|
||||
r->out.sam = NULL;
|
||||
@ -1456,27 +1456,31 @@ static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call,
|
||||
if (!entries) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
num_filtered_entries = 0;
|
||||
for (i=0;i<count;i++) {
|
||||
entries[i].idx = samdb_result_rid_from_sid(mem_ctx, res[i], "objectSid", 0);
|
||||
entries[i].name.string = samdb_result_string(res[i], "sAMAccountName", "");
|
||||
/* Check if a mask has been requested */
|
||||
if (r->in.acct_flags
|
||||
&& ((samdb_result_acct_flags(res[i],
|
||||
"userAccountControl") & r->in.acct_flags) == 0)) {
|
||||
continue;
|
||||
}
|
||||
entries[num_filtered_entries].idx = samdb_result_rid_from_sid(mem_ctx, res[i], "objectSid", 0);
|
||||
entries[num_filtered_entries].name.string = samdb_result_string(res[i], "sAMAccountName", "");
|
||||
num_filtered_entries++;
|
||||
}
|
||||
|
||||
/* sort the results by rid */
|
||||
qsort(entries, count, sizeof(struct samr_SamEntry),
|
||||
qsort(entries, num_filtered_entries, sizeof(struct samr_SamEntry),
|
||||
(comparison_fn_t)compare_SamEntry);
|
||||
|
||||
/* find the first entry to return */
|
||||
for (first=0;
|
||||
first<count && entries[first].idx <= *r->in.resume_handle;
|
||||
first<num_filtered_entries && entries[first].idx <= *r->in.resume_handle;
|
||||
first++) ;
|
||||
|
||||
if (first == count) {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* return the rest, limit by max_size. Note that we
|
||||
use the w2k3 element size value of 54 */
|
||||
r->out.num_entries = count - first;
|
||||
r->out.num_entries = num_filtered_entries - first;
|
||||
r->out.num_entries = MIN(r->out.num_entries,
|
||||
1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
|
||||
|
||||
@ -1488,7 +1492,11 @@ static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call,
|
||||
r->out.sam->entries = entries+first;
|
||||
r->out.sam->count = r->out.num_entries;
|
||||
|
||||
if (r->out.num_entries < count - first) {
|
||||
if (first == num_filtered_entries) {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
if (r->out.num_entries < num_filtered_entries - first) {
|
||||
*r->out.resume_handle = entries[first+r->out.num_entries-1].idx;
|
||||
return STATUS_MORE_ENTRIES;
|
||||
}
|
||||
|
@ -2861,42 +2861,100 @@ static BOOL test_OpenAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL check_mask(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle, uint32_t rid,
|
||||
uint32_t acct_flag_mask)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct samr_OpenUser r;
|
||||
struct samr_QueryUserInfo q;
|
||||
struct policy_handle user_handle;
|
||||
BOOL ret = True;
|
||||
|
||||
printf("Testing OpenUser(%u)\n", rid);
|
||||
|
||||
r.in.domain_handle = handle;
|
||||
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
r.in.rid = rid;
|
||||
r.out.user_handle = &user_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;
|
||||
}
|
||||
|
||||
q.in.user_handle = &user_handle;
|
||||
q.in.level = 16;
|
||||
|
||||
status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("QueryUserInfo level 16 failed - %s\n",
|
||||
nt_errstr(status));
|
||||
ret = False;
|
||||
} else {
|
||||
if ((acct_flag_mask & q.out.info->info16.acct_flags) == 0) {
|
||||
printf("Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
|
||||
acct_flag_mask, q.out.info->info16.acct_flags, rid);
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL test_EnumDomainUsers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle)
|
||||
{
|
||||
NTSTATUS status;
|
||||
NTSTATUS status = STATUS_MORE_ENTRIES;
|
||||
struct samr_EnumDomainUsers r;
|
||||
uint32_t resume_handle=0;
|
||||
int i;
|
||||
uint32_t mask, resume_handle=0;
|
||||
int i, mask_idx;
|
||||
BOOL ret = True;
|
||||
struct samr_LookupNames n;
|
||||
struct samr_LookupRids lr ;
|
||||
uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
|
||||
ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
|
||||
ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
|
||||
ACB_PWNOEXP, 0};
|
||||
|
||||
printf("Testing EnumDomainUsers\n");
|
||||
|
||||
r.in.domain_handle = handle;
|
||||
r.in.resume_handle = &resume_handle;
|
||||
r.in.acct_flags = 0;
|
||||
r.in.max_size = (uint32_t)-1;
|
||||
r.out.resume_handle = &resume_handle;
|
||||
for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
|
||||
r.in.domain_handle = handle;
|
||||
r.in.resume_handle = &resume_handle;
|
||||
r.in.acct_flags = mask = masks[mask_idx];
|
||||
r.in.max_size = (uint32_t)-1;
|
||||
r.out.resume_handle = &resume_handle;
|
||||
|
||||
status = dcerpc_samr_EnumDomainUsers(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
status = dcerpc_samr_EnumDomainUsers(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
|
||||
!NT_STATUS_IS_OK(status)) {
|
||||
printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!r.out.sam) {
|
||||
return False;
|
||||
}
|
||||
if (!r.out.sam) {
|
||||
printf("EnumDomainUsers failed: r.out.sam unexpectedly NULL\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
if (r.out.sam->count == 0) {
|
||||
return True;
|
||||
}
|
||||
if (r.out.sam->count == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i=0;i<r.out.sam->count;i++) {
|
||||
if (!test_OpenUser(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
|
||||
ret = False;
|
||||
for (i=0;i<r.out.sam->count;i++) {
|
||||
if (mask) {
|
||||
if (!check_mask(p, mem_ctx, handle, r.out.sam->entries[i].idx, mask)) {
|
||||
ret = False;
|
||||
}
|
||||
} else if (!test_OpenUser(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user