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