r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
[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    Copyright (C) Stefan (metze) Metzmacher      2002
8    Copyright (C) Simo Sorce                     2002
9    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
10       
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 2 of the License, or
14    (at your option) any later version.
15    
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.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "includes.h"
27
28 /*
29  * Some useful sids
30  */
31
32
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 const DOM_SID global_sid_Network =                      /* Network rids */
48 { 1, 1, {0,0,0,0,0,5}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
49
50 const DOM_SID global_sid_Creator_Owner =                /* Creator Owner */
51 { 1, 1, {0,0,0,0,0,3}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
52 const DOM_SID global_sid_Creator_Group =                /* Creator Group */
53 { 1, 1, {0,0,0,0,0,3}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
54 const DOM_SID global_sid_Anonymous =                    /* Anonymous login */
55 { 1, 1, {0,0,0,0,0,5}, {7,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
56
57 const DOM_SID global_sid_Builtin =                      /* Local well-known domain */
58 { 1, 1, {0,0,0,0,0,5}, {32,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
59 const DOM_SID global_sid_Builtin_Administrators =       /* Builtin administrators */
60 { 1, 2, {0,0,0,0,0,5}, {32,544,0,0,0,0,0,0,0,0,0,0,0,0,0}};
61 const DOM_SID global_sid_Builtin_Users =                /* Builtin users */
62 { 1, 2, {0,0,0,0,0,5}, {32,545,0,0,0,0,0,0,0,0,0,0,0,0,0}};
63 const DOM_SID global_sid_Builtin_Guests =               /* Builtin guest users */
64 { 1, 2, {0,0,0,0,0,5}, {32,546,0,0,0,0,0,0,0,0,0,0,0,0,0}};
65 const DOM_SID global_sid_Builtin_Power_Users =  /* Builtin power users */
66 { 1, 2, {0,0,0,0,0,5}, {32,547,0,0,0,0,0,0,0,0,0,0,0,0,0}};
67 const DOM_SID global_sid_Builtin_Account_Operators =    /* Builtin account operators */
68 { 1, 2, {0,0,0,0,0,5}, {32,548,0,0,0,0,0,0,0,0,0,0,0,0,0}};
69 const DOM_SID global_sid_Builtin_Server_Operators =     /* Builtin server operators */
70 { 1, 2, {0,0,0,0,0,5}, {32,549,0,0,0,0,0,0,0,0,0,0,0,0,0}};
71 const DOM_SID global_sid_Builtin_Print_Operators =      /* Builtin print operators */
72 { 1, 2, {0,0,0,0,0,5}, {32,550,0,0,0,0,0,0,0,0,0,0,0,0,0}};
73 const DOM_SID global_sid_Builtin_Backup_Operators =     /* Builtin backup operators */
74 { 1, 2, {0,0,0,0,0,5}, {32,551,0,0,0,0,0,0,0,0,0,0,0,0,0}};
75 const DOM_SID global_sid_Builtin_Replicator =           /* Builtin replicator */
76 { 1, 2, {0,0,0,0,0,5}, {32,552,0,0,0,0,0,0,0,0,0,0,0,0,0}};
77
78 const DOM_SID global_sid_Unix_Users =                   /* Unmapped Unix users */
79 { 1, 1, {0,0,0,0,0,22}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
80 const DOM_SID global_sid_Unix_Groups =                  /* Unmapped Unix groups */
81 { 1, 1, {0,0,0,0,0,22}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
82
83 /* Unused, left here for documentary purposes */
84 #if 0
85 #define SECURITY_NULL_SID_AUTHORITY    0
86 #define SECURITY_WORLD_SID_AUTHORITY   1
87 #define SECURITY_LOCAL_SID_AUTHORITY   2
88 #define SECURITY_CREATOR_SID_AUTHORITY 3
89 #define SECURITY_NT_AUTHORITY          5
90 #endif
91
92 /*
93  * An NT compatible anonymous token.
94  */
95
96 static DOM_SID anon_sid_array[3] =
97 { { 1, 1, {0,0,0,0,0,1}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
98   { 1, 1, {0,0,0,0,0,5}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
99   { 1, 1, {0,0,0,0,0,5}, {7,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} };
100 NT_USER_TOKEN anonymous_token = { 3, anon_sid_array, SE_NONE };
101
102 static DOM_SID system_sid_array[1] =
103 { { 1, 1, {0,0,0,0,0,5}, {18,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} };
104 NT_USER_TOKEN system_token = { 1, system_sid_array, SE_ALL_PRIVS };
105
106 /****************************************************************************
107  Lookup string names for SID types.
108 ****************************************************************************/
109
110 static const struct {
111         enum SID_NAME_USE sid_type;
112         const char *string;
113 } sid_name_type[] = {
114         {SID_NAME_USER, "User"},
115         {SID_NAME_DOM_GRP, "Domain Group"},
116         {SID_NAME_DOMAIN, "Domain"},
117         {SID_NAME_ALIAS, "Local Group"},
118         {SID_NAME_WKN_GRP, "Well-known Group"},
119         {SID_NAME_DELETED, "Deleted Account"},
120         {SID_NAME_INVALID, "Invalid Account"},
121         {SID_NAME_UNKNOWN, "UNKNOWN"},
122         {SID_NAME_COMPUTER, "Computer"},
123
124         {(enum SID_NAME_USE)0, NULL}
125 };
126
127 const char *sid_type_lookup(uint32 sid_type) 
128 {
129         int i = 0;
130
131         /* Look through list */
132         while(sid_name_type[i].sid_type != 0) {
133                 if (sid_name_type[i].sid_type == sid_type)
134                         return sid_name_type[i].string;
135                 i++;
136         }
137
138         /* Default return */
139         return "SID *TYPE* is INVALID";
140 }
141
142 /**************************************************************************
143  Create the SYSTEM token.
144 ***************************************************************************/
145
146 NT_USER_TOKEN *get_system_token(void) 
147 {
148         return &system_token;
149 }
150
151 /******************************************************************
152  get the default domain/netbios name to be used when dealing 
153  with our passdb list of accounts
154 ******************************************************************/
155
156 const char *get_global_sam_name(void) 
157 {
158         if ((lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC)) {
159                 return lp_workgroup();
160         }
161         return global_myname();
162 }
163
164 /*****************************************************************
165  Convert a SID to an ascii string.
166 *****************************************************************/
167
168 char *sid_to_string(fstring sidstr_out, const DOM_SID *sid)
169 {
170         char subauth[16];
171         int i;
172         uint32 ia;
173   
174         if (!sid) {
175                 fstrcpy(sidstr_out, "(NULL SID)");
176                 return sidstr_out;
177         }
178
179         /*
180          * BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 
181          * in a range of 2^48.
182          */
183         ia = (sid->id_auth[5]) +
184                 (sid->id_auth[4] << 8 ) +
185                 (sid->id_auth[3] << 16) +
186                 (sid->id_auth[2] << 24);
187
188         slprintf(sidstr_out, sizeof(fstring) - 1, "S-%u-%lu", (unsigned int)sid->sid_rev_num, (unsigned long)ia);
189
190         for (i = 0; i < sid->num_auths; i++) {
191                 slprintf(subauth, sizeof(subauth)-1, "-%lu", (unsigned long)sid->sub_auths[i]);
192                 fstrcat(sidstr_out, subauth);
193         }
194
195         return sidstr_out;
196 }
197
198 /*****************************************************************
199  Useful function for debug lines.
200 *****************************************************************/  
201
202 const char *sid_string_static(const DOM_SID *sid)
203 {
204         static fstring sid_str;
205         sid_to_string(sid_str, sid);
206         return sid_str;
207 }
208
209 /*****************************************************************
210  Convert a string to a SID. Returns True on success, False on fail.
211 *****************************************************************/  
212    
213 BOOL string_to_sid(DOM_SID *sidout, const char *sidstr)
214 {
215         const char *p;
216         char *q;
217         /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
218         uint32 conv;
219   
220         if ((sidstr[0] != 'S' && sidstr[0] != 's') || sidstr[1] != '-') {
221                 DEBUG(3,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr));
222                 return False;
223         }
224
225         ZERO_STRUCTP(sidout);
226
227         /* Get the revision number. */
228         p = sidstr + 2;
229         conv = (uint32) strtoul(p, &q, 10);
230         if (!q || (*q != '-')) {
231                 DEBUG(3,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
232                 return False;
233         }
234         sidout->sid_rev_num = (uint8) conv;
235         q++;
236
237         /* get identauth */
238         conv = (uint32) strtoul(q, &q, 10);
239         if (!q || (*q != '-')) {
240                 DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
241                 return False;
242         }
243         /* identauth in decimal should be <  2^32 */
244         /* NOTE - the conv value is in big-endian format. */
245         sidout->id_auth[0] = 0;
246         sidout->id_auth[1] = 0;
247         sidout->id_auth[2] = (conv & 0xff000000) >> 24;
248         sidout->id_auth[3] = (conv & 0x00ff0000) >> 16;
249         sidout->id_auth[4] = (conv & 0x0000ff00) >> 8;
250         sidout->id_auth[5] = (conv & 0x000000ff);
251
252         q++;
253         sidout->num_auths = 0;
254
255         for(conv = (uint32) strtoul(q, &q, 10);
256             q && (*q =='-' || *q =='\0') && (sidout->num_auths < MAXSUBAUTHS);
257             conv = (uint32) strtoul(q, &q, 10)) {
258                 sid_append_rid(sidout, conv);
259                 if (*q == '\0')
260                         break;
261                 q++;
262         }
263                 
264         return True;
265 }
266
267 DOM_SID *string_sid_talloc(TALLOC_CTX *mem_ctx, const char *sidstr)
268 {
269         DOM_SID *result = TALLOC_P(mem_ctx, DOM_SID);
270
271         if (result == NULL)
272                 return NULL;
273
274         if (!string_to_sid(result, sidstr))
275                 return NULL;
276
277         return result;
278 }
279
280 /*****************************************************************
281  Add a rid to the end of a sid
282 *****************************************************************/  
283
284 BOOL sid_append_rid(DOM_SID *sid, uint32 rid)
285 {
286         if (sid->num_auths < MAXSUBAUTHS) {
287                 sid->sub_auths[sid->num_auths++] = rid;
288                 return True;
289         }
290         return False;
291 }
292
293 BOOL sid_compose(DOM_SID *dst, const DOM_SID *domain_sid, uint32 rid)
294 {
295         sid_copy(dst, domain_sid);
296         return sid_append_rid(dst, rid);
297 }
298
299 /*****************************************************************
300  Removes the last rid from the end of a sid
301 *****************************************************************/  
302
303 BOOL sid_split_rid(DOM_SID *sid, uint32 *rid)
304 {
305         if (sid->num_auths > 0) {
306                 sid->num_auths--;
307                 *rid = sid->sub_auths[sid->num_auths];
308                 return True;
309         }
310         return False;
311 }
312
313 /*****************************************************************
314  Return the last rid from the end of a sid
315 *****************************************************************/  
316
317 BOOL sid_peek_rid(const DOM_SID *sid, uint32 *rid)
318 {
319         if (!sid || !rid)
320                 return False;           
321         
322         if (sid->num_auths > 0) {
323                 *rid = sid->sub_auths[sid->num_auths - 1];
324                 return True;
325         }
326         return False;
327 }
328
329 /*****************************************************************
330  Return the last rid from the end of a sid
331  and check the sid against the exp_dom_sid  
332 *****************************************************************/  
333
334 BOOL sid_peek_check_rid(const DOM_SID *exp_dom_sid, const DOM_SID *sid, uint32 *rid)
335 {
336         if (!exp_dom_sid || !sid || !rid)
337                 return False;
338                         
339         if (sid->num_auths != (exp_dom_sid->num_auths+1)) {
340                 return False;
341         }
342
343         if (sid_compare_domain(exp_dom_sid, sid)!=0){
344                 *rid=(-1);
345                 return False;
346         }
347         
348         return sid_peek_rid(sid, rid);
349 }
350
351 /*****************************************************************
352  Copies a sid
353 *****************************************************************/  
354
355 void sid_copy(DOM_SID *dst, const DOM_SID *src)
356 {
357         int i;
358
359         ZERO_STRUCTP(dst);
360
361         dst->sid_rev_num = src->sid_rev_num;
362         dst->num_auths = src->num_auths;
363
364         memcpy(&dst->id_auth[0], &src->id_auth[0], sizeof(src->id_auth));
365
366         for (i = 0; i < src->num_auths; i++)
367                 dst->sub_auths[i] = src->sub_auths[i];
368 }
369
370 /*****************************************************************
371  Write a sid out into on-the-wire format.
372 *****************************************************************/  
373
374 BOOL sid_linearize(char *outbuf, size_t len, const DOM_SID *sid)
375 {
376         size_t i;
377
378         if (len < sid_size(sid))
379                 return False;
380
381         SCVAL(outbuf,0,sid->sid_rev_num);
382         SCVAL(outbuf,1,sid->num_auths);
383         memcpy(&outbuf[2], sid->id_auth, 6);
384         for(i = 0; i < sid->num_auths; i++)
385                 SIVAL(outbuf, 8 + (i*4), sid->sub_auths[i]);
386
387         return True;
388 }
389
390 /*****************************************************************
391  Parse a on-the-wire SID to a DOM_SID.
392 *****************************************************************/  
393
394 BOOL sid_parse(const char *inbuf, size_t len, DOM_SID *sid)
395 {
396         int i;
397         if (len < 8)
398                 return False;
399
400         ZERO_STRUCTP(sid);
401
402         sid->sid_rev_num = CVAL(inbuf, 0);
403         sid->num_auths = CVAL(inbuf, 1);
404         memcpy(sid->id_auth, inbuf+2, 6);
405         if (len < 8 + sid->num_auths*4)
406                 return False;
407         for (i=0;i<sid->num_auths;i++)
408                 sid->sub_auths[i] = IVAL(inbuf, 8+i*4);
409         return True;
410 }
411
412 /*****************************************************************
413  Compare the auth portion of two sids.
414 *****************************************************************/  
415
416 static int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2)
417 {
418         int i;
419
420         if (sid1 == sid2)
421                 return 0;
422         if (!sid1)
423                 return -1;
424         if (!sid2)
425                 return 1;
426
427         if (sid1->sid_rev_num != sid2->sid_rev_num)
428                 return sid1->sid_rev_num - sid2->sid_rev_num;
429
430         for (i = 0; i < 6; i++)
431                 if (sid1->id_auth[i] != sid2->id_auth[i])
432                         return sid1->id_auth[i] - sid2->id_auth[i];
433
434         return 0;
435 }
436
437 /*****************************************************************
438  Compare two sids.
439 *****************************************************************/  
440
441 int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2)
442 {
443         int i;
444
445         if (sid1 == sid2)
446                 return 0;
447         if (!sid1)
448                 return -1;
449         if (!sid2)
450                 return 1;
451
452         /* Compare most likely different rids, first: i.e start at end */
453         if (sid1->num_auths != sid2->num_auths)
454                 return sid1->num_auths - sid2->num_auths;
455
456         for (i = sid1->num_auths-1; i >= 0; --i)
457                 if (sid1->sub_auths[i] != sid2->sub_auths[i])
458                         return sid1->sub_auths[i] - sid2->sub_auths[i];
459
460         return sid_compare_auth(sid1, sid2);
461 }
462
463 /*****************************************************************
464  See if 2 SIDs are in the same domain
465  this just compares the leading sub-auths
466 *****************************************************************/  
467
468 int sid_compare_domain(const DOM_SID *sid1, const DOM_SID *sid2)
469 {
470         int n, i;
471
472         n = MIN(sid1->num_auths, sid2->num_auths);
473
474         for (i = n-1; i >= 0; --i)
475                 if (sid1->sub_auths[i] != sid2->sub_auths[i])
476                         return sid1->sub_auths[i] - sid2->sub_auths[i];
477
478         return sid_compare_auth(sid1, sid2);
479 }
480
481 /*****************************************************************
482  Compare two sids.
483 *****************************************************************/  
484
485 BOOL sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
486 {
487         return sid_compare(sid1, sid2) == 0;
488 }
489
490 /*****************************************************************
491  Calculates size of a sid.
492 *****************************************************************/  
493
494 size_t sid_size(const DOM_SID *sid)
495 {
496         if (sid == NULL)
497                 return 0;
498
499         return sid->num_auths * sizeof(uint32) + 8;
500 }
501
502 /*****************************************************************
503  Returns true if SID is internal (and non-mappable).
504 *****************************************************************/
505
506 BOOL non_mappable_sid(DOM_SID *sid)
507 {
508         DOM_SID dom;
509         uint32 rid;
510
511         sid_copy(&dom, sid);
512         sid_split_rid(&dom, &rid);
513
514         if (sid_equal(&dom, &global_sid_Builtin))
515                 return True;
516
517         if (sid_equal(&dom, &global_sid_NT_Authority))
518                 return True;
519
520         return False;
521 }
522
523 /*****************************************************************
524  Return the binary string representation of a DOM_SID.
525  Caller must free.
526 *****************************************************************/
527
528 char *sid_binstring(const DOM_SID *sid)
529 {
530         char *buf, *s;
531         int len = sid_size(sid);
532         buf = SMB_MALLOC(len);
533         if (!buf)
534                 return NULL;
535         sid_linearize(buf, len, sid);
536         s = binary_string(buf, len);
537         free(buf);
538         return s;
539 }
540
541 /*******************************************************************
542  Tallocs a duplicate SID. 
543 ********************************************************************/ 
544
545 DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, const DOM_SID *src)
546 {
547         DOM_SID *dst;
548         
549         if(!src)
550                 return NULL;
551         
552         if((dst = TALLOC_ZERO_P(ctx, DOM_SID)) != NULL) {
553                 sid_copy( dst, src);
554         }
555         
556         return dst;
557 }
558
559 /********************************************************************
560  Add SID to an array SIDs
561 ********************************************************************/
562
563 void add_sid_to_array(TALLOC_CTX *mem_ctx, const DOM_SID *sid, 
564                       DOM_SID **sids, size_t *num)
565 {
566         if (mem_ctx != NULL) {
567                 *sids = TALLOC_REALLOC_ARRAY(mem_ctx, *sids, DOM_SID,
568                                              (*num)+1);
569         } else {
570                 *sids = SMB_REALLOC_ARRAY(*sids, DOM_SID, (*num)+1);
571         }
572
573         if (*sids == NULL) {
574                 return;
575         }
576
577         sid_copy(&((*sids)[*num]), sid);
578         *num += 1;
579
580         return;
581 }
582
583
584 /********************************************************************
585  Add SID to an array SIDs ensuring that it is not already there
586 ********************************************************************/
587
588 void add_sid_to_array_unique(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
589                              DOM_SID **sids, size_t *num_sids)
590 {
591         size_t i;
592
593         for (i=0; i<(*num_sids); i++) {
594                 if (sid_compare(sid, &(*sids)[i]) == 0)
595                         return;
596         }
597
598         add_sid_to_array(mem_ctx, sid, sids, num_sids);
599 }
600
601 /********************************************************************
602  Remove SID from an array
603 ********************************************************************/
604
605 void del_sid_from_array(const DOM_SID *sid, DOM_SID **sids, size_t *num)
606 {
607         DOM_SID *sid_list = *sids;
608         size_t i;
609
610         for ( i=0; i<*num; i++ ) {
611
612                 /* if we find the SID, then decrement the count
613                    and break out of the loop */
614
615                 if ( sid_equal(sid, &sid_list[i]) ) {
616                         *num -= 1;
617                         break;
618                 }
619         }
620
621         /* This loop will copy the remainder of the array 
622            if i < num of sids ni the array */
623
624         for ( ; i<*num; i++ ) 
625                 sid_copy( &sid_list[i], &sid_list[i+1] );
626         
627         return;
628 }
629
630 BOOL is_null_sid(const DOM_SID *sid)
631 {
632         static const DOM_SID null_sid = {0};
633         return sid_equal(sid, &null_sid);
634 }