Changed again how the privilege list is handled in the group mapping code.
[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
265 /****************************************************************************
266 add a privilege to a privilege array
267 ****************************************************************************/
268 BOOL add_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
269 {
270         LUID_ATTR *new_set;
271
272         /* check if the privilege is not already in the list */
273         if (check_priv_in_privilege(priv_set, set))
274                 return False;
275
276         /* we can allocate memory to add the new privilege */
277
278         new_set=(LUID_ATTR *)Realloc(priv_set->set, (priv_set->count+1)*(sizeof(LUID_ATTR)));
279         if (new_set==NULL) {
280                 DEBUG(0,("add_privilege: could not Realloc memory to add a new privilege\n"));
281                 return False;
282         }
283
284         new_set[priv_set->count].luid.high=set.luid.high;
285         new_set[priv_set->count].luid.low=set.luid.low;
286         new_set[priv_set->count].attr=set.attr;
287         
288         priv_set->count++;
289         priv_set->set=new_set;
290         
291         return True;    
292 }
293
294 /****************************************************************************
295 add all the privileges to a privilege array
296 ****************************************************************************/
297 BOOL add_all_privilege(PRIVILEGE_SET *priv_set)
298 {
299         LUID_ATTR set;
300
301         set.attr=0;
302         set.luid.high=0;
303         
304         set.luid.low=SE_PRIV_ADD_USERS;
305         add_privilege(priv_set, set);
306
307         set.luid.low=SE_PRIV_ADD_MACHINES;
308         add_privilege(priv_set, set);
309
310         set.luid.low=SE_PRIV_PRINT_OPERATOR;
311         add_privilege(priv_set, set);
312         
313         return True;
314 }
315
316 /****************************************************************************
317 check if the privilege list is empty
318 ****************************************************************************/
319 BOOL check_empty_privilege(PRIVILEGE_SET *priv_set)
320 {
321
322         if (priv_set->count!=0)
323                 return False;
324
325         return True;
326 }
327
328 /****************************************************************************
329 check if the privilege is in the privilege list
330 ****************************************************************************/
331 BOOL check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
332 {
333         int i;
334
335         /* if the list is empty, obviously we can't have it */
336         if (check_empty_privilege(priv_set))
337                 return False;
338
339         for (i=0; i<priv_set->count; i++) {
340                 LUID_ATTR *cur_set;
341
342                 cur_set=&priv_set->set[i];
343                 /* check only the low and high part. Checking the attr field has no meaning */
344                 if( (cur_set->luid.low==set.luid.low) && (cur_set->luid.high==set.luid.high) )
345                         return True;
346         }
347
348         return False;
349 }
350
351 /****************************************************************************
352 remove a privilege to a privilege array
353 ****************************************************************************/
354 BOOL remove_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
355 {
356         LUID_ATTR *new_set;
357         LUID_ATTR *old_set;
358         int i,j;
359
360         /* check if the privilege is in the list */
361         if (!check_priv_in_privilege(priv_set, set))
362                 return False;
363
364         /* special case if it's the only privilege in the list */
365         if (priv_set->count==1) {
366                 free_privilege(priv_set);
367                 init_privilege(priv_set);       
368         
369                 return True;
370         }
371
372         /* 
373          * the privilege is there, create a new list,
374          * and copy the other privileges
375          */
376
377         old_set=priv_set->set;
378
379         new_set=(LUID_ATTR *)malloc((priv_set->count-1)*(sizeof(LUID_ATTR)));
380         if (new_set==NULL) {
381                 DEBUG(0,("remove_privilege: could not malloc memory for new privilege list\n"));
382                 return False;
383         }
384
385         for (i=0, j=0; i<priv_set->count; i++) {
386                 if ((old_set[i].luid.low==set.luid.low) && 
387                     (old_set[i].luid.high==set.luid.high)) {
388                         continue;
389                 }
390                 
391                 new_set[j].luid.low=old_set[i].luid.low;
392                 new_set[j].luid.high=old_set[i].luid.high;
393                 new_set[j].attr=old_set[i].attr;
394
395                 j++;
396         }
397         
398         if (j!=priv_set->count-1) {
399                 DEBUG(0,("remove_privilege: mismatch ! difference is not -1\n"));
400                 DEBUGADD(0,("old count:%d, new count:%d\n", priv_set->count, j));
401                 safe_free(new_set);
402                 return False;
403         }
404                 
405         /* ok everything is fine */
406         
407         priv_set->count--;
408         priv_set->set=new_set;
409         
410         safe_free(old_set);
411         
412         return True;    
413 }
414
415 /****************************************************************************
416 initialise first time the mapping list
417 ****************************************************************************/
418 BOOL default_group_mapping(void)
419 {
420         DOM_SID sid_admins;
421         DOM_SID sid_users;
422         DOM_SID sid_guests;
423         fstring str_admins;
424         fstring str_users;
425         fstring str_guests;
426         LUID_ATTR set;
427
428         PRIVILEGE_SET privilege_none;
429         PRIVILEGE_SET privilege_all;
430         PRIVILEGE_SET privilege_print_op;
431
432         init_privilege(&privilege_none);
433         init_privilege(&privilege_all);
434         init_privilege(&privilege_print_op);
435
436         set.attr=0;
437         set.luid.high=0;
438         set.luid.low=SE_PRIV_PRINT_OPERATOR;
439         add_privilege(&privilege_print_op, set);
440
441         add_all_privilege(&privilege_all);
442
443         /* Add the Wellknown groups */
444
445         add_initial_entry(-1, "S-1-5-32-544", SID_NAME_WKN_GRP, "Administrators", "", privilege_all, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
446         add_initial_entry(-1, "S-1-5-32-545", SID_NAME_WKN_GRP, "Users", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
447         add_initial_entry(-1, "S-1-5-32-546", SID_NAME_WKN_GRP, "Guests", "", privilege_none, PR_ACCESS_FROM_NETWORK);
448         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);
449
450         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);
451         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);
452         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);
453         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);
454
455         add_initial_entry(-1, "S-1-5-32-552", SID_NAME_WKN_GRP, "Replicators", "", privilege_none, PR_ACCESS_FROM_NETWORK);
456
457         /* Add the defaults domain groups */
458
459         sid_copy(&sid_admins, &global_sam_sid);
460         sid_append_rid(&sid_admins, DOMAIN_GROUP_RID_ADMINS);
461         sid_to_string(str_admins, &sid_admins);
462         add_initial_entry(-1, str_admins, SID_NAME_DOM_GRP, "Domain Admins", "", privilege_all, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
463
464         sid_copy(&sid_users,  &global_sam_sid);
465         sid_append_rid(&sid_users,  DOMAIN_GROUP_RID_USERS);
466         sid_to_string(str_users, &sid_users);
467         add_initial_entry(-1, str_users,  SID_NAME_DOM_GRP, "Domain Users",  "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
468
469         sid_copy(&sid_guests, &global_sam_sid);
470         sid_append_rid(&sid_guests, DOMAIN_GROUP_RID_GUESTS);
471         sid_to_string(str_guests, &sid_guests);
472         add_initial_entry(-1, str_guests, SID_NAME_DOM_GRP, "Domain Guests", "", privilege_none, PR_ACCESS_FROM_NETWORK);
473
474         return True;
475 }
476
477
478 /****************************************************************************
479 return the sid and the type of the unix group
480 ****************************************************************************/
481 BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
482 {
483         TDB_DATA kbuf, dbuf;
484         pstring key;
485         fstring string_sid;
486         int ret;
487         int i;
488         PRIVILEGE_SET *set;
489         
490         /* the key is the SID, retrieving is direct */
491
492         sid_to_string(string_sid, &sid);
493         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
494
495         kbuf.dptr = key;
496         kbuf.dsize = strlen(key)+1;
497                 
498         dbuf = tdb_fetch(tdb, kbuf);
499         if (!dbuf.dptr) return False;
500
501         ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
502                                 &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount);
503
504         set=&map->priv_set;
505         init_privilege(set);
506         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
507
508         DEBUG(10,("get_group_map_from_sid: %d privileges\n", map->priv_set.count));
509         
510         set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
511         if (set->set==NULL) {
512                 DEBUG(0,("get_group_map_from_sid: could not allocate memory for privileges\n"));
513                 return False;
514         }
515
516         for (i=0; i<set->count; i++)
517                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
518                                 &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
519
520         SAFE_FREE(dbuf.dptr);
521         if (ret != dbuf.dsize) {
522                 DEBUG(0,("get_group_map_from_sid: group mapping TDB corrupted ?\n"));
523                 free_privilege(set);
524                 return False;
525         }
526
527         sid_copy(&map->sid, &sid);
528         
529         return True;
530 }
531
532
533 /****************************************************************************
534 return the sid and the type of the unix group
535 ****************************************************************************/
536 BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
537 {
538         TDB_DATA kbuf, dbuf, newkey;
539         fstring string_sid;
540         int ret;
541         int i;
542         PRIVILEGE_SET *set;
543
544         /* we need to enumerate the TDB to find the GID */
545
546         for (kbuf = tdb_firstkey(tdb); 
547              kbuf.dptr; 
548              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
549
550                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
551                 
552                 dbuf = tdb_fetch(tdb, kbuf);
553                 if (!dbuf.dptr) continue;
554
555                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
556
557                 string_to_sid(&map->sid, string_sid);
558                 
559                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
560                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount);
561
562                 set=&map->priv_set;
563                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
564         
565                 set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
566                 if (set->set==NULL) {
567                         DEBUG(0,("get_group_map_from_sid: could not allocate memory for privileges\n"));
568                         return False;
569                 }
570
571                 for (i=0; i<set->count; i++)
572                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
573                                         &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
574
575                 SAFE_FREE(dbuf.dptr);
576                 if (ret != dbuf.dsize){
577                         free_privilege(set);
578                         continue;
579                 }
580
581                 if (gid==map->gid)
582                         return True;
583
584                 free_privilege(set);
585         }
586
587         return False;
588 }
589
590 /****************************************************************************
591 return the sid and the type of the unix group
592 ****************************************************************************/
593 BOOL get_group_map_from_ntname(char *name, GROUP_MAP *map)
594 {
595         TDB_DATA kbuf, dbuf, newkey;
596         fstring string_sid;
597         int ret;
598         int i;
599         PRIVILEGE_SET *set;
600
601         /* we need to enumerate the TDB to find the name */
602
603         for (kbuf = tdb_firstkey(tdb); 
604              kbuf.dptr; 
605              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
606
607                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
608                 
609                 dbuf = tdb_fetch(tdb, kbuf);
610                 if (!dbuf.dptr) continue;
611
612                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
613
614                 string_to_sid(&map->sid, string_sid);
615                 
616                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
617                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount);
618
619                 set=&map->priv_set;
620                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
621         
622                 set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
623                 if (set->set==NULL) {
624                         DEBUG(0,("get_group_map_from_sid: could not allocate memory for privileges\n"));
625                         return False;
626                 }
627
628                 for (i=0; i<set->count; i++)
629                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
630                                         &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
631
632                 SAFE_FREE(dbuf.dptr);
633                 if (ret != dbuf.dsize) {
634                         free_privilege(set);
635                         continue;
636                 }
637
638                 if (StrCaseCmp(name, map->nt_name)==0)
639                         return True;
640
641                 free_privilege(set);
642         }
643
644         return False;
645 }
646
647 /****************************************************************************
648  remove a group mapping entry
649 ****************************************************************************/
650 BOOL group_map_remove(DOM_SID sid)
651 {
652         TDB_DATA kbuf, dbuf;
653         pstring key;
654         fstring string_sid;
655         
656         /* the key is the SID, retrieving is direct */
657
658         sid_to_string(string_sid, &sid);
659         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
660
661         kbuf.dptr = key;
662         kbuf.dsize = strlen(key)+1;
663                 
664         dbuf = tdb_fetch(tdb, kbuf);
665         if (!dbuf.dptr) return False;
666         
667         SAFE_FREE(dbuf.dptr);
668
669         if(tdb_delete(tdb, kbuf) != TDB_SUCCESS)
670                 return False;
671
672         return True;
673 }
674
675
676 /****************************************************************************
677 enumerate the group mapping
678 ****************************************************************************/
679 BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
680                         int *num_entries, BOOL unix_only)
681 {
682         TDB_DATA kbuf, dbuf, newkey;
683         fstring string_sid;
684         fstring group_type;
685         GROUP_MAP map;
686         GROUP_MAP *mapt;
687         int ret;
688         int entries=0;
689         int i;
690         PRIVILEGE_SET *set;
691
692         *num_entries=0;
693         *rmap=NULL;
694
695         for (kbuf = tdb_firstkey(tdb); 
696              kbuf.dptr; 
697              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
698
699                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0)
700                         continue;
701                 
702                 dbuf = tdb_fetch(tdb, kbuf);
703                 if (!dbuf.dptr)
704                         continue;
705
706                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
707                                 
708                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
709                                  &map.gid, &map.sid_name_use, &map.nt_name, &map.comment, &map.systemaccount);
710
711                 set=&map.priv_set;
712                 init_privilege(set);
713                 
714                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
715         
716                 if (set->count!=0) {
717                         set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
718                         if (set->set==NULL) {
719                                 DEBUG(0,("enum_group_mapping: could not allocate memory for privileges\n"));
720                                 return False;
721                         }
722                 }
723
724                 for (i=0; i<set->count; i++)
725                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
726                                         &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
727
728                 SAFE_FREE(dbuf.dptr);
729                 if (ret != dbuf.dsize) {
730                         free_privilege(set);
731                         continue;
732                 }
733
734                 /* list only the type or everything if UNKNOWN */
735                 if (sid_name_use!=SID_NAME_UNKNOWN  && sid_name_use!=map.sid_name_use) {
736                         free_privilege(set);
737                         continue;
738                 }
739                 
740                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
741                         free_privilege(set);
742                         continue;
743                 }
744
745                 string_to_sid(&map.sid, string_sid);
746                 
747                 decode_sid_name_use(group_type, map.sid_name_use);
748
749                 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
750                 if (!mapt) {
751                         DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
752                         SAFE_FREE(*rmap);
753                         free_privilege(set);
754                         return False;
755                 }
756                 else
757                         (*rmap) = mapt;
758
759                 mapt[entries].gid = map.gid;
760                 sid_copy( &mapt[entries].sid, &map.sid);
761                 mapt[entries].sid_name_use = map.sid_name_use;
762                 fstrcpy(mapt[entries].nt_name, map.nt_name);
763                 fstrcpy(mapt[entries].comment, map.comment);
764                 mapt[entries].systemaccount=map.systemaccount;
765                 mapt[entries].priv_set.count=set->count;
766                 mapt[entries].priv_set.control=set->control;
767                 mapt[entries].priv_set.set=set->set;
768
769                 entries++;
770         }
771
772         *num_entries=entries;
773         return True;
774 }
775
776
777 /****************************************************************************
778 convert a privilege string to a privilege array
779 ****************************************************************************/
780 void convert_priv_from_text(PRIVILEGE_SET *se_priv, char *privilege)
781 {
782         pstring tok;
783         char *p = privilege;
784         int i;
785         LUID_ATTR set;
786
787         /* By default no privilege */
788         init_privilege(se_priv);
789         
790         if (privilege==NULL)
791                 return;
792
793         while(next_token(&p, tok, " ", sizeof(tok)) ) {
794                 for (i=0; i<=PRIV_ALL_INDEX; i++) {
795                         if (StrCaseCmp(privs[i].priv, tok)==0) {
796                                 set.attr=0;
797                                 set.luid.high=0;
798                                 set.luid.low=privs[i].se_priv;
799                                 add_privilege(se_priv, set);
800                         }
801                 }               
802         }
803 }
804
805 /****************************************************************************
806 convert a privilege array to a privilege string
807 ****************************************************************************/
808 void convert_priv_to_text(PRIVILEGE_SET *se_priv, char *privilege)
809 {
810         int i,j;
811
812         if (privilege==NULL)
813                 return;
814
815         ZERO_STRUCTP(privilege);
816
817         if (check_empty_privilege(se_priv)) {
818                 fstrcat(privilege, "No privilege");
819                 return;
820         }
821
822         for(i=0; i<se_priv->count; i++) {
823                 j=1;
824                 while (privs[j].se_priv!=se_priv->set[i].luid.low && j<=PRIV_ALL_INDEX) {
825                         j++;
826                 }
827
828                 fstrcat(privilege, privs[j].priv);
829                 fstrcat(privilege, " ");
830         }
831 }
832
833
834 /*
835  *
836  * High level functions
837  * better to use them than the lower ones.
838  *
839  * we are checking if the group is in the mapping file
840  * and if the group is an existing unix group
841  *
842  */
843
844 /* get a domain group from it's SID */
845
846 BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
847 {
848         struct group *grp;
849
850         DEBUG(10, ("get_domain_group_from_sid\n"));
851
852         /* if the group is NOT in the database, it CAN NOT be a domain group */
853         if(!get_group_map_from_sid(sid, map))
854                 return False;
855
856         DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
857
858         /* if it's not a domain group, continue */
859         if (map->sid_name_use!=SID_NAME_DOM_GRP)
860                 return False;
861
862         DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n"));
863         
864         if (map->gid==-1)
865                 return False;
866
867         DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%d\n",map->gid));
868
869         if ( (grp=getgrgid(map->gid)) == NULL)
870                 return False;
871
872         DEBUG(10, ("get_domain_group_from_sid: gid exists in UNIX security\n"));
873
874         return True;
875 }
876
877
878 /* get a local (alias) group from it's SID */
879
880 BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map)
881 {
882         struct group *grp;
883
884         /* The group is in the mapping table */
885         if(get_group_map_from_sid(sid, map)) {
886                 if (map->sid_name_use!=SID_NAME_ALIAS)
887                         return False;
888         
889                 if (map->gid==-1)
890                         return False;
891
892                 if ( (grp=getgrgid(map->gid)) == NULL)
893                         return False;
894         } else {
895                 /* the group isn't in the mapping table.
896                  * make one based on the unix information */
897                 uint32 alias_rid;
898
899                 sid_peek_rid(&sid, &alias_rid);
900                 map->gid=pdb_user_rid_to_gid(alias_rid);
901
902                 if ((grp=getgrgid(map->gid)) == NULL)
903                         return False;
904
905                 map->sid_name_use=SID_NAME_ALIAS;
906                 map->systemaccount=PR_ACCESS_FROM_NETWORK;
907
908                 fstrcpy(map->nt_name, grp->gr_name);
909                 fstrcpy(map->comment, "Local Unix Group");
910
911                 init_privilege(&map->priv_set);
912
913                 sid_copy(&map->sid, &sid);
914         }
915
916         return True;
917 }
918
919 /* get a builtin group from it's SID */
920
921 BOOL get_builtin_group_from_sid(DOM_SID sid, GROUP_MAP *map)
922 {
923         struct group *grp;
924
925         if(!get_group_map_from_sid(sid, map))
926                 return False;
927
928         if (map->sid_name_use!=SID_NAME_WKN_GRP)
929                 return False;
930
931         if (map->gid==-1)
932                 return False;
933
934         if ( (grp=getgrgid(map->gid)) == NULL)
935                 return False;
936
937         return True;
938 }
939
940
941
942 /****************************************************************************
943 Returns a GROUP_MAP struct based on the gid.
944 ****************************************************************************/
945 BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
946 {
947         struct group *grp;
948
949         if ( (grp=getgrgid(gid)) == NULL)
950                 return False;
951
952         /*
953          * make a group map from scratch if doesn't exist.
954          */
955         if (!get_group_map_from_gid(gid, map)) {
956                 map->gid=gid;
957                 map->sid_name_use=SID_NAME_ALIAS;
958                 map->systemaccount=PR_ACCESS_FROM_NETWORK;
959                 init_privilege(&map->priv_set);
960
961                 sid_copy(&map->sid, &global_sam_sid);
962                 sid_append_rid(&map->sid, pdb_gid_to_group_rid(gid));
963
964                 fstrcpy(map->nt_name, grp->gr_name);
965                 fstrcpy(map->comment, "Local Unix Group");
966         }
967         
968         return True;
969 }
970
971
972
973
974 /****************************************************************************
975  Get the member users of a group and
976  all the users who have that group as primary.
977             
978  give back an array of uid
979  return the grand number of users
980
981
982  TODO: sort the list and remove duplicate. JFM.
983
984 ****************************************************************************/
985         
986 BOOL get_uid_list_of_group(gid_t gid, uid_t **uid, int *num_uids)
987 {
988         struct group *grp;
989         struct passwd *pwd;
990         int i=0;
991         char *gr;
992         uid_t *u;
993  
994         *num_uids = 0;
995         *uid=NULL;
996         
997         if ( (grp=getgrgid(gid)) == NULL)
998                 return False;
999
1000         gr = grp->gr_mem[0];
1001         DEBUG(10, ("getting members\n"));
1002         
1003         while (gr && (*gr != (char)'\0')) {
1004                 u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
1005                 if (!u) {
1006                         DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
1007                         return False;
1008                 }
1009                 else (*uid) = u;
1010
1011                 if( (pwd=getpwnam(gr)) !=NULL) {
1012                         (*uid)[*num_uids]=pwd->pw_uid;
1013                         (*num_uids)++;
1014                 }
1015                 gr = grp->gr_mem[++i];
1016         }
1017         DEBUG(10, ("got [%d] members\n", *num_uids));
1018
1019         setpwent();
1020         while ((pwd=getpwent()) != NULL) {
1021                 if (pwd->pw_gid==gid) {
1022                         u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
1023                         if (!u) {
1024                                 DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
1025                                 return False;
1026                         }
1027                         else (*uid) = u;
1028                         (*uid)[*num_uids]=pwd->pw_uid;
1029
1030                         (*num_uids)++;
1031                 }
1032         }
1033         endpwent();
1034         DEBUG(10, ("got primary groups, members: [%d]\n", *num_uids));
1035
1036         return True;
1037 }
1038
1039 /****************************************************************************
1040  Create a UNIX group on demand.
1041 ****************************************************************************/
1042
1043 int smb_create_group(char *unix_group)
1044 {
1045         pstring add_script;
1046         int ret;
1047
1048         pstrcpy(add_script, lp_addgroup_script());
1049         if (! *add_script) return -1;
1050         pstring_sub(add_script, "%g", unix_group);
1051         ret = smbrun(add_script,NULL);
1052         DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
1053         return ret;
1054 }
1055
1056 /****************************************************************************
1057  Delete a UNIX group on demand.
1058 ****************************************************************************/
1059
1060 int smb_delete_group(char *unix_group)
1061 {
1062         pstring del_script;
1063         int ret;
1064
1065         pstrcpy(del_script, lp_delgroup_script());
1066         if (! *del_script) return -1;
1067         pstring_sub(del_script, "%g", unix_group);
1068         ret = smbrun(del_script,NULL);
1069         DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
1070         return ret;
1071 }
1072
1073 /****************************************************************************
1074  Create a UNIX group on demand.
1075 ****************************************************************************/
1076
1077 int smb_add_user_group(char *unix_group, char *unix_user)
1078 {
1079         pstring add_script;
1080         int ret;
1081
1082         pstrcpy(add_script, lp_addusertogroup_script());
1083         if (! *add_script) return -1;
1084         pstring_sub(add_script, "%g", unix_group);
1085         pstring_sub(add_script, "%u", unix_user);
1086         ret = smbrun(add_script,NULL);
1087         DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
1088         return ret;
1089 }
1090
1091 /****************************************************************************
1092  Delete a UNIX group on demand.
1093 ****************************************************************************/
1094
1095 int smb_delete_user_group(char *unix_group, char *unix_user)
1096 {
1097         pstring del_script;
1098         int ret;
1099
1100         pstrcpy(del_script, lp_deluserfromgroup_script());
1101         if (! *del_script) return -1;
1102         pstring_sub(del_script, "%g", unix_group);
1103         pstring_sub(del_script, "%u", unix_user);
1104         ret = smbrun(del_script,NULL);
1105         DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
1106         return ret;
1107 }
1108
1109
1110