When re-writing tdb version numbers as little endian int32, we must
[ira/wip.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=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
535         if (set->set==NULL) {
536                 DEBUG(0,("get_group_map_from_sid: could not allocate memory for privileges\n"));
537                 return False;
538         }
539
540         for (i=0; i<set->count; i++)
541                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
542                                 &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
543
544         SAFE_FREE(dbuf.dptr);
545         if (ret != dbuf.dsize) {
546                 DEBUG(0,("get_group_map_from_sid: group mapping TDB corrupted ?\n"));
547                 free_privilege(set);
548                 return False;
549         }
550
551         /* we don't want the privileges */
552         if (with_priv==MAPPING_WITHOUT_PRIV)
553                 free_privilege(set);
554
555         sid_copy(&map->sid, &sid);
556         
557         return True;
558 }
559
560
561 /****************************************************************************
562 return the sid and the type of the unix group
563 ****************************************************************************/
564 BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map, BOOL with_priv)
565 {
566         TDB_DATA kbuf, dbuf, newkey;
567         fstring string_sid;
568         int ret;
569         int i;
570         PRIVILEGE_SET *set;
571
572         init_group_mapping();
573
574         /* we need to enumerate the TDB to find the GID */
575
576         for (kbuf = tdb_firstkey(tdb); 
577              kbuf.dptr; 
578              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
579
580                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
581                 
582                 dbuf = tdb_fetch(tdb, kbuf);
583                 if (!dbuf.dptr) continue;
584
585                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
586
587                 string_to_sid(&map->sid, string_sid);
588                 
589                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
590                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount);
591
592                 set=&map->priv_set;
593                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
594         
595                 set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
596                 if (set->set==NULL) {
597                         DEBUG(0,("get_group_map_from_gid: could not allocate memory for privileges\n"));
598                         return False;
599                 }
600
601                 for (i=0; i<set->count; i++)
602                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
603                                         &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
604
605                 SAFE_FREE(dbuf.dptr);
606                 if (ret != dbuf.dsize){
607                         free_privilege(set);
608                         continue;
609                 }
610
611                 if (gid==map->gid) {
612                         if (!with_priv)
613                                 free_privilege(&map->priv_set);
614                         return True;
615                 }
616                 
617                 free_privilege(set);
618         }
619
620         return False;
621 }
622
623 /****************************************************************************
624 return the sid and the type of the unix group
625 ****************************************************************************/
626 BOOL get_group_map_from_ntname(char *name, GROUP_MAP *map, BOOL with_priv)
627 {
628         TDB_DATA kbuf, dbuf, newkey;
629         fstring string_sid;
630         int ret;
631         int i;
632         PRIVILEGE_SET *set;
633
634         init_group_mapping();
635
636         /* we need to enumerate the TDB to find the name */
637
638         for (kbuf = tdb_firstkey(tdb); 
639              kbuf.dptr; 
640              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
641
642                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
643                 
644                 dbuf = tdb_fetch(tdb, kbuf);
645                 if (!dbuf.dptr) continue;
646
647                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
648
649                 string_to_sid(&map->sid, string_sid);
650                 
651                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
652                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount);
653
654                 set=&map->priv_set;
655                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
656         
657                 set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
658                 if (set->set==NULL) {
659                         DEBUG(0,("get_group_map_from_ntname: could not allocate memory for privileges\n"));
660                         return False;
661                 }
662
663                 for (i=0; i<set->count; i++)
664                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
665                                         &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
666
667                 SAFE_FREE(dbuf.dptr);
668                 if (ret != dbuf.dsize) {
669                         free_privilege(set);
670                         continue;
671                 }
672
673                 if (StrCaseCmp(name, map->nt_name)==0) {
674                         if (!with_priv)
675                                 free_privilege(&map->priv_set);
676                         return True;
677                 }
678
679                 free_privilege(set);
680         }
681
682         return False;
683 }
684
685 /****************************************************************************
686  remove a group mapping entry
687 ****************************************************************************/
688 BOOL group_map_remove(DOM_SID sid)
689 {
690         TDB_DATA kbuf, dbuf;
691         pstring key;
692         fstring string_sid;
693         
694         init_group_mapping();
695
696         /* the key is the SID, retrieving is direct */
697
698         sid_to_string(string_sid, &sid);
699         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
700
701         kbuf.dptr = key;
702         kbuf.dsize = strlen(key)+1;
703                 
704         dbuf = tdb_fetch(tdb, kbuf);
705         if (!dbuf.dptr) return False;
706         
707         SAFE_FREE(dbuf.dptr);
708
709         if(tdb_delete(tdb, kbuf) != TDB_SUCCESS)
710                 return False;
711
712         return True;
713 }
714
715
716 /****************************************************************************
717 enumerate the group mapping
718 ****************************************************************************/
719 BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
720                         int *num_entries, BOOL unix_only, BOOL with_priv)
721 {
722         TDB_DATA kbuf, dbuf, newkey;
723         fstring string_sid;
724         fstring group_type;
725         GROUP_MAP map;
726         GROUP_MAP *mapt;
727         int ret;
728         int entries=0;
729         int i;
730         PRIVILEGE_SET *set;
731
732         init_group_mapping();
733
734         *num_entries=0;
735         *rmap=NULL;
736
737         for (kbuf = tdb_firstkey(tdb); 
738              kbuf.dptr; 
739              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
740
741                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0)
742                         continue;
743                 
744                 dbuf = tdb_fetch(tdb, kbuf);
745                 if (!dbuf.dptr)
746                         continue;
747
748                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
749                                 
750                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
751                                  &map.gid, &map.sid_name_use, &map.nt_name, &map.comment, &map.systemaccount);
752
753                 set=&map.priv_set;
754                 init_privilege(set);
755                 
756                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
757         
758                 if (set->count!=0) {
759                         set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
760                         if (set->set==NULL) {
761                                 DEBUG(0,("enum_group_mapping: could not allocate memory for privileges\n"));
762                                 return False;
763                         }
764                 }
765
766                 for (i=0; i<set->count; i++)
767                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
768                                         &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
769
770                 SAFE_FREE(dbuf.dptr);
771                 if (ret != dbuf.dsize) {
772                         DEBUG(11,("enum_group_mapping: error in memory size\n"));
773                         free_privilege(set);
774                         continue;
775                 }
776
777                 /* list only the type or everything if UNKNOWN */
778                 if (sid_name_use!=SID_NAME_UNKNOWN  && sid_name_use!=map.sid_name_use) {
779                         DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
780                         free_privilege(set);
781                         continue;
782                 }
783                 
784                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
785                         DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
786                         free_privilege(set);
787                         continue;
788                 }
789
790                 string_to_sid(&map.sid, string_sid);
791                 
792                 decode_sid_name_use(group_type, map.sid_name_use);
793                 DEBUG(11,("enum_group_mapping: returning group %s of type %s\n", map.nt_name ,group_type));
794
795                 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
796                 if (!mapt) {
797                         DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
798                         SAFE_FREE(*rmap);
799                         free_privilege(set);
800                         return False;
801                 }
802                 else
803                         (*rmap) = mapt;
804
805                 mapt[entries].gid = map.gid;
806                 sid_copy( &mapt[entries].sid, &map.sid);
807                 mapt[entries].sid_name_use = map.sid_name_use;
808                 fstrcpy(mapt[entries].nt_name, map.nt_name);
809                 fstrcpy(mapt[entries].comment, map.comment);
810                 mapt[entries].systemaccount=map.systemaccount;
811                 mapt[entries].priv_set.count=set->count;
812                 mapt[entries].priv_set.control=set->control;
813                 mapt[entries].priv_set.set=set->set;
814                 if (!with_priv)
815                         free_privilege(&(mapt[entries].priv_set));
816
817                 entries++;
818         }
819
820         *num_entries=entries;
821         return True;
822 }
823
824
825 /****************************************************************************
826 convert a privilege string to a privilege array
827 ****************************************************************************/
828 void convert_priv_from_text(PRIVILEGE_SET *se_priv, char *privilege)
829 {
830         pstring tok;
831         char *p = privilege;
832         int i;
833         LUID_ATTR set;
834
835         /* By default no privilege */
836         init_privilege(se_priv);
837         
838         if (privilege==NULL)
839                 return;
840
841         while(next_token(&p, tok, " ", sizeof(tok)) ) {
842                 for (i=0; i<=PRIV_ALL_INDEX; i++) {
843                         if (StrCaseCmp(privs[i].priv, tok)==0) {
844                                 set.attr=0;
845                                 set.luid.high=0;
846                                 set.luid.low=privs[i].se_priv;
847                                 add_privilege(se_priv, set);
848                         }
849                 }               
850         }
851 }
852
853 /****************************************************************************
854 convert a privilege array to a privilege string
855 ****************************************************************************/
856 void convert_priv_to_text(PRIVILEGE_SET *se_priv, char *privilege)
857 {
858         int i,j;
859
860         if (privilege==NULL)
861                 return;
862
863         ZERO_STRUCTP(privilege);
864
865         if (check_empty_privilege(se_priv)) {
866                 fstrcat(privilege, "No privilege");
867                 return;
868         }
869
870         for(i=0; i<se_priv->count; i++) {
871                 j=1;
872                 while (privs[j].se_priv!=se_priv->set[i].luid.low && j<=PRIV_ALL_INDEX) {
873                         j++;
874                 }
875
876                 fstrcat(privilege, privs[j].priv);
877                 fstrcat(privilege, " ");
878         }
879 }
880
881
882 /*
883  *
884  * High level functions
885  * better to use them than the lower ones.
886  *
887  * we are checking if the group is in the mapping file
888  * and if the group is an existing unix group
889  *
890  */
891
892 /* get a domain group from it's SID */
893
894 BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv)
895 {
896         struct group *grp;
897
898         DEBUG(10, ("get_domain_group_from_sid\n"));
899
900         /* if the group is NOT in the database, it CAN NOT be a domain group */
901         if(!get_group_map_from_sid(sid, map, with_priv))
902                 return False;
903
904         DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
905
906         /* if it's not a domain group, continue */
907         if (map->sid_name_use!=SID_NAME_DOM_GRP) {
908                 if (with_priv)
909                         free_privilege(&map->priv_set);
910                 return False;
911         }
912
913         DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n"));
914         
915         if (map->gid==-1) {
916                 if (with_priv)
917                         free_privilege(&map->priv_set);
918                 return False;
919         }
920
921         DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%d\n",map->gid));
922
923         if ( (grp=getgrgid(map->gid)) == NULL) {
924                 DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n"));
925                 if (with_priv)
926                         free_privilege(&map->priv_set);
927                 return False;
928         }
929
930         DEBUG(10, ("get_domain_group_from_sid: gid exists in UNIX security\n"));
931
932         return True;
933 }
934
935
936 /* get a local (alias) group from it's SID */
937
938 BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv)
939 {
940         struct group *grp;
941
942         /* The group is in the mapping table */
943         if(get_group_map_from_sid(sid, map, with_priv)) {
944                 if (map->sid_name_use!=SID_NAME_ALIAS) {
945                         if (with_priv)
946                                 free_privilege(&map->priv_set);
947                         return False;
948                 }
949                 
950                 if (map->gid==-1) {
951                         if (with_priv)
952                                 free_privilege(&map->priv_set);
953                         return False;
954                 }
955
956                 if ( (grp=getgrgid(map->gid)) == NULL) {
957                         if (with_priv)
958                                 free_privilege(&map->priv_set);
959                         return False;
960                 }
961         } else {
962                 /* the group isn't in the mapping table.
963                  * make one based on the unix information */
964                 uint32 alias_rid;
965
966                 sid_peek_rid(&sid, &alias_rid);
967                 map->gid=pdb_group_rid_to_gid(alias_rid);
968
969                 if ((grp=getgrgid(map->gid)) == NULL)
970                         return False;
971
972                 map->sid_name_use=SID_NAME_ALIAS;
973                 map->systemaccount=PR_ACCESS_FROM_NETWORK;
974
975                 fstrcpy(map->nt_name, grp->gr_name);
976                 fstrcpy(map->comment, "Local Unix Group");
977
978                 init_privilege(&map->priv_set);
979
980                 sid_copy(&map->sid, &sid);
981         }
982
983         return True;
984 }
985
986 /* get a builtin group from it's SID */
987
988 BOOL get_builtin_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv)
989 {
990         struct group *grp;
991
992         if(!get_group_map_from_sid(sid, map, with_priv))
993                 return False;
994
995         if (map->sid_name_use!=SID_NAME_WKN_GRP) {
996                 if (with_priv)
997                         free_privilege(&map->priv_set);
998                 return False;
999         }
1000
1001         if (map->gid==-1) {
1002                 if (with_priv)
1003                         free_privilege(&map->priv_set);
1004                 return False;
1005         }
1006
1007         if ( (grp=getgrgid(map->gid)) == NULL) {
1008                 if (with_priv)
1009                         free_privilege(&map->priv_set);
1010                 return False;
1011         }
1012
1013         return True;
1014 }
1015
1016
1017
1018 /****************************************************************************
1019 Returns a GROUP_MAP struct based on the gid.
1020 ****************************************************************************/
1021 BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map, BOOL with_priv)
1022 {
1023         struct group *grp;
1024
1025         if ( (grp=getgrgid(gid)) == NULL)
1026                 return False;
1027
1028         /*
1029          * make a group map from scratch if doesn't exist.
1030          */
1031         if (!get_group_map_from_gid(gid, map, with_priv)) {
1032                 map->gid=gid;
1033                 map->sid_name_use=SID_NAME_ALIAS;
1034                 map->systemaccount=PR_ACCESS_FROM_NETWORK;
1035                 init_privilege(&map->priv_set);
1036
1037                 /* interim solution until we have a last RID allocated */
1038
1039                 sid_copy(&map->sid, &global_sam_sid);
1040                 sid_append_rid(&map->sid, pdb_gid_to_group_rid(gid));
1041
1042                 fstrcpy(map->nt_name, grp->gr_name);
1043                 fstrcpy(map->comment, "Local Unix Group");
1044         }
1045         
1046         return True;
1047 }
1048
1049
1050
1051
1052 /****************************************************************************
1053  Get the member users of a group and
1054  all the users who have that group as primary.
1055             
1056  give back an array of uid
1057  return the grand number of users
1058
1059
1060  TODO: sort the list and remove duplicate. JFM.
1061
1062 ****************************************************************************/
1063         
1064 BOOL get_uid_list_of_group(gid_t gid, uid_t **uid, int *num_uids)
1065 {
1066         struct group *grp;
1067         struct passwd *pwd;
1068         int i=0;
1069         char *gr;
1070         uid_t *u;
1071  
1072         *num_uids = 0;
1073         *uid=NULL;
1074         
1075         if ( (grp=getgrgid(gid)) == NULL)
1076                 return False;
1077
1078         gr = grp->gr_mem[0];
1079         DEBUG(10, ("getting members\n"));
1080         
1081         while (gr && (*gr != (char)'\0')) {
1082                 u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
1083                 if (!u) {
1084                         DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
1085                         return False;
1086                 }
1087                 else (*uid) = u;
1088
1089                 if( (pwd=getpwnam(gr)) !=NULL) {
1090                         (*uid)[*num_uids]=pwd->pw_uid;
1091                         (*num_uids)++;
1092                 }
1093                 gr = grp->gr_mem[++i];
1094         }
1095         DEBUG(10, ("got [%d] members\n", *num_uids));
1096
1097         setpwent();
1098         while ((pwd=getpwent()) != NULL) {
1099                 if (pwd->pw_gid==gid) {
1100                         u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
1101                         if (!u) {
1102                                 DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
1103                                 return False;
1104                         }
1105                         else (*uid) = u;
1106                         (*uid)[*num_uids]=pwd->pw_uid;
1107
1108                         (*num_uids)++;
1109                 }
1110         }
1111         endpwent();
1112         DEBUG(10, ("got primary groups, members: [%d]\n", *num_uids));
1113
1114         return True;
1115 }
1116
1117 /****************************************************************************
1118  Create a UNIX group on demand.
1119 ****************************************************************************/
1120
1121 int smb_create_group(char *unix_group)
1122 {
1123         pstring add_script;
1124         int ret;
1125
1126         pstrcpy(add_script, lp_addgroup_script());
1127         if (! *add_script) return -1;
1128         pstring_sub(add_script, "%g", unix_group);
1129         ret = smbrun(add_script,NULL);
1130         DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
1131         return ret;
1132 }
1133
1134 /****************************************************************************
1135  Delete a UNIX group on demand.
1136 ****************************************************************************/
1137
1138 int smb_delete_group(char *unix_group)
1139 {
1140         pstring del_script;
1141         int ret;
1142
1143         pstrcpy(del_script, lp_delgroup_script());
1144         if (! *del_script) return -1;
1145         pstring_sub(del_script, "%g", unix_group);
1146         ret = smbrun(del_script,NULL);
1147         DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
1148         return ret;
1149 }
1150
1151 /****************************************************************************
1152  Create a UNIX group on demand.
1153 ****************************************************************************/
1154
1155 int smb_add_user_group(char *unix_group, char *unix_user)
1156 {
1157         pstring add_script;
1158         int ret;
1159
1160         pstrcpy(add_script, lp_addusertogroup_script());
1161         if (! *add_script) return -1;
1162         pstring_sub(add_script, "%g", unix_group);
1163         pstring_sub(add_script, "%u", unix_user);
1164         ret = smbrun(add_script,NULL);
1165         DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
1166         return ret;
1167 }
1168
1169 /****************************************************************************
1170  Delete a UNIX group on demand.
1171 ****************************************************************************/
1172
1173 int smb_delete_user_group(const char *unix_group, const char *unix_user)
1174 {
1175         pstring del_script;
1176         int ret;
1177
1178         pstrcpy(del_script, lp_deluserfromgroup_script());
1179         if (! *del_script) return -1;
1180         pstring_sub(del_script, "%g", unix_group);
1181         pstring_sub(del_script, "%u", unix_user);
1182         ret = smbrun(del_script,NULL);
1183         DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
1184         return ret;
1185 }
1186
1187
1188