s3:gse_krb5: make use of precalculated krb5 keys in fill_mem_keytab_from_secrets()
[Samba.git] / source3 / passdb / lookup_sid.c
blobb06dd1b6f724c5942424b13ef6d744208267cb87
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 "lib/util_unixsids.h"
25 #include "../librpc/gen_ndr/ndr_security.h"
26 #include "secrets.h"
27 #include "../lib/util/memcache.h"
28 #include "idmap_cache.h"
29 #include "../libcli/security/security.h"
30 #include "lib/winbind_util.h"
31 #include "../librpc/gen_ndr/idmap.h"
33 static bool lookup_unix_user_name(const char *name, struct dom_sid *sid)
35 struct passwd *pwd;
36 bool ret;
38 pwd = Get_Pwnam_alloc(talloc_tos(), name);
39 if (pwd == NULL) {
40 return False;
44 * For 64-bit uid's we have enough space in the whole SID,
45 * should they become necessary
47 ret = sid_compose(sid, &global_sid_Unix_Users, pwd->pw_uid);
48 TALLOC_FREE(pwd);
49 return ret;
52 static bool lookup_unix_group_name(const char *name, struct dom_sid *sid)
54 struct group *grp;
56 grp = getgrnam(name);
57 if (grp == NULL) {
58 return False;
62 * For 64-bit gid's we have enough space in the whole SID,
63 * should they become necessary
65 return sid_compose(sid, &global_sid_Unix_Groups, grp->gr_gid);
68 /*****************************************************************
69 Dissect a user-provided name into domain, name, sid and type.
71 If an explicit domain name was given in the form domain\user, it
72 has to try that. If no explicit domain name was given, we have
73 to do guesswork.
74 *****************************************************************/
76 bool lookup_name(TALLOC_CTX *mem_ctx,
77 const char *full_name, int flags,
78 const char **ret_domain, const char **ret_name,
79 struct dom_sid *ret_sid, enum lsa_SidType *ret_type)
81 char *p;
82 const char *tmp;
83 const char *domain = NULL;
84 const char *name = NULL;
85 uint32_t rid;
86 struct dom_sid sid;
87 enum lsa_SidType type;
88 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
90 if (tmp_ctx == NULL) {
91 DEBUG(0, ("talloc_new failed\n"));
92 return false;
95 p = strchr_m(full_name, '\\');
97 if (p != NULL) {
98 domain = talloc_strndup(tmp_ctx, full_name,
99 PTR_DIFF(p, full_name));
100 name = talloc_strdup(tmp_ctx, p+1);
101 } else {
102 domain = talloc_strdup(tmp_ctx, "");
103 name = talloc_strdup(tmp_ctx, full_name);
106 if ((domain == NULL) || (name == NULL)) {
107 DEBUG(0, ("talloc failed\n"));
108 TALLOC_FREE(tmp_ctx);
109 return false;
112 DEBUG(10,("lookup_name: %s => domain=[%s], name=[%s]\n",
113 full_name, domain, name));
114 DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
116 if ((flags & LOOKUP_NAME_DOMAIN) &&
117 strequal(domain, get_global_sam_name()))
120 /* It's our own domain, lookup the name in passdb */
121 if (lookup_global_sam_name(name, flags, &rid, &type)) {
122 sid_compose(&sid, get_global_sam_sid(), rid);
123 goto ok;
125 TALLOC_FREE(tmp_ctx);
126 return false;
129 if ((flags & LOOKUP_NAME_BUILTIN) &&
130 strequal(domain, builtin_domain_name()))
132 if (strlen(name) == 0) {
133 /* Swap domain and name */
134 tmp = name; name = domain; domain = tmp;
135 sid_copy(&sid, &global_sid_Builtin);
136 type = SID_NAME_DOMAIN;
137 goto ok;
140 /* Explicit request for a name in BUILTIN */
141 if (lookup_builtin_name(name, &rid)) {
142 sid_compose(&sid, &global_sid_Builtin, rid);
143 type = SID_NAME_ALIAS;
144 goto ok;
146 TALLOC_FREE(tmp_ctx);
147 return false;
150 /* Try the explicit winbind lookup first, don't let it guess the
151 * domain yet at this point yet. This comes later. */
153 if ((domain[0] != '\0') &&
154 (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
155 (winbind_lookup_name(domain, name, &sid, &type))) {
156 goto ok;
159 if (((flags & (LOOKUP_NAME_NO_NSS|LOOKUP_NAME_GROUP)) == 0)
160 && strequal(domain, unix_users_domain_name())) {
161 if (lookup_unix_user_name(name, &sid)) {
162 type = SID_NAME_USER;
163 goto ok;
165 TALLOC_FREE(tmp_ctx);
166 return false;
169 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
170 && strequal(domain, unix_groups_domain_name())) {
171 if (lookup_unix_group_name(name, &sid)) {
172 type = SID_NAME_DOM_GRP;
173 goto ok;
175 TALLOC_FREE(tmp_ctx);
176 return false;
180 * Finally check for a well known domain name ("NT Authority"),
181 * this is taken care if in lookup_wellknown_name().
183 if ((domain[0] != '\0') &&
184 (flags & LOOKUP_NAME_WKN) &&
185 lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
187 type = SID_NAME_WKN_GRP;
188 goto ok;
192 * If we're told not to look up 'isolated' names then we're
193 * done.
195 if (!(flags & LOOKUP_NAME_ISOLATED)) {
196 TALLOC_FREE(tmp_ctx);
197 return false;
201 * No domain names beyond this point
203 if (domain[0] != '\0') {
204 TALLOC_FREE(tmp_ctx);
205 return false;
208 /* Now the guesswork begins, we haven't been given an explicit
209 * domain. Try the sequence as documented on
210 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
211 * November 27, 2005 */
213 /* 1. well-known names */
216 * Check for well known names without a domain name.
217 * e.g. \Creator Owner.
220 if ((flags & LOOKUP_NAME_WKN) &&
221 lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
223 type = SID_NAME_WKN_GRP;
224 goto ok;
227 /* 2. Builtin domain as such */
229 if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
230 strequal(name, builtin_domain_name()))
232 /* Swap domain and name */
233 tmp = name; name = domain; domain = tmp;
234 sid_copy(&sid, &global_sid_Builtin);
235 type = SID_NAME_DOMAIN;
236 goto ok;
239 /* 3. Account domain */
241 if ((flags & LOOKUP_NAME_DOMAIN) &&
242 strequal(name, get_global_sam_name()))
244 if (!secrets_fetch_domain_sid(name, &sid)) {
245 DEBUG(3, ("Could not fetch my SID\n"));
246 TALLOC_FREE(tmp_ctx);
247 return false;
249 /* Swap domain and name */
250 tmp = name; name = domain; domain = tmp;
251 type = SID_NAME_DOMAIN;
252 goto ok;
255 /* 4. Primary domain */
257 if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
258 strequal(name, lp_workgroup()))
260 if (!secrets_fetch_domain_sid(name, &sid)) {
261 DEBUG(3, ("Could not fetch the domain SID\n"));
262 TALLOC_FREE(tmp_ctx);
263 return false;
265 /* Swap domain and name */
266 tmp = name; name = domain; domain = tmp;
267 type = SID_NAME_DOMAIN;
268 goto ok;
271 /* 5. Trusted domains as such, to me it looks as if members don't do
272 this, tested an XP workstation in a NT domain -- vl */
274 if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
275 (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
277 /* Swap domain and name */
278 tmp = name; name = domain; domain = tmp;
279 type = SID_NAME_DOMAIN;
280 goto ok;
283 /* 6. Builtin aliases */
285 if ((flags & LOOKUP_NAME_BUILTIN) &&
286 lookup_builtin_name(name, &rid))
288 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
289 sid_compose(&sid, &global_sid_Builtin, rid);
290 type = SID_NAME_ALIAS;
291 goto ok;
294 /* 7. Local systems' SAM (DCs don't have a local SAM) */
295 /* 8. Primary SAM (On members, this is the domain) */
297 /* Both cases are done by looking at our passdb */
299 if ((flags & LOOKUP_NAME_DOMAIN) &&
300 lookup_global_sam_name(name, flags, &rid, &type))
302 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
303 sid_compose(&sid, get_global_sam_sid(), rid);
304 goto ok;
307 /* Now our local possibilities are exhausted. */
309 if (!(flags & LOOKUP_NAME_REMOTE)) {
310 TALLOC_FREE(tmp_ctx);
311 return false;
314 /* If we are not a DC, we have to ask in our primary domain. Let
315 * winbind do that. */
317 if (!IS_DC &&
318 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
319 domain = talloc_strdup(tmp_ctx, lp_workgroup());
320 goto ok;
323 /* 9. Trusted domains */
325 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
326 * that (yet), but give it a chance. */
328 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
329 struct dom_sid dom_sid;
330 enum lsa_SidType domain_type;
332 if (type == SID_NAME_DOMAIN) {
333 /* Swap name and type */
334 tmp = name; name = domain; domain = tmp;
335 goto ok;
338 /* Here we have to cope with a little deficiency in the
339 * winbind API: We have to ask it again for the name of the
340 * domain it figured out itself. Maybe fix that later... */
342 sid_copy(&dom_sid, &sid);
343 sid_split_rid(&dom_sid, NULL);
345 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
346 &domain_type) ||
347 (domain_type != SID_NAME_DOMAIN)) {
348 DEBUG(2, ("winbind could not find the domain's name "
349 "it just looked up for us\n"));
350 TALLOC_FREE(tmp_ctx);
351 return false;
353 goto ok;
356 /* 10. Don't translate */
358 /* 11. Ok, windows would end here. Samba has two more options:
359 Unmapped users and unmapped groups */
361 if (((flags & (LOOKUP_NAME_NO_NSS|LOOKUP_NAME_GROUP)) == 0)
362 && lookup_unix_user_name(name, &sid)) {
363 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
364 type = SID_NAME_USER;
365 goto ok;
368 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
369 && lookup_unix_group_name(name, &sid)) {
370 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
371 type = SID_NAME_DOM_GRP;
372 goto ok;
376 * Ok, all possibilities tried. Fail.
379 TALLOC_FREE(tmp_ctx);
380 return false;
383 if ((domain == NULL) || (name == NULL)) {
384 DEBUG(0, ("talloc failed\n"));
385 TALLOC_FREE(tmp_ctx);
386 return false;
390 * Hand over the results to the talloc context we've been given.
393 if ((ret_name != NULL) &&
394 !(*ret_name = talloc_strdup(mem_ctx, name))) {
395 DEBUG(0, ("talloc failed\n"));
396 TALLOC_FREE(tmp_ctx);
397 return false;
400 if (ret_domain != NULL) {
401 char *tmp_dom;
402 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
403 DEBUG(0, ("talloc failed\n"));
404 TALLOC_FREE(tmp_ctx);
405 return false;
407 if (!strupper_m(tmp_dom)) {
408 TALLOC_FREE(tmp_ctx);
409 return false;
411 *ret_domain = tmp_dom;
414 if (ret_sid != NULL) {
415 sid_copy(ret_sid, &sid);
418 if (ret_type != NULL) {
419 *ret_type = type;
422 TALLOC_FREE(tmp_ctx);
423 return true;
426 /************************************************************************
427 Names from smb.conf can be unqualified. eg. valid users = foo
428 These names should never map to a remote name. Try global_sam_name()\foo,
429 and then "Unix Users"\foo (or "Unix Groups"\foo).
430 ************************************************************************/
432 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
433 const char *full_name, int flags,
434 const char **ret_domain, const char **ret_name,
435 struct dom_sid *ret_sid, enum lsa_SidType *ret_type)
437 char *qualified_name;
438 const char *p;
440 if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
442 /* The name is already qualified with a domain. */
444 if (*lp_winbind_separator() != '\\') {
445 char *tmp;
447 /* lookup_name() needs '\\' as a separator */
449 tmp = talloc_strdup(mem_ctx, full_name);
450 if (!tmp) {
451 return false;
453 tmp[p - full_name] = '\\';
454 full_name = tmp;
457 return lookup_name(mem_ctx, full_name, flags,
458 ret_domain, ret_name,
459 ret_sid, ret_type);
462 /* Try with winbind default domain name. */
463 if (lp_winbind_use_default_domain()) {
464 bool ok;
466 qualified_name = talloc_asprintf(mem_ctx,
467 "%s\\%s",
468 lp_workgroup(),
469 full_name);
470 if (qualified_name == NULL) {
471 return false;
474 ok = lookup_name(mem_ctx,
475 qualified_name,
476 flags,
477 ret_domain,
478 ret_name,
479 ret_sid,
480 ret_type);
481 if (ok) {
482 return true;
486 /* Try with our own SAM name. */
487 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
488 get_global_sam_name(),
489 full_name );
490 if (!qualified_name) {
491 return false;
494 if (lookup_name(mem_ctx, qualified_name, flags,
495 ret_domain, ret_name,
496 ret_sid, ret_type)) {
497 return true;
500 /* Finally try with "Unix Users" or "Unix Group" */
501 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
502 flags & LOOKUP_NAME_GROUP ?
503 unix_groups_domain_name() :
504 unix_users_domain_name(),
505 full_name );
506 if (!qualified_name) {
507 return false;
510 return lookup_name(mem_ctx, qualified_name, flags,
511 ret_domain, ret_name,
512 ret_sid, ret_type);
515 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
516 const struct dom_sid *domain_sid,
517 int num_rids, uint32_t *rids,
518 const char **domain_name,
519 const char **names, enum lsa_SidType *types)
521 int i;
522 const char **my_names;
523 enum lsa_SidType *my_types;
524 TALLOC_CTX *tmp_ctx;
526 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
527 return false;
530 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
531 domain_name, &my_names, &my_types)) {
532 *domain_name = "";
533 for (i=0; i<num_rids; i++) {
534 names[i] = "";
535 types[i] = SID_NAME_UNKNOWN;
537 TALLOC_FREE(tmp_ctx);
538 return true;
541 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
542 TALLOC_FREE(tmp_ctx);
543 return false;
547 * winbind_lookup_rids allocates its own array. We've been given the
548 * array, so copy it over
551 for (i=0; i<num_rids; i++) {
552 if (my_names[i] == NULL) {
553 TALLOC_FREE(tmp_ctx);
554 return false;
556 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
557 TALLOC_FREE(tmp_ctx);
558 return false;
560 types[i] = my_types[i];
562 TALLOC_FREE(tmp_ctx);
563 return true;
566 static bool lookup_rids(TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid,
567 int num_rids, uint32_t *rids,
568 const char **domain_name,
569 const char ***names, enum lsa_SidType **types)
571 int i;
573 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
574 sid_string_dbg(domain_sid)));
576 if (num_rids) {
577 *names = talloc_zero_array(mem_ctx, const char *, num_rids);
578 *types = talloc_array(mem_ctx, enum lsa_SidType, num_rids);
580 if ((*names == NULL) || (*types == NULL)) {
581 return false;
584 for (i = 0; i < num_rids; i++)
585 (*types)[i] = SID_NAME_UNKNOWN;
586 } else {
587 *names = NULL;
588 *types = NULL;
591 if (sid_check_is_our_sam(domain_sid)) {
592 NTSTATUS result;
594 if (*domain_name == NULL) {
595 *domain_name = talloc_strdup(
596 mem_ctx, get_global_sam_name());
599 if (*domain_name == NULL) {
600 return false;
603 become_root();
604 result = pdb_lookup_rids(domain_sid, num_rids, rids,
605 *names, *types);
606 unbecome_root();
608 return (NT_STATUS_IS_OK(result) ||
609 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
610 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
613 if (sid_check_is_builtin(domain_sid)) {
615 if (*domain_name == NULL) {
616 *domain_name = talloc_strdup(
617 mem_ctx, builtin_domain_name());
620 if (*domain_name == NULL) {
621 return false;
624 for (i=0; i<num_rids; i++) {
625 if (lookup_builtin_rid(*names, rids[i],
626 &(*names)[i])) {
627 if ((*names)[i] == NULL) {
628 return false;
630 (*types)[i] = SID_NAME_ALIAS;
631 } else {
632 (*types)[i] = SID_NAME_UNKNOWN;
635 return true;
638 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
639 for (i=0; i<num_rids; i++) {
640 struct dom_sid sid;
641 sid_compose(&sid, domain_sid, rids[i]);
642 if (lookup_wellknown_sid(mem_ctx, &sid,
643 domain_name, &(*names)[i])) {
644 if ((*names)[i] == NULL) {
645 return false;
647 (*types)[i] = SID_NAME_WKN_GRP;
648 } else {
649 (*types)[i] = SID_NAME_UNKNOWN;
652 return true;
655 if (sid_check_is_unix_users(domain_sid)) {
656 if (*domain_name == NULL) {
657 *domain_name = talloc_strdup(
658 mem_ctx, unix_users_domain_name());
659 if (*domain_name == NULL) {
660 return false;
663 for (i=0; i<num_rids; i++) {
664 (*names)[i] = talloc_strdup(
665 (*names), uidtoname(rids[i]));
666 if ((*names)[i] == NULL) {
667 return false;
669 (*types)[i] = SID_NAME_USER;
671 return true;
674 if (sid_check_is_unix_groups(domain_sid)) {
675 if (*domain_name == NULL) {
676 *domain_name = talloc_strdup(
677 mem_ctx, unix_groups_domain_name());
678 if (*domain_name == NULL) {
679 return false;
682 for (i=0; i<num_rids; i++) {
683 (*names)[i] = talloc_strdup(
684 (*names), gidtoname(rids[i]));
685 if ((*names)[i] == NULL) {
686 return false;
688 (*types)[i] = SID_NAME_DOM_GRP;
690 return true;
693 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
694 domain_name, *names, *types);
698 * Is the SID a domain as such? If yes, lookup its name.
701 static bool lookup_as_domain(const struct dom_sid *sid, TALLOC_CTX *mem_ctx,
702 const char **name)
704 const char *tmp;
705 enum lsa_SidType type;
707 if (sid_check_is_our_sam(sid)) {
708 *name = talloc_strdup(mem_ctx, get_global_sam_name());
709 return true;
712 if (sid_check_is_builtin(sid)) {
713 *name = talloc_strdup(mem_ctx, builtin_domain_name());
714 return true;
717 if (sid_check_is_wellknown_domain(sid, &tmp)) {
718 *name = talloc_strdup(mem_ctx, tmp);
719 return true;
722 if (sid_check_is_unix_users(sid)) {
723 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
724 return true;
727 if (sid_check_is_unix_groups(sid)) {
728 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
729 return true;
732 if (sid->num_auths != 4) {
733 /* This can't be a domain */
734 return false;
737 if (IS_DC) {
738 uint32_t i, num_domains;
739 struct trustdom_info **domains;
741 /* This is relatively expensive, but it happens only on DCs
742 * and for SIDs that have 4 sub-authorities and thus look like
743 * domains */
745 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
746 &num_domains,
747 &domains))) {
748 return false;
751 for (i=0; i<num_domains; i++) {
752 if (dom_sid_equal(sid, &domains[i]->sid)) {
753 *name = talloc_strdup(mem_ctx,
754 domains[i]->name);
755 return true;
758 return false;
761 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
762 (type == SID_NAME_DOMAIN)) {
763 *name = tmp;
764 return true;
767 return false;
771 * This tries to implement the rather weird rules for the lsa_lookup level
772 * parameter.
774 * This is as close as we can get to what W2k3 does. With this we survive the
775 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
776 * different, but I assume that's just being too liberal. For example, W2k3
777 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
778 * whereas NT4 does the same as level 1 (I think). I did not fully test that
779 * with NT4, this is what w2k3 does.
781 * Level 1: Ask everywhere
782 * Level 2: Ask domain and trusted domains, no builtin and wkn
783 * Level 3: Only ask domain
784 * Level 4: W2k3ad: Only ask AD trusts
785 * Level 5: Only ask transitive forest trusts
786 * Level 6: Like 4
789 static bool check_dom_sid_to_level(const struct dom_sid *sid, int level)
791 int ret = false;
793 switch(level) {
794 case 1:
795 ret = true;
796 break;
797 case 2:
798 ret = (!sid_check_is_builtin(sid) &&
799 !sid_check_is_wellknown_domain(sid, NULL));
800 break;
801 case 3:
802 case 4:
803 case 6:
804 ret = sid_check_is_our_sam(sid);
805 break;
806 case 5:
807 ret = false;
808 break;
811 DEBUG(10, ("%s SID %s in level %d\n",
812 ret ? "Accepting" : "Rejecting",
813 sid_string_dbg(sid), level));
814 return ret;
818 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
819 * references to domains, it is explicitly made for this.
821 * This attempts to be as efficient as possible: It collects all SIDs
822 * belonging to a domain and hands them in bulk to the appropriate lookup
823 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
824 * *hugely* from this.
827 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
828 const struct dom_sid **sids, int level,
829 struct lsa_dom_info **ret_domains,
830 struct lsa_name_info **ret_names)
832 TALLOC_CTX *tmp_ctx;
833 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
834 struct lsa_name_info *name_infos;
835 struct lsa_dom_info *dom_infos = NULL;
837 int i, j;
839 if (!(tmp_ctx = talloc_new(mem_ctx))) {
840 DEBUG(0, ("talloc_new failed\n"));
841 return NT_STATUS_NO_MEMORY;
844 if (num_sids) {
845 name_infos = talloc_array(mem_ctx, struct lsa_name_info, num_sids);
846 if (name_infos == NULL) {
847 result = NT_STATUS_NO_MEMORY;
848 goto fail;
850 } else {
851 name_infos = NULL;
854 dom_infos = talloc_zero_array(mem_ctx, struct lsa_dom_info,
855 LSA_REF_DOMAIN_LIST_MULTIPLIER);
856 if (dom_infos == NULL) {
857 result = NT_STATUS_NO_MEMORY;
858 goto fail;
861 /* First build up the data structures:
863 * dom_infos is a list of domains referenced in the list of
864 * SIDs. Later we will walk the list of domains and look up the RIDs
865 * in bulk.
867 * name_infos is a shadow-copy of the SIDs array to collect the real
868 * data.
870 * dom_info->idxs is an index into the name_infos array. The
871 * difficulty we have here is that we need to keep the SIDs the client
872 * asked for in the same order for the reply
875 for (i=0; i<num_sids; i++) {
876 struct dom_sid sid;
877 uint32_t rid = 0;
878 const char *domain_name = NULL;
880 sid_copy(&sid, sids[i]);
881 name_infos[i].type = SID_NAME_USE_NONE;
883 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
884 /* We can't push that through the normal lookup
885 * process, as this would reference illegal
886 * domains.
888 * For example S-1-5-32 would end up referencing
889 * domain S-1-5- with RID 32 which is clearly wrong.
891 if (domain_name == NULL) {
892 result = NT_STATUS_NO_MEMORY;
893 goto fail;
896 name_infos[i].rid = 0;
897 name_infos[i].type = SID_NAME_DOMAIN;
898 name_infos[i].name = NULL;
900 if (sid_check_is_builtin(&sid)) {
901 /* Yes, W2k3 returns "BUILTIN" both as domain
902 * and name here */
903 name_infos[i].name = talloc_strdup(
904 name_infos, builtin_domain_name());
905 if (name_infos[i].name == NULL) {
906 result = NT_STATUS_NO_MEMORY;
907 goto fail;
910 } else {
911 /* This is a normal SID with rid component */
912 if (!sid_split_rid(&sid, &rid)) {
913 result = NT_STATUS_INVALID_SID;
914 goto fail;
918 if (!check_dom_sid_to_level(&sid, level)) {
919 name_infos[i].rid = 0;
920 name_infos[i].type = SID_NAME_UNKNOWN;
921 name_infos[i].name = NULL;
922 continue;
925 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
926 if (!dom_infos[j].valid) {
927 break;
929 if (dom_sid_equal(&sid, &dom_infos[j].sid)) {
930 break;
934 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
935 /* TODO: What's the right error message here? */
936 result = NT_STATUS_NONE_MAPPED;
937 goto fail;
940 if (!dom_infos[j].valid) {
941 /* We found a domain not yet referenced, create a new
942 * ref. */
943 dom_infos[j].valid = true;
944 sid_copy(&dom_infos[j].sid, &sid);
946 if (domain_name != NULL) {
947 /* This name was being found above in the case
948 * when we found a domain SID */
949 dom_infos[j].name =
950 talloc_strdup(dom_infos, domain_name);
951 if (dom_infos[j].name == NULL) {
952 result = NT_STATUS_NO_MEMORY;
953 goto fail;
955 } else {
956 /* lookup_rids will take care of this */
957 dom_infos[j].name = NULL;
961 name_infos[i].dom_idx = j;
963 if (name_infos[i].type == SID_NAME_USE_NONE) {
964 name_infos[i].rid = rid;
966 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
967 &dom_infos[j].num_idxs);
969 if (dom_infos[j].idxs == NULL) {
970 result = NT_STATUS_NO_MEMORY;
971 goto fail;
976 /* Iterate over the domains found */
978 for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
979 uint32_t *rids;
980 const char *domain_name = NULL;
981 const char **names;
982 enum lsa_SidType *types;
983 struct lsa_dom_info *dom = &dom_infos[i];
985 if (!dom->valid) {
986 /* No domains left, we're done */
987 break;
990 if (dom->num_idxs == 0) {
992 * This happens only if the only sid related to
993 * this domain is the domain sid itself, which
994 * is mapped to SID_NAME_DOMAIN above.
996 continue;
999 if (!(rids = talloc_array(tmp_ctx, uint32_t, dom->num_idxs))) {
1000 result = NT_STATUS_NO_MEMORY;
1001 goto fail;
1004 for (j=0; j<dom->num_idxs; j++) {
1005 rids[j] = name_infos[dom->idxs[j]].rid;
1008 if (!lookup_rids(tmp_ctx, &dom->sid,
1009 dom->num_idxs, rids, &domain_name,
1010 &names, &types)) {
1011 result = NT_STATUS_NO_MEMORY;
1012 goto fail;
1015 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
1016 result = NT_STATUS_NO_MEMORY;
1017 goto fail;
1020 for (j=0; j<dom->num_idxs; j++) {
1021 int idx = dom->idxs[j];
1022 name_infos[idx].type = types[j];
1023 if (types[j] != SID_NAME_UNKNOWN) {
1024 name_infos[idx].name =
1025 talloc_strdup(name_infos, names[j]);
1026 if (name_infos[idx].name == NULL) {
1027 result = NT_STATUS_NO_MEMORY;
1028 goto fail;
1030 } else {
1031 name_infos[idx].name = NULL;
1036 *ret_domains = dom_infos;
1037 *ret_names = name_infos;
1038 TALLOC_FREE(tmp_ctx);
1039 return NT_STATUS_OK;
1041 fail:
1042 TALLOC_FREE(dom_infos);
1043 TALLOC_FREE(name_infos);
1044 TALLOC_FREE(tmp_ctx);
1045 return result;
1048 /*****************************************************************
1049 *THE CANONICAL* convert SID to name function.
1050 *****************************************************************/
1052 bool lookup_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
1053 const char **ret_domain, const char **ret_name,
1054 enum lsa_SidType *ret_type)
1056 struct lsa_dom_info *domain;
1057 struct lsa_name_info *name;
1058 TALLOC_CTX *tmp_ctx;
1059 bool ret = false;
1061 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
1063 if (!(tmp_ctx = talloc_new(mem_ctx))) {
1064 DEBUG(0, ("talloc_new failed\n"));
1065 return false;
1068 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
1069 &domain, &name))) {
1070 goto done;
1073 if (name->type == SID_NAME_UNKNOWN) {
1074 goto done;
1077 if ((ret_domain != NULL) &&
1078 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
1079 goto done;
1082 if ((ret_name != NULL) &&
1083 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
1084 goto done;
1087 if (ret_type != NULL) {
1088 *ret_type = name->type;
1091 ret = true;
1093 done:
1094 if (ret) {
1095 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
1096 domain->name, name->name, name->type));
1097 } else {
1098 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
1100 TALLOC_FREE(tmp_ctx);
1101 return ret;
1104 /*****************************************************************
1105 Id mapping cache. This is to avoid Winbind mappings already
1106 seen by smbd to be queried too frequently, keeping winbindd
1107 busy, and blocking smbd while winbindd is busy with other
1108 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1109 modified to use linked lists by jra.
1110 *****************************************************************/
1113 /*****************************************************************
1114 *THE LEGACY* convert uid_t to SID function.
1115 *****************************************************************/
1117 static void legacy_uid_to_sid(struct dom_sid *psid, uid_t uid)
1119 bool ret;
1120 struct unixid id;
1122 ZERO_STRUCTP(psid);
1124 id.id = uid;
1125 id.type = ID_TYPE_UID;
1127 become_root();
1128 ret = pdb_id_to_sid(&id, psid);
1129 unbecome_root();
1131 if (ret) {
1132 /* This is a mapped user */
1133 goto done;
1136 /* This is an unmapped user */
1138 uid_to_unix_users_sid(uid, psid);
1141 struct unixid xid = {
1142 .id = uid, .type = ID_TYPE_UID
1144 idmap_cache_set_sid2unixid(psid, &xid);
1147 done:
1148 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1149 sid_string_dbg(psid)));
1151 return;
1154 /*****************************************************************
1155 *THE LEGACY* convert gid_t to SID function.
1156 *****************************************************************/
1158 static void legacy_gid_to_sid(struct dom_sid *psid, gid_t gid)
1160 bool ret;
1161 struct unixid id;
1163 ZERO_STRUCTP(psid);
1165 id.id = gid;
1166 id.type = ID_TYPE_GID;
1168 become_root();
1169 ret = pdb_id_to_sid(&id, psid);
1170 unbecome_root();
1172 if (ret) {
1173 /* This is a mapped group */
1174 goto done;
1177 /* This is an unmapped group */
1179 gid_to_unix_groups_sid(gid, psid);
1182 struct unixid xid = {
1183 .id = gid, .type = ID_TYPE_GID
1185 idmap_cache_set_sid2unixid(psid, &xid);
1188 done:
1189 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1190 sid_string_dbg(psid)));
1192 return;
1195 /*****************************************************************
1196 *THE LEGACY* convert SID to id function.
1197 *****************************************************************/
1199 static bool legacy_sid_to_unixid(const struct dom_sid *psid, struct unixid *id)
1201 bool ret;
1203 become_root();
1204 ret = pdb_sid_to_id(psid, id);
1205 unbecome_root();
1207 if (!ret) {
1208 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1209 sid_string_dbg(psid)));
1210 return false;
1213 return true;
1216 static bool legacy_sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1218 struct unixid id;
1219 if (!legacy_sid_to_unixid(psid, &id)) {
1220 return false;
1222 if (id.type == ID_TYPE_GID || id.type == ID_TYPE_BOTH) {
1223 *pgid = id.id;
1224 return true;
1226 return false;
1229 static bool legacy_sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1231 struct unixid id;
1232 if (!legacy_sid_to_unixid(psid, &id)) {
1233 return false;
1235 if (id.type == ID_TYPE_UID || id.type == ID_TYPE_BOTH) {
1236 *puid = id.id;
1237 return true;
1239 return false;
1242 /*****************************************************************
1243 *THE CANONICAL* convert uid_t to SID function.
1244 *****************************************************************/
1246 void uid_to_sid(struct dom_sid *psid, uid_t uid)
1248 bool expired = true;
1249 bool ret;
1250 ZERO_STRUCTP(psid);
1252 /* Check the winbindd cache directly. */
1253 ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1255 if (ret && !expired && is_null_sid(psid)) {
1257 * Negative cache entry, we already asked.
1258 * do legacy.
1260 legacy_uid_to_sid(psid, uid);
1261 return;
1264 if (!ret || expired) {
1265 /* Not in cache. Ask winbindd. */
1266 if (!winbind_uid_to_sid(psid, uid)) {
1268 * We shouldn't return the NULL SID
1269 * here if winbind was running and
1270 * couldn't map, as winbind will have
1271 * added a negative entry that will
1272 * cause us to go though the
1273 * legacy_uid_to_sid()
1274 * function anyway in the case above
1275 * the next time we ask.
1277 DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1278 "for uid %u\n", (unsigned int)uid));
1280 legacy_uid_to_sid(psid, uid);
1281 return;
1285 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1286 sid_string_dbg(psid)));
1288 return;
1291 /*****************************************************************
1292 *THE CANONICAL* convert gid_t to SID function.
1293 *****************************************************************/
1295 void gid_to_sid(struct dom_sid *psid, gid_t gid)
1297 bool expired = true;
1298 bool ret;
1299 ZERO_STRUCTP(psid);
1301 /* Check the winbindd cache directly. */
1302 ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1304 if (ret && !expired && is_null_sid(psid)) {
1306 * Negative cache entry, we already asked.
1307 * do legacy.
1309 legacy_gid_to_sid(psid, gid);
1310 return;
1313 if (!ret || expired) {
1314 /* Not in cache. Ask winbindd. */
1315 if (!winbind_gid_to_sid(psid, gid)) {
1317 * We shouldn't return the NULL SID
1318 * here if winbind was running and
1319 * couldn't map, as winbind will have
1320 * added a negative entry that will
1321 * cause us to go though the
1322 * legacy_gid_to_sid()
1323 * function anyway in the case above
1324 * the next time we ask.
1326 DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1327 "for gid %u\n", (unsigned int)gid));
1329 legacy_gid_to_sid(psid, gid);
1330 return;
1334 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1335 sid_string_dbg(psid)));
1337 return;
1340 bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
1341 struct unixid *ids)
1343 struct wbcDomainSid *wbc_sids = NULL;
1344 struct wbcUnixId *wbc_ids = NULL;
1345 uint32_t i, num_not_cached;
1346 wbcErr err;
1347 bool ret = false;
1349 wbc_sids = talloc_array(talloc_tos(), struct wbcDomainSid, num_sids);
1350 if (wbc_sids == NULL) {
1351 return false;
1354 num_not_cached = 0;
1356 for (i=0; i<num_sids; i++) {
1357 bool expired;
1358 uint32_t rid;
1360 if (sid_peek_check_rid(&global_sid_Unix_Users,
1361 &sids[i], &rid)) {
1362 ids[i].type = ID_TYPE_UID;
1363 ids[i].id = rid;
1364 continue;
1366 if (sid_peek_check_rid(&global_sid_Unix_Groups,
1367 &sids[i], &rid)) {
1368 ids[i].type = ID_TYPE_GID;
1369 ids[i].id = rid;
1370 continue;
1372 if (idmap_cache_find_sid2unixid(&sids[i], &ids[i], &expired)
1373 && !expired)
1375 continue;
1377 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1378 memcpy(&wbc_sids[num_not_cached], &sids[i],
1379 ndr_size_dom_sid(&sids[i], 0));
1380 num_not_cached += 1;
1382 if (num_not_cached == 0) {
1383 goto done;
1385 wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, num_not_cached);
1386 if (wbc_ids == NULL) {
1387 goto fail;
1389 for (i=0; i<num_not_cached; i++) {
1390 wbc_ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1392 err = wbcSidsToUnixIds(wbc_sids, num_not_cached, wbc_ids);
1393 if (!WBC_ERROR_IS_OK(err)) {
1394 DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
1395 wbcErrorString(err)));
1398 num_not_cached = 0;
1400 for (i=0; i<num_sids; i++) {
1401 if (ids[i].type == ID_TYPE_NOT_SPECIFIED) {
1402 switch (wbc_ids[num_not_cached].type) {
1403 case WBC_ID_TYPE_UID:
1404 ids[i].type = ID_TYPE_UID;
1405 ids[i].id = wbc_ids[num_not_cached].id.uid;
1406 break;
1407 case WBC_ID_TYPE_GID:
1408 ids[i].type = ID_TYPE_GID;
1409 ids[i].id = wbc_ids[num_not_cached].id.gid;
1410 break;
1411 default:
1412 /* The types match, and wbcUnixId -> id is a union anyway */
1413 ids[i].type = (enum id_type)wbc_ids[num_not_cached].type;
1414 ids[i].id = wbc_ids[num_not_cached].id.gid;
1415 break;
1417 num_not_cached += 1;
1421 for (i=0; i<num_sids; i++) {
1422 if (ids[i].type != ID_TYPE_NOT_SPECIFIED) {
1423 continue;
1425 if (legacy_sid_to_gid(&sids[i], &ids[i].id)) {
1426 ids[i].type = ID_TYPE_GID;
1427 continue;
1429 if (legacy_sid_to_uid(&sids[i], &ids[i].id)) {
1430 ids[i].type = ID_TYPE_UID;
1431 continue;
1434 done:
1435 for (i=0; i<num_sids; i++) {
1436 switch(ids[i].type) {
1437 case WBC_ID_TYPE_GID:
1438 case WBC_ID_TYPE_UID:
1439 case WBC_ID_TYPE_BOTH:
1440 if (ids[i].id == -1) {
1441 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1443 break;
1444 case WBC_ID_TYPE_NOT_SPECIFIED:
1445 break;
1449 ret = true;
1450 fail:
1451 TALLOC_FREE(wbc_ids);
1452 TALLOC_FREE(wbc_sids);
1453 return ret;
1456 /*****************************************************************
1457 *THE CANONICAL* convert SID to uid function.
1458 *****************************************************************/
1460 bool sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1462 bool expired = true;
1463 bool ret;
1464 uint32_t rid;
1466 /* Optimize for the Unix Users Domain
1467 * as the conversion is straightforward */
1468 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1469 uid_t uid = rid;
1470 *puid = uid;
1472 /* return here, don't cache */
1473 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1474 (unsigned int)*puid ));
1475 return true;
1478 /* Check the winbindd cache directly. */
1479 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1481 if (ret && !expired && (*puid == (uid_t)-1)) {
1483 * Negative cache entry, we already asked.
1484 * do legacy.
1486 return legacy_sid_to_uid(psid, puid);
1489 if (!ret || expired) {
1490 /* Not in cache. Ask winbindd. */
1491 if (!winbind_sid_to_uid(puid, psid)) {
1492 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1493 sid_string_dbg(psid)));
1494 /* winbind failed. do legacy */
1495 return legacy_sid_to_uid(psid, puid);
1499 /* TODO: Here would be the place to allocate both a gid and a uid for
1500 * the SID in question */
1502 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1503 (unsigned int)*puid ));
1505 return true;
1508 /*****************************************************************
1509 *THE CANONICAL* convert SID to gid function.
1510 Group mapping is used for gids that maps to Wellknown SIDs
1511 *****************************************************************/
1513 bool sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1515 bool expired = true;
1516 bool ret;
1517 uint32_t rid;
1519 /* Optimize for the Unix Groups Domain
1520 * as the conversion is straightforward */
1521 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1522 gid_t gid = rid;
1523 *pgid = gid;
1525 /* return here, don't cache */
1526 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1527 (unsigned int)*pgid ));
1528 return true;
1531 /* Check the winbindd cache directly. */
1532 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1534 if (ret && !expired && (*pgid == (gid_t)-1)) {
1536 * Negative cache entry, we already asked.
1537 * do legacy.
1539 return legacy_sid_to_gid(psid, pgid);
1542 if (!ret || expired) {
1543 /* Not in cache or negative. Ask winbindd. */
1544 /* Ask winbindd if it can map this sid to a gid.
1545 * (Idmap will check it is a valid SID and of the right type) */
1547 if ( !winbind_sid_to_gid(pgid, psid) ) {
1549 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1550 sid_string_dbg(psid)));
1551 /* winbind failed. do legacy */
1552 return legacy_sid_to_gid(psid, pgid);
1556 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1557 (unsigned int)*pgid ));
1559 return true;
1563 * @brief This function gets the primary group SID mapping the primary
1564 * GID of the user as obtained by an actual getpwnam() call.
1565 * This is necessary to avoid issues with arbitrary group SIDs
1566 * stored in passdb. We try as hard as we can to get the SID
1567 * corresponding to the GID, including trying group mapping.
1568 * If nothing else works, we will force "Domain Users" as the
1569 * primary group.
1570 * This is needed because we must always be able to lookup the
1571 * primary group SID, so we cannot settle for an arbitrary SID.
1573 * This call can be expensive. Use with moderation.
1574 * If you have a "samu" struct around use pdb_get_group_sid()
1575 * instead as it does properly cache results.
1577 * @param mem_ctx[in] The memory context iused to allocate the result.
1578 * @param username[in] The user's name
1579 * @param _pwd[in|out] If available, pass in user's passwd struct.
1580 * It will contain a tallocated passwd if NULL was
1581 * passed in.
1582 * @param _group_sid[out] The user's Primary Group SID
1584 * @return NTSTATUS error code.
1586 NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx,
1587 const char *username,
1588 struct passwd **_pwd,
1589 struct dom_sid **_group_sid)
1591 TALLOC_CTX *tmp_ctx;
1592 bool need_lookup_sid = false;
1593 struct dom_sid *group_sid;
1594 struct passwd *pwd = *_pwd;
1596 tmp_ctx = talloc_new(mem_ctx);
1597 if (!tmp_ctx) {
1598 return NT_STATUS_NO_MEMORY;
1601 if (!pwd) {
1602 pwd = Get_Pwnam_alloc(mem_ctx, username);
1603 if (!pwd) {
1604 DEBUG(0, ("Failed to find a Unix account for %s\n",
1605 username));
1606 TALLOC_FREE(tmp_ctx);
1607 return NT_STATUS_NO_SUCH_USER;
1611 group_sid = talloc_zero(mem_ctx, struct dom_sid);
1612 if (!group_sid) {
1613 TALLOC_FREE(tmp_ctx);
1614 return NT_STATUS_NO_MEMORY;
1617 gid_to_sid(group_sid, pwd->pw_gid);
1618 if (!is_null_sid(group_sid)) {
1619 struct dom_sid domain_sid;
1620 uint32_t rid;
1622 /* We need a sid within our domain */
1623 sid_copy(&domain_sid, group_sid);
1624 sid_split_rid(&domain_sid, &rid);
1625 if (dom_sid_equal(&domain_sid, get_global_sam_sid())) {
1627 * As shortcut for the expensive lookup_sid call
1628 * compare the domain sid part
1630 switch (rid) {
1631 case DOMAIN_RID_ADMINS:
1632 case DOMAIN_RID_USERS:
1633 goto done;
1634 default:
1635 need_lookup_sid = true;
1636 break;
1638 } else {
1639 /* Try group mapping */
1640 struct unixid id;
1642 id.id = pwd->pw_gid;
1643 id.type = ID_TYPE_GID;
1645 ZERO_STRUCTP(group_sid);
1646 if (pdb_id_to_sid(&id, group_sid)) {
1647 need_lookup_sid = true;
1652 /* We must verify that this is a valid SID that resolves to a
1653 * group of the correct type */
1654 if (need_lookup_sid) {
1655 enum lsa_SidType type = SID_NAME_UNKNOWN;
1656 bool lookup_ret;
1658 DEBUG(10, ("do lookup_sid(%s) for group of user %s\n",
1659 sid_string_dbg(group_sid), username));
1661 /* Now check that it's actually a domain group and
1662 * not something else */
1663 lookup_ret = lookup_sid(tmp_ctx, group_sid,
1664 NULL, NULL, &type);
1666 if (lookup_ret && (type == SID_NAME_DOM_GRP)) {
1667 goto done;
1670 DEBUG(3, ("Primary group %s for user %s is"
1671 " a %s and not a domain group\n",
1672 sid_string_dbg(group_sid), username,
1673 sid_type_lookup(type)));
1676 /* Everything else, failed.
1677 * Just set it to the 'Domain Users' RID of 513 which will
1678 always resolve to a name */
1679 DEBUG(3, ("Forcing Primary Group to 'Domain Users' for %s\n",
1680 username));
1682 sid_compose(group_sid, get_global_sam_sid(), DOMAIN_RID_USERS);
1684 done:
1685 *_pwd = talloc_move(mem_ctx, &pwd);
1686 *_group_sid = talloc_move(mem_ctx, &group_sid);
1687 TALLOC_FREE(tmp_ctx);
1688 return NT_STATUS_OK;