mirror of
https://github.com/samba-team/samba.git
synced 2024-12-27 03:21:53 +03:00
7738941ccf
(This used to be commit 0189af5442
)
766 lines
22 KiB
C
766 lines
22 KiB
C
/*
|
|
Unix SMB/Netbios implementation.
|
|
Version 2.0
|
|
|
|
Winbind daemon for ntdom nss module
|
|
|
|
Copyright (C) Tim Potter 2000
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include "winbindd.h"
|
|
|
|
/* Fill a grent structure from various other information */
|
|
|
|
static void winbindd_fill_grent(struct winbindd_gr *gr, char *gr_name,
|
|
gid_t unix_gid)
|
|
{
|
|
/* Fill in uid/gid */
|
|
|
|
gr->gr_gid = unix_gid;
|
|
|
|
/* Group name and password */
|
|
|
|
safe_strcpy(gr->gr_name, gr_name, sizeof(gr->gr_name) - 1);
|
|
safe_strcpy(gr->gr_passwd, "x", sizeof(gr->gr_passwd) - 1);
|
|
}
|
|
|
|
/* Fill in group membership */
|
|
|
|
struct grent_mem_group {
|
|
uint32 rid;
|
|
enum SID_NAME_USE name_type;
|
|
fstring domain_name;
|
|
struct winbindd_domain *domain;
|
|
struct grent_mem_group *prev, *next;
|
|
};
|
|
|
|
struct grent_mem_list {
|
|
fstring name;
|
|
struct grent_mem_list *prev, *next;
|
|
};
|
|
|
|
/* Name comparison function for qsort() */
|
|
|
|
static int name_comp(struct grent_mem_list *n1, struct grent_mem_list *n2)
|
|
{
|
|
/* Silly cases */
|
|
|
|
if (!n1 && !n2) return 0;
|
|
if (!n1) return -1;
|
|
if (!n2) return 1;
|
|
|
|
return strcmp(n1->name, n2->name);
|
|
}
|
|
|
|
static struct grent_mem_list *sort_groupmem_list(struct grent_mem_list *list,
|
|
int num_gr_mem)
|
|
{
|
|
struct grent_mem_list *groupmem_array, *temp;
|
|
int i;
|
|
|
|
/* Allocate and zero an array to hold sorted entries */
|
|
|
|
if ((groupmem_array = malloc(num_gr_mem *
|
|
sizeof(struct grent_mem_list))) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
memset((char *)groupmem_array, 0, num_gr_mem *
|
|
sizeof(struct grent_mem_list));
|
|
|
|
/* Copy list to array */
|
|
|
|
for(temp = list, i = 0; temp && i < num_gr_mem; temp = temp->next, i++) {
|
|
fstrcpy(groupmem_array[i].name, temp->name);
|
|
}
|
|
|
|
/* Sort array */
|
|
|
|
qsort(groupmem_array, num_gr_mem, sizeof(struct grent_mem_list),
|
|
name_comp);
|
|
|
|
/* Fix up resulting array to a linked list and return it */
|
|
|
|
for(i = 0; i < num_gr_mem; i++) {
|
|
|
|
/* Fix up previous link */
|
|
|
|
if (i != 0) {
|
|
groupmem_array[i].prev = &groupmem_array[i - 1];
|
|
}
|
|
|
|
/* Fix up next link */
|
|
|
|
if (i != (num_gr_mem - 1)) {
|
|
groupmem_array[i].next = &groupmem_array[i + 1];
|
|
}
|
|
}
|
|
|
|
return groupmem_array;
|
|
}
|
|
|
|
static BOOL winbindd_fill_grent_mem(struct winbindd_domain *domain,
|
|
uint32 group_rid,
|
|
enum SID_NAME_USE group_name_type,
|
|
struct winbindd_response *response)
|
|
{
|
|
struct grent_mem_group *done_groups = NULL, *todo_groups = NULL;
|
|
struct grent_mem_group *temp_group;
|
|
struct grent_mem_list *groupmem_list = NULL;
|
|
struct winbindd_gr *gr;
|
|
|
|
if (response) {
|
|
gr = &response->data.gr;
|
|
} else {
|
|
return False;
|
|
}
|
|
|
|
/* Initialise group membership information */
|
|
|
|
gr->num_gr_mem = 0;
|
|
|
|
/* Add first group to todo_groups list */
|
|
|
|
if ((temp_group =
|
|
(struct grent_mem_group *)malloc(sizeof(*temp_group))) == NULL) {
|
|
return False;
|
|
}
|
|
|
|
ZERO_STRUCTP(temp_group);
|
|
|
|
temp_group->rid = group_rid;
|
|
temp_group->name_type = group_name_type;
|
|
temp_group->domain = domain;
|
|
fstrcpy(temp_group->domain_name, domain->name);
|
|
|
|
DLIST_ADD(todo_groups, temp_group);
|
|
|
|
/* Iterate over all groups to find members of */
|
|
|
|
while(todo_groups != NULL) {
|
|
struct grent_mem_group *current_group = todo_groups;
|
|
uint32 num_names = 0, *rid_mem = NULL;
|
|
enum SID_NAME_USE *name_types = NULL;
|
|
|
|
DOM_SID **sids = NULL;
|
|
char **names = NULL;
|
|
BOOL done_group;
|
|
int i;
|
|
|
|
/* Check we haven't looked up this group before */
|
|
|
|
done_group = 0;
|
|
|
|
for (temp_group = done_groups; temp_group != NULL;
|
|
temp_group = temp_group->next) {
|
|
|
|
if ((temp_group->rid == current_group->rid) &&
|
|
(strcmp(temp_group->domain_name,
|
|
current_group->domain_name) == 0)) {
|
|
|
|
done_group = 1;
|
|
}
|
|
}
|
|
|
|
if (done_group) goto cleanup;
|
|
|
|
/* Lookup group membership for the current group */
|
|
|
|
if (current_group->name_type == SID_NAME_DOM_GRP) {
|
|
|
|
if (!winbindd_lookup_groupmem(current_group->domain,
|
|
current_group->rid, &num_names,
|
|
&rid_mem, &names, &name_types)) {
|
|
|
|
DEBUG(1, ("fill_grent_mem(): could not lookup membership "
|
|
"for group rid %d in domain %s\n",
|
|
current_group->rid,
|
|
current_group->domain->name));
|
|
|
|
/* Exit if we cannot lookup the membership for the group
|
|
this function was called to look at */
|
|
|
|
if (current_group->rid == group_rid) {
|
|
return False;
|
|
} else {
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (current_group->name_type == SID_NAME_ALIAS) {
|
|
|
|
if (!winbindd_lookup_aliasmem(current_group->domain,
|
|
current_group->rid, &num_names,
|
|
&sids, &names, &name_types)) {
|
|
|
|
DEBUG(1, ("fill_grent_mem(): group rid %d not a local group\n",
|
|
group_rid));
|
|
|
|
/* Exit if we cannot lookup the membership for the group
|
|
this function was called to look at */
|
|
|
|
if (current_group->rid == group_rid) {
|
|
return False;
|
|
} else {
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Now for each member of the group, add it to the group list if it
|
|
is a user, otherwise push it onto the todo_group list if it is a
|
|
group or an alias. */
|
|
|
|
for (i = 0; i < num_names; i++) {
|
|
enum SID_NAME_USE name_type;
|
|
fstring name_part1, name_part2;
|
|
char *name_dom, *name_user, *the_name;
|
|
struct winbindd_domain *name_domain;
|
|
|
|
/* Lookup name */
|
|
|
|
ZERO_STRUCT(name_part1);
|
|
ZERO_STRUCT(name_part2);
|
|
|
|
the_name = names[i];
|
|
parse_domain_user(the_name, name_part1, name_part2);
|
|
|
|
if (strcmp(name_part1, "") != 0) {
|
|
name_dom = name_part1;
|
|
name_user = name_part2;
|
|
|
|
if ((name_domain = find_domain_from_name(name_dom)) == NULL) {
|
|
DEBUG(0, ("unable to look up domain record for domain "
|
|
"%s\n", name_dom));
|
|
continue;
|
|
}
|
|
|
|
} else {
|
|
name_dom = current_group->domain->name;
|
|
name_user = name_part2;
|
|
name_domain = current_group->domain;
|
|
}
|
|
|
|
if (winbindd_lookup_sid_by_name(name_domain, name_user, NULL,
|
|
&name_type) == WINBINDD_OK) {
|
|
|
|
/* Check name type */
|
|
|
|
if (name_type == SID_NAME_USER) {
|
|
struct grent_mem_list *entry;
|
|
|
|
/* Add to group membership list */
|
|
|
|
if ((entry = (struct grent_mem_list *)
|
|
malloc(sizeof(*entry))) != NULL) {
|
|
|
|
/* Create name */
|
|
slprintf(entry->name, sizeof(entry->name),
|
|
"%s%s%s", name_dom, lp_winbind_separator(), name_user);
|
|
|
|
/* Add to list */
|
|
|
|
DLIST_ADD(groupmem_list, entry);
|
|
gr->num_gr_mem++;
|
|
}
|
|
|
|
} else {
|
|
struct grent_mem_group *todo_group;
|
|
DOM_SID todo_sid;
|
|
uint32 todo_rid;
|
|
|
|
/* Add group to todo list */
|
|
|
|
if (winbindd_lookup_sid_by_name(name_domain, names[i],
|
|
&todo_sid, &name_type)
|
|
== WINBINDD_OK) {
|
|
|
|
/* Fill in group entry */
|
|
|
|
sid_split_rid(&todo_sid, &todo_rid);
|
|
|
|
if ((todo_group = (struct grent_mem_group *)
|
|
malloc(sizeof(*todo_group))) != NULL) {
|
|
|
|
ZERO_STRUCTP(todo_group);
|
|
|
|
todo_group->rid = todo_rid;
|
|
todo_group->name_type = name_type;
|
|
todo_group->domain = name_domain;
|
|
|
|
fstrcpy(todo_group->domain_name, name_dom);
|
|
|
|
DLIST_ADD(todo_groups, todo_group);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
|
|
/* Remove group from todo list and add to done_groups list */
|
|
|
|
DLIST_REMOVE(todo_groups, current_group);
|
|
DLIST_ADD(done_groups, current_group);
|
|
|
|
/* Free memory allocated in winbindd_lookup_{alias,group}mem() */
|
|
|
|
safe_free(name_types);
|
|
safe_free(rid_mem);
|
|
|
|
free_char_array(num_names, names);
|
|
free_sid_array(num_names, sids);
|
|
}
|
|
|
|
/* Free done groups list */
|
|
|
|
temp_group = done_groups;
|
|
|
|
if (temp_group != NULL) {
|
|
while (temp_group != NULL) {
|
|
struct grent_mem_group *next;
|
|
|
|
DLIST_REMOVE(done_groups, temp_group);
|
|
next = temp_group->next;
|
|
|
|
free(temp_group);
|
|
temp_group = next;
|
|
}
|
|
}
|
|
|
|
/* Remove duplicates from group member list. */
|
|
|
|
if (gr->num_gr_mem > 0) {
|
|
struct grent_mem_list *sorted_groupmem_list, *temp;
|
|
int extra_data_len = 0;
|
|
fstring prev_name;
|
|
char *head;
|
|
|
|
/* Sort list */
|
|
|
|
sorted_groupmem_list = sort_groupmem_list(groupmem_list,
|
|
gr->num_gr_mem);
|
|
/* Remove duplicates by iteration */
|
|
|
|
fstrcpy(prev_name, "");
|
|
|
|
for(temp = sorted_groupmem_list; temp; temp = temp->next) {
|
|
if (strequal(temp->name, prev_name)) {
|
|
|
|
/* Got a duplicate name - delete it. Don't panic as we're
|
|
only adjusting the prev and next pointers so memory
|
|
allocation is not messed up. */
|
|
|
|
DLIST_REMOVE(sorted_groupmem_list, temp);
|
|
gr->num_gr_mem--;
|
|
|
|
} else {
|
|
|
|
/* Got a unique name - count how long it is */
|
|
|
|
extra_data_len += strlen(temp->name) + 1;
|
|
}
|
|
}
|
|
|
|
extra_data_len++; /* Don't forget null a terminator */
|
|
|
|
/* Convert sorted list into extra data field to send back to ntdom
|
|
client. Add one to extra_data_len for null termination */
|
|
|
|
if ((response->extra_data = malloc(extra_data_len))) {
|
|
|
|
/* Initialise extra data */
|
|
|
|
memset(response->extra_data, 0, extra_data_len);
|
|
|
|
head = response->extra_data;
|
|
|
|
/* Fill in extra data */
|
|
|
|
for(temp = sorted_groupmem_list; temp; temp = temp->next) {
|
|
int len = strlen(temp->name) + 1;
|
|
|
|
safe_strcpy(head, temp->name, len);
|
|
head[len - 1] = ',';
|
|
head += len;
|
|
}
|
|
|
|
*head = '\0';
|
|
|
|
/* Update response length */
|
|
|
|
response->length = sizeof(struct winbindd_response) +
|
|
extra_data_len;
|
|
}
|
|
|
|
/* Free memory for sorted_groupmem_list. It was allocated as an
|
|
array in sort_groupmem_list() so can be freed in one go. */
|
|
|
|
free(sorted_groupmem_list);
|
|
|
|
/* Free groupmem_list */
|
|
|
|
temp = groupmem_list;
|
|
|
|
while (temp != NULL) {
|
|
struct grent_mem_list *next;
|
|
|
|
DLIST_REMOVE(groupmem_list, temp);
|
|
next = temp->next;
|
|
|
|
free(temp);
|
|
temp = next;
|
|
}
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
/* Return a group structure from a group name */
|
|
|
|
enum winbindd_result winbindd_getgrnam_from_group(struct winbindd_cli_state *state)
|
|
{
|
|
DOM_SID group_sid;
|
|
struct winbindd_domain *domain;
|
|
enum SID_NAME_USE name_type;
|
|
uint32 group_rid;
|
|
fstring name_domain, name_group, name;
|
|
char *tmp;
|
|
gid_t gid;
|
|
int extra_data_len;
|
|
|
|
/* Parse domain and groupname */
|
|
|
|
memset(name_group, 0, sizeof(fstring));
|
|
|
|
tmp = state->request.data.groupname;
|
|
parse_domain_user(tmp, name_domain, name_group);
|
|
|
|
/* Reject names that don't have a domain - i.e name_domain contains the
|
|
entire name. */
|
|
|
|
if (strequal(name_group, "")) {
|
|
return WINBINDD_ERROR;
|
|
}
|
|
|
|
/* Get info for the domain */
|
|
|
|
if ((domain = find_domain_from_name(name_domain)) == NULL) {
|
|
DEBUG(0, ("getgrname_from_group(): could not get domain sid for "
|
|
"domain %s\n", name_domain));
|
|
return WINBINDD_ERROR;
|
|
}
|
|
|
|
/* Check for cached user entry */
|
|
|
|
if (winbindd_fetch_group_cache_entry(name_domain, name_group,
|
|
&state->response.data.gr,
|
|
&state->response.extra_data,
|
|
&extra_data_len)) {
|
|
state->response.length += extra_data_len;
|
|
return WINBINDD_OK;
|
|
}
|
|
|
|
slprintf(name, sizeof(name), "%s\\%s", name_domain, name_group);
|
|
|
|
/* Get rid and name type from name */
|
|
|
|
if (!winbindd_lookup_sid_by_name(domain, name, &group_sid,
|
|
&name_type)) {
|
|
DEBUG(1, ("group %s in domain %s does not exist\n", name_group,
|
|
name_domain));
|
|
return WINBINDD_ERROR;
|
|
}
|
|
|
|
if ((name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_DOM_GRP)) {
|
|
DEBUG(1, ("from_group: name '%s' is not a local or domain group: %d\n",
|
|
name_group, name_type));
|
|
return WINBINDD_ERROR;
|
|
}
|
|
|
|
/* Fill in group structure */
|
|
|
|
sid_split_rid(&group_sid, &group_rid);
|
|
|
|
if (!winbindd_idmap_get_gid_from_rid(domain->name, group_rid, &gid)) {
|
|
DEBUG(1, ("error sursing unix gid for sid\n"));
|
|
return WINBINDD_ERROR;
|
|
}
|
|
|
|
winbindd_fill_grent(&state->response.data.gr,
|
|
state->request.data.groupname, gid);
|
|
|
|
if (!winbindd_fill_grent_mem(domain, group_rid, name_type,
|
|
&state->response)) {
|
|
return WINBINDD_ERROR;
|
|
}
|
|
|
|
/* Update cached group info */
|
|
|
|
winbindd_fill_group_cache_entry(name_domain, name_group,
|
|
&state->response.data.gr,
|
|
state->response.extra_data,
|
|
state->response.length -
|
|
sizeof(struct winbindd_response));
|
|
|
|
return WINBINDD_OK;
|
|
}
|
|
|
|
/* Return a group structure from a gid number */
|
|
|
|
enum winbindd_result winbindd_getgrnam_from_gid(struct winbindd_cli_state
|
|
*state)
|
|
{
|
|
struct winbindd_domain *domain;
|
|
DOM_SID group_sid;
|
|
enum SID_NAME_USE name_type;
|
|
fstring group_name;
|
|
uint32 group_rid;
|
|
int extra_data_len;
|
|
|
|
/* Get rid from gid */
|
|
if (!winbindd_idmap_get_rid_from_gid(state->request.data.gid, &group_rid,
|
|
&domain)) {
|
|
DEBUG(1, ("Could not convert gid %d to rid\n",
|
|
state->request.data.gid));
|
|
return WINBINDD_ERROR;
|
|
}
|
|
|
|
/* try a cached entry */
|
|
if (winbindd_fetch_gid_cache_entry(domain->name, state->request.data.gid,
|
|
&state->response.data.gr,
|
|
&state->response.extra_data,
|
|
&extra_data_len)) {
|
|
state->response.length += extra_data_len;
|
|
return WINBINDD_OK;
|
|
}
|
|
|
|
/* Get sid from gid */
|
|
|
|
sid_copy(&group_sid, &domain->sid);
|
|
sid_append_rid(&group_sid, group_rid);
|
|
|
|
if (!winbindd_lookup_name_by_sid(domain, &group_sid, group_name,
|
|
&name_type)) {
|
|
DEBUG(1, ("Could not lookup sid\n"));
|
|
return WINBINDD_ERROR;
|
|
}
|
|
|
|
if (strcmp(lp_winbind_separator(),"\\")) {
|
|
string_sub(group_name, "\\", lp_winbind_separator(), sizeof(fstring));
|
|
}
|
|
|
|
if (!((name_type == SID_NAME_ALIAS) || (name_type == SID_NAME_DOM_GRP))) {
|
|
DEBUG(1, ("from_gid: name '%s' is not a local or domain group: %d\n",
|
|
group_name, name_type));
|
|
return WINBINDD_ERROR;
|
|
}
|
|
|
|
/* Fill in group structure */
|
|
|
|
winbindd_fill_grent(&state->response.data.gr, group_name,
|
|
state->request.data.gid);
|
|
|
|
if (!winbindd_fill_grent_mem(domain, group_rid, name_type,
|
|
&state->response)) {
|
|
return WINBINDD_ERROR;
|
|
}
|
|
|
|
/* Update cached group info */
|
|
winbindd_fill_gid_cache_entry(domain->name, state->request.data.gid,
|
|
&state->response.data.gr,
|
|
state->response.extra_data,
|
|
state->response.length -
|
|
sizeof(struct winbindd_response));
|
|
|
|
return WINBINDD_OK;
|
|
}
|
|
|
|
/*
|
|
* set/get/endgrent functions
|
|
*/
|
|
|
|
/* "Rewind" file pointer for group database enumeration */
|
|
|
|
enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state)
|
|
{
|
|
struct winbindd_domain *tmp;
|
|
|
|
if (state == NULL) return WINBINDD_ERROR;
|
|
|
|
/* Free old static data if it exists */
|
|
|
|
if (state->getgrent_state != NULL) {
|
|
free_getent_state(state->getgrent_state);
|
|
state->getgrent_state = NULL;
|
|
}
|
|
|
|
/* Create sam pipes for each domain we know about */
|
|
|
|
for (tmp = domain_list; tmp != NULL; tmp = tmp->next) {
|
|
struct getent_state *domain_state;
|
|
|
|
/* Skip domains other than WINBINDD_DOMAIN environment variable */
|
|
|
|
if ((strcmp(state->request.domain, "") != 0) &&
|
|
(strcmp(state->request.domain, tmp->name) != 0)) {
|
|
continue;
|
|
}
|
|
|
|
/* Create a state record for this domain */
|
|
|
|
if ((domain_state = (struct getent_state *)
|
|
malloc(sizeof(struct getent_state))) == NULL) {
|
|
|
|
return WINBINDD_ERROR;
|
|
}
|
|
|
|
ZERO_STRUCTP(domain_state);
|
|
|
|
/* Add to list of open domains */
|
|
|
|
domain_state->domain = tmp;
|
|
DLIST_ADD(state->getgrent_state, domain_state);
|
|
}
|
|
|
|
return WINBINDD_OK;
|
|
}
|
|
|
|
/* Close file pointer to ntdom group database */
|
|
|
|
enum winbindd_result winbindd_endgrent(struct winbindd_cli_state *state)
|
|
{
|
|
if (state == NULL) return WINBINDD_ERROR;
|
|
|
|
free_getent_state(state->getgrent_state);
|
|
state->getgrent_state = NULL;
|
|
|
|
return WINBINDD_OK;
|
|
}
|
|
|
|
/* Fetch next group entry from netdom database */
|
|
|
|
enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
|
|
{
|
|
if (state == NULL) return WINBINDD_ERROR;
|
|
|
|
/* Process the current head of the getent_state list */
|
|
|
|
while(state->getgrent_state != NULL) {
|
|
struct getent_state *ent = state->getgrent_state;
|
|
|
|
/* Get list of entries if we haven't already got them */
|
|
|
|
if (!ent->got_sam_entries) {
|
|
uint32 status, start_ndx = 0, start_ndx2 = 0;
|
|
|
|
if (!winbindd_fetch_group_cache(ent->domain->name,
|
|
&ent->sam_entries,
|
|
&ent->num_sam_entries)) {
|
|
|
|
/* Fetch group entries */
|
|
|
|
if (!domain_handles_open(ent->domain)) goto cleanup;
|
|
|
|
/* Enumerate domain groups */
|
|
|
|
do {
|
|
status =
|
|
samr_enum_dom_groups(&ent->domain->sam_dom_handle,
|
|
&start_ndx, 0x100000,
|
|
&ent->sam_entries,
|
|
&ent->num_sam_entries);
|
|
} while (status == STATUS_MORE_ENTRIES);
|
|
|
|
/* Enumerate domain aliases */
|
|
|
|
do {
|
|
status =
|
|
samr_enum_dom_aliases(&ent->domain->sam_dom_handle,
|
|
&start_ndx2, 0x100000,
|
|
&ent->sam_entries,
|
|
&ent->num_sam_entries);
|
|
} while (status == STATUS_MORE_ENTRIES);
|
|
|
|
/* Fill cache with received entries */
|
|
|
|
winbindd_fill_group_cache(ent->domain->name, ent->sam_entries,
|
|
ent->num_sam_entries);
|
|
}
|
|
|
|
ent->got_sam_entries = True;
|
|
}
|
|
|
|
/* Send back a group */
|
|
|
|
while (ent->sam_entry_index < ent->num_sam_entries) {
|
|
enum winbindd_result result;
|
|
fstring domain_group_name;
|
|
char *group_name = (ent->sam_entries)
|
|
[ent->sam_entry_index].acct_name;
|
|
|
|
/* Prepend domain to name */
|
|
|
|
slprintf(domain_group_name, sizeof(domain_group_name),
|
|
"%s%s%s", ent->domain->name, lp_winbind_separator(), group_name);
|
|
|
|
/* Get group entry from group name */
|
|
|
|
fstrcpy(state->request.data.groupname, domain_group_name);
|
|
result = winbindd_getgrnam_from_group(state);
|
|
|
|
ent->sam_entry_index++;
|
|
|
|
if (result == WINBINDD_OK) {
|
|
return result;
|
|
}
|
|
|
|
/* Try next group */
|
|
|
|
DEBUG(1, ("could not getgrnam_from_group for group name %s\n",
|
|
domain_group_name));
|
|
}
|
|
|
|
/* We've exhausted all users for this pipe - close it down and
|
|
start on the next one. */
|
|
|
|
cleanup:
|
|
|
|
/* Free mallocated memory for sam entries. The data stored here
|
|
may have been allocated from the cache. */
|
|
|
|
if (ent->sam_entries != NULL) free(ent->sam_entries);
|
|
ent->sam_entries = NULL;
|
|
|
|
/* Free state information for this domain */
|
|
|
|
{
|
|
struct getent_state *old_ent;
|
|
|
|
old_ent = state->getgrent_state;
|
|
DLIST_REMOVE(state->getgrent_state, state->getgrent_state);
|
|
free(old_ent);
|
|
}
|
|
}
|
|
|
|
/* Out of pipes so we're done */
|
|
|
|
return WINBINDD_ERROR;
|
|
}
|