Removed version number from file header.
[kai/samba.git] / source3 / lib / util_sid.c
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    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25 DOM_SID global_sam_sid;
26 extern pstring global_myname;
27 extern fstring global_myworkgroup;
28
29 /*
30  * Some useful sids
31  */
32
33 DOM_SID global_sid_Builtin;                             /* Local well-known domain */
34 DOM_SID global_sid_World_Domain;                /* Everyone domain */
35 DOM_SID global_sid_World;                               /* Everyone */
36 DOM_SID global_sid_Creator_Owner_Domain;    /* Creator Owner domain */
37 DOM_SID global_sid_Creator_Owner;               /* Creator Owner */
38 DOM_SID global_sid_NT_Authority;                /* NT Authority */
39 DOM_SID global_sid_NULL;                        /* NULL sid */
40 DOM_SID global_sid_Builtin_Guests;                      /* Builtin guest users */
41 DOM_SID global_sid_Authenticated_Users;         /* All authenticated rids */
42 DOM_SID global_sid_Network;                                     /* Network rids */
43 DOM_SID global_sid_Anonymous;                           /* Anonymous login */
44 DOM_SID global_sid_nonexistent;                 /* S-0-0. Used in Lsa level 3. */
45
46 const DOM_SID *global_sid_everyone = &global_sid_World;
47
48 typedef struct _known_sid_users {
49         uint32 rid;
50         enum SID_NAME_USE sid_name_use;
51         char *known_user_name;
52 } known_sid_users;
53
54 /* static known_sid_users no_users[] = {{0, 0, NULL}}; */
55
56 static known_sid_users everyone_users[] = {
57         { 0, SID_NAME_WKN_GRP, "Everyone" },
58         {0, (enum SID_NAME_USE)0, NULL}};
59
60 static known_sid_users creator_owner_users[] = {
61         { 0, SID_NAME_ALIAS, "Creator Owner" },
62         {0, (enum SID_NAME_USE)0, NULL}};
63
64 static known_sid_users nt_authority_users[] = {
65         {  1, SID_NAME_ALIAS, "Dialup" },
66         {  2, SID_NAME_ALIAS, "Network"},
67         {  3, SID_NAME_ALIAS, "Batch"},
68         {  4, SID_NAME_ALIAS, "Interactive"},
69         {  6, SID_NAME_ALIAS, "Service"},
70         {  7, SID_NAME_ALIAS, "AnonymousLogon"},
71         {  8, SID_NAME_ALIAS, "Proxy"},
72         {  9, SID_NAME_ALIAS, "ServerLogon"},
73         { 11, SID_NAME_ALIAS, "Authenticated Users"},
74         { 18, SID_NAME_ALIAS, "SYSTEM"},
75         {  0, (enum SID_NAME_USE)0, NULL}};
76
77 static known_sid_users builtin_groups[] = {
78         { BUILTIN_ALIAS_RID_ADMINS, SID_NAME_ALIAS, "Administrators" },
79         { BUILTIN_ALIAS_RID_USERS, SID_NAME_ALIAS, "Users" },
80         { BUILTIN_ALIAS_RID_GUESTS, SID_NAME_ALIAS, "Guests" },
81         { BUILTIN_ALIAS_RID_ACCOUNT_OPS, SID_NAME_ALIAS, "Account Operators" },
82         { BUILTIN_ALIAS_RID_SYSTEM_OPS, SID_NAME_ALIAS, "Server Operators" },
83         { BUILTIN_ALIAS_RID_PRINT_OPS, SID_NAME_ALIAS, "Print Operators" },
84         { BUILTIN_ALIAS_RID_BACKUP_OPS, SID_NAME_ALIAS, "Backup Operators" },
85         {  0, (enum SID_NAME_USE)0, NULL}};
86
87 #define MAX_SID_NAMES   7
88
89 static struct sid_name_map_info
90 {
91         DOM_SID *sid;
92         char *name;
93         known_sid_users *known_users;
94 } sid_name_map[MAX_SID_NAMES];
95
96 static BOOL sid_name_map_initialized = False;
97
98 /*
99  * An NT compatible anonymous token.
100  */
101
102 static DOM_SID anon_sid_array[3];
103
104 NT_USER_TOKEN anonymous_token = {
105     3,
106     anon_sid_array
107 };
108
109 /**************************************************************************
110  quick init function
111  *************************************************************************/
112 static void init_sid_name_map (void)
113 {
114         int i = 0;
115         
116         if (sid_name_map_initialized) return;
117         
118
119         if ((lp_security() == SEC_USER) && lp_domain_logons()) {
120                 sid_name_map[i].sid = &global_sam_sid;
121                 sid_name_map[i].name = global_myworkgroup;
122                 sid_name_map[i].known_users = NULL;
123                 i++;
124                 sid_name_map[i].sid = &global_sam_sid;
125                 sid_name_map[i].name = global_myname;
126                 sid_name_map[i].known_users = NULL;
127                 i++;
128         }
129         else {
130                 sid_name_map[i].sid = &global_sam_sid;
131                 sid_name_map[i].name = global_myname;
132                 sid_name_map[i].known_users = NULL;
133                 i++;
134         }
135
136         sid_name_map[i].sid = &global_sid_Builtin;
137         sid_name_map[i].name = "BUILTIN";
138         sid_name_map[i].known_users = &builtin_groups[0];
139         i++;
140         
141         sid_name_map[i].sid = &global_sid_World_Domain;
142         sid_name_map[i].name = "";
143         sid_name_map[i].known_users = &everyone_users[0];
144         i++;
145
146         sid_name_map[i].sid = &global_sid_Creator_Owner_Domain;
147         sid_name_map[i].name = "";
148         sid_name_map[i].known_users = &creator_owner_users[0];
149         i++;
150                 
151         sid_name_map[i].sid = &global_sid_NT_Authority;
152         sid_name_map[i].name = "NT Authority";
153         sid_name_map[i].known_users = &nt_authority_users[0];
154         i++;
155                 
156
157         /* end of array */
158         sid_name_map[i].sid = NULL;
159         sid_name_map[i].name = NULL;
160         sid_name_map[i].known_users = NULL;
161         
162         sid_name_map_initialized = True;
163                 
164         return;
165
166 }
167
168 /****************************************************************************
169  Creates some useful well known sids
170 ****************************************************************************/
171
172 void generate_wellknown_sids(void)
173 {
174         string_to_sid(&global_sid_Builtin, "S-1-5-32");
175         string_to_sid(&global_sid_Builtin_Guests, "S-1-5-32-546");
176         string_to_sid(&global_sid_World_Domain, "S-1-1");
177         string_to_sid(&global_sid_World, "S-1-1-0");
178         string_to_sid(&global_sid_Creator_Owner_Domain, "S-1-3");
179         string_to_sid(&global_sid_Creator_Owner, "S-1-3-0");
180         string_to_sid(&global_sid_NT_Authority, "S-1-5");
181         string_to_sid(&global_sid_NULL, "S-1-0-0");
182         string_to_sid(&global_sid_Authenticated_Users, "S-1-5-11");
183         string_to_sid(&global_sid_Network, "S-1-5-2");
184         string_to_sid(&global_sid_Anonymous, "S-1-5-7");
185         string_to_sid(&global_sid_nonexistent, "S-0-0"); /* Used in Lsa level 3. */
186
187         /* Create the anon token. */
188         sid_copy( &anonymous_token.user_sids[0], &global_sid_World);
189         sid_copy( &anonymous_token.user_sids[1], &global_sid_Network);
190         sid_copy( &anonymous_token.user_sids[2], &global_sid_Anonymous);
191 }
192
193 /**************************************************************************
194  Turns a domain SID into a name, returned in the nt_domain argument.
195 ***************************************************************************/
196
197 BOOL map_domain_sid_to_name(DOM_SID *sid, char *nt_domain)
198 {
199         fstring sid_str;
200         int i = 0;
201         
202         sid_to_string(sid_str, sid);
203
204         if (!sid_name_map_initialized) 
205                 init_sid_name_map();
206
207         DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str));
208
209         if (nt_domain == NULL)
210                 return False;
211
212         while (sid_name_map[i].sid != NULL) {
213                 sid_to_string(sid_str, sid_name_map[i].sid);
214                 DEBUG(5,("map_domain_sid_to_name: compare: %s\n", sid_str));
215                 if (sid_equal(sid_name_map[i].sid, sid)) {              
216                         fstrcpy(nt_domain, sid_name_map[i].name);
217                         DEBUG(5,("map_domain_sid_to_name: found '%s'\n", nt_domain));
218                         return True;
219                 }
220                 i++;
221         }
222
223         DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", sid_str));
224
225     return False;
226 }
227
228 /**************************************************************************
229  Looks up a known username from one of the known domains.
230 ***************************************************************************/
231
232 BOOL lookup_known_rid(DOM_SID *sid, uint32 rid, char *name, enum SID_NAME_USE *psid_name_use)
233 {
234         int i = 0;
235         struct sid_name_map_info *psnm;
236
237         if (!sid_name_map_initialized) 
238                 init_sid_name_map();
239
240         for(i = 0; sid_name_map[i].sid != NULL; i++) {
241                 psnm = &sid_name_map[i];
242                 if(sid_equal(psnm->sid, sid)) {
243                         int j;
244                         for(j = 0; psnm->known_users && psnm->known_users[j].known_user_name != NULL; j++) {
245                                 if(rid == psnm->known_users[j].rid) {
246                                         DEBUG(5,("lookup_builtin_rid: rid = %u, domain = '%s', user = '%s'\n",
247                                                 (unsigned int)rid, psnm->name, psnm->known_users[j].known_user_name ));
248                                         fstrcpy( name, psnm->known_users[j].known_user_name);
249                                         *psid_name_use = psnm->known_users[j].sid_name_use;
250                                         return True;
251                                 }
252                         }
253                 }
254         }
255
256         return False;
257 }
258
259 /**************************************************************************
260  Turns a domain name into a SID.
261  *** side-effect: if the domain name is NULL, it is set to our domain ***
262 ***************************************************************************/
263
264 BOOL map_domain_name_to_sid(DOM_SID *sid, char *nt_domain)
265 {
266         int i = 0;
267
268         if (nt_domain == NULL) {
269                 DEBUG(5,("map_domain_name_to_sid: mapping NULL domain to our SID.\n"));
270                 sid_copy(sid, &global_sam_sid);
271                 return True;
272         }
273
274         if (nt_domain[0] == 0) {
275                 fstrcpy(nt_domain, global_myname);
276                 DEBUG(5,("map_domain_name_to_sid: overriding blank name to %s\n", nt_domain));
277                 sid_copy(sid, &global_sam_sid);
278                 return True;
279         }
280
281         DEBUG(5,("map_domain_name_to_sid: %s\n", nt_domain));
282
283         if (!sid_name_map_initialized) 
284                 init_sid_name_map();
285
286         while (sid_name_map[i].name != NULL) {
287                 DEBUG(5,("map_domain_name_to_sid: compare: %s\n", sid_name_map[i].name));
288                 if (strequal(sid_name_map[i].name, nt_domain)) {
289                         fstring sid_str;
290                         sid_copy(sid, sid_name_map[i].sid);
291                         sid_to_string(sid_str, sid_name_map[i].sid);
292                         DEBUG(5,("map_domain_name_to_sid: found %s\n", sid_str));
293                         return True;
294                 }
295                 i++;
296         }
297
298         DEBUG(0,("map_domain_name_to_sid: mapping to %s not found.\n", nt_domain));
299         return False;
300 }
301
302 /**************************************************************************
303  Splits a name of format \DOMAIN\name or name into its two components.
304  Sets the DOMAIN name to global_myname if it has not been specified.
305 ***************************************************************************/
306
307 void split_domain_name(const char *fullname, char *domain, char *name)
308 {
309         pstring full_name;
310         char *p, *sep;
311
312         sep = lp_winbind_separator();
313
314         *domain = *name = '\0';
315
316         if (fullname[0] == sep[0] || fullname[0] == '\\')
317                 fullname++;
318
319         pstrcpy(full_name, fullname);
320         p = strchr_m(full_name+1, '\\');
321         if (!p) p = strchr_m(full_name+1, sep[0]);
322
323         if (p != NULL) {
324                 *p = 0;
325                 fstrcpy(domain, full_name);
326                 fstrcpy(name, p+1);
327         } else {
328                 fstrcpy(domain, global_myname);
329                 fstrcpy(name, full_name);
330         }
331
332         DEBUG(10,("split_domain_name:name '%s' split into domain :'%s' and user :'%s'\n",
333                         fullname, domain, name));
334 }
335
336 /*****************************************************************
337  Convert a SID to an ascii string.
338 *****************************************************************/
339
340 char *sid_to_string(fstring sidstr_out, DOM_SID *sid)
341 {
342   char subauth[16];
343   int i;
344   /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
345   uint32 ia = (sid->id_auth[5]) +
346               (sid->id_auth[4] << 8 ) +
347               (sid->id_auth[3] << 16) +
348               (sid->id_auth[2] << 24);
349
350   slprintf(sidstr_out, sizeof(fstring) - 1, "S-%u-%lu", (unsigned int)sid->sid_rev_num, (unsigned long)ia);
351
352   for (i = 0; i < sid->num_auths; i++) {
353     slprintf(subauth, sizeof(subauth)-1, "-%lu", (unsigned long)sid->sub_auths[i]);
354     fstrcat(sidstr_out, subauth);
355   }
356
357   return sidstr_out;
358 }
359
360 /*
361   useful function for debug lines
362 */
363 const char *sid_string_static(DOM_SID *sid)
364 {
365         static fstring sid_str;
366         sid_to_string(sid_str, sid);
367         return sid_str;
368 }
369
370 /*****************************************************************
371  Convert a string to a SID. Returns True on success, False on fail.
372 *****************************************************************/  
373    
374 BOOL string_to_sid(DOM_SID *sidout, const char *sidstr)
375 {
376   pstring tok;
377   char *p, *q;
378   /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
379   uint32 ia;
380   
381   if (StrnCaseCmp( sidstr, "S-", 2)) {
382     DEBUG(0,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr));
383     return False;
384   }
385
386   memset((char *)sidout, '\0', sizeof(DOM_SID));
387
388   q = p = strdup(sidstr + 2);
389   if (p == NULL) {
390     DEBUG(0, ("string_to_sid: out of memory!\n"));
391     return False;
392   }
393
394   if (!next_token(&p, tok, "-", sizeof(tok))) {
395     DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
396     SAFE_FREE(q);
397     return False;
398   }
399
400   /* Get the revision number. */
401   sidout->sid_rev_num = (uint8)strtoul(tok, NULL, 10);
402
403   if (!next_token(&p, tok, "-", sizeof(tok))) {
404     DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
405     SAFE_FREE(q);
406     return False;
407   }
408
409   /* identauth in decimal should be <  2^32 */
410   ia = (uint32)strtoul(tok, NULL, 10);
411
412   /* NOTE - the ia value is in big-endian format. */
413   sidout->id_auth[0] = 0;
414   sidout->id_auth[1] = 0;
415   sidout->id_auth[2] = (ia & 0xff000000) >> 24;
416   sidout->id_auth[3] = (ia & 0x00ff0000) >> 16;
417   sidout->id_auth[4] = (ia & 0x0000ff00) >> 8;
418   sidout->id_auth[5] = (ia & 0x000000ff);
419
420   sidout->num_auths = 0;
421
422   while(next_token(&p, tok, "-", sizeof(tok)) && 
423         sidout->num_auths < MAXSUBAUTHS) {
424     /* 
425      * NOTE - the subauths are in native machine-endian format. They
426      * are converted to little-endian when linearized onto the wire.
427      */
428         sid_append_rid(sidout, (uint32)strtoul(tok, NULL, 10));
429   }
430
431   SAFE_FREE(q);
432   return True;
433 }
434
435 /*****************************************************************
436  Add a rid to the end of a sid
437 *****************************************************************/  
438
439 BOOL sid_append_rid(DOM_SID *sid, uint32 rid)
440 {
441         if (sid->num_auths < MAXSUBAUTHS) {
442                 sid->sub_auths[sid->num_auths++] = rid;
443                 return True;
444         }
445         return False;
446 }
447
448 /*****************************************************************
449  Removes the last rid from the end of a sid
450 *****************************************************************/  
451
452 BOOL sid_split_rid(DOM_SID *sid, uint32 *rid)
453 {
454         if (sid->num_auths > 0) {
455                 sid->num_auths--;
456                 *rid = sid->sub_auths[sid->num_auths];
457                 return True;
458         }
459         return False;
460 }
461
462 /*****************************************************************
463  Return the last rid from the end of a sid
464 *****************************************************************/  
465
466 BOOL sid_peek_rid(DOM_SID *sid, uint32 *rid)
467 {
468         if (sid->num_auths > 0) {
469                 *rid = sid->sub_auths[sid->num_auths - 1];
470                 return True;
471         }
472         return False;
473 }
474
475 /*****************************************************************
476  Copies a sid
477 *****************************************************************/  
478
479 void sid_copy(DOM_SID *dst, const DOM_SID *src)
480 {
481         int i;
482
483         memset((char *)dst, '\0', sizeof(DOM_SID));
484
485         dst->sid_rev_num = src->sid_rev_num;
486         dst->num_auths = src->num_auths;
487
488         memcpy(&dst->id_auth[0], &src->id_auth[0], sizeof(src->id_auth));
489
490         for (i = 0; i < src->num_auths; i++)
491                 dst->sub_auths[i] = src->sub_auths[i];
492 }
493
494 /*****************************************************************
495  Duplicates a sid - mallocs the target.
496 *****************************************************************/
497
498 DOM_SID *sid_dup(DOM_SID *src)
499 {
500   DOM_SID *dst;
501
502   if(!src)
503     return NULL;
504
505   if((dst = malloc(sizeof(DOM_SID))) != NULL) {
506         memset(dst, '\0', sizeof(DOM_SID));
507         sid_copy( dst, src);
508   }
509
510   return dst;
511 }
512
513 /*****************************************************************
514  Write a sid out into on-the-wire format.
515 *****************************************************************/  
516 BOOL sid_linearize(char *outbuf, size_t len, DOM_SID *sid)
517 {
518         size_t i;
519
520         if (len < sid_size(sid))
521                 return False;
522
523         SCVAL(outbuf,0,sid->sid_rev_num);
524         SCVAL(outbuf,1,sid->num_auths);
525         memcpy(&outbuf[2], sid->id_auth, 6);
526         for(i = 0; i < sid->num_auths; i++)
527                 SIVAL(outbuf, 8 + (i*4), sid->sub_auths[i]);
528
529         return True;
530 }
531
532 /*****************************************************************
533  parse a on-the-wire SID to a DOM_SID
534 *****************************************************************/  
535 BOOL sid_parse(char *inbuf, size_t len, DOM_SID *sid)
536 {
537         int i;
538         if (len < 8) return False;
539         sid->sid_rev_num = CVAL(inbuf, 0);
540         sid->num_auths = CVAL(inbuf, 1);
541         memcpy(sid->id_auth, inbuf+2, 6);
542         if (len < 8 + sid->num_auths*4) return False;
543         for (i=0;i<sid->num_auths;i++) {
544                 sid->sub_auths[i] = IVAL(inbuf, 8+i*4);
545         }
546         return True;
547 }
548
549
550 /*****************************************************************
551  Compare the auth portion of two sids.
552 *****************************************************************/  
553 int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2)
554 {
555         int i;
556
557         if (sid1 == sid2) return 0;
558         if (!sid1) return -1;
559         if (!sid2) return 1;
560
561         if (sid1->sid_rev_num != sid2->sid_rev_num)
562                 return sid1->sid_rev_num - sid2->sid_rev_num;
563
564         for (i = 0; i < 6; i++)
565                 if (sid1->id_auth[i] != sid2->id_auth[i])
566                         return sid1->id_auth[i] - sid2->id_auth[i];
567
568         return 0;
569 }
570
571 /*****************************************************************
572  Compare two sids.
573 *****************************************************************/  
574 int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2)
575 {
576         int i;
577
578         if (sid1 == sid2) return 0;
579         if (!sid1) return -1;
580         if (!sid2) return 1;
581
582         /* compare most likely different rids, first: i.e start at end */
583         if (sid1->num_auths != sid2->num_auths)
584                 return sid1->num_auths - sid2->num_auths;
585
586         for (i = sid1->num_auths-1; i >= 0; --i)
587                 if (sid1->sub_auths[i] != sid2->sub_auths[i])
588                         return sid1->sub_auths[i] - sid2->sub_auths[i];
589
590         return sid_compare_auth(sid1, sid2);
591 }
592
593 /*****************************************************************
594 see if 2 SIDs are in the same domain
595 this just compares the leading sub-auths
596 *****************************************************************/  
597 int sid_compare_domain(const DOM_SID *sid1, const DOM_SID *sid2)
598 {
599         int n, i;
600
601         n = MIN(sid1->num_auths, sid2->num_auths);
602
603         for (i = n-1; i >= 0; --i)
604                 if (sid1->sub_auths[i] != sid2->sub_auths[i])
605                         return sid1->sub_auths[i] - sid2->sub_auths[i];
606
607         return sid_compare_auth(sid1, sid2);
608 }
609
610 /*****************************************************************
611  Compare two sids.
612 *****************************************************************/  
613 BOOL sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
614 {
615         return sid_compare(sid1, sid2) == 0;
616 }
617
618
619 /*****************************************************************
620  Check if the SID is our domain SID (S-1-5-21-x-y-z).
621 *****************************************************************/  
622 BOOL sid_check_is_domain(const DOM_SID *sid)
623 {
624         return sid_equal(sid, &global_sam_sid);
625 }
626
627
628 /*****************************************************************
629  Check if the SID is the builtin SID (S-1-5-32).
630 *****************************************************************/  
631 BOOL sid_check_is_builtin(const DOM_SID *sid)
632 {
633         return sid_equal(sid, &global_sid_Builtin);
634 }
635
636
637 /*****************************************************************
638  Check if the SID is our domain SID (S-1-5-21-x-y-z).
639 *****************************************************************/  
640 BOOL sid_check_is_in_our_domain(const DOM_SID *sid)
641 {
642         DOM_SID dom_sid;
643         uint32 rid;
644
645         sid_copy(&dom_sid, sid);
646         sid_split_rid(&dom_sid, &rid);
647         
648         return sid_equal(&dom_sid, &global_sam_sid);
649 }
650
651 /*****************************************************************
652  Check if the SID is our domain SID (S-1-5-21-x-y-z).
653 *****************************************************************/  
654 BOOL sid_check_is_in_builtin(const DOM_SID *sid)
655 {
656         DOM_SID dom_sid;
657         uint32 rid;
658
659         sid_copy(&dom_sid, sid);
660         sid_split_rid(&dom_sid, &rid);
661         
662         return sid_equal(&dom_sid, &global_sid_Builtin);
663 }
664
665
666 /*****************************************************************
667  Calculates size of a sid.
668 *****************************************************************/  
669
670 size_t sid_size(DOM_SID *sid)
671 {
672         if (sid == NULL)
673                 return 0;
674
675         return sid->num_auths * sizeof(uint32) + 8;
676 }
677
678 /*****************************************************************
679  Returns true if SID is internal (and non-mappable).
680 *****************************************************************/
681
682 BOOL non_mappable_sid(DOM_SID *sid)
683 {
684         DOM_SID dom;
685         uint32 rid;
686
687         sid_copy(&dom, sid);
688         sid_split_rid(&dom, &rid);
689
690         if (sid_equal(&dom, &global_sid_Builtin))
691                 return True;
692
693         if (sid_equal(&dom, &global_sid_Creator_Owner_Domain))
694                 return True;
695  
696         if (sid_equal(&dom, &global_sid_NT_Authority))
697                 return True;
698
699         return False;
700 }
701
702 /*
703   return the binary string representation of a DOM_SID
704   caller must free
705 */
706 char *sid_binstring(DOM_SID *sid)
707 {
708         char *buf, *s;
709         int len = sid_size(sid);
710         buf = malloc(len);
711         if (!buf) return NULL;
712         sid_linearize(buf, len, sid);
713         s = binary_string(buf, len);
714         free(buf);
715         return s;
716 }
717