Missing return in free_privilege()
[amitay/samba.git] / source3 / groupdb / mapping.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2001.
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 extern DOM_SID global_sam_sid;
26
27 static TDB_CONTEXT *tdb; /* used for driver files */
28
29 #define DATABASE_VERSION 1
30 #define GROUP_PREFIX "UNIXGROUP/"
31
32 PRIVS privs[] = {
33         {SE_PRIV_NONE,           "no_privs",                  "No privilege"                    }, /* this one MUST be first */
34         {SE_PRIV_ADD_MACHINES,   "SeMachineAccountPrivilege", "Add workstations to the domain"  },
35         {SE_PRIV_SEC_PRIV,       "SeSecurityPrivilege",       "Manage the audit logs"           },
36         {SE_PRIV_TAKE_OWNER,     "SeTakeOwnershipPrivilege",  "Take ownership of file"          },
37         {SE_PRIV_ADD_USERS,      "SaAddUsers",                "Add users to the domain - Samba" },
38         {SE_PRIV_PRINT_OPERATOR, "SaPrintOp",                 "Add or remove printers - Samba"  },
39         {SE_PRIV_ALL,            "SaAllPrivs",                "all privileges"                  }
40 };
41 /*
42 PRIVS privs[] = {
43         {  2, "SeCreateTokenPrivilege" },
44         {  3, "SeAssignPrimaryTokenPrivilege" },
45         {  4, "SeLockMemoryPrivilege" },
46         {  5, "SeIncreaseQuotaPrivilege" },
47         {  6, "SeMachineAccountPrivilege" },
48         {  7, "SeTcbPrivilege" },
49         {  8, "SeSecurityPrivilege" },
50         {  9, "SeTakeOwnershipPrivilege" },
51         { 10, "SeLoadDriverPrivilege" },
52         { 11, "SeSystemProfilePrivilege" },
53         { 12, "SeSystemtimePrivilege" },
54         { 13, "SeProfileSingleProcessPrivilege" },
55         { 14, "SeIncreaseBasePriorityPrivilege" },
56         { 15, "SeCreatePagefilePrivilege" },
57         { 16, "SeCreatePermanentPrivilege" },
58         { 17, "SeBackupPrivilege" },
59         { 18, "SeRestorePrivilege" },
60         { 19, "SeShutdownPrivilege" },
61         { 20, "SeDebugPrivilege" },
62         { 21, "SeAuditPrivilege" },
63         { 22, "SeSystemEnvironmentPrivilege" },
64         { 23, "SeChangeNotifyPrivilege" },
65         { 24, "SeRemoteShutdownPrivilege" },
66         { 25, "SeUndockPrivilege" },
67         { 26, "SeSyncAgentPrivilege" },
68         { 27, "SeEnableDelegationPrivilege" },
69 };
70 */
71
72         /*
73          * Those are not really privileges like the other ones.
74          * They are handled in a special case and called
75          * system privileges.
76          *
77          * SeNetworkLogonRight
78          * SeUnsolicitedInputPrivilege
79          * SeBatchLogonRight
80          * SeServiceLogonRight
81          * SeInteractiveLogonRight
82          * SeDenyInteractiveLogonRight
83          * SeDenyNetworkLogonRight
84          * SeDenyBatchLogonRight
85          * SeDenyBatchLogonRight
86          */
87
88 #if 0
89 /****************************************************************************
90 check if the user has the required privilege.
91 ****************************************************************************/
92 static BOOL se_priv_access_check(NT_USER_TOKEN *token, uint32 privilege)
93 {
94         /* no token, no privilege */
95         if (token==NULL)
96                 return False;
97         
98         if ((token->privilege & privilege)==privilege)
99                 return True;
100         
101         return False;
102 }
103 #endif
104
105 /****************************************************************************
106 dump the mapping group mapping to a text file
107 ****************************************************************************/
108 char *decode_sid_name_use(fstring group, enum SID_NAME_USE name_use)
109 {       
110         static fstring group_type;
111
112         switch(name_use) {
113                 case SID_NAME_USER:
114                         fstrcpy(group_type,"User");
115                         break;
116                 case SID_NAME_DOM_GRP:
117                         fstrcpy(group_type,"Domain group");
118                         break;
119                 case SID_NAME_DOMAIN:
120                         fstrcpy(group_type,"Domain");
121                         break;
122                 case SID_NAME_ALIAS:
123                         fstrcpy(group_type,"Local group");
124                         break;
125                 case SID_NAME_WKN_GRP:
126                         fstrcpy(group_type,"Builtin group");
127                         break;
128                 case SID_NAME_DELETED:
129                         fstrcpy(group_type,"Deleted");
130                         break;
131                 case SID_NAME_INVALID:
132                         fstrcpy(group_type,"Invalid");
133                         break;
134                 case SID_NAME_UNKNOWN:
135                 default:
136                         fstrcpy(group_type,"Unknown type");
137                         break;
138         }
139         
140         fstrcpy(group, group_type);
141         return group_type;
142 }
143
144 /****************************************************************************
145 open the group mapping tdb
146 ****************************************************************************/
147 BOOL init_group_mapping(void)
148 {
149         static pid_t local_pid;
150         char *vstring = "INFO/version";
151
152         if (tdb && local_pid == sys_getpid()) return True;
153         tdb = tdb_open_log(lock_path("group_mapping.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
154         if (!tdb) {
155                 DEBUG(0,("Failed to open group mapping database\n"));
156                 return False;
157         }
158
159         local_pid = sys_getpid();
160
161         /* handle a Samba upgrade */
162         tdb_lock_bystring(tdb, vstring);
163         if (tdb_fetch_int(tdb, vstring) != DATABASE_VERSION) {
164                 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
165                 tdb_store_int(tdb, vstring, DATABASE_VERSION);
166         }
167         tdb_unlock_bystring(tdb, vstring);
168
169
170         return True;
171 }
172
173 /****************************************************************************
174 ****************************************************************************/
175 BOOL add_mapping_entry(GROUP_MAP *map, int flag)
176 {
177         TDB_DATA kbuf, dbuf;
178         pstring key, buf;
179         fstring string_sid="";
180         int len;
181         int i;
182         PRIVILEGE_SET *set;
183         
184         sid_to_string(string_sid, &map->sid);
185
186         len = tdb_pack(buf, sizeof(buf), "ddffd",
187                         map->gid, map->sid_name_use, map->nt_name, map->comment, map->systemaccount);
188
189         /* write the privilege list in the TDB database */
190
191         set=&map->priv_set;
192         len += tdb_pack(buf+len, sizeof(buf)-len, "d", set->count);
193         for (i=0; i<set->count; i++)
194                 len += tdb_pack(buf+len, sizeof(buf)-len, "ddd", 
195                                 set->set[i].luid.low, set->set[i].luid.high, set->set[i].attr);
196
197         if (len > sizeof(buf))
198                 return False;
199
200         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
201
202         kbuf.dsize = strlen(key)+1;
203         kbuf.dptr = key;
204         dbuf.dsize = len;
205         dbuf.dptr = buf;
206         if (tdb_store(tdb, kbuf, dbuf, flag) != 0) return False;
207
208         return True;
209 }
210
211 /****************************************************************************
212 initialise first time the mapping list
213 ****************************************************************************/
214 BOOL add_initial_entry(gid_t gid, fstring sid, enum SID_NAME_USE sid_name_use,
215                               fstring nt_name, fstring comment, PRIVILEGE_SET priv_set, uint32 systemaccount)
216 {
217         GROUP_MAP map;
218
219         map.gid=gid;
220         string_to_sid(&map.sid, sid);
221         map.sid_name_use=sid_name_use;
222         fstrcpy(map.nt_name, nt_name);
223         fstrcpy(map.comment, comment);
224         map.systemaccount=systemaccount;
225
226         map.priv_set.count=priv_set.count;
227         map.priv_set.set=priv_set.set;
228
229         add_mapping_entry(&map, TDB_INSERT);
230
231         return True;
232 }
233
234 /****************************************************************************
235 initialise a privilege list
236 ****************************************************************************/
237 void init_privilege(PRIVILEGE_SET *priv_set)
238 {
239         priv_set->count=0;
240         priv_set->control=0;
241         priv_set->set=NULL;
242 }
243
244 /****************************************************************************
245 free a privilege list
246 ****************************************************************************/
247 BOOL free_privilege(PRIVILEGE_SET *priv_set)
248 {
249         if (priv_set->count==0) {
250                 DEBUG(10,("free_privilege: count=0, nothing to clear ?\n"));
251                 return False;
252         }
253
254         if (priv_set->set==NULL) {
255                 DEBUG(0,("free_privilege: list ptr is NULL, very strange !\n"));
256                 return False;
257         }
258
259         safe_free(priv_set->set);
260         priv_set->count=0;
261         priv_set->control=0;
262         priv_set->set=NULL;
263
264         return True;
265 }
266
267 /****************************************************************************
268 add a privilege to a privilege array
269 ****************************************************************************/
270 BOOL add_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
271 {
272         LUID_ATTR *new_set;
273
274         /* check if the privilege is not already in the list */
275         if (check_priv_in_privilege(priv_set, set))
276                 return False;
277
278         /* we can allocate memory to add the new privilege */
279
280         new_set=(LUID_ATTR *)Realloc(priv_set->set, (priv_set->count+1)*(sizeof(LUID_ATTR)));
281         if (new_set==NULL) {
282                 DEBUG(0,("add_privilege: could not Realloc memory to add a new privilege\n"));
283                 return False;
284         }
285
286         new_set[priv_set->count].luid.high=set.luid.high;
287         new_set[priv_set->count].luid.low=set.luid.low;
288         new_set[priv_set->count].attr=set.attr;
289         
290         priv_set->count++;
291         priv_set->set=new_set;
292         
293         return True;    
294 }
295
296 /****************************************************************************
297 add all the privileges to a privilege array
298 ****************************************************************************/
299 BOOL add_all_privilege(PRIVILEGE_SET *priv_set)
300 {
301         LUID_ATTR set;
302
303         set.attr=0;
304         set.luid.high=0;
305         
306         set.luid.low=SE_PRIV_ADD_USERS;
307         add_privilege(priv_set, set);
308
309         set.luid.low=SE_PRIV_ADD_MACHINES;
310         add_privilege(priv_set, set);
311
312         set.luid.low=SE_PRIV_PRINT_OPERATOR;
313         add_privilege(priv_set, set);
314         
315         return True;
316 }
317
318 /****************************************************************************
319 check if the privilege list is empty
320 ****************************************************************************/
321 BOOL check_empty_privilege(PRIVILEGE_SET *priv_set)
322 {
323
324         if (priv_set->count!=0)
325                 return False;
326
327         return True;
328 }
329
330 /****************************************************************************
331 check if the privilege is in the privilege list
332 ****************************************************************************/
333 BOOL check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
334 {
335         int i;
336
337         /* if the list is empty, obviously we can't have it */
338         if (check_empty_privilege(priv_set))
339                 return False;
340
341         for (i=0; i<priv_set->count; i++) {
342                 LUID_ATTR *cur_set;
343
344                 cur_set=&priv_set->set[i];
345                 /* check only the low and high part. Checking the attr field has no meaning */
346                 if( (cur_set->luid.low==set.luid.low) && (cur_set->luid.high==set.luid.high) )
347                         return True;
348         }
349
350         return False;
351 }
352
353 /****************************************************************************
354 remove a privilege to a privilege array
355 ****************************************************************************/
356 BOOL remove_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
357 {
358         LUID_ATTR *new_set;
359         LUID_ATTR *old_set;
360         int i,j;
361
362         /* check if the privilege is in the list */
363         if (!check_priv_in_privilege(priv_set, set))
364                 return False;
365
366         /* special case if it's the only privilege in the list */
367         if (priv_set->count==1) {
368                 free_privilege(priv_set);
369                 init_privilege(priv_set);       
370         
371                 return True;
372         }
373
374         /* 
375          * the privilege is there, create a new list,
376          * and copy the other privileges
377          */
378
379         old_set=priv_set->set;
380
381         new_set=(LUID_ATTR *)malloc((priv_set->count-1)*(sizeof(LUID_ATTR)));
382         if (new_set==NULL) {
383                 DEBUG(0,("remove_privilege: could not malloc memory for new privilege list\n"));
384                 return False;
385         }
386
387         for (i=0, j=0; i<priv_set->count; i++) {
388                 if ((old_set[i].luid.low==set.luid.low) && 
389                     (old_set[i].luid.high==set.luid.high)) {
390                         continue;
391                 }
392                 
393                 new_set[j].luid.low=old_set[i].luid.low;
394                 new_set[j].luid.high=old_set[i].luid.high;
395                 new_set[j].attr=old_set[i].attr;
396
397                 j++;
398         }
399         
400         if (j!=priv_set->count-1) {
401                 DEBUG(0,("remove_privilege: mismatch ! difference is not -1\n"));
402                 DEBUGADD(0,("old count:%d, new count:%d\n", priv_set->count, j));
403                 safe_free(new_set);
404                 return False;
405         }
406                 
407         /* ok everything is fine */
408         
409         priv_set->count--;
410         priv_set->set=new_set;
411         
412         safe_free(old_set);
413         
414         return True;    
415 }
416
417 /****************************************************************************
418 initialise first time the mapping list
419 ****************************************************************************/
420 BOOL default_group_mapping(void)
421 {
422         DOM_SID sid_admins;
423         DOM_SID sid_users;
424         DOM_SID sid_guests;
425         fstring str_admins;
426         fstring str_users;
427         fstring str_guests;
428         LUID_ATTR set;
429
430         PRIVILEGE_SET privilege_none;
431         PRIVILEGE_SET privilege_all;
432         PRIVILEGE_SET privilege_print_op;
433
434         init_privilege(&privilege_none);
435         init_privilege(&privilege_all);
436         init_privilege(&privilege_print_op);
437
438         set.attr=0;
439         set.luid.high=0;
440         set.luid.low=SE_PRIV_PRINT_OPERATOR;
441         add_privilege(&privilege_print_op, set);
442
443         add_all_privilege(&privilege_all);
444
445         /* Add the Wellknown groups */
446
447         add_initial_entry(-1, "S-1-5-32-544", SID_NAME_WKN_GRP, "Administrators", "", privilege_all, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
448         add_initial_entry(-1, "S-1-5-32-545", SID_NAME_WKN_GRP, "Users", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
449         add_initial_entry(-1, "S-1-5-32-546", SID_NAME_WKN_GRP, "Guests", "", privilege_none, PR_ACCESS_FROM_NETWORK);
450         add_initial_entry(-1, "S-1-5-32-547", SID_NAME_WKN_GRP, "Power Users", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
451
452         add_initial_entry(-1, "S-1-5-32-548", SID_NAME_WKN_GRP, "Account Operators", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
453         add_initial_entry(-1, "S-1-5-32-549", SID_NAME_WKN_GRP, "System Operators", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
454         add_initial_entry(-1, "S-1-5-32-550", SID_NAME_WKN_GRP, "Print Operators", "", privilege_print_op, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
455         add_initial_entry(-1, "S-1-5-32-551", SID_NAME_WKN_GRP, "Backup Operators", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
456
457         add_initial_entry(-1, "S-1-5-32-552", SID_NAME_WKN_GRP, "Replicators", "", privilege_none, PR_ACCESS_FROM_NETWORK);
458
459         /* Add the defaults domain groups */
460
461         sid_copy(&sid_admins, &global_sam_sid);
462         sid_append_rid(&sid_admins, DOMAIN_GROUP_RID_ADMINS);
463         sid_to_string(str_admins, &sid_admins);
464         add_initial_entry(-1, str_admins, SID_NAME_DOM_GRP, "Domain Admins", "", privilege_all, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
465
466         sid_copy(&sid_users,  &global_sam_sid);
467         sid_append_rid(&sid_users,  DOMAIN_GROUP_RID_USERS);
468         sid_to_string(str_users, &sid_users);
469         add_initial_entry(-1, str_users,  SID_NAME_DOM_GRP, "Domain Users",  "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
470
471         sid_copy(&sid_guests, &global_sam_sid);
472         sid_append_rid(&sid_guests, DOMAIN_GROUP_RID_GUESTS);
473         sid_to_string(str_guests, &sid_guests);
474         add_initial_entry(-1, str_guests, SID_NAME_DOM_GRP, "Domain Guests", "", privilege_none, PR_ACCESS_FROM_NETWORK);
475
476         return True;
477 }
478
479
480 /****************************************************************************
481 return the sid and the type of the unix group
482 ****************************************************************************/
483 BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
484 {
485         TDB_DATA kbuf, dbuf;
486         pstring key;
487         fstring string_sid;
488         int ret;
489         int i;
490         PRIVILEGE_SET *set;
491         
492         /* the key is the SID, retrieving is direct */
493
494         sid_to_string(string_sid, &sid);
495         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
496
497         kbuf.dptr = key;
498         kbuf.dsize = strlen(key)+1;
499                 
500         dbuf = tdb_fetch(tdb, kbuf);
501         if (!dbuf.dptr) return False;
502
503         ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
504                                 &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount);
505
506         set=&map->priv_set;
507         init_privilege(set);
508         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
509
510         DEBUG(10,("get_group_map_from_sid: %d privileges\n", map->priv_set.count));
511         
512         set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
513         if (set->set==NULL) {
514                 DEBUG(0,("get_group_map_from_sid: could not allocate memory for privileges\n"));
515                 return False;
516         }
517
518         for (i=0; i<set->count; i++)
519                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
520                                 &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
521
522         SAFE_FREE(dbuf.dptr);
523         if (ret != dbuf.dsize) {
524                 DEBUG(0,("get_group_map_from_sid: group mapping TDB corrupted ?\n"));
525                 free_privilege(set);
526                 return False;
527         }
528
529         sid_copy(&map->sid, &sid);
530         
531         return True;
532 }
533
534
535 /****************************************************************************
536 return the sid and the type of the unix group
537 ****************************************************************************/
538 BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
539 {
540         TDB_DATA kbuf, dbuf, newkey;
541         fstring string_sid;
542         int ret;
543         int i;
544         PRIVILEGE_SET *set;
545
546         /* we need to enumerate the TDB to find the GID */
547
548         for (kbuf = tdb_firstkey(tdb); 
549              kbuf.dptr; 
550              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
551
552                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
553                 
554                 dbuf = tdb_fetch(tdb, kbuf);
555                 if (!dbuf.dptr) continue;
556
557                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
558
559                 string_to_sid(&map->sid, string_sid);
560                 
561                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
562                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount);
563
564                 set=&map->priv_set;
565                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
566         
567                 set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
568                 if (set->set==NULL) {
569                         DEBUG(0,("get_group_map_from_sid: could not allocate memory for privileges\n"));
570                         return False;
571                 }
572
573                 for (i=0; i<set->count; i++)
574                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
575                                         &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
576
577                 SAFE_FREE(dbuf.dptr);
578                 if (ret != dbuf.dsize){
579                         free_privilege(set);
580                         continue;
581                 }
582
583                 if (gid==map->gid)
584                         return True;
585
586                 free_privilege(set);
587         }
588
589         return False;
590 }
591
592 /****************************************************************************
593 return the sid and the type of the unix group
594 ****************************************************************************/
595 BOOL get_group_map_from_ntname(char *name, GROUP_MAP *map)
596 {
597         TDB_DATA kbuf, dbuf, newkey;
598         fstring string_sid;
599         int ret;
600         int i;
601         PRIVILEGE_SET *set;
602
603         /* we need to enumerate the TDB to find the name */
604
605         for (kbuf = tdb_firstkey(tdb); 
606              kbuf.dptr; 
607              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
608
609                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
610                 
611                 dbuf = tdb_fetch(tdb, kbuf);
612                 if (!dbuf.dptr) continue;
613
614                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
615
616                 string_to_sid(&map->sid, string_sid);
617                 
618                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
619                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount);
620
621                 set=&map->priv_set;
622                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
623         
624                 set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
625                 if (set->set==NULL) {
626                         DEBUG(0,("get_group_map_from_sid: could not allocate memory for privileges\n"));
627                         return False;
628                 }
629
630                 for (i=0; i<set->count; i++)
631                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
632                                         &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
633
634                 SAFE_FREE(dbuf.dptr);
635                 if (ret != dbuf.dsize) {
636                         free_privilege(set);
637                         continue;
638                 }
639
640                 if (StrCaseCmp(name, map->nt_name)==0)
641                         return True;
642
643                 free_privilege(set);
644         }
645
646         return False;
647 }
648
649 /****************************************************************************
650  remove a group mapping entry
651 ****************************************************************************/
652 BOOL group_map_remove(DOM_SID sid)
653 {
654         TDB_DATA kbuf, dbuf;
655         pstring key;
656         fstring string_sid;
657         
658         /* the key is the SID, retrieving is direct */
659
660         sid_to_string(string_sid, &sid);
661         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
662
663         kbuf.dptr = key;
664         kbuf.dsize = strlen(key)+1;
665                 
666         dbuf = tdb_fetch(tdb, kbuf);
667         if (!dbuf.dptr) return False;
668         
669         SAFE_FREE(dbuf.dptr);
670
671         if(tdb_delete(tdb, kbuf) != TDB_SUCCESS)
672                 return False;
673
674         return True;
675 }
676
677
678 /****************************************************************************
679 enumerate the group mapping
680 ****************************************************************************/
681 BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
682                         int *num_entries, BOOL unix_only)
683 {
684         TDB_DATA kbuf, dbuf, newkey;
685         fstring string_sid;
686         fstring group_type;
687         GROUP_MAP map;
688         GROUP_MAP *mapt;
689         int ret;
690         int entries=0;
691         int i;
692         PRIVILEGE_SET *set;
693
694         *num_entries=0;
695         *rmap=NULL;
696
697         for (kbuf = tdb_firstkey(tdb); 
698              kbuf.dptr; 
699              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
700
701                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0)
702                         continue;
703                 
704                 dbuf = tdb_fetch(tdb, kbuf);
705                 if (!dbuf.dptr)
706                         continue;
707
708                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
709                                 
710                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
711                                  &map.gid, &map.sid_name_use, &map.nt_name, &map.comment, &map.systemaccount);
712
713                 set=&map.priv_set;
714                 init_privilege(set);
715                 
716                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
717         
718                 if (set->count!=0) {
719                         set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
720                         if (set->set==NULL) {
721                                 DEBUG(0,("enum_group_mapping: could not allocate memory for privileges\n"));
722                                 return False;
723                         }
724                 }
725
726                 for (i=0; i<set->count; i++)
727                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
728                                         &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
729
730                 SAFE_FREE(dbuf.dptr);
731                 if (ret != dbuf.dsize) {
732                         free_privilege(set);
733                         continue;
734                 }
735
736                 /* list only the type or everything if UNKNOWN */
737                 if (sid_name_use!=SID_NAME_UNKNOWN  && sid_name_use!=map.sid_name_use) {
738                         free_privilege(set);
739                         continue;
740                 }
741                 
742                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
743                         free_privilege(set);
744                         continue;
745                 }
746
747                 string_to_sid(&map.sid, string_sid);
748                 
749                 decode_sid_name_use(group_type, map.sid_name_use);
750
751                 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
752                 if (!mapt) {
753                         DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
754                         SAFE_FREE(*rmap);
755                         free_privilege(set);
756                         return False;
757                 }
758                 else
759                         (*rmap) = mapt;
760
761                 mapt[entries].gid = map.gid;
762                 sid_copy( &mapt[entries].sid, &map.sid);
763                 mapt[entries].sid_name_use = map.sid_name_use;
764                 fstrcpy(mapt[entries].nt_name, map.nt_name);
765                 fstrcpy(mapt[entries].comment, map.comment);
766                 mapt[entries].systemaccount=map.systemaccount;
767                 mapt[entries].priv_set.count=set->count;
768                 mapt[entries].priv_set.control=set->control;
769                 mapt[entries].priv_set.set=set->set;
770
771                 entries++;
772         }
773
774         *num_entries=entries;
775         return True;
776 }
777
778
779 /****************************************************************************
780 convert a privilege string to a privilege array
781 ****************************************************************************/
782 void convert_priv_from_text(PRIVILEGE_SET *se_priv, char *privilege)
783 {
784         pstring tok;
785         char *p = privilege;
786         int i;
787         LUID_ATTR set;
788
789         /* By default no privilege */
790         init_privilege(se_priv);
791         
792         if (privilege==NULL)
793                 return;
794
795         while(next_token(&p, tok, " ", sizeof(tok)) ) {
796                 for (i=0; i<=PRIV_ALL_INDEX; i++) {
797                         if (StrCaseCmp(privs[i].priv, tok)==0) {
798                                 set.attr=0;
799                                 set.luid.high=0;
800                                 set.luid.low=privs[i].se_priv;
801                                 add_privilege(se_priv, set);
802                         }
803                 }               
804         }
805 }
806
807 /****************************************************************************
808 convert a privilege array to a privilege string
809 ****************************************************************************/
810 void convert_priv_to_text(PRIVILEGE_SET *se_priv, char *privilege)
811 {
812         int i,j;
813
814         if (privilege==NULL)
815                 return;
816
817         ZERO_STRUCTP(privilege);
818
819         if (check_empty_privilege(se_priv)) {
820                 fstrcat(privilege, "No privilege");
821                 return;
822         }
823
824         for(i=0; i<se_priv->count; i++) {
825                 j=1;
826                 while (privs[j].se_priv!=se_priv->set[i].luid.low && j<=PRIV_ALL_INDEX) {
827                         j++;
828                 }
829
830                 fstrcat(privilege, privs[j].priv);
831                 fstrcat(privilege, " ");
832         }
833 }
834
835
836 /*
837  *
838  * High level functions
839  * better to use them than the lower ones.
840  *
841  * we are checking if the group is in the mapping file
842  * and if the group is an existing unix group
843  *
844  */
845
846 /* get a domain group from it's SID */
847
848 BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
849 {
850         struct group *grp;
851
852         DEBUG(10, ("get_domain_group_from_sid\n"));
853
854         /* if the group is NOT in the database, it CAN NOT be a domain group */
855         if(!get_group_map_from_sid(sid, map))
856                 return False;
857
858         DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
859
860         /* if it's not a domain group, continue */
861         if (map->sid_name_use!=SID_NAME_DOM_GRP)
862                 return False;
863
864         DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n"));
865         
866         if (map->gid==-1)
867                 return False;
868
869         DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%d\n",map->gid));
870
871         if ( (grp=getgrgid(map->gid)) == NULL)
872                 return False;
873
874         DEBUG(10, ("get_domain_group_from_sid: gid exists in UNIX security\n"));
875
876         return True;
877 }
878
879
880 /* get a local (alias) group from it's SID */
881
882 BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map)
883 {
884         struct group *grp;
885
886         /* The group is in the mapping table */
887         if(get_group_map_from_sid(sid, map)) {
888                 if (map->sid_name_use!=SID_NAME_ALIAS)
889                         return False;
890         
891                 if (map->gid==-1)
892                         return False;
893
894                 if ( (grp=getgrgid(map->gid)) == NULL)
895                         return False;
896         } else {
897                 /* the group isn't in the mapping table.
898                  * make one based on the unix information */
899                 uint32 alias_rid;
900
901                 sid_peek_rid(&sid, &alias_rid);
902                 map->gid=pdb_user_rid_to_gid(alias_rid);
903
904                 if ((grp=getgrgid(map->gid)) == NULL)
905                         return False;
906
907                 map->sid_name_use=SID_NAME_ALIAS;
908                 map->systemaccount=PR_ACCESS_FROM_NETWORK;
909
910                 fstrcpy(map->nt_name, grp->gr_name);
911                 fstrcpy(map->comment, "Local Unix Group");
912
913                 init_privilege(&map->priv_set);
914
915                 sid_copy(&map->sid, &sid);
916         }
917
918         return True;
919 }
920
921 /* get a builtin group from it's SID */
922
923 BOOL get_builtin_group_from_sid(DOM_SID sid, GROUP_MAP *map)
924 {
925         struct group *grp;
926
927         if(!get_group_map_from_sid(sid, map))
928                 return False;
929
930         if (map->sid_name_use!=SID_NAME_WKN_GRP)
931                 return False;
932
933         if (map->gid==-1)
934                 return False;
935
936         if ( (grp=getgrgid(map->gid)) == NULL)
937                 return False;
938
939         return True;
940 }
941
942
943
944 /****************************************************************************
945 Returns a GROUP_MAP struct based on the gid.
946 ****************************************************************************/
947 BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
948 {
949         struct group *grp;
950
951         if ( (grp=getgrgid(gid)) == NULL)
952                 return False;
953
954         /*
955          * make a group map from scratch if doesn't exist.
956          */
957         if (!get_group_map_from_gid(gid, map)) {
958                 map->gid=gid;
959                 map->sid_name_use=SID_NAME_ALIAS;
960                 map->systemaccount=PR_ACCESS_FROM_NETWORK;
961                 init_privilege(&map->priv_set);
962
963                 sid_copy(&map->sid, &global_sam_sid);
964                 sid_append_rid(&map->sid, pdb_gid_to_group_rid(gid));
965
966                 fstrcpy(map->nt_name, grp->gr_name);
967                 fstrcpy(map->comment, "Local Unix Group");
968         }
969         
970         return True;
971 }
972
973
974
975
976 /****************************************************************************
977  Get the member users of a group and
978  all the users who have that group as primary.
979             
980  give back an array of uid
981  return the grand number of users
982
983
984  TODO: sort the list and remove duplicate. JFM.
985
986 ****************************************************************************/
987         
988 BOOL get_uid_list_of_group(gid_t gid, uid_t **uid, int *num_uids)
989 {
990         struct group *grp;
991         struct passwd *pwd;
992         int i=0;
993         char *gr;
994         uid_t *u;
995  
996         *num_uids = 0;
997         *uid=NULL;
998         
999         if ( (grp=getgrgid(gid)) == NULL)
1000                 return False;
1001
1002         gr = grp->gr_mem[0];
1003         DEBUG(10, ("getting members\n"));
1004         
1005         while (gr && (*gr != (char)'\0')) {
1006                 u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
1007                 if (!u) {
1008                         DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
1009                         return False;
1010                 }
1011                 else (*uid) = u;
1012
1013                 if( (pwd=getpwnam(gr)) !=NULL) {
1014                         (*uid)[*num_uids]=pwd->pw_uid;
1015                         (*num_uids)++;
1016                 }
1017                 gr = grp->gr_mem[++i];
1018         }
1019         DEBUG(10, ("got [%d] members\n", *num_uids));
1020
1021         setpwent();
1022         while ((pwd=getpwent()) != NULL) {
1023                 if (pwd->pw_gid==gid) {
1024                         u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
1025                         if (!u) {
1026                                 DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
1027                                 return False;
1028                         }
1029                         else (*uid) = u;
1030                         (*uid)[*num_uids]=pwd->pw_uid;
1031
1032                         (*num_uids)++;
1033                 }
1034         }
1035         endpwent();
1036         DEBUG(10, ("got primary groups, members: [%d]\n", *num_uids));
1037
1038         return True;
1039 }
1040
1041 /****************************************************************************
1042  Create a UNIX group on demand.
1043 ****************************************************************************/
1044
1045 int smb_create_group(char *unix_group)
1046 {
1047         pstring add_script;
1048         int ret;
1049
1050         pstrcpy(add_script, lp_addgroup_script());
1051         if (! *add_script) return -1;
1052         pstring_sub(add_script, "%g", unix_group);
1053         ret = smbrun(add_script,NULL);
1054         DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
1055         return ret;
1056 }
1057
1058 /****************************************************************************
1059  Delete a UNIX group on demand.
1060 ****************************************************************************/
1061
1062 int smb_delete_group(char *unix_group)
1063 {
1064         pstring del_script;
1065         int ret;
1066
1067         pstrcpy(del_script, lp_delgroup_script());
1068         if (! *del_script) return -1;
1069         pstring_sub(del_script, "%g", unix_group);
1070         ret = smbrun(del_script,NULL);
1071         DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
1072         return ret;
1073 }
1074
1075 /****************************************************************************
1076  Create a UNIX group on demand.
1077 ****************************************************************************/
1078
1079 int smb_add_user_group(char *unix_group, char *unix_user)
1080 {
1081         pstring add_script;
1082         int ret;
1083
1084         pstrcpy(add_script, lp_addusertogroup_script());
1085         if (! *add_script) return -1;
1086         pstring_sub(add_script, "%g", unix_group);
1087         pstring_sub(add_script, "%u", unix_user);
1088         ret = smbrun(add_script,NULL);
1089         DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
1090         return ret;
1091 }
1092
1093 /****************************************************************************
1094  Delete a UNIX group on demand.
1095 ****************************************************************************/
1096
1097 int smb_delete_user_group(char *unix_group, char *unix_user)
1098 {
1099         pstring del_script;
1100         int ret;
1101
1102         pstrcpy(del_script, lp_deluserfromgroup_script());
1103         if (! *del_script) return -1;
1104         pstring_sub(del_script, "%g", unix_group);
1105         pstring_sub(del_script, "%u", unix_user);
1106         ret = smbrun(del_script,NULL);
1107         DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
1108         return ret;
1109 }
1110
1111
1112