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