s3-passdb: Respect LOOKUP_NAME_GROUP flag in sid lookup.
[Samba.git] / source3 / passdb / lookup_sid.c
blob3f99ee1e4e053db928ed2a2ca48e0aa12080e76f
1 /*
2 Unix SMB/CIFS implementation.
3 uid/user handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Gerald (Jerry) Carter 2003
6 Copyright (C) Volker Lendecke 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "passdb.h"
24 #include "../librpc/gen_ndr/ndr_security.h"
25 #include "secrets.h"
26 #include "../lib/util/memcache.h"
27 #include "idmap_cache.h"
28 #include "../libcli/security/security.h"
29 #include "lib/winbind_util.h"
30 #include "../librpc/gen_ndr/idmap.h"
32 /*****************************************************************
33 Dissect a user-provided name into domain, name, sid and type.
35 If an explicit domain name was given in the form domain\user, it
36 has to try that. If no explicit domain name was given, we have
37 to do guesswork.
38 *****************************************************************/
40 bool lookup_name(TALLOC_CTX *mem_ctx,
41 const char *full_name, int flags,
42 const char **ret_domain, const char **ret_name,
43 struct dom_sid *ret_sid, enum lsa_SidType *ret_type)
45 char *p;
46 const char *tmp;
47 const char *domain = NULL;
48 const char *name = NULL;
49 uint32_t rid;
50 struct dom_sid sid;
51 enum lsa_SidType type;
52 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
54 if (tmp_ctx == NULL) {
55 DEBUG(0, ("talloc_new failed\n"));
56 return false;
59 p = strchr_m(full_name, '\\');
61 if (p != NULL) {
62 domain = talloc_strndup(tmp_ctx, full_name,
63 PTR_DIFF(p, full_name));
64 name = talloc_strdup(tmp_ctx, p+1);
65 } else {
66 domain = talloc_strdup(tmp_ctx, "");
67 name = talloc_strdup(tmp_ctx, full_name);
70 if ((domain == NULL) || (name == NULL)) {
71 DEBUG(0, ("talloc failed\n"));
72 TALLOC_FREE(tmp_ctx);
73 return false;
76 DEBUG(10,("lookup_name: %s => domain=[%s], name=[%s]\n",
77 full_name, domain, name));
78 DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
80 if ((flags & LOOKUP_NAME_DOMAIN) &&
81 strequal(domain, get_global_sam_name()))
84 /* It's our own domain, lookup the name in passdb */
85 if (lookup_global_sam_name(name, flags, &rid, &type)) {
86 sid_compose(&sid, get_global_sam_sid(), rid);
87 goto ok;
89 TALLOC_FREE(tmp_ctx);
90 return false;
93 if ((flags & LOOKUP_NAME_BUILTIN) &&
94 strequal(domain, builtin_domain_name()))
96 if (strlen(name) == 0) {
97 /* Swap domain and name */
98 tmp = name; name = domain; domain = tmp;
99 sid_copy(&sid, &global_sid_Builtin);
100 type = SID_NAME_DOMAIN;
101 goto ok;
104 /* Explicit request for a name in BUILTIN */
105 if (lookup_builtin_name(name, &rid)) {
106 sid_compose(&sid, &global_sid_Builtin, rid);
107 type = SID_NAME_ALIAS;
108 goto ok;
110 TALLOC_FREE(tmp_ctx);
111 return false;
114 /* Try the explicit winbind lookup first, don't let it guess the
115 * domain yet at this point yet. This comes later. */
117 if ((domain[0] != '\0') &&
118 (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
119 (winbind_lookup_name(domain, name, &sid, &type))) {
120 goto ok;
123 if (((flags & (LOOKUP_NAME_NO_NSS|LOOKUP_NAME_GROUP)) == 0)
124 && strequal(domain, unix_users_domain_name())) {
125 if (lookup_unix_user_name(name, &sid)) {
126 type = SID_NAME_USER;
127 goto ok;
129 TALLOC_FREE(tmp_ctx);
130 return false;
133 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
134 && strequal(domain, unix_groups_domain_name())) {
135 if (lookup_unix_group_name(name, &sid)) {
136 type = SID_NAME_DOM_GRP;
137 goto ok;
139 TALLOC_FREE(tmp_ctx);
140 return false;
143 if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
144 TALLOC_FREE(tmp_ctx);
145 return false;
148 /* Now the guesswork begins, we haven't been given an explicit
149 * domain. Try the sequence as documented on
150 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
151 * November 27, 2005 */
153 /* 1. well-known names */
155 if ((flags & LOOKUP_NAME_WKN) &&
156 lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
158 type = SID_NAME_WKN_GRP;
159 goto ok;
162 /* 2. Builtin domain as such */
164 if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
165 strequal(name, builtin_domain_name()))
167 /* Swap domain and name */
168 tmp = name; name = domain; domain = tmp;
169 sid_copy(&sid, &global_sid_Builtin);
170 type = SID_NAME_DOMAIN;
171 goto ok;
174 /* 3. Account domain */
176 if ((flags & LOOKUP_NAME_DOMAIN) &&
177 strequal(name, get_global_sam_name()))
179 if (!secrets_fetch_domain_sid(name, &sid)) {
180 DEBUG(3, ("Could not fetch my SID\n"));
181 TALLOC_FREE(tmp_ctx);
182 return false;
184 /* Swap domain and name */
185 tmp = name; name = domain; domain = tmp;
186 type = SID_NAME_DOMAIN;
187 goto ok;
190 /* 4. Primary domain */
192 if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
193 strequal(name, lp_workgroup()))
195 if (!secrets_fetch_domain_sid(name, &sid)) {
196 DEBUG(3, ("Could not fetch the domain SID\n"));
197 TALLOC_FREE(tmp_ctx);
198 return false;
200 /* Swap domain and name */
201 tmp = name; name = domain; domain = tmp;
202 type = SID_NAME_DOMAIN;
203 goto ok;
206 /* 5. Trusted domains as such, to me it looks as if members don't do
207 this, tested an XP workstation in a NT domain -- vl */
209 if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
210 (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
212 /* Swap domain and name */
213 tmp = name; name = domain; domain = tmp;
214 type = SID_NAME_DOMAIN;
215 goto ok;
218 /* 6. Builtin aliases */
220 if ((flags & LOOKUP_NAME_BUILTIN) &&
221 lookup_builtin_name(name, &rid))
223 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
224 sid_compose(&sid, &global_sid_Builtin, rid);
225 type = SID_NAME_ALIAS;
226 goto ok;
229 /* 7. Local systems' SAM (DCs don't have a local SAM) */
230 /* 8. Primary SAM (On members, this is the domain) */
232 /* Both cases are done by looking at our passdb */
234 if ((flags & LOOKUP_NAME_DOMAIN) &&
235 lookup_global_sam_name(name, flags, &rid, &type))
237 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
238 sid_compose(&sid, get_global_sam_sid(), rid);
239 goto ok;
242 /* Now our local possibilities are exhausted. */
244 if (!(flags & LOOKUP_NAME_REMOTE)) {
245 TALLOC_FREE(tmp_ctx);
246 return false;
249 /* If we are not a DC, we have to ask in our primary domain. Let
250 * winbind do that. */
252 if (!IS_DC &&
253 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
254 domain = talloc_strdup(tmp_ctx, lp_workgroup());
255 goto ok;
258 /* 9. Trusted domains */
260 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
261 * that (yet), but give it a chance. */
263 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
264 struct dom_sid dom_sid;
265 enum lsa_SidType domain_type;
267 if (type == SID_NAME_DOMAIN) {
268 /* Swap name and type */
269 tmp = name; name = domain; domain = tmp;
270 goto ok;
273 /* Here we have to cope with a little deficiency in the
274 * winbind API: We have to ask it again for the name of the
275 * domain it figured out itself. Maybe fix that later... */
277 sid_copy(&dom_sid, &sid);
278 sid_split_rid(&dom_sid, NULL);
280 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
281 &domain_type) ||
282 (domain_type != SID_NAME_DOMAIN)) {
283 DEBUG(2, ("winbind could not find the domain's name "
284 "it just looked up for us\n"));
285 TALLOC_FREE(tmp_ctx);
286 return false;
288 goto ok;
291 /* 10. Don't translate */
293 /* 11. Ok, windows would end here. Samba has two more options:
294 Unmapped users and unmapped groups */
296 if (((flags & (LOOKUP_NAME_NO_NSS|LOOKUP_NAME_GROUP)) == 0)
297 && lookup_unix_user_name(name, &sid)) {
298 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
299 type = SID_NAME_USER;
300 goto ok;
303 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
304 && lookup_unix_group_name(name, &sid)) {
305 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
306 type = SID_NAME_DOM_GRP;
307 goto ok;
311 * Ok, all possibilities tried. Fail.
314 TALLOC_FREE(tmp_ctx);
315 return false;
318 if ((domain == NULL) || (name == NULL)) {
319 DEBUG(0, ("talloc failed\n"));
320 TALLOC_FREE(tmp_ctx);
321 return false;
325 * Hand over the results to the talloc context we've been given.
328 if ((ret_name != NULL) &&
329 !(*ret_name = talloc_strdup(mem_ctx, name))) {
330 DEBUG(0, ("talloc failed\n"));
331 TALLOC_FREE(tmp_ctx);
332 return false;
335 if (ret_domain != NULL) {
336 char *tmp_dom;
337 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
338 DEBUG(0, ("talloc failed\n"));
339 TALLOC_FREE(tmp_ctx);
340 return false;
342 if (!strupper_m(tmp_dom)) {
343 TALLOC_FREE(tmp_ctx);
344 return false;
346 *ret_domain = tmp_dom;
349 if (ret_sid != NULL) {
350 sid_copy(ret_sid, &sid);
353 if (ret_type != NULL) {
354 *ret_type = type;
357 TALLOC_FREE(tmp_ctx);
358 return true;
361 /************************************************************************
362 Names from smb.conf can be unqualified. eg. valid users = foo
363 These names should never map to a remote name. Try global_sam_name()\foo,
364 and then "Unix Users"\foo (or "Unix Groups"\foo).
365 ************************************************************************/
367 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
368 const char *full_name, int flags,
369 const char **ret_domain, const char **ret_name,
370 struct dom_sid *ret_sid, enum lsa_SidType *ret_type)
372 char *qualified_name;
373 const char *p;
375 /* NB. No winbindd_separator here as lookup_name needs \\' */
376 if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
378 /* The name is already qualified with a domain. */
380 if (*lp_winbind_separator() != '\\') {
381 char *tmp;
383 /* lookup_name() needs '\\' as a separator */
385 tmp = talloc_strdup(mem_ctx, full_name);
386 if (!tmp) {
387 return false;
389 tmp[p - full_name] = '\\';
390 full_name = tmp;
393 return lookup_name(mem_ctx, full_name, flags,
394 ret_domain, ret_name,
395 ret_sid, ret_type);
398 /* Try with winbind default domain name. */
399 if (lp_winbind_use_default_domain()) {
400 bool ok;
402 qualified_name = talloc_asprintf(mem_ctx,
403 "%s\\%s",
404 lp_workgroup(),
405 full_name);
406 if (qualified_name == NULL) {
407 return false;
410 ok = lookup_name(mem_ctx,
411 qualified_name,
412 flags,
413 ret_domain,
414 ret_name,
415 ret_sid,
416 ret_type);
417 if (ok) {
418 return true;
422 /* Try with our own SAM name. */
423 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
424 get_global_sam_name(),
425 full_name );
426 if (!qualified_name) {
427 return false;
430 if (lookup_name(mem_ctx, qualified_name, flags,
431 ret_domain, ret_name,
432 ret_sid, ret_type)) {
433 return true;
436 /* Finally try with "Unix Users" or "Unix Group" */
437 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
438 flags & LOOKUP_NAME_GROUP ?
439 unix_groups_domain_name() :
440 unix_users_domain_name(),
441 full_name );
442 if (!qualified_name) {
443 return false;
446 return lookup_name(mem_ctx, qualified_name, flags,
447 ret_domain, ret_name,
448 ret_sid, ret_type);
451 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
452 const struct dom_sid *domain_sid,
453 int num_rids, uint32_t *rids,
454 const char **domain_name,
455 const char **names, enum lsa_SidType *types)
457 int i;
458 const char **my_names;
459 enum lsa_SidType *my_types;
460 TALLOC_CTX *tmp_ctx;
462 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
463 return false;
466 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
467 domain_name, &my_names, &my_types)) {
468 *domain_name = "";
469 for (i=0; i<num_rids; i++) {
470 names[i] = "";
471 types[i] = SID_NAME_UNKNOWN;
473 TALLOC_FREE(tmp_ctx);
474 return true;
477 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
478 TALLOC_FREE(tmp_ctx);
479 return false;
483 * winbind_lookup_rids allocates its own array. We've been given the
484 * array, so copy it over
487 for (i=0; i<num_rids; i++) {
488 if (my_names[i] == NULL) {
489 TALLOC_FREE(tmp_ctx);
490 return false;
492 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
493 TALLOC_FREE(tmp_ctx);
494 return false;
496 types[i] = my_types[i];
498 TALLOC_FREE(tmp_ctx);
499 return true;
502 static bool lookup_rids(TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid,
503 int num_rids, uint32_t *rids,
504 const char **domain_name,
505 const char ***names, enum lsa_SidType **types)
507 int i;
509 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
510 sid_string_dbg(domain_sid)));
512 if (num_rids) {
513 *names = talloc_zero_array(mem_ctx, const char *, num_rids);
514 *types = talloc_array(mem_ctx, enum lsa_SidType, num_rids);
516 if ((*names == NULL) || (*types == NULL)) {
517 return false;
520 for (i = 0; i < num_rids; i++)
521 (*types)[i] = SID_NAME_UNKNOWN;
522 } else {
523 *names = NULL;
524 *types = NULL;
527 if (sid_check_is_our_sam(domain_sid)) {
528 NTSTATUS result;
530 if (*domain_name == NULL) {
531 *domain_name = talloc_strdup(
532 mem_ctx, get_global_sam_name());
535 if (*domain_name == NULL) {
536 return false;
539 become_root();
540 result = pdb_lookup_rids(domain_sid, num_rids, rids,
541 *names, *types);
542 unbecome_root();
544 return (NT_STATUS_IS_OK(result) ||
545 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
546 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
549 if (sid_check_is_builtin(domain_sid)) {
551 if (*domain_name == NULL) {
552 *domain_name = talloc_strdup(
553 mem_ctx, builtin_domain_name());
556 if (*domain_name == NULL) {
557 return false;
560 for (i=0; i<num_rids; i++) {
561 if (lookup_builtin_rid(*names, rids[i],
562 &(*names)[i])) {
563 if ((*names)[i] == NULL) {
564 return false;
566 (*types)[i] = SID_NAME_ALIAS;
567 } else {
568 (*types)[i] = SID_NAME_UNKNOWN;
571 return true;
574 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
575 for (i=0; i<num_rids; i++) {
576 struct dom_sid sid;
577 sid_compose(&sid, domain_sid, rids[i]);
578 if (lookup_wellknown_sid(mem_ctx, &sid,
579 domain_name, &(*names)[i])) {
580 if ((*names)[i] == NULL) {
581 return false;
583 (*types)[i] = SID_NAME_WKN_GRP;
584 } else {
585 (*types)[i] = SID_NAME_UNKNOWN;
588 return true;
591 if (sid_check_is_unix_users(domain_sid)) {
592 if (*domain_name == NULL) {
593 *domain_name = talloc_strdup(
594 mem_ctx, unix_users_domain_name());
595 if (*domain_name == NULL) {
596 return false;
599 for (i=0; i<num_rids; i++) {
600 (*names)[i] = talloc_strdup(
601 (*names), uidtoname(rids[i]));
602 if ((*names)[i] == NULL) {
603 return false;
605 (*types)[i] = SID_NAME_USER;
607 return true;
610 if (sid_check_is_unix_groups(domain_sid)) {
611 if (*domain_name == NULL) {
612 *domain_name = talloc_strdup(
613 mem_ctx, unix_groups_domain_name());
614 if (*domain_name == NULL) {
615 return false;
618 for (i=0; i<num_rids; i++) {
619 (*names)[i] = talloc_strdup(
620 (*names), gidtoname(rids[i]));
621 if ((*names)[i] == NULL) {
622 return false;
624 (*types)[i] = SID_NAME_DOM_GRP;
626 return true;
629 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
630 domain_name, *names, *types);
634 * Is the SID a domain as such? If yes, lookup its name.
637 static bool lookup_as_domain(const struct dom_sid *sid, TALLOC_CTX *mem_ctx,
638 const char **name)
640 const char *tmp;
641 enum lsa_SidType type;
643 if (sid_check_is_our_sam(sid)) {
644 *name = talloc_strdup(mem_ctx, get_global_sam_name());
645 return true;
648 if (sid_check_is_builtin(sid)) {
649 *name = talloc_strdup(mem_ctx, builtin_domain_name());
650 return true;
653 if (sid_check_is_wellknown_domain(sid, &tmp)) {
654 *name = talloc_strdup(mem_ctx, tmp);
655 return true;
658 if (sid_check_is_unix_users(sid)) {
659 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
660 return true;
663 if (sid_check_is_unix_groups(sid)) {
664 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
665 return true;
668 if (sid->num_auths != 4) {
669 /* This can't be a domain */
670 return false;
673 if (IS_DC) {
674 uint32_t i, num_domains;
675 struct trustdom_info **domains;
677 /* This is relatively expensive, but it happens only on DCs
678 * and for SIDs that have 4 sub-authorities and thus look like
679 * domains */
681 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
682 &num_domains,
683 &domains))) {
684 return false;
687 for (i=0; i<num_domains; i++) {
688 if (dom_sid_equal(sid, &domains[i]->sid)) {
689 *name = talloc_strdup(mem_ctx,
690 domains[i]->name);
691 return true;
694 return false;
697 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
698 (type == SID_NAME_DOMAIN)) {
699 *name = tmp;
700 return true;
703 return false;
707 * This tries to implement the rather weird rules for the lsa_lookup level
708 * parameter.
710 * This is as close as we can get to what W2k3 does. With this we survive the
711 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
712 * different, but I assume that's just being too liberal. For example, W2k3
713 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
714 * whereas NT4 does the same as level 1 (I think). I did not fully test that
715 * with NT4, this is what w2k3 does.
717 * Level 1: Ask everywhere
718 * Level 2: Ask domain and trusted domains, no builtin and wkn
719 * Level 3: Only ask domain
720 * Level 4: W2k3ad: Only ask AD trusts
721 * Level 5: Only ask transitive forest trusts
722 * Level 6: Like 4
725 static bool check_dom_sid_to_level(const struct dom_sid *sid, int level)
727 int ret = false;
729 switch(level) {
730 case 1:
731 ret = true;
732 break;
733 case 2:
734 ret = (!sid_check_is_builtin(sid) &&
735 !sid_check_is_wellknown_domain(sid, NULL));
736 break;
737 case 3:
738 case 4:
739 case 6:
740 ret = sid_check_is_our_sam(sid);
741 break;
742 case 5:
743 ret = false;
744 break;
747 DEBUG(10, ("%s SID %s in level %d\n",
748 ret ? "Accepting" : "Rejecting",
749 sid_string_dbg(sid), level));
750 return ret;
754 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
755 * references to domains, it is explicitly made for this.
757 * This attempts to be as efficient as possible: It collects all SIDs
758 * belonging to a domain and hands them in bulk to the appropriate lookup
759 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
760 * *hugely* from this.
763 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
764 const struct dom_sid **sids, int level,
765 struct lsa_dom_info **ret_domains,
766 struct lsa_name_info **ret_names)
768 TALLOC_CTX *tmp_ctx;
769 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
770 struct lsa_name_info *name_infos;
771 struct lsa_dom_info *dom_infos = NULL;
773 int i, j;
775 if (!(tmp_ctx = talloc_new(mem_ctx))) {
776 DEBUG(0, ("talloc_new failed\n"));
777 return NT_STATUS_NO_MEMORY;
780 if (num_sids) {
781 name_infos = talloc_array(mem_ctx, struct lsa_name_info, num_sids);
782 if (name_infos == NULL) {
783 result = NT_STATUS_NO_MEMORY;
784 goto fail;
786 } else {
787 name_infos = NULL;
790 dom_infos = talloc_zero_array(mem_ctx, struct lsa_dom_info,
791 LSA_REF_DOMAIN_LIST_MULTIPLIER);
792 if (dom_infos == NULL) {
793 result = NT_STATUS_NO_MEMORY;
794 goto fail;
797 /* First build up the data structures:
799 * dom_infos is a list of domains referenced in the list of
800 * SIDs. Later we will walk the list of domains and look up the RIDs
801 * in bulk.
803 * name_infos is a shadow-copy of the SIDs array to collect the real
804 * data.
806 * dom_info->idxs is an index into the name_infos array. The
807 * difficulty we have here is that we need to keep the SIDs the client
808 * asked for in the same order for the reply
811 for (i=0; i<num_sids; i++) {
812 struct dom_sid sid;
813 uint32_t rid = 0;
814 const char *domain_name = NULL;
816 sid_copy(&sid, sids[i]);
817 name_infos[i].type = SID_NAME_USE_NONE;
819 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
820 /* We can't push that through the normal lookup
821 * process, as this would reference illegal
822 * domains.
824 * For example S-1-5-32 would end up referencing
825 * domain S-1-5- with RID 32 which is clearly wrong.
827 if (domain_name == NULL) {
828 result = NT_STATUS_NO_MEMORY;
829 goto fail;
832 name_infos[i].rid = 0;
833 name_infos[i].type = SID_NAME_DOMAIN;
834 name_infos[i].name = NULL;
836 if (sid_check_is_builtin(&sid)) {
837 /* Yes, W2k3 returns "BUILTIN" both as domain
838 * and name here */
839 name_infos[i].name = talloc_strdup(
840 name_infos, builtin_domain_name());
841 if (name_infos[i].name == NULL) {
842 result = NT_STATUS_NO_MEMORY;
843 goto fail;
846 } else {
847 /* This is a normal SID with rid component */
848 if (!sid_split_rid(&sid, &rid)) {
849 result = NT_STATUS_INVALID_SID;
850 goto fail;
854 if (!check_dom_sid_to_level(&sid, level)) {
855 name_infos[i].rid = 0;
856 name_infos[i].type = SID_NAME_UNKNOWN;
857 name_infos[i].name = NULL;
858 continue;
861 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
862 if (!dom_infos[j].valid) {
863 break;
865 if (dom_sid_equal(&sid, &dom_infos[j].sid)) {
866 break;
870 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
871 /* TODO: What's the right error message here? */
872 result = NT_STATUS_NONE_MAPPED;
873 goto fail;
876 if (!dom_infos[j].valid) {
877 /* We found a domain not yet referenced, create a new
878 * ref. */
879 dom_infos[j].valid = true;
880 sid_copy(&dom_infos[j].sid, &sid);
882 if (domain_name != NULL) {
883 /* This name was being found above in the case
884 * when we found a domain SID */
885 dom_infos[j].name =
886 talloc_strdup(dom_infos, domain_name);
887 if (dom_infos[j].name == NULL) {
888 result = NT_STATUS_NO_MEMORY;
889 goto fail;
891 } else {
892 /* lookup_rids will take care of this */
893 dom_infos[j].name = NULL;
897 name_infos[i].dom_idx = j;
899 if (name_infos[i].type == SID_NAME_USE_NONE) {
900 name_infos[i].rid = rid;
902 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
903 &dom_infos[j].num_idxs);
905 if (dom_infos[j].idxs == NULL) {
906 result = NT_STATUS_NO_MEMORY;
907 goto fail;
912 /* Iterate over the domains found */
914 for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
915 uint32_t *rids;
916 const char *domain_name = NULL;
917 const char **names;
918 enum lsa_SidType *types;
919 struct lsa_dom_info *dom = &dom_infos[i];
921 if (!dom->valid) {
922 /* No domains left, we're done */
923 break;
926 if (dom->num_idxs == 0) {
928 * This happens only if the only sid related to
929 * this domain is the domain sid itself, which
930 * is mapped to SID_NAME_DOMAIN above.
932 continue;
935 if (!(rids = talloc_array(tmp_ctx, uint32_t, dom->num_idxs))) {
936 result = NT_STATUS_NO_MEMORY;
937 goto fail;
940 for (j=0; j<dom->num_idxs; j++) {
941 rids[j] = name_infos[dom->idxs[j]].rid;
944 if (!lookup_rids(tmp_ctx, &dom->sid,
945 dom->num_idxs, rids, &domain_name,
946 &names, &types)) {
947 result = NT_STATUS_NO_MEMORY;
948 goto fail;
951 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
952 result = NT_STATUS_NO_MEMORY;
953 goto fail;
956 for (j=0; j<dom->num_idxs; j++) {
957 int idx = dom->idxs[j];
958 name_infos[idx].type = types[j];
959 if (types[j] != SID_NAME_UNKNOWN) {
960 name_infos[idx].name =
961 talloc_strdup(name_infos, names[j]);
962 if (name_infos[idx].name == NULL) {
963 result = NT_STATUS_NO_MEMORY;
964 goto fail;
966 } else {
967 name_infos[idx].name = NULL;
972 *ret_domains = dom_infos;
973 *ret_names = name_infos;
974 TALLOC_FREE(tmp_ctx);
975 return NT_STATUS_OK;
977 fail:
978 TALLOC_FREE(dom_infos);
979 TALLOC_FREE(name_infos);
980 TALLOC_FREE(tmp_ctx);
981 return result;
984 /*****************************************************************
985 *THE CANONICAL* convert SID to name function.
986 *****************************************************************/
988 bool lookup_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
989 const char **ret_domain, const char **ret_name,
990 enum lsa_SidType *ret_type)
992 struct lsa_dom_info *domain;
993 struct lsa_name_info *name;
994 TALLOC_CTX *tmp_ctx;
995 bool ret = false;
997 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
999 if (!(tmp_ctx = talloc_new(mem_ctx))) {
1000 DEBUG(0, ("talloc_new failed\n"));
1001 return false;
1004 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
1005 &domain, &name))) {
1006 goto done;
1009 if (name->type == SID_NAME_UNKNOWN) {
1010 goto done;
1013 if ((ret_domain != NULL) &&
1014 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
1015 goto done;
1018 if ((ret_name != NULL) &&
1019 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
1020 goto done;
1023 if (ret_type != NULL) {
1024 *ret_type = name->type;
1027 ret = true;
1029 done:
1030 if (ret) {
1031 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
1032 domain->name, name->name, name->type));
1033 } else {
1034 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
1036 TALLOC_FREE(tmp_ctx);
1037 return ret;
1040 /*****************************************************************
1041 Id mapping cache. This is to avoid Winbind mappings already
1042 seen by smbd to be queried too frequently, keeping winbindd
1043 busy, and blocking smbd while winbindd is busy with other
1044 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1045 modified to use linked lists by jra.
1046 *****************************************************************/
1049 /*****************************************************************
1050 *THE LEGACY* convert uid_t to SID function.
1051 *****************************************************************/
1053 static void legacy_uid_to_sid(struct dom_sid *psid, uid_t uid)
1055 bool ret;
1056 struct unixid id;
1058 ZERO_STRUCTP(psid);
1060 id.id = uid;
1061 id.type = ID_TYPE_UID;
1063 become_root();
1064 ret = pdb_id_to_sid(&id, psid);
1065 unbecome_root();
1067 if (ret) {
1068 /* This is a mapped user */
1069 goto done;
1072 /* This is an unmapped user */
1074 uid_to_unix_users_sid(uid, psid);
1077 struct unixid xid = {
1078 .id = uid, .type = ID_TYPE_UID
1080 idmap_cache_set_sid2unixid(psid, &xid);
1083 done:
1084 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1085 sid_string_dbg(psid)));
1087 return;
1090 /*****************************************************************
1091 *THE LEGACY* convert gid_t to SID function.
1092 *****************************************************************/
1094 static void legacy_gid_to_sid(struct dom_sid *psid, gid_t gid)
1096 bool ret;
1097 struct unixid id;
1099 ZERO_STRUCTP(psid);
1101 id.id = gid;
1102 id.type = ID_TYPE_GID;
1104 become_root();
1105 ret = pdb_id_to_sid(&id, psid);
1106 unbecome_root();
1108 if (ret) {
1109 /* This is a mapped group */
1110 goto done;
1113 /* This is an unmapped group */
1115 gid_to_unix_groups_sid(gid, psid);
1118 struct unixid xid = {
1119 .id = gid, .type = ID_TYPE_GID
1121 idmap_cache_set_sid2unixid(psid, &xid);
1124 done:
1125 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1126 sid_string_dbg(psid)));
1128 return;
1131 /*****************************************************************
1132 *THE LEGACY* convert SID to id function.
1133 *****************************************************************/
1135 static bool legacy_sid_to_unixid(const struct dom_sid *psid, struct unixid *id)
1137 bool ret;
1139 become_root();
1140 ret = pdb_sid_to_id(psid, id);
1141 unbecome_root();
1143 if (!ret) {
1144 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1145 sid_string_dbg(psid)));
1146 return false;
1149 return true;
1152 static bool legacy_sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1154 struct unixid id;
1155 if (!legacy_sid_to_unixid(psid, &id)) {
1156 return false;
1158 if (id.type == ID_TYPE_GID || id.type == ID_TYPE_BOTH) {
1159 *pgid = id.id;
1160 return true;
1162 return false;
1165 static bool legacy_sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1167 struct unixid id;
1168 if (!legacy_sid_to_unixid(psid, &id)) {
1169 return false;
1171 if (id.type == ID_TYPE_UID || id.type == ID_TYPE_BOTH) {
1172 *puid = id.id;
1173 return true;
1175 return false;
1178 /*****************************************************************
1179 *THE CANONICAL* convert uid_t to SID function.
1180 *****************************************************************/
1182 void uid_to_sid(struct dom_sid *psid, uid_t uid)
1184 bool expired = true;
1185 bool ret;
1186 ZERO_STRUCTP(psid);
1188 /* Check the winbindd cache directly. */
1189 ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1191 if (ret && !expired && is_null_sid(psid)) {
1193 * Negative cache entry, we already asked.
1194 * do legacy.
1196 legacy_uid_to_sid(psid, uid);
1197 return;
1200 if (!ret || expired) {
1201 /* Not in cache. Ask winbindd. */
1202 if (!winbind_uid_to_sid(psid, uid)) {
1204 * We shouldn't return the NULL SID
1205 * here if winbind was running and
1206 * couldn't map, as winbind will have
1207 * added a negative entry that will
1208 * cause us to go though the
1209 * legacy_uid_to_sid()
1210 * function anyway in the case above
1211 * the next time we ask.
1213 DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1214 "for uid %u\n", (unsigned int)uid));
1216 legacy_uid_to_sid(psid, uid);
1217 return;
1221 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1222 sid_string_dbg(psid)));
1224 return;
1227 /*****************************************************************
1228 *THE CANONICAL* convert gid_t to SID function.
1229 *****************************************************************/
1231 void gid_to_sid(struct dom_sid *psid, gid_t gid)
1233 bool expired = true;
1234 bool ret;
1235 ZERO_STRUCTP(psid);
1237 /* Check the winbindd cache directly. */
1238 ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1240 if (ret && !expired && is_null_sid(psid)) {
1242 * Negative cache entry, we already asked.
1243 * do legacy.
1245 legacy_gid_to_sid(psid, gid);
1246 return;
1249 if (!ret || expired) {
1250 /* Not in cache. Ask winbindd. */
1251 if (!winbind_gid_to_sid(psid, gid)) {
1253 * We shouldn't return the NULL SID
1254 * here if winbind was running and
1255 * couldn't map, as winbind will have
1256 * added a negative entry that will
1257 * cause us to go though the
1258 * legacy_gid_to_sid()
1259 * function anyway in the case above
1260 * the next time we ask.
1262 DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1263 "for gid %u\n", (unsigned int)gid));
1265 legacy_gid_to_sid(psid, gid);
1266 return;
1270 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1271 sid_string_dbg(psid)));
1273 return;
1276 bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
1277 struct unixid *ids)
1279 struct wbcDomainSid *wbc_sids = NULL;
1280 struct wbcUnixId *wbc_ids = NULL;
1281 uint32_t i, num_not_cached;
1282 wbcErr err;
1283 bool ret = false;
1285 wbc_sids = talloc_array(talloc_tos(), struct wbcDomainSid, num_sids);
1286 if (wbc_sids == NULL) {
1287 return false;
1290 num_not_cached = 0;
1292 for (i=0; i<num_sids; i++) {
1293 bool expired;
1294 uint32_t rid;
1296 if (sid_peek_check_rid(&global_sid_Unix_Users,
1297 &sids[i], &rid)) {
1298 ids[i].type = ID_TYPE_UID;
1299 ids[i].id = rid;
1300 continue;
1302 if (sid_peek_check_rid(&global_sid_Unix_Groups,
1303 &sids[i], &rid)) {
1304 ids[i].type = ID_TYPE_GID;
1305 ids[i].id = rid;
1306 continue;
1308 if (idmap_cache_find_sid2unixid(&sids[i], &ids[i], &expired)
1309 && !expired)
1311 continue;
1313 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1314 memcpy(&wbc_sids[num_not_cached], &sids[i],
1315 ndr_size_dom_sid(&sids[i], 0));
1316 num_not_cached += 1;
1318 if (num_not_cached == 0) {
1319 goto done;
1321 wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, num_not_cached);
1322 if (wbc_ids == NULL) {
1323 goto fail;
1325 for (i=0; i<num_not_cached; i++) {
1326 wbc_ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1328 err = wbcSidsToUnixIds(wbc_sids, num_not_cached, wbc_ids);
1329 if (!WBC_ERROR_IS_OK(err)) {
1330 DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
1331 wbcErrorString(err)));
1334 num_not_cached = 0;
1336 for (i=0; i<num_sids; i++) {
1337 if (ids[i].type == ID_TYPE_NOT_SPECIFIED) {
1338 switch (wbc_ids[num_not_cached].type) {
1339 case WBC_ID_TYPE_UID:
1340 ids[i].type = ID_TYPE_UID;
1341 ids[i].id = wbc_ids[num_not_cached].id.uid;
1342 break;
1343 case WBC_ID_TYPE_GID:
1344 ids[i].type = ID_TYPE_GID;
1345 ids[i].id = wbc_ids[num_not_cached].id.gid;
1346 break;
1347 default:
1348 /* The types match, and wbcUnixId -> id is a union anyway */
1349 ids[i].type = (enum id_type)wbc_ids[num_not_cached].type;
1350 ids[i].id = wbc_ids[num_not_cached].id.gid;
1351 break;
1353 num_not_cached += 1;
1357 for (i=0; i<num_sids; i++) {
1358 if (ids[i].type != ID_TYPE_NOT_SPECIFIED) {
1359 continue;
1361 if (legacy_sid_to_gid(&sids[i], &ids[i].id)) {
1362 ids[i].type = ID_TYPE_GID;
1363 continue;
1365 if (legacy_sid_to_uid(&sids[i], &ids[i].id)) {
1366 ids[i].type = ID_TYPE_UID;
1367 continue;
1370 done:
1371 for (i=0; i<num_sids; i++) {
1372 switch(ids[i].type) {
1373 case WBC_ID_TYPE_GID:
1374 case WBC_ID_TYPE_UID:
1375 case WBC_ID_TYPE_BOTH:
1376 if (ids[i].id == -1) {
1377 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1379 break;
1380 case WBC_ID_TYPE_NOT_SPECIFIED:
1381 break;
1385 ret = true;
1386 fail:
1387 TALLOC_FREE(wbc_ids);
1388 TALLOC_FREE(wbc_sids);
1389 return ret;
1392 /*****************************************************************
1393 *THE CANONICAL* convert SID to uid function.
1394 *****************************************************************/
1396 bool sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1398 bool expired = true;
1399 bool ret;
1400 uint32_t rid;
1402 /* Optimize for the Unix Users Domain
1403 * as the conversion is straightforward */
1404 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1405 uid_t uid = rid;
1406 *puid = uid;
1408 /* return here, don't cache */
1409 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1410 (unsigned int)*puid ));
1411 return true;
1414 /* Check the winbindd cache directly. */
1415 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1417 if (ret && !expired && (*puid == (uid_t)-1)) {
1419 * Negative cache entry, we already asked.
1420 * do legacy.
1422 return legacy_sid_to_uid(psid, puid);
1425 if (!ret || expired) {
1426 /* Not in cache. Ask winbindd. */
1427 if (!winbind_sid_to_uid(puid, psid)) {
1428 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1429 sid_string_dbg(psid)));
1430 /* winbind failed. do legacy */
1431 return legacy_sid_to_uid(psid, puid);
1435 /* TODO: Here would be the place to allocate both a gid and a uid for
1436 * the SID in question */
1438 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1439 (unsigned int)*puid ));
1441 return true;
1444 /*****************************************************************
1445 *THE CANONICAL* convert SID to gid function.
1446 Group mapping is used for gids that maps to Wellknown SIDs
1447 *****************************************************************/
1449 bool sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1451 bool expired = true;
1452 bool ret;
1453 uint32_t rid;
1455 /* Optimize for the Unix Groups Domain
1456 * as the conversion is straightforward */
1457 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1458 gid_t gid = rid;
1459 *pgid = gid;
1461 /* return here, don't cache */
1462 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1463 (unsigned int)*pgid ));
1464 return true;
1467 /* Check the winbindd cache directly. */
1468 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1470 if (ret && !expired && (*pgid == (gid_t)-1)) {
1472 * Negative cache entry, we already asked.
1473 * do legacy.
1475 return legacy_sid_to_gid(psid, pgid);
1478 if (!ret || expired) {
1479 /* Not in cache or negative. Ask winbindd. */
1480 /* Ask winbindd if it can map this sid to a gid.
1481 * (Idmap will check it is a valid SID and of the right type) */
1483 if ( !winbind_sid_to_gid(pgid, psid) ) {
1485 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1486 sid_string_dbg(psid)));
1487 /* winbind failed. do legacy */
1488 return legacy_sid_to_gid(psid, pgid);
1492 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1493 (unsigned int)*pgid ));
1495 return true;
1499 * @brief This function gets the primary group SID mapping the primary
1500 * GID of the user as obtained by an actual getpwnam() call.
1501 * This is necessary to avoid issues with arbitrary group SIDs
1502 * stored in passdb. We try as hard as we can to get the SID
1503 * corresponding to the GID, including trying group mapping.
1504 * If nothing else works, we will force "Domain Users" as the
1505 * primary group.
1506 * This is needed because we must always be able to lookup the
1507 * primary group SID, so we cannot settle for an arbitrary SID.
1509 * This call can be expensive. Use with moderation.
1510 * If you have a "samu" struct around use pdb_get_group_sid()
1511 * instead as it does properly cache results.
1513 * @param mem_ctx[in] The memory context iused to allocate the result.
1514 * @param username[in] The user's name
1515 * @param _pwd[in|out] If available, pass in user's passwd struct.
1516 * It will contain a tallocated passwd if NULL was
1517 * passed in.
1518 * @param _group_sid[out] The user's Primary Group SID
1520 * @return NTSTATUS error code.
1522 NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx,
1523 const char *username,
1524 struct passwd **_pwd,
1525 struct dom_sid **_group_sid)
1527 TALLOC_CTX *tmp_ctx;
1528 bool need_lookup_sid = false;
1529 struct dom_sid *group_sid;
1530 struct passwd *pwd = *_pwd;
1532 tmp_ctx = talloc_new(mem_ctx);
1533 if (!tmp_ctx) {
1534 return NT_STATUS_NO_MEMORY;
1537 if (!pwd) {
1538 pwd = Get_Pwnam_alloc(mem_ctx, username);
1539 if (!pwd) {
1540 DEBUG(0, ("Failed to find a Unix account for %s\n",
1541 username));
1542 TALLOC_FREE(tmp_ctx);
1543 return NT_STATUS_NO_SUCH_USER;
1547 group_sid = talloc_zero(mem_ctx, struct dom_sid);
1548 if (!group_sid) {
1549 TALLOC_FREE(tmp_ctx);
1550 return NT_STATUS_NO_MEMORY;
1553 gid_to_sid(group_sid, pwd->pw_gid);
1554 if (!is_null_sid(group_sid)) {
1555 struct dom_sid domain_sid;
1556 uint32_t rid;
1558 /* We need a sid within our domain */
1559 sid_copy(&domain_sid, group_sid);
1560 sid_split_rid(&domain_sid, &rid);
1561 if (dom_sid_equal(&domain_sid, get_global_sam_sid())) {
1563 * As shortcut for the expensive lookup_sid call
1564 * compare the domain sid part
1566 switch (rid) {
1567 case DOMAIN_RID_ADMINS:
1568 case DOMAIN_RID_USERS:
1569 goto done;
1570 default:
1571 need_lookup_sid = true;
1572 break;
1574 } else {
1575 /* Try group mapping */
1576 struct unixid id;
1578 id.id = pwd->pw_gid;
1579 id.type = ID_TYPE_GID;
1581 ZERO_STRUCTP(group_sid);
1582 if (pdb_id_to_sid(&id, group_sid)) {
1583 need_lookup_sid = true;
1588 /* We must verify that this is a valid SID that resolves to a
1589 * group of the correct type */
1590 if (need_lookup_sid) {
1591 enum lsa_SidType type = SID_NAME_UNKNOWN;
1592 bool lookup_ret;
1594 DEBUG(10, ("do lookup_sid(%s) for group of user %s\n",
1595 sid_string_dbg(group_sid), username));
1597 /* Now check that it's actually a domain group and
1598 * not something else */
1599 lookup_ret = lookup_sid(tmp_ctx, group_sid,
1600 NULL, NULL, &type);
1602 if (lookup_ret && (type == SID_NAME_DOM_GRP)) {
1603 goto done;
1606 DEBUG(3, ("Primary group %s for user %s is"
1607 " a %s and not a domain group\n",
1608 sid_string_dbg(group_sid), username,
1609 sid_type_lookup(type)));
1612 /* Everything else, failed.
1613 * Just set it to the 'Domain Users' RID of 513 which will
1614 always resolve to a name */
1615 DEBUG(3, ("Forcing Primary Group to 'Domain Users' for %s\n",
1616 username));
1618 sid_compose(group_sid, get_global_sam_sid(), DOMAIN_RID_USERS);
1620 done:
1621 *_pwd = talloc_move(mem_ctx, &pwd);
1622 *_group_sid = talloc_move(mem_ctx, &group_sid);
1623 TALLOC_FREE(tmp_ctx);
1624 return NT_STATUS_OK;