r6769: Fix bugzilla #2538 and #2527. Unused variables found by Jason Mader.
[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         } else if ( winbind_create_group( unix_group, NULL ) ) {
992
993                 DEBUG(3,("smb_create_group: winbindd created the group (%s)\n",
994                         unix_group));
995                 ret = 0;
996         }
997         
998         if (*new_gid == 0) {
999                 struct group *grp = getgrnam(unix_group);
1000
1001                 if (grp != NULL)
1002                         *new_gid = grp->gr_gid;
1003         }
1004                         
1005         return ret;     
1006 }
1007
1008 /****************************************************************************
1009  Delete a UNIX group on demand.
1010 ****************************************************************************/
1011
1012 int smb_delete_group(char *unix_group)
1013 {
1014         pstring del_script;
1015         int ret;
1016
1017         /* defer to scripts */
1018         
1019         if ( *lp_delgroup_script() ) {
1020                 pstrcpy(del_script, lp_delgroup_script());
1021                 pstring_sub(del_script, "%g", unix_group);
1022                 ret = smbrun(del_script,NULL);
1023                 DEBUG(ret ? 0 : 3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
1024                 return ret;
1025         }
1026
1027         if ( winbind_delete_group( unix_group ) ) {
1028                 DEBUG(3,("smb_delete_group: winbindd deleted the group (%s)\n",
1029                         unix_group));
1030                 return 0;
1031         }
1032                 
1033         return -1;
1034 }
1035
1036 /****************************************************************************
1037  Set a user's primary UNIX group.
1038 ****************************************************************************/
1039 int smb_set_primary_group(const char *unix_group, const char* unix_user)
1040 {
1041         pstring add_script;
1042         int ret;
1043
1044         /* defer to scripts */
1045         
1046         if ( *lp_setprimarygroup_script() ) {
1047                 pstrcpy(add_script, lp_setprimarygroup_script());
1048                 all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
1049                 all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
1050                 ret = smbrun(add_script,NULL);
1051                 flush_pwnam_cache();
1052                 DEBUG(ret ? 0 : 3,("smb_set_primary_group: "
1053                          "Running the command `%s' gave %d\n",add_script,ret));
1054                 return ret;
1055         }
1056
1057         /* Try winbindd */
1058         
1059         if ( winbind_set_user_primary_group( unix_user, unix_group ) ) {
1060                 DEBUG(3,("smb_delete_group: winbindd set the group (%s) as the primary group for user (%s)\n",
1061                         unix_group, unix_user));
1062                 flush_pwnam_cache();
1063                 return 0;
1064         }               
1065         
1066         return -1;
1067 }
1068
1069 /****************************************************************************
1070  Add a user to a UNIX group.
1071 ****************************************************************************/
1072
1073 int smb_add_user_group(char *unix_group, char *unix_user)
1074 {
1075         pstring add_script;
1076         int ret;
1077
1078         /* defer to scripts */
1079         
1080         if ( *lp_addusertogroup_script() ) {
1081                 pstrcpy(add_script, lp_addusertogroup_script());
1082                 pstring_sub(add_script, "%g", unix_group);
1083                 pstring_sub(add_script, "%u", unix_user);
1084                 ret = smbrun(add_script,NULL);
1085                 DEBUG(ret ? 0 : 3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
1086                 return ret;
1087         }
1088         
1089         /* Try winbindd */
1090
1091         if ( winbind_add_user_to_group( unix_user, unix_group ) ) {
1092                 DEBUG(3,("smb_delete_group: winbindd added user (%s) to the group (%s)\n",
1093                         unix_user, unix_group));
1094                 return -1;
1095         }       
1096         
1097         return -1;
1098 }
1099
1100 /****************************************************************************
1101  Delete a user from a UNIX group
1102 ****************************************************************************/
1103
1104 int smb_delete_user_group(const char *unix_group, const char *unix_user)
1105 {
1106         pstring del_script;
1107         int ret;
1108
1109         /* defer to scripts */
1110         
1111         if ( *lp_deluserfromgroup_script() ) {
1112                 pstrcpy(del_script, lp_deluserfromgroup_script());
1113                 pstring_sub(del_script, "%g", unix_group);
1114                 pstring_sub(del_script, "%u", unix_user);
1115                 ret = smbrun(del_script,NULL);
1116                 DEBUG(ret ? 0 : 3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
1117                 return ret;
1118         }
1119         
1120         /* Try winbindd */
1121
1122         if ( winbind_remove_user_from_group( unix_user, unix_group ) ) {
1123                 DEBUG(3,("smb_delete_group: winbindd removed user (%s) from the group (%s)\n",
1124                         unix_user, unix_group));
1125                 return 0;
1126         }
1127         
1128         return -1;
1129 }
1130
1131
1132 NTSTATUS pdb_default_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1133                                  DOM_SID sid)
1134 {
1135         return get_group_map_from_sid(sid, map) ?
1136                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1137 }
1138
1139 NTSTATUS pdb_default_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1140                                  gid_t gid)
1141 {
1142         return get_group_map_from_gid(gid, map) ?
1143                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1144 }
1145
1146 NTSTATUS pdb_default_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1147                                  const char *name)
1148 {
1149         return get_group_map_from_ntname(name, map) ?
1150                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1151 }
1152
1153 NTSTATUS pdb_default_add_group_mapping_entry(struct pdb_methods *methods,
1154                                                 GROUP_MAP *map)
1155 {
1156         return add_mapping_entry(map, TDB_INSERT) ?
1157                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1158 }
1159
1160 NTSTATUS pdb_default_update_group_mapping_entry(struct pdb_methods *methods,
1161                                                    GROUP_MAP *map)
1162 {
1163         return add_mapping_entry(map, TDB_REPLACE) ?
1164                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1165 }
1166
1167 NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods,
1168                                                    DOM_SID sid)
1169 {
1170         return group_map_remove(sid) ?
1171                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1172 }
1173
1174 NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods,
1175                                            enum SID_NAME_USE sid_name_use,
1176                                            GROUP_MAP **rmap, int *num_entries,
1177                                            BOOL unix_only)
1178 {
1179         return enum_group_mapping(sid_name_use, rmap, num_entries, unix_only) ?
1180                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1181 }
1182
1183 NTSTATUS pdb_default_find_alias(struct pdb_methods *methods,
1184                                 const char *name, DOM_SID *sid)
1185 {
1186         GROUP_MAP map;
1187
1188         if (!pdb_getgrnam(&map, name))
1189                 return NT_STATUS_NO_SUCH_ALIAS;
1190
1191         if ((map.sid_name_use != SID_NAME_WKN_GRP) &&
1192             (map.sid_name_use != SID_NAME_ALIAS))
1193                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
1194
1195         sid_copy(sid, &map.sid);
1196         return NT_STATUS_OK;
1197 }
1198
1199 NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
1200                                   const char *name, uint32 *rid)
1201 {
1202         DOM_SID sid;
1203         enum SID_NAME_USE type;
1204         uint32 new_rid;
1205         gid_t gid;
1206
1207         GROUP_MAP map;
1208
1209         if (lookup_name(get_global_sam_name(), name, &sid, &type))
1210                 return NT_STATUS_ALIAS_EXISTS;
1211
1212         if (!winbind_allocate_rid(&new_rid))
1213                 return NT_STATUS_ACCESS_DENIED;
1214
1215         sid_copy(&sid, get_global_sam_sid());
1216         sid_append_rid(&sid, new_rid);
1217
1218         /* Here we allocate the gid */
1219         if (!winbind_sid_to_gid(&gid, &sid)) {
1220                 DEBUG(0, ("Could not get gid for new RID\n"));
1221                 return NT_STATUS_ACCESS_DENIED;
1222         }
1223
1224         map.gid = gid;
1225         sid_copy(&map.sid, &sid);
1226         map.sid_name_use = SID_NAME_ALIAS;
1227         fstrcpy(map.nt_name, name);
1228         fstrcpy(map.comment, "");
1229
1230         if (!pdb_add_group_mapping_entry(&map)) {
1231                 DEBUG(0, ("Could not add group mapping entry for alias %s\n",
1232                           name));
1233                 return NT_STATUS_ACCESS_DENIED;
1234         }
1235
1236         *rid = new_rid;
1237
1238         return NT_STATUS_OK;
1239 }
1240
1241 NTSTATUS pdb_default_delete_alias(struct pdb_methods *methods,
1242                                   const DOM_SID *sid)
1243 {
1244         return pdb_delete_group_mapping_entry(*sid) ?
1245                 NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
1246 }
1247
1248 NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
1249                                    const DOM_SID *sid,
1250                                    struct acct_info *info)
1251 {
1252         GROUP_MAP map;
1253
1254         if (!pdb_getgrsid(&map, *sid))
1255                 return NT_STATUS_NO_SUCH_ALIAS;
1256
1257         fstrcpy(info->acct_name, map.nt_name);
1258         fstrcpy(info->acct_desc, map.comment);
1259         sid_peek_rid(&map.sid, &info->rid);
1260         return NT_STATUS_OK;
1261 }
1262
1263 NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods,
1264                                    const DOM_SID *sid,
1265                                    struct acct_info *info)
1266 {
1267         GROUP_MAP map;
1268
1269         if (!pdb_getgrsid(&map, *sid))
1270                 return NT_STATUS_NO_SUCH_ALIAS;
1271
1272         fstrcpy(map.comment, info->acct_desc);
1273
1274         if (!pdb_update_group_mapping_entry(&map))
1275                 return NT_STATUS_ACCESS_DENIED;
1276
1277         return NT_STATUS_OK;
1278 }
1279
1280 NTSTATUS pdb_default_add_aliasmem(struct pdb_methods *methods,
1281                                   const DOM_SID *alias, const DOM_SID *member)
1282 {
1283         return add_aliasmem(alias, member);
1284 }
1285
1286 NTSTATUS pdb_default_del_aliasmem(struct pdb_methods *methods,
1287                                   const DOM_SID *alias, const DOM_SID *member)
1288 {
1289         return del_aliasmem(alias, member);
1290 }
1291
1292 NTSTATUS pdb_default_enum_aliasmem(struct pdb_methods *methods,
1293                                    const DOM_SID *alias, DOM_SID **members,
1294                                    int *num_members)
1295 {
1296         return enum_aliasmem(alias, members, num_members);
1297 }
1298
1299 NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods,
1300                                        TALLOC_CTX *mem_ctx,
1301                                        const DOM_SID *domain_sid,
1302                                        const DOM_SID *members,
1303                                        int num_members,
1304                                        uint32 **alias_rids,
1305                                        int *num_alias_rids)
1306 {
1307         DOM_SID *alias_sids;
1308         int i, num_alias_sids;
1309         NTSTATUS result;
1310
1311         alias_sids = NULL;
1312         num_alias_sids = 0;
1313
1314         result = alias_memberships(members, num_members,
1315                                    &alias_sids, &num_alias_sids);
1316
1317         if (!NT_STATUS_IS_OK(result))
1318                 return result;
1319
1320         *alias_rids = TALLOC_ARRAY(mem_ctx, uint32, num_alias_sids);
1321         if ((alias_sids != 0) && (*alias_rids == NULL))
1322                 return NT_STATUS_NO_MEMORY;
1323
1324         *num_alias_rids = 0;
1325
1326         for (i=0; i<num_alias_sids; i++) {
1327                 if (!sid_peek_check_rid(domain_sid, &alias_sids[i],
1328                                         &(*alias_rids)[*num_alias_rids]))
1329                         continue;
1330                 *num_alias_rids += 1;
1331         }
1332
1333         SAFE_FREE(alias_sids);
1334
1335         return NT_STATUS_OK;
1336 }
1337
1338 /**********************************************************************
1339  no ops for passdb backends that don't implement group mapping
1340  *********************************************************************/
1341
1342 NTSTATUS pdb_nop_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1343                                  DOM_SID sid)
1344 {
1345         return NT_STATUS_UNSUCCESSFUL;
1346 }
1347
1348 NTSTATUS pdb_nop_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1349                                  gid_t gid)
1350 {
1351         return NT_STATUS_UNSUCCESSFUL;
1352 }
1353
1354 NTSTATUS pdb_nop_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1355                                  const char *name)
1356 {
1357         return NT_STATUS_UNSUCCESSFUL;
1358 }
1359
1360 NTSTATUS pdb_nop_add_group_mapping_entry(struct pdb_methods *methods,
1361                                                 GROUP_MAP *map)
1362 {
1363         return NT_STATUS_UNSUCCESSFUL;
1364 }
1365
1366 NTSTATUS pdb_nop_update_group_mapping_entry(struct pdb_methods *methods,
1367                                                    GROUP_MAP *map)
1368 {
1369         return NT_STATUS_UNSUCCESSFUL;
1370 }
1371
1372 NTSTATUS pdb_nop_delete_group_mapping_entry(struct pdb_methods *methods,
1373                                                    DOM_SID sid)
1374 {
1375         return NT_STATUS_UNSUCCESSFUL;
1376 }
1377
1378 NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods,
1379                                            enum SID_NAME_USE sid_name_use,
1380                                            GROUP_MAP **rmap, int *num_entries,
1381                                            BOOL unix_only)
1382 {
1383         return NT_STATUS_UNSUCCESSFUL;
1384 }
1385