summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/nsswitch/winbindd.h22
-rw-r--r--source3/nsswitch/winbindd_ads.c147
-rw-r--r--source3/nsswitch/winbindd_group.c10
-rw-r--r--source3/nsswitch/winbindd_proto.h10
-rw-r--r--source3/nsswitch/winbindd_rpc.c124
-rw-r--r--source3/nsswitch/winbindd_user.c6
-rw-r--r--source3/nsswitch/winbindd_util.c101
7 files changed, 250 insertions, 170 deletions
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index a00bf54cad..462a078fae 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -89,39 +89,51 @@ typedef struct {
I'm just starting small
*/
struct winbindd_methods {
+ /* get a list of users, returning a WINBIND_USERINFO for each one */
NTSTATUS (*query_user_list)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *start_ndx, uint32 *num_entries,
WINBIND_USERINFO **info);
+ /* get a list of groups */
NTSTATUS (*enum_dom_groups)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *start_ndx, uint32 *num_entries,
struct acct_info **info);
+ /* convert one user or group name to a sid */
NTSTATUS (*name_to_sid)(struct winbindd_domain *domain,
const char *name,
DOM_SID *sid,
enum SID_NAME_USE *type);
+ /* convert a sid to a user or group name */
NTSTATUS (*sid_to_name)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
DOM_SID *sid,
char **name,
enum SID_NAME_USE *type);
- /* query_user is a bit strange. The backend has a choice of
- doing the lookup by user name or rid */
+ /* lookup user info for a given rid */
NTSTATUS (*query_user)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- const char *user_name, uint32 user_rid,
+ uint32 user_rid,
WINBIND_USERINFO *user_info);
- /* the backend can also choose for this function */
+ /* lookup all groups that a user is a member of. The backend
+ can also choose to lookup by username or rid for this
+ function */
NTSTATUS (*lookup_usergroups)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- const char *user_name, uint32 user_rid,
+ uint32 user_rid,
uint32 *num_groups, uint32 **user_gids);
+
+ /* find all members of the group with the specified group_rid */
+ NTSTATUS (*lookup_groupmem)(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 group_rid, uint32 *num_names,
+ uint32 **rid_mem, char ***names,
+ uint32 **name_types);
};
/* Structures to hold per domain information */
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c
index 3ae2f85b46..e90e590e8c 100644
--- a/source3/nsswitch/winbindd_ads.c
+++ b/source3/nsswitch/winbindd_ads.c
@@ -24,6 +24,27 @@
#ifdef HAVE_ADS
+/* useful utility */
+static void sid_from_rid(struct winbindd_domain *domain, uint32 rid, DOM_SID *sid)
+{
+ sid_copy(sid, &domain->sid);
+ sid_append_rid(sid, rid);
+}
+
+/* turn a sAMAccountType into a SID_NAME_USE */
+static enum SID_NAME_USE ads_atype_map(uint32 atype)
+{
+ switch (atype & 0xF0000000) {
+ case ATYPE_GROUP:
+ return SID_NAME_DOM_GRP;
+ case ATYPE_USER:
+ return SID_NAME_USER;
+ default:
+ DEBUG(1,("hmm, need to map account type 0x%x\n", atype));
+ }
+ return SID_NAME_UNKNOWN;
+}
+
/* Query display info for a realm. This is the basic user list fn */
static NTSTATUS query_user_list(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -254,28 +275,70 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
return NT_STATUS_UNSUCCESSFUL;
}
- switch (t & 0xF0000000) {
- case ATYPE_GROUP:
- *type = SID_NAME_DOM_GRP;
- break;
- case ATYPE_USER:
- *type = SID_NAME_USER;
- break;
- default:
- DEBUG(1,("hmm, need to map account type 0x%x\n", t));
- *type = SID_NAME_UNKNOWN;
- break;
- }
+ *type = ads_atype_map(t);
ads_destroy(&ads);
+
+ return NT_STATUS_OK;
+}
+
+/* convert a sid to a user or group name */
+static NTSTATUS sid_to_name(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ DOM_SID *sid,
+ char **name,
+ enum SID_NAME_USE *type)
+{
+ ADS_STRUCT *ads;
+ const char *attrs[] = {"sAMAccountName", "sAMAccountType", NULL};
+ int rc;
+ void *msg;
+ char *exp;
+ char *sidstr;
+ uint32 atype;
+ char *s;
+
+ DEBUG(3,("ads: sid_to_name\n"));
+
+ ads = ads_init(NULL, NULL, NULL);
+ if (!ads) {
+ DEBUG(1,("ads_init failed\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ rc = ads_connect(ads);
+ if (rc) {
+ DEBUG(1,("sid_to_name ads_connect: %s\n", ads_errstr(rc)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ sidstr = ads_sid_binstring(sid);
+ asprintf(&exp, "(objectSid=%s)", sidstr);
+ rc = ads_search(ads, &msg, exp, attrs);
+ free(exp);
+ free(sidstr);
+ if (rc) {
+ DEBUG(1,("sid_to_name ads_search: %s\n", ads_errstr(rc)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ s = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName");
+ *name = talloc_asprintf(mem_ctx, "%s%s%s", domain->name, lp_winbind_separator(), s);
+ *type = ads_atype_map(atype);
+
return NT_STATUS_OK;
}
-/* Lookup user information from a rid or username. */
+
+/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- const char *user_name, uint32 user_rid,
+ uint32 user_rid,
WINBIND_USERINFO *info)
{
ADS_STRUCT *ads;
@@ -285,14 +348,12 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
void *msg;
char *exp;
DOM_SID sid;
- fstring dom2, name2;
+ char *sidstr;
- /* sigh. Need to fix interface to give us a raw name */
- if (!parse_domain_user(user_name, dom2, name2))
- return NT_STATUS_UNSUCCESSFUL;
-
DEBUG(3,("ads: query_user\n"));
+ sid_from_rid(domain, user_rid, &sid);
+
ads = ads_init(NULL, NULL, NULL);
if (!ads) {
DEBUG(1,("ads_init failed\n"));
@@ -305,33 +366,35 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
return NT_STATUS_UNSUCCESSFUL;
}
- asprintf(&exp, "(sAMAccountName=%s)", name2);
+ sidstr = ads_sid_binstring(&sid);
+ asprintf(&exp, "(objectSid=%s)", sidstr);
rc = ads_search(ads, &msg, exp, attrs);
free(exp);
+ free(sidstr);
if (rc) {
- DEBUG(1,("query_user(%s) ads_search: %s\n", user_name, ads_errstr(rc)));
+ DEBUG(1,("query_user(rid=%d) ads_search: %s\n", user_rid, ads_errstr(rc)));
return NT_STATUS_UNSUCCESSFUL;
}
count = ads_count_replies(ads, msg);
if (count != 1) {
- DEBUG(1,("query_user(%s): Not found\n", user_name));
+ DEBUG(1,("query_user(rid=%d): Not found\n", user_rid));
return NT_STATUS_UNSUCCESSFUL;
}
info->acct_name = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName");
info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
- DEBUG(1,("No sid for %s !?\n", user_name));
+ DEBUG(1,("No sid for %d !?\n", user_rid));
goto error;
}
if (!ads_pull_uint32(ads, msg, "primaryGroupID", &info->group_rid)) {
- DEBUG(1,("No primary group for %s !?\n", user_name));
+ DEBUG(1,("No primary group for %d !?\n", user_rid));
goto error;
}
if (!sid_peek_rid(&sid, &info->user_rid)) {
- DEBUG(1,("No rid for %s !?\n", user_name));
+ DEBUG(1,("No rid for %d !?\n", user_rid));
goto error;
}
@@ -346,7 +409,7 @@ error:
/* Lookup groups a user is a member of. */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- const char *user_name, uint32 user_rid,
+ uint32 user_rid,
uint32 *num_groups, uint32 **user_gids)
{
ADS_STRUCT *ads;
@@ -359,11 +422,15 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
DOM_SID *sids;
int i;
uint32 primary_group;
+ DOM_SID sid;
+ char *sidstr;
DEBUG(3,("ads: lookup_usergroups\n"));
(*num_groups) = 0;
+ sid_from_rid(domain, user_rid, &sid);
+
ads = ads_init(NULL, NULL, NULL);
if (!ads) {
DEBUG(1,("ads_init failed\n"));
@@ -376,11 +443,13 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
return NT_STATUS_UNSUCCESSFUL;
}
- asprintf(&exp, "(sAMAccountName=%s)", user_name);
+ sidstr = ads_sid_binstring(&sid);
+ asprintf(&exp, "(objectSid=%s)", sidstr);
rc = ads_search(ads, &msg, exp, attrs);
free(exp);
+ free(sidstr);
if (rc) {
- DEBUG(1,("lookup_usergroups(%s) ads_search: %s\n", user_name, ads_errstr(rc)));
+ DEBUG(1,("lookup_usergroups(rid=%d) ads_search: %s\n", user_rid, ads_errstr(rc)));
return NT_STATUS_UNSUCCESSFUL;
}
@@ -388,12 +457,12 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
rc = ads_search_dn(ads, &msg, user_dn, attrs2);
if (rc) {
- DEBUG(1,("lookup_usergroups(%s) ads_search tokenGroups: %s\n", user_name, ads_errstr(rc)));
+ DEBUG(1,("lookup_usergroups(rid=%d) ads_search tokenGroups: %s\n", user_rid, ads_errstr(rc)));
return NT_STATUS_UNSUCCESSFUL;
}
if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group)) {
- DEBUG(1,("No primary group for %s !?\n", user_name));
+ DEBUG(1,("No primary group for rid=%d !?\n", user_rid));
return NT_STATUS_UNSUCCESSFUL;
}
@@ -412,17 +481,25 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
return NT_STATUS_OK;
}
+
+static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 group_rid, uint32 *num_names,
+ uint32 **rid_mem, char ***names,
+ uint32 **name_types)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
/* the ADS backend methods are exposed via this structure */
struct winbindd_methods ads_methods = {
query_user_list,
enum_dom_groups,
name_to_sid,
- /* I can't see a good way to do a sid to name mapping with ldap,
- and MS servers always allow RPC for this (even in native mode) so
- just use RPC for sid_to_name. Maybe that's why they allow it? */
- winbindd_rpc_sid_to_name,
+ sid_to_name,
query_user,
- lookup_usergroups
+ lookup_usergroups,
+ lookup_groupmem
};
#endif
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index b03e506494..440f009366 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -60,6 +60,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
char **names = NULL, *buf;
BOOL result = False;
TALLOC_CTX *mem_ctx;
+ NTSTATUS status;
if (!(mem_ctx = talloc_init()))
return False;
@@ -78,10 +79,9 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
}
/* Lookup group members */
-
- if (!winbindd_lookup_groupmem(domain, mem_ctx, group_rid, &num_names,
- &rid_mem, &names, &name_types)) {
-
+ status = domain->methods->lookup_groupmem(domain, mem_ctx, group_rid, &num_names,
+ &rid_mem, &names, &name_types);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("fill_grent_mem(): could not lookup membership "
"for group rid %d in domain %s\n",
group_rid, domain->name));
@@ -958,7 +958,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
sid_split_rid(&user_sid, &user_rid);
- status = domain->methods->lookup_usergroups(domain, mem_ctx, name_user, user_rid, &num_groups, &user_gids);
+ status = domain->methods->lookup_usergroups(domain, mem_ctx, user_rid, &num_groups, &user_gids);
if (!NT_STATUS_IS_OK(status)) goto done;
/* Copy data back to client */
diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h
index 4659ad69dd..893064b801 100644
--- a/source3/nsswitch/winbindd_proto.h
+++ b/source3/nsswitch/winbindd_proto.h
@@ -109,11 +109,6 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state);
/* The following definitions come from nsswitch/winbindd_rpc.c */
-NTSTATUS winbindd_rpc_sid_to_name(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- DOM_SID *sid,
- char **name,
- enum SID_NAME_USE *type);
/* The following definitions come from nsswitch/winbindd_sid.c */
@@ -145,11 +140,6 @@ BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain,
BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
fstring name,
enum SID_NAME_USE *type);
-BOOL winbindd_lookup_groupmem(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- uint32 group_rid, uint32 *num_names,
- uint32 **rid_mem, char ***names,
- uint32 **name_types);
void free_getent_state(struct getent_state *state);
BOOL winbindd_param_init(void);
BOOL check_domain_env(char *domain_env, char *domain);
diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c
index d783156815..c04bcdc954 100644
--- a/source3/nsswitch/winbindd_rpc.c
+++ b/source3/nsswitch/winbindd_rpc.c
@@ -156,11 +156,11 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
/*
convert a domain SID to a user or group name
*/
-NTSTATUS winbindd_rpc_sid_to_name(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- DOM_SID *sid,
- char **name,
- enum SID_NAME_USE *type)
+static NTSTATUS sid_to_name(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ DOM_SID *sid,
+ char **name,
+ enum SID_NAME_USE *type)
{
CLI_POLICY_HND *hnd;
char **names;
@@ -187,7 +187,7 @@ NTSTATUS winbindd_rpc_sid_to_name(struct winbindd_domain *domain,
/* Lookup user information from a rid or username. */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- const char *user_name, uint32 user_rid,
+ uint32 user_rid,
WINBIND_USERINFO *user_info)
{
CLI_POLICY_HND *hnd;
@@ -224,8 +224,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
cli_samr_close(hnd->cli, mem_ctx, &user_pol);
- user_info->acct_name = talloc_strdup(mem_ctx, user_name);
user_info->group_rid = ctr->info.id21->group_rid;
+ user_info->acct_name = unistr2_tdup(mem_ctx,
+ &ctr->info.id21->uni_user_name);
user_info->full_name = unistr2_tdup(mem_ctx,
&ctr->info.id21->uni_full_name);
@@ -243,7 +244,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
/* Lookup groups a user is a member of. I wish Unix had a call like this! */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- const char *user_name, uint32 user_rid,
+ uint32 user_rid,
uint32 *num_groups, uint32 **user_gids)
{
CLI_POLICY_HND *hnd;
@@ -300,13 +301,116 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
}
+/* Lookup group membership given a rid. */
+static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 group_rid, uint32 *num_names,
+ uint32 **rid_mem, char ***names,
+ uint32 **name_types)
+{
+ CLI_POLICY_HND *hnd;
+ 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;
+
+ /* Get sam handle */
+
+ if (!(hnd = cm_get_sam_handle(domain->name)))
+ goto done;
+
+ /* Get domain handle */
+
+ result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
+ des_access, &domain->sid, &dom_pol);
+
+ 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;
+
+ /* 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(mem_ctx, *num_names * sizeof(char *));
+ *name_types = talloc(mem_ctx, *num_names * sizeof(uint32));
+
+ 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);
+
+ if (!NT_STATUS_IS_OK(result))
+ 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;
+
+ 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;
+}
+
+
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods msrpc_methods = {
query_user_list,
enum_dom_groups,
name_to_sid,
- winbindd_rpc_sid_to_name,
+ sid_to_name,
query_user,
- lookup_usergroups
+ lookup_usergroups,
+ lookup_groupmem
};
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index 52122a4f29..d9b2b5a0e6 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -163,8 +163,7 @@ enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_cli_state *stat
sid_split_rid(&user_sid, &user_rid);
- status = domain->methods->query_user(domain, mem_ctx, name_user, user_rid,
- &user_info);
+ status = domain->methods->query_user(domain, mem_ctx, user_rid, &user_info);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("pwnam_from_user(): error getting user info for "
"user '%s'\n", name_user));
@@ -259,8 +258,7 @@ enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_cli_state *state
return WINBINDD_ERROR;
}
- status = domain->methods->query_user(domain, mem_ctx, user_name, user_rid,
- &user_info);
+ status = domain->methods->query_user(domain, mem_ctx, user_rid, &user_info);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("pwnam_from_uid(): error getting user info for "
"user '%s'\n", user_name));
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index d49e0b5bc2..2ac090f8e5 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -478,107 +478,6 @@ BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
return rv;
}
-/* Lookup group membership given a rid. */
-
-BOOL winbindd_lookup_groupmem(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- uint32 group_rid, uint32 *num_names,
- uint32 **rid_mem, char ***names,
- uint32 **name_types)
-{
- CLI_POLICY_HND *hnd;
- 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;
-
- /* Get sam handle */
-
- if (!(hnd = cm_get_sam_handle(domain->name)))
- goto done;
-
- /* Get domain handle */
-
- result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
- des_access, &domain->sid, &dom_pol);
-
- 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;
-
- /* 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(mem_ctx, *num_names * sizeof(char *));
- *name_types = talloc(mem_ctx, *num_names * sizeof(uint32));
-
- 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);
-
- if (!NT_STATUS_IS_OK(result))
- 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;
-
- 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 NT_STATUS_IS_OK(result);
-}
/* Free state information held for {set,get,end}{pw,gr}ent() functions */