diff options
-rw-r--r-- | source3/nsswitch/winbindd_group.c | 116 |
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++] = ','; |