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