r24053: Ensure we filter EnumDomainUsers with the supplied mask.
authorAndrew Bartlett <abartlet@samba.org>
Thu, 26 Jul 2007 07:27:46 +0000 (07:27 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 20:01:19 +0000 (15:01 -0500)
Should fix another part (list of domains in usrmgr incorrectly
including accounts) of bug #4815 by mwallnoefer@yahoo.de.

Andrew Bartlett
(This used to be commit 7f7e4fe2989ef4cb7ec0f855b25e558f3bbd18c5)

source4/rpc_server/samr/dcesrv_samr.c
source4/torture/rpc/samr.c

index cedf4059e22c783c8ff21c03eb226f03b1058be7..f1c4ac24c9a04e4b2d50b6ca265a58814baeff89 100644 (file)
@@ -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;
        }
index 20a79a7d4fdfcae055b1f013b5d6368b1f3bedc9..58488b77178ff6f5e2d4cb0cc4173053ae2c132c 100644 (file)
@@ -2861,42 +2861,100 @@ static BOOL test_OpenAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-static BOOL test_EnumDomainUsers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                                struct policy_handle *handle)
+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_EnumDomainUsers r;
-       uint32_t resume_handle=0;
-       int i;
+       struct samr_OpenUser r;
+       struct samr_QueryUserInfo q;
+       struct policy_handle user_handle;
        BOOL ret = True;
-       struct samr_LookupNames n;
-       struct samr_LookupRids  lr ;
 
-       printf("Testing EnumDomainUsers\n");
+       printf("Testing OpenUser(%u)\n", rid);
 
        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;
+       r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       r.in.rid = rid;
+       r.out.user_handle = &user_handle;
 
-       status = dcerpc_samr_EnumDomainUsers(p, mem_ctx, &r);
+       status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
+               printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
                return False;
        }
+
+       q.in.user_handle = &user_handle;
+       q.in.level = 16;
        
-       if (!r.out.sam) {
-               return False;
+       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 (r.out.sam->count == 0) {
-               return True;
+       
+       if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
+               ret = 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_EnumDomainUsers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                                struct policy_handle *handle)
+{
+       NTSTATUS status = STATUS_MORE_ENTRIES;
+       struct samr_EnumDomainUsers r;
+       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");
+
+       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_EQUAL(status, STATUS_MORE_ENTRIES) &&  
+                   !NT_STATUS_IS_OK(status)) {
+                       printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
+                       return False;
+               }
+       
+               if (!r.out.sam) {
+                       printf("EnumDomainUsers failed: r.out.sam unexpectedly NULL\n");
+                       return False;
+               }
+
+               if (r.out.sam->count == 0) {
+                       continue;
+               }
+
+               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;
+                       }
                }
        }