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
24static 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/****************************************************************************
39dump the mapping group mapping to a text file
40****************************************************************************/
41char *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/****************************************************************************
78initialise first time the mapping list - called from init_group_mapping()
79****************************************************************************/
80static 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
125static 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****************************************************************************/
165static 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/****************************************************************************
197initialise first time the mapping list
198****************************************************************************/
199BOOL 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
225static 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
268static 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
318static 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
368static 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
403static 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
488static 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(&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
531static 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
547static 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
567static 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
622struct aliasmem_closure {
623	const DOM_SID *alias;
624	DOM_SID **sids;
625	int *num;
626};
627
628static 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(&member, closure->sids, closure->num);
669	}
670
671	return 0;
672}
673
674static 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
702static 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
789BOOL 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
839BOOL 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
897BOOL get_builtin_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
898{
899	struct group *grp;
900	BOOL ret;
901
902
903	if(!init_group_mapping()) {
904		DEBUG(0,("failed to initialize group mapping\n"));
905		return(False);
906	}
907
908	become_root();
909	ret = pdb_getgrsid(map, *sid);
910	unbecome_root();
911
912	if ( !ret )
913		return False;
914
915	if (map->sid_name_use!=SID_NAME_WKN_GRP) {
916		return False;
917	}
918
919	if (map->gid==-1) {
920		return False;
921	}
922
923	if ( (grp=getgrgid(map->gid)) == NULL) {
924		return False;
925	}
926
927	return True;
928}
929
930
931
932/****************************************************************************
933Returns a GROUP_MAP struct based on the gid.
934****************************************************************************/
935BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
936{
937	struct group *grp;
938	BOOL ret;
939
940	if(!init_group_mapping()) {
941		DEBUG(0,("failed to initialize group mapping\n"));
942		return(False);
943	}
944
945	if ( (grp=getgrgid(gid)) == NULL)
946		return False;
947
948	become_root();
949	ret = pdb_getgrgid(map, gid);
950	unbecome_root();
951
952	if ( !ret ) {
953		return False;
954	}
955
956	return True;
957}
958
959
960/****************************************************************************
961 Create a UNIX group on demand.
962****************************************************************************/
963
964int smb_create_group(char *unix_group, gid_t *new_gid)
965{
966	pstring add_script;
967	int 	ret = -1;
968	int 	fd = 0;
969
970	*new_gid = 0;
971
972	/* defer to scripts */
973
974	if ( *lp_addgroup_script() ) {
975		pstrcpy(add_script, lp_addgroup_script());
976		pstring_sub(add_script, "%g", unix_group);
977		ret = smbrun(add_script, (new_gid!=NULL) ? &fd : NULL);
978		DEBUG(ret ? 0 : 3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
979		if (ret != 0)
980			return ret;
981
982		if (fd != 0) {
983			fstring output;
984
985			*new_gid = 0;
986			if (read(fd, output, sizeof(output)) > 0) {
987				*new_gid = (gid_t)strtoul(output, NULL, 10);
988			}
989
990			close(fd);
991		}
992
993	} else if ( winbind_create_group( unix_group, NULL ) ) {
994
995		DEBUG(3,("smb_create_group: winbindd created the group (%s)\n",
996			unix_group));
997		ret = 0;
998	}
999
1000	if (*new_gid == 0) {
1001		struct group *grp = getgrnam(unix_group);
1002
1003		if (grp != NULL)
1004			*new_gid = grp->gr_gid;
1005	}
1006
1007	return ret;
1008}
1009
1010/****************************************************************************
1011 Delete a UNIX group on demand.
1012****************************************************************************/
1013
1014int smb_delete_group(char *unix_group)
1015{
1016	pstring del_script;
1017	int ret;
1018
1019	/* defer to scripts */
1020
1021	if ( *lp_delgroup_script() ) {
1022		pstrcpy(del_script, lp_delgroup_script());
1023		pstring_sub(del_script, "%g", unix_group);
1024		ret = smbrun(del_script,NULL);
1025		DEBUG(ret ? 0 : 3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
1026		return ret;
1027	}
1028
1029	if ( winbind_delete_group( unix_group ) ) {
1030		DEBUG(3,("smb_delete_group: winbindd deleted the group (%s)\n",
1031			unix_group));
1032		return 0;
1033	}
1034
1035	return -1;
1036}
1037
1038/****************************************************************************
1039 Set a user's primary UNIX group.
1040****************************************************************************/
1041int smb_set_primary_group(const char *unix_group, const char* unix_user)
1042{
1043	pstring add_script;
1044	int ret;
1045
1046	/* defer to scripts */
1047
1048	if ( *lp_setprimarygroup_script() ) {
1049		pstrcpy(add_script, lp_setprimarygroup_script());
1050		all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
1051		all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
1052		ret = smbrun(add_script,NULL);
1053		flush_pwnam_cache();
1054		DEBUG(ret ? 0 : 3,("smb_set_primary_group: "
1055			 "Running the command `%s' gave %d\n",add_script,ret));
1056		return ret;
1057	}
1058
1059	/* Try winbindd */
1060
1061	if ( winbind_set_user_primary_group( unix_user, unix_group ) ) {
1062		DEBUG(3,("smb_delete_group: winbindd set the group (%s) as the primary group for user (%s)\n",
1063			unix_group, unix_user));
1064		flush_pwnam_cache();
1065		return 0;
1066	}
1067
1068	return -1;
1069}
1070
1071/****************************************************************************
1072 Add a user to a UNIX group.
1073****************************************************************************/
1074
1075int smb_add_user_group(char *unix_group, char *unix_user)
1076{
1077	pstring add_script;
1078	int ret;
1079
1080	/* defer to scripts */
1081
1082	if ( *lp_addusertogroup_script() ) {
1083		pstrcpy(add_script, lp_addusertogroup_script());
1084		pstring_sub(add_script, "%g", unix_group);
1085		pstring_sub(add_script, "%u", unix_user);
1086		ret = smbrun(add_script,NULL);
1087		DEBUG(ret ? 0 : 3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
1088		return ret;
1089	}
1090
1091	/* Try winbindd */
1092
1093	if ( winbind_add_user_to_group( unix_user, unix_group ) ) {
1094		DEBUG(3,("smb_delete_group: winbindd added user (%s) to the group (%s)\n",
1095			unix_user, unix_group));
1096		return -1;
1097	}
1098
1099	return -1;
1100}
1101
1102/****************************************************************************
1103 Delete a user from a UNIX group
1104****************************************************************************/
1105
1106int smb_delete_user_group(const char *unix_group, const char *unix_user)
1107{
1108	pstring del_script;
1109	int ret;
1110
1111	/* defer to scripts */
1112
1113	if ( *lp_deluserfromgroup_script() ) {
1114		pstrcpy(del_script, lp_deluserfromgroup_script());
1115		pstring_sub(del_script, "%g", unix_group);
1116		pstring_sub(del_script, "%u", unix_user);
1117		ret = smbrun(del_script,NULL);
1118		DEBUG(ret ? 0 : 3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
1119		return ret;
1120	}
1121
1122	/* Try winbindd */
1123
1124	if ( winbind_remove_user_from_group( unix_user, unix_group ) ) {
1125		DEBUG(3,("smb_delete_group: winbindd removed user (%s) from the group (%s)\n",
1126			unix_user, unix_group));
1127		return 0;
1128	}
1129
1130	return -1;
1131}
1132
1133
1134NTSTATUS pdb_default_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1135				 DOM_SID sid)
1136{
1137	return get_group_map_from_sid(sid, map) ?
1138		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1139}
1140
1141NTSTATUS pdb_default_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1142				 gid_t gid)
1143{
1144	return get_group_map_from_gid(gid, map) ?
1145		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1146}
1147
1148NTSTATUS pdb_default_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1149				 const char *name)
1150{
1151	return get_group_map_from_ntname(name, map) ?
1152		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1153}
1154
1155NTSTATUS pdb_default_add_group_mapping_entry(struct pdb_methods *methods,
1156						GROUP_MAP *map)
1157{
1158	return add_mapping_entry(map, TDB_INSERT) ?
1159		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1160}
1161
1162NTSTATUS pdb_default_update_group_mapping_entry(struct pdb_methods *methods,
1163						   GROUP_MAP *map)
1164{
1165	return add_mapping_entry(map, TDB_REPLACE) ?
1166		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1167}
1168
1169NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods,
1170						   DOM_SID sid)
1171{
1172	return group_map_remove(sid) ?
1173		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1174}
1175
1176NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods,
1177					   enum SID_NAME_USE sid_name_use,
1178					   GROUP_MAP **rmap, int *num_entries,
1179					   BOOL unix_only)
1180{
1181	return enum_group_mapping(sid_name_use, rmap, num_entries, unix_only) ?
1182		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1183}
1184
1185NTSTATUS pdb_default_find_alias(struct pdb_methods *methods,
1186				const char *name, DOM_SID *sid)
1187{
1188	GROUP_MAP map;
1189
1190	if (!pdb_getgrnam(&map, name))
1191		return NT_STATUS_NO_SUCH_ALIAS;
1192
1193	if ((map.sid_name_use != SID_NAME_WKN_GRP) &&
1194	    (map.sid_name_use != SID_NAME_ALIAS))
1195		return NT_STATUS_OBJECT_TYPE_MISMATCH;
1196
1197	sid_copy(sid, &map.sid);
1198	return NT_STATUS_OK;
1199}
1200
1201NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
1202				  const char *name, uint32 *rid)
1203{
1204	DOM_SID sid;
1205	enum SID_NAME_USE type;
1206	uint32 new_rid;
1207	gid_t gid;
1208
1209	GROUP_MAP map;
1210
1211	if (lookup_name(get_global_sam_name(), name, &sid, &type))
1212		return NT_STATUS_ALIAS_EXISTS;
1213
1214	if (!winbind_allocate_rid(&new_rid))
1215		return NT_STATUS_ACCESS_DENIED;
1216
1217	sid_copy(&sid, get_global_sam_sid());
1218	sid_append_rid(&sid, new_rid);
1219
1220	/* Here we allocate the gid */
1221	if (!winbind_sid_to_gid(&gid, &sid)) {
1222		DEBUG(0, ("Could not get gid for new RID\n"));
1223		return NT_STATUS_ACCESS_DENIED;
1224	}
1225
1226	map.gid = gid;
1227	sid_copy(&map.sid, &sid);
1228	map.sid_name_use = SID_NAME_ALIAS;
1229	fstrcpy(map.nt_name, name);
1230	fstrcpy(map.comment, "");
1231
1232	if (!pdb_add_group_mapping_entry(&map)) {
1233		DEBUG(0, ("Could not add group mapping entry for alias %s\n",
1234			  name));
1235		return NT_STATUS_ACCESS_DENIED;
1236	}
1237
1238	*rid = new_rid;
1239
1240	return NT_STATUS_OK;
1241}
1242
1243NTSTATUS pdb_default_delete_alias(struct pdb_methods *methods,
1244				  const DOM_SID *sid)
1245{
1246	return pdb_delete_group_mapping_entry(*sid) ?
1247		NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
1248}
1249
1250NTSTATUS pdb_default_enum_aliases(struct pdb_methods *methods,
1251				  const DOM_SID *sid,
1252				  uint32 start_idx, uint32 max_entries,
1253				  uint32 *num_aliases,
1254				  struct acct_info **info)
1255{
1256	extern DOM_SID global_sid_Builtin;
1257
1258	GROUP_MAP *map;
1259	int i, num_maps;
1260	enum SID_NAME_USE type = SID_NAME_UNKNOWN;
1261
1262	if (sid_compare(sid, get_global_sam_sid()) == 0)
1263		type = SID_NAME_ALIAS;
1264
1265	if (sid_compare(sid, &global_sid_Builtin) == 0)
1266		type = SID_NAME_WKN_GRP;
1267
1268	if (!pdb_enum_group_mapping(type, &map, &num_maps, False) ||
1269	    (num_maps == 0)) {
1270		*num_aliases = 0;
1271		*info = NULL;
1272		goto done;
1273	}
1274
1275	if (start_idx > num_maps) {
1276		*num_aliases = 0;
1277		*info = NULL;
1278		goto done;
1279	}
1280
1281	*num_aliases = num_maps - start_idx;
1282
1283	if (*num_aliases > max_entries)
1284		*num_aliases = max_entries;
1285
1286	*info = SMB_MALLOC_ARRAY(struct acct_info, *num_aliases);
1287
1288	for (i=0; i<*num_aliases; i++) {
1289		fstrcpy((*info)[i].acct_name, map[i+start_idx].nt_name);
1290		fstrcpy((*info)[i].acct_desc, map[i+start_idx].comment);
1291		sid_peek_rid(&map[i].sid, &(*info)[i+start_idx].rid);
1292	}
1293
1294 done:
1295	SAFE_FREE(map);
1296	return NT_STATUS_OK;
1297}
1298
1299NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
1300				   const DOM_SID *sid,
1301				   struct acct_info *info)
1302{
1303	GROUP_MAP map;
1304
1305	if (!pdb_getgrsid(&map, *sid))
1306		return NT_STATUS_NO_SUCH_ALIAS;
1307
1308	fstrcpy(info->acct_name, map.nt_name);
1309	fstrcpy(info->acct_desc, map.comment);
1310	sid_peek_rid(&map.sid, &info->rid);
1311	return NT_STATUS_OK;
1312}
1313
1314NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods,
1315				   const DOM_SID *sid,
1316				   struct acct_info *info)
1317{
1318	GROUP_MAP map;
1319
1320	if (!pdb_getgrsid(&map, *sid))
1321		return NT_STATUS_NO_SUCH_ALIAS;
1322
1323	fstrcpy(map.comment, info->acct_desc);
1324
1325	if (!pdb_update_group_mapping_entry(&map))
1326		return NT_STATUS_ACCESS_DENIED;
1327
1328	return NT_STATUS_OK;
1329}
1330
1331NTSTATUS pdb_default_add_aliasmem(struct pdb_methods *methods,
1332				  const DOM_SID *alias, const DOM_SID *member)
1333{
1334	return add_aliasmem(alias, member);
1335}
1336
1337NTSTATUS pdb_default_del_aliasmem(struct pdb_methods *methods,
1338				  const DOM_SID *alias, const DOM_SID *member)
1339{
1340	return del_aliasmem(alias, member);
1341}
1342
1343NTSTATUS pdb_default_enum_aliasmem(struct pdb_methods *methods,
1344				   const DOM_SID *alias, DOM_SID **members,
1345				   int *num_members)
1346{
1347	return enum_aliasmem(alias, members, num_members);
1348}
1349
1350NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods,
1351				       const DOM_SID *members,
1352				       int num_members,
1353				       DOM_SID **aliases, int *num)
1354{
1355	return alias_memberships(members, num_members, aliases, num);
1356}
1357
1358/**********************************************************************
1359 no ops for passdb backends that don't implement group mapping
1360 *********************************************************************/
1361
1362NTSTATUS pdb_nop_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1363				 DOM_SID sid)
1364{
1365	return NT_STATUS_UNSUCCESSFUL;
1366}
1367
1368NTSTATUS pdb_nop_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1369				 gid_t gid)
1370{
1371	return NT_STATUS_UNSUCCESSFUL;
1372}
1373
1374NTSTATUS pdb_nop_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1375				 const char *name)
1376{
1377	return NT_STATUS_UNSUCCESSFUL;
1378}
1379
1380NTSTATUS pdb_nop_add_group_mapping_entry(struct pdb_methods *methods,
1381						GROUP_MAP *map)
1382{
1383	return NT_STATUS_UNSUCCESSFUL;
1384}
1385
1386NTSTATUS pdb_nop_update_group_mapping_entry(struct pdb_methods *methods,
1387						   GROUP_MAP *map)
1388{
1389	return NT_STATUS_UNSUCCESSFUL;
1390}
1391
1392NTSTATUS pdb_nop_delete_group_mapping_entry(struct pdb_methods *methods,
1393						   DOM_SID sid)
1394{
1395	return NT_STATUS_UNSUCCESSFUL;
1396}
1397
1398NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods,
1399					   enum SID_NAME_USE sid_name_use,
1400					   GROUP_MAP **rmap, int *num_entries,
1401					   BOOL unix_only)
1402{
1403	return NT_STATUS_UNSUCCESSFUL;
1404}
1405
1406