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.
9
Copyright (C) Volker Lendecke 2005
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 3 of the License, or
14
(at your option) any later version.
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
21
You should have received a copy of the GNU General Public License
22
along with this program. If not, see <http://www.gnu.org/licenses/>.
29
#define DBGC_CLASS DBGC_WINBIND
31
static void add_member(const char *domain, const char *user,
32
char **pp_members, size_t *p_num_members)
37
fill_domain_username(name, domain, user, True);
41
safe_strcat(name, ",", sizeof(name)-1);
42
string_append(pp_members, name);
46
/**********************************************************************
47
Add member users resulting from sid. Expand if it is a domain group.
48
**********************************************************************/
50
static void add_expanded_sid(const DOM_SID *sid,
52
size_t *p_num_members)
56
struct winbindd_domain *domain;
59
char *domain_name = NULL;
61
enum lsa_SidType type;
70
TALLOC_CTX *mem_ctx = talloc_init("add_expanded_sid");
72
if (mem_ctx == NULL) {
73
DEBUG(1, ("talloc_init failed\n"));
77
sid_copy(&dom_sid, sid);
78
sid_split_rid(&dom_sid, &rid);
80
domain = find_lookup_domain_from_sid(sid);
83
DEBUG(3, ("Could not find domain for sid %s\n",
84
sid_string_dbg(sid)));
88
result = domain->methods->sid_to_name(domain, mem_ctx, sid,
89
&domain_name, &name, &type);
91
if (!NT_STATUS_IS_OK(result)) {
92
DEBUG(3, ("sid_to_name failed for sid %s\n",
93
sid_string_dbg(sid)));
97
DEBUG(10, ("Found name %s, type %d\n", name, type));
99
if (type == SID_NAME_USER) {
100
add_member(domain_name, name, pp_members, p_num_members);
104
if (type != SID_NAME_DOM_GRP) {
105
DEBUG(10, ("Alias member %s neither user nor group, ignore\n",
110
/* Expand the domain group, this must be done via the target domain */
112
domain = find_domain_from_sid(sid);
114
if (domain == NULL) {
115
DEBUG(3, ("Could not find domain from SID %s\n",
116
sid_string_dbg(sid)));
120
result = domain->methods->lookup_groupmem(domain, mem_ctx,
125
if (!NT_STATUS_IS_OK(result)) {
126
DEBUG(10, ("Could not lookup group members for %s: %s\n",
127
name, nt_errstr(result)));
131
for (i=0; i<num_names; i++) {
132
DEBUG(10, ("Adding group member SID %s\n",
133
sid_string_dbg(&sid_mem[i])));
135
if (types[i] != SID_NAME_USER) {
136
DEBUG(1, ("Hmmm. Member %s of group %s is no user. "
137
"Ignoring.\n", names[i], name));
141
add_member(NULL, names[i], pp_members, p_num_members);
145
talloc_destroy(mem_ctx);
149
static bool fill_passdb_alias_grmem(struct winbindd_domain *domain,
150
DOM_SID *group_sid, size_t *num_gr_mem,
151
char **gr_mem, size_t *gr_mem_len)
154
size_t i, num_members;
160
if (!NT_STATUS_IS_OK(pdb_enum_aliasmem(group_sid, &members,
164
for (i=0; i<num_members; i++) {
165
add_expanded_sid(&members[i], gr_mem, num_gr_mem);
168
TALLOC_FREE(members);
170
if (*gr_mem != NULL) {
173
/* We have at least one member, strip off the last "," */
174
len = strlen(*gr_mem);
175
(*gr_mem)[len-1] = '\0';
182
/* Fill a grent structure from various other information */
184
static bool fill_grent(TALLOC_CTX *mem_ctx, struct winbindd_gr *gr,
185
const char *dom_name,
186
char *gr_name, gid_t unix_gid)
188
fstring full_group_name;
189
char *mapped_name = NULL;
190
struct winbindd_domain *domain = find_domain_from_name_noinit(dom_name);
191
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
193
nt_status = normalize_name_map(mem_ctx, domain, gr_name,
196
/* Basic whitespace replacement */
197
if (NT_STATUS_IS_OK(nt_status)) {
198
fill_domain_username(full_group_name, dom_name,
201
/* Mapped to an aliase */
202
else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) {
203
fstrcpy(full_group_name, mapped_name);
207
fill_domain_username( full_group_name, dom_name,
211
gr->gr_gid = unix_gid;
213
/* Group name and password */
215
safe_strcpy(gr->gr_name, full_group_name, sizeof(gr->gr_name) - 1);
216
safe_strcpy(gr->gr_passwd, "x", sizeof(gr->gr_passwd) - 1);
221
/***********************************************************************
222
If "enum users" is set to false, and the group being looked
223
up is the Domain Users SID: S-1-5-domain-513, then for the
224
list of members check if the querying user is in that group,
225
and if so only return that user as the gr_mem array.
226
We can change this to a different parameter than "enum users"
227
if neccessaey, or parameterize the group list we do this for.
228
***********************************************************************/
230
static bool fill_grent_mem_domusers( TALLOC_CTX *mem_ctx,
231
struct winbindd_domain *domain,
232
struct winbindd_cli_state *state,
234
enum lsa_SidType group_name_type,
235
size_t *num_gr_mem, char **gr_mem,
238
DOM_SID querying_user_sid;
239
DOM_SID *pquerying_user_sid = NULL;
240
uint32 num_groups = 0;
241
DOM_SID *user_sids = NULL;
242
bool u_in_group = False;
245
unsigned int buf_len = 0;
248
DEBUG(10,("fill_grent_mem_domain_users: domain %s\n",
252
uid_t ret_uid = (uid_t)-1;
253
if (sys_getpeereid(state->sock, &ret_uid)==0) {
254
/* We know who's asking - look up their SID if
255
it's one we've mapped before. */
256
status = idmap_uid_to_sid(domain->name,
257
&querying_user_sid, ret_uid);
258
if (NT_STATUS_IS_OK(status)) {
259
pquerying_user_sid = &querying_user_sid;
260
DEBUG(10,("fill_grent_mem_domain_users: "
261
"querying uid %u -> %s\n",
262
(unsigned int)ret_uid,
263
sid_string_dbg(pquerying_user_sid)));
268
/* Only look up if it was a winbindd user in this domain. */
269
if (pquerying_user_sid &&
270
(sid_compare_domain(pquerying_user_sid, &domain->sid) == 0)) {
272
DEBUG(10,("fill_grent_mem_domain_users: querying user = %s\n",
273
sid_string_dbg(pquerying_user_sid) ));
275
status = domain->methods->lookup_usergroups(domain,
280
if (!NT_STATUS_IS_OK(status)) {
281
DEBUG(1, ("fill_grent_mem_domain_users: "
282
"lookup_usergroups failed "
283
"for sid %s in domain %s (error: %s)\n",
284
sid_string_dbg(pquerying_user_sid),
290
for (i = 0; i < num_groups; i++) {
291
if (sid_equal(group_sid, &user_sids[i])) {
292
/* User is in Domain Users, add their name
293
as the only group member. */
302
char *domainname = NULL;
303
char *username = NULL;
305
char *mapped_name = NULL;
306
enum lsa_SidType type;
307
struct winbindd_domain *target_domain = NULL;
308
NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
310
DEBUG(10,("fill_grent_mem_domain_users: "
311
"sid %s in 'Domain Users' in domain %s\n",
312
sid_string_dbg(pquerying_user_sid),
315
status = domain->methods->sid_to_name(domain, mem_ctx,
320
if (!NT_STATUS_IS_OK(status)) {
321
DEBUG(1, ("could not lookup username for user "
322
"sid %s in domain %s (error: %s)\n",
323
sid_string_dbg(pquerying_user_sid),
329
target_domain = find_domain_from_name_noinit(domainname);
330
name_map_status = normalize_name_map(mem_ctx, target_domain,
331
username, &mapped_name);
333
/* Basic whitespace replacement */
334
if (NT_STATUS_IS_OK(name_map_status)) {
335
fill_domain_username(name, domainname, mapped_name, true);
337
/* Mapped to an alias */
338
else if (NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED)) {
339
fstrcpy(name, mapped_name);
341
/* no mapping done...use original name */
343
fill_domain_username(name, domainname, username, true);
348
if (!(buf = (char *)SMB_MALLOC(buf_len))) {
349
DEBUG(1, ("out of memory\n"));
352
memcpy(buf, name, buf_len);
354
DEBUG(10,("fill_grent_mem_domain_users: user %s in "
355
"'Domain Users' in domain %s\n",
356
name, domain->name ));
358
/* user is the only member */
363
*gr_mem_len = buf_len;
365
DEBUG(10, ("fill_grent_mem_domain_users: "
366
"num_mem = %u, len = %u, mem = %s\n",
367
(unsigned int)*num_gr_mem,
368
(unsigned int)buf_len, *num_gr_mem ? buf : "NULL"));
373
/***********************************************************************
374
Add names to a list. Assumes a canonical version of the string
376
***********************************************************************/
378
static int namecmp( const void *a, const void *b )
380
return StrCaseCmp( * (char * const *) a, * (char * const *) b);
383
static void sort_unique_list(char ***list, uint32 *n_list)
387
/* search for duplicates for sorting and looking for matching
390
qsort(*list, *n_list, sizeof(char*), QSORT_CAST namecmp);
392
for (i=1; i < *n_list; i++) {
393
if (strcmp((*list)[i-1], (*list)[i]) == 0) {
394
memmove(&((*list)[i-1]), &((*list)[i]),
395
sizeof(char*)*((*n_list)-i));
401
static NTSTATUS add_names_to_list( TALLOC_CTX *ctx,
402
char ***list, uint32 *n_list,
403
char **names, uint32 n_names )
405
char **new_list = NULL;
406
uint32 n_new_list = 0;
409
if ( !names || (n_names == 0) )
412
/* Alloc the maximum size we'll need */
414
if ( *list == NULL ) {
415
if ((new_list = TALLOC_ARRAY(ctx, char *, n_names)) == NULL) {
416
return NT_STATUS_NO_MEMORY;
418
n_new_list = n_names;
420
new_list = TALLOC_REALLOC_ARRAY( ctx, *list, char *,
421
(*n_list) + n_names );
423
return NT_STATUS_NO_MEMORY;
424
n_new_list = (*n_list) + n_names;
429
for ( i=*n_list, j=0; i<n_new_list; i++, j++ ) {
430
new_list[i] = talloc_strdup( new_list, names[j] );
434
*n_list = n_new_list;
439
/***********************************************************************
440
***********************************************************************/
442
static NTSTATUS expand_groups( TALLOC_CTX *ctx,
443
struct winbindd_domain *d,
444
DOM_SID *glist, uint32 n_glist,
445
DOM_SID **new_glist, uint32 *n_new_glist,
446
char ***members, uint32 *n_members )
449
NTSTATUS status = NT_STATUS_OK;
450
uint32 num_names = 0;
451
uint32 *name_types = NULL;
453
DOM_SID *sid_mem = NULL;
454
TALLOC_CTX *tmp_ctx = NULL;
455
DOM_SID *new_groups = NULL;
456
size_t new_groups_size = 0;
463
for ( i=0; i<n_glist; i++ ) {
464
tmp_ctx = talloc_new( ctx );
466
/* Lookup the group membership */
468
status = d->methods->lookup_groupmem(d, tmp_ctx,
469
&glist[i], &num_names,
472
if ( !NT_STATUS_IS_OK(status) )
475
/* Separate users and groups into two lists */
477
for ( j=0; j<num_names; j++ ) {
480
if ( name_types[j] == SID_NAME_USER ||
481
name_types[j] == SID_NAME_COMPUTER )
483
status = add_names_to_list( ctx, members,
486
if ( !NT_STATUS_IS_OK(status) )
493
if ( name_types[j] == SID_NAME_DOM_GRP ||
494
name_types[j] == SID_NAME_ALIAS )
496
status = add_sid_to_array_unique(ctx,
500
if (!NT_STATUS_IS_OK(status)) {
508
TALLOC_FREE( tmp_ctx );
511
*new_glist = new_groups;
512
*n_new_glist = (uint32)new_groups_size;
515
TALLOC_FREE( tmp_ctx );
520
/***********************************************************************
521
Fill in the group membership field of a NT group given by group_sid
522
***********************************************************************/
524
static bool fill_grent_mem(struct winbindd_domain *domain,
525
struct winbindd_cli_state *state,
527
enum lsa_SidType group_name_type,
528
size_t *num_gr_mem, char **gr_mem,
531
uint32 num_names = 0;
532
unsigned int buf_len = 0, buf_ndx = 0, i;
533
char **names = NULL, *buf = NULL;
537
DOM_SID *glist = NULL;
538
DOM_SID *new_glist = NULL;
539
uint32 n_glist, n_new_glist;
540
int max_depth = lp_winbind_expand_groups();
542
if (!(mem_ctx = talloc_init("fill_grent_mem(%s)", domain->name)))
545
DEBUG(10, ("group SID %s\n", sid_string_dbg(group_sid)));
547
/* Initialize with no members */
551
/* HACK ALERT!! This whole routine does not cope with group members
552
* from more than one domain, ie aliases. Thus we have to work it out
553
* ourselves in a special routine. */
555
if (domain->internal) {
556
result = fill_passdb_alias_grmem(domain, group_sid,
562
/* Verify name type */
564
if ( !((group_name_type==SID_NAME_DOM_GRP) ||
565
((group_name_type==SID_NAME_ALIAS) && domain->primary)) )
567
DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n",
568
sid_string_dbg(group_sid),
569
domain->name, group_name_type));
573
/* OPTIMIZATION / HACK. See comment in
574
fill_grent_mem_domusers() */
576
sid_peek_rid( group_sid, &group_rid );
577
if (!lp_winbind_enum_users() && group_rid == DOMAIN_GROUP_RID_USERS) {
578
result = fill_grent_mem_domusers( mem_ctx, domain, state,
579
group_sid, group_name_type,
585
/* Real work goes here. Create a list of group names to
586
expand starting with the initial one. Pass that to
587
expand_groups() which returns a list of more group names
588
to expand. Do this up to the max search depth. */
590
if ( (glist = TALLOC_ARRAY(mem_ctx, DOM_SID, 1 )) == NULL ) {
592
DEBUG(0,("fill_grent_mem: talloc failure!\n"));
595
sid_copy( &glist[0], group_sid );
598
for ( i=0; i<max_depth && glist; i++ ) {
599
uint32 n_members = 0;
600
char **members = NULL;
604
nt_status = expand_groups( mem_ctx, domain,
606
&new_glist, &n_new_glist,
607
&members, &n_members);
608
if ( !NT_STATUS_IS_OK(nt_status) ) {
613
/* Add new group members to list. Pass through the
614
alias mapping function */
616
for (j=0; j<n_members; j++) {
617
fstring name_domain, name_acct;
618
fstring qualified_name;
619
char *mapped_name = NULL;
620
NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
621
struct winbindd_domain *target_domain = NULL;
623
if (parse_domain_user(members[j], name_domain, name_acct)) {
624
target_domain = find_domain_from_name_noinit(name_domain);
627
if (!target_domain) {
628
target_domain = domain;
631
name_map_status = normalize_name_map(members, target_domain,
632
name_acct, &mapped_name);
634
/* Basic whitespace replacement */
635
if (NT_STATUS_IS_OK(name_map_status)) {
636
fill_domain_username(qualified_name, name_domain,
638
mapped_name = qualified_name;
640
/* no mapping at all */
641
else if (!NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED)) {
642
mapped_name = members[j];
645
nt_status = add_names_to_list( mem_ctx, &names,
648
if ( !NT_STATUS_IS_OK(nt_status) ) {
654
TALLOC_FREE( members );
656
/* If we have no more groups to expand, break out
659
if (new_glist == NULL)
665
n_glist = n_new_glist;
667
TALLOC_FREE( glist );
669
sort_unique_list(&names, &num_names);
671
DEBUG(10, ("looked up %d names\n", num_names));
674
/* Add members to list */
676
for (i = 0; i < num_names; i++) {
679
DEBUG(10, ("processing name %s\n", names[i]));
681
len = strlen(names[i]);
683
/* Add to list or calculate buffer length */
686
buf_len += len + 1; /* List is comma separated */
688
DEBUG(10, ("buf_len + %d = %d\n", len + 1, buf_len));
690
DEBUG(10, ("appending %s at ndx %d\n",
692
parse_add_domuser(&buf[buf_ndx], names[i], &len);
699
/* Allocate buffer */
701
if (!buf && buf_len != 0) {
702
if (!(buf = (char *)SMB_MALLOC(buf_len))) {
703
DEBUG(1, ("out of memory\n"));
707
memset(buf, 0, buf_len);
713
if (buf && buf_ndx > 0) {
714
buf[buf_ndx - 1] = '\0';
718
*gr_mem_len = buf_len;
720
DEBUG(10, ("num_mem = %u, len = %u, mem = %s\n",
721
(unsigned int)*num_gr_mem,
722
(unsigned int)buf_len, *num_gr_mem ? buf : "NULL"));
727
talloc_destroy(mem_ctx);
729
DEBUG(10, ("fill_grent_mem returning %d\n", result));
734
static void winbindd_getgrsid(struct winbindd_cli_state *state, DOM_SID group_sid);
736
static void getgrnam_recv( void *private_data, bool success, const DOM_SID *sid,
737
enum lsa_SidType type )
739
struct winbindd_cli_state *state = (struct winbindd_cli_state*)private_data;
742
DEBUG(5,("getgrnam_recv: lookupname failed!\n"));
743
request_error(state);
747
if ( (type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) ) {
748
DEBUG(5,("getgrnam_recv: not a group!\n"));
749
request_error(state);
753
winbindd_getgrsid( state, *sid );
757
/* Return a group structure from a group name */
759
void winbindd_getgrnam(struct winbindd_cli_state *state)
761
struct winbindd_domain *domain;
762
fstring name_domain, name_group;
764
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
766
/* Ensure null termination */
767
state->request.data.groupname[sizeof(state->request.data.groupname)-1]='\0';
769
DEBUG(3, ("[%5lu]: getgrnam %s\n", (unsigned long)state->pid,
770
state->request.data.groupname));
772
nt_status = normalize_name_unmap(state->mem_ctx,
773
state->request.data.groupname,
775
/* If we didn't map anything in the above call, just reset the
776
tmp pointer to the original string */
777
if (!NT_STATUS_IS_OK(nt_status) &&
778
!NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED))
780
tmp = state->request.data.groupname;
783
/* Parse domain and groupname */
785
memset(name_group, 0, sizeof(name_group));
787
name_domain[0] = '\0';
788
name_group[0] = '\0';
790
parse_domain_user(tmp, name_domain, name_group);
792
/* if no domain or our local domain and no local tdb group, default to
793
* our local domain for aliases */
795
if ( !*name_domain || strequal(name_domain, get_global_sam_name()) ) {
796
fstrcpy(name_domain, get_global_sam_name());
799
/* Get info for the domain */
801
if ((domain = find_domain_from_name_noinit(name_domain)) == NULL) {
802
DEBUG(3, ("could not get domain sid for domain %s\n",
804
request_error(state);
807
/* should we deal with users for our domain? */
809
if ( lp_winbind_trusted_domains_only() && domain->primary) {
810
DEBUG(7,("winbindd_getgrnam: My domain -- rejecting "
811
"getgrnam() for %s\\%s.\n", name_domain, name_group));
812
request_error(state);
816
/* Get rid and name type from name */
818
fstrcpy( name_group, tmp );
820
winbindd_lookupname_async( state->mem_ctx, domain->name, name_group,
821
getgrnam_recv, WINBINDD_GETGRNAM, state );
824
struct getgrsid_state {
825
struct winbindd_cli_state *state;
826
struct winbindd_domain *domain;
828
enum lsa_SidType group_type;
833
static void getgrsid_sid2gid_recv(void *private_data, bool success, gid_t gid)
835
struct getgrsid_state *s =
836
(struct getgrsid_state *)private_data;
837
struct winbindd_domain *domain;
841
fstring dom_name, group_name;
844
DEBUG(5,("getgrsid_sid2gid_recv: sid2gid failed!\n"));
845
request_error(s->state);
851
if ( !parse_domain_user( s->group_name, dom_name, group_name ) ) {
852
DEBUG(5,("getgrsid_sid2gid_recv: parse_domain_user() failed!\n"));
853
request_error(s->state);
858
/* Fill in group structure */
860
if ( (domain = find_domain_from_name_noinit(dom_name)) == NULL ) {
861
DEBUG(1,("Can't find domain from name (%s)\n", dom_name));
862
request_error(s->state);
866
if (!fill_grent(s->state->mem_ctx, &s->state->response.data.gr,
867
dom_name, group_name, gid) ||
868
!fill_grent_mem(domain, s->state, &s->group_sid, s->group_type,
869
&num_gr_mem, &gr_mem, &gr_mem_len))
871
request_error(s->state);
875
s->state->response.data.gr.num_gr_mem = (uint32)num_gr_mem;
877
/* Group membership lives at start of extra data */
879
s->state->response.data.gr.gr_mem_ofs = 0;
881
s->state->response.length += gr_mem_len;
882
s->state->response.extra_data.data = gr_mem;
884
request_ok(s->state);
887
static void getgrsid_lookupsid_recv( void *private_data, bool success,
888
const char *dom_name, const char *name,
889
enum lsa_SidType name_type )
891
struct getgrsid_state *s = (struct getgrsid_state *)private_data;
892
char *mapped_name = NULL;
894
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
897
DEBUG(5,("getgrsid_lookupsid_recv: lookupsid failed!\n"));
898
request_error(s->state);
902
/* either it's a domain group, a domain local group, or a
903
local group in an internal domain */
905
if ( !( (name_type==SID_NAME_DOM_GRP) ||
906
((name_type==SID_NAME_ALIAS) &&
907
(s->domain->primary || s->domain->internal)) ) )
909
DEBUG(1, ("name '%s\\%s' is not a local or domain group: %d\n",
910
dom_name, name, name_type));
911
request_error(s->state);
915
/* normalize the name and ensure that we have the DOM\name
916
coming out of here */
918
fstrcpy(raw_name, name);
920
nt_status = normalize_name_unmap(s->state->mem_ctx, raw_name,
923
/* basic whitespace reversal */
924
if (NT_STATUS_IS_OK(nt_status)) {
925
s->group_name = talloc_asprintf(s->state->mem_ctx,
928
*lp_winbind_separator(),
931
/* mapped from alias */
932
else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) {
933
s->group_name = mapped_name;
935
/* no mapping at all. use original string */
937
s->group_name = talloc_asprintf(s->state->mem_ctx,
940
*lp_winbind_separator(),
944
if (s->group_name == NULL) {
945
DEBUG(1, ("getgrsid_lookupsid_recv: group_name is NULL!\n"));
946
request_error(s->state);
950
s->group_type = name_type;
952
winbindd_sid2gid_async(s->state->mem_ctx, &s->group_sid,
953
getgrsid_sid2gid_recv, s);
956
static void winbindd_getgrsid( struct winbindd_cli_state *state, const DOM_SID group_sid )
958
struct getgrsid_state *s;
960
if ( (s = TALLOC_ZERO_P(state->mem_ctx, struct getgrsid_state)) == NULL ) {
961
DEBUG(0, ("talloc failed\n"));
962
request_error(state);
968
if ( (s->domain = find_domain_from_sid_noinit(&group_sid)) == NULL ) {
969
DEBUG(3, ("Could not find domain for sid %s\n",
970
sid_string_dbg(&group_sid)));
971
request_error(state);
975
sid_copy(&s->group_sid, &group_sid);
977
winbindd_lookupsid_async( s->state->mem_ctx, &group_sid,
978
getgrsid_lookupsid_recv, s );
982
static void getgrgid_recv(void *private_data, bool success, const char *sid)
984
struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state);
985
enum lsa_SidType name_type;
989
DEBUG(10,("getgrgid_recv: gid %lu has sid %s\n",
990
(unsigned long)(state->request.data.gid), sid));
992
if (!string_to_sid(&group_sid, sid)) {
993
DEBUG(1,("getgrgid_recv: Could not convert sid %s "
994
"from string\n", sid));
995
request_error(state);
999
winbindd_getgrsid(state, group_sid);
1003
/* Ok, this might be "ours", i.e. an alias */
1004
if (pdb_gid_to_sid(state->request.data.gid, &group_sid) &&
1005
lookup_sid(state->mem_ctx, &group_sid, NULL, NULL, &name_type) &&
1006
(name_type == SID_NAME_ALIAS)) {
1007
/* Hey, got an alias */
1008
DEBUG(10,("getgrgid_recv: we have an alias with gid %lu and sid %s\n",
1009
(unsigned long)(state->request.data.gid), sid));
1010
winbindd_getgrsid(state, group_sid);
1014
DEBUG(1, ("could not convert gid %lu to sid\n",
1015
(unsigned long)state->request.data.gid));
1016
request_error(state);
1019
/* Return a group structure from a gid number */
1020
void winbindd_getgrgid(struct winbindd_cli_state *state)
1022
gid_t gid = state->request.data.gid;
1024
DEBUG(3, ("[%5lu]: getgrgid %lu\n",
1025
(unsigned long)state->pid,
1026
(unsigned long)gid));
1028
/* always use the async interface */
1029
winbindd_gid2sid_async(state->mem_ctx, gid, getgrgid_recv, state);
1033
* set/get/endgrent functions
1036
/* "Rewind" file pointer for group database enumeration */
1038
static bool winbindd_setgrent_internal(struct winbindd_cli_state *state)
1040
struct winbindd_domain *domain;
1042
DEBUG(3, ("[%5lu]: setgrent\n", (unsigned long)state->pid));
1044
/* Check user has enabled this */
1046
if (!lp_winbind_enum_groups()) {
1050
/* Free old static data if it exists */
1052
if (state->getgrent_state != NULL) {
1053
free_getent_state(state->getgrent_state);
1054
state->getgrent_state = NULL;
1057
/* Create sam pipes for each domain we know about */
1059
for (domain = domain_list(); domain != NULL; domain = domain->next) {
1060
struct getent_state *domain_state;
1062
/* Create a state record for this domain */
1064
/* don't add our domaina if we are a PDC or if we
1065
are a member of a Samba domain */
1067
if ( lp_winbind_trusted_domains_only() && domain->primary )
1072
domain_state = SMB_MALLOC_P(struct getent_state);
1073
if (!domain_state) {
1074
DEBUG(1, ("winbindd_setgrent: "
1075
"malloc failed for domain_state!\n"));
1079
ZERO_STRUCTP(domain_state);
1081
fstrcpy(domain_state->domain_name, domain->name);
1083
/* Add to list of open domains */
1085
DLIST_ADD(state->getgrent_state, domain_state);
1088
state->getgrent_initialized = True;
1092
void winbindd_setgrent(struct winbindd_cli_state *state)
1094
if (winbindd_setgrent_internal(state)) {
1097
request_error(state);
1101
/* Close file pointer to ntdom group database */
1103
void winbindd_endgrent(struct winbindd_cli_state *state)
1105
DEBUG(3, ("[%5lu]: endgrent\n", (unsigned long)state->pid));
1107
free_getent_state(state->getgrent_state);
1108
state->getgrent_initialized = False;
1109
state->getgrent_state = NULL;
1113
/* Get the list of domain groups and domain aliases for a domain. We fill in
1114
the sam_entries and num_sam_entries fields with domain group information.
1115
Return True if some groups were returned, False otherwise. */
1117
bool get_sam_group_entries(struct getent_state *ent)
1121
struct acct_info *name_list = NULL;
1122
TALLOC_CTX *mem_ctx;
1123
bool result = False;
1124
struct acct_info *sam_grp_entries = NULL;
1125
struct winbindd_domain *domain;
1127
if (ent->got_sam_entries)
1130
if (!(mem_ctx = talloc_init("get_sam_group_entries(%s)",
1131
ent->domain_name))) {
1132
DEBUG(1, ("get_sam_group_entries: "
1133
"could not create talloc context!\n"));
1137
/* Free any existing group info */
1139
SAFE_FREE(ent->sam_entries);
1140
ent->num_sam_entries = 0;
1141
ent->got_sam_entries = True;
1143
/* Enumerate domain groups */
1147
if (!(domain = find_domain_from_name(ent->domain_name))) {
1148
DEBUG(3, ("no such domain %s in get_sam_group_entries\n",
1153
/* always get the domain global groups */
1155
status = domain->methods->enum_dom_groups(domain, mem_ctx, &num_entries,
1158
if (!NT_STATUS_IS_OK(status)) {
1159
DEBUG(3, ("get_sam_group_entries: "
1160
"could not enumerate domain groups! Error: %s\n",
1161
nt_errstr(status)));
1166
/* Copy entries into return buffer */
1169
name_list = SMB_MALLOC_ARRAY(struct acct_info, num_entries);
1171
DEBUG(0,("get_sam_group_entries: Failed to malloc "
1172
"memory for %d domain groups!\n",
1177
memcpy(name_list, sam_grp_entries,
1178
num_entries * sizeof(struct acct_info));
1181
ent->num_sam_entries = num_entries;
1183
/* get the domain local groups if we are a member of a native win2k
1184
* domain and are not using LDAP to get the groups */
1186
if ( ( lp_security() != SEC_ADS && domain->native_mode
1187
&& domain->primary) || domain->internal )
1189
DEBUG(4,("get_sam_group_entries: %s domain; "
1190
"enumerating local groups as well\n",
1191
domain->native_mode ? "Native Mode 2k":
1192
"BUILTIN or local"));
1194
status = domain->methods->enum_local_groups(domain, mem_ctx,
1198
if ( !NT_STATUS_IS_OK(status) ) {
1199
DEBUG(3,("get_sam_group_entries: "
1200
"Failed to enumerate "
1201
"domain local groups with error %s!\n",
1202
nt_errstr(status)));
1206
DEBUG(4,("get_sam_group_entries: "
1207
"Returned %d local groups\n",
1210
/* Copy entries into return buffer */
1212
if ( num_entries ) {
1213
name_list = SMB_REALLOC_ARRAY(name_list,
1215
ent->num_sam_entries+
1218
DEBUG(0,("get_sam_group_entries: "
1219
"Failed to realloc more memory "
1220
"for %d local groups!\n",
1226
memcpy(&name_list[ent->num_sam_entries],
1228
num_entries * sizeof(struct acct_info));
1231
ent->num_sam_entries += num_entries;
1235
/* Fill in remaining fields */
1237
ent->sam_entries = name_list;
1238
ent->sam_entry_index = 0;
1240
result = (ent->num_sam_entries > 0);
1243
talloc_destroy(mem_ctx);
1248
/* Fetch next group entry from ntdom database */
1250
#define MAX_GETGRENT_GROUPS 500
1252
void winbindd_getgrent(struct winbindd_cli_state *state)
1254
struct getent_state *ent;
1255
struct winbindd_gr *group_list = NULL;
1256
int num_groups, group_list_ndx, gr_mem_list_len = 0;
1257
char *gr_mem_list = NULL;
1259
DEBUG(3, ("[%5lu]: getgrent\n", (unsigned long)state->pid));
1261
/* Check user has enabled this */
1263
if (!lp_winbind_enum_groups()) {
1264
request_error(state);
1268
num_groups = MIN(MAX_GETGRENT_GROUPS, state->request.data.num_entries);
1270
if (num_groups == 0) {
1271
request_error(state);
1275
group_list = SMB_MALLOC_ARRAY(struct winbindd_gr, num_groups);
1277
request_error(state);
1280
/* will be freed by process_request() */
1281
state->response.extra_data.data = group_list;
1283
memset(state->response.extra_data.data, '\0',
1284
num_groups * sizeof(struct winbindd_gr) );
1286
state->response.data.num_entries = 0;
1288
if (!state->getgrent_initialized)
1289
winbindd_setgrent_internal(state);
1291
if (!(ent = state->getgrent_state)) {
1292
request_error(state);
1296
/* Start sending back groups */
1298
for (group_list_ndx = 0; group_list_ndx < num_groups; ) {
1299
struct acct_info *name_list = NULL;
1300
fstring domain_group_name;
1306
struct winbindd_domain *domain;
1308
/* Do we need to fetch another chunk of groups? */
1312
DEBUG(10, ("entry_index = %d, num_entries = %d\n",
1313
ent->sam_entry_index, ent->num_sam_entries));
1315
if (ent->num_sam_entries == ent->sam_entry_index) {
1317
while(ent && !get_sam_group_entries(ent)) {
1318
struct getent_state *next_ent;
1320
DEBUG(10, ("freeing state info for domain %s\n",
1323
/* Free state information for this domain */
1325
SAFE_FREE(ent->sam_entries);
1327
next_ent = ent->next;
1328
DLIST_REMOVE(state->getgrent_state, ent);
1334
/* No more domains */
1340
name_list = (struct acct_info *)ent->sam_entries;
1342
if (!(domain = find_domain_from_name(ent->domain_name))) {
1343
DEBUG(3, ("No such domain %s in winbindd_getgrent\n",
1349
/* Lookup group info */
1351
sid_copy(&group_sid, &domain->sid);
1352
sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid);
1354
if (!NT_STATUS_IS_OK(idmap_sid_to_gid(domain->have_idmap_config
1355
? domain->name : "",
1356
&group_sid, &group_gid)))
1359
enum lsa_SidType type;
1361
DEBUG(10, ("SID %s not in idmap\n",
1362
sid_string_dbg(&group_sid)));
1364
if (!pdb_sid_to_id(&group_sid, &id, &type)) {
1365
DEBUG(1,("could not look up gid for group %s\n",
1366
name_list[ent->sam_entry_index].acct_name));
1367
ent->sam_entry_index++;
1371
if ((type != SID_NAME_DOM_GRP) &&
1372
(type != SID_NAME_ALIAS) &&
1373
(type != SID_NAME_WKN_GRP)) {
1374
DEBUG(1, ("Group %s is a %s, not a group\n",
1375
sid_type_lookup(type),
1376
name_list[ent->sam_entry_index].acct_name));
1377
ent->sam_entry_index++;
1383
DEBUG(10, ("got gid %lu for group %lu\n",
1384
(unsigned long)group_gid,
1385
(unsigned long)name_list[ent->sam_entry_index].rid));
1387
/* Fill in group entry */
1389
fill_domain_username(domain_group_name, ent->domain_name,
1390
name_list[ent->sam_entry_index].acct_name, True);
1392
result = fill_grent(state->mem_ctx, &group_list[group_list_ndx],
1394
name_list[ent->sam_entry_index].acct_name,
1397
/* Fill in group membership entry */
1400
size_t num_gr_mem = 0;
1402
group_list[group_list_ndx].num_gr_mem = 0;
1406
/* Get group membership */
1407
if (state->request.cmd == WINBINDD_GETGRLST) {
1410
sid_copy(&member_sid, &domain->sid);
1411
sid_append_rid(&member_sid, name_list[ent->sam_entry_index].rid);
1412
result = fill_grent_mem(
1418
&gr_mem, &gr_mem_len);
1420
group_list[group_list_ndx].num_gr_mem = (uint32)num_gr_mem;
1425
/* Append to group membership list */
1426
gr_mem_list = (char *)SMB_REALLOC(
1427
gr_mem_list, gr_mem_list_len + gr_mem_len);
1430
(group_list[group_list_ndx].num_gr_mem != 0)) {
1431
DEBUG(0, ("out of memory\n"));
1432
gr_mem_list_len = 0;
1436
DEBUG(10, ("list_len = %d, mem_len = %u\n",
1437
gr_mem_list_len, (unsigned int)gr_mem_len));
1439
memcpy(&gr_mem_list[gr_mem_list_len], gr_mem,
1444
group_list[group_list_ndx].gr_mem_ofs =
1447
gr_mem_list_len += gr_mem_len;
1450
ent->sam_entry_index++;
1452
/* Add group to return list */
1456
DEBUG(10, ("adding group num_entries = %d\n",
1457
state->response.data.num_entries));
1460
state->response.data.num_entries++;
1462
state->response.length +=
1463
sizeof(struct winbindd_gr);
1466
DEBUG(0, ("could not lookup domain group %s\n",
1467
domain_group_name));
1471
/* Copy the list of group memberships to the end of the extra data */
1473
if (group_list_ndx == 0)
1476
state->response.extra_data.data = SMB_REALLOC(
1477
state->response.extra_data.data,
1478
group_list_ndx * sizeof(struct winbindd_gr) + gr_mem_list_len);
1480
if (!state->response.extra_data.data) {
1481
DEBUG(0, ("out of memory\n"));
1483
SAFE_FREE(gr_mem_list);
1484
request_error(state);
1488
memcpy(&((char *)state->response.extra_data.data)
1489
[group_list_ndx * sizeof(struct winbindd_gr)],
1490
gr_mem_list, gr_mem_list_len);
1492
state->response.length += gr_mem_list_len;
1494
DEBUG(10, ("returning %d groups, length = %d\n",
1495
group_list_ndx, gr_mem_list_len));
1497
/* Out of domains */
1501
SAFE_FREE(gr_mem_list);
1503
if (group_list_ndx > 0)
1506
request_error(state);
1509
/* List domain groups without mapping to unix ids */
1510
void winbindd_list_groups(struct winbindd_cli_state *state)
1512
winbindd_list_ent(state, LIST_GROUPS);
1515
/* Get user supplementary groups. This is much quicker than trying to
1516
invert the groups database. We merge the groups from the gids and
1517
other_sids info3 fields as trusted domain, universal group
1518
memberships, and nested groups (win2k native mode only) are not
1519
returned by the getgroups RPC call but are present in the info3. */
1521
struct getgroups_state {
1522
struct winbindd_cli_state *state;
1523
struct winbindd_domain *domain;
1528
const DOM_SID *token_sids;
1529
size_t i, num_token_sids;
1532
size_t num_token_gids;
1535
static void getgroups_usersid_recv(void *private_data, bool success,
1536
const DOM_SID *sid, enum lsa_SidType type);
1537
static void getgroups_tokensids_recv(void *private_data, bool success,
1538
DOM_SID *token_sids, size_t num_token_sids);
1539
static void getgroups_sid2gid_recv(void *private_data, bool success, gid_t gid);
1541
void winbindd_getgroups(struct winbindd_cli_state *state)
1543
struct getgroups_state *s;
1544
char *real_name = NULL;
1545
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1547
/* Ensure null termination */
1548
state->request.data.username
1549
[sizeof(state->request.data.username)-1]='\0';
1551
DEBUG(3, ("[%5lu]: getgroups %s\n", (unsigned long)state->pid,
1552
state->request.data.username));
1554
/* Parse domain and username */
1556
s = TALLOC_P(state->mem_ctx, struct getgroups_state);
1558
DEBUG(0, ("talloc failed\n"));
1559
request_error(state);
1565
nt_status = normalize_name_unmap(state->mem_ctx,
1566
state->request.data.username,
1569
/* Reset the real_name pointer if we didn't do anything
1570
productive in the above call */
1571
if (!NT_STATUS_IS_OK(nt_status) &&
1572
!NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED))
1574
real_name = state->request.data.username;
1577
if (!parse_domain_user_talloc(state->mem_ctx, real_name,
1578
&s->domname, &s->username)) {
1579
DEBUG(5, ("Could not parse domain user: %s\n",
1582
/* error out if we do not have nested group support */
1584
if ( !lp_winbind_nested_groups() ) {
1585
request_error(state);
1589
s->domname = talloc_strdup(state->mem_ctx,
1590
get_global_sam_name());
1591
s->username = talloc_strdup(state->mem_ctx,
1592
state->request.data.username);
1595
/* Get info for the domain (either by short domain name or
1596
DNS name in the case of a UPN) */
1598
s->domain = find_domain_from_name_noinit(s->domname);
1600
char *p = strchr(s->username, '@');
1603
s->domain = find_domain_from_name_noinit(p+1);
1608
if (s->domain == NULL) {
1609
DEBUG(7, ("could not find domain entry for domain %s\n",
1611
request_error(state);
1615
if ( s->domain->primary && lp_winbind_trusted_domains_only()) {
1616
DEBUG(7,("winbindd_getgroups: My domain -- rejecting "
1617
"getgroups() for %s\\%s.\n", s->domname,
1619
request_error(state);
1623
/* Get rid and name type from name. The following costs 1 packet */
1625
winbindd_lookupname_async(state->mem_ctx,
1626
s->domname, s->username,
1627
getgroups_usersid_recv,
1628
WINBINDD_GETGROUPS, s);
1631
static void getgroups_usersid_recv(void *private_data, bool success,
1632
const DOM_SID *sid, enum lsa_SidType type)
1634
struct getgroups_state *s =
1635
(struct getgroups_state *)private_data;
1638
((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER))) {
1639
request_error(s->state);
1643
sid_copy(&s->user_sid, sid);
1645
winbindd_gettoken_async(s->state->mem_ctx, &s->user_sid,
1646
getgroups_tokensids_recv, s);
1649
static void getgroups_tokensids_recv(void *private_data, bool success,
1650
DOM_SID *token_sids, size_t num_token_sids)
1652
struct getgroups_state *s =
1653
(struct getgroups_state *)private_data;
1655
/* We need at least the user sid and the primary group in the token,
1656
* otherwise it's an error */
1658
if ((!success) || (num_token_sids < 2)) {
1659
request_error(s->state);
1663
s->token_sids = token_sids;
1664
s->num_token_sids = num_token_sids;
1667
s->token_gids = NULL;
1668
s->num_token_gids = 0;
1670
getgroups_sid2gid_recv(s, False, 0);
1673
static void getgroups_sid2gid_recv(void *private_data, bool success, gid_t gid)
1675
struct getgroups_state *s =
1676
(struct getgroups_state *)private_data;
1679
if (!add_gid_to_array_unique(s->state->mem_ctx, gid,
1681
&s->num_token_gids)) {
1686
if (s->i < s->num_token_sids) {
1687
const DOM_SID *sid = &s->token_sids[s->i];
1690
if (sid_equal(sid, &s->user_sid)) {
1691
getgroups_sid2gid_recv(s, False, 0);
1695
winbindd_sid2gid_async(s->state->mem_ctx, sid,
1696
getgroups_sid2gid_recv, s);
1700
s->state->response.data.num_entries = s->num_token_gids;
1701
if (s->num_token_gids) {
1702
/* s->token_gids are talloced */
1703
s->state->response.extra_data.data =
1704
smb_xmemdup(s->token_gids,
1705
s->num_token_gids * sizeof(gid_t));
1706
s->state->response.length += s->num_token_gids * sizeof(gid_t);
1708
request_ok(s->state);
1711
/* Get user supplementary sids. This is equivalent to the
1712
winbindd_getgroups() function but it involves a SID->SIDs mapping
1713
rather than a NAME->SID->SIDS->GIDS mapping, which means we avoid
1714
idmap. This call is designed to be used with applications that need
1715
to do ACL evaluation themselves. Note that the cached info3 data is
1718
this function assumes that the SID that comes in is a user SID. If
1719
you pass in another type of SID then you may get unpredictable
1723
static void getusersids_recv(void *private_data, bool success, DOM_SID *sids,
1726
void winbindd_getusersids(struct winbindd_cli_state *state)
1730
/* Ensure null termination */
1731
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
1733
user_sid = TALLOC_P(state->mem_ctx, DOM_SID);
1734
if (user_sid == NULL) {
1735
DEBUG(1, ("talloc failed\n"));
1736
request_error(state);
1740
if (!string_to_sid(user_sid, state->request.data.sid)) {
1741
DEBUG(1, ("Could not get convert sid %s from string\n",
1742
state->request.data.sid));
1743
request_error(state);
1747
winbindd_gettoken_async(state->mem_ctx, user_sid, getusersids_recv,
1751
static void getusersids_recv(void *private_data, bool success, DOM_SID *sids,
1754
struct winbindd_cli_state *state =
1755
(struct winbindd_cli_state *)private_data;
1757
unsigned ofs, ret_size = 0;
1761
request_error(state);
1765
/* work out the response size */
1766
for (i = 0; i < num_sids; i++) {
1768
sid_to_fstring(s, &sids[i]);
1769
ret_size += strlen(s) + 1;
1772
/* build the reply */
1773
ret = (char *)SMB_MALLOC(ret_size);
1775
DEBUG(0, ("malloc failed\n"));
1776
request_error(state);
1780
for (i = 0; i < num_sids; i++) {
1782
sid_to_fstring(s, &sids[i]);
1783
safe_strcpy(ret + ofs, s, ret_size - ofs - 1);
1784
ofs += strlen(ret+ofs) + 1;
1787
/* Send data back to client */
1788
state->response.data.num_entries = num_sids;
1789
state->response.extra_data.data = ret;
1790
state->response.length += ret_size;
1794
void winbindd_getuserdomgroups(struct winbindd_cli_state *state)
1797
struct winbindd_domain *domain;
1799
/* Ensure null termination */
1800
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
1802
if (!string_to_sid(&user_sid, state->request.data.sid)) {
1803
DEBUG(1, ("Could not get convert sid %s from string\n",
1804
state->request.data.sid));
1805
request_error(state);
1809
/* Get info for the domain */
1810
if ((domain = find_domain_from_sid_noinit(&user_sid)) == NULL) {
1811
DEBUG(0,("could not find domain entry for sid %s\n",
1812
sid_string_dbg(&user_sid)));
1813
request_error(state);
1817
sendto_domain(state, domain);
1820
enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *domain,
1821
struct winbindd_cli_state *state)
1831
/* Ensure null termination */
1832
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
1834
if (!string_to_sid(&user_sid, state->request.data.sid)) {
1835
DEBUG(1, ("Could not get convert sid %s from string\n",
1836
state->request.data.sid));
1837
return WINBINDD_ERROR;
1840
status = domain->methods->lookup_usergroups(domain, state->mem_ctx,
1841
&user_sid, &num_groups,
1843
if (!NT_STATUS_IS_OK(status))
1844
return WINBINDD_ERROR;
1846
if (num_groups == 0) {
1847
state->response.data.num_entries = 0;
1848
state->response.extra_data.data = NULL;
1852
if (!print_sidlist(state->mem_ctx,
1854
&sidstring, &len)) {
1855
DEBUG(0, ("talloc failed\n"));
1856
return WINBINDD_ERROR;
1859
state->response.extra_data.data = SMB_STRDUP(sidstring);
1860
if (!state->response.extra_data.data) {
1861
return WINBINDD_ERROR;
1863
state->response.length += len+1;
1864
state->response.data.num_entries = num_groups;
1869
void winbindd_getsidaliases(struct winbindd_cli_state *state)
1872
struct winbindd_domain *domain;
1874
/* Ensure null termination */
1875
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
1877
if (!string_to_sid(&domain_sid, state->request.data.sid)) {
1878
DEBUG(1, ("Could not get convert sid %s from string\n",
1879
state->request.data.sid));
1880
request_error(state);
1884
/* Get info for the domain */
1885
if ((domain = find_domain_from_sid_noinit(&domain_sid)) == NULL) {
1886
DEBUG(0,("could not find domain entry for sid %s\n",
1887
sid_string_dbg(&domain_sid)));
1888
request_error(state);
1892
sendto_domain(state, domain);
1895
enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
1896
struct winbindd_cli_state *state)
1898
DOM_SID *sids = NULL;
1899
size_t num_sids = 0;
1900
char *sidstr = NULL;
1907
DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
1909
sidstr = state->request.extra_data.data;
1910
if (sidstr == NULL) {
1911
sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
1913
DEBUG(0, ("Out of memory\n"));
1914
return WINBINDD_ERROR;
1918
DEBUG(10, ("Sidlist: %s\n", sidstr));
1920
if (!parse_sidlist(state->mem_ctx, sidstr, &sids, &num_sids)) {
1921
DEBUG(0, ("Could not parse SID list: %s\n", sidstr));
1922
return WINBINDD_ERROR;
1928
result = domain->methods->lookup_useraliases(domain,
1934
if (!NT_STATUS_IS_OK(result)) {
1935
DEBUG(3, ("Could not lookup_useraliases: %s\n",
1936
nt_errstr(result)));
1937
return WINBINDD_ERROR;
1944
DEBUG(10, ("Got %d aliases\n", num_aliases));
1946
for (i=0; i<num_aliases; i++) {
1948
DEBUGADD(10, (" rid %d\n", alias_rids[i]));
1949
sid_copy(&sid, &domain->sid);
1950
sid_append_rid(&sid, alias_rids[i]);
1951
result = add_sid_to_array(state->mem_ctx, &sid, &sids,
1953
if (!NT_STATUS_IS_OK(result)) {
1954
return WINBINDD_ERROR;
1959
if (!print_sidlist(state->mem_ctx, sids, num_sids, &sidstr, &len)) {
1960
DEBUG(0, ("Could not print_sidlist\n"));
1961
state->response.extra_data.data = NULL;
1962
return WINBINDD_ERROR;
1965
state->response.extra_data.data = NULL;
1968
state->response.extra_data.data = SMB_STRDUP(sidstr);
1969
if (!state->response.extra_data.data) {
1970
DEBUG(0, ("Out of memory\n"));
1971
return WINBINDD_ERROR;
1973
DEBUG(10, ("aliases_list: %s\n",
1974
(char *)state->response.extra_data.data));
1975
state->response.length += len+1;
1976
state->response.data.num_entries = num_sids;