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