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  *  Copyright (C) Volker Lendecke              2006.
7  *  Copyright (C) Gerald Carter                2006.
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 3 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "includes.h"
24 #include "system/passwd.h"
25 #include "passdb.h"
26 #include "groupdb/mapping.h"
27 #include "../libcli/security/security.h"
28 #include "lib/winbind_util.h"
29 #include <tdb.h>
30 #include "groupdb/mapping_tdb.h"
31 
32 static const struct mapping_backend *backend;
33 
34 /*
35   initialise a group mapping backend
36  */
37 static bool init_group_mapping(void)
38 {
39 	if (backend != NULL) {
40 		/* already initialised */
41 		return True;
42 	}
43 
44         backend = groupdb_tdb_init();
45 
46 	return backend != NULL;
47 }
48 
49 /****************************************************************************
50 initialise first time the mapping list
51 ****************************************************************************/
52 NTSTATUS add_initial_entry(gid_t gid, const char *sid, enum lsa_SidType sid_name_use, const char *nt_name, const char *comment)
53 {
54 	NTSTATUS status;
55 	GROUP_MAP *map;
56 
57 	if(!init_group_mapping()) {
58 		DEBUG(0,("failed to initialize group mapping\n"));
59 		return NT_STATUS_UNSUCCESSFUL;
60 	}
61 
62 	map = talloc_zero(NULL, GROUP_MAP);
63 	if (!map) {
64 		return NT_STATUS_NO_MEMORY;
65 	}
66 
67 	map->gid=gid;
68 	if (!string_to_sid(&map->sid, sid)) {
69 		DEBUG(0, ("string_to_sid failed: %s", sid));
70 		status = NT_STATUS_UNSUCCESSFUL;
71 		goto done;
72 	}
73 
74 	map->sid_name_use=sid_name_use;
75 	map->nt_name = talloc_strdup(map, nt_name);
76 	if (!map->nt_name) {
77 		status = NT_STATUS_NO_MEMORY;
78 		goto done;
79 	}
80 
81 	if (comment) {
82 		map->comment = talloc_strdup(map, comment);
83 	} else {
84 		map->comment = talloc_strdup(map, "");
85 	}
86 	if (!map->comment) {
87 		status = NT_STATUS_NO_MEMORY;
88 		goto done;
89 	}
90 
91 	status = pdb_add_group_mapping_entry(map);
92 
93 done:
94 	TALLOC_FREE(map);
95 	return status;
96 }
97 
98 static NTSTATUS alias_memberships(const struct dom_sid *members, size_t num_members,
99 				  struct dom_sid **sids, size_t *num)
100 {
101 	size_t i;
102 
103 	*num = 0;
104 	*sids = NULL;
105 
106 	for (i=0; i<num_members; i++) {
107 		NTSTATUS status = backend->one_alias_membership(&members[i], sids, num);
108 		if (!NT_STATUS_IS_OK(status))
109 			return status;
110 	}
111 	return NT_STATUS_OK;
112 }
113 
114 struct aliasmem_closure {
115 	const struct dom_sid *alias;
116 	struct dom_sid **sids;
117 	size_t *num;
118 };
119 
120 
121 
122 /*
123  *
124  * High level functions
125  * better to use them than the lower ones.
126  *
127  * we are checking if the group is in the mapping file
128  * and if the group is an existing unix group
129  *
130  */
131 
132 /* get a domain group from it's SID */
133 
134 bool get_domain_group_from_sid(struct dom_sid sid, GROUP_MAP *map)
135 {
136 	struct group *grp;
137 	bool ret;
138 
139 	if(!init_group_mapping()) {
140 		DEBUG(0,("failed to initialize group mapping\n"));
141 		return(False);
142 	}
143 
144 	DEBUG(10, ("get_domain_group_from_sid\n"));
145 
146 	/* if the group is NOT in the database, it CAN NOT be a domain group */
147 
148 	become_root();
149 	ret = pdb_getgrsid(map, sid);
150 	unbecome_root();
151 
152 	/* special case check for rid 513 */
153 
154 	if ( !ret ) {
155 		uint32_t rid;
156 
157 		sid_peek_rid( &sid, &rid );
158 
159 		if ( rid == DOMAIN_RID_USERS ) {
160 			map->nt_name = talloc_strdup(map, "None");
161 			if (!map->nt_name) {
162 				return false;
163 			}
164 			map->comment = talloc_strdup(map, "Ordinary Users");
165 			if (!map->comment) {
166 				return false;
167 			}
168 			sid_copy( &map->sid, &sid );
169 			map->sid_name_use = SID_NAME_DOM_GRP;
170 			map->gid = (gid_t)-1;
171 			return True;
172 		}
173 		return False;
174 	}
175 
176 	DEBUG(10, ("get_domain_group_from_sid: SID found in passdb\n"));
177 
178 	/* if it's not a domain group, continue */
179 	if (map->sid_name_use!=SID_NAME_DOM_GRP) {
180 		return False;
181 	}
182 
183 	DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n"));
184 
185 	if (map->gid==-1) {
186 		return False;
187 	}
188 
189 	DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%lu\n",(unsigned long)map->gid));
190 
191 	grp = getgrgid(map->gid);
192 	if ( !grp ) {
193 		DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n"));
194 		return False;
195 	}
196 
197 	DEBUG(10, ("get_domain_group_from_sid: gid exists in UNIX security\n"));
198 
199 	return True;
200 }
201 
202 /****************************************************************************
203  Create a UNIX group on demand.
204 ****************************************************************************/
205 
206 int smb_create_group(const char *unix_group, gid_t *new_gid)
207 {
208 	const struct loadparm_substitution *lp_sub =
209 		loadparm_s3_global_substitution();
210 	char *add_script = NULL;
211 	int 	ret = -1;
212 	int 	fd = 0;
213 	int error = 0;
214 
215 	*new_gid = 0;
216 
217 	/* defer to scripts */
218 
219 	if ( *lp_add_group_script(talloc_tos(), lp_sub) ) {
220 		TALLOC_CTX *ctx = talloc_tos();
221 
222 		add_script = talloc_strdup(ctx,
223 					lp_add_group_script(ctx, lp_sub));
224 		if (!add_script) {
225 			return -1;
226 		}
227 		add_script = talloc_string_sub(ctx,
228 				add_script, "%g", unix_group);
229 		if (!add_script) {
230 			return -1;
231 		}
232 
233 		ret = smbrun(add_script, &fd, NULL);
234 		DEBUG(ret ? 0 : 3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
235 		if (ret == 0) {
236 			smb_nscd_flush_group_cache();
237 		}
238 		if (ret != 0)
239 			return ret;
240 
241 		if (fd != 0) {
242 			fstring output;
243 			ssize_t nread;
244 
245 			*new_gid = 0;
246 
247 			nread = read(fd, output, sizeof(output)-1);
248 			if (nread > 0) {
249 				output[nread] = '\0';
250 				*new_gid = (gid_t)smb_strtoul(output,
251 							      NULL,
252 							      10,
253 							      &error,
254 							      SMB_STR_STANDARD);
255 				if (error != 0) {
256 					*new_gid = 0;
257 					close(fd);
258 					return -1;
259 				}
260 			}
261 
262 			close(fd);
263 		}
264 
265 	}
266 
267 	if (*new_gid == 0) {
268 		struct group *grp = getgrnam(unix_group);
269 
270 		if (grp != NULL)
271 			*new_gid = grp->gr_gid;
272 	}
273 
274 	return ret;
275 }
276 
277 /****************************************************************************
278  Delete a UNIX group on demand.
279 ****************************************************************************/
280 
281 int smb_delete_group(const char *unix_group)
282 {
283 	const struct loadparm_substitution *lp_sub =
284 		loadparm_s3_global_substitution();
285 	char *del_script = NULL;
286 	int ret = -1;
287 
288 	/* defer to scripts */
289 
290 	if ( *lp_delete_group_script(talloc_tos(), lp_sub) ) {
291 		TALLOC_CTX *ctx = talloc_tos();
292 
293 		del_script = talloc_strdup(ctx,
294 				lp_delete_group_script(ctx, lp_sub));
295 		if (!del_script) {
296 			return -1;
297 		}
298 		del_script = talloc_string_sub(ctx,
299 				del_script, "%g", unix_group);
300 		if (!del_script) {
301 			return -1;
302 		}
303 		ret = smbrun(del_script, NULL, NULL);
304 		DEBUG(ret ? 0 : 3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
305 		if (ret == 0) {
306 			smb_nscd_flush_group_cache();
307 		}
308 		return ret;
309 	}
310 
311 	return -1;
312 }
313 
314 /****************************************************************************
315  Set a user's primary UNIX group.
316 ****************************************************************************/
317 
318 int smb_set_primary_group(const char *unix_group, const char* unix_user)
319 {
320 	const struct loadparm_substitution *lp_sub =
321 		loadparm_s3_global_substitution();
322 	char *add_script = NULL;
323 	int ret = -1;
324 
325 	/* defer to scripts */
326 
327 	if ( *lp_set_primary_group_script(talloc_tos(), lp_sub) ) {
328 		TALLOC_CTX *ctx = talloc_tos();
329 
330 		add_script = talloc_strdup(ctx,
331 				lp_set_primary_group_script(ctx, lp_sub));
332 		if (!add_script) {
333 			return -1;
334 		}
335 		add_script = talloc_all_string_sub(ctx,
336 				add_script, "%g", unix_group);
337 		if (!add_script) {
338 			return -1;
339 		}
340 		add_script = talloc_string_sub(ctx,
341 				add_script, "%u", unix_user);
342 		if (!add_script) {
343 			return -1;
344 		}
345 		ret = smbrun(add_script, NULL, NULL);
346 		flush_pwnam_cache();
347 		DEBUG(ret ? 0 : 3,("smb_set_primary_group: "
348 			 "Running the command `%s' gave %d\n",add_script,ret));
349 		if (ret == 0) {
350 			smb_nscd_flush_group_cache();
351 		}
352 		return ret;
353 	}
354 
355 	return -1;
356 }
357 
358 /****************************************************************************
359  Add a user to a UNIX group.
360 ****************************************************************************/
361 
362 int smb_add_user_group(const char *unix_group, const char *unix_user)
363 {
364 	const struct loadparm_substitution *lp_sub =
365 		loadparm_s3_global_substitution();
366 	char *add_script = NULL;
367 	int ret = -1;
368 
369 	/* defer to scripts */
370 
371 	if ( *lp_add_user_to_group_script(talloc_tos(), lp_sub) ) {
372 		TALLOC_CTX *ctx = talloc_tos();
373 
374 		add_script = talloc_strdup(ctx,
375 				lp_add_user_to_group_script(ctx, lp_sub));
376 		if (!add_script) {
377 			return -1;
378 		}
379 		add_script = talloc_string_sub(ctx,
380 				add_script, "%g", unix_group);
381 		if (!add_script) {
382 			return -1;
383 		}
384 		add_script = talloc_string_sub2(ctx,
385 				add_script, "%u", unix_user, true, false, true);
386 		if (!add_script) {
387 			return -1;
388 		}
389 		ret = smbrun(add_script, NULL, NULL);
390 		DEBUG(ret ? 0 : 3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
391 		if (ret == 0) {
392 			smb_nscd_flush_group_cache();
393 		}
394 		return ret;
395 	}
396 
397 	return -1;
398 }
399 
400 /****************************************************************************
401  Delete a user from a UNIX group
402 ****************************************************************************/
403 
404 int smb_delete_user_group(const char *unix_group, const char *unix_user)
405 {
406 	const struct loadparm_substitution *lp_sub =
407 		loadparm_s3_global_substitution();
408 	char *del_script = NULL;
409 	int ret = -1;
410 
411 	/* defer to scripts */
412 
413 	if ( *lp_delete_user_from_group_script(talloc_tos(), lp_sub) ) {
414 		TALLOC_CTX *ctx = talloc_tos();
415 
416 		del_script = talloc_strdup(ctx,
417 				lp_delete_user_from_group_script(ctx, lp_sub));
418 		if (!del_script) {
419 			return -1;
420 		}
421 		del_script = talloc_string_sub(ctx,
422 				del_script, "%g", unix_group);
423 		if (!del_script) {
424 			return -1;
425 		}
426 		del_script = talloc_string_sub2(ctx,
427 				del_script, "%u", unix_user, true, false, true);
428 		if (!del_script) {
429 			return -1;
430 		}
431 		ret = smbrun(del_script, NULL, NULL);
432 		DEBUG(ret ? 0 : 3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
433 		if (ret == 0) {
434 			smb_nscd_flush_group_cache();
435 		}
436 		return ret;
437 	}
438 
439 	return -1;
440 }
441 
442 
443 NTSTATUS pdb_default_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
444 				 struct dom_sid sid)
445 {
446 	if (!init_group_mapping()) {
447 		DEBUG(0,("failed to initialize group mapping\n"));
448 		return NT_STATUS_UNSUCCESSFUL;
449 	}
450 	return backend->get_group_map_from_sid(sid, map) ?
451 		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
452 }
453 
454 NTSTATUS pdb_default_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
455 				 gid_t gid)
456 {
457 	if (!init_group_mapping()) {
458 		DEBUG(0,("failed to initialize group mapping\n"));
459 		return NT_STATUS_UNSUCCESSFUL;
460 	}
461 	return backend->get_group_map_from_gid(gid, map) ?
462 		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
463 }
464 
465 NTSTATUS pdb_default_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
466 				 const char *name)
467 {
468 	if (!init_group_mapping()) {
469 		DEBUG(0,("failed to initialize group mapping\n"));
470 		return NT_STATUS_UNSUCCESSFUL;
471 	}
472 	return backend->get_group_map_from_ntname(name, map) ?
473 		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
474 }
475 
476 NTSTATUS pdb_default_add_group_mapping_entry(struct pdb_methods *methods,
477 						GROUP_MAP *map)
478 {
479 	if (!init_group_mapping()) {
480 		DEBUG(0,("failed to initialize group mapping\n"));
481 		return NT_STATUS_UNSUCCESSFUL;
482 	}
483 	return backend->add_mapping_entry(map, TDB_INSERT) ?
484 		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
485 }
486 
487 NTSTATUS pdb_default_update_group_mapping_entry(struct pdb_methods *methods,
488 						   GROUP_MAP *map)
489 {
490 	if (!init_group_mapping()) {
491 		DEBUG(0,("failed to initialize group mapping\n"));
492 		return NT_STATUS_UNSUCCESSFUL;
493 	}
494 	return backend->add_mapping_entry(map, TDB_REPLACE) ?
495 		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
496 }
497 
498 NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods,
499 						   struct dom_sid sid)
500 {
501 	if (!init_group_mapping()) {
502 		DEBUG(0,("failed to initialize group mapping\n"));
503 		return NT_STATUS_UNSUCCESSFUL;
504 	}
505 	return backend->group_map_remove(&sid) ?
506 		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
507 }
508 
509 NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods,
510 					const struct dom_sid *sid,
511 					enum lsa_SidType sid_name_use,
512 					GROUP_MAP ***pp_rmap,
513 					size_t *p_num_entries,
514 					bool unix_only)
515 {
516 	if (!init_group_mapping()) {
517 		DEBUG(0,("failed to initialize group mapping\n"));
518 		return NT_STATUS_UNSUCCESSFUL;
519 	}
520 	return backend->enum_group_mapping(sid, sid_name_use, pp_rmap, p_num_entries, unix_only) ?
521 		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
522 }
523 
524 NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
525 				  const char *name, uint32_t *rid)
526 {
527 	struct dom_sid sid;
528 	enum lsa_SidType type;
529 	uint32_t new_rid;
530 	gid_t gid;
531 	bool exists;
532 	GROUP_MAP *map;
533 	TALLOC_CTX *mem_ctx;
534 	NTSTATUS status;
535 
536 	DEBUG(10, ("Trying to create alias %s\n", name));
537 
538 	mem_ctx = talloc_new(NULL);
539 	if (mem_ctx == NULL) {
540 		return NT_STATUS_NO_MEMORY;
541 	}
542 
543 	exists = lookup_name(mem_ctx, name, LOOKUP_NAME_LOCAL,
544 			     NULL, NULL, &sid, &type);
545 
546 	if (exists) {
547 		status = NT_STATUS_ALIAS_EXISTS;
548 		goto done;
549 	}
550 
551 	if (!pdb_new_rid(&new_rid)) {
552 		DEBUG(0, ("Could not allocate a RID.\n"));
553 		status = NT_STATUS_ACCESS_DENIED;
554 		goto done;
555 	}
556 
557 	sid_compose(&sid, get_global_sam_sid(), new_rid);
558 
559 	if (!winbind_allocate_gid(&gid)) {
560 		DEBUG(3, ("Could not get a gid out of winbind - "
561 			  "wasted a rid :-(\n"));
562 		status = NT_STATUS_ACCESS_DENIED;
563 		goto done;
564 	}
565 
566 	DEBUG(10, ("Creating alias %s with gid %u and rid %u\n",
567 		   name, (unsigned int)gid, (unsigned int)new_rid));
568 
569 	map = talloc_zero(mem_ctx, GROUP_MAP);
570 	if (!map) {
571 		status = NT_STATUS_NO_MEMORY;
572 		goto done;
573 	}
574 
575 	map->gid = gid;
576 	sid_copy(&map->sid, &sid);
577 	map->sid_name_use = SID_NAME_ALIAS;
578 	map->nt_name = talloc_strdup(map, name);
579 	if (!map->nt_name) {
580 		status = NT_STATUS_NO_MEMORY;
581 		goto done;
582 	}
583 	map->comment = talloc_strdup(map, "");
584 	if (!map->comment) {
585 		status = NT_STATUS_NO_MEMORY;
586 		goto done;
587 	}
588 
589 	status = pdb_add_group_mapping_entry(map);
590 
591 	if (!NT_STATUS_IS_OK(status)) {
592 		DEBUG(0, ("Could not add group mapping entry for alias %s "
593 			  "(%s)\n", name, nt_errstr(status)));
594 		goto done;
595 	}
596 
597 	*rid = new_rid;
598 
599 done:
600 	TALLOC_FREE(mem_ctx);
601 	return status;
602 }
603 
604 NTSTATUS pdb_default_delete_alias(struct pdb_methods *methods,
605 				  const struct dom_sid *sid)
606 {
607 	return pdb_delete_group_mapping_entry(*sid);
608 }
609 
610 NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
611 				   const struct dom_sid *sid,
612 				   struct acct_info *info)
613 {
614 	NTSTATUS status = NT_STATUS_OK;
615 	GROUP_MAP *map;
616 
617 	map = talloc_zero(NULL, GROUP_MAP);
618 	if (!map) {
619 		return NT_STATUS_NO_MEMORY;
620 	}
621 
622 	if (!pdb_getgrsid(map, *sid)) {
623 		status = NT_STATUS_NO_SUCH_ALIAS;
624 		goto done;
625 	}
626 
627 	if ((map->sid_name_use != SID_NAME_ALIAS) &&
628 	    (map->sid_name_use != SID_NAME_WKN_GRP)) {
629 		struct dom_sid_buf buf;
630 		DEBUG(2, ("%s is a %s, expected an alias\n",
631 			  dom_sid_str_buf(sid, &buf),
632 			  sid_type_lookup(map->sid_name_use)));
633 		status = NT_STATUS_NO_SUCH_ALIAS;
634 		goto done;
635 	}
636 
637 	info->acct_name = talloc_move(info, &map->nt_name);
638 	if (!info->acct_name) {
639 		status = NT_STATUS_NO_MEMORY;
640 		goto done;
641 	}
642 	info->acct_desc = talloc_move(info, &map->comment);
643 	if (!info->acct_desc) {
644 		status = NT_STATUS_NO_MEMORY;
645 		goto done;
646 	}
647 	sid_peek_rid(&map->sid, &info->rid);
648 
649 done:
650 	TALLOC_FREE(map);
651 	return status;
652 }
653 
654 NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods,
655 				   const struct dom_sid *sid,
656 				   struct acct_info *info)
657 {
658 	NTSTATUS status;
659 	GROUP_MAP *map;
660 
661 	map = talloc_zero(NULL, GROUP_MAP);
662 	if (!map) {
663 		return NT_STATUS_NO_MEMORY;
664 	}
665 
666 	if (!pdb_getgrsid(map, *sid)) {
667 		status = NT_STATUS_NO_SUCH_ALIAS;
668 		goto done;
669 	}
670 
671 	map->nt_name = talloc_strdup(map, info->acct_name);
672 	if (!map->nt_name) {
673 		status = NT_STATUS_NO_MEMORY;
674 		goto done;
675 	}
676 	map->comment = talloc_strdup(map, info->acct_desc);
677 	if (!map->comment) {
678 		status = NT_STATUS_NO_MEMORY;
679 		goto done;
680 	}
681 
682 	status = pdb_update_group_mapping_entry(map);
683 
684 done:
685 	TALLOC_FREE(map);
686 	return status;
687 }
688 
689 NTSTATUS pdb_default_add_aliasmem(struct pdb_methods *methods,
690 				  const struct dom_sid *alias, const struct dom_sid *member)
691 {
692 	if (!init_group_mapping()) {
693 		DEBUG(0,("failed to initialize group mapping\n"));
694 		return NT_STATUS_UNSUCCESSFUL;
695 	}
696 	return backend->add_aliasmem(alias, member);
697 }
698 
699 NTSTATUS pdb_default_del_aliasmem(struct pdb_methods *methods,
700 				  const struct dom_sid *alias, const struct dom_sid *member)
701 {
702 	if (!init_group_mapping()) {
703 		DEBUG(0,("failed to initialize group mapping\n"));
704 		return NT_STATUS_UNSUCCESSFUL;
705 	}
706 	return backend->del_aliasmem(alias, member);
707 }
708 
709 NTSTATUS pdb_default_enum_aliasmem(struct pdb_methods *methods,
710 				   const struct dom_sid *alias, TALLOC_CTX *mem_ctx,
711 				   struct dom_sid **pp_members, size_t *p_num_members)
712 {
713 	if (!init_group_mapping()) {
714 		DEBUG(0,("failed to initialize group mapping\n"));
715 		return NT_STATUS_UNSUCCESSFUL;
716 	}
717 	return backend->enum_aliasmem(alias, mem_ctx, pp_members,
718 				      p_num_members);
719 }
720 
721 NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods,
722 				       TALLOC_CTX *mem_ctx,
723 				       const struct dom_sid *domain_sid,
724 				       const struct dom_sid *members,
725 				       size_t num_members,
726 				       uint32_t **pp_alias_rids,
727 				       size_t *p_num_alias_rids)
728 {
729 	struct dom_sid *alias_sids;
730 	size_t i, num_alias_sids;
731 	NTSTATUS result;
732 
733 	if (!init_group_mapping()) {
734 		DEBUG(0,("failed to initialize group mapping\n"));
735 		return NT_STATUS_UNSUCCESSFUL;
736 	}
737 
738 	alias_sids = NULL;
739 	num_alias_sids = 0;
740 
741 	result = alias_memberships(members, num_members,
742 				   &alias_sids, &num_alias_sids);
743 
744 	if (!NT_STATUS_IS_OK(result))
745 		return result;
746 
747 	*p_num_alias_rids = 0;
748 
749 	if (num_alias_sids == 0) {
750 		TALLOC_FREE(alias_sids);
751 		return NT_STATUS_OK;
752 	}
753 
754 	*pp_alias_rids = talloc_array(mem_ctx, uint32_t, num_alias_sids);
755 	if (*pp_alias_rids == NULL)
756 		return NT_STATUS_NO_MEMORY;
757 
758 	for (i=0; i<num_alias_sids; i++) {
759 		if (!sid_peek_check_rid(domain_sid, &alias_sids[i],
760 					&(*pp_alias_rids)[*p_num_alias_rids]))
761 			continue;
762 		*p_num_alias_rids += 1;
763 	}
764 
765 	TALLOC_FREE(alias_sids);
766 
767 	return NT_STATUS_OK;
768 }
769 
770 /**********************************************************************
771  no ops for passdb backends that don't implement group mapping
772  *********************************************************************/
773 
774 NTSTATUS pdb_nop_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
775 				 struct dom_sid sid)
776 {
777 	return NT_STATUS_UNSUCCESSFUL;
778 }
779 
780 NTSTATUS pdb_nop_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
781 				 gid_t gid)
782 {
783 	return NT_STATUS_UNSUCCESSFUL;
784 }
785 
786 NTSTATUS pdb_nop_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
787 				 const char *name)
788 {
789 	return NT_STATUS_UNSUCCESSFUL;
790 }
791 
792 NTSTATUS pdb_nop_add_group_mapping_entry(struct pdb_methods *methods,
793 						GROUP_MAP *map)
794 {
795 	return NT_STATUS_UNSUCCESSFUL;
796 }
797 
798 NTSTATUS pdb_nop_update_group_mapping_entry(struct pdb_methods *methods,
799 						   GROUP_MAP *map)
800 {
801 	return NT_STATUS_UNSUCCESSFUL;
802 }
803 
804 NTSTATUS pdb_nop_delete_group_mapping_entry(struct pdb_methods *methods,
805 						   struct dom_sid sid)
806 {
807 	return NT_STATUS_UNSUCCESSFUL;
808 }
809 
810 NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods,
811 					   enum lsa_SidType sid_name_use,
812 					   GROUP_MAP **rmap, size_t *num_entries,
813 					   bool unix_only)
814 {
815 	return NT_STATUS_UNSUCCESSFUL;
816 }
817 
818 /**
819 * @brief Add a new group mapping
820 *
821 * @param[in] gid gid to use to store the mapping. If gid is 0,
822 *                new gid will be allocated from winbind
823 *
824 * @return Normal NTSTATUS return
825 */
826 NTSTATUS pdb_create_builtin_alias(uint32_t rid, gid_t gid)
827 {
828 	struct dom_sid sid;
829 	enum lsa_SidType type;
830 	gid_t gidformap;
831 	GROUP_MAP *map;
832 	NTSTATUS status;
833 	const char *name = NULL;
834 
835 	DEBUG(10, ("Trying to create builtin alias %d\n", rid));
836 
837 	if ( !sid_compose( &sid, &global_sid_Builtin, rid ) ) {
838 		return NT_STATUS_NO_SUCH_ALIAS;
839 	}
840 
841 	/* use map as overall temp mem context */
842 	map = talloc_zero(NULL, GROUP_MAP);
843 	if (!map) {
844 		return NT_STATUS_NO_MEMORY;
845 	}
846 
847 	if (!lookup_sid(map, &sid, NULL, &name, &type)) {
848 		status = NT_STATUS_NO_SUCH_ALIAS;
849 		goto done;
850 	}
851 
852 	if (gid == 0) {
853 		if (!winbind_allocate_gid(&gidformap)) {
854 			DEBUG(3, ("pdb_create_builtin_alias: Could not get a "
855 				  "gid out of winbind\n"));
856 			status = NT_STATUS_ACCESS_DENIED;
857 			goto done;
858 		}
859 	} else {
860 		gidformap = gid;
861 	}
862 
863 	DEBUG(10, ("Creating alias %s with gid %u\n", name,
864 		   (unsigned) gidformap));
865 
866 	map->gid = gidformap;
867 	sid_copy(&map->sid, &sid);
868 	map->sid_name_use = SID_NAME_ALIAS;
869 	map->nt_name = talloc_strdup(map, name);
870 	if (!map->nt_name) {
871 		status = NT_STATUS_NO_MEMORY;
872 		goto done;
873 	}
874 	map->comment = talloc_strdup(map, "");
875 	if (!map->comment) {
876 		status = NT_STATUS_NO_MEMORY;
877 		goto done;
878 	}
879 
880 	status = pdb_add_group_mapping_entry(map);
881 
882 	if (!NT_STATUS_IS_OK(status)) {
883 		DEBUG(0, ("pdb_create_builtin_alias: Could not add group mapping entry for alias %d "
884 			  "(%s)\n", rid, nt_errstr(status)));
885 	}
886 
887 done:
888 	TALLOC_FREE(map);
889 	return status;
890 }
891 
892 
893