r7130: remove 'winbind enable local accounts' code from the 3.0 tree
[kai/samba.git] / source3 / groupdb / mapping.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2001.
6  *  
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *  
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *  
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include "includes.h"
23
24 static TDB_CONTEXT *tdb; /* used for driver files */
25
26 #define DATABASE_VERSION_V1 1 /* native byte format. */
27 #define DATABASE_VERSION_V2 2 /* le format. */
28
29 #define GROUP_PREFIX "UNIXGROUP/"
30
31 /* Alias memberships are stored reverse, as memberships. The performance
32  * critical operation is to determine the aliases a SID is member of, not
33  * listing alias members. So we store a list of alias SIDs a SID is member of
34  * hanging of the member as key.
35  */
36 #define MEMBEROF_PREFIX "MEMBEROF/"
37
38 /****************************************************************************
39 dump the mapping group mapping to a text file
40 ****************************************************************************/
41 char *decode_sid_name_use(fstring group, enum SID_NAME_USE name_use)
42 {       
43         static fstring group_type;
44
45         switch(name_use) {
46                 case SID_NAME_USER:
47                         fstrcpy(group_type,"User");
48                         break;
49                 case SID_NAME_DOM_GRP:
50                         fstrcpy(group_type,"Domain group");
51                         break;
52                 case SID_NAME_DOMAIN:
53                         fstrcpy(group_type,"Domain");
54                         break;
55                 case SID_NAME_ALIAS:
56                         fstrcpy(group_type,"Local group");
57                         break;
58                 case SID_NAME_WKN_GRP:
59                         fstrcpy(group_type,"Builtin group");
60                         break;
61                 case SID_NAME_DELETED:
62                         fstrcpy(group_type,"Deleted");
63                         break;
64                 case SID_NAME_INVALID:
65                         fstrcpy(group_type,"Invalid");
66                         break;
67                 case SID_NAME_UNKNOWN:
68                 default:
69                         fstrcpy(group_type,"Unknown type");
70                         break;
71         }
72         
73         fstrcpy(group, group_type);
74         return group_type;
75 }
76
77 /****************************************************************************
78 initialise first time the mapping list - called from init_group_mapping()
79 ****************************************************************************/
80 static BOOL default_group_mapping(void)
81 {
82         DOM_SID sid_admins;
83         DOM_SID sid_users;
84         DOM_SID sid_guests;
85         fstring str_admins;
86         fstring str_users;
87         fstring str_guests;
88
89         /* Add the Wellknown groups */
90
91         add_initial_entry(-1, "S-1-5-32-544", SID_NAME_WKN_GRP, "Administrators", "");
92         add_initial_entry(-1, "S-1-5-32-545", SID_NAME_WKN_GRP, "Users", "");
93         add_initial_entry(-1, "S-1-5-32-546", SID_NAME_WKN_GRP, "Guests", "");
94         add_initial_entry(-1, "S-1-5-32-547", SID_NAME_WKN_GRP, "Power Users", "");
95         add_initial_entry(-1, "S-1-5-32-548", SID_NAME_WKN_GRP, "Account Operators", "");
96         add_initial_entry(-1, "S-1-5-32-549", SID_NAME_WKN_GRP, "System Operators", "");
97         add_initial_entry(-1, "S-1-5-32-550", SID_NAME_WKN_GRP, "Print Operators", "");
98         add_initial_entry(-1, "S-1-5-32-551", SID_NAME_WKN_GRP, "Backup Operators", "");
99         add_initial_entry(-1, "S-1-5-32-552", SID_NAME_WKN_GRP, "Replicators", "");
100
101         /* Add the defaults domain groups */
102
103         sid_copy(&sid_admins, get_global_sam_sid());
104         sid_append_rid(&sid_admins, DOMAIN_GROUP_RID_ADMINS);
105         sid_to_string(str_admins, &sid_admins);
106         add_initial_entry(-1, str_admins, SID_NAME_DOM_GRP, "Domain Admins", "");
107
108         sid_copy(&sid_users,  get_global_sam_sid());
109         sid_append_rid(&sid_users,  DOMAIN_GROUP_RID_USERS);
110         sid_to_string(str_users, &sid_users);
111         add_initial_entry(-1, str_users,  SID_NAME_DOM_GRP, "Domain Users",  "");
112
113         sid_copy(&sid_guests, get_global_sam_sid());
114         sid_append_rid(&sid_guests, DOMAIN_GROUP_RID_GUESTS);
115         sid_to_string(str_guests, &sid_guests);
116         add_initial_entry(-1, str_guests, SID_NAME_DOM_GRP, "Domain Guests", "");
117
118         return True;
119 }
120
121 /****************************************************************************
122  Open the group mapping tdb.
123 ****************************************************************************/
124
125 static BOOL init_group_mapping(void)
126 {
127         const char *vstring = "INFO/version";
128         int32 vers_id;
129         
130         if (tdb)
131                 return True;
132         tdb = tdb_open_log(lock_path("group_mapping.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
133         if (!tdb) {
134                 DEBUG(0,("Failed to open group mapping database\n"));
135                 return False;
136         }
137
138         /* handle a Samba upgrade */
139         tdb_lock_bystring(tdb, vstring, 0);
140
141         /* Cope with byte-reversed older versions of the db. */
142         vers_id = tdb_fetch_int32(tdb, vstring);
143         if ((vers_id == DATABASE_VERSION_V1) || (IREV(vers_id) == DATABASE_VERSION_V1)) {
144                 /* Written on a bigendian machine with old fetch_int code. Save as le. */
145                 tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
146                 vers_id = DATABASE_VERSION_V2;
147         }
148
149         if (vers_id != DATABASE_VERSION_V2) {
150                 tdb_traverse(tdb, tdb_traverse_delete_fn, NULL);
151                 tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
152         }
153
154         tdb_unlock_bystring(tdb, vstring);
155
156         /* write a list of default groups */
157         if(!default_group_mapping())
158                 return False;
159
160         return True;
161 }
162
163 /****************************************************************************
164 ****************************************************************************/
165 static BOOL add_mapping_entry(GROUP_MAP *map, int flag)
166 {
167         TDB_DATA kbuf, dbuf;
168         pstring key, buf;
169         fstring string_sid="";
170         int len;
171
172         if(!init_group_mapping()) {
173                 DEBUG(0,("failed to initialize group mapping\n"));
174                 return(False);
175         }
176         
177         sid_to_string(string_sid, &map->sid);
178
179         len = tdb_pack(buf, sizeof(buf), "ddff",
180                         map->gid, map->sid_name_use, map->nt_name, map->comment);
181
182         if (len > sizeof(buf))
183                 return False;
184
185         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
186
187         kbuf.dsize = strlen(key)+1;
188         kbuf.dptr = key;
189         dbuf.dsize = len;
190         dbuf.dptr = buf;
191         if (tdb_store(tdb, kbuf, dbuf, flag) != 0) return False;
192
193         return True;
194 }
195
196 /****************************************************************************
197 initialise first time the mapping list
198 ****************************************************************************/
199 BOOL add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_use, const char *nt_name, const char *comment)
200 {
201         GROUP_MAP map;
202
203         if(!init_group_mapping()) {
204                 DEBUG(0,("failed to initialize group mapping\n"));
205                 return(False);
206         }
207         
208         map.gid=gid;
209         if (!string_to_sid(&map.sid, sid)) {
210                 DEBUG(0, ("string_to_sid failed: %s", sid));
211                 return False;
212         }
213         
214         map.sid_name_use=sid_name_use;
215         fstrcpy(map.nt_name, nt_name);
216         fstrcpy(map.comment, comment);
217
218         return pdb_add_group_mapping_entry(&map);
219 }
220
221 /****************************************************************************
222  Return the sid and the type of the unix group.
223 ****************************************************************************/
224
225 static BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
226 {
227         TDB_DATA kbuf, dbuf;
228         pstring key;
229         fstring string_sid;
230         int ret = 0;
231         
232         if(!init_group_mapping()) {
233                 DEBUG(0,("failed to initialize group mapping\n"));
234                 return(False);
235         }
236
237         /* the key is the SID, retrieving is direct */
238
239         sid_to_string(string_sid, &sid);
240         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
241
242         kbuf.dptr = key;
243         kbuf.dsize = strlen(key)+1;
244                 
245         dbuf = tdb_fetch(tdb, kbuf);
246         if (!dbuf.dptr)
247                 return False;
248
249         ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
250                                 &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
251
252         SAFE_FREE(dbuf.dptr);
253         
254         if ( ret == -1 ) {
255                 DEBUG(3,("get_group_map_from_sid: tdb_unpack failure\n"));
256                 return False;
257         }
258
259         sid_copy(&map->sid, &sid);
260         
261         return True;
262 }
263
264 /****************************************************************************
265  Return the sid and the type of the unix group.
266 ****************************************************************************/
267
268 static BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
269 {
270         TDB_DATA kbuf, dbuf, newkey;
271         fstring string_sid;
272         int ret;
273
274         if(!init_group_mapping()) {
275                 DEBUG(0,("failed to initialize group mapping\n"));
276                 return(False);
277         }
278
279         /* we need to enumerate the TDB to find the GID */
280
281         for (kbuf = tdb_firstkey(tdb); 
282              kbuf.dptr; 
283              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
284
285                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
286                 
287                 dbuf = tdb_fetch(tdb, kbuf);
288                 if (!dbuf.dptr)
289                         continue;
290
291                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
292
293                 string_to_sid(&map->sid, string_sid);
294                 
295                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
296                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
297
298                 SAFE_FREE(dbuf.dptr);
299
300                 if ( ret == -1 ) {
301                         DEBUG(3,("get_group_map_from_gid: tdb_unpack failure\n"));
302                         return False;
303                 }
304         
305                 if (gid==map->gid) {
306                         SAFE_FREE(kbuf.dptr);
307                         return True;
308                 }
309         }
310
311         return False;
312 }
313
314 /****************************************************************************
315  Return the sid and the type of the unix group.
316 ****************************************************************************/
317
318 static BOOL get_group_map_from_ntname(const char *name, GROUP_MAP *map)
319 {
320         TDB_DATA kbuf, dbuf, newkey;
321         fstring string_sid;
322         int ret;
323
324         if(!init_group_mapping()) {
325                 DEBUG(0,("get_group_map_from_ntname:failed to initialize group mapping\n"));
326                 return(False);
327         }
328
329         /* we need to enumerate the TDB to find the name */
330
331         for (kbuf = tdb_firstkey(tdb); 
332              kbuf.dptr; 
333              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
334
335                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
336                 
337                 dbuf = tdb_fetch(tdb, kbuf);
338                 if (!dbuf.dptr)
339                         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, "ddff",
346                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
347
348                 SAFE_FREE(dbuf.dptr);
349                 
350                 if ( ret == -1 ) {
351                         DEBUG(3,("get_group_map_from_ntname: tdb_unpack failure\n"));
352                         return False;
353                 }
354
355                 if (StrCaseCmp(name, map->nt_name)==0) {
356                         SAFE_FREE(kbuf.dptr);
357                         return True;
358                 }
359         }
360
361         return False;
362 }
363
364 /****************************************************************************
365  Remove a group mapping entry.
366 ****************************************************************************/
367
368 static BOOL group_map_remove(DOM_SID sid)
369 {
370         TDB_DATA kbuf, dbuf;
371         pstring key;
372         fstring string_sid;
373         
374         if(!init_group_mapping()) {
375                 DEBUG(0,("failed to initialize group mapping\n"));
376                 return(False);
377         }
378
379         /* the key is the SID, retrieving is direct */
380
381         sid_to_string(string_sid, &sid);
382         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
383
384         kbuf.dptr = key;
385         kbuf.dsize = strlen(key)+1;
386                 
387         dbuf = tdb_fetch(tdb, kbuf);
388         if (!dbuf.dptr)
389                 return False;
390         
391         SAFE_FREE(dbuf.dptr);
392
393         if(tdb_delete(tdb, kbuf) != TDB_SUCCESS)
394                 return False;
395
396         return True;
397 }
398
399 /****************************************************************************
400  Enumerate the group mapping.
401 ****************************************************************************/
402
403 static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
404                         int *num_entries, BOOL unix_only)
405 {
406         TDB_DATA kbuf, dbuf, newkey;
407         fstring string_sid;
408         fstring group_type;
409         GROUP_MAP map;
410         GROUP_MAP *mapt;
411         int ret;
412         int entries=0;
413
414         if(!init_group_mapping()) {
415                 DEBUG(0,("failed to initialize group mapping\n"));
416                 return(False);
417         }
418
419         *num_entries=0;
420         *rmap=NULL;
421
422         for (kbuf = tdb_firstkey(tdb); 
423              kbuf.dptr; 
424              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
425
426                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0)
427                         continue;
428
429                 dbuf = tdb_fetch(tdb, kbuf);
430                 if (!dbuf.dptr)
431                         continue;
432
433                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
434                                 
435                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
436                                  &map.gid, &map.sid_name_use, &map.nt_name, &map.comment);
437
438                 SAFE_FREE(dbuf.dptr);
439
440                 if ( ret == -1 ) {
441                         DEBUG(3,("enum_group_mapping: tdb_unpack failure\n"));
442                         continue;
443                 }
444         
445                 /* list only the type or everything if UNKNOWN */
446                 if (sid_name_use!=SID_NAME_UNKNOWN  && sid_name_use!=map.sid_name_use) {
447                         DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
448                         continue;
449                 }
450
451                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
452                         DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
453                         continue;
454                 }
455
456                 string_to_sid(&map.sid, string_sid);
457                 
458                 decode_sid_name_use(group_type, map.sid_name_use);
459                 DEBUG(11,("enum_group_mapping: returning group %s of type %s\n", map.nt_name ,group_type));
460
461                 mapt= SMB_REALLOC_ARRAY((*rmap), GROUP_MAP, entries+1);
462                 if (!mapt) {
463                         DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
464                         SAFE_FREE(*rmap);
465                         return False;
466                 }
467                 else
468                         (*rmap) = mapt;
469
470                 mapt[entries].gid = map.gid;
471                 sid_copy( &mapt[entries].sid, &map.sid);
472                 mapt[entries].sid_name_use = map.sid_name_use;
473                 fstrcpy(mapt[entries].nt_name, map.nt_name);
474                 fstrcpy(mapt[entries].comment, map.comment);
475
476                 entries++;
477
478         }
479
480         *num_entries=entries;
481
482         return True;
483 }
484
485 /* This operation happens on session setup, so it should better be fast. We
486  * store a list of aliases a SID is member of hanging off MEMBEROF/SID. */
487
488 static NTSTATUS one_alias_membership(const DOM_SID *member,
489                                      DOM_SID **sids, int *num)
490 {
491         fstring key, string_sid;
492         TDB_DATA kbuf, dbuf;
493         const char *p;
494
495         if (!init_group_mapping()) {
496                 DEBUG(0,("failed to initialize group mapping\n"));
497                 return NT_STATUS_ACCESS_DENIED;
498         }
499
500         sid_to_string(string_sid, member);
501         slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, string_sid);
502
503         kbuf.dsize = strlen(key)+1;
504         kbuf.dptr = key;
505
506         dbuf = tdb_fetch(tdb, kbuf);
507
508         if (dbuf.dptr == NULL) {
509                 return NT_STATUS_OK;
510         }
511
512         p = dbuf.dptr;
513
514         while (next_token(&p, string_sid, " ", sizeof(string_sid))) {
515
516                 DOM_SID alias;
517
518                 if (!string_to_sid(&alias, string_sid))
519                         continue;
520
521                 add_sid_to_array_unique(NULL, &alias, sids, num);
522
523                 if (sids == NULL)
524                         return NT_STATUS_NO_MEMORY;
525         }
526
527         SAFE_FREE(dbuf.dptr);
528         return NT_STATUS_OK;
529 }
530
531 static NTSTATUS alias_memberships(const DOM_SID *members, int num_members,
532                                   DOM_SID **sids, int *num)
533 {
534         int i;
535
536         *num = 0;
537         *sids = NULL;
538
539         for (i=0; i<num_members; i++) {
540                 NTSTATUS status = one_alias_membership(&members[i], sids, num);
541                 if (!NT_STATUS_IS_OK(status))
542                         return status;
543         }
544         return NT_STATUS_OK;
545 }
546
547 static BOOL is_aliasmem(const DOM_SID *alias, const DOM_SID *member)
548 {
549         DOM_SID *sids;
550         int i, num;
551
552         /* This feels the wrong way round, but the on-disk data structure
553          * dictates it this way. */
554         if (!NT_STATUS_IS_OK(alias_memberships(member, 1, &sids, &num)))
555                 return False;
556
557         for (i=0; i<num; i++) {
558                 if (sid_compare(alias, &sids[i]) == 0) {
559                         SAFE_FREE(sids);
560                         return True;
561                 }
562         }
563         SAFE_FREE(sids);
564         return False;
565 }
566
567 static NTSTATUS add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
568 {
569         GROUP_MAP map;
570         TDB_DATA kbuf, dbuf;
571         pstring key;
572         fstring string_sid;
573         char *new_memberstring;
574         int result;
575
576         if(!init_group_mapping()) {
577                 DEBUG(0,("failed to initialize group mapping\n"));
578                 return NT_STATUS_ACCESS_DENIED;
579         }
580
581         if (!get_group_map_from_sid(*alias, &map))
582                 return NT_STATUS_NO_SUCH_ALIAS;
583
584         if ( (map.sid_name_use != SID_NAME_ALIAS) &&
585              (map.sid_name_use != SID_NAME_WKN_GRP) )
586                 return NT_STATUS_NO_SUCH_ALIAS;
587
588         if (is_aliasmem(alias, member))
589                 return NT_STATUS_MEMBER_IN_ALIAS;
590
591         sid_to_string(string_sid, member);
592         slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, string_sid);
593
594         kbuf.dsize = strlen(key)+1;
595         kbuf.dptr = key;
596
597         dbuf = tdb_fetch(tdb, kbuf);
598
599         sid_to_string(string_sid, alias);
600
601         if (dbuf.dptr != NULL) {
602                 asprintf(&new_memberstring, "%s %s", (char *)(dbuf.dptr),
603                          string_sid);
604         } else {
605                 new_memberstring = SMB_STRDUP(string_sid);
606         }
607
608         if (new_memberstring == NULL)
609                 return NT_STATUS_NO_MEMORY;
610
611         SAFE_FREE(dbuf.dptr);
612         dbuf.dsize = strlen(new_memberstring)+1;
613         dbuf.dptr = new_memberstring;
614
615         result = tdb_store(tdb, kbuf, dbuf, 0);
616
617         SAFE_FREE(new_memberstring);
618
619         return (result == 0 ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED);
620 }
621
622 struct aliasmem_closure {
623         const DOM_SID *alias;
624         DOM_SID **sids;
625         int *num;
626 };
627
628 static int collect_aliasmem(TDB_CONTEXT *tdb_ctx, TDB_DATA key, TDB_DATA data,
629                             void *state)
630 {
631         struct aliasmem_closure *closure = (struct aliasmem_closure *)state;
632         const char *p;
633         fstring alias_string;
634
635         if (strncmp(key.dptr, MEMBEROF_PREFIX,
636                     strlen(MEMBEROF_PREFIX)) != 0)
637                 return 0;
638
639         p = data.dptr;
640
641         while (next_token(&p, alias_string, " ", sizeof(alias_string))) {
642
643                 DOM_SID alias, member;
644                 const char *member_string;
645                 
646
647                 if (!string_to_sid(&alias, alias_string))
648                         continue;
649
650                 if (sid_compare(closure->alias, &alias) != 0)
651                         continue;
652
653                 /* Ok, we found the alias we're looking for in the membership
654                  * list currently scanned. The key represents the alias
655                  * member. Add that. */
656
657                 member_string = strchr(key.dptr, '/');
658
659                 /* Above we tested for MEMBEROF_PREFIX which includes the
660                  * slash. */
661
662                 SMB_ASSERT(member_string != NULL);
663                 member_string += 1;
664
665                 if (!string_to_sid(&member, member_string))
666                         continue;
667                 
668                 add_sid_to_array(NULL, &member, closure->sids, closure->num);
669         }
670
671         return 0;
672 }
673
674 static NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, int *num)
675 {
676         GROUP_MAP map;
677         struct aliasmem_closure closure;
678
679         if(!init_group_mapping()) {
680                 DEBUG(0,("failed to initialize group mapping\n"));
681                 return NT_STATUS_ACCESS_DENIED;
682         }
683
684         if (!get_group_map_from_sid(*alias, &map))
685                 return NT_STATUS_NO_SUCH_ALIAS;
686
687         if ( (map.sid_name_use != SID_NAME_ALIAS) &&
688              (map.sid_name_use != SID_NAME_WKN_GRP) )
689                 return NT_STATUS_NO_SUCH_ALIAS;
690
691         *sids = NULL;
692         *num = 0;
693
694         closure.alias = alias;
695         closure.sids = sids;
696         closure.num = num;
697
698         tdb_traverse(tdb, collect_aliasmem, &closure);
699         return NT_STATUS_OK;
700 }
701
702 static NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
703 {
704         NTSTATUS result;
705         DOM_SID *sids;
706         int i, num;
707         BOOL found = False;
708         char *member_string;
709         TDB_DATA kbuf, dbuf;
710         pstring key;
711         fstring sid_string;
712
713         result = alias_memberships(member, 1, &sids, &num);
714
715         if (!NT_STATUS_IS_OK(result))
716                 return result;
717
718         for (i=0; i<num; i++) {
719                 if (sid_compare(&sids[i], alias) == 0) {
720                         found = True;
721                         break;
722                 }
723         }
724
725         if (!found) {
726                 SAFE_FREE(sids);
727                 return NT_STATUS_MEMBER_NOT_IN_ALIAS;
728         }
729
730         if (i < num)
731                 sids[i] = sids[num-1];
732
733         num -= 1;
734
735         sid_to_string(sid_string, member);
736         slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, sid_string);
737
738         kbuf.dsize = strlen(key)+1;
739         kbuf.dptr = key;
740
741         if (num == 0)
742                 return tdb_delete(tdb, kbuf) == 0 ?
743                         NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
744
745         member_string = SMB_STRDUP("");
746
747         if (member_string == NULL) {
748                 SAFE_FREE(sids);
749                 return NT_STATUS_NO_MEMORY;
750         }
751
752         for (i=0; i<num; i++) {
753                 char *s = member_string;
754
755                 sid_to_string(sid_string, &sids[i]);
756                 asprintf(&member_string, "%s %s", s, sid_string);
757
758                 SAFE_FREE(s);
759                 if (member_string == NULL) {
760                         SAFE_FREE(sids);
761                         return NT_STATUS_NO_MEMORY;
762                 }
763         }
764
765         dbuf.dsize = strlen(member_string)+1;
766         dbuf.dptr = member_string;
767
768         result = tdb_store(tdb, kbuf, dbuf, 0) == 0 ?
769                 NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
770
771         SAFE_FREE(sids);
772         SAFE_FREE(member_string);
773
774         return result;
775 }
776
777 /*
778  *
779  * High level functions
780  * better to use them than the lower ones.
781  *
782  * we are checking if the group is in the mapping file
783  * and if the group is an existing unix group
784  *
785  */
786
787 /* get a domain group from it's SID */
788
789 BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
790 {
791         struct group *grp;
792         BOOL ret;
793         
794         if(!init_group_mapping()) {
795                 DEBUG(0,("failed to initialize group mapping\n"));
796                 return(False);
797         }
798
799         DEBUG(10, ("get_domain_group_from_sid\n"));
800
801         /* if the group is NOT in the database, it CAN NOT be a domain group */
802         
803         become_root();
804         ret = pdb_getgrsid(map, sid);
805         unbecome_root();
806         
807         if ( !ret ) 
808                 return False;
809
810         DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
811
812         /* if it's not a domain group, continue */
813         if (map->sid_name_use!=SID_NAME_DOM_GRP) {
814                 return False;
815         }
816
817         DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n"));
818         
819         if (map->gid==-1) {
820                 return False;
821         }
822
823         DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%lu\n",(unsigned long)map->gid));
824         
825         grp = getgrgid(map->gid);
826         if ( !grp ) {
827                 DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n"));
828                 return False;
829         }
830
831         DEBUG(10, ("get_domain_group_from_sid: gid exists in UNIX security\n"));
832
833         return True;
834 }
835
836
837 /* get a local (alias) group from it's SID */
838
839 BOOL get_local_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
840 {
841         BOOL ret;
842         
843         if(!init_group_mapping()) {
844                 DEBUG(0,("failed to initialize group mapping\n"));
845                 return(False);
846         }
847
848         /* The group is in the mapping table */
849         become_root();
850         ret = pdb_getgrsid(map, *sid);
851         unbecome_root();
852         
853         if ( !ret )
854                 return False;
855                 
856         if ( ( (map->sid_name_use != SID_NAME_ALIAS) &&
857                (map->sid_name_use != SID_NAME_WKN_GRP) )
858                 || (map->gid == -1)
859                 || (getgrgid(map->gid) == NULL) ) 
860         {
861                 return False;
862         }               
863                         
864 #if 1   /* JERRY */
865         /* local groups only exist in the group mapping DB so this 
866            is not necessary */
867            
868         else {
869                 /* the group isn't in the mapping table.
870                  * make one based on the unix information */
871                 uint32 alias_rid;
872                 struct group *grp;
873
874                 sid_peek_rid(sid, &alias_rid);
875                 map->gid=pdb_group_rid_to_gid(alias_rid);
876                 
877                 grp = getgrgid(map->gid);
878                 if ( !grp ) {
879                         DEBUG(3,("get_local_group_from_sid: No unix group for [%ul]\n", map->gid));
880                         return False;
881                 }
882
883                 map->sid_name_use=SID_NAME_ALIAS;
884
885                 fstrcpy(map->nt_name, grp->gr_name);
886                 fstrcpy(map->comment, "Local Unix Group");
887
888                 sid_copy(&map->sid, sid);
889         }
890 #endif
891
892         return True;
893 }
894
895 /* get a builtin group from it's SID */
896
897 BOOL get_builtin_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
898 {
899         BOOL ret;
900         
901
902         if(!init_group_mapping()) {
903                 DEBUG(0,("failed to initialize group mapping\n"));
904                 return(False);
905         }
906
907         become_root();
908         ret = pdb_getgrsid(map, *sid);
909         unbecome_root();
910         
911         if ( !ret )
912                 return False;
913
914         if (map->sid_name_use!=SID_NAME_WKN_GRP) {
915                 return False;
916         }
917
918         if (map->gid==-1) {
919                 return False;
920         }
921
922         if ( getgrgid(map->gid) == NULL) {
923                 return False;
924         }
925
926         return True;
927 }
928
929
930
931 /****************************************************************************
932 Returns a GROUP_MAP struct based on the gid.
933 ****************************************************************************/
934 BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
935 {
936         BOOL ret;
937
938         if(!init_group_mapping()) {
939                 DEBUG(0,("failed to initialize group mapping\n"));
940                 return(False);
941         }
942
943         if ( getgrgid(gid) == NULL)
944                 return False;
945
946         become_root();
947         ret = pdb_getgrgid(map, gid);
948         unbecome_root();
949         
950         if ( !ret ) {
951                 return False;
952         }
953         
954         return True;
955 }
956
957
958 /****************************************************************************
959  Create a UNIX group on demand.
960 ****************************************************************************/
961
962 int smb_create_group(char *unix_group, gid_t *new_gid)
963 {
964         pstring add_script;
965         int     ret = -1;
966         int     fd = 0;
967         
968         *new_gid = 0;
969
970         /* defer to scripts */
971         
972         if ( *lp_addgroup_script() ) {
973                 pstrcpy(add_script, lp_addgroup_script());
974                 pstring_sub(add_script, "%g", unix_group);
975                 ret = smbrun(add_script, (new_gid!=NULL) ? &fd : NULL);
976                 DEBUG(ret ? 0 : 3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
977                 if (ret != 0)
978                         return ret;
979                         
980                 if (fd != 0) {
981                         fstring output;
982
983                         *new_gid = 0;
984                         if (read(fd, output, sizeof(output)) > 0) {
985                                 *new_gid = (gid_t)strtoul(output, NULL, 10);
986                         }
987                         
988                         close(fd);
989                 }
990
991         } 
992         
993         if (*new_gid == 0) {
994                 struct group *grp = getgrnam(unix_group);
995
996                 if (grp != NULL)
997                         *new_gid = grp->gr_gid;
998         }
999                         
1000         return ret;     
1001 }
1002
1003 /****************************************************************************
1004  Delete a UNIX group on demand.
1005 ****************************************************************************/
1006
1007 int smb_delete_group(char *unix_group)
1008 {
1009         pstring del_script;
1010         int ret;
1011
1012         /* defer to scripts */
1013         
1014         if ( *lp_delgroup_script() ) {
1015                 pstrcpy(del_script, lp_delgroup_script());
1016                 pstring_sub(del_script, "%g", unix_group);
1017                 ret = smbrun(del_script,NULL);
1018                 DEBUG(ret ? 0 : 3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
1019                 return ret;
1020         }
1021
1022         return -1;
1023 }
1024
1025 /****************************************************************************
1026  Set a user's primary UNIX group.
1027 ****************************************************************************/
1028 int smb_set_primary_group(const char *unix_group, const char* unix_user)
1029 {
1030         pstring add_script;
1031         int ret;
1032
1033         /* defer to scripts */
1034         
1035         if ( *lp_setprimarygroup_script() ) {
1036                 pstrcpy(add_script, lp_setprimarygroup_script());
1037                 all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
1038                 all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
1039                 ret = smbrun(add_script,NULL);
1040                 flush_pwnam_cache();
1041                 DEBUG(ret ? 0 : 3,("smb_set_primary_group: "
1042                          "Running the command `%s' gave %d\n",add_script,ret));
1043                 return ret;
1044         }
1045
1046         return -1;
1047 }
1048
1049 /****************************************************************************
1050  Add a user to a UNIX group.
1051 ****************************************************************************/
1052
1053 int smb_add_user_group(char *unix_group, char *unix_user)
1054 {
1055         pstring add_script;
1056         int ret;
1057
1058         /* defer to scripts */
1059         
1060         if ( *lp_addusertogroup_script() ) {
1061                 pstrcpy(add_script, lp_addusertogroup_script());
1062                 pstring_sub(add_script, "%g", unix_group);
1063                 pstring_sub(add_script, "%u", unix_user);
1064                 ret = smbrun(add_script,NULL);
1065                 DEBUG(ret ? 0 : 3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
1066                 return ret;
1067         }
1068         
1069         return -1;
1070 }
1071
1072 /****************************************************************************
1073  Delete a user from a UNIX group
1074 ****************************************************************************/
1075
1076 int smb_delete_user_group(const char *unix_group, const char *unix_user)
1077 {
1078         pstring del_script;
1079         int ret;
1080
1081         /* defer to scripts */
1082         
1083         if ( *lp_deluserfromgroup_script() ) {
1084                 pstrcpy(del_script, lp_deluserfromgroup_script());
1085                 pstring_sub(del_script, "%g", unix_group);
1086                 pstring_sub(del_script, "%u", unix_user);
1087                 ret = smbrun(del_script,NULL);
1088                 DEBUG(ret ? 0 : 3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
1089                 return ret;
1090         }
1091         
1092         return -1;
1093 }
1094
1095
1096 NTSTATUS pdb_default_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1097                                  DOM_SID sid)
1098 {
1099         return get_group_map_from_sid(sid, map) ?
1100                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1101 }
1102
1103 NTSTATUS pdb_default_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1104                                  gid_t gid)
1105 {
1106         return get_group_map_from_gid(gid, map) ?
1107                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1108 }
1109
1110 NTSTATUS pdb_default_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1111                                  const char *name)
1112 {
1113         return get_group_map_from_ntname(name, map) ?
1114                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1115 }
1116
1117 NTSTATUS pdb_default_add_group_mapping_entry(struct pdb_methods *methods,
1118                                                 GROUP_MAP *map)
1119 {
1120         return add_mapping_entry(map, TDB_INSERT) ?
1121                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1122 }
1123
1124 NTSTATUS pdb_default_update_group_mapping_entry(struct pdb_methods *methods,
1125                                                    GROUP_MAP *map)
1126 {
1127         return add_mapping_entry(map, TDB_REPLACE) ?
1128                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1129 }
1130
1131 NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods,
1132                                                    DOM_SID sid)
1133 {
1134         return group_map_remove(sid) ?
1135                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1136 }
1137
1138 NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods,
1139                                            enum SID_NAME_USE sid_name_use,
1140                                            GROUP_MAP **rmap, int *num_entries,
1141                                            BOOL unix_only)
1142 {
1143         return enum_group_mapping(sid_name_use, rmap, num_entries, unix_only) ?
1144                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1145 }
1146
1147 NTSTATUS pdb_default_find_alias(struct pdb_methods *methods,
1148                                 const char *name, DOM_SID *sid)
1149 {
1150         GROUP_MAP map;
1151
1152         if (!pdb_getgrnam(&map, name))
1153                 return NT_STATUS_NO_SUCH_ALIAS;
1154
1155         if ((map.sid_name_use != SID_NAME_WKN_GRP) &&
1156             (map.sid_name_use != SID_NAME_ALIAS))
1157                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
1158
1159         sid_copy(sid, &map.sid);
1160         return NT_STATUS_OK;
1161 }
1162
1163 NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
1164                                   const char *name, uint32 *rid)
1165 {
1166         DOM_SID sid;
1167         enum SID_NAME_USE type;
1168         uint32 new_rid;
1169         gid_t gid;
1170
1171         GROUP_MAP map;
1172
1173         if (lookup_name(get_global_sam_name(), name, &sid, &type))
1174                 return NT_STATUS_ALIAS_EXISTS;
1175
1176         if (!winbind_allocate_rid(&new_rid))
1177                 return NT_STATUS_ACCESS_DENIED;
1178
1179         sid_copy(&sid, get_global_sam_sid());
1180         sid_append_rid(&sid, new_rid);
1181
1182         /* Here we allocate the gid */
1183         if (!winbind_sid_to_gid(&gid, &sid)) {
1184                 DEBUG(0, ("Could not get gid for new RID\n"));
1185                 return NT_STATUS_ACCESS_DENIED;
1186         }
1187
1188         map.gid = gid;
1189         sid_copy(&map.sid, &sid);
1190         map.sid_name_use = SID_NAME_ALIAS;
1191         fstrcpy(map.nt_name, name);
1192         fstrcpy(map.comment, "");
1193
1194         if (!pdb_add_group_mapping_entry(&map)) {
1195                 DEBUG(0, ("Could not add group mapping entry for alias %s\n",
1196                           name));
1197                 return NT_STATUS_ACCESS_DENIED;
1198         }
1199
1200         *rid = new_rid;
1201
1202         return NT_STATUS_OK;
1203 }
1204
1205 NTSTATUS pdb_default_delete_alias(struct pdb_methods *methods,
1206                                   const DOM_SID *sid)
1207 {
1208         return pdb_delete_group_mapping_entry(*sid) ?
1209                 NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
1210 }
1211
1212 NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
1213                                    const DOM_SID *sid,
1214                                    struct acct_info *info)
1215 {
1216         GROUP_MAP map;
1217
1218         if (!pdb_getgrsid(&map, *sid))
1219                 return NT_STATUS_NO_SUCH_ALIAS;
1220
1221         fstrcpy(info->acct_name, map.nt_name);
1222         fstrcpy(info->acct_desc, map.comment);
1223         sid_peek_rid(&map.sid, &info->rid);
1224         return NT_STATUS_OK;
1225 }
1226
1227 NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods,
1228                                    const DOM_SID *sid,
1229                                    struct acct_info *info)
1230 {
1231         GROUP_MAP map;
1232
1233         if (!pdb_getgrsid(&map, *sid))
1234                 return NT_STATUS_NO_SUCH_ALIAS;
1235
1236         fstrcpy(map.comment, info->acct_desc);
1237
1238         if (!pdb_update_group_mapping_entry(&map))
1239                 return NT_STATUS_ACCESS_DENIED;
1240
1241         return NT_STATUS_OK;
1242 }
1243
1244 NTSTATUS pdb_default_add_aliasmem(struct pdb_methods *methods,
1245                                   const DOM_SID *alias, const DOM_SID *member)
1246 {
1247         return add_aliasmem(alias, member);
1248 }
1249
1250 NTSTATUS pdb_default_del_aliasmem(struct pdb_methods *methods,
1251                                   const DOM_SID *alias, const DOM_SID *member)
1252 {
1253         return del_aliasmem(alias, member);
1254 }
1255
1256 NTSTATUS pdb_default_enum_aliasmem(struct pdb_methods *methods,
1257                                    const DOM_SID *alias, DOM_SID **members,
1258                                    int *num_members)
1259 {
1260         return enum_aliasmem(alias, members, num_members);
1261 }
1262
1263 NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods,
1264                                        TALLOC_CTX *mem_ctx,
1265                                        const DOM_SID *domain_sid,
1266                                        const DOM_SID *members,
1267                                        int num_members,
1268                                        uint32 **alias_rids,
1269                                        int *num_alias_rids)
1270 {
1271         DOM_SID *alias_sids;
1272         int i, num_alias_sids;
1273         NTSTATUS result;
1274
1275         alias_sids = NULL;
1276         num_alias_sids = 0;
1277
1278         result = alias_memberships(members, num_members,
1279                                    &alias_sids, &num_alias_sids);
1280
1281         if (!NT_STATUS_IS_OK(result))
1282                 return result;
1283
1284         *alias_rids = TALLOC_ARRAY(mem_ctx, uint32, num_alias_sids);
1285         if ((alias_sids != 0) && (*alias_rids == NULL))
1286                 return NT_STATUS_NO_MEMORY;
1287
1288         *num_alias_rids = 0;
1289
1290         for (i=0; i<num_alias_sids; i++) {
1291                 if (!sid_peek_check_rid(domain_sid, &alias_sids[i],
1292                                         &(*alias_rids)[*num_alias_rids]))
1293                         continue;
1294                 *num_alias_rids += 1;
1295         }
1296
1297         SAFE_FREE(alias_sids);
1298
1299         return NT_STATUS_OK;
1300 }
1301
1302 /**********************************************************************
1303  no ops for passdb backends that don't implement group mapping
1304  *********************************************************************/
1305
1306 NTSTATUS pdb_nop_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1307                                  DOM_SID sid)
1308 {
1309         return NT_STATUS_UNSUCCESSFUL;
1310 }
1311
1312 NTSTATUS pdb_nop_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1313                                  gid_t gid)
1314 {
1315         return NT_STATUS_UNSUCCESSFUL;
1316 }
1317
1318 NTSTATUS pdb_nop_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1319                                  const char *name)
1320 {
1321         return NT_STATUS_UNSUCCESSFUL;
1322 }
1323
1324 NTSTATUS pdb_nop_add_group_mapping_entry(struct pdb_methods *methods,
1325                                                 GROUP_MAP *map)
1326 {
1327         return NT_STATUS_UNSUCCESSFUL;
1328 }
1329
1330 NTSTATUS pdb_nop_update_group_mapping_entry(struct pdb_methods *methods,
1331                                                    GROUP_MAP *map)
1332 {
1333         return NT_STATUS_UNSUCCESSFUL;
1334 }
1335
1336 NTSTATUS pdb_nop_delete_group_mapping_entry(struct pdb_methods *methods,
1337                                                    DOM_SID sid)
1338 {
1339         return NT_STATUS_UNSUCCESSFUL;
1340 }
1341
1342 NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods,
1343                                            enum SID_NAME_USE sid_name_use,
1344                                            GROUP_MAP **rmap, int *num_entries,
1345                                            BOOL unix_only)
1346 {
1347         return NT_STATUS_UNSUCCESSFUL;
1348 }
1349