Changed how the privileges are stored in the group mapping code. It's now
[kai/samba.git] / source3 / groupdb / mapping.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2001.
7  *  
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *  
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *  
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "includes.h"
24
25 extern DOM_SID global_sam_sid;
26
27 static TDB_CONTEXT *tdb; /* used for driver files */
28
29 #define DATABASE_VERSION 1
30 #define GROUP_PREFIX "UNIXGROUP/"
31
32 PRIVS privs[] = {
33         {SE_PRIV_NONE,           "no_privs",                  "No privilege"                    }, /* this one MUST be first */
34         {SE_PRIV_ADD_MACHINES,   "SeMachineAccountPrivilege", "Add workstations to the domain"  },
35         {SE_PRIV_SEC_PRIV,       "SeSecurityPrivilege",       "Manage the audit logs"           },
36         {SE_PRIV_TAKE_OWNER,     "SeTakeOwnershipPrivilege",  "Take ownership of file"          },
37         {SE_PRIV_ADD_USERS,      "SaAddUsers",                "Add users to the domain - Samba" },
38         {SE_PRIV_PRINT_OPERATOR, "SaPrintOp",                 "Add or remove printers - Samba"  },
39         {SE_PRIV_ALL,            "SaAllPrivs",                "all privileges"                  }
40 };
41 /*
42 PRIVS privs[] = {
43         {  2, "SeCreateTokenPrivilege" },
44         {  3, "SeAssignPrimaryTokenPrivilege" },
45         {  4, "SeLockMemoryPrivilege" },
46         {  5, "SeIncreaseQuotaPrivilege" },
47         {  6, "SeMachineAccountPrivilege" },
48         {  7, "SeTcbPrivilege" },
49         {  8, "SeSecurityPrivilege" },
50         {  9, "SeTakeOwnershipPrivilege" },
51         { 10, "SeLoadDriverPrivilege" },
52         { 11, "SeSystemProfilePrivilege" },
53         { 12, "SeSystemtimePrivilege" },
54         { 13, "SeProfileSingleProcessPrivilege" },
55         { 14, "SeIncreaseBasePriorityPrivilege" },
56         { 15, "SeCreatePagefilePrivilege" },
57         { 16, "SeCreatePermanentPrivilege" },
58         { 17, "SeBackupPrivilege" },
59         { 18, "SeRestorePrivilege" },
60         { 19, "SeShutdownPrivilege" },
61         { 20, "SeDebugPrivilege" },
62         { 21, "SeAuditPrivilege" },
63         { 22, "SeSystemEnvironmentPrivilege" },
64         { 23, "SeChangeNotifyPrivilege" },
65         { 24, "SeRemoteShutdownPrivilege" },
66         { 25, "SeUndockPrivilege" },
67         { 26, "SeSyncAgentPrivilege" },
68         { 27, "SeEnableDelegationPrivilege" },
69 };
70 */
71
72 #if 0
73 /****************************************************************************
74 check if the user has the required privilege.
75 ****************************************************************************/
76 static BOOL se_priv_access_check(NT_USER_TOKEN *token, uint32 privilege)
77 {
78         /* no token, no privilege */
79         if (token==NULL)
80                 return False;
81         
82         if ((token->privilege & privilege)==privilege)
83                 return True;
84         
85         return False;
86 }
87 #endif
88
89 /****************************************************************************
90 dump the mapping group mapping to a text file
91 ****************************************************************************/
92 char *decode_sid_name_use(fstring group, enum SID_NAME_USE name_use)
93 {       
94         static fstring group_type;
95
96         switch(name_use) {
97                 case SID_NAME_USER:
98                         fstrcpy(group_type,"User");
99                         break;
100                 case SID_NAME_DOM_GRP:
101                         fstrcpy(group_type,"Domain group");
102                         break;
103                 case SID_NAME_DOMAIN:
104                         fstrcpy(group_type,"Domain");
105                         break;
106                 case SID_NAME_ALIAS:
107                         fstrcpy(group_type,"Local group");
108                         break;
109                 case SID_NAME_WKN_GRP:
110                         fstrcpy(group_type,"Builtin group");
111                         break;
112                 case SID_NAME_DELETED:
113                         fstrcpy(group_type,"Deleted");
114                         break;
115                 case SID_NAME_INVALID:
116                         fstrcpy(group_type,"Invalid");
117                         break;
118                 case SID_NAME_UNKNOWN:
119                 default:
120                         fstrcpy(group_type,"Unknown type");
121                         break;
122         }
123         
124         fstrcpy(group, group_type);
125         return group_type;
126 }
127
128 /****************************************************************************
129 open the group mapping tdb
130 ****************************************************************************/
131 BOOL init_group_mapping(void)
132 {
133         static pid_t local_pid;
134         char *vstring = "INFO/version";
135
136         if (tdb && local_pid == sys_getpid()) return True;
137         tdb = tdb_open_log(lock_path("group_mapping.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
138         if (!tdb) {
139                 DEBUG(0,("Failed to open group mapping database\n"));
140                 return False;
141         }
142
143         local_pid = sys_getpid();
144
145         /* handle a Samba upgrade */
146         tdb_lock_bystring(tdb, vstring);
147         if (tdb_fetch_int(tdb, vstring) != DATABASE_VERSION) {
148                 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
149                 tdb_store_int(tdb, vstring, DATABASE_VERSION);
150         }
151         tdb_unlock_bystring(tdb, vstring);
152
153
154         return True;
155 }
156
157 /****************************************************************************
158 ****************************************************************************/
159 BOOL add_mapping_entry(GROUP_MAP *map, int flag)
160 {
161         TDB_DATA kbuf, dbuf;
162         pstring key, buf;
163         fstring string_sid="";
164         int len;
165         int i;
166         
167         sid_to_string(string_sid, &map->sid);
168
169         len = tdb_pack(buf, sizeof(buf), "ddff",
170                         map->gid, map->sid_name_use, map->nt_name, map->comment);
171
172         for (i=0; i<PRIV_ALL_INDEX; i++)
173                 len += tdb_pack(buf+len, sizeof(buf)-len, "d", map->privileges[i]);
174
175         if (len > sizeof(buf)) return False;
176
177         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
178
179         kbuf.dsize = strlen(key)+1;
180         kbuf.dptr = key;
181         dbuf.dsize = len;
182         dbuf.dptr = buf;
183         if (tdb_store(tdb, kbuf, dbuf, flag) != 0) return False;
184
185         return True;
186 }
187
188 /****************************************************************************
189 initialise first time the mapping list
190 ****************************************************************************/
191 BOOL add_initial_entry(gid_t gid, fstring sid, enum SID_NAME_USE sid_name_use,
192                               fstring nt_name, fstring comment, uint32 *privilege)
193 {
194         GROUP_MAP map;
195         int i;
196
197         map.gid=gid;
198         string_to_sid(&map.sid, sid);
199         map.sid_name_use=sid_name_use;
200         fstrcpy(map.nt_name, nt_name);
201         fstrcpy(map.comment, comment);
202         for (i=0; i<PRIV_ALL_INDEX; i++)
203                 map.privileges[i]=privilege[i];
204
205         add_mapping_entry(&map, TDB_INSERT);
206
207         return True;
208 }
209
210 /****************************************************************************
211 initialise a privilege list
212 ****************************************************************************/
213 void init_privilege(uint32 *privilege)
214 {
215         int i;
216
217         for (i=0; i<PRIV_ALL_INDEX; i++)
218                 privilege[i]=0;
219 }
220
221 /****************************************************************************
222 add a privilege to a privilege array
223 ****************************************************************************/
224 BOOL add_privilege(uint32 *privilege, uint32 priv)
225 {
226         int i;
227
228         while (i<PRIV_ALL_INDEX && privilege[i]!=0 && privilege[i]!=priv)
229                 i++;
230
231         if (i==PRIV_ALL_INDEX) {
232                 DEBUG(10,("add_privilege: the privilege array is full, can't add new priv\n"));
233                 return False;
234         }
235
236         if (privilege[i]==priv) {
237                 DEBUG(10,("add_privilege: privilege already in array\n"));
238                 return False;
239         }
240
241         if (privilege[i]==0)
242                 privilege[i]=priv;
243         
244         return True;    
245 }
246
247 /****************************************************************************
248 add all the privileges to a privilege array
249 ****************************************************************************/
250 BOOL add_all_privilege(uint32 *privilege)
251 {
252         add_privilege(privilege, SE_PRIV_ADD_USERS);
253         add_privilege(privilege, SE_PRIV_ADD_MACHINES);
254         add_privilege(privilege, SE_PRIV_PRINT_OPERATOR);
255 }
256
257 /****************************************************************************
258 check if the privilege list is empty
259 ****************************************************************************/
260 BOOL check_empty_privilege(uint32 *privilege)
261 {
262         int i;
263
264         for (i=0; i<PRIV_ALL_INDEX; i++)
265                 if(privilege[i]!=0)
266                         return False;
267         return True;
268 }
269
270 /****************************************************************************
271 check if the privilege is in the privilege list
272 ****************************************************************************/
273 BOOL check_priv_in_privilege(uint32 *privilege, uint32 priv)
274 {
275         int i;
276
277         for (i=0; i<PRIV_ALL_INDEX; i++)
278                 if(privilege[i]==priv)
279                         return True;
280         return False;
281 }
282
283 /****************************************************************************
284 initialise first time the mapping list
285 ****************************************************************************/
286 BOOL default_group_mapping(void)
287 {
288         DOM_SID sid_admins;
289         DOM_SID sid_users;
290         DOM_SID sid_guests;
291         fstring str_admins;
292         fstring str_users;
293         fstring str_guests;
294         int i;
295
296         uint32 privilege_none[PRIV_ALL_INDEX];
297         uint32 privilege_all[PRIV_ALL_INDEX];
298         uint32 privilege_print_op[PRIV_ALL_INDEX];
299
300         init_privilege(privilege_none);
301         init_privilege(privilege_all);
302         init_privilege(privilege_print_op);
303
304         add_privilege(privilege_print_op, SE_PRIV_PRINT_OPERATOR);
305
306         add_all_privilege(privilege_all);
307
308         /* Add the Wellknown groups */
309
310         add_initial_entry(-1, "S-1-5-32-544", SID_NAME_WKN_GRP, "Administrators", "", privilege_all);
311         add_initial_entry(-1, "S-1-5-32-545", SID_NAME_WKN_GRP, "Users", "", privilege_none);
312         add_initial_entry(-1, "S-1-5-32-546", SID_NAME_WKN_GRP, "Guests", "", privilege_none);
313         add_initial_entry(-1, "S-1-5-32-547", SID_NAME_WKN_GRP, "Power Users", "", privilege_none);
314
315         add_initial_entry(-1, "S-1-5-32-548", SID_NAME_WKN_GRP, "Account Operators", "", privilege_none);
316         add_initial_entry(-1, "S-1-5-32-549", SID_NAME_WKN_GRP, "System Operators", "", privilege_none);
317         add_initial_entry(-1, "S-1-5-32-550", SID_NAME_WKN_GRP, "Print Operators", "", privilege_print_op);
318         add_initial_entry(-1, "S-1-5-32-551", SID_NAME_WKN_GRP, "Backup Operators", "", privilege_none);
319
320         add_initial_entry(-1, "S-1-5-32-552", SID_NAME_WKN_GRP, "Replicators", "", privilege_none);
321
322         /* Add the defaults domain groups */
323
324         sid_copy(&sid_admins, &global_sam_sid);
325         sid_append_rid(&sid_admins, DOMAIN_GROUP_RID_ADMINS);
326         sid_to_string(str_admins, &sid_admins);
327         add_initial_entry(-1, str_admins, SID_NAME_DOM_GRP, "Domain Admins", "", privilege_all);
328
329         sid_copy(&sid_users,  &global_sam_sid);
330         sid_append_rid(&sid_users,  DOMAIN_GROUP_RID_USERS);
331         sid_to_string(str_users, &sid_users);
332         add_initial_entry(-1, str_users,  SID_NAME_DOM_GRP, "Domain Users",  "", privilege_none);
333
334         sid_copy(&sid_guests, &global_sam_sid);
335         sid_append_rid(&sid_guests, DOMAIN_GROUP_RID_GUESTS);
336         sid_to_string(str_guests, &sid_guests);
337         add_initial_entry(-1, str_guests, SID_NAME_DOM_GRP, "Domain Guests", "", privilege_none);
338
339         return True;
340 }
341
342
343 /****************************************************************************
344 return the sid and the type of the unix group
345 ****************************************************************************/
346 BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
347 {
348         TDB_DATA kbuf, dbuf;
349         pstring key;
350         fstring string_sid;
351         int ret;
352         int i;
353         
354         /* the key is the SID, retrieving is direct */
355
356         sid_to_string(string_sid, &sid);
357         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
358
359         kbuf.dptr = key;
360         kbuf.dsize = strlen(key)+1;
361                 
362         dbuf = tdb_fetch(tdb, kbuf);
363         if (!dbuf.dptr) return False;
364
365         ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
366                                 &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
367
368         for (i=0; i<PRIV_ALL_INDEX; i++)
369                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &map->privileges[i]);
370
371         SAFE_FREE(dbuf.dptr);
372         if (ret != dbuf.dsize) {
373                 DEBUG(0,("get_group_map_from_sid: group mapping TDB corrupted ?\n"));
374                 return False;
375         }
376
377         sid_copy(&map->sid, &sid);
378         
379         return True;
380 }
381
382
383 /****************************************************************************
384 return the sid and the type of the unix group
385 ****************************************************************************/
386 BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
387 {
388         TDB_DATA kbuf, dbuf, newkey;
389         fstring string_sid;
390         int ret;
391         int i;
392
393         /* we need to enumerate the TDB to find the GID */
394
395         for (kbuf = tdb_firstkey(tdb); 
396              kbuf.dptr; 
397              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
398
399                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
400                 
401                 dbuf = tdb_fetch(tdb, kbuf);
402                 if (!dbuf.dptr) continue;
403
404                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
405
406                 string_to_sid(&map->sid, string_sid);
407                 
408                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
409                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
410
411                 for (i=0; i<PRIV_ALL_INDEX; i++)
412                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &map->privileges[i]);
413
414                 SAFE_FREE(dbuf.dptr);
415                 if (ret != dbuf.dsize) continue;
416
417                 if (gid==map->gid)
418                         return True;
419         }
420
421         return False;
422 }
423
424 /****************************************************************************
425 return the sid and the type of the unix group
426 ****************************************************************************/
427 BOOL get_group_map_from_ntname(char *name, GROUP_MAP *map)
428 {
429         TDB_DATA kbuf, dbuf, newkey;
430         fstring string_sid;
431         int ret;
432         int i;
433
434         /* we need to enumerate the TDB to find the SID */
435
436         for (kbuf = tdb_firstkey(tdb); 
437              kbuf.dptr; 
438              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
439
440                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
441                 
442                 dbuf = tdb_fetch(tdb, kbuf);
443                 if (!dbuf.dptr) continue;
444
445                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
446
447                 string_to_sid(&map->sid, string_sid);
448                 
449                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
450                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
451
452                 for (i=0; i<PRIV_ALL_INDEX; i++)
453                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &map->privileges[i]);
454
455                 SAFE_FREE(dbuf.dptr);
456                 if (ret != dbuf.dsize) continue;
457
458                 if (StrCaseCmp(name, map->nt_name)==0)
459                         return True;
460
461         }
462
463         return False;
464 }
465
466 /****************************************************************************
467 enumerate the group mapping
468 ****************************************************************************/
469 BOOL group_map_remove(DOM_SID sid)
470 {
471         TDB_DATA kbuf, dbuf;
472         pstring key;
473         fstring string_sid;
474         
475         /* the key is the SID, retrieving is direct */
476
477         sid_to_string(string_sid, &sid);
478         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
479
480         kbuf.dptr = key;
481         kbuf.dsize = strlen(key)+1;
482                 
483         dbuf = tdb_fetch(tdb, kbuf);
484         if (!dbuf.dptr) return False;
485         
486         SAFE_FREE(dbuf.dptr);
487
488         if(tdb_delete(tdb, kbuf) != TDB_SUCCESS)
489                 return False;
490
491         return True;
492 }
493
494
495 /****************************************************************************
496 enumerate the group mapping
497 ****************************************************************************/
498 BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
499                         int *num_entries, BOOL unix_only)
500 {
501         TDB_DATA kbuf, dbuf, newkey;
502         fstring string_sid;
503         fstring group_type;
504         GROUP_MAP map;
505         GROUP_MAP *mapt;
506         int ret;
507         int entries=0;
508         int i;
509
510         *num_entries=0;
511         *rmap=NULL;
512
513         for (kbuf = tdb_firstkey(tdb); 
514              kbuf.dptr; 
515              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
516
517                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0)
518                         continue;
519                 
520                 dbuf = tdb_fetch(tdb, kbuf);
521                 if (!dbuf.dptr)
522                         continue;
523
524                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
525                                 
526                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
527                                  &map.gid, &map.sid_name_use, &map.nt_name, &map.comment);
528
529                 for (i=0; i<PRIV_ALL_INDEX; i++)
530                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &map.privileges[i]);
531
532                 SAFE_FREE(dbuf.dptr);
533                 if (ret != dbuf.dsize)
534                         continue;
535
536                 /* list only the type or everything if UNKNOWN */
537                 if (sid_name_use!=SID_NAME_UNKNOWN  && sid_name_use!=map.sid_name_use)
538                         continue;
539
540                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1)
541                         continue;
542
543                 string_to_sid(&map.sid, string_sid);
544                 
545                 decode_sid_name_use(group_type, map.sid_name_use);
546
547                 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
548                 if (!mapt) {
549                         DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
550                         SAFE_FREE(*rmap);
551                         return False;
552                 }
553                 else (*rmap) = mapt;
554
555                 mapt[entries].gid = map.gid;
556                 sid_copy( &mapt[entries].sid, &map.sid);
557                 mapt[entries].sid_name_use = map.sid_name_use;
558                 fstrcpy(mapt[entries].nt_name, map.nt_name);
559                 fstrcpy(mapt[entries].comment, map.comment);
560                 for (i=0; i<PRIV_ALL_INDEX; i++)
561                         mapt[entries].privileges[i] = map.privileges[i];
562
563                 entries++;
564         }
565
566         *num_entries=entries;
567         return True;
568 }
569
570
571 /****************************************************************************
572 convert a privilege string to a privilege array
573 ****************************************************************************/
574 void convert_priv_from_text(uint32 *se_priv, char *privilege)
575 {
576         pstring tok;
577         char *p = privilege;
578         int i;
579
580         /* By default no privilege */
581         init_privilege(se_priv);
582         
583         if (privilege==NULL)
584                 return;
585
586         while(next_token(&p, tok, " ", sizeof(tok)) ) {
587                 for (i=0; i<=PRIV_ALL_INDEX; i++) {
588                         if (StrCaseCmp(privs[i].priv, tok)==0)
589                                 add_privilege(se_priv, privs[i].se_priv);
590                 }               
591         }
592 }
593
594 /****************************************************************************
595 convert a privilege array to a privilege string
596 ****************************************************************************/
597 void convert_priv_to_text(uint32 *se_priv, char *privilege)
598 {
599         int i=0,j;
600
601         if (privilege==NULL)
602                 return;
603
604         ZERO_STRUCTP(privilege);
605
606         if (check_empty_privilege(se_priv)) {
607                 fstrcat(privilege, "No privilege");
608                 return;
609         }
610
611         while(i<PRIV_ALL_INDEX && se_priv[i]!=0) {
612                 j=1;
613                 while (privs[j].se_priv!=se_priv[i])
614                         j++;
615
616                 fstrcat(privilege, privs[j].priv);
617                 fstrcat(privilege, " ");
618                 i++;
619         }
620 }
621
622
623 /*
624  *
625  * High level functions
626  * better to use them than the lower ones.
627  *
628  * we are checking if the group is in the mapping file
629  * and if the group is an existing unix group
630  *
631  */
632
633 /* get a domain group from it's SID */
634
635 BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
636 {
637         struct group *grp;
638
639         DEBUG(10, ("get_domain_group_from_sid\n"));
640
641         /* if the group is NOT in the database, it CAN NOT be a domain group */
642         if(!get_group_map_from_sid(sid, map))
643                 return False;
644
645         DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
646
647         /* if it's not a domain group, continue */
648         if (map->sid_name_use!=SID_NAME_DOM_GRP)
649                 return False;
650
651         DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n"));
652         
653         if (map->gid==-1)
654                 return False;
655
656         DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%d\n",map->gid));
657
658         if ( (grp=getgrgid(map->gid)) == NULL)
659                 return False;
660
661         DEBUG(10, ("get_domain_group_from_sid: gid exists in UNIX security\n"));
662
663         return True;
664 }
665
666
667 /* get a local (alias) group from it's SID */
668
669 BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map)
670 {
671         struct group *grp;
672
673         /* The group is in the mapping table */
674         if(get_group_map_from_sid(sid, map)) {
675                 if (map->sid_name_use!=SID_NAME_ALIAS)
676                         return False;
677         
678                 if (map->gid==-1)
679                         return False;
680
681                 if ( (grp=getgrgid(map->gid)) == NULL)
682                         return False;
683         } else {
684                 /* the group isn't in the mapping table.
685                  * make one based on the unix information */
686                 uint32 alias_rid;
687
688                 sid_peek_rid(&sid, &alias_rid);
689                 map->gid=pdb_user_rid_to_gid(alias_rid);
690
691                 if ((grp=getgrgid(map->gid)) == NULL)
692                         return False;
693
694                 map->sid_name_use=SID_NAME_ALIAS;
695
696                 fstrcpy(map->nt_name, grp->gr_name);
697                 fstrcpy(map->comment, "Local Unix Group");
698
699                 init_privilege(map->privileges);
700
701                 sid_copy(&map->sid, &sid);
702         }
703
704         return True;
705 }
706
707 /* get a builtin group from it's SID */
708
709 BOOL get_builtin_group_from_sid(DOM_SID sid, GROUP_MAP *map)
710 {
711         struct group *grp;
712
713         if(!get_group_map_from_sid(sid, map))
714                 return False;
715
716         if (map->sid_name_use!=SID_NAME_WKN_GRP)
717                 return False;
718
719         if (map->gid==-1)
720                 return False;
721
722         if ( (grp=getgrgid(map->gid)) == NULL)
723                 return False;
724
725         return True;
726 }
727
728
729
730 /****************************************************************************
731 Returns a GROUP_MAP struct based on the gid.
732 ****************************************************************************/
733 BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
734 {
735         struct group *grp;
736
737         if ( (grp=getgrgid(gid)) == NULL)
738                 return False;
739
740         /*
741          * make a group map from scratch if doesn't exist.
742          */
743         if (!get_group_map_from_gid(gid, map)) {
744                 map->gid=gid;
745                 map->sid_name_use=SID_NAME_ALIAS;
746                 init_privilege(map->privileges);
747
748                 sid_copy(&map->sid, &global_sam_sid);
749                 sid_append_rid(&map->sid, pdb_gid_to_group_rid(gid));
750
751                 fstrcpy(map->nt_name, grp->gr_name);
752                 fstrcpy(map->comment, "Local Unix Group");
753         }
754         
755         return True;
756 }
757
758
759
760
761 /****************************************************************************
762  Get the member users of a group and
763  all the users who have that group as primary.
764             
765  give back an array of uid
766  return the grand number of users
767
768
769  TODO: sort the list and remove duplicate. JFM.
770
771 ****************************************************************************/
772         
773 BOOL get_uid_list_of_group(gid_t gid, uid_t **uid, int *num_uids)
774 {
775         struct group *grp;
776         struct passwd *pwd;
777         int i=0;
778         char *gr;
779         uid_t *u;
780  
781         *num_uids = 0;
782         *uid=NULL;
783         
784         if ( (grp=getgrgid(gid)) == NULL)
785                 return False;
786
787         gr = grp->gr_mem[0];
788         DEBUG(10, ("getting members\n"));
789         
790         while (gr && (*gr != (char)'\0')) {
791                 u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
792                 if (!u) {
793                         DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
794                         return False;
795                 }
796                 else (*uid) = u;
797
798                 if( (pwd=getpwnam(gr)) !=NULL) {
799                         (*uid)[*num_uids]=pwd->pw_uid;
800                         (*num_uids)++;
801                 }
802                 gr = grp->gr_mem[++i];
803         }
804         DEBUG(10, ("got [%d] members\n", *num_uids));
805
806         setpwent();
807         while ((pwd=getpwent()) != NULL) {
808                 if (pwd->pw_gid==gid) {
809                         u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
810                         if (!u) {
811                                 DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
812                                 return False;
813                         }
814                         else (*uid) = u;
815                         (*uid)[*num_uids]=pwd->pw_uid;
816
817                         (*num_uids)++;
818                 }
819         }
820         endpwent();
821         DEBUG(10, ("got primary groups, members: [%d]\n", *num_uids));
822
823         return True;
824 }
825
826 /****************************************************************************
827  Create a UNIX group on demand.
828 ****************************************************************************/
829
830 int smb_create_group(char *unix_group)
831 {
832         pstring add_script;
833         int ret;
834
835         pstrcpy(add_script, lp_addgroup_script());
836         if (! *add_script) return -1;
837         pstring_sub(add_script, "%g", unix_group);
838         ret = smbrun(add_script,NULL);
839         DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
840         return ret;
841 }
842
843 /****************************************************************************
844  Delete a UNIX group on demand.
845 ****************************************************************************/
846
847 int smb_delete_group(char *unix_group)
848 {
849         pstring del_script;
850         int ret;
851
852         pstrcpy(del_script, lp_delgroup_script());
853         if (! *del_script) return -1;
854         pstring_sub(del_script, "%g", unix_group);
855         ret = smbrun(del_script,NULL);
856         DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
857         return ret;
858 }
859
860 /****************************************************************************
861  Create a UNIX group on demand.
862 ****************************************************************************/
863
864 int smb_add_user_group(char *unix_group, char *unix_user)
865 {
866         pstring add_script;
867         int ret;
868
869         pstrcpy(add_script, lp_addusertogroup_script());
870         if (! *add_script) return -1;
871         pstring_sub(add_script, "%g", unix_group);
872         pstring_sub(add_script, "%u", unix_user);
873         ret = smbrun(add_script,NULL);
874         DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
875         return ret;
876 }
877
878 /****************************************************************************
879  Delete a UNIX group on demand.
880 ****************************************************************************/
881
882 int smb_delete_user_group(char *unix_group, char *unix_user)
883 {
884         pstring del_script;
885         int ret;
886
887         pstrcpy(del_script, lp_deluserfromgroup_script());
888         if (! *del_script) return -1;
889         pstring_sub(del_script, "%g", unix_group);
890         pstring_sub(del_script, "%u", unix_user);
891         ret = smbrun(del_script,NULL);
892         DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
893         return ret;
894 }
895
896
897