s3: Fix bug #9085.
[Samba.git] / source3 / lib / util_sid.c
blobf918eba7deb7fc63b2aa17b8efea1d7423ed3271
1 /*
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/>.
25 #include "includes.h"
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}};
47 #if 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}};
51 #endif
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 */
91 #if 0
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
97 #endif
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;
119 const char *string;
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)
136 int i = 0;
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;
142 i++;
145 /* Default return */
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);
179 TALLOC_FREE(str);
180 return sidstr_out;
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);
195 return result;
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 /*****************************************************************
208 Use with care!
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)
222 const char *p;
223 char *q;
224 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
225 uint32 conv;
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));
229 return False;
232 ZERO_STRUCTP(sidout);
234 /* Get the revision number. */
235 p = sidstr + 2;
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));
239 return False;
241 sidout->sid_rev_num = (uint8) conv;
242 q++;
244 /* get identauth */
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));
248 return False;
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);
259 q++;
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);
266 if (*q == '\0')
267 break;
268 q++;
271 return True;
274 DOM_SID *string_sid_talloc(TALLOC_CTX *mem_ctx, const char *sidstr)
276 DOM_SID *result = TALLOC_P(mem_ctx, DOM_SID);
278 if (result == NULL)
279 return NULL;
281 if (!string_to_sid(result, sidstr))
282 return NULL;
284 return result;
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;
295 return True;
297 return False;
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) {
313 sid->num_auths--;
314 *rid = sid->sub_auths[sid->num_auths];
315 return True;
317 return False;
320 /*****************************************************************
321 Return the last rid from the end of a sid
322 *****************************************************************/
324 bool sid_peek_rid(const DOM_SID *sid, uint32 *rid)
326 if (!sid || !rid)
327 return False;
329 if (sid->num_auths > 0) {
330 *rid = sid->sub_auths[sid->num_auths - 1];
331 return True;
333 return False;
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)
344 return False;
346 if (sid->num_auths != (exp_dom_sid->num_auths+1)) {
347 return False;
350 if (sid_compare_domain(exp_dom_sid, sid)!=0){
351 *rid=(-1);
352 return False;
355 return sid_peek_rid(sid, rid);
358 /*****************************************************************
359 Copies a sid
360 *****************************************************************/
362 void sid_copy(DOM_SID *dst, const DOM_SID *src)
364 int i;
366 ZERO_STRUCTP(dst);
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)
383 size_t i;
385 if (len < ndr_size_dom_sid(sid, NULL, 0))
386 return False;
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]);
394 return True;
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)
403 int i;
404 if (len < 8)
405 return False;
407 ZERO_STRUCTP(sid);
409 sid->sid_rev_num = CVAL(inbuf, 0);
410 sid->num_auths = CVAL(inbuf, 1);
411 if (sid->num_auths > MAXSUBAUTHS) {
412 return false;
414 memcpy(sid->id_auth, inbuf+2, 6);
415 if (len < 8 + sid->num_auths*4)
416 return False;
417 for (i=0;i<sid->num_auths;i++)
418 sid->sub_auths[i] = IVAL(inbuf, 8+i*4);
419 return True;
422 /*****************************************************************
423 Compare the auth portion of two sids.
424 *****************************************************************/
426 static int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2)
428 int i;
430 if (sid1 == sid2)
431 return 0;
432 if (!sid1)
433 return -1;
434 if (!sid2)
435 return 1;
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];
444 return 0;
447 /*****************************************************************
448 Compare two sids.
449 *****************************************************************/
451 int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2)
453 int i;
455 if (sid1 == sid2)
456 return 0;
457 if (!sid1)
458 return -1;
459 if (!sid2)
460 return 1;
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)
480 int n, i;
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 /*****************************************************************
492 Compare two sids.
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)
506 DOM_SID dom;
507 uint32 rid;
509 sid_copy(&dom, sid);
510 sid_split_rid(&dom, &rid);
512 if (sid_equal(&dom, &global_sid_Builtin))
513 return True;
515 if (sid_equal(&dom, &global_sid_NT_Authority))
516 return True;
518 return False;
521 /*****************************************************************
522 Return the binary string representation of a DOM_SID.
523 Caller must free.
524 *****************************************************************/
526 char *sid_binstring(TALLOC_CTX *mem_ctx, const DOM_SID *sid)
528 uint8_t *buf;
529 char *s;
530 int len = ndr_size_dom_sid(sid, NULL, 0);
531 buf = talloc_array(mem_ctx, uint8_t, len);
532 if (!buf) {
533 return NULL;
535 sid_linearize((char *)buf, len, sid);
536 s = binary_string_rfc2254(mem_ctx, buf, len);
537 TALLOC_FREE(buf);
538 return s;
541 /*****************************************************************
542 Return the binary string representation of a DOM_SID.
543 Caller must free.
544 *****************************************************************/
546 char *sid_binstring_hex(const DOM_SID *sid)
548 char *buf, *s;
549 int len = ndr_size_dom_sid(sid, NULL, 0);
550 buf = (char *)SMB_MALLOC(len);
551 if (!buf)
552 return NULL;
553 sid_linearize(buf, len, sid);
554 s = binary_string(buf, len);
555 free(buf);
556 return s;
559 /*******************************************************************
560 Tallocs a duplicate SID.
561 ********************************************************************/
563 DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, const DOM_SID *src)
565 DOM_SID *dst;
567 if(!src)
568 return NULL;
570 if((dst = TALLOC_ZERO_P(ctx, DOM_SID)) != NULL) {
571 sid_copy( dst, src);
574 return dst;
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,
585 (*num)+1);
586 if (*sids == NULL) {
587 *num = 0;
588 return NT_STATUS_NO_MEMORY;
591 sid_copy(&((*sids)[*num]), sid);
592 *num += 1;
594 return NT_STATUS_OK;
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)
605 size_t i;
607 for (i=0; i<(*num_sids); i++) {
608 if (sid_compare(sid, &(*sids)[i]) == 0)
609 return NT_STATUS_OK;
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;
622 size_t i;
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]) ) {
630 *num -= 1;
631 break;
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] );
641 return;
644 bool add_rid_to_array_unique(TALLOC_CTX *mem_ctx,
645 uint32 rid, uint32 **pp_rids, size_t *p_num)
647 size_t i;
649 for (i=0; i<*p_num; i++) {
650 if ((*pp_rids)[i] == rid)
651 return True;
654 *pp_rids = TALLOC_REALLOC_ARRAY(mem_ctx, *pp_rids, uint32, *p_num+1);
656 if (*pp_rids == NULL) {
657 *p_num = 0;
658 return False;
661 (*pp_rids)[*p_num] = rid;
662 *p_num += 1;
663 return True;
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)
674 int i;
676 for (i=0; i<token->num_sids; i++) {
677 if (sid_compare(sid, &token->user_sids[i]) == 0)
678 return true;
680 return false;
683 NTSTATUS sid_array_from_info3(TALLOC_CTX *mem_ctx,
684 const struct netr_SamInfo3 *info3,
685 DOM_SID **user_sids,
686 size_t *num_user_sids,
687 bool include_user_group_rid)
689 NTSTATUS status;
690 DOM_SID sid;
691 DOM_SID *sid_array = NULL;
692 size_t num_sids = 0;
693 int i;
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",
698 info3->base.rid));
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",
704 info3->base.rid));
705 return status;
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",
717 info3->base.rid));
718 return status;
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) {
724 continue;
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));
736 return status;
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)));
753 return status;
757 *user_sids = sid_array;
758 *num_user_sids = num_sids;
760 return NT_STATUS_OK;