2 Unix SMB/CIFS implementation.
4 Winbind daemon for ntdom nss module
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Jeremy Allison 2001.
8 Copyright (C) Gerald (Jerry) Carter 2003.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #define DBGC_CLASS DBGC_WINBIND
30 /***************************************************************
31 Empty static struct for negative caching.
32 ****************************************************************/
34 /* Fill a grent structure from various other information */
36 static BOOL fill_grent(struct winbindd_gr *gr, const char *dom_name,
37 const char *gr_name, gid_t unix_gid)
39 fstring full_group_name;
41 fill_domain_username(full_group_name, dom_name, gr_name);
43 gr->gr_gid = unix_gid;
45 /* Group name and password */
47 safe_strcpy(gr->gr_name, full_group_name, sizeof(gr->gr_name) - 1);
48 safe_strcpy(gr->gr_passwd, "x", sizeof(gr->gr_passwd) - 1);
53 /* Fill in the group membership field of a NT group given by group_sid */
55 static BOOL fill_grent_mem(struct winbindd_domain *domain,
57 enum SID_NAME_USE group_name_type,
58 int *num_gr_mem, char **gr_mem, int *gr_mem_len)
60 DOM_SID **sid_mem = NULL;
62 uint32 *name_types = NULL;
63 unsigned int buf_len, buf_ndx, i;
64 char **names = NULL, *buf;
70 if (!(mem_ctx = talloc_init("fill_grent_mem(%s)", domain->name)))
73 /* Initialise group membership information */
75 DEBUG(10, ("group SID %s\n", sid_to_string(sid_string, group_sid)));
79 if ( !((group_name_type==SID_NAME_DOM_GRP) ||
80 ((group_name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
82 DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n",
83 sid_to_string(sid_string, group_sid), domain->name,
88 /* Lookup group members */
89 status = domain->methods->lookup_groupmem(domain, mem_ctx, group_sid, &num_names,
90 &sid_mem, &names, &name_types);
91 if (!NT_STATUS_IS_OK(status)) {
92 DEBUG(1, ("could not lookup membership for group rid %s in domain %s (error: %s)\n",
93 sid_to_string(sid_string, group_sid), domain->name, nt_errstr(status)));
98 DEBUG(10, ("looked up %d names\n", num_names));
100 if (DEBUGLEVEL >= 10) {
101 for (i = 0; i < num_names; i++)
102 DEBUG(10, ("\t%20s %s %d\n", names[i], sid_to_string(sid_string, sid_mem[i]),
106 /* Add members to list */
109 buf_len = buf_ndx = 0;
113 for (i = 0; i < num_names; i++) {
120 DEBUG(10, ("processing name %s\n", the_name));
122 /* FIXME: need to cope with groups within groups. These
123 occur in Universal groups on a Windows 2000 native mode
126 if (name_types[i] != SID_NAME_USER) {
127 DEBUG(3, ("name %s isn't a domain user\n", the_name));
131 /* Don't bother with machine accounts */
133 if (the_name[strlen(the_name) - 1] == '$') {
134 DEBUG(10, ("%s is machine account\n", the_name));
138 /* Append domain name */
140 fill_domain_username(name, domain->name, the_name);
144 /* Add to list or calculate buffer length */
147 buf_len += len + 1; /* List is comma separated */
149 DEBUG(10, ("buf_len + %d = %d\n", len + 1, buf_len));
151 DEBUG(10, ("appending %s at ndx %d\n", name, len));
152 safe_strcpy(&buf[buf_ndx], name, len);
159 /* Allocate buffer */
161 if (!buf && buf_len != 0) {
162 if (!(buf = malloc(buf_len))) {
163 DEBUG(1, ("out of memory\n"));
167 memset(buf, 0, buf_len);
171 if (buf && buf_ndx > 0) {
172 buf[buf_ndx - 1] = '\0';
176 *gr_mem_len = buf_len;
178 DEBUG(10, ("num_mem = %d, len = %d, mem = %s\n", *num_gr_mem,
179 buf_len, *num_gr_mem ? buf : "NULL"));
184 talloc_destroy(mem_ctx);
186 DEBUG(10, ("fill_grent_mem returning %d\n", result));
191 /* Return a group structure from a group name */
193 enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
196 struct winbindd_domain *domain;
197 enum SID_NAME_USE name_type;
198 fstring name_domain, name_group;
203 /* Ensure null termination */
204 state->request.data.groupname[sizeof(state->request.data.groupname)-1]='\0';
206 DEBUG(3, ("[%5d]: getgrnam %s\n", state->pid,
207 state->request.data.groupname));
209 /* Parse domain and groupname */
211 memset(name_group, 0, sizeof(fstring));
213 tmp = state->request.data.groupname;
214 if (!parse_domain_user(tmp, name_domain, name_group))
215 return WINBINDD_ERROR;
217 /* don't handle our own domain if we are a DC ( or a member of a Samba domain
218 that shares UNIX accounts). This code handles cases where
219 the account doesn't exist anywhere and gets passed on down the NSS layer */
221 if ( (IS_DC || lp_winbind_trusted_domains_only()) && strequal(name_domain, lp_workgroup()) ) {
222 DEBUG(7,("winbindd_getgrnam: rejecting getpwnam() for %s\\%s since I am on the PDC for this domain\n",
223 name_domain, name_group));
224 return WINBINDD_ERROR;
227 /* Get info for the domain */
229 if ((domain = find_domain_from_name(name_domain)) == NULL) {
230 DEBUG(0, ("could not get domain sid for domain %s\n",
232 return WINBINDD_ERROR;
235 /* Get rid and name type from name */
237 if (!winbindd_lookup_sid_by_name(domain, name_group, &group_sid,
239 DEBUG(1, ("group %s in domain %s does not exist\n",
240 name_group, name_domain));
241 return WINBINDD_ERROR;
244 if ( !((name_type==SID_NAME_DOM_GRP) ||
245 ((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
247 DEBUG(1, ("name '%s' is not a local or domain group: %d\n",
248 name_group, name_type));
249 return WINBINDD_ERROR;
252 if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &gid, 0))) {
253 DEBUG(1, ("error converting unix gid to sid\n"));
254 return WINBINDD_ERROR;
257 if (!fill_grent(&state->response.data.gr, name_domain,
259 !fill_grent_mem(domain, &group_sid, name_type,
260 &state->response.data.gr.num_gr_mem,
261 &gr_mem, &gr_mem_len)) {
262 return WINBINDD_ERROR;
265 /* Group membership lives at start of extra data */
267 state->response.data.gr.gr_mem_ofs = 0;
269 state->response.length += gr_mem_len;
270 state->response.extra_data = gr_mem;
275 /* Return a group structure from a gid number */
277 enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
279 struct winbindd_domain *domain;
281 enum SID_NAME_USE name_type;
287 DEBUG(3, ("[%5d]: getgrgid %d\n", state->pid,
288 state->request.data.gid));
290 /* Bug out if the gid isn't in the winbind range */
292 if ((state->request.data.gid < server_state.gid_low) ||
293 (state->request.data.gid > server_state.gid_high))
294 return WINBINDD_ERROR;
296 /* Get rid from gid */
297 if (!NT_STATUS_IS_OK(idmap_gid_to_sid(&group_sid, state->request.data.gid))) {
298 DEBUG(1, ("could not convert gid %d to rid\n",
299 state->request.data.gid));
300 return WINBINDD_ERROR;
303 /* Get name from sid */
305 if (!winbindd_lookup_name_by_sid(&group_sid, dom_name, group_name, &name_type)) {
306 DEBUG(1, ("could not lookup sid\n"));
307 return WINBINDD_ERROR;
310 /* Fill in group structure */
312 domain = find_domain_from_sid(&group_sid);
315 DEBUG(1,("Can't find domain from sid\n"));
316 return WINBINDD_ERROR;
319 if ( !((name_type==SID_NAME_DOM_GRP) ||
320 ((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
322 DEBUG(1, ("name '%s' is not a local or domain group: %d\n",
323 group_name, name_type));
324 return WINBINDD_ERROR;
327 if (!fill_grent(&state->response.data.gr, dom_name, group_name,
328 state->request.data.gid) ||
329 !fill_grent_mem(domain, &group_sid, name_type,
330 &state->response.data.gr.num_gr_mem,
331 &gr_mem, &gr_mem_len))
332 return WINBINDD_ERROR;
334 /* Group membership lives at start of extra data */
336 state->response.data.gr.gr_mem_ofs = 0;
338 state->response.length += gr_mem_len;
339 state->response.extra_data = gr_mem;
345 * set/get/endgrent functions
348 /* "Rewind" file pointer for group database enumeration */
350 enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state)
352 struct winbindd_domain *domain;
354 DEBUG(3, ("[%5d]: setgrent\n", state->pid));
356 /* Check user has enabled this */
358 if (!lp_winbind_enum_groups())
359 return WINBINDD_ERROR;
361 /* Free old static data if it exists */
363 if (state->getgrent_state != NULL) {
364 free_getent_state(state->getgrent_state);
365 state->getgrent_state = NULL;
368 /* Create sam pipes for each domain we know about */
370 for (domain = domain_list(); domain != NULL; domain = domain->next) {
371 struct getent_state *domain_state;
374 /* don't add our domaina if we are a PDC or if we
375 are a member of a Samba domain */
377 if ( (IS_DC || lp_winbind_trusted_domains_only())
378 && strequal(domain->name, lp_workgroup()) )
383 /* Create a state record for this domain */
385 if ((domain_state = (struct getent_state *)
386 malloc(sizeof(struct getent_state))) == NULL) {
387 DEBUG(1, ("winbindd_setgrent: malloc failed for domain_state!\n"));
388 return WINBINDD_ERROR;
391 ZERO_STRUCTP(domain_state);
393 fstrcpy(domain_state->domain_name, domain->name);
395 /* Add to list of open domains */
397 DLIST_ADD(state->getgrent_state, domain_state);
403 /* Close file pointer to ntdom group database */
405 enum winbindd_result winbindd_endgrent(struct winbindd_cli_state *state)
407 DEBUG(3, ("[%5d]: endgrent\n", state->pid));
409 free_getent_state(state->getgrent_state);
410 state->getgrent_state = NULL;
415 /* Get the list of domain groups and domain aliases for a domain. We fill in
416 the sam_entries and num_sam_entries fields with domain group information.
417 The dispinfo_ndx field is incremented to the index of the next group to
418 fetch. Return True if some groups were returned, False otherwise. */
420 #define MAX_FETCH_SAM_ENTRIES 100
422 static BOOL get_sam_group_entries(struct getent_state *ent)
426 struct acct_info *name_list = NULL, *tmp_name_list = NULL;
429 struct acct_info *sam_grp_entries = NULL;
430 struct winbindd_domain *domain;
432 if (ent->got_sam_entries)
435 if (!(mem_ctx = talloc_init("get_sam_group_entries(%s)",
436 ent->domain_name))) {
437 DEBUG(1, ("get_sam_group_entries: could not create talloc context!\n"));
441 /* Free any existing group info */
443 SAFE_FREE(ent->sam_entries);
444 ent->num_sam_entries = 0;
445 ent->got_sam_entries = True;
447 /* Enumerate domain groups */
451 if (!(domain = find_domain_from_name(ent->domain_name))) {
452 DEBUG(3, ("no such domain %s in get_sam_group_entries\n", ent->domain_name));
456 /* always get the domain global groups */
458 status = domain->methods->enum_dom_groups(domain, mem_ctx, &num_entries, &sam_grp_entries);
460 if (!NT_STATUS_IS_OK(status)) {
461 DEBUG(3, ("get_sam_group_entries: could not enumerate domain groups! Error: %s\n", nt_errstr(status)));
466 /* Copy entries into return buffer */
469 if ( !(name_list = malloc(sizeof(struct acct_info) * num_entries)) ) {
470 DEBUG(0,("get_sam_group_entries: Failed to malloc memory for %d domain groups!\n",
475 memcpy( name_list, sam_grp_entries, num_entries * sizeof(struct acct_info) );
478 ent->num_sam_entries = num_entries;
480 /* get the domain local groups if we are a member of a native win2k domain
481 and are not using LDAP to get the groups */
483 if ( lp_security() != SEC_ADS && domain->native_mode
484 && strequal(lp_workgroup(), domain->name) )
486 DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n"));
488 status = domain->methods->enum_local_groups(domain, mem_ctx, &num_entries, &sam_grp_entries);
490 if ( !NT_STATUS_IS_OK(status) ) {
491 DEBUG(3,("get_sam_group_entries: Failed to enumerate domain local groups!\n"));
495 DEBUG(4,("get_sam_group_entries: Returned %d local groups\n", num_entries));
497 /* Copy entries into return buffer */
500 if ( !(tmp_name_list = Realloc( name_list, sizeof(struct acct_info) * (ent->num_sam_entries+num_entries))) )
502 DEBUG(0,("get_sam_group_entries: Failed to realloc more memory for %d local groups!\n",
505 SAFE_FREE( name_list );
509 name_list = tmp_name_list;
511 memcpy( &name_list[ent->num_sam_entries], sam_grp_entries,
512 num_entries * sizeof(struct acct_info) );
515 ent->num_sam_entries += num_entries;
519 /* Fill in remaining fields */
521 ent->sam_entries = name_list;
522 ent->sam_entry_index = 0;
524 result = (ent->num_sam_entries > 0);
527 talloc_destroy(mem_ctx);
532 /* Fetch next group entry from ntdom database */
534 #define MAX_GETGRENT_GROUPS 500
536 enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
538 struct getent_state *ent;
539 struct winbindd_gr *group_list = NULL;
540 int num_groups, group_list_ndx = 0, i, gr_mem_list_len = 0;
541 char *new_extra_data, *gr_mem_list = NULL;
543 DEBUG(3, ("[%5d]: getgrent\n", state->pid));
545 /* Check user has enabled this */
547 if (!lp_winbind_enum_groups())
548 return WINBINDD_ERROR;
550 num_groups = MIN(MAX_GETGRENT_GROUPS, state->request.data.num_entries);
552 if ((state->response.extra_data =
553 malloc(num_groups * sizeof(struct winbindd_gr))) == NULL)
554 return WINBINDD_ERROR;
556 state->response.data.num_entries = 0;
558 group_list = (struct winbindd_gr *)state->response.extra_data;
560 if (!(ent = state->getgrent_state))
561 return WINBINDD_ERROR;
563 /* Start sending back groups */
565 for (i = 0; i < num_groups; i++) {
566 struct acct_info *name_list = NULL;
567 fstring domain_group_name;
571 char *gr_mem, *new_gr_mem_list;
573 struct winbindd_domain *domain;
575 /* Do we need to fetch another chunk of groups? */
579 DEBUG(10, ("entry_index = %d, num_entries = %d\n",
580 ent->sam_entry_index, ent->num_sam_entries));
582 if (ent->num_sam_entries == ent->sam_entry_index) {
584 while(ent && !get_sam_group_entries(ent)) {
585 struct getent_state *next_ent;
587 DEBUG(10, ("freeing state info for domain %s\n", ent->domain_name));
589 /* Free state information for this domain */
591 SAFE_FREE(ent->sam_entries);
593 next_ent = ent->next;
594 DLIST_REMOVE(state->getgrent_state, ent);
600 /* No more domains */
606 name_list = ent->sam_entries;
609 find_domain_from_name(ent->domain_name))) {
610 DEBUG(3, ("No such domain %s in winbindd_getgrent\n", ent->domain_name));
615 /* Lookup group info */
617 sid_copy(&group_sid, &domain->sid);
618 sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid);
620 if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &group_gid, 0))) {
622 DEBUG(1, ("could not look up gid for group %s\n",
623 name_list[ent->sam_entry_index].acct_name));
625 ent->sam_entry_index++;
629 DEBUG(10, ("got gid %d for group %x\n", group_gid,
630 name_list[ent->sam_entry_index].rid));
632 /* Fill in group entry */
634 fill_domain_username(domain_group_name, ent->domain_name,
635 name_list[ent->sam_entry_index].acct_name);
637 result = fill_grent(&group_list[group_list_ndx],
639 name_list[ent->sam_entry_index].acct_name,
642 /* Fill in group membership entry */
646 group_list[group_list_ndx].num_gr_mem = 0;
650 /* Get group membership */
651 if (state->request.cmd == WINBINDD_GETGRLST) {
654 sid_copy(&member_sid, &domain->sid);
655 sid_append_rid(&member_sid, name_list[ent->sam_entry_index].rid);
656 result = fill_grent_mem(
660 &group_list[group_list_ndx].num_gr_mem,
661 &gr_mem, &gr_mem_len);
666 /* Append to group membership list */
667 new_gr_mem_list = Realloc(
669 gr_mem_list_len + gr_mem_len);
671 if (!new_gr_mem_list && (group_list[group_list_ndx].num_gr_mem != 0)) {
672 DEBUG(0, ("out of memory\n"));
673 SAFE_FREE(gr_mem_list);
678 DEBUG(10, ("list_len = %d, mem_len = %d\n",
679 gr_mem_list_len, gr_mem_len));
681 gr_mem_list = new_gr_mem_list;
683 memcpy(&gr_mem_list[gr_mem_list_len], gr_mem,
688 group_list[group_list_ndx].gr_mem_ofs =
691 gr_mem_list_len += gr_mem_len;
694 ent->sam_entry_index++;
696 /* Add group to return list */
700 DEBUG(10, ("adding group num_entries = %d\n",
701 state->response.data.num_entries));
704 state->response.data.num_entries++;
706 state->response.length +=
707 sizeof(struct winbindd_gr);
710 DEBUG(0, ("could not lookup domain group %s\n",
715 /* Copy the list of group memberships to the end of the extra data */
717 if (group_list_ndx == 0)
720 new_extra_data = Realloc(
721 state->response.extra_data,
722 group_list_ndx * sizeof(struct winbindd_gr) + gr_mem_list_len);
724 if (!new_extra_data) {
725 DEBUG(0, ("out of memory\n"));
727 SAFE_FREE(state->response.extra_data);
728 SAFE_FREE(gr_mem_list);
730 return WINBINDD_ERROR;
733 state->response.extra_data = new_extra_data;
735 memcpy(&((char *)state->response.extra_data)
736 [group_list_ndx * sizeof(struct winbindd_gr)],
737 gr_mem_list, gr_mem_list_len);
739 SAFE_FREE(gr_mem_list);
741 state->response.length += gr_mem_list_len;
743 DEBUG(10, ("returning %d groups, length = %d\n",
744 group_list_ndx, gr_mem_list_len));
750 return (group_list_ndx > 0) ? WINBINDD_OK : WINBINDD_ERROR;
753 /* List domain groups without mapping to unix ids */
755 enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
757 uint32 total_entries = 0;
758 struct winbindd_domain *domain;
759 char *extra_data = NULL;
761 unsigned int extra_data_len = 0, i;
763 DEBUG(3, ("[%5d]: list groups\n", state->pid));
765 /* Enumerate over trusted domains */
767 for (domain = domain_list(); domain; domain = domain->next) {
768 struct getent_state groups;
772 /* Get list of sam groups */
774 fstrcpy(groups.domain_name, domain->name);
776 get_sam_group_entries(&groups);
778 if (groups.num_sam_entries == 0) {
779 /* this domain is empty or in an error state */
783 /* keep track the of the total number of groups seen so
784 far over all domains */
785 total_entries += groups.num_sam_entries;
787 /* Allocate some memory for extra data. Note that we limit
788 account names to sizeof(fstring) = 128 characters. */
789 ted = Realloc(extra_data, sizeof(fstring) * total_entries);
792 DEBUG(0,("failed to enlarge buffer!\n"));
793 SAFE_FREE(extra_data);
794 return WINBINDD_ERROR;
798 /* Pack group list into extra data fields */
799 for (i = 0; i < groups.num_sam_entries; i++) {
800 char *group_name = ((struct acct_info *)
801 groups.sam_entries)[i].acct_name;
804 fill_domain_username(name, domain->name, group_name);
805 /* Append to extra data */
806 memcpy(&extra_data[extra_data_len], name,
808 extra_data_len += strlen(name);
809 extra_data[extra_data_len++] = ',';
812 free(groups.sam_entries);
815 /* Assign extra_data fields in response structure */
817 extra_data[extra_data_len - 1] = '\0';
818 state->response.extra_data = extra_data;
819 state->response.length += extra_data_len;
822 /* No domains may have responded but that's still OK so don't
828 /* Get user supplementary groups. This is much quicker than trying to
829 invert the groups database. We merge the groups from the gids and
830 other_sids info3 fields as trusted domain, universal group
831 memberships, and nested groups (win2k native mode only) are not
832 returned by the getgroups RPC call but are present in the info3. */
834 enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
836 fstring name_domain, name_user;
837 DOM_SID user_sid, group_sid;
838 enum SID_NAME_USE name_type;
839 uint32 num_groups = 0;
842 DOM_SID **user_grpsids;
843 struct winbindd_domain *domain;
844 enum winbindd_result result = WINBINDD_ERROR;
848 NET_USER_INFO_3 *info3 = NULL;
850 /* Ensure null termination */
851 state->request.data.username[sizeof(state->request.data.username)-1]='\0';
853 DEBUG(3, ("[%5d]: getgroups %s\n", state->pid,
854 state->request.data.username));
856 if (!(mem_ctx = talloc_init("winbindd_getgroups(%s)",
857 state->request.data.username)))
858 return WINBINDD_ERROR;
860 /* Parse domain and username */
862 if (!parse_domain_user(state->request.data.username, name_domain,
866 /* Get info for the domain */
868 if ((domain = find_domain_from_name(name_domain)) == NULL) {
869 DEBUG(0, ("could not find domain entry for domain %s\n",
874 /* Get rid and name type from name. The following costs 1 packet */
876 if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid,
878 DEBUG(1, ("user '%s' does not exist\n", name_user));
882 if (name_type != SID_NAME_USER) {
883 DEBUG(1, ("name '%s' is not a user name: %d\n",
884 name_user, name_type));
888 /* Treat the info3 cache as authoritative as the
889 lookup_usergroups() function may return cached data. */
891 if ((info3 = netsamlogon_cache_get(mem_ctx, &user_sid))) {
893 DEBUG(10, ("winbindd_getgroups: info3 has %d groups, %d other sids\n",
894 info3->num_groups2, info3->num_other_sids));
896 num_groups = info3->num_other_sids + info3->num_groups2;
897 gid_list = calloc(sizeof(gid_t), num_groups);
899 /* Go through each other sid and convert it to a gid */
901 for (i = 0; i < info3->num_other_sids; i++) {
904 enum SID_NAME_USE sid_type;
906 /* Is this sid known to us? It can either be
907 a trusted domain sid or a foreign sid. */
909 if (!winbindd_lookup_name_by_sid( &info3->other_sids[i].sid,
910 dom_name, name, &sid_type))
912 DEBUG(10, ("winbindd_getgroups: could not lookup name for %s\n",
913 sid_string_static(&info3->other_sids[i].sid)));
917 /* Check it is a domain group or an alias (domain local group)
918 in a win2k native mode domain. */
920 if ( !((sid_type==SID_NAME_DOM_GRP) ||
921 ((sid_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
923 DEBUG(10, ("winbindd_getgroups: sid type %d "
924 "for %s is not a domain group\n",
927 &info3->other_sids[i].sid)));
933 if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&info3->other_sids[i].sid, &gid_list[num_gids], 0)) )
935 DEBUG(10, ("winbindd_getgroups: could not map sid %s to gid\n",
936 sid_string_static(&info3->other_sids[i].sid)));
940 /* We've jumped through a lot of hoops to get here */
942 DEBUG(10, ("winbindd_getgroups: mapped other sid %s to "
943 "gid %d\n", sid_string_static(
944 &info3->other_sids[i].sid),
945 gid_list[num_gids]));
950 for (i = 0; i < info3->num_groups2; i++) {
952 /* create the group SID */
954 sid_copy( &group_sid, &domain->sid );
955 sid_append_rid( &group_sid, info3->gids[i].g_rid );
957 if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &gid_list[num_gids], 0)) ) {
958 DEBUG(10, ("winbindd_getgroups: could not map sid %s to gid\n",
959 sid_string_static(&group_sid)));
968 status = domain->methods->lookup_usergroups(domain, mem_ctx,
969 &user_sid, &num_groups,
971 if (!NT_STATUS_IS_OK(status))
974 gid_list = malloc(sizeof(gid_t) * num_groups);
976 if (state->response.extra_data)
979 for (i = 0; i < num_groups; i++) {
980 if (!NT_STATUS_IS_OK(idmap_sid_to_gid(user_grpsids[i], &gid_list[num_gids], 0))) {
981 DEBUG(1, ("unable to convert group sid %s to gid\n",
982 sid_string_static(user_grpsids[i])));
989 /* Send data back to client */
991 state->response.data.num_entries = num_gids;
992 state->response.extra_data = gid_list;
993 state->response.length += num_gids * sizeof(gid_t);
995 result = WINBINDD_OK;
999 talloc_destroy(mem_ctx);