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