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