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