trying to get HEAD building again. If you want the code
[nivanova/samba-autobuild/.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;
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         sid_copy(&map->sid, &sid);
262         
263         return True;
264 }
265
266 /****************************************************************************
267  Return the sid and the type of the unix group.
268 ****************************************************************************/
269
270 static BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
271 {
272         TDB_DATA kbuf, dbuf, newkey;
273         fstring string_sid;
274         int ret;
275
276         if(!init_group_mapping()) {
277                 DEBUG(0,("failed to initialize group mapping"));
278                 return(False);
279         }
280
281         /* we need to enumerate the TDB to find the GID */
282
283         for (kbuf = tdb_firstkey(tdb); 
284              kbuf.dptr; 
285              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
286
287                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
288                 
289                 dbuf = tdb_fetch(tdb, kbuf);
290                 if (!dbuf.dptr)
291                         continue;
292
293                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
294
295                 string_to_sid(&map->sid, string_sid);
296                 
297                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
298                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
299
300                 SAFE_FREE(dbuf.dptr);
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"));
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 (StrCaseCmp(name, map->nt_name)==0) {
348                         SAFE_FREE(kbuf.dptr);
349                         return True;
350                 }
351         }
352
353         return False;
354 }
355
356 /****************************************************************************
357  Remove a group mapping entry.
358 ****************************************************************************/
359
360 static BOOL group_map_remove(DOM_SID sid)
361 {
362         TDB_DATA kbuf, dbuf;
363         pstring key;
364         fstring string_sid;
365         
366         if(!init_group_mapping()) {
367                 DEBUG(0,("failed to initialize group mapping"));
368                 return(False);
369         }
370
371         /* the key is the SID, retrieving is direct */
372
373         sid_to_string(string_sid, &sid);
374         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
375
376         kbuf.dptr = key;
377         kbuf.dsize = strlen(key)+1;
378                 
379         dbuf = tdb_fetch(tdb, kbuf);
380         if (!dbuf.dptr)
381                 return False;
382         
383         SAFE_FREE(dbuf.dptr);
384
385         if(tdb_delete(tdb, kbuf) != TDB_SUCCESS)
386                 return False;
387
388         return True;
389 }
390
391 /****************************************************************************
392  Enumerate the group mapping.
393 ****************************************************************************/
394
395 static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
396                         int *num_entries, BOOL unix_only)
397 {
398         TDB_DATA kbuf, dbuf, newkey;
399         fstring string_sid;
400         fstring group_type;
401         GROUP_MAP map;
402         GROUP_MAP *mapt;
403         int ret;
404         int entries=0;
405
406         if(!init_group_mapping()) {
407                 DEBUG(0,("failed to initialize group mapping"));
408                 return(False);
409         }
410
411         *num_entries=0;
412         *rmap=NULL;
413
414         for (kbuf = tdb_firstkey(tdb); 
415              kbuf.dptr; 
416              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
417
418                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0)
419                         continue;
420
421                 dbuf = tdb_fetch(tdb, kbuf);
422                 if (!dbuf.dptr)
423                         continue;
424
425                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
426                                 
427                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
428                                  &map.gid, &map.sid_name_use, &map.nt_name, &map.comment);
429
430                 SAFE_FREE(dbuf.dptr);
431
432                 /* list only the type or everything if UNKNOWN */
433                 if (sid_name_use!=SID_NAME_UNKNOWN  && sid_name_use!=map.sid_name_use) {
434                         DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
435                         continue;
436                 }
437
438                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
439                         DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
440                         continue;
441                 }
442
443                 string_to_sid(&map.sid, string_sid);
444                 
445                 decode_sid_name_use(group_type, map.sid_name_use);
446                 DEBUG(11,("enum_group_mapping: returning group %s of type %s\n", map.nt_name ,group_type));
447
448                 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
449                 if (!mapt) {
450                         DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
451                         SAFE_FREE(*rmap);
452                         return False;
453                 }
454                 else
455                         (*rmap) = mapt;
456
457                 mapt[entries].gid = map.gid;
458                 sid_copy( &mapt[entries].sid, &map.sid);
459                 mapt[entries].sid_name_use = map.sid_name_use;
460                 fstrcpy(mapt[entries].nt_name, map.nt_name);
461                 fstrcpy(mapt[entries].comment, map.comment);
462
463                 entries++;
464
465         }
466
467         *num_entries=entries;
468
469         return True;
470 }
471
472 /*
473  *
474  * High level functions
475  * better to use them than the lower ones.
476  *
477  * we are checking if the group is in the mapping file
478  * and if the group is an existing unix group
479  *
480  */
481
482 /* get a domain group from it's SID */
483
484 BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
485 {
486         struct group *grp;
487
488         if(!init_group_mapping()) {
489                 DEBUG(0,("failed to initialize group mapping"));
490                 return(False);
491         }
492
493         DEBUG(10, ("get_domain_group_from_sid\n"));
494
495         /* if the group is NOT in the database, it CAN NOT be a domain group */
496         if(!pdb_getgrsid(map, sid))
497                 return False;
498
499         DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
500
501         /* if it's not a domain group, continue */
502         if (map->sid_name_use!=SID_NAME_DOM_GRP) {
503                 return False;
504         }
505
506         DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n"));
507         
508         if (map->gid==-1) {
509                 return False;
510         }
511
512         DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%d\n",map->gid));
513
514         if ( (grp=getgrgid(map->gid)) == NULL) {
515                 DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n"));
516                 return False;
517         }
518
519         DEBUG(10, ("get_domain_group_from_sid: gid exists in UNIX security\n"));
520
521         return True;
522 }
523
524
525 /* get a local (alias) group from it's SID */
526
527 BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map)
528 {
529         struct group *grp;
530
531         if(!init_group_mapping()) {
532                 DEBUG(0,("failed to initialize group mapping"));
533                 return(False);
534         }
535
536         /* The group is in the mapping table */
537         if(pdb_getgrsid(map, sid)) {
538                 if (map->sid_name_use!=SID_NAME_ALIAS) {
539                         return False;
540                 }
541                 
542                 if (map->gid==-1) {
543                         return False;
544                 }
545
546                 if ( (grp=getgrgid(map->gid)) == NULL) {
547                         return False;
548                 }
549         } else {
550                 /* the group isn't in the mapping table.
551                  * make one based on the unix information */
552                 uint32 alias_rid;
553
554                 sid_peek_rid(&sid, &alias_rid);
555                 map->gid=pdb_group_rid_to_gid(alias_rid);
556
557                 if ((grp=getgrgid(map->gid)) == NULL)
558                         return False;
559
560                 map->sid_name_use=SID_NAME_ALIAS;
561
562                 fstrcpy(map->nt_name, grp->gr_name);
563                 fstrcpy(map->comment, "Local Unix Group");
564
565                 sid_copy(&map->sid, &sid);
566         }
567
568         return True;
569 }
570
571 /* get a builtin group from it's SID */
572
573 BOOL get_builtin_group_from_sid(DOM_SID sid, GROUP_MAP *map)
574 {
575         struct group *grp;
576
577         if(!init_group_mapping()) {
578                 DEBUG(0,("failed to initialize group mapping"));
579                 return(False);
580         }
581
582         if(!pdb_getgrsid(map, sid))
583                 return False;
584
585         if (map->sid_name_use!=SID_NAME_WKN_GRP) {
586                 return False;
587         }
588
589         if (map->gid==-1) {
590                 return False;
591         }
592
593         if ( (grp=getgrgid(map->gid)) == NULL) {
594                 return False;
595         }
596
597         return True;
598 }
599
600
601
602 /****************************************************************************
603 Returns a GROUP_MAP struct based on the gid.
604 ****************************************************************************/
605 BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
606 {
607         struct group *grp;
608
609         if(!init_group_mapping()) {
610                 DEBUG(0,("failed to initialize group mapping"));
611                 return(False);
612         }
613
614         if ( (grp=getgrgid(gid)) == NULL)
615                 return False;
616
617         /*
618          * make a group map from scratch if doesn't exist.
619          */
620         if (!pdb_getgrgid(map, gid)) {
621                 map->gid=gid;
622                 map->sid_name_use=SID_NAME_ALIAS;
623
624                 /* interim solution until we have a last RID allocated */
625
626                 sid_copy(&map->sid, get_global_sam_sid());
627                 sid_append_rid(&map->sid, pdb_gid_to_group_rid(gid));
628
629                 fstrcpy(map->nt_name, grp->gr_name);
630                 fstrcpy(map->comment, "Local Unix Group");
631         }
632         
633         return True;
634 }
635
636
637
638
639 /****************************************************************************
640  Get the member users of a group and
641  all the users who have that group as primary.
642             
643  give back an array of uid
644  return the grand number of users
645
646
647  TODO: sort the list and remove duplicate. JFM.
648
649 ****************************************************************************/
650         
651 BOOL get_uid_list_of_group(gid_t gid, uid_t **uid, int *num_uids)
652 {
653         struct group *grp;
654         struct passwd *pwd;
655         int i=0;
656         char *gr;
657         uid_t *u;
658  
659         if(!init_group_mapping()) {
660                 DEBUG(0,("failed to initialize group mapping"));
661                 return(False);
662         }
663
664         *num_uids = 0;
665         *uid=NULL;
666         
667         if ( (grp=getgrgid(gid)) == NULL)
668                 return False;
669
670         gr = grp->gr_mem[0];
671         DEBUG(10, ("getting members\n"));
672         
673         while (gr && (*gr != (char)'\0')) {
674                 u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
675                 if (!u) {
676                         DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
677                         return False;
678                 }
679                 else (*uid) = u;
680
681                 if( (pwd=getpwnam_alloc(gr)) !=NULL) {
682                         (*uid)[*num_uids]=pwd->pw_uid;
683                         (*num_uids)++;
684                         passwd_free(&pwd);
685                 }
686                 gr = grp->gr_mem[++i];
687         }
688         DEBUG(10, ("got [%d] members\n", *num_uids));
689
690         setpwent();
691         while ((pwd=getpwent()) != NULL) {
692                 if (pwd->pw_gid==gid) {
693                         u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
694                         if (!u) {
695                                 DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
696                                 return False;
697                         }
698                         else (*uid) = u;
699                         (*uid)[*num_uids]=pwd->pw_uid;
700
701                         (*num_uids)++;
702                 }
703         }
704         endpwent();
705         DEBUG(10, ("got primary groups, members: [%d]\n", *num_uids));
706
707         return True;
708 }
709
710 /****************************************************************************
711  Create a UNIX group on demand.
712 ****************************************************************************/
713
714 int smb_create_group(char *unix_group, gid_t *new_gid)
715 {
716         pstring add_script;
717         int     ret = -1;
718         int     fd = 0;
719         
720         *new_gid = 0;
721
722         /* defer to scripts */
723         
724         if ( *lp_addgroup_script() ) {
725                 pstrcpy(add_script, lp_addgroup_script());
726                 pstring_sub(add_script, "%g", unix_group);
727                 ret = smbrun(add_script, (new_gid!=NULL) ? &fd : NULL);
728                 DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
729                 if (ret != 0)
730                         return ret;
731                         
732                 if (fd != 0) {
733                         fstring output;
734
735                         *new_gid = 0;
736                         if (read(fd, output, sizeof(output)) > 0) {
737                                 *new_gid = (gid_t)strtoul(output, NULL, 10);
738                         }
739                         
740                         close(fd);
741                 }
742         }
743
744         /* Try winbindd */
745
746         if ( winbind_create_group( unix_group, NULL ) ) {
747                 DEBUG(3,("smb_create_group: winbindd created the group (%s)\n",
748                         unix_group));
749                 ret = 0;
750         }
751         
752         if (*new_gid == 0) {
753                 struct group *grp = getgrnam(unix_group);
754
755                 if (grp != NULL)
756                         *new_gid = grp->gr_gid;
757         }
758                         
759         return ret;     
760 }
761
762 /****************************************************************************
763  Delete a UNIX group on demand.
764 ****************************************************************************/
765
766 int smb_delete_group(char *unix_group)
767 {
768         pstring del_script;
769         int ret;
770
771         /* defer to scripts */
772         
773         if ( *lp_delgroup_script() ) {
774                 pstrcpy(del_script, lp_delgroup_script());
775                 pstring_sub(del_script, "%g", unix_group);
776                 ret = smbrun(del_script,NULL);
777                 DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
778                 return ret;
779         }
780
781         if ( winbind_delete_group( unix_group ) ) {
782                 DEBUG(3,("smb_delete_group: winbindd deleted the group (%s)\n",
783                         unix_group));
784                 return 0;
785         }
786                 
787         return -1;
788 }
789
790 /****************************************************************************
791  Set a user's primary UNIX group.
792 ****************************************************************************/
793 int smb_set_primary_group(const char *unix_group, const char* unix_user)
794 {
795         pstring add_script;
796         int ret;
797
798         /* defer to scripts */
799         
800         if ( *lp_setprimarygroup_script() ) {
801                 pstrcpy(add_script, lp_setprimarygroup_script());
802                 all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
803                 all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
804                 ret = smbrun(add_script,NULL);
805                 DEBUG(3,("smb_set_primary_group: "
806                          "Running the command `%s' gave %d\n",add_script,ret));
807                 return ret;
808         }
809
810         /* Try winbindd */
811         
812         if ( winbind_set_user_primary_group( unix_user, unix_group ) ) {
813                 DEBUG(3,("smb_delete_group: winbindd set the group (%s) as the primary group for user (%s)\n",
814                         unix_group, unix_user));
815                 return 0;
816         }               
817         
818         return -1;
819 }
820
821 /****************************************************************************
822  Add a user to a UNIX group.
823 ****************************************************************************/
824
825 int smb_add_user_group(char *unix_group, char *unix_user)
826 {
827         pstring add_script;
828         int ret;
829
830         /* defer to scripts */
831         
832         if ( *lp_addusertogroup_script() ) {
833                 pstrcpy(add_script, lp_addusertogroup_script());
834                 pstring_sub(add_script, "%g", unix_group);
835                 pstring_sub(add_script, "%u", unix_user);
836                 ret = smbrun(add_script,NULL);
837                 DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
838                 return ret;
839         }
840         
841         /* Try winbindd */
842
843         if ( winbind_add_user_to_group( unix_user, unix_group ) ) {
844                 DEBUG(3,("smb_delete_group: winbindd added user (%s) to the group (%s)\n",
845                         unix_user, unix_group));
846                 return -1;
847         }       
848         
849         return -1;
850 }
851
852 /****************************************************************************
853  Delete a user from a UNIX group
854 ****************************************************************************/
855
856 int smb_delete_user_group(const char *unix_group, const char *unix_user)
857 {
858         pstring del_script;
859         int ret;
860
861         /* defer to scripts */
862         
863         if ( *lp_deluserfromgroup_script() ) {
864                 pstrcpy(del_script, lp_deluserfromgroup_script());
865                 pstring_sub(del_script, "%g", unix_group);
866                 pstring_sub(del_script, "%u", unix_user);
867                 ret = smbrun(del_script,NULL);
868                 DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
869                 return ret;
870         }
871         
872         /* Try winbindd */
873
874         if ( winbind_remove_user_from_group( unix_user, unix_group ) ) {
875                 DEBUG(3,("smb_delete_group: winbindd removed user (%s) from the group (%s)\n",
876                         unix_user, unix_group));
877                 return 0;
878         }
879         
880         return -1;
881 }
882
883
884 NTSTATUS pdb_default_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
885                                  DOM_SID sid)
886 {
887         return get_group_map_from_sid(sid, map) ?
888                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
889 }
890
891 NTSTATUS pdb_default_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
892                                  gid_t gid)
893 {
894         return get_group_map_from_gid(gid, map) ?
895                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
896 }
897
898 NTSTATUS pdb_default_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
899                                  const char *name)
900 {
901         return get_group_map_from_ntname(name, map) ?
902                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
903 }
904
905 NTSTATUS pdb_default_add_group_mapping_entry(struct pdb_methods *methods,
906                                                 GROUP_MAP *map)
907 {
908         return add_mapping_entry(map, TDB_INSERT) ?
909                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
910 }
911
912 NTSTATUS pdb_default_update_group_mapping_entry(struct pdb_methods *methods,
913                                                    GROUP_MAP *map)
914 {
915         return add_mapping_entry(map, TDB_REPLACE) ?
916                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
917 }
918
919 NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods,
920                                                    DOM_SID sid)
921 {
922         return group_map_remove(sid) ?
923                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
924 }
925
926 NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods,
927                                            enum SID_NAME_USE sid_name_use,
928                                            GROUP_MAP **rmap, int *num_entries,
929                                            BOOL unix_only)
930 {
931         return enum_group_mapping(sid_name_use, rmap, num_entries, unix_only) ?
932                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
933 }
934
935 /**********************************************************************
936  no ops for passdb backends that don't implement group mapping
937  *********************************************************************/
938
939 NTSTATUS pdb_nop_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
940                                  DOM_SID sid)
941 {
942         return NT_STATUS_UNSUCCESSFUL;
943 }
944
945 NTSTATUS pdb_nop_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
946                                  gid_t gid)
947 {
948         return NT_STATUS_UNSUCCESSFUL;
949 }
950
951 NTSTATUS pdb_nop_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
952                                  const char *name)
953 {
954         return NT_STATUS_UNSUCCESSFUL;
955 }
956
957 NTSTATUS pdb_nop_add_group_mapping_entry(struct pdb_methods *methods,
958                                                 GROUP_MAP *map)
959 {
960         return NT_STATUS_UNSUCCESSFUL;
961 }
962
963 NTSTATUS pdb_nop_update_group_mapping_entry(struct pdb_methods *methods,
964                                                    GROUP_MAP *map)
965 {
966         return NT_STATUS_UNSUCCESSFUL;
967 }
968
969 NTSTATUS pdb_nop_delete_group_mapping_entry(struct pdb_methods *methods,
970                                                    DOM_SID sid)
971 {
972         return NT_STATUS_UNSUCCESSFUL;
973 }
974
975 NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods,
976                                            enum SID_NAME_USE sid_name_use,
977                                            GROUP_MAP **rmap, int *num_entries,
978                                            BOOL unix_only)
979 {
980         return NT_STATUS_UNSUCCESSFUL;
981 }
982