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