summaryrefslogtreecommitdiff
path: root/source3/nsswitch
diff options
context:
space:
mode:
Diffstat (limited to 'source3/nsswitch')
-rw-r--r--source3/nsswitch/winbindd_group.c116
1 files changed, 73 insertions, 43 deletions
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index 30b874a820..de8ecd45f1 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -465,7 +465,7 @@ enum winbindd_result winbindd_endgrent(struct winbindd_cli_state *state)
static BOOL get_sam_group_entries(struct getent_state *ent)
{
- NTSTATUS status, num_entries, start_ndx = 0;
+ uint32 status, num_entries;
struct acct_info *name_list = NULL;
if (ent->got_all_sam_entries) {
@@ -501,43 +501,33 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
num_entries = 0;
- status =
- wb_samr_enum_dom_groups(&ent->domain->
- sam_dom_handle,
- &start_ndx,
- 0x8000, /* buffer size? */
- (struct acct_info **)
- &sam_grp_entries,
- &num_entries);
+ status = samr_enum_dom_groups(&ent->domain->sam_dom_handle,
+ &ent->grp_query_start_ndx,
+ 0x8000, /* buffer size? */
+ (struct acct_info **)
+ &sam_grp_entries,
+ &num_entries);
/* Copy entries into return buffer */
if (num_entries) {
- struct acct_info *tnl;
- tnl = (struct acct_info *)Realloc(name_list,
+ name_list = Realloc(name_list,
sizeof(struct acct_info) *
(ent->num_sam_entries +
num_entries));
- if (!tnl) {
- DEBUG(0,("get_sam_group_entries: Realloc fail.\n"));
- if (name_list)
- free(name_list);
- return False;
- } else
- name_list = tnl;
-
memcpy(&name_list[ent->num_sam_entries],
sam_grp_entries,
num_entries * sizeof(struct acct_info));
+
+ safe_free(sam_grp_entries);
}
ent->num_sam_entries += num_entries;
-
- if (status != STATUS_MORE_ENTRIES) {
+
+ if (status != STATUS_MORE_ENTRIES)
break;
- }
} while (ent->num_sam_entries < MAX_FETCH_SAM_ENTRIES);
@@ -615,7 +605,7 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
struct getent_state *next_ent;
DEBUG(10, ("getgrent(): freeing state info for "
- "domain %s\n", ent->domain->name));
+ "domain %s\n", ent->domain->name));
/* Free state information for this domain */
@@ -683,7 +673,7 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
gr_mem_list,
gr_mem_list_len + gr_mem_len);
- if (!new_gr_mem_list) {
+ if (!new_gr_mem_list && (group_list[group_list_ndx].num_gr_mem != 0)) {
DEBUG(0, ("getgrent(): out of memory\n"));
free(gr_mem_list);
gr_mem_list_len = 0;
@@ -770,16 +760,19 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
{
- uint32 total_entries = 0;
- struct winbindd_domain *domain;
+ uint32 total_entries = 0;
+ uint32 num_domain_entries;
+ struct winbindd_domain *domain;
struct getent_state groups;
- char *ted, *extra_data = NULL;
+ char *extra_data = NULL;
+ char *ted = NULL;
int extra_data_len = 0, i;
+ void *sam_entries = NULL;
DEBUG(3, ("[%5d]: list groups\n", state->pid));
/* Enumerate over trusted domains */
-
+ ZERO_STRUCT(groups);
for (domain = domain_list; domain; domain = domain->next) {
/* Skip domains other than WINBINDD_DOMAIN environment
@@ -795,23 +788,62 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
ZERO_STRUCT(groups);
groups.domain = domain;
- get_sam_group_entries(&groups);
+ /*
+ * iterate through all groups
+ * total_entries : maintains a total count over **all domains**
+ * num_domain_entries : is the running count for this domain
+ */
+
+ num_domain_entries = 0;
+ while (get_sam_group_entries(&groups))
+ {
+ int new_size;
+ int offset;
+
+ offset = sizeof(struct acct_info) * num_domain_entries;
+ new_size = sizeof(struct acct_info)
+ * (groups.num_sam_entries + num_domain_entries);
+ sam_entries = Realloc(sam_entries, new_size);
+
+ if (!sam_entries)
+ return WINBINDD_ERROR;
+
+ num_domain_entries += groups.num_sam_entries;
+ memcpy (sam_entries+offset, groups.sam_entries,
+ sizeof(struct acct_info) * groups.num_sam_entries);
+
+ groups.sam_entries = NULL;
+ groups.num_sam_entries = 0;
+ }
+
+ /* skip remainder of loop if we idn;t retrieve any groups */
+
+ if (num_domain_entries == 0)
+ continue;
- if (groups.num_sam_entries == 0) continue;
+ /* setup the groups struct to contain all the groups
+ retrieved for this domain */
+
+ groups.num_sam_entries = num_domain_entries;
+ groups.sam_entries = sam_entries;
- /* Allocate some memory for extra data. Note that we limit
- account names to sizeof(fstring) = 128 characters. */
+ /* keep track the of the total number of groups seen so
+ far over all domains */
total_entries += groups.num_sam_entries;
- ted = Realloc(extra_data,
- sizeof(fstring) * total_entries);
-
+
+ /* Allocate some memory for extra data. Note that we limit
+ account names to sizeof(fstring) = 128 characters. */
+
+ ted = Realloc(extra_data, sizeof(fstring) * total_entries);
+
if (!ted) {
DEBUG(0,("winbindd_list_groups: failed to enlarge buffer!\n"));
- if (extra_data) free(extra_data);
+ if (extra_data)
+ free(extra_data);
return WINBINDD_ERROR;
- }
- else extra_data = ted;
+ } else
+ extra_data = ted;
/* Pack group list into extra data fields */
@@ -822,14 +854,12 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
/* Convert unistring to ascii */
- snprintf(name, sizeof(name), "%s%s%s",
- domain->name, lp_winbind_separator(),
- group_name);
+ snprintf(name, sizeof(name), "%s%s%s", domain->name,
+ lp_winbind_separator(), group_name);
/* Append to extra data */
- memcpy(&extra_data[extra_data_len], name,
- strlen(name));
+ memcpy(&extra_data[extra_data_len], name, strlen(name));
extra_data_len += strlen(name);
extra_data[extra_data_len++] = ',';