diff options
| -rw-r--r-- | source3/nsswitch/winbindd.h | 22 | ||||
| -rw-r--r-- | source3/nsswitch/winbindd_ads.c | 147 | ||||
| -rw-r--r-- | source3/nsswitch/winbindd_group.c | 10 | ||||
| -rw-r--r-- | source3/nsswitch/winbindd_proto.h | 10 | ||||
| -rw-r--r-- | source3/nsswitch/winbindd_rpc.c | 124 | ||||
| -rw-r--r-- | source3/nsswitch/winbindd_user.c | 6 | ||||
| -rw-r--r-- | source3/nsswitch/winbindd_util.c | 101 | 
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 */  | 
