torture: Improve winbindd.pac test to check multiple GENSEC mechanims
[Samba.git] / source3 / passdb / lookup_sid.c
blob494a8407c0a87e2941d08cc0ae16dfdc08efe3e1
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 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) == 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) == 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 our own SAM name. */
399 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
400 get_global_sam_name(),
401 full_name );
402 if (!qualified_name) {
403 return false;
406 if (lookup_name(mem_ctx, qualified_name, flags,
407 ret_domain, ret_name,
408 ret_sid, ret_type)) {
409 return true;
412 /* Finally try with "Unix Users" or "Unix Group" */
413 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
414 flags & LOOKUP_NAME_GROUP ?
415 unix_groups_domain_name() :
416 unix_users_domain_name(),
417 full_name );
418 if (!qualified_name) {
419 return false;
422 return lookup_name(mem_ctx, qualified_name, flags,
423 ret_domain, ret_name,
424 ret_sid, ret_type);
427 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
428 const struct dom_sid *domain_sid,
429 int num_rids, uint32 *rids,
430 const char **domain_name,
431 const char **names, enum lsa_SidType *types)
433 int i;
434 const char **my_names;
435 enum lsa_SidType *my_types;
436 TALLOC_CTX *tmp_ctx;
438 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
439 return false;
442 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
443 domain_name, &my_names, &my_types)) {
444 *domain_name = "";
445 for (i=0; i<num_rids; i++) {
446 names[i] = "";
447 types[i] = SID_NAME_UNKNOWN;
449 TALLOC_FREE(tmp_ctx);
450 return true;
453 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
454 TALLOC_FREE(tmp_ctx);
455 return false;
459 * winbind_lookup_rids allocates its own array. We've been given the
460 * array, so copy it over
463 for (i=0; i<num_rids; i++) {
464 if (my_names[i] == NULL) {
465 TALLOC_FREE(tmp_ctx);
466 return false;
468 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
469 TALLOC_FREE(tmp_ctx);
470 return false;
472 types[i] = my_types[i];
474 TALLOC_FREE(tmp_ctx);
475 return true;
478 static bool lookup_rids(TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid,
479 int num_rids, uint32_t *rids,
480 const char **domain_name,
481 const char ***names, enum lsa_SidType **types)
483 int i;
485 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
486 sid_string_dbg(domain_sid)));
488 if (num_rids) {
489 *names = talloc_zero_array(mem_ctx, const char *, num_rids);
490 *types = talloc_array(mem_ctx, enum lsa_SidType, num_rids);
492 if ((*names == NULL) || (*types == NULL)) {
493 return false;
496 for (i = 0; i < num_rids; i++)
497 (*types)[i] = SID_NAME_UNKNOWN;
498 } else {
499 *names = NULL;
500 *types = NULL;
503 if (sid_check_is_our_sam(domain_sid)) {
504 NTSTATUS result;
506 if (*domain_name == NULL) {
507 *domain_name = talloc_strdup(
508 mem_ctx, get_global_sam_name());
511 if (*domain_name == NULL) {
512 return false;
515 become_root();
516 result = pdb_lookup_rids(domain_sid, num_rids, rids,
517 *names, *types);
518 unbecome_root();
520 return (NT_STATUS_IS_OK(result) ||
521 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
522 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
525 if (sid_check_is_builtin(domain_sid)) {
527 if (*domain_name == NULL) {
528 *domain_name = talloc_strdup(
529 mem_ctx, builtin_domain_name());
532 if (*domain_name == NULL) {
533 return false;
536 for (i=0; i<num_rids; i++) {
537 if (lookup_builtin_rid(*names, rids[i],
538 &(*names)[i])) {
539 if ((*names)[i] == NULL) {
540 return false;
542 (*types)[i] = SID_NAME_ALIAS;
543 } else {
544 (*types)[i] = SID_NAME_UNKNOWN;
547 return true;
550 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
551 for (i=0; i<num_rids; i++) {
552 struct dom_sid sid;
553 sid_compose(&sid, domain_sid, rids[i]);
554 if (lookup_wellknown_sid(mem_ctx, &sid,
555 domain_name, &(*names)[i])) {
556 if ((*names)[i] == NULL) {
557 return false;
559 (*types)[i] = SID_NAME_WKN_GRP;
560 } else {
561 (*types)[i] = SID_NAME_UNKNOWN;
564 return true;
567 if (sid_check_is_unix_users(domain_sid)) {
568 if (*domain_name == NULL) {
569 *domain_name = talloc_strdup(
570 mem_ctx, unix_users_domain_name());
571 if (*domain_name == NULL) {
572 return false;
575 for (i=0; i<num_rids; i++) {
576 (*names)[i] = talloc_strdup(
577 (*names), uidtoname(rids[i]));
578 if ((*names)[i] == NULL) {
579 return false;
581 (*types)[i] = SID_NAME_USER;
583 return true;
586 if (sid_check_is_unix_groups(domain_sid)) {
587 if (*domain_name == NULL) {
588 *domain_name = talloc_strdup(
589 mem_ctx, unix_groups_domain_name());
590 if (*domain_name == NULL) {
591 return false;
594 for (i=0; i<num_rids; i++) {
595 (*names)[i] = talloc_strdup(
596 (*names), gidtoname(rids[i]));
597 if ((*names)[i] == NULL) {
598 return false;
600 (*types)[i] = SID_NAME_DOM_GRP;
602 return true;
605 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
606 domain_name, *names, *types);
610 * Is the SID a domain as such? If yes, lookup its name.
613 static bool lookup_as_domain(const struct dom_sid *sid, TALLOC_CTX *mem_ctx,
614 const char **name)
616 const char *tmp;
617 enum lsa_SidType type;
619 if (sid_check_is_our_sam(sid)) {
620 *name = talloc_strdup(mem_ctx, get_global_sam_name());
621 return true;
624 if (sid_check_is_builtin(sid)) {
625 *name = talloc_strdup(mem_ctx, builtin_domain_name());
626 return true;
629 if (sid_check_is_wellknown_domain(sid, &tmp)) {
630 *name = talloc_strdup(mem_ctx, tmp);
631 return true;
634 if (sid_check_is_unix_users(sid)) {
635 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
636 return true;
639 if (sid_check_is_unix_groups(sid)) {
640 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
641 return true;
644 if (sid->num_auths != 4) {
645 /* This can't be a domain */
646 return false;
649 if (IS_DC) {
650 uint32 i, num_domains;
651 struct trustdom_info **domains;
653 /* This is relatively expensive, but it happens only on DCs
654 * and for SIDs that have 4 sub-authorities and thus look like
655 * domains */
657 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
658 &num_domains,
659 &domains))) {
660 return false;
663 for (i=0; i<num_domains; i++) {
664 if (dom_sid_equal(sid, &domains[i]->sid)) {
665 *name = talloc_strdup(mem_ctx,
666 domains[i]->name);
667 return true;
670 return false;
673 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
674 (type == SID_NAME_DOMAIN)) {
675 *name = tmp;
676 return true;
679 return false;
683 * This tries to implement the rather weird rules for the lsa_lookup level
684 * parameter.
686 * This is as close as we can get to what W2k3 does. With this we survive the
687 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
688 * different, but I assume that's just being too liberal. For example, W2k3
689 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
690 * whereas NT4 does the same as level 1 (I think). I did not fully test that
691 * with NT4, this is what w2k3 does.
693 * Level 1: Ask everywhere
694 * Level 2: Ask domain and trusted domains, no builtin and wkn
695 * Level 3: Only ask domain
696 * Level 4: W2k3ad: Only ask AD trusts
697 * Level 5: Only ask transitive forest trusts
698 * Level 6: Like 4
701 static bool check_dom_sid_to_level(const struct dom_sid *sid, int level)
703 int ret = false;
705 switch(level) {
706 case 1:
707 ret = true;
708 break;
709 case 2:
710 ret = (!sid_check_is_builtin(sid) &&
711 !sid_check_is_wellknown_domain(sid, NULL));
712 break;
713 case 3:
714 case 4:
715 case 6:
716 ret = sid_check_is_our_sam(sid);
717 break;
718 case 5:
719 ret = false;
720 break;
723 DEBUG(10, ("%s SID %s in level %d\n",
724 ret ? "Accepting" : "Rejecting",
725 sid_string_dbg(sid), level));
726 return ret;
730 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
731 * references to domains, it is explicitly made for this.
733 * This attempts to be as efficient as possible: It collects all SIDs
734 * belonging to a domain and hands them in bulk to the appropriate lookup
735 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
736 * *hugely* from this.
739 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
740 const struct dom_sid **sids, int level,
741 struct lsa_dom_info **ret_domains,
742 struct lsa_name_info **ret_names)
744 TALLOC_CTX *tmp_ctx;
745 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
746 struct lsa_name_info *name_infos;
747 struct lsa_dom_info *dom_infos = NULL;
749 int i, j;
751 if (!(tmp_ctx = talloc_new(mem_ctx))) {
752 DEBUG(0, ("talloc_new failed\n"));
753 return NT_STATUS_NO_MEMORY;
756 if (num_sids) {
757 name_infos = talloc_array(mem_ctx, struct lsa_name_info, num_sids);
758 if (name_infos == NULL) {
759 result = NT_STATUS_NO_MEMORY;
760 goto fail;
762 } else {
763 name_infos = NULL;
766 dom_infos = talloc_zero_array(mem_ctx, struct lsa_dom_info,
767 LSA_REF_DOMAIN_LIST_MULTIPLIER);
768 if (dom_infos == NULL) {
769 result = NT_STATUS_NO_MEMORY;
770 goto fail;
773 /* First build up the data structures:
775 * dom_infos is a list of domains referenced in the list of
776 * SIDs. Later we will walk the list of domains and look up the RIDs
777 * in bulk.
779 * name_infos is a shadow-copy of the SIDs array to collect the real
780 * data.
782 * dom_info->idxs is an index into the name_infos array. The
783 * difficulty we have here is that we need to keep the SIDs the client
784 * asked for in the same order for the reply
787 for (i=0; i<num_sids; i++) {
788 struct dom_sid sid;
789 uint32_t rid = 0;
790 const char *domain_name = NULL;
792 sid_copy(&sid, sids[i]);
793 name_infos[i].type = SID_NAME_USE_NONE;
795 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
796 /* We can't push that through the normal lookup
797 * process, as this would reference illegal
798 * domains.
800 * For example S-1-5-32 would end up referencing
801 * domain S-1-5- with RID 32 which is clearly wrong.
803 if (domain_name == NULL) {
804 result = NT_STATUS_NO_MEMORY;
805 goto fail;
808 name_infos[i].rid = 0;
809 name_infos[i].type = SID_NAME_DOMAIN;
810 name_infos[i].name = NULL;
812 if (sid_check_is_builtin(&sid)) {
813 /* Yes, W2k3 returns "BUILTIN" both as domain
814 * and name here */
815 name_infos[i].name = talloc_strdup(
816 name_infos, builtin_domain_name());
817 if (name_infos[i].name == NULL) {
818 result = NT_STATUS_NO_MEMORY;
819 goto fail;
822 } else {
823 /* This is a normal SID with rid component */
824 if (!sid_split_rid(&sid, &rid)) {
825 result = NT_STATUS_INVALID_SID;
826 goto fail;
830 if (!check_dom_sid_to_level(&sid, level)) {
831 name_infos[i].rid = 0;
832 name_infos[i].type = SID_NAME_UNKNOWN;
833 name_infos[i].name = NULL;
834 continue;
837 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
838 if (!dom_infos[j].valid) {
839 break;
841 if (dom_sid_equal(&sid, &dom_infos[j].sid)) {
842 break;
846 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
847 /* TODO: What's the right error message here? */
848 result = NT_STATUS_NONE_MAPPED;
849 goto fail;
852 if (!dom_infos[j].valid) {
853 /* We found a domain not yet referenced, create a new
854 * ref. */
855 dom_infos[j].valid = true;
856 sid_copy(&dom_infos[j].sid, &sid);
858 if (domain_name != NULL) {
859 /* This name was being found above in the case
860 * when we found a domain SID */
861 dom_infos[j].name =
862 talloc_strdup(dom_infos, domain_name);
863 if (dom_infos[j].name == NULL) {
864 result = NT_STATUS_NO_MEMORY;
865 goto fail;
867 } else {
868 /* lookup_rids will take care of this */
869 dom_infos[j].name = NULL;
873 name_infos[i].dom_idx = j;
875 if (name_infos[i].type == SID_NAME_USE_NONE) {
876 name_infos[i].rid = rid;
878 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
879 &dom_infos[j].num_idxs);
881 if (dom_infos[j].idxs == NULL) {
882 result = NT_STATUS_NO_MEMORY;
883 goto fail;
888 /* Iterate over the domains found */
890 for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
891 uint32_t *rids;
892 const char *domain_name = NULL;
893 const char **names;
894 enum lsa_SidType *types;
895 struct lsa_dom_info *dom = &dom_infos[i];
897 if (!dom->valid) {
898 /* No domains left, we're done */
899 break;
902 if (dom->num_idxs == 0) {
904 * This happens only if the only sid related to
905 * this domain is the domain sid itself, which
906 * is mapped to SID_NAME_DOMAIN above.
908 continue;
911 if (!(rids = talloc_array(tmp_ctx, uint32, dom->num_idxs))) {
912 result = NT_STATUS_NO_MEMORY;
913 goto fail;
916 for (j=0; j<dom->num_idxs; j++) {
917 rids[j] = name_infos[dom->idxs[j]].rid;
920 if (!lookup_rids(tmp_ctx, &dom->sid,
921 dom->num_idxs, rids, &domain_name,
922 &names, &types)) {
923 result = NT_STATUS_NO_MEMORY;
924 goto fail;
927 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
928 result = NT_STATUS_NO_MEMORY;
929 goto fail;
932 for (j=0; j<dom->num_idxs; j++) {
933 int idx = dom->idxs[j];
934 name_infos[idx].type = types[j];
935 if (types[j] != SID_NAME_UNKNOWN) {
936 name_infos[idx].name =
937 talloc_strdup(name_infos, names[j]);
938 if (name_infos[idx].name == NULL) {
939 result = NT_STATUS_NO_MEMORY;
940 goto fail;
942 } else {
943 name_infos[idx].name = NULL;
948 *ret_domains = dom_infos;
949 *ret_names = name_infos;
950 TALLOC_FREE(tmp_ctx);
951 return NT_STATUS_OK;
953 fail:
954 TALLOC_FREE(dom_infos);
955 TALLOC_FREE(name_infos);
956 TALLOC_FREE(tmp_ctx);
957 return result;
960 /*****************************************************************
961 *THE CANONICAL* convert SID to name function.
962 *****************************************************************/
964 bool lookup_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
965 const char **ret_domain, const char **ret_name,
966 enum lsa_SidType *ret_type)
968 struct lsa_dom_info *domain;
969 struct lsa_name_info *name;
970 TALLOC_CTX *tmp_ctx;
971 bool ret = false;
973 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
975 if (!(tmp_ctx = talloc_new(mem_ctx))) {
976 DEBUG(0, ("talloc_new failed\n"));
977 return false;
980 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
981 &domain, &name))) {
982 goto done;
985 if (name->type == SID_NAME_UNKNOWN) {
986 goto done;
989 if ((ret_domain != NULL) &&
990 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
991 goto done;
994 if ((ret_name != NULL) &&
995 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
996 goto done;
999 if (ret_type != NULL) {
1000 *ret_type = name->type;
1003 ret = true;
1005 done:
1006 if (ret) {
1007 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
1008 domain->name, name->name, name->type));
1009 } else {
1010 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
1012 TALLOC_FREE(tmp_ctx);
1013 return ret;
1016 /*****************************************************************
1017 Id mapping cache. This is to avoid Winbind mappings already
1018 seen by smbd to be queried too frequently, keeping winbindd
1019 busy, and blocking smbd while winbindd is busy with other
1020 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1021 modified to use linked lists by jra.
1022 *****************************************************************/
1025 /*****************************************************************
1026 *THE LEGACY* convert uid_t to SID function.
1027 *****************************************************************/
1029 static void legacy_uid_to_sid(struct dom_sid *psid, uid_t uid)
1031 bool ret;
1032 struct unixid id;
1034 ZERO_STRUCTP(psid);
1036 id.id = uid;
1037 id.type = ID_TYPE_UID;
1039 become_root();
1040 ret = pdb_id_to_sid(&id, psid);
1041 unbecome_root();
1043 if (ret) {
1044 /* This is a mapped user */
1045 goto done;
1048 /* This is an unmapped user */
1050 uid_to_unix_users_sid(uid, psid);
1052 done:
1053 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1054 sid_string_dbg(psid)));
1056 return;
1059 /*****************************************************************
1060 *THE LEGACY* convert gid_t to SID function.
1061 *****************************************************************/
1063 static void legacy_gid_to_sid(struct dom_sid *psid, gid_t gid)
1065 bool ret;
1066 struct unixid id;
1068 ZERO_STRUCTP(psid);
1070 id.id = gid;
1071 id.type = ID_TYPE_GID;
1073 become_root();
1074 ret = pdb_id_to_sid(&id, psid);
1075 unbecome_root();
1077 if (ret) {
1078 /* This is a mapped group */
1079 goto done;
1082 /* This is an unmapped group */
1084 gid_to_unix_groups_sid(gid, psid);
1086 done:
1087 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1088 sid_string_dbg(psid)));
1090 return;
1093 /*****************************************************************
1094 *THE LEGACY* convert SID to id function.
1095 *****************************************************************/
1097 static bool legacy_sid_to_unixid(const struct dom_sid *psid, struct unixid *id)
1099 bool ret;
1101 become_root();
1102 ret = pdb_sid_to_id(psid, id);
1103 unbecome_root();
1105 if (!ret) {
1106 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1107 sid_string_dbg(psid)));
1108 return false;
1111 return true;
1114 static bool legacy_sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1116 struct unixid id;
1117 if (!legacy_sid_to_unixid(psid, &id)) {
1118 return false;
1120 if (id.type == ID_TYPE_GID || id.type == ID_TYPE_BOTH) {
1121 *pgid = id.id;
1122 return true;
1124 return false;
1127 static bool legacy_sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1129 struct unixid id;
1130 if (!legacy_sid_to_unixid(psid, &id)) {
1131 return false;
1133 if (id.type == ID_TYPE_UID || id.type == ID_TYPE_BOTH) {
1134 *puid = id.id;
1135 return true;
1137 return false;
1140 /*****************************************************************
1141 *THE CANONICAL* convert uid_t to SID function.
1142 *****************************************************************/
1144 void uid_to_sid(struct dom_sid *psid, uid_t uid)
1146 bool expired = true;
1147 bool ret;
1148 ZERO_STRUCTP(psid);
1150 /* Check the winbindd cache directly. */
1151 ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1153 if (ret && !expired && is_null_sid(psid)) {
1155 * Negative cache entry, we already asked.
1156 * do legacy.
1158 legacy_uid_to_sid(psid, uid);
1159 return;
1162 if (!ret || expired) {
1163 /* Not in cache. Ask winbindd. */
1164 if (!winbind_uid_to_sid(psid, uid)) {
1166 * We shouldn't return the NULL SID
1167 * here if winbind was running and
1168 * couldn't map, as winbind will have
1169 * added a negative entry that will
1170 * cause us to go though the
1171 * legacy_uid_to_sid()
1172 * function anyway in the case above
1173 * the next time we ask.
1175 DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1176 "for uid %u\n", (unsigned int)uid));
1178 legacy_uid_to_sid(psid, uid);
1179 return;
1183 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1184 sid_string_dbg(psid)));
1186 return;
1189 /*****************************************************************
1190 *THE CANONICAL* convert gid_t to SID function.
1191 *****************************************************************/
1193 void gid_to_sid(struct dom_sid *psid, gid_t gid)
1195 bool expired = true;
1196 bool ret;
1197 ZERO_STRUCTP(psid);
1199 /* Check the winbindd cache directly. */
1200 ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1202 if (ret && !expired && is_null_sid(psid)) {
1204 * Negative cache entry, we already asked.
1205 * do legacy.
1207 legacy_gid_to_sid(psid, gid);
1208 return;
1211 if (!ret || expired) {
1212 /* Not in cache. Ask winbindd. */
1213 if (!winbind_gid_to_sid(psid, gid)) {
1215 * We shouldn't return the NULL SID
1216 * here if winbind was running and
1217 * couldn't map, as winbind will have
1218 * added a negative entry that will
1219 * cause us to go though the
1220 * legacy_gid_to_sid()
1221 * function anyway in the case above
1222 * the next time we ask.
1224 DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1225 "for gid %u\n", (unsigned int)gid));
1227 legacy_gid_to_sid(psid, gid);
1228 return;
1232 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1233 sid_string_dbg(psid)));
1235 return;
1238 bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
1239 struct unixid *ids)
1241 struct wbcDomainSid *wbc_sids = NULL;
1242 struct wbcUnixId *wbc_ids = NULL;
1243 uint32_t i, num_not_cached;
1244 wbcErr err;
1245 bool ret = false;
1247 wbc_sids = talloc_array(talloc_tos(), struct wbcDomainSid, num_sids);
1248 if (wbc_sids == NULL) {
1249 return false;
1252 num_not_cached = 0;
1254 for (i=0; i<num_sids; i++) {
1255 bool expired;
1256 uint32_t rid;
1258 if (sid_peek_check_rid(&global_sid_Unix_Users,
1259 &sids[i], &rid)) {
1260 ids[i].type = ID_TYPE_UID;
1261 ids[i].id = rid;
1262 continue;
1264 if (sid_peek_check_rid(&global_sid_Unix_Groups,
1265 &sids[i], &rid)) {
1266 ids[i].type = ID_TYPE_GID;
1267 ids[i].id = rid;
1268 continue;
1270 if (idmap_cache_find_sid2unixid(&sids[i], &ids[i], &expired)
1271 && !expired)
1273 continue;
1275 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1276 memcpy(&wbc_sids[num_not_cached], &sids[i],
1277 ndr_size_dom_sid(&sids[i], 0));
1278 num_not_cached += 1;
1280 if (num_not_cached == 0) {
1281 goto done;
1283 wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, num_not_cached);
1284 if (wbc_ids == NULL) {
1285 goto fail;
1287 for (i=0; i<num_not_cached; i++) {
1288 wbc_ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1290 err = wbcSidsToUnixIds(wbc_sids, num_not_cached, wbc_ids);
1291 if (!WBC_ERROR_IS_OK(err)) {
1292 DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
1293 wbcErrorString(err)));
1296 num_not_cached = 0;
1298 for (i=0; i<num_sids; i++) {
1299 if (ids[i].type == ID_TYPE_NOT_SPECIFIED) {
1300 switch (wbc_ids[num_not_cached].type) {
1301 case WBC_ID_TYPE_UID:
1302 ids[i].type = ID_TYPE_UID;
1303 ids[i].id = wbc_ids[num_not_cached].id.uid;
1304 break;
1305 case WBC_ID_TYPE_GID:
1306 ids[i].type = ID_TYPE_GID;
1307 ids[i].id = wbc_ids[num_not_cached].id.gid;
1308 break;
1309 default:
1310 /* The types match, and wbcUnixId -> id is a union anyway */
1311 ids[i].type = (enum id_type)wbc_ids[num_not_cached].type;
1312 ids[i].id = wbc_ids[num_not_cached].id.gid;
1313 break;
1315 num_not_cached += 1;
1319 for (i=0; i<num_sids; i++) {
1320 if (ids[i].type != ID_TYPE_NOT_SPECIFIED) {
1321 continue;
1323 if (legacy_sid_to_gid(&sids[i], &ids[i].id)) {
1324 ids[i].type = ID_TYPE_GID;
1325 continue;
1327 if (legacy_sid_to_uid(&sids[i], &ids[i].id)) {
1328 ids[i].type = ID_TYPE_UID;
1329 continue;
1332 done:
1333 for (i=0; i<num_sids; i++) {
1334 switch(ids[i].type) {
1335 case WBC_ID_TYPE_GID:
1336 case WBC_ID_TYPE_UID:
1337 case WBC_ID_TYPE_BOTH:
1338 if (ids[i].id == -1) {
1339 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1341 break;
1342 case WBC_ID_TYPE_NOT_SPECIFIED:
1343 break;
1347 ret = true;
1348 fail:
1349 TALLOC_FREE(wbc_ids);
1350 TALLOC_FREE(wbc_sids);
1351 return ret;
1354 /*****************************************************************
1355 *THE CANONICAL* convert SID to uid function.
1356 *****************************************************************/
1358 bool sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1360 bool expired = true;
1361 bool ret;
1362 uint32 rid;
1364 /* Optimize for the Unix Users Domain
1365 * as the conversion is straightforward */
1366 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1367 uid_t uid = rid;
1368 *puid = uid;
1370 /* return here, don't cache */
1371 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1372 (unsigned int)*puid ));
1373 return true;
1376 /* Check the winbindd cache directly. */
1377 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1379 if (ret && !expired && (*puid == (uid_t)-1)) {
1381 * Negative cache entry, we already asked.
1382 * do legacy.
1384 return legacy_sid_to_uid(psid, puid);
1387 if (!ret || expired) {
1388 /* Not in cache. Ask winbindd. */
1389 if (!winbind_sid_to_uid(puid, psid)) {
1390 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1391 sid_string_dbg(psid)));
1392 /* winbind failed. do legacy */
1393 return legacy_sid_to_uid(psid, puid);
1397 /* TODO: Here would be the place to allocate both a gid and a uid for
1398 * the SID in question */
1400 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1401 (unsigned int)*puid ));
1403 return true;
1406 /*****************************************************************
1407 *THE CANONICAL* convert SID to gid function.
1408 Group mapping is used for gids that maps to Wellknown SIDs
1409 *****************************************************************/
1411 bool sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1413 bool expired = true;
1414 bool ret;
1415 uint32 rid;
1417 /* Optimize for the Unix Groups Domain
1418 * as the conversion is straightforward */
1419 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1420 gid_t gid = rid;
1421 *pgid = gid;
1423 /* return here, don't cache */
1424 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1425 (unsigned int)*pgid ));
1426 return true;
1429 /* Check the winbindd cache directly. */
1430 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1432 if (ret && !expired && (*pgid == (gid_t)-1)) {
1434 * Negative cache entry, we already asked.
1435 * do legacy.
1437 return legacy_sid_to_gid(psid, pgid);
1440 if (!ret || expired) {
1441 /* Not in cache or negative. Ask winbindd. */
1442 /* Ask winbindd if it can map this sid to a gid.
1443 * (Idmap will check it is a valid SID and of the right type) */
1445 if ( !winbind_sid_to_gid(pgid, psid) ) {
1447 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1448 sid_string_dbg(psid)));
1449 /* winbind failed. do legacy */
1450 return legacy_sid_to_gid(psid, pgid);
1454 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1455 (unsigned int)*pgid ));
1457 return true;
1461 * @brief This function gets the primary group SID mapping the primary
1462 * GID of the user as obtained by an actual getpwnam() call.
1463 * This is necessary to avoid issues with arbitrary group SIDs
1464 * stored in passdb. We try as hard as we can to get the SID
1465 * corresponding to the GID, including trying group mapping.
1466 * If nothing else works, we will force "Domain Users" as the
1467 * primary group.
1468 * This is needed because we must always be able to lookup the
1469 * primary group SID, so we cannot settle for an arbitrary SID.
1471 * This call can be expensive. Use with moderation.
1472 * If you have a "samu" struct around use pdb_get_group_sid()
1473 * instead as it does properly cache results.
1475 * @param mem_ctx[in] The memory context iused to allocate the result.
1476 * @param username[in] The user's name
1477 * @param _pwd[in|out] If available, pass in user's passwd struct.
1478 * It will contain a tallocated passwd if NULL was
1479 * passed in.
1480 * @param _group_sid[out] The user's Primary Group SID
1482 * @return NTSTATUS error code.
1484 NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx,
1485 const char *username,
1486 struct passwd **_pwd,
1487 struct dom_sid **_group_sid)
1489 TALLOC_CTX *tmp_ctx;
1490 bool need_lookup_sid = false;
1491 struct dom_sid *group_sid;
1492 struct passwd *pwd = *_pwd;
1494 tmp_ctx = talloc_new(mem_ctx);
1495 if (!tmp_ctx) {
1496 return NT_STATUS_NO_MEMORY;
1499 if (!pwd) {
1500 pwd = Get_Pwnam_alloc(mem_ctx, username);
1501 if (!pwd) {
1502 DEBUG(0, ("Failed to find a Unix account for %s\n",
1503 username));
1504 TALLOC_FREE(tmp_ctx);
1505 return NT_STATUS_NO_SUCH_USER;
1509 group_sid = talloc_zero(mem_ctx, struct dom_sid);
1510 if (!group_sid) {
1511 TALLOC_FREE(tmp_ctx);
1512 return NT_STATUS_NO_MEMORY;
1515 gid_to_sid(group_sid, pwd->pw_gid);
1516 if (!is_null_sid(group_sid)) {
1517 struct dom_sid domain_sid;
1518 uint32_t rid;
1520 /* We need a sid within our domain */
1521 sid_copy(&domain_sid, group_sid);
1522 sid_split_rid(&domain_sid, &rid);
1523 if (dom_sid_equal(&domain_sid, get_global_sam_sid())) {
1525 * As shortcut for the expensive lookup_sid call
1526 * compare the domain sid part
1528 switch (rid) {
1529 case DOMAIN_RID_ADMINS:
1530 case DOMAIN_RID_USERS:
1531 goto done;
1532 default:
1533 need_lookup_sid = true;
1534 break;
1536 } else {
1537 /* Try group mapping */
1538 struct unixid id;
1540 id.id = pwd->pw_gid;
1541 id.type = ID_TYPE_GID;
1543 ZERO_STRUCTP(group_sid);
1544 if (pdb_id_to_sid(&id, group_sid)) {
1545 need_lookup_sid = true;
1550 /* We must verify that this is a valid SID that resolves to a
1551 * group of the correct type */
1552 if (need_lookup_sid) {
1553 enum lsa_SidType type = SID_NAME_UNKNOWN;
1554 bool lookup_ret;
1556 DEBUG(10, ("do lookup_sid(%s) for group of user %s\n",
1557 sid_string_dbg(group_sid), username));
1559 /* Now check that it's actually a domain group and
1560 * not something else */
1561 lookup_ret = lookup_sid(tmp_ctx, group_sid,
1562 NULL, NULL, &type);
1564 if (lookup_ret && (type == SID_NAME_DOM_GRP)) {
1565 goto done;
1568 DEBUG(3, ("Primary group %s for user %s is"
1569 " a %s and not a domain group\n",
1570 sid_string_dbg(group_sid), username,
1571 sid_type_lookup(type)));
1574 /* Everything else, failed.
1575 * Just set it to the 'Domain Users' RID of 513 which will
1576 always resolve to a name */
1577 DEBUG(3, ("Forcing Primary Group to 'Domain Users' for %s\n",
1578 username));
1580 sid_compose(group_sid, get_global_sam_sid(), DOMAIN_RID_USERS);
1582 done:
1583 *_pwd = talloc_move(mem_ctx, &pwd);
1584 *_group_sid = talloc_move(mem_ctx, &group_sid);
1585 TALLOC_FREE(tmp_ctx);
1586 return NT_STATUS_OK;