s3-auth: make_new_system_info_session() not query passdb
[Samba/vl.git] / source3 / passdb / lookup_sid.c
blob3f8b06dfca96c8bdd2cd52cd63a51302bd1b25d3
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 "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 strupper_m(tmp_dom);
343 *ret_domain = tmp_dom;
346 if (ret_sid != NULL) {
347 sid_copy(ret_sid, &sid);
350 if (ret_type != NULL) {
351 *ret_type = type;
354 TALLOC_FREE(tmp_ctx);
355 return true;
358 /************************************************************************
359 Names from smb.conf can be unqualified. eg. valid users = foo
360 These names should never map to a remote name. Try global_sam_name()\foo,
361 and then "Unix Users"\foo (or "Unix Groups"\foo).
362 ************************************************************************/
364 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
365 const char *full_name, int flags,
366 const char **ret_domain, const char **ret_name,
367 struct dom_sid *ret_sid, enum lsa_SidType *ret_type)
369 char *qualified_name;
370 const char *p;
372 /* NB. No winbindd_separator here as lookup_name needs \\' */
373 if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
375 /* The name is already qualified with a domain. */
377 if (*lp_winbind_separator() != '\\') {
378 char *tmp;
380 /* lookup_name() needs '\\' as a separator */
382 tmp = talloc_strdup(mem_ctx, full_name);
383 if (!tmp) {
384 return false;
386 tmp[p - full_name] = '\\';
387 full_name = tmp;
390 return lookup_name(mem_ctx, full_name, flags,
391 ret_domain, ret_name,
392 ret_sid, ret_type);
395 /* Try with our own SAM name. */
396 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
397 get_global_sam_name(),
398 full_name );
399 if (!qualified_name) {
400 return false;
403 if (lookup_name(mem_ctx, qualified_name, flags,
404 ret_domain, ret_name,
405 ret_sid, ret_type)) {
406 return true;
409 /* Finally try with "Unix Users" or "Unix Group" */
410 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
411 flags & LOOKUP_NAME_GROUP ?
412 unix_groups_domain_name() :
413 unix_users_domain_name(),
414 full_name );
415 if (!qualified_name) {
416 return false;
419 return lookup_name(mem_ctx, qualified_name, flags,
420 ret_domain, ret_name,
421 ret_sid, ret_type);
424 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
425 const struct dom_sid *domain_sid,
426 int num_rids, uint32 *rids,
427 const char **domain_name,
428 const char **names, enum lsa_SidType *types)
430 int i;
431 const char **my_names;
432 enum lsa_SidType *my_types;
433 TALLOC_CTX *tmp_ctx;
435 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
436 return false;
439 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
440 domain_name, &my_names, &my_types)) {
441 *domain_name = "";
442 for (i=0; i<num_rids; i++) {
443 names[i] = "";
444 types[i] = SID_NAME_UNKNOWN;
446 TALLOC_FREE(tmp_ctx);
447 return true;
450 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
451 TALLOC_FREE(tmp_ctx);
452 return false;
456 * winbind_lookup_rids allocates its own array. We've been given the
457 * array, so copy it over
460 for (i=0; i<num_rids; i++) {
461 if (my_names[i] == NULL) {
462 TALLOC_FREE(tmp_ctx);
463 return false;
465 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
466 TALLOC_FREE(tmp_ctx);
467 return false;
469 types[i] = my_types[i];
471 TALLOC_FREE(tmp_ctx);
472 return true;
475 static bool lookup_rids(TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid,
476 int num_rids, uint32_t *rids,
477 const char **domain_name,
478 const char ***names, enum lsa_SidType **types)
480 int i;
482 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
483 sid_string_dbg(domain_sid)));
485 if (num_rids) {
486 *names = talloc_zero_array(mem_ctx, const char *, num_rids);
487 *types = talloc_array(mem_ctx, enum lsa_SidType, num_rids);
489 if ((*names == NULL) || (*types == NULL)) {
490 return false;
493 for (i = 0; i < num_rids; i++)
494 (*types)[i] = SID_NAME_UNKNOWN;
495 } else {
496 *names = NULL;
497 *types = NULL;
500 if (sid_check_is_domain(domain_sid)) {
501 NTSTATUS result;
503 if (*domain_name == NULL) {
504 *domain_name = talloc_strdup(
505 mem_ctx, get_global_sam_name());
508 if (*domain_name == NULL) {
509 return false;
512 become_root();
513 result = pdb_lookup_rids(domain_sid, num_rids, rids,
514 *names, *types);
515 unbecome_root();
517 return (NT_STATUS_IS_OK(result) ||
518 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
519 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
522 if (sid_check_is_builtin(domain_sid)) {
524 if (*domain_name == NULL) {
525 *domain_name = talloc_strdup(
526 mem_ctx, builtin_domain_name());
529 if (*domain_name == NULL) {
530 return false;
533 for (i=0; i<num_rids; i++) {
534 if (lookup_builtin_rid(*names, rids[i],
535 &(*names)[i])) {
536 if ((*names)[i] == NULL) {
537 return false;
539 (*types)[i] = SID_NAME_ALIAS;
540 } else {
541 (*types)[i] = SID_NAME_UNKNOWN;
544 return true;
547 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
548 for (i=0; i<num_rids; i++) {
549 struct dom_sid sid;
550 sid_compose(&sid, domain_sid, rids[i]);
551 if (lookup_wellknown_sid(mem_ctx, &sid,
552 domain_name, &(*names)[i])) {
553 if ((*names)[i] == NULL) {
554 return false;
556 (*types)[i] = SID_NAME_WKN_GRP;
557 } else {
558 (*types)[i] = SID_NAME_UNKNOWN;
561 return true;
564 if (sid_check_is_unix_users(domain_sid)) {
565 if (*domain_name == NULL) {
566 *domain_name = talloc_strdup(
567 mem_ctx, unix_users_domain_name());
568 if (*domain_name == NULL) {
569 return false;
572 for (i=0; i<num_rids; i++) {
573 (*names)[i] = talloc_strdup(
574 (*names), uidtoname(rids[i]));
575 if ((*names)[i] == NULL) {
576 return false;
578 (*types)[i] = SID_NAME_USER;
580 return true;
583 if (sid_check_is_unix_groups(domain_sid)) {
584 if (*domain_name == NULL) {
585 *domain_name = talloc_strdup(
586 mem_ctx, unix_groups_domain_name());
587 if (*domain_name == NULL) {
588 return false;
591 for (i=0; i<num_rids; i++) {
592 (*names)[i] = talloc_strdup(
593 (*names), gidtoname(rids[i]));
594 if ((*names)[i] == NULL) {
595 return false;
597 (*types)[i] = SID_NAME_DOM_GRP;
599 return true;
602 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
603 domain_name, *names, *types);
607 * Is the SID a domain as such? If yes, lookup its name.
610 static bool lookup_as_domain(const struct dom_sid *sid, TALLOC_CTX *mem_ctx,
611 const char **name)
613 const char *tmp;
614 enum lsa_SidType type;
616 if (sid_check_is_domain(sid)) {
617 *name = talloc_strdup(mem_ctx, get_global_sam_name());
618 return true;
621 if (sid_check_is_builtin(sid)) {
622 *name = talloc_strdup(mem_ctx, builtin_domain_name());
623 return true;
626 if (sid_check_is_wellknown_domain(sid, &tmp)) {
627 *name = talloc_strdup(mem_ctx, tmp);
628 return true;
631 if (sid_check_is_unix_users(sid)) {
632 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
633 return true;
636 if (sid_check_is_unix_groups(sid)) {
637 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
638 return true;
641 if (sid->num_auths != 4) {
642 /* This can't be a domain */
643 return false;
646 if (IS_DC) {
647 uint32 i, num_domains;
648 struct trustdom_info **domains;
650 /* This is relatively expensive, but it happens only on DCs
651 * and for SIDs that have 4 sub-authorities and thus look like
652 * domains */
654 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
655 &num_domains,
656 &domains))) {
657 return false;
660 for (i=0; i<num_domains; i++) {
661 if (dom_sid_equal(sid, &domains[i]->sid)) {
662 *name = talloc_strdup(mem_ctx,
663 domains[i]->name);
664 return true;
667 return false;
670 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
671 (type == SID_NAME_DOMAIN)) {
672 *name = tmp;
673 return true;
676 return false;
680 * This tries to implement the rather weird rules for the lsa_lookup level
681 * parameter.
683 * This is as close as we can get to what W2k3 does. With this we survive the
684 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
685 * different, but I assume that's just being too liberal. For example, W2k3
686 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
687 * whereas NT4 does the same as level 1 (I think). I did not fully test that
688 * with NT4, this is what w2k3 does.
690 * Level 1: Ask everywhere
691 * Level 2: Ask domain and trusted domains, no builtin and wkn
692 * Level 3: Only ask domain
693 * Level 4: W2k3ad: Only ask AD trusts
694 * Level 5: Only ask transitive forest trusts
695 * Level 6: Like 4
698 static bool check_dom_sid_to_level(const struct dom_sid *sid, int level)
700 int ret = false;
702 switch(level) {
703 case 1:
704 ret = true;
705 break;
706 case 2:
707 ret = (!sid_check_is_builtin(sid) &&
708 !sid_check_is_wellknown_domain(sid, NULL));
709 break;
710 case 3:
711 case 4:
712 case 6:
713 ret = sid_check_is_domain(sid);
714 break;
715 case 5:
716 ret = false;
717 break;
720 DEBUG(10, ("%s SID %s in level %d\n",
721 ret ? "Accepting" : "Rejecting",
722 sid_string_dbg(sid), level));
723 return ret;
727 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
728 * references to domains, it is explicitly made for this.
730 * This attempts to be as efficient as possible: It collects all SIDs
731 * belonging to a domain and hands them in bulk to the appropriate lookup
732 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
733 * *hugely* from this.
736 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
737 const struct dom_sid **sids, int level,
738 struct lsa_dom_info **ret_domains,
739 struct lsa_name_info **ret_names)
741 TALLOC_CTX *tmp_ctx;
742 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
743 struct lsa_name_info *name_infos;
744 struct lsa_dom_info *dom_infos = NULL;
746 int i, j;
748 if (!(tmp_ctx = talloc_new(mem_ctx))) {
749 DEBUG(0, ("talloc_new failed\n"));
750 return NT_STATUS_NO_MEMORY;
753 if (num_sids) {
754 name_infos = talloc_array(mem_ctx, struct lsa_name_info, num_sids);
755 if (name_infos == NULL) {
756 result = NT_STATUS_NO_MEMORY;
757 goto fail;
759 } else {
760 name_infos = NULL;
763 dom_infos = talloc_zero_array(mem_ctx, struct lsa_dom_info,
764 LSA_REF_DOMAIN_LIST_MULTIPLIER);
765 if (dom_infos == NULL) {
766 result = NT_STATUS_NO_MEMORY;
767 goto fail;
770 /* First build up the data structures:
772 * dom_infos is a list of domains referenced in the list of
773 * SIDs. Later we will walk the list of domains and look up the RIDs
774 * in bulk.
776 * name_infos is a shadow-copy of the SIDs array to collect the real
777 * data.
779 * dom_info->idxs is an index into the name_infos array. The
780 * difficulty we have here is that we need to keep the SIDs the client
781 * asked for in the same order for the reply
784 for (i=0; i<num_sids; i++) {
785 struct dom_sid sid;
786 uint32_t rid = 0;
787 const char *domain_name = NULL;
789 sid_copy(&sid, sids[i]);
790 name_infos[i].type = SID_NAME_USE_NONE;
792 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
793 /* We can't push that through the normal lookup
794 * process, as this would reference illegal
795 * domains.
797 * For example S-1-5-32 would end up referencing
798 * domain S-1-5- with RID 32 which is clearly wrong.
800 if (domain_name == NULL) {
801 result = NT_STATUS_NO_MEMORY;
802 goto fail;
805 name_infos[i].rid = 0;
806 name_infos[i].type = SID_NAME_DOMAIN;
807 name_infos[i].name = NULL;
809 if (sid_check_is_builtin(&sid)) {
810 /* Yes, W2k3 returns "BUILTIN" both as domain
811 * and name here */
812 name_infos[i].name = talloc_strdup(
813 name_infos, builtin_domain_name());
814 if (name_infos[i].name == NULL) {
815 result = NT_STATUS_NO_MEMORY;
816 goto fail;
819 } else {
820 /* This is a normal SID with rid component */
821 if (!sid_split_rid(&sid, &rid)) {
822 result = NT_STATUS_INVALID_SID;
823 goto fail;
827 if (!check_dom_sid_to_level(&sid, level)) {
828 name_infos[i].rid = 0;
829 name_infos[i].type = SID_NAME_UNKNOWN;
830 name_infos[i].name = NULL;
831 continue;
834 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
835 if (!dom_infos[j].valid) {
836 break;
838 if (dom_sid_equal(&sid, &dom_infos[j].sid)) {
839 break;
843 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
844 /* TODO: What's the right error message here? */
845 result = NT_STATUS_NONE_MAPPED;
846 goto fail;
849 if (!dom_infos[j].valid) {
850 /* We found a domain not yet referenced, create a new
851 * ref. */
852 dom_infos[j].valid = true;
853 sid_copy(&dom_infos[j].sid, &sid);
855 if (domain_name != NULL) {
856 /* This name was being found above in the case
857 * when we found a domain SID */
858 dom_infos[j].name =
859 talloc_strdup(dom_infos, domain_name);
860 if (dom_infos[j].name == NULL) {
861 result = NT_STATUS_NO_MEMORY;
862 goto fail;
864 } else {
865 /* lookup_rids will take care of this */
866 dom_infos[j].name = NULL;
870 name_infos[i].dom_idx = j;
872 if (name_infos[i].type == SID_NAME_USE_NONE) {
873 name_infos[i].rid = rid;
875 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
876 &dom_infos[j].num_idxs);
878 if (dom_infos[j].idxs == NULL) {
879 result = NT_STATUS_NO_MEMORY;
880 goto fail;
885 /* Iterate over the domains found */
887 for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
888 uint32_t *rids;
889 const char *domain_name = NULL;
890 const char **names;
891 enum lsa_SidType *types;
892 struct lsa_dom_info *dom = &dom_infos[i];
894 if (!dom->valid) {
895 /* No domains left, we're done */
896 break;
899 if (dom->num_idxs) {
900 if (!(rids = talloc_array(tmp_ctx, uint32, dom->num_idxs))) {
901 result = NT_STATUS_NO_MEMORY;
902 goto fail;
904 } else {
905 rids = NULL;
908 for (j=0; j<dom->num_idxs; j++) {
909 rids[j] = name_infos[dom->idxs[j]].rid;
912 if (!lookup_rids(tmp_ctx, &dom->sid,
913 dom->num_idxs, rids, &domain_name,
914 &names, &types)) {
915 result = NT_STATUS_NO_MEMORY;
916 goto fail;
919 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
920 result = NT_STATUS_NO_MEMORY;
921 goto fail;
924 for (j=0; j<dom->num_idxs; j++) {
925 int idx = dom->idxs[j];
926 name_infos[idx].type = types[j];
927 if (types[j] != SID_NAME_UNKNOWN) {
928 name_infos[idx].name =
929 talloc_strdup(name_infos, names[j]);
930 if (name_infos[idx].name == NULL) {
931 result = NT_STATUS_NO_MEMORY;
932 goto fail;
934 } else {
935 name_infos[idx].name = NULL;
940 *ret_domains = dom_infos;
941 *ret_names = name_infos;
942 TALLOC_FREE(tmp_ctx);
943 return NT_STATUS_OK;
945 fail:
946 TALLOC_FREE(dom_infos);
947 TALLOC_FREE(name_infos);
948 TALLOC_FREE(tmp_ctx);
949 return result;
952 /*****************************************************************
953 *THE CANONICAL* convert SID to name function.
954 *****************************************************************/
956 bool lookup_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
957 const char **ret_domain, const char **ret_name,
958 enum lsa_SidType *ret_type)
960 struct lsa_dom_info *domain;
961 struct lsa_name_info *name;
962 TALLOC_CTX *tmp_ctx;
963 bool ret = false;
965 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
967 if (!(tmp_ctx = talloc_new(mem_ctx))) {
968 DEBUG(0, ("talloc_new failed\n"));
969 return false;
972 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
973 &domain, &name))) {
974 goto done;
977 if (name->type == SID_NAME_UNKNOWN) {
978 goto done;
981 if ((ret_domain != NULL) &&
982 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
983 goto done;
986 if ((ret_name != NULL) &&
987 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
988 goto done;
991 if (ret_type != NULL) {
992 *ret_type = name->type;
995 ret = true;
997 done:
998 if (ret) {
999 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
1000 domain->name, name->name, name->type));
1001 } else {
1002 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
1004 TALLOC_FREE(tmp_ctx);
1005 return ret;
1008 /*****************************************************************
1009 Id mapping cache. This is to avoid Winbind mappings already
1010 seen by smbd to be queried too frequently, keeping winbindd
1011 busy, and blocking smbd while winbindd is busy with other
1012 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1013 modified to use linked lists by jra.
1014 *****************************************************************/
1017 /*****************************************************************
1018 *THE LEGACY* convert uid_t to SID function.
1019 *****************************************************************/
1021 static void legacy_uid_to_sid(struct dom_sid *psid, uid_t uid)
1023 bool ret;
1025 ZERO_STRUCTP(psid);
1027 become_root();
1028 ret = pdb_uid_to_sid(uid, psid);
1029 unbecome_root();
1031 if (ret) {
1032 /* This is a mapped user */
1033 goto done;
1036 /* This is an unmapped user */
1038 uid_to_unix_users_sid(uid, psid);
1040 done:
1041 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1042 sid_string_dbg(psid)));
1044 return;
1047 /*****************************************************************
1048 *THE LEGACY* convert gid_t to SID function.
1049 *****************************************************************/
1051 static void legacy_gid_to_sid(struct dom_sid *psid, gid_t gid)
1053 bool ret;
1055 ZERO_STRUCTP(psid);
1057 become_root();
1058 ret = pdb_gid_to_sid(gid, psid);
1059 unbecome_root();
1061 if (ret) {
1062 /* This is a mapped group */
1063 goto done;
1066 /* This is an unmapped group */
1068 gid_to_unix_groups_sid(gid, psid);
1070 done:
1071 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1072 sid_string_dbg(psid)));
1074 return;
1077 /*****************************************************************
1078 *THE LEGACY* convert SID to id function.
1079 *****************************************************************/
1081 static bool legacy_sid_to_unixid(const struct dom_sid *psid, struct unixid *id)
1083 GROUP_MAP *map;
1084 if (sid_check_is_in_our_domain(psid)) {
1085 bool ret;
1087 become_root();
1088 ret = pdb_sid_to_id(psid, id);
1089 unbecome_root();
1091 if (ret) {
1092 goto done;
1095 /* This was ours, but it was not mapped. Fail */
1098 if ((sid_check_is_in_builtin(psid) ||
1099 sid_check_is_in_wellknown_domain(psid))) {
1100 bool ret;
1102 map = talloc_zero(NULL, GROUP_MAP);
1103 if (!map) {
1104 return false;
1107 become_root();
1108 ret = pdb_getgrsid(map, *psid);
1109 unbecome_root();
1111 if (ret) {
1112 id->id = map->gid;
1113 id->type = ID_TYPE_GID;
1114 TALLOC_FREE(map);
1115 goto done;
1117 TALLOC_FREE(map);
1118 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1119 sid_string_dbg(psid)));
1120 return false;
1123 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1124 sid_string_dbg(psid)));
1125 return false;
1127 done:
1128 return true;
1131 static bool legacy_sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1133 struct unixid id;
1134 if (!legacy_sid_to_unixid(psid, &id)) {
1135 return false;
1137 if (id.type == ID_TYPE_GID || id.type == ID_TYPE_BOTH) {
1138 *pgid = id.id;
1139 return true;
1141 return false;
1144 static bool legacy_sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1146 struct unixid id;
1147 if (!legacy_sid_to_unixid(psid, &id)) {
1148 return false;
1150 if (id.type == ID_TYPE_UID || id.type == ID_TYPE_BOTH) {
1151 *puid = id.id;
1152 return true;
1154 return false;
1157 /*****************************************************************
1158 *THE CANONICAL* convert uid_t to SID function.
1159 *****************************************************************/
1161 void uid_to_sid(struct dom_sid *psid, uid_t uid)
1163 bool expired = true;
1164 bool ret;
1165 ZERO_STRUCTP(psid);
1167 /* Check the winbindd cache directly. */
1168 ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1170 if (ret && !expired && is_null_sid(psid)) {
1172 * Negative cache entry, we already asked.
1173 * do legacy.
1175 legacy_uid_to_sid(psid, uid);
1176 return;
1179 if (!ret || expired) {
1180 /* Not in cache. Ask winbindd. */
1181 if (!winbind_uid_to_sid(psid, uid)) {
1183 * We shouldn't return the NULL SID
1184 * here if winbind was running and
1185 * couldn't map, as winbind will have
1186 * added a negative entry that will
1187 * cause us to go though the
1188 * legacy_uid_to_sid()
1189 * function anyway in the case above
1190 * the next time we ask.
1192 DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1193 "for uid %u\n", (unsigned int)uid));
1195 legacy_uid_to_sid(psid, uid);
1196 return;
1200 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1201 sid_string_dbg(psid)));
1203 return;
1206 /*****************************************************************
1207 *THE CANONICAL* convert gid_t to SID function.
1208 *****************************************************************/
1210 void gid_to_sid(struct dom_sid *psid, gid_t gid)
1212 bool expired = true;
1213 bool ret;
1214 ZERO_STRUCTP(psid);
1216 /* Check the winbindd cache directly. */
1217 ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1219 if (ret && !expired && is_null_sid(psid)) {
1221 * Negative cache entry, we already asked.
1222 * do legacy.
1224 legacy_gid_to_sid(psid, gid);
1225 return;
1228 if (!ret || expired) {
1229 /* Not in cache. Ask winbindd. */
1230 if (!winbind_gid_to_sid(psid, gid)) {
1232 * We shouldn't return the NULL SID
1233 * here if winbind was running and
1234 * couldn't map, as winbind will have
1235 * added a negative entry that will
1236 * cause us to go though the
1237 * legacy_gid_to_sid()
1238 * function anyway in the case above
1239 * the next time we ask.
1241 DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1242 "for gid %u\n", (unsigned int)gid));
1244 legacy_gid_to_sid(psid, gid);
1245 return;
1249 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1250 sid_string_dbg(psid)));
1252 return;
1255 bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
1256 struct unixid *ids)
1258 struct wbcDomainSid *wbc_sids = NULL;
1259 struct wbcUnixId *wbc_ids = NULL;
1260 uint32_t i, num_not_cached;
1261 wbcErr err;
1262 bool ret = false;
1264 wbc_sids = talloc_array(talloc_tos(), struct wbcDomainSid, num_sids);
1265 if (wbc_sids == NULL) {
1266 return false;
1269 num_not_cached = 0;
1271 for (i=0; i<num_sids; i++) {
1272 bool expired;
1273 uint32_t rid;
1275 if (sid_peek_check_rid(&global_sid_Unix_Users,
1276 &sids[i], &rid)) {
1277 ids[i].type = ID_TYPE_UID;
1278 ids[i].id = rid;
1279 continue;
1281 if (sid_peek_check_rid(&global_sid_Unix_Groups,
1282 &sids[i], &rid)) {
1283 ids[i].type = ID_TYPE_GID;
1284 ids[i].id = rid;
1285 continue;
1287 if (idmap_cache_find_sid2unixid(&sids[i], &ids[i], &expired)
1288 && !expired)
1290 continue;
1292 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1293 memcpy(&wbc_sids[num_not_cached], &sids[i],
1294 ndr_size_dom_sid(&sids[i], 0));
1295 num_not_cached += 1;
1297 if (num_not_cached == 0) {
1298 goto done;
1300 wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, num_not_cached);
1301 if (wbc_ids == NULL) {
1302 goto fail;
1304 for (i=0; i<num_not_cached; i++) {
1305 wbc_ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1307 err = wbcSidsToUnixIds(wbc_sids, num_not_cached, wbc_ids);
1308 if (!WBC_ERROR_IS_OK(err)) {
1309 DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
1310 wbcErrorString(err)));
1313 num_not_cached = 0;
1315 for (i=0; i<num_sids; i++) {
1316 if (ids[i].type == ID_TYPE_NOT_SPECIFIED) {
1317 switch (wbc_ids[num_not_cached].type) {
1318 case ID_TYPE_UID:
1319 ids[i].type = WBC_ID_TYPE_UID;
1320 ids[i].id = wbc_ids[num_not_cached].id.uid;
1321 break;
1322 case ID_TYPE_GID:
1323 ids[i].type = WBC_ID_TYPE_GID;
1324 ids[i].id = wbc_ids[num_not_cached].id.gid;
1325 break;
1326 default:
1327 /* The types match, and wbcUnixId -> id is a union anyway */
1328 ids[i].type = wbc_ids[num_not_cached].type;
1329 ids[i].id = wbc_ids[num_not_cached].id.gid;
1330 break;
1332 num_not_cached += 1;
1336 for (i=0; i<num_sids; i++) {
1337 if (ids[i].type != ID_TYPE_NOT_SPECIFIED) {
1338 continue;
1340 if (legacy_sid_to_gid(&sids[i], &ids[i].id)) {
1341 ids[i].type = ID_TYPE_GID;
1342 continue;
1344 if (legacy_sid_to_uid(&sids[i], &ids[i].id)) {
1345 ids[i].type = ID_TYPE_UID;
1346 continue;
1349 done:
1350 for (i=0; i<num_sids; i++) {
1351 switch(ids[i].type) {
1352 case WBC_ID_TYPE_GID:
1353 case WBC_ID_TYPE_UID:
1354 case WBC_ID_TYPE_BOTH:
1355 if (ids[i].id == -1) {
1356 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1358 break;
1359 case WBC_ID_TYPE_NOT_SPECIFIED:
1360 break;
1364 ret = true;
1365 fail:
1366 TALLOC_FREE(wbc_ids);
1367 TALLOC_FREE(wbc_sids);
1368 return ret;
1371 /*****************************************************************
1372 *THE CANONICAL* convert SID to uid function.
1373 *****************************************************************/
1375 bool sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1377 bool expired = true;
1378 bool ret;
1379 uint32 rid;
1381 /* Optimize for the Unix Users Domain
1382 * as the conversion is straightforward */
1383 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1384 uid_t uid = rid;
1385 *puid = uid;
1387 /* return here, don't cache */
1388 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1389 (unsigned int)*puid ));
1390 return true;
1393 /* Check the winbindd cache directly. */
1394 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1396 if (ret && !expired && (*puid == (uid_t)-1)) {
1398 * Negative cache entry, we already asked.
1399 * do legacy.
1401 return legacy_sid_to_uid(psid, puid);
1404 if (!ret || expired) {
1405 /* Not in cache. Ask winbindd. */
1406 if (!winbind_sid_to_uid(puid, psid)) {
1407 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1408 sid_string_dbg(psid)));
1409 /* winbind failed. do legacy */
1410 return legacy_sid_to_uid(psid, puid);
1414 /* TODO: Here would be the place to allocate both a gid and a uid for
1415 * the SID in question */
1417 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1418 (unsigned int)*puid ));
1420 return true;
1423 /*****************************************************************
1424 *THE CANONICAL* convert SID to gid function.
1425 Group mapping is used for gids that maps to Wellknown SIDs
1426 *****************************************************************/
1428 bool sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1430 bool expired = true;
1431 bool ret;
1432 uint32 rid;
1434 /* Optimize for the Unix Groups Domain
1435 * as the conversion is straightforward */
1436 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1437 gid_t gid = rid;
1438 *pgid = gid;
1440 /* return here, don't cache */
1441 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1442 (unsigned int)*pgid ));
1443 return true;
1446 /* Check the winbindd cache directly. */
1447 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1449 if (ret && !expired && (*pgid == (gid_t)-1)) {
1451 * Negative cache entry, we already asked.
1452 * do legacy.
1454 return legacy_sid_to_gid(psid, pgid);
1457 if (!ret || expired) {
1458 /* Not in cache or negative. Ask winbindd. */
1459 /* Ask winbindd if it can map this sid to a gid.
1460 * (Idmap will check it is a valid SID and of the right type) */
1462 if ( !winbind_sid_to_gid(pgid, psid) ) {
1464 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1465 sid_string_dbg(psid)));
1466 /* winbind failed. do legacy */
1467 return legacy_sid_to_gid(psid, pgid);
1471 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1472 (unsigned int)*pgid ));
1474 return true;
1478 * @brief This function gets the primary group SID mapping the primary
1479 * GID of the user as obtained by an actual getpwnam() call.
1480 * This is necessary to avoid issues with arbitrary group SIDs
1481 * stored in passdb. We try as hard as we can to get the SID
1482 * corresponding to the GID, including trying group mapping.
1483 * If nothing else works, we will force "Domain Users" as the
1484 * primary group.
1485 * This is needed because we must always be able to lookup the
1486 * primary group SID, so we cannot settle for an arbitrary SID.
1488 * This call can be expensive. Use with moderation.
1489 * If you have a "samu" struct around use pdb_get_group_sid()
1490 * instead as it does properly cache results.
1492 * @param mem_ctx[in] The memory context iused to allocate the result.
1493 * @param username[in] The user's name
1494 * @param _pwd[in|out] If available, pass in user's passwd struct.
1495 * It will contain a tallocated passwd if NULL was
1496 * passed in.
1497 * @param _group_sid[out] The user's Primary Group SID
1499 * @return NTSTATUS error code.
1501 NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx,
1502 const char *username,
1503 struct passwd **_pwd,
1504 struct dom_sid **_group_sid)
1506 TALLOC_CTX *tmp_ctx;
1507 bool need_lookup_sid = false;
1508 struct dom_sid *group_sid;
1509 struct passwd *pwd = *_pwd;
1511 tmp_ctx = talloc_new(mem_ctx);
1512 if (!tmp_ctx) {
1513 return NT_STATUS_NO_MEMORY;
1516 if (!pwd) {
1517 pwd = Get_Pwnam_alloc(mem_ctx, username);
1518 if (!pwd) {
1519 DEBUG(0, ("Failed to find a Unix account for %s",
1520 username));
1521 TALLOC_FREE(tmp_ctx);
1522 return NT_STATUS_NO_SUCH_USER;
1526 group_sid = talloc_zero(mem_ctx, struct dom_sid);
1527 if (!group_sid) {
1528 TALLOC_FREE(tmp_ctx);
1529 return NT_STATUS_NO_MEMORY;
1532 gid_to_sid(group_sid, pwd->pw_gid);
1533 if (!is_null_sid(group_sid)) {
1534 struct dom_sid domain_sid;
1535 uint32_t rid;
1537 /* We need a sid within our domain */
1538 sid_copy(&domain_sid, group_sid);
1539 sid_split_rid(&domain_sid, &rid);
1540 if (dom_sid_equal(&domain_sid, get_global_sam_sid())) {
1542 * As shortcut for the expensive lookup_sid call
1543 * compare the domain sid part
1545 switch (rid) {
1546 case DOMAIN_RID_ADMINS:
1547 case DOMAIN_RID_USERS:
1548 goto done;
1549 default:
1550 need_lookup_sid = true;
1551 break;
1553 } else {
1554 /* Try group mapping */
1555 ZERO_STRUCTP(group_sid);
1556 if (pdb_gid_to_sid(pwd->pw_gid, group_sid)) {
1557 need_lookup_sid = true;
1562 /* We must verify that this is a valid SID that resolves to a
1563 * group of the correct type */
1564 if (need_lookup_sid) {
1565 enum lsa_SidType type = SID_NAME_UNKNOWN;
1566 bool lookup_ret;
1568 DEBUG(10, ("do lookup_sid(%s) for group of user %s\n",
1569 sid_string_dbg(group_sid), username));
1571 /* Now check that it's actually a domain group and
1572 * not something else */
1573 lookup_ret = lookup_sid(tmp_ctx, group_sid,
1574 NULL, NULL, &type);
1576 if (lookup_ret && (type == SID_NAME_DOM_GRP)) {
1577 goto done;
1580 DEBUG(3, ("Primary group %s for user %s is"
1581 " a %s and not a domain group\n",
1582 sid_string_dbg(group_sid), username,
1583 sid_type_lookup(type)));
1586 /* Everything else, failed.
1587 * Just set it to the 'Domain Users' RID of 513 which will
1588 always resolve to a name */
1589 DEBUG(3, ("Forcing Primary Group to 'Domain Users' for %s\n",
1590 username));
1592 sid_compose(group_sid, get_global_sam_sid(), DOMAIN_RID_USERS);
1594 done:
1595 *_pwd = talloc_move(mem_ctx, &pwd);
1596 *_group_sid = talloc_move(mem_ctx, &group_sid);
1597 TALLOC_FREE(tmp_ctx);
1598 return NT_STATUS_OK;