2 Unix SMB/CIFS implementation.
3 Samba utility functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Luke Kenneth Caseson Leighton 1998-1999
6 Copyright (C) Jeremy Allison 1999
7 Copyright (C) Stefan (metze) Metzmacher 2002
8 Copyright (C) Simo Sorce 2002
9 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 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/>.
28 * Some useful sids, more well known sids can be found at
29 * http://support.microsoft.com/kb/243330/EN-US/
33 const DOM_SID global_sid_World_Domain
= /* Everyone domain */
34 { 1, 0, {0,0,0,0,0,1}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
35 const DOM_SID global_sid_World
= /* Everyone */
36 { 1, 1, {0,0,0,0,0,1}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
37 const DOM_SID global_sid_Creator_Owner_Domain
= /* Creator Owner domain */
38 { 1, 0, {0,0,0,0,0,3}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
39 const DOM_SID global_sid_NT_Authority
= /* NT Authority */
40 { 1, 0, {0,0,0,0,0,5}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
41 const DOM_SID global_sid_System
= /* System */
42 { 1, 1, {0,0,0,0,0,5}, {18,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
43 const DOM_SID global_sid_NULL
= /* NULL sid */
44 { 1, 1, {0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
45 const DOM_SID global_sid_Authenticated_Users
= /* All authenticated rids */
46 { 1, 1, {0,0,0,0,0,5}, {11,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
48 /* for documentation */
49 const DOM_SID global_sid_Restriced
= /* Restriced Code */
50 { 1, 1, {0,0,0,0,0,5}, {12,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
52 const DOM_SID global_sid_Network
= /* Network rids */
53 { 1, 1, {0,0,0,0,0,5}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
55 const DOM_SID global_sid_Creator_Owner
= /* Creator Owner */
56 { 1, 1, {0,0,0,0,0,3}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
57 const DOM_SID global_sid_Creator_Group
= /* Creator Group */
58 { 1, 1, {0,0,0,0,0,3}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
59 const DOM_SID global_sid_Anonymous
= /* Anonymous login */
60 { 1, 1, {0,0,0,0,0,5}, {7,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
62 const DOM_SID global_sid_Builtin
= /* Local well-known domain */
63 { 1, 1, {0,0,0,0,0,5}, {32,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
64 const DOM_SID global_sid_Builtin_Administrators
= /* Builtin administrators */
65 { 1, 2, {0,0,0,0,0,5}, {32,544,0,0,0,0,0,0,0,0,0,0,0,0,0}};
66 const DOM_SID global_sid_Builtin_Users
= /* Builtin users */
67 { 1, 2, {0,0,0,0,0,5}, {32,545,0,0,0,0,0,0,0,0,0,0,0,0,0}};
68 const DOM_SID global_sid_Builtin_Guests
= /* Builtin guest users */
69 { 1, 2, {0,0,0,0,0,5}, {32,546,0,0,0,0,0,0,0,0,0,0,0,0,0}};
70 const DOM_SID global_sid_Builtin_Power_Users
= /* Builtin power users */
71 { 1, 2, {0,0,0,0,0,5}, {32,547,0,0,0,0,0,0,0,0,0,0,0,0,0}};
72 const DOM_SID global_sid_Builtin_Account_Operators
= /* Builtin account operators */
73 { 1, 2, {0,0,0,0,0,5}, {32,548,0,0,0,0,0,0,0,0,0,0,0,0,0}};
74 const DOM_SID global_sid_Builtin_Server_Operators
= /* Builtin server operators */
75 { 1, 2, {0,0,0,0,0,5}, {32,549,0,0,0,0,0,0,0,0,0,0,0,0,0}};
76 const DOM_SID global_sid_Builtin_Print_Operators
= /* Builtin print operators */
77 { 1, 2, {0,0,0,0,0,5}, {32,550,0,0,0,0,0,0,0,0,0,0,0,0,0}};
78 const DOM_SID global_sid_Builtin_Backup_Operators
= /* Builtin backup operators */
79 { 1, 2, {0,0,0,0,0,5}, {32,551,0,0,0,0,0,0,0,0,0,0,0,0,0}};
80 const DOM_SID global_sid_Builtin_Replicator
= /* Builtin replicator */
81 { 1, 2, {0,0,0,0,0,5}, {32,552,0,0,0,0,0,0,0,0,0,0,0,0,0}};
82 const DOM_SID global_sid_Builtin_PreWin2kAccess
= /* Builtin pre win2k access */
83 { 1, 2, {0,0,0,0,0,5}, {32,554,0,0,0,0,0,0,0,0,0,0,0,0,0}};
85 const DOM_SID global_sid_Unix_Users
= /* Unmapped Unix users */
86 { 1, 1, {0,0,0,0,0,22}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
87 const DOM_SID global_sid_Unix_Groups
= /* Unmapped Unix groups */
88 { 1, 1, {0,0,0,0,0,22}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
90 /* Unused, left here for documentary purposes */
92 #define SECURITY_NULL_SID_AUTHORITY 0
93 #define SECURITY_WORLD_SID_AUTHORITY 1
94 #define SECURITY_LOCAL_SID_AUTHORITY 2
95 #define SECURITY_CREATOR_SID_AUTHORITY 3
96 #define SECURITY_NT_AUTHORITY 5
100 * An NT compatible anonymous token.
103 static DOM_SID anon_sid_array
[3] =
104 { { 1, 1, {0,0,0,0,0,1}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
105 { 1, 1, {0,0,0,0,0,5}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
106 { 1, 1, {0,0,0,0,0,5}, {7,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} };
107 NT_USER_TOKEN anonymous_token
= { 3, anon_sid_array
, SE_NONE
};
109 static DOM_SID system_sid_array
[1] =
110 { { 1, 1, {0,0,0,0,0,5}, {18,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} };
111 NT_USER_TOKEN system_token
= { 1, system_sid_array
, SE_ALL_PRIVS
};
113 /****************************************************************************
114 Lookup string names for SID types.
115 ****************************************************************************/
117 static const struct {
118 enum lsa_SidType sid_type
;
120 } sid_name_type
[] = {
121 {SID_NAME_USER
, "User"},
122 {SID_NAME_DOM_GRP
, "Domain Group"},
123 {SID_NAME_DOMAIN
, "Domain"},
124 {SID_NAME_ALIAS
, "Local Group"},
125 {SID_NAME_WKN_GRP
, "Well-known Group"},
126 {SID_NAME_DELETED
, "Deleted Account"},
127 {SID_NAME_INVALID
, "Invalid Account"},
128 {SID_NAME_UNKNOWN
, "UNKNOWN"},
129 {SID_NAME_COMPUTER
, "Computer"},
131 {(enum lsa_SidType
)0, NULL
}
134 const char *sid_type_lookup(uint32 sid_type
)
138 /* Look through list */
139 while(sid_name_type
[i
].sid_type
!= 0) {
140 if (sid_name_type
[i
].sid_type
== sid_type
)
141 return sid_name_type
[i
].string
;
146 return "SID *TYPE* is INVALID";
149 /**************************************************************************
150 Create the SYSTEM token.
151 ***************************************************************************/
153 NT_USER_TOKEN
*get_system_token(void)
155 return &system_token
;
158 /******************************************************************
159 get the default domain/netbios name to be used when dealing
160 with our passdb list of accounts
161 ******************************************************************/
163 const char *get_global_sam_name(void)
165 if ((lp_server_role() == ROLE_DOMAIN_PDC
) || (lp_server_role() == ROLE_DOMAIN_BDC
)) {
166 return lp_workgroup();
168 return global_myname();
171 /*****************************************************************
172 Convert a SID to an ascii string.
173 *****************************************************************/
175 char *sid_to_fstring(fstring sidstr_out
, const DOM_SID
*sid
)
177 char *str
= sid_string_talloc(talloc_tos(), sid
);
178 fstrcpy(sidstr_out
, str
);
183 /*****************************************************************
184 Essentially a renamed dom_sid_string from librpc/ndr with a
185 panic if it didn't work
187 This introduces a dependency on librpc/ndr/sid.o which can easily
188 be turned around if necessary
189 *****************************************************************/
191 char *sid_string_talloc(TALLOC_CTX
*mem_ctx
, const DOM_SID
*sid
)
193 char *result
= dom_sid_string(mem_ctx
, sid
);
194 SMB_ASSERT(result
!= NULL
);
198 /*****************************************************************
199 Useful function for debug lines.
200 *****************************************************************/
202 char *sid_string_dbg(const DOM_SID
*sid
)
204 return sid_string_talloc(talloc_tos(), sid
);
207 /*****************************************************************
209 *****************************************************************/
211 char *sid_string_tos(const DOM_SID
*sid
)
213 return sid_string_talloc(talloc_tos(), sid
);
216 /*****************************************************************
217 Convert a string to a SID. Returns True on success, False on fail.
218 *****************************************************************/
220 bool string_to_sid(DOM_SID
*sidout
, const char *sidstr
)
224 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
227 if ((sidstr
[0] != 'S' && sidstr
[0] != 's') || sidstr
[1] != '-') {
228 DEBUG(3,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr
));
232 ZERO_STRUCTP(sidout
);
234 /* Get the revision number. */
236 conv
= (uint32
) strtoul(p
, &q
, 10);
237 if (!q
|| (*q
!= '-')) {
238 DEBUG(3,("string_to_sid: Sid %s is not in a valid format.\n", sidstr
));
241 sidout
->sid_rev_num
= (uint8
) conv
;
245 conv
= (uint32
) strtoul(q
, &q
, 10);
246 if (!q
|| (*q
!= '-')) {
247 DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr
));
250 /* identauth in decimal should be < 2^32 */
251 /* NOTE - the conv value is in big-endian format. */
252 sidout
->id_auth
[0] = 0;
253 sidout
->id_auth
[1] = 0;
254 sidout
->id_auth
[2] = (conv
& 0xff000000) >> 24;
255 sidout
->id_auth
[3] = (conv
& 0x00ff0000) >> 16;
256 sidout
->id_auth
[4] = (conv
& 0x0000ff00) >> 8;
257 sidout
->id_auth
[5] = (conv
& 0x000000ff);
260 sidout
->num_auths
= 0;
262 for(conv
= (uint32
) strtoul(q
, &q
, 10);
263 q
&& (*q
=='-' || *q
=='\0') && (sidout
->num_auths
< MAXSUBAUTHS
);
264 conv
= (uint32
) strtoul(q
, &q
, 10)) {
265 sid_append_rid(sidout
, conv
);
274 DOM_SID
*string_sid_talloc(TALLOC_CTX
*mem_ctx
, const char *sidstr
)
276 DOM_SID
*result
= TALLOC_P(mem_ctx
, DOM_SID
);
281 if (!string_to_sid(result
, sidstr
))
287 /*****************************************************************
288 Add a rid to the end of a sid
289 *****************************************************************/
291 bool sid_append_rid(DOM_SID
*sid
, uint32 rid
)
293 if (sid
->num_auths
< MAXSUBAUTHS
) {
294 sid
->sub_auths
[sid
->num_auths
++] = rid
;
300 bool sid_compose(DOM_SID
*dst
, const DOM_SID
*domain_sid
, uint32 rid
)
302 sid_copy(dst
, domain_sid
);
303 return sid_append_rid(dst
, rid
);
306 /*****************************************************************
307 Removes the last rid from the end of a sid
308 *****************************************************************/
310 bool sid_split_rid(DOM_SID
*sid
, uint32
*rid
)
312 if (sid
->num_auths
> 0) {
314 *rid
= sid
->sub_auths
[sid
->num_auths
];
320 /*****************************************************************
321 Return the last rid from the end of a sid
322 *****************************************************************/
324 bool sid_peek_rid(const DOM_SID
*sid
, uint32
*rid
)
329 if (sid
->num_auths
> 0) {
330 *rid
= sid
->sub_auths
[sid
->num_auths
- 1];
336 /*****************************************************************
337 Return the last rid from the end of a sid
338 and check the sid against the exp_dom_sid
339 *****************************************************************/
341 bool sid_peek_check_rid(const DOM_SID
*exp_dom_sid
, const DOM_SID
*sid
, uint32
*rid
)
343 if (!exp_dom_sid
|| !sid
|| !rid
)
346 if (sid
->num_auths
!= (exp_dom_sid
->num_auths
+1)) {
350 if (sid_compare_domain(exp_dom_sid
, sid
)!=0){
355 return sid_peek_rid(sid
, rid
);
358 /*****************************************************************
360 *****************************************************************/
362 void sid_copy(DOM_SID
*dst
, const DOM_SID
*src
)
368 dst
->sid_rev_num
= src
->sid_rev_num
;
369 dst
->num_auths
= src
->num_auths
;
371 memcpy(&dst
->id_auth
[0], &src
->id_auth
[0], sizeof(src
->id_auth
));
373 for (i
= 0; i
< src
->num_auths
; i
++)
374 dst
->sub_auths
[i
] = src
->sub_auths
[i
];
377 /*****************************************************************
378 Write a sid out into on-the-wire format.
379 *****************************************************************/
381 bool sid_linearize(char *outbuf
, size_t len
, const DOM_SID
*sid
)
385 if (len
< ndr_size_dom_sid(sid
, NULL
, 0))
388 SCVAL(outbuf
,0,sid
->sid_rev_num
);
389 SCVAL(outbuf
,1,sid
->num_auths
);
390 memcpy(&outbuf
[2], sid
->id_auth
, 6);
391 for(i
= 0; i
< sid
->num_auths
; i
++)
392 SIVAL(outbuf
, 8 + (i
*4), sid
->sub_auths
[i
]);
397 /*****************************************************************
398 Parse a on-the-wire SID to a DOM_SID.
399 *****************************************************************/
401 bool sid_parse(const char *inbuf
, size_t len
, DOM_SID
*sid
)
409 sid
->sid_rev_num
= CVAL(inbuf
, 0);
410 sid
->num_auths
= CVAL(inbuf
, 1);
411 if (sid
->num_auths
> MAXSUBAUTHS
) {
414 memcpy(sid
->id_auth
, inbuf
+2, 6);
415 if (len
< 8 + sid
->num_auths
*4)
417 for (i
=0;i
<sid
->num_auths
;i
++)
418 sid
->sub_auths
[i
] = IVAL(inbuf
, 8+i
*4);
422 /*****************************************************************
423 Compare the auth portion of two sids.
424 *****************************************************************/
426 static int sid_compare_auth(const DOM_SID
*sid1
, const DOM_SID
*sid2
)
437 if (sid1
->sid_rev_num
!= sid2
->sid_rev_num
)
438 return sid1
->sid_rev_num
- sid2
->sid_rev_num
;
440 for (i
= 0; i
< 6; i
++)
441 if (sid1
->id_auth
[i
] != sid2
->id_auth
[i
])
442 return sid1
->id_auth
[i
] - sid2
->id_auth
[i
];
447 /*****************************************************************
449 *****************************************************************/
451 int sid_compare(const DOM_SID
*sid1
, const DOM_SID
*sid2
)
462 /* Compare most likely different rids, first: i.e start at end */
463 if (sid1
->num_auths
!= sid2
->num_auths
)
464 return sid1
->num_auths
- sid2
->num_auths
;
466 for (i
= sid1
->num_auths
-1; i
>= 0; --i
)
467 if (sid1
->sub_auths
[i
] != sid2
->sub_auths
[i
])
468 return sid1
->sub_auths
[i
] - sid2
->sub_auths
[i
];
470 return sid_compare_auth(sid1
, sid2
);
473 /*****************************************************************
474 See if 2 SIDs are in the same domain
475 this just compares the leading sub-auths
476 *****************************************************************/
478 int sid_compare_domain(const DOM_SID
*sid1
, const DOM_SID
*sid2
)
482 n
= MIN(sid1
->num_auths
, sid2
->num_auths
);
484 for (i
= n
-1; i
>= 0; --i
)
485 if (sid1
->sub_auths
[i
] != sid2
->sub_auths
[i
])
486 return sid1
->sub_auths
[i
] - sid2
->sub_auths
[i
];
488 return sid_compare_auth(sid1
, sid2
);
491 /*****************************************************************
493 *****************************************************************/
495 bool sid_equal(const DOM_SID
*sid1
, const DOM_SID
*sid2
)
497 return sid_compare(sid1
, sid2
) == 0;
500 /*****************************************************************
501 Returns true if SID is internal (and non-mappable).
502 *****************************************************************/
504 bool non_mappable_sid(DOM_SID
*sid
)
510 sid_split_rid(&dom
, &rid
);
512 if (sid_equal(&dom
, &global_sid_Builtin
))
515 if (sid_equal(&dom
, &global_sid_NT_Authority
))
521 /*****************************************************************
522 Return the binary string representation of a DOM_SID.
524 *****************************************************************/
526 char *sid_binstring(TALLOC_CTX
*mem_ctx
, const DOM_SID
*sid
)
530 int len
= ndr_size_dom_sid(sid
, NULL
, 0);
531 buf
= talloc_array(mem_ctx
, uint8_t, len
);
535 sid_linearize((char *)buf
, len
, sid
);
536 s
= binary_string_rfc2254(mem_ctx
, buf
, len
);
541 /*****************************************************************
542 Return the binary string representation of a DOM_SID.
544 *****************************************************************/
546 char *sid_binstring_hex(const DOM_SID
*sid
)
549 int len
= ndr_size_dom_sid(sid
, NULL
, 0);
550 buf
= (char *)SMB_MALLOC(len
);
553 sid_linearize(buf
, len
, sid
);
554 s
= binary_string(buf
, len
);
559 /*******************************************************************
560 Tallocs a duplicate SID.
561 ********************************************************************/
563 DOM_SID
*sid_dup_talloc(TALLOC_CTX
*ctx
, const DOM_SID
*src
)
570 if((dst
= TALLOC_ZERO_P(ctx
, DOM_SID
)) != NULL
) {
577 /********************************************************************
578 Add SID to an array SIDs
579 ********************************************************************/
581 NTSTATUS
add_sid_to_array(TALLOC_CTX
*mem_ctx
, const DOM_SID
*sid
,
582 DOM_SID
**sids
, size_t *num
)
584 *sids
= TALLOC_REALLOC_ARRAY(mem_ctx
, *sids
, DOM_SID
,
588 return NT_STATUS_NO_MEMORY
;
591 sid_copy(&((*sids
)[*num
]), sid
);
598 /********************************************************************
599 Add SID to an array SIDs ensuring that it is not already there
600 ********************************************************************/
602 NTSTATUS
add_sid_to_array_unique(TALLOC_CTX
*mem_ctx
, const DOM_SID
*sid
,
603 DOM_SID
**sids
, size_t *num_sids
)
607 for (i
=0; i
<(*num_sids
); i
++) {
608 if (sid_compare(sid
, &(*sids
)[i
]) == 0)
612 return add_sid_to_array(mem_ctx
, sid
, sids
, num_sids
);
615 /********************************************************************
616 Remove SID from an array
617 ********************************************************************/
619 void del_sid_from_array(const DOM_SID
*sid
, DOM_SID
**sids
, size_t *num
)
621 DOM_SID
*sid_list
= *sids
;
624 for ( i
=0; i
<*num
; i
++ ) {
626 /* if we find the SID, then decrement the count
627 and break out of the loop */
629 if ( sid_equal(sid
, &sid_list
[i
]) ) {
635 /* This loop will copy the remainder of the array
636 if i < num of sids ni the array */
638 for ( ; i
<*num
; i
++ )
639 sid_copy( &sid_list
[i
], &sid_list
[i
+1] );
644 bool add_rid_to_array_unique(TALLOC_CTX
*mem_ctx
,
645 uint32 rid
, uint32
**pp_rids
, size_t *p_num
)
649 for (i
=0; i
<*p_num
; i
++) {
650 if ((*pp_rids
)[i
] == rid
)
654 *pp_rids
= TALLOC_REALLOC_ARRAY(mem_ctx
, *pp_rids
, uint32
, *p_num
+1);
656 if (*pp_rids
== NULL
) {
661 (*pp_rids
)[*p_num
] = rid
;
666 bool is_null_sid(const DOM_SID
*sid
)
668 static const DOM_SID null_sid
= {0};
669 return sid_equal(sid
, &null_sid
);
672 bool is_sid_in_token(const NT_USER_TOKEN
*token
, const DOM_SID
*sid
)
676 for (i
=0; i
<token
->num_sids
; i
++) {
677 if (sid_compare(sid
, &token
->user_sids
[i
]) == 0)
683 NTSTATUS
sid_array_from_info3(TALLOC_CTX
*mem_ctx
,
684 const struct netr_SamInfo3
*info3
,
686 size_t *num_user_sids
,
687 bool include_user_group_rid
)
691 DOM_SID
*sid_array
= NULL
;
695 if (include_user_group_rid
) {
696 if (!sid_compose(&sid
, info3
->base
.domain_sid
, info3
->base
.rid
)) {
697 DEBUG(3, ("could not compose user SID from rid 0x%x\n",
699 return NT_STATUS_INVALID_PARAMETER
;
701 status
= add_sid_to_array(mem_ctx
, &sid
, &sid_array
, &num_sids
);
702 if (!NT_STATUS_IS_OK(status
)) {
703 DEBUG(3, ("could not append user SID from rid 0x%x\n",
709 if (!sid_compose(&sid
, info3
->base
.domain_sid
, info3
->base
.primary_gid
)) {
710 DEBUG(3, ("could not compose group SID from rid 0x%x\n",
711 info3
->base
.primary_gid
));
712 return NT_STATUS_INVALID_PARAMETER
;
714 status
= add_sid_to_array(mem_ctx
, &sid
, &sid_array
, &num_sids
);
715 if (!NT_STATUS_IS_OK(status
)) {
716 DEBUG(3, ("could not append group SID from rid 0x%x\n",
721 for (i
= 0; i
< info3
->base
.groups
.count
; i
++) {
722 /* Don't add the primary group sid twice. */
723 if (info3
->base
.primary_gid
== info3
->base
.groups
.rids
[i
].rid
) {
726 if (!sid_compose(&sid
, info3
->base
.domain_sid
,
727 info3
->base
.groups
.rids
[i
].rid
)) {
728 DEBUG(3, ("could not compose SID from additional group "
729 "rid 0x%x\n", info3
->base
.groups
.rids
[i
].rid
));
730 return NT_STATUS_INVALID_PARAMETER
;
732 status
= add_sid_to_array(mem_ctx
, &sid
, &sid_array
, &num_sids
);
733 if (!NT_STATUS_IS_OK(status
)) {
734 DEBUG(3, ("could not append SID from additional group "
735 "rid 0x%x\n", info3
->base
.groups
.rids
[i
].rid
));
740 /* SID filtering should only be handled by the domain controller on a
741 trust by trust basis, and is counter-indicated for forests. Since
742 native AD return all Domain Local groups as other SIDs, then this
743 must not filter them when parsing INFO3 responses such that the
744 list is identical to the tokenGroups LDAP query.
747 for (i
= 0; i
< info3
->sidcount
; i
++) {
748 status
= add_sid_to_array(mem_ctx
, info3
->sids
[i
].sid
,
749 &sid_array
, &num_sids
);
750 if (!NT_STATUS_IS_OK(status
)) {
751 DEBUG(3, ("could not add SID to array: %s\n",
752 sid_string_dbg(info3
->sids
[i
].sid
)));
757 *user_sids
= sid_array
;
758 *num_user_sids
= num_sids
;