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