static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { POLICY_HND connect_pol, domain_pol, group_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 num_members, *group_rids, *group_attrs, group_rid; uint32 access_mask = MAXIMUM_ALLOWED_ACCESS; int i; fstring server; if ((argc < 2) || (argc > 3)) { printf("Usage: %s rid [access mask]\n", argv[0]); return NT_STATUS_OK; } sscanf(argv[1], "%i", &group_rid); if (argc > 2) sscanf(argv[2], "%x", &access_mask); slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; result = cli_samr_open_group(cli, mem_ctx, &domain_pol, access_mask, group_rid, &group_pol); if (!NT_STATUS_IS_OK(result)) goto done; result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol, &num_members, &group_rids, &group_attrs); if (!NT_STATUS_IS_OK(result)) goto done; for (i = 0; i < num_members; i++) { printf("\trid:[0x%x] attr:[0x%x]\n", group_rids[i], group_attrs[i]); } done: return result; }
/* Lookup group membership given a rid. */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *group_sid, uint32 *num_names, DOM_SID ***sid_mem, char ***names, uint32 **name_types) { CLI_POLICY_HND *hnd = NULL; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 i, total_names = 0; POLICY_HND dom_pol, group_pol; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; BOOL got_dom_pol = False, got_group_pol = False; uint32 *rid_mem = NULL; uint32 group_rid; int retry; unsigned int j; fstring sid_string; DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid))); if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) { goto done; } *num_names = 0; retry = 0; do { /* Get sam handle */ if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd))) goto done; /* Get domain handle */ result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, des_access, &domain->sid, &dom_pol); } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); if (!NT_STATUS_IS_OK(result)) goto done; got_dom_pol = True; /* Get group handle */ result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol, des_access, group_rid, &group_pol); if (!NT_STATUS_IS_OK(result)) goto done; got_group_pol = True; /* Step #1: Get a list of user rids that are the members of the group. */ result = cli_samr_query_groupmem(hnd->cli, mem_ctx, &group_pol, num_names, &rid_mem, name_types); if (!NT_STATUS_IS_OK(result)) goto done; if (!*num_names) { names = NULL; name_types = NULL; sid_mem = NULL; goto done; } /* Step #2: Convert list of rids into list of usernames. Do this in bunches of ~1000 to avoid crashing NT4. It looks like there is a buffer overflow or something like that lurking around somewhere. */ #define MAX_LOOKUP_RIDS 900 *names = talloc_zero(mem_ctx, *num_names * sizeof(char *)); *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32)); *sid_mem = talloc_zero(mem_ctx, *num_names * sizeof(DOM_SID *)); for (j=0;j<(*num_names);j++) { (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]); } if (*num_names>0 && (!*names || !*name_types)) { result = NT_STATUS_NO_MEMORY; goto done; } for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) { int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS); uint32 tmp_num_names = 0; char **tmp_names = NULL; uint32 *tmp_types = NULL; /* Lookup a chunk of rids */ result = cli_samr_lookup_rids(hnd->cli, mem_ctx, &dom_pol, 1000, /* flags */ num_lookup_rids, &rid_mem[i], &tmp_num_names, &tmp_names, &tmp_types); /* see if we have a real error (and yes the STATUS_SOME_UNMAPPED is the one returned from 2k) */ if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED)) goto done; /* Copy result into array. The talloc system will take care of freeing the temporary arrays later on. */ memcpy(&(*names)[i], tmp_names, sizeof(char *) * tmp_num_names); memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) * tmp_num_names); total_names += tmp_num_names; } *num_names = total_names; result = NT_STATUS_OK; done: if (got_group_pol) cli_samr_close(hnd->cli, mem_ctx, &group_pol); if (got_dom_pol) cli_samr_close(hnd->cli, mem_ctx, &dom_pol); return result; }