groupdb/mapping.c: Fix gcc compiler warning.
[ira/wip.git] / source / groupdb / mapping.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2001.
7  *  
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *  
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *  
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "includes.h"
24
25 extern int DEBUGLEVEL;
26 extern DOM_SID global_sam_sid;
27
28 static TDB_CONTEXT *tdb; /* used for driver files */
29
30 #define DATABASE_VERSION 1
31 #define GROUP_PREFIX "UNIXGROUP/"
32
33 PRIVS privs[] = {
34         {SE_PRIV_NONE, "no_privs", "No privilege"},
35         {SE_PRIV_ADD_USERS, "add_users", "add users"},
36         {SE_PRIV_ADD_MACHINES, "add_computers", ""},
37         {SE_PRIV_PRINT_OPERATOR, "print_op", ""},
38         {SE_PRIV_ALL, "all_privs", ""}
39 };
40 /*
41 PRIVS privs[] = {
42         {  2, "SeCreateTokenPrivilege" },
43         {  3, "SeAssignPrimaryTokenPrivilege" },
44         {  4, "SeLockMemoryPrivilege" },
45         {  5, "SeIncreaseQuotaPrivilege" },
46         {  6, "SeMachineAccountPrivilege" },
47         {  7, "SeTcbPrivilege" },
48         {  8, "SeSecurityPrivilege" },
49         {  9, "SeTakeOwnershipPrivilege" },
50         { 10, "SeLoadDriverPrivilege" },
51         { 11, "SeSystemProfilePrivilege" },
52         { 12, "SeSystemtimePrivilege" },
53         { 13, "SeProfileSingleProcessPrivilege" },
54         { 14, "SeIncreaseBasePriorityPrivilege" },
55         { 15, "SeCreatePagefilePrivilege" },
56         { 16, "SeCreatePermanentPrivilege" },
57         { 17, "SeBackupPrivilege" },
58         { 18, "SeRestorePrivilege" },
59         { 19, "SeShutdownPrivilege" },
60         { 20, "SeDebugPrivilege" },
61         { 21, "SeAuditPrivilege" },
62         { 22, "SeSystemEnvironmentPrivilege" },
63         { 23, "SeChangeNotifyPrivilege" },
64         { 24, "SeRemoteShutdownPrivilege" },
65 };
66 */
67
68 #if 0
69 /****************************************************************************
70 check if the user has the required privilege.
71 ****************************************************************************/
72 static BOOL se_priv_access_check(NT_USER_TOKEN *token, uint32 privilege)
73 {
74         /* no token, no privilege */
75         if (token==NULL)
76                 return False;
77         
78         if ((token->privilege & privilege)==privilege)
79                 return True;
80         
81         return False;
82 }
83 #endif
84
85 /****************************************************************************
86 dump the mapping group mapping to a text file
87 ****************************************************************************/
88 char *decode_sid_name_use(fstring group, enum SID_NAME_USE name_use)
89 {       
90         static fstring group_type;
91
92         switch(name_use) {
93                 case SID_NAME_USER:
94                         fstrcpy(group_type,"User");
95                         break;
96                 case SID_NAME_DOM_GRP:
97                         fstrcpy(group_type,"Domain group");
98                         break;
99                 case SID_NAME_DOMAIN:
100                         fstrcpy(group_type,"Domain");
101                         break;
102                 case SID_NAME_ALIAS:
103                         fstrcpy(group_type,"Local group");
104                         break;
105                 case SID_NAME_WKN_GRP:
106                         fstrcpy(group_type,"Builtin group");
107                         break;
108                 case SID_NAME_DELETED:
109                         fstrcpy(group_type,"Deleted");
110                         break;
111                 case SID_NAME_INVALID:
112                         fstrcpy(group_type,"Invalid");
113                         break;
114                 case SID_NAME_UNKNOWN:
115                 default:
116                         fstrcpy(group_type,"Unknown type");
117                         break;
118         }
119         
120         fstrcpy(group, group_type);
121         return group_type;
122 }
123
124 /****************************************************************************
125 open the group mapping tdb
126 ****************************************************************************/
127 BOOL init_group_mapping(void)
128 {
129         static pid_t local_pid;
130         char *vstring = "INFO/version";
131
132         if (tdb && local_pid == sys_getpid()) return True;
133         tdb = tdb_open(lock_path("group_mapping.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
134         if (!tdb) {
135                 DEBUG(0,("Failed to open group mapping database\n"));
136                 return False;
137         }
138
139         local_pid = sys_getpid();
140
141         /* handle a Samba upgrade */
142         tdb_lock_bystring(tdb, vstring);
143         if (tdb_fetch_int(tdb, vstring) != DATABASE_VERSION) {
144                 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
145                 tdb_store_int(tdb, vstring, DATABASE_VERSION);
146         }
147         tdb_unlock_bystring(tdb, vstring);
148
149
150         return True;
151 }
152
153 /****************************************************************************
154 ****************************************************************************/
155 BOOL add_mapping_entry(GROUP_MAP *map, int flag)
156 {
157         TDB_DATA kbuf, dbuf;
158         pstring key, buf;
159         fstring string_sid;
160         int len;
161         
162         sid_to_string(string_sid, &map->sid);
163
164         len = tdb_pack(buf, sizeof(buf), "ddffd",
165                         map->gid, map->sid_name_use, map->nt_name, map->comment, map->privilege);
166
167         if (len > sizeof(buf)) return False;
168
169         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
170
171         kbuf.dsize = strlen(key)+1;
172         kbuf.dptr = key;
173         dbuf.dsize = len;
174         dbuf.dptr = buf;
175         if (tdb_store(tdb, kbuf, dbuf, flag) != 0) return False;
176
177         return True;
178 }
179
180 /****************************************************************************
181 initialise first time the mapping list
182 ****************************************************************************/
183 BOOL add_initial_entry(gid_t gid, fstring sid, enum SID_NAME_USE sid_name_use,
184                               fstring nt_name, fstring comment, uint32 privilege)
185 {
186         GROUP_MAP map;
187
188         map.gid=gid;
189         string_to_sid(&map.sid, sid);
190         map.sid_name_use=sid_name_use;
191         fstrcpy(map.nt_name, nt_name);
192         fstrcpy(map.comment, comment);
193         map.privilege=privilege;
194
195         add_mapping_entry(&map, TDB_INSERT);
196
197         return True;
198 }
199
200 /****************************************************************************
201 initialise first time the mapping list
202 ****************************************************************************/
203 BOOL default_group_mapping(void)
204 {
205         DOM_SID sid_admins;
206         DOM_SID sid_users;
207         DOM_SID sid_guests;
208         fstring str_admins;
209         fstring str_users;
210         fstring str_guests;
211
212
213         /* Add the Wellknown groups */
214
215         add_initial_entry(-1, "S-1-5-32-544", SID_NAME_WKN_GRP, "Administrators", "", SE_PRIV_ALL);
216         add_initial_entry(-1, "S-1-5-32-545", SID_NAME_WKN_GRP, "Users", "", SE_PRIV_NONE);
217         add_initial_entry(-1, "S-1-5-32-546", SID_NAME_WKN_GRP, "Guests", "", SE_PRIV_NONE);
218         add_initial_entry(-1, "S-1-5-32-547", SID_NAME_WKN_GRP, "Power Users", "", SE_PRIV_NONE);
219
220         add_initial_entry(-1, "S-1-5-32-548", SID_NAME_WKN_GRP, "Account Operators", "", SE_PRIV_NONE);
221         add_initial_entry(-1, "S-1-5-32-549", SID_NAME_WKN_GRP, "System Operators", "", SE_PRIV_NONE);
222         add_initial_entry(-1, "S-1-5-32-550", SID_NAME_WKN_GRP, "Print Operators", "", SE_PRIV_PRINT_OPERATOR);
223         add_initial_entry(-1, "S-1-5-32-551", SID_NAME_WKN_GRP, "Backup Operators", "", SE_PRIV_NONE);
224
225         add_initial_entry(-1, "S-1-5-32-552", SID_NAME_WKN_GRP, "Replicators", "", SE_PRIV_NONE);
226
227         /* Add the defaults domain groups */
228
229         sid_copy(&sid_admins, &global_sam_sid);
230         sid_append_rid(&sid_admins, DOMAIN_GROUP_RID_ADMINS);
231         sid_to_string(str_admins, &sid_admins);
232         add_initial_entry(-1, str_admins, SID_NAME_DOM_GRP, "Domain Admins", "", SE_PRIV_ALL);
233
234         sid_copy(&sid_users,  &global_sam_sid);
235         sid_append_rid(&sid_users,  DOMAIN_GROUP_RID_USERS);
236         sid_to_string(str_users, &sid_users);
237         add_initial_entry(-1, str_users,  SID_NAME_DOM_GRP, "Domain Users",  "", SE_PRIV_NONE);
238
239         sid_copy(&sid_guests, &global_sam_sid);
240         sid_append_rid(&sid_guests, DOMAIN_GROUP_RID_GUESTS);
241         sid_to_string(str_guests, &sid_guests);
242         add_initial_entry(-1, str_guests, SID_NAME_DOM_GRP, "Domain Guests", "", SE_PRIV_NONE);
243
244         return True;
245 }
246
247
248 /****************************************************************************
249 return the sid and the type of the unix group
250 ****************************************************************************/
251 BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
252 {
253         TDB_DATA kbuf, dbuf;
254         pstring key;
255         fstring string_sid;
256         int ret;
257         
258         /* the key is the SID, retrieving is direct */
259
260         sid_to_string(string_sid, &sid);
261         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
262
263         kbuf.dptr = key;
264         kbuf.dsize = strlen(key)+1;
265                 
266         dbuf = tdb_fetch(tdb, kbuf);
267         if (!dbuf.dptr) return False;
268
269         ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
270                                 &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->privilege);
271
272         safe_free(dbuf.dptr);
273         if (ret != dbuf.dsize) {
274                 DEBUG(0,("get_group_map_from_sid: mapping TDB corrupted ?\n"));
275                 return False;
276         }
277
278         sid_copy(&map->sid, &sid);
279         
280         return True;
281 }
282
283
284 /****************************************************************************
285 return the sid and the type of the unix group
286 ****************************************************************************/
287 BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
288 {
289         TDB_DATA kbuf, dbuf, newkey;
290         fstring string_sid;
291         int ret;
292
293         /* we need to enumerate the TDB to find the GID */
294
295         for (kbuf = tdb_firstkey(tdb); 
296              kbuf.dptr; 
297              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
298
299                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
300                 
301                 dbuf = tdb_fetch(tdb, kbuf);
302                 if (!dbuf.dptr) continue;
303
304                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
305
306                 string_to_sid(&map->sid, string_sid);
307                 
308                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
309                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->privilege);
310
311                 safe_free(dbuf.dptr);
312                 if (ret != dbuf.dsize) continue;
313
314                 if (gid==map->gid)
315                         return True;
316         }
317
318         return False;
319 }
320
321 /****************************************************************************
322 return the sid and the type of the unix group
323 ****************************************************************************/
324 BOOL get_group_map_from_ntname(char *name, GROUP_MAP *map)
325 {
326         TDB_DATA kbuf, dbuf, newkey;
327         fstring string_sid;
328         int ret;
329
330         /* we need to enumerate the TDB to find the GID */
331
332         for (kbuf = tdb_firstkey(tdb); 
333              kbuf.dptr; 
334              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
335
336                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
337                 
338                 dbuf = tdb_fetch(tdb, kbuf);
339                 if (!dbuf.dptr) continue;
340
341                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
342
343                 string_to_sid(&map->sid, string_sid);
344                 
345                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
346                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->privilege);
347
348                 safe_free(dbuf.dptr);
349                 if (ret != dbuf.dsize) continue;
350
351                 if (StrCaseCmp(name, map->nt_name)==0)
352                         return True;
353
354         }
355
356         return False;
357 }
358
359 /****************************************************************************
360 enumerate the group mapping
361 ****************************************************************************/
362 BOOL group_map_remove(DOM_SID sid)
363 {
364         TDB_DATA kbuf, dbuf;
365         pstring key;
366         fstring string_sid;
367         
368         /* the key is the SID, retrieving is direct */
369
370         sid_to_string(string_sid, &sid);
371         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
372
373         kbuf.dptr = key;
374         kbuf.dsize = strlen(key)+1;
375                 
376         dbuf = tdb_fetch(tdb, kbuf);
377         if (!dbuf.dptr) return False;
378         
379         safe_free(dbuf.dptr);
380
381         if(tdb_delete(tdb, kbuf) != TDB_SUCCESS)
382                 return False;
383
384         return True;
385 }
386
387
388 /****************************************************************************
389 enumerate the group mapping
390 ****************************************************************************/
391 BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
392                         int *num_entries, BOOL unix_only)
393 {
394         TDB_DATA kbuf, dbuf, newkey;
395         fstring string_sid;
396         fstring group_type;
397         GROUP_MAP map;
398         GROUP_MAP *mapt=NULL;
399         int ret;
400         int entries=0;
401
402         *num_entries=0;
403         *rmap=NULL;
404
405         for (kbuf = tdb_firstkey(tdb); 
406              kbuf.dptr; 
407              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
408
409                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0)
410                         continue;
411                 
412                 dbuf = tdb_fetch(tdb, kbuf);
413                 if (!dbuf.dptr)
414                         continue;
415
416                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
417                                 
418                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
419                                  &map.gid, &map.sid_name_use, &map.nt_name, &map.comment, &map.privilege);
420
421                 safe_free(dbuf.dptr);
422                 if (ret != dbuf.dsize)
423                         continue;
424
425                 /* list only the type or everything if UNKNOWN */
426                 if (sid_name_use!=SID_NAME_UNKNOWN  && sid_name_use!=map.sid_name_use)
427                         continue;
428
429                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1)
430                         continue;
431
432                 string_to_sid(&map.sid, string_sid);
433                 
434                 decode_sid_name_use(group_type, map.sid_name_use);
435
436                 mapt=(GROUP_MAP *)Realloc(mapt, (entries+1)*sizeof(GROUP_MAP));
437
438                 mapt[entries].gid = map.gid;
439                 sid_copy( &mapt[entries].sid, &map.sid);
440                 mapt[entries].sid_name_use = map.sid_name_use;
441                 fstrcpy(mapt[entries].nt_name, map.nt_name);
442                 fstrcpy(mapt[entries].comment, map.comment);
443                 mapt[entries].privilege = map.privilege;
444
445                 entries++;
446         }
447
448         *rmap=mapt;
449         *num_entries=entries;
450         return True;
451 }
452
453
454 /****************************************************************************
455 convert a privilege list to a privilege value
456 ****************************************************************************/
457 void convert_priv_from_text(uint32 *se_priv, char *privilege)
458 {
459         pstring tok;
460         char *p = privilege;
461         int i;
462
463         /* By default no privilege */
464         (*se_priv)=0x0;
465
466         if (privilege==NULL)
467                 return;
468
469         while(next_token(&p, tok, " ", sizeof(tok)) ) {
470                 for (i=0; i<=PRIV_ALL_INDEX; i++) {
471                         if (StrCaseCmp(privs[i].priv, tok)==0)
472                                 (*se_priv)+=privs[i].se_priv;
473                 }               
474         }
475 }
476
477 /****************************************************************************
478 convert a privilege value to a privilege list
479 ****************************************************************************/
480 void convert_priv_to_text(uint32 se_priv, char *privilege)
481 {
482         int i;
483
484         if (privilege==NULL)
485                 return;
486
487         ZERO_STRUCTP(privilege);
488
489         if (se_priv==SE_PRIV_NONE) {
490                 fstrcat(privilege, privs[0].priv);
491                 return;
492         }
493
494         if (se_priv==SE_PRIV_ALL) {
495                 fstrcat(privilege, privs[PRIV_ALL_INDEX].priv);
496                 return;
497         }
498
499         for (i=1; privs[i].se_priv!=SE_PRIV_ALL; i++) {
500                 if ( (se_priv & privs[i].se_priv) == privs[i].se_priv) {
501                         fstrcat(privilege, privs[i].priv);
502                         fstrcat(privilege, " ");
503                 }
504         }
505 }
506
507
508 /*
509  *
510  * High level functions
511  * better to use them than the lower ones.
512  *
513  * we are checking if the group is in the mapping file
514  * and if the group is an existing unix group
515  *
516  */
517
518 /* get a domain group from it's SID */
519
520 BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
521 {
522         struct group *grp;
523
524         DEBUG(10, ("get_domain_group_from_sid\n"));
525
526         /* if the group is NOT in the database, it CAN NOT be a domain group */
527         if(!get_group_map_from_sid(sid, map))
528                 return False;
529
530         DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
531
532         /* if it's not a domain group, continue */
533         if (map->sid_name_use!=SID_NAME_DOM_GRP)
534                 return False;
535
536         DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n"));
537         
538         if (map->gid==-1)
539                 return False;
540
541         DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%d\n",map->gid));
542
543         if ( (grp=getgrgid(map->gid)) == NULL)
544                 return False;
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         struct group *grp;
557
558         /* The group is in the mapping table */
559         if(get_group_map_from_sid(sid, map)) {
560                 if (map->sid_name_use!=SID_NAME_ALIAS)
561                         return False;
562         
563                 if (map->gid==-1)
564                         return False;
565
566                 if ( (grp=getgrgid(map->gid)) == NULL)
567                         return False;
568         } else {
569                 /* the group isn't in the mapping table.
570                  * make one based on the unix information */
571                 uint32 alias_rid;
572
573                 sid_split_rid(&sid, &alias_rid);
574                 map->gid=pdb_user_rid_to_gid(alias_rid);
575
576                 if ((grp=getgrgid(map->gid)) == NULL)
577                         return False;
578
579                 map->sid_name_use=SID_NAME_ALIAS;
580
581                 fstrcpy(map->nt_name, grp->gr_name);
582                 fstrcpy(map->comment, "Local Unix Group");
583
584                 map->privilege=SE_PRIV_NONE;
585
586         }
587
588         return True;
589 }
590
591 /* get a builtin group from it's SID */
592
593 BOOL get_builtin_group_from_sid(DOM_SID sid, GROUP_MAP *map)
594 {
595         struct group *grp;
596
597         if(!get_group_map_from_sid(sid, map))
598                 return False;
599
600         if (map->sid_name_use!=SID_NAME_WKN_GRP)
601                 return False;
602
603         if (map->gid==-1)
604                 return False;
605
606         if ( (grp=getgrgid(map->gid)) == NULL)
607                 return False;
608
609         return True;
610 }
611
612
613
614 /****************************************************************************
615 Returns a GROUP_MAP struct based on the gid.
616 ****************************************************************************/
617 BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
618 {
619         struct group *grp;
620
621         if ( (grp=getgrgid(gid)) == NULL)
622                 return False;
623
624         /*
625          * make a group map from scratch if doesn't exist.
626          */
627         if (!get_group_map_from_gid(gid, map)) {
628                 map->gid=gid;
629                 map->sid_name_use=SID_NAME_ALIAS;
630                 map->privilege=SE_PRIV_NONE;
631
632                 sid_copy(&map->sid, &global_sam_sid);
633                 sid_append_rid(&map->sid, pdb_gid_to_group_rid(gid));
634
635                 fstrcpy(map->nt_name, grp->gr_name);
636                 fstrcpy(map->comment, "Local Unix Group");
637         }
638         
639         return True;
640 }
641
642
643
644
645 /****************************************************************************
646  Get the member users of a group and
647  all the users who have that group as primary.
648             
649  give back an array of uid
650  return the grand number of users
651
652
653  TODO: sort the list and remove duplicate. JFM.
654
655 ****************************************************************************/
656         
657 BOOL get_uid_list_of_group(gid_t gid, uid_t **uid, int *num_uids)
658 {
659         struct group *grp;
660         struct passwd *pwd;
661         int i=0;
662         char *gr;
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                 (*uid)=Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
675
676                 if( (pwd=getpwnam(gr)) !=NULL) {
677                         (*uid)[*num_uids]=pwd->pw_uid;
678                         (*num_uids)++;
679                 }
680                 gr = grp->gr_mem[++i];
681         }
682         DEBUG(10, ("got [%d] members\n", *num_uids));
683
684         setpwent();
685         while ((pwd=getpwent()) != NULL) {
686                 if (pwd->pw_gid==gid) {
687                         (*uid)=Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
688                         (*uid)[*num_uids]=pwd->pw_uid;
689
690                         (*num_uids)++;
691                 }
692         }
693         endpwent();
694         DEBUG(10, ("got primary groups, members: [%d]\n", *num_uids));
695
696         return True;
697 }
698
699 /****************************************************************************
700  Create a UNIX group on demand.
701 ****************************************************************************/
702
703 int smb_create_group(char *unix_group)
704 {
705         pstring add_script;
706         int ret;
707
708         pstrcpy(add_script, lp_addgroup_script());
709         if (! *add_script) return -1;
710         pstring_sub(add_script, "%g", unix_group);
711         ret = smbrun(add_script,NULL);
712         DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
713         return ret;
714 }
715
716 /****************************************************************************
717  Delete a UNIX group on demand.
718 ****************************************************************************/
719
720 int smb_delete_group(char *unix_group)
721 {
722         pstring del_script;
723         int ret;
724
725         pstrcpy(del_script, lp_delgroup_script());
726         if (! *del_script) return -1;
727         pstring_sub(del_script, "%g", unix_group);
728         ret = smbrun(del_script,NULL);
729         DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
730         return ret;
731 }
732
733 /****************************************************************************
734  Create a UNIX group on demand.
735 ****************************************************************************/
736
737 int smb_add_user_group(char *unix_group, char *unix_user)
738 {
739         pstring add_script;
740         int ret;
741
742         pstrcpy(add_script, lp_addusertogroup_script());
743         if (! *add_script) return -1;
744         pstring_sub(add_script, "%g", unix_group);
745         pstring_sub(add_script, "%u", unix_user);
746         ret = smbrun(add_script,NULL);
747         DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
748         return ret;
749 }
750
751 /****************************************************************************
752  Delete a UNIX group on demand.
753 ****************************************************************************/
754
755 int smb_delete_user_group(char *unix_group, char *unix_user)
756 {
757         pstring del_script;
758         int ret;
759
760         pstrcpy(del_script, lp_deluserfromgroup_script());
761         if (! *del_script) return -1;
762         pstring_sub(del_script, "%g", unix_group);
763         pstring_sub(del_script, "%u", unix_user);
764         ret = smbrun(del_script,NULL);
765         DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
766         return ret;
767 }
768
769
770