Add find_alias, create_alias, delete_alias, get_aliasinfo, set_aliasinfo and
[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(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 NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, int *num)
535 {
536         GROUP_MAP map;
537         TDB_DATA kbuf, dbuf;
538         pstring key;
539         fstring string_sid;
540         const char *p;
541
542         if(!init_group_mapping()) {
543                 DEBUG(0,("failed to initialize group mapping\n"));
544                 return NT_STATUS_ACCESS_DENIED;
545         }
546
547         if (!get_group_map_from_sid(*alias, &map))
548                 return NT_STATUS_NO_SUCH_ALIAS;
549
550         if ( (map.sid_name_use != SID_NAME_ALIAS) &&
551              (map.sid_name_use != SID_NAME_WKN_GRP) )
552                 return NT_STATUS_NO_SUCH_ALIAS;
553
554         *sids = NULL;
555         *num = 0;
556
557         sid_to_string(string_sid, alias);
558         slprintf(key, sizeof(key), "%s%s", ALIASMEM_PREFIX, string_sid);
559
560         kbuf.dsize = strlen(key)+1;
561         kbuf.dptr = key;
562
563         dbuf = tdb_fetch(tdb, kbuf);
564
565         if (dbuf.dptr == NULL) {
566                 return NT_STATUS_OK;
567         }
568
569         p = dbuf.dptr;
570
571         while (next_token(&p, string_sid, " ", sizeof(string_sid))) {
572
573                 DOM_SID sid;
574
575                 if (!string_to_sid(&sid, string_sid))
576                         continue;
577
578                 add_sid_to_array(&sid, sids, num);
579
580                 if (sids == NULL)
581                         return NT_STATUS_NO_MEMORY;
582         }
583
584         SAFE_FREE(dbuf.dptr);
585
586         return NT_STATUS_OK;
587 }
588
589 /* This is racy as hell, but hey, it's only a prototype :-) */
590
591 static NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
592 {
593         NTSTATUS result;
594         DOM_SID *sids;
595         int i, num;
596         BOOL found = False;
597         char *member_string;
598         TDB_DATA kbuf, dbuf;
599         pstring key;
600         fstring sid_string;
601
602         result = enum_aliasmem(alias, &sids, &num);
603
604         if (!NT_STATUS_IS_OK(result))
605                 return result;
606
607         for (i=0; i<num; i++) {
608                 if (sid_compare(&sids[i], member) == 0) {
609                         found = True;
610                         break;
611                 }
612         }
613
614         if (!found) {
615                 SAFE_FREE(sids);
616                 return NT_STATUS_MEMBER_NOT_IN_ALIAS;
617         }
618
619         if (i < num)
620                 sids[i] = sids[num-1];
621
622         num -= 1;
623
624         member_string = strdup("");
625
626         if (member_string == NULL) {
627                 SAFE_FREE(sids);
628                 return NT_STATUS_NO_MEMORY;
629         }
630
631         for (i=0; i<num; i++) {
632                 char *s = member_string;
633
634                 sid_to_string(sid_string, &sids[i]);
635                 asprintf(&member_string, "%s %s", s, sid_string);
636
637                 SAFE_FREE(s);
638                 if (member_string == NULL) {
639                         SAFE_FREE(sids);
640                         return NT_STATUS_NO_MEMORY;
641                 }
642         }
643
644         sid_to_string(sid_string, alias);
645         slprintf(key, sizeof(key), "%s%s", ALIASMEM_PREFIX, sid_string);
646
647         kbuf.dsize = strlen(key)+1;
648         kbuf.dptr = key;
649         dbuf.dsize = strlen(member_string)+1;
650         dbuf.dptr = member_string;
651
652         result = tdb_store(tdb, kbuf, dbuf, 0) == 0 ?
653                 NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
654
655         SAFE_FREE(sids);
656         SAFE_FREE(member_string);
657
658         return result;
659 }
660
661 static BOOL is_foreign_alias_member(const DOM_SID *sid, const DOM_SID *alias)
662 {
663         DOM_SID *members;
664         int i, num;
665         BOOL result = False;
666
667         if (!NT_STATUS_IS_OK(enum_aliasmem(alias, &members, &num)))
668                 return False;
669
670         for (i=0; i<num; i++) {
671
672                 if (sid_compare(&members[i], sid) == 0) {
673                         result = True;
674                         break;
675                 }
676         }
677
678         SAFE_FREE(members);
679         return result;
680 }
681
682 static NTSTATUS alias_memberships(const DOM_SID *sid, DOM_SID **sids, int *num)
683 {
684         GROUP_MAP *maps;
685         int i, num_maps;
686
687         *num = 0;
688         *sids = NULL;
689
690         if (!enum_group_mapping(SID_NAME_WKN_GRP, &maps, &num_maps, False))
691                 return NT_STATUS_NO_MEMORY;
692
693         for (i=0; i<num_maps; i++) {
694
695                 if (is_foreign_alias_member(sid, &maps[i].sid)) {
696
697                         add_sid_to_array(&maps[i].sid, sids, num);
698
699                         if (sids == NULL) {
700                                 SAFE_FREE(maps);
701                                 return NT_STATUS_NO_MEMORY;
702                         }
703                 }
704         }
705         SAFE_FREE(maps);
706                                 
707         if (!enum_group_mapping(SID_NAME_ALIAS, &maps, &num_maps, False))
708                 return NT_STATUS_NO_MEMORY;
709
710         for (i=0; i<num_maps; i++) {
711                 if (is_foreign_alias_member(sid, &maps[i].sid)) {
712
713                         add_sid_to_array(&maps[i].sid, sids, num);
714
715                         if (sids == NULL) {
716                                 SAFE_FREE(maps);
717                                 return NT_STATUS_NO_MEMORY;
718                         }
719                 }
720         }
721         SAFE_FREE(maps);
722                                 
723         return NT_STATUS_OK;
724 }
725
726 /*
727  *
728  * High level functions
729  * better to use them than the lower ones.
730  *
731  * we are checking if the group is in the mapping file
732  * and if the group is an existing unix group
733  *
734  */
735
736 /* get a domain group from it's SID */
737
738 BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
739 {
740         struct group *grp;
741         BOOL ret;
742         
743         if(!init_group_mapping()) {
744                 DEBUG(0,("failed to initialize group mapping\n"));
745                 return(False);
746         }
747
748         DEBUG(10, ("get_domain_group_from_sid\n"));
749
750         /* if the group is NOT in the database, it CAN NOT be a domain group */
751         
752         become_root();
753         ret = pdb_getgrsid(map, sid);
754         unbecome_root();
755         
756         if ( !ret ) 
757                 return False;
758
759         DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
760
761         /* if it's not a domain group, continue */
762         if (map->sid_name_use!=SID_NAME_DOM_GRP) {
763                 return False;
764         }
765
766         DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n"));
767         
768         if (map->gid==-1) {
769                 return False;
770         }
771
772         DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%lu\n",(unsigned long)map->gid));
773         
774         grp = getgrgid(map->gid);
775         if ( !grp ) {
776                 DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n"));
777                 return False;
778         }
779
780         DEBUG(10, ("get_domain_group_from_sid: gid exists in UNIX security\n"));
781
782         return True;
783 }
784
785
786 /* get a local (alias) group from it's SID */
787
788 BOOL get_local_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
789 {
790         BOOL ret;
791         
792         if(!init_group_mapping()) {
793                 DEBUG(0,("failed to initialize group mapping\n"));
794                 return(False);
795         }
796
797         /* The group is in the mapping table */
798         become_root();
799         ret = pdb_getgrsid(map, *sid);
800         unbecome_root();
801         
802         if ( !ret )
803                 return False;
804                 
805         if ( ( (map->sid_name_use != SID_NAME_ALIAS) &&
806                (map->sid_name_use != SID_NAME_WKN_GRP) )
807                 || (map->gid == -1)
808                 || (getgrgid(map->gid) == NULL) ) 
809         {
810                 return False;
811         }               
812                         
813 #if 1   /* JERRY */
814         /* local groups only exist in the group mapping DB so this 
815            is not necessary */
816            
817         else {
818                 /* the group isn't in the mapping table.
819                  * make one based on the unix information */
820                 uint32 alias_rid;
821                 struct group *grp;
822
823                 sid_peek_rid(sid, &alias_rid);
824                 map->gid=pdb_group_rid_to_gid(alias_rid);
825                 
826                 grp = getgrgid(map->gid);
827                 if ( !grp ) {
828                         DEBUG(3,("get_local_group_from_sid: No unix group for [%ul]\n", map->gid));
829                         return False;
830                 }
831
832                 map->sid_name_use=SID_NAME_ALIAS;
833
834                 fstrcpy(map->nt_name, grp->gr_name);
835                 fstrcpy(map->comment, "Local Unix Group");
836
837                 sid_copy(&map->sid, sid);
838         }
839 #endif
840
841         return True;
842 }
843
844 /* get a builtin group from it's SID */
845
846 BOOL get_builtin_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
847 {
848         struct group *grp;
849         BOOL ret;
850         
851
852         if(!init_group_mapping()) {
853                 DEBUG(0,("failed to initialize group mapping\n"));
854                 return(False);
855         }
856
857         become_root();
858         ret = pdb_getgrsid(map, *sid);
859         unbecome_root();
860         
861         if ( !ret )
862                 return False;
863
864         if (map->sid_name_use!=SID_NAME_WKN_GRP) {
865                 return False;
866         }
867
868         if (map->gid==-1) {
869                 return False;
870         }
871
872         if ( (grp=getgrgid(map->gid)) == NULL) {
873                 return False;
874         }
875
876         return True;
877 }
878
879
880
881 /****************************************************************************
882 Returns a GROUP_MAP struct based on the gid.
883 ****************************************************************************/
884 BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
885 {
886         struct group *grp;
887         BOOL ret;
888
889         if(!init_group_mapping()) {
890                 DEBUG(0,("failed to initialize group mapping\n"));
891                 return(False);
892         }
893
894         if ( (grp=getgrgid(gid)) == NULL)
895                 return False;
896
897         /*
898          * make a group map from scratch if doesn't exist.
899          */
900         
901         become_root();
902         ret = pdb_getgrgid(map, gid);
903         unbecome_root();
904         
905         if ( !ret ) {
906                 map->gid=gid;
907                 map->sid_name_use=SID_NAME_ALIAS;
908
909                 /* interim solution until we have a last RID allocated */
910
911                 sid_copy(&map->sid, get_global_sam_sid());
912                 sid_append_rid(&map->sid, pdb_gid_to_group_rid(gid));
913
914                 fstrcpy(map->nt_name, grp->gr_name);
915                 fstrcpy(map->comment, "Local Unix Group");
916         }
917         
918         return True;
919 }
920
921
922
923
924 /****************************************************************************
925  Get the member users of a group and
926  all the users who have that group as primary.
927             
928  give back an array of SIDS
929  return the grand number of users
930
931
932  TODO: sort the list and remove duplicate. JFM.
933
934 ****************************************************************************/
935         
936 BOOL get_sid_list_of_group(gid_t gid, DOM_SID **sids, int *num_sids)
937 {
938         struct group *grp;
939         int i=0;
940         char *gr;
941         DOM_SID *s;
942         DOM_SID sid;
943         DOM_SID *members;
944         int num_members;
945
946         struct sys_pwent *userlist;
947         struct sys_pwent *user;
948  
949         if(!init_group_mapping()) {
950                 DEBUG(0,("failed to initialize group mapping\n"));
951                 return(False);
952         }
953
954         *num_sids = 0;
955         *sids=NULL;
956         
957         if ( (grp=getgrgid(gid)) == NULL)
958                 return False;
959
960         gr = grp->gr_mem[0];
961         DEBUG(10, ("getting members\n"));
962         
963         while (gr && (*gr != (char)'\0')) {
964                 SAM_ACCOUNT *group_member_acct = NULL;
965                 BOOL found_user;
966                 s = Realloc((*sids), sizeof(**sids)*(*num_sids+1));
967                 if (!s) {
968                         DEBUG(0,("get_uid_list_of_group: unable to enlarge SID list!\n"));
969                         return False;
970                 }
971                 else (*sids) = s;
972
973                 if (!NT_STATUS_IS_OK(pdb_init_sam(&group_member_acct))) {
974                         continue;
975                 }
976
977                 become_root();
978                 found_user = pdb_getsampwnam(group_member_acct, gr);
979                 unbecome_root();
980         
981                 if (found_user) {
982                         sid_copy(&(*sids)[*num_sids], pdb_get_user_sid(group_member_acct));
983                         (*num_sids)++;
984                 }
985         
986                 pdb_free_sam(&group_member_acct);
987
988                 gr = grp->gr_mem[++i];
989         }
990         DEBUG(10, ("got [%d] members\n", *num_sids));
991
992         winbind_off();
993
994         user = userlist = getpwent_list();
995
996         while (user != NULL) {
997
998                 SAM_ACCOUNT *group_member_acct = NULL;
999                 BOOL found_user;
1000
1001                 if (user->pw_gid != gid) {
1002                         user = user->next;
1003                         continue;
1004                 }
1005
1006                 s = Realloc((*sids), sizeof(**sids)*(*num_sids+1));
1007                 if (!s) {
1008                         DEBUG(0,("get_sid_list_of_group: unable to enlarge "
1009                                  "SID list!\n"));
1010                         pwent_free(userlist);
1011                         winbind_on();
1012                         return False;
1013                 }
1014                 else (*sids) = s;
1015                         
1016                 if (!NT_STATUS_IS_OK(pdb_init_sam(&group_member_acct))) {
1017                         continue;
1018                 }
1019                         
1020                 become_root();
1021                 found_user = pdb_getsampwnam(group_member_acct, user->pw_name);
1022                 unbecome_root();
1023                         
1024                 if (found_user) {
1025                         sid_copy(&(*sids)[*num_sids],
1026                                  pdb_get_user_sid(group_member_acct));
1027                         (*num_sids)++;
1028                 } else {
1029                         DEBUG(4,("get_sid_list_of_group: User %s [uid == %lu] "
1030                                  "has no samba account\n",
1031                                  user->pw_name, (unsigned long)user->pw_uid));
1032                         if (algorithmic_uid_to_sid(&(*sids)[*num_sids],
1033                                                    user->pw_uid))
1034                                 (*num_sids)++;
1035                 }
1036                 pdb_free_sam(&group_member_acct);
1037
1038                 user = user->next;
1039         }
1040         pwent_free(userlist);
1041         DEBUG(10, ("got primary groups, members: [%d]\n", *num_sids));
1042
1043         winbind_on();
1044
1045         if ( NT_STATUS_IS_OK(gid_to_sid(&sid, gid)) &&
1046              NT_STATUS_IS_OK(enum_aliasmem(&sid, &members, &num_members)) ) {
1047
1048                 for (i=0; i<num_members; i++) {
1049                         add_sid_to_array(&members[i], sids, num_sids);
1050
1051                         if (sids == NULL)
1052                                 return False;
1053                 }
1054         }
1055
1056         return True;
1057 }
1058
1059 /****************************************************************************
1060  Create a UNIX group on demand.
1061 ****************************************************************************/
1062
1063 int smb_create_group(char *unix_group, gid_t *new_gid)
1064 {
1065         pstring add_script;
1066         int     ret = -1;
1067         int     fd = 0;
1068         
1069         *new_gid = 0;
1070
1071         /* defer to scripts */
1072         
1073         if ( *lp_addgroup_script() ) {
1074                 pstrcpy(add_script, lp_addgroup_script());
1075                 pstring_sub(add_script, "%g", unix_group);
1076                 ret = smbrun(add_script, (new_gid!=NULL) ? &fd : NULL);
1077                 DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
1078                 if (ret != 0)
1079                         return ret;
1080                         
1081                 if (fd != 0) {
1082                         fstring output;
1083
1084                         *new_gid = 0;
1085                         if (read(fd, output, sizeof(output)) > 0) {
1086                                 *new_gid = (gid_t)strtoul(output, NULL, 10);
1087                         }
1088                         
1089                         close(fd);
1090                 }
1091
1092         } else if ( winbind_create_group( unix_group, NULL ) ) {
1093
1094                 DEBUG(3,("smb_create_group: winbindd created the group (%s)\n",
1095                         unix_group));
1096                 ret = 0;
1097         }
1098         
1099         if (*new_gid == 0) {
1100                 struct group *grp = getgrnam(unix_group);
1101
1102                 if (grp != NULL)
1103                         *new_gid = grp->gr_gid;
1104         }
1105                         
1106         return ret;     
1107 }
1108
1109 /****************************************************************************
1110  Delete a UNIX group on demand.
1111 ****************************************************************************/
1112
1113 int smb_delete_group(char *unix_group)
1114 {
1115         pstring del_script;
1116         int ret;
1117
1118         /* defer to scripts */
1119         
1120         if ( *lp_delgroup_script() ) {
1121                 pstrcpy(del_script, lp_delgroup_script());
1122                 pstring_sub(del_script, "%g", unix_group);
1123                 ret = smbrun(del_script,NULL);
1124                 DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
1125                 return ret;
1126         }
1127
1128         if ( winbind_delete_group( unix_group ) ) {
1129                 DEBUG(3,("smb_delete_group: winbindd deleted the group (%s)\n",
1130                         unix_group));
1131                 return 0;
1132         }
1133                 
1134         return -1;
1135 }
1136
1137 /****************************************************************************
1138  Set a user's primary UNIX group.
1139 ****************************************************************************/
1140 int smb_set_primary_group(const char *unix_group, const char* unix_user)
1141 {
1142         pstring add_script;
1143         int ret;
1144
1145         /* defer to scripts */
1146         
1147         if ( *lp_setprimarygroup_script() ) {
1148                 pstrcpy(add_script, lp_setprimarygroup_script());
1149                 all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
1150                 all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
1151                 ret = smbrun(add_script,NULL);
1152                 DEBUG(3,("smb_set_primary_group: "
1153                          "Running the command `%s' gave %d\n",add_script,ret));
1154                 return ret;
1155         }
1156
1157         /* Try winbindd */
1158         
1159         if ( winbind_set_user_primary_group( unix_user, unix_group ) ) {
1160                 DEBUG(3,("smb_delete_group: winbindd set the group (%s) as the primary group for user (%s)\n",
1161                         unix_group, unix_user));
1162                 return 0;
1163         }               
1164         
1165         return -1;
1166 }
1167
1168 /****************************************************************************
1169  Add a user to a UNIX group.
1170 ****************************************************************************/
1171
1172 int smb_add_user_group(char *unix_group, char *unix_user)
1173 {
1174         pstring add_script;
1175         int ret;
1176
1177         /* defer to scripts */
1178         
1179         if ( *lp_addusertogroup_script() ) {
1180                 pstrcpy(add_script, lp_addusertogroup_script());
1181                 pstring_sub(add_script, "%g", unix_group);
1182                 pstring_sub(add_script, "%u", unix_user);
1183                 ret = smbrun(add_script,NULL);
1184                 DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
1185                 return ret;
1186         }
1187         
1188         /* Try winbindd */
1189
1190         if ( winbind_add_user_to_group( unix_user, unix_group ) ) {
1191                 DEBUG(3,("smb_delete_group: winbindd added user (%s) to the group (%s)\n",
1192                         unix_user, unix_group));
1193                 return -1;
1194         }       
1195         
1196         return -1;
1197 }
1198
1199 /****************************************************************************
1200  Delete a user from a UNIX group
1201 ****************************************************************************/
1202
1203 int smb_delete_user_group(const char *unix_group, const char *unix_user)
1204 {
1205         pstring del_script;
1206         int ret;
1207
1208         /* defer to scripts */
1209         
1210         if ( *lp_deluserfromgroup_script() ) {
1211                 pstrcpy(del_script, lp_deluserfromgroup_script());
1212                 pstring_sub(del_script, "%g", unix_group);
1213                 pstring_sub(del_script, "%u", unix_user);
1214                 ret = smbrun(del_script,NULL);
1215                 DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
1216                 return ret;
1217         }
1218         
1219         /* Try winbindd */
1220
1221         if ( winbind_remove_user_from_group( unix_user, unix_group ) ) {
1222                 DEBUG(3,("smb_delete_group: winbindd removed user (%s) from the group (%s)\n",
1223                         unix_user, unix_group));
1224                 return 0;
1225         }
1226         
1227         return -1;
1228 }
1229
1230
1231 NTSTATUS pdb_default_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1232                                  DOM_SID sid)
1233 {
1234         return get_group_map_from_sid(sid, map) ?
1235                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1236 }
1237
1238 NTSTATUS pdb_default_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1239                                  gid_t gid)
1240 {
1241         return get_group_map_from_gid(gid, map) ?
1242                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1243 }
1244
1245 NTSTATUS pdb_default_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1246                                  const char *name)
1247 {
1248         return get_group_map_from_ntname(name, map) ?
1249                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1250 }
1251
1252 NTSTATUS pdb_default_add_group_mapping_entry(struct pdb_methods *methods,
1253                                                 GROUP_MAP *map)
1254 {
1255         return add_mapping_entry(map, TDB_INSERT) ?
1256                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1257 }
1258
1259 NTSTATUS pdb_default_update_group_mapping_entry(struct pdb_methods *methods,
1260                                                    GROUP_MAP *map)
1261 {
1262         return add_mapping_entry(map, TDB_REPLACE) ?
1263                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1264 }
1265
1266 NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods,
1267                                                    DOM_SID sid)
1268 {
1269         return group_map_remove(sid) ?
1270                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1271 }
1272
1273 NTSTATUS pdb_default_find_alias(struct pdb_methods *methods,
1274                                 const char *name, DOM_SID *sid)
1275 {
1276         GROUP_MAP map;
1277
1278         if (!get_group_map_from_ntname(name, &map))
1279                 return NT_STATUS_NO_SUCH_ALIAS;
1280
1281         if ((map.sid_name_use != SID_NAME_WKN_GRP) &&
1282             (map.sid_name_use != SID_NAME_ALIAS))
1283                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
1284
1285         sid_copy(sid, &map.sid);
1286         return NT_STATUS_OK;
1287 }
1288
1289 NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
1290                                   const char *name, uint32 *rid)
1291 {
1292         return NT_STATUS_ACCESS_DENIED;
1293 }
1294
1295 NTSTATUS pdb_default_delete_alias(struct pdb_methods *methods,
1296                                   const DOM_SID *sid)
1297 {
1298         return NT_STATUS_ACCESS_DENIED;
1299 }
1300
1301 NTSTATUS pdb_default_enum_aliases(struct pdb_methods *methods,
1302                                   const DOM_SID *sid,
1303                                   uint32 start_idx, uint32 max_entries,
1304                                   uint32 *num_aliases,
1305                                   struct acct_info **info)
1306 {
1307         extern DOM_SID global_sid_Builtin;
1308
1309         GROUP_MAP *map;
1310         int i, num_maps;
1311         enum SID_NAME_USE type = SID_NAME_UNKNOWN;
1312
1313         if (sid_compare(sid, get_global_sam_sid()) == 0)
1314                 type = SID_NAME_ALIAS;
1315
1316         if (sid_compare(sid, &global_sid_Builtin) == 0)
1317                 type = SID_NAME_WKN_GRP;
1318
1319         if (!enum_group_mapping(type, &map, &num_maps, False) ||
1320             (num_maps == 0)) {
1321                 *num_aliases = 0;
1322                 *info = NULL;
1323                 goto done;
1324         }
1325
1326         if (start_idx > num_maps) {
1327                 *num_aliases = 0;
1328                 *info = NULL;
1329                 goto done;
1330         }
1331
1332         *num_aliases = num_maps - start_idx;
1333
1334         if (*num_aliases > max_entries)
1335                 *num_aliases = max_entries;
1336
1337         *info = malloc(sizeof(struct acct_info) * (*num_aliases));
1338
1339         for (i=0; i<*num_aliases; i++) {
1340                 fstrcpy((*info)[i].acct_name, map[i+start_idx].nt_name);
1341                 fstrcpy((*info)[i].acct_desc, map[i+start_idx].comment);
1342                 sid_peek_rid(&map[i].sid, &(*info)[i+start_idx].rid);
1343         }
1344
1345  done:
1346         SAFE_FREE(map);
1347         return NT_STATUS_OK;
1348 }
1349
1350 NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
1351                                    const DOM_SID *sid,
1352                                    struct acct_info *info)
1353 {
1354         GROUP_MAP map;
1355
1356         if (!get_group_map_from_sid(*sid, &map))
1357                 return NT_STATUS_NO_SUCH_ALIAS;
1358
1359         fstrcpy(info->acct_name, map.nt_name);
1360         fstrcpy(info->acct_desc, map.comment);
1361         sid_peek_rid(&map.sid, &info->rid);
1362         return NT_STATUS_OK;
1363 }
1364
1365 NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods,
1366                                    const DOM_SID *sid,
1367                                    struct acct_info *info)
1368 {
1369         GROUP_MAP map;
1370
1371         if (!get_group_map_from_sid(*sid, &map))
1372                 return NT_STATUS_NO_SUCH_ALIAS;
1373
1374         fstrcpy(map.comment, info->acct_desc);
1375
1376         if (!add_mapping_entry(&map, TDB_REPLACE))
1377                 return NT_STATUS_ACCESS_DENIED;
1378
1379         return NT_STATUS_OK;
1380 }
1381
1382 NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods,
1383                                            enum SID_NAME_USE sid_name_use,
1384                                            GROUP_MAP **rmap, int *num_entries,
1385                                            BOOL unix_only)
1386 {
1387         return enum_group_mapping(sid_name_use, rmap, num_entries, unix_only) ?
1388                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1389 }
1390
1391 NTSTATUS pdb_default_add_aliasmem(struct pdb_methods *methods,
1392                                   const DOM_SID *alias, const DOM_SID *member)
1393 {
1394         return add_aliasmem(alias, member);
1395 }
1396
1397 NTSTATUS pdb_default_del_aliasmem(struct pdb_methods *methods,
1398                                   const DOM_SID *alias, const DOM_SID *member)
1399 {
1400         return del_aliasmem(alias, member);
1401 }
1402
1403 NTSTATUS pdb_default_enum_aliasmem(struct pdb_methods *methods,
1404                                    const DOM_SID *alias, DOM_SID **members,
1405                                    int *num_members)
1406 {
1407         return enum_aliasmem(alias, members, num_members);
1408 }
1409
1410 NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods,
1411                                        const DOM_SID *sid,
1412                                        DOM_SID **aliases, int *num)
1413 {
1414         return alias_memberships(sid, aliases, num);
1415 }
1416
1417 /**********************************************************************
1418  no ops for passdb backends that don't implement group mapping
1419  *********************************************************************/
1420
1421 NTSTATUS pdb_nop_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1422                                  DOM_SID sid)
1423 {
1424         return NT_STATUS_UNSUCCESSFUL;
1425 }
1426
1427 NTSTATUS pdb_nop_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1428                                  gid_t gid)
1429 {
1430         return NT_STATUS_UNSUCCESSFUL;
1431 }
1432
1433 NTSTATUS pdb_nop_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1434                                  const char *name)
1435 {
1436         return NT_STATUS_UNSUCCESSFUL;
1437 }
1438
1439 NTSTATUS pdb_nop_add_group_mapping_entry(struct pdb_methods *methods,
1440                                                 GROUP_MAP *map)
1441 {
1442         return NT_STATUS_UNSUCCESSFUL;
1443 }
1444
1445 NTSTATUS pdb_nop_update_group_mapping_entry(struct pdb_methods *methods,
1446                                                    GROUP_MAP *map)
1447 {
1448         return NT_STATUS_UNSUCCESSFUL;
1449 }
1450
1451 NTSTATUS pdb_nop_delete_group_mapping_entry(struct pdb_methods *methods,
1452                                                    DOM_SID sid)
1453 {
1454         return NT_STATUS_UNSUCCESSFUL;
1455 }
1456
1457 NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods,
1458                                            enum SID_NAME_USE sid_name_use,
1459                                            GROUP_MAP **rmap, int *num_entries,
1460                                            BOOL unix_only)
1461 {
1462         return NT_STATUS_UNSUCCESSFUL;
1463 }
1464