s4-ldb: cope better with corruption of tdb records
[Samba/aatanasov.git] / source3 / passdb / lookup_sid.c
blob4f8d6a4759dc193a7ba4d14987160c93228f8119
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"
24 /*****************************************************************
25 Dissect a user-provided name into domain, name, sid and type.
27 If an explicit domain name was given in the form domain\user, it
28 has to try that. If no explicit domain name was given, we have
29 to do guesswork.
30 *****************************************************************/
32 bool lookup_name(TALLOC_CTX *mem_ctx,
33 const char *full_name, int flags,
34 const char **ret_domain, const char **ret_name,
35 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
37 char *p;
38 const char *tmp;
39 const char *domain = NULL;
40 const char *name = NULL;
41 uint32 rid;
42 DOM_SID sid;
43 enum lsa_SidType type;
44 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
46 if (tmp_ctx == NULL) {
47 DEBUG(0, ("talloc_new failed\n"));
48 return false;
51 p = strchr_m(full_name, '\\');
53 if (p != NULL) {
54 domain = talloc_strndup(tmp_ctx, full_name,
55 PTR_DIFF(p, full_name));
56 name = talloc_strdup(tmp_ctx, p+1);
57 } else {
58 domain = talloc_strdup(tmp_ctx, "");
59 name = talloc_strdup(tmp_ctx, full_name);
62 if ((domain == NULL) || (name == NULL)) {
63 DEBUG(0, ("talloc failed\n"));
64 TALLOC_FREE(tmp_ctx);
65 return false;
68 DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
69 full_name, domain, name));
70 DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
72 if ((flags & LOOKUP_NAME_DOMAIN) &&
73 strequal(domain, get_global_sam_name()))
76 /* It's our own domain, lookup the name in passdb */
77 if (lookup_global_sam_name(name, flags, &rid, &type)) {
78 sid_copy(&sid, get_global_sam_sid());
79 sid_append_rid(&sid, rid);
80 goto ok;
82 TALLOC_FREE(tmp_ctx);
83 return false;
86 if ((flags & LOOKUP_NAME_BUILTIN) &&
87 strequal(domain, builtin_domain_name()))
89 /* Explicit request for a name in BUILTIN */
90 if (lookup_builtin_name(name, &rid)) {
91 sid_copy(&sid, &global_sid_Builtin);
92 sid_append_rid(&sid, rid);
93 type = SID_NAME_ALIAS;
94 goto ok;
96 TALLOC_FREE(tmp_ctx);
97 return false;
100 /* Try the explicit winbind lookup first, don't let it guess the
101 * domain yet at this point yet. This comes later. */
103 if ((domain[0] != '\0') &&
104 (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
105 (winbind_lookup_name(domain, name, &sid, &type))) {
106 goto ok;
109 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
110 && strequal(domain, unix_users_domain_name())) {
111 if (lookup_unix_user_name(name, &sid)) {
112 type = SID_NAME_USER;
113 goto ok;
115 TALLOC_FREE(tmp_ctx);
116 return false;
119 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
120 && strequal(domain, unix_groups_domain_name())) {
121 if (lookup_unix_group_name(name, &sid)) {
122 type = SID_NAME_DOM_GRP;
123 goto ok;
125 TALLOC_FREE(tmp_ctx);
126 return false;
129 if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
130 TALLOC_FREE(tmp_ctx);
131 return false;
134 /* Now the guesswork begins, we haven't been given an explicit
135 * domain. Try the sequence as documented on
136 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
137 * November 27, 2005 */
139 /* 1. well-known names */
141 if ((flags & LOOKUP_NAME_WKN) &&
142 lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
144 type = SID_NAME_WKN_GRP;
145 goto ok;
148 /* 2. Builtin domain as such */
150 if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
151 strequal(name, builtin_domain_name()))
153 /* Swap domain and name */
154 tmp = name; name = domain; domain = tmp;
155 sid_copy(&sid, &global_sid_Builtin);
156 type = SID_NAME_DOMAIN;
157 goto ok;
160 /* 3. Account domain */
162 if ((flags & LOOKUP_NAME_DOMAIN) &&
163 strequal(name, get_global_sam_name()))
165 if (!secrets_fetch_domain_sid(name, &sid)) {
166 DEBUG(3, ("Could not fetch my SID\n"));
167 TALLOC_FREE(tmp_ctx);
168 return false;
170 /* Swap domain and name */
171 tmp = name; name = domain; domain = tmp;
172 type = SID_NAME_DOMAIN;
173 goto ok;
176 /* 4. Primary domain */
178 if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
179 strequal(name, lp_workgroup()))
181 if (!secrets_fetch_domain_sid(name, &sid)) {
182 DEBUG(3, ("Could not fetch the domain SID\n"));
183 TALLOC_FREE(tmp_ctx);
184 return false;
186 /* Swap domain and name */
187 tmp = name; name = domain; domain = tmp;
188 type = SID_NAME_DOMAIN;
189 goto ok;
192 /* 5. Trusted domains as such, to me it looks as if members don't do
193 this, tested an XP workstation in a NT domain -- vl */
195 if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
196 (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
198 /* Swap domain and name */
199 tmp = name; name = domain; domain = tmp;
200 type = SID_NAME_DOMAIN;
201 goto ok;
204 /* 6. Builtin aliases */
206 if ((flags & LOOKUP_NAME_BUILTIN) &&
207 lookup_builtin_name(name, &rid))
209 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
210 sid_copy(&sid, &global_sid_Builtin);
211 sid_append_rid(&sid, rid);
212 type = SID_NAME_ALIAS;
213 goto ok;
216 /* 7. Local systems' SAM (DCs don't have a local SAM) */
217 /* 8. Primary SAM (On members, this is the domain) */
219 /* Both cases are done by looking at our passdb */
221 if ((flags & LOOKUP_NAME_DOMAIN) &&
222 lookup_global_sam_name(name, flags, &rid, &type))
224 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
225 sid_copy(&sid, get_global_sam_sid());
226 sid_append_rid(&sid, rid);
227 goto ok;
230 /* Now our local possibilities are exhausted. */
232 if (!(flags & LOOKUP_NAME_REMOTE)) {
233 TALLOC_FREE(tmp_ctx);
234 return false;
237 /* If we are not a DC, we have to ask in our primary domain. Let
238 * winbind do that. */
240 if (!IS_DC &&
241 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
242 domain = talloc_strdup(tmp_ctx, lp_workgroup());
243 goto ok;
246 /* 9. Trusted domains */
248 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
249 * that (yet), but give it a chance. */
251 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
252 DOM_SID dom_sid;
253 uint32 tmp_rid;
254 enum lsa_SidType domain_type;
256 if (type == SID_NAME_DOMAIN) {
257 /* Swap name and type */
258 tmp = name; name = domain; domain = tmp;
259 goto ok;
262 /* Here we have to cope with a little deficiency in the
263 * winbind API: We have to ask it again for the name of the
264 * domain it figured out itself. Maybe fix that later... */
266 sid_copy(&dom_sid, &sid);
267 sid_split_rid(&dom_sid, &tmp_rid);
269 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
270 &domain_type) ||
271 (domain_type != SID_NAME_DOMAIN)) {
272 DEBUG(2, ("winbind could not find the domain's name "
273 "it just looked up for us\n"));
274 TALLOC_FREE(tmp_ctx);
275 return false;
277 goto ok;
280 /* 10. Don't translate */
282 /* 11. Ok, windows would end here. Samba has two more options:
283 Unmapped users and unmapped groups */
285 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
286 && lookup_unix_user_name(name, &sid)) {
287 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
288 type = SID_NAME_USER;
289 goto ok;
292 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
293 && lookup_unix_group_name(name, &sid)) {
294 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
295 type = SID_NAME_DOM_GRP;
296 goto ok;
300 * Ok, all possibilities tried. Fail.
303 TALLOC_FREE(tmp_ctx);
304 return false;
307 if ((domain == NULL) || (name == NULL)) {
308 DEBUG(0, ("talloc failed\n"));
309 TALLOC_FREE(tmp_ctx);
310 return false;
314 * Hand over the results to the talloc context we've been given.
317 if ((ret_name != NULL) &&
318 !(*ret_name = talloc_strdup(mem_ctx, name))) {
319 DEBUG(0, ("talloc failed\n"));
320 TALLOC_FREE(tmp_ctx);
321 return false;
324 if (ret_domain != NULL) {
325 char *tmp_dom;
326 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
327 DEBUG(0, ("talloc failed\n"));
328 TALLOC_FREE(tmp_ctx);
329 return false;
331 strupper_m(tmp_dom);
332 *ret_domain = tmp_dom;
335 if (ret_sid != NULL) {
336 sid_copy(ret_sid, &sid);
339 if (ret_type != NULL) {
340 *ret_type = type;
343 TALLOC_FREE(tmp_ctx);
344 return true;
347 /************************************************************************
348 Names from smb.conf can be unqualified. eg. valid users = foo
349 These names should never map to a remote name. Try global_sam_name()\foo,
350 and then "Unix Users"\foo (or "Unix Groups"\foo).
351 ************************************************************************/
353 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
354 const char *full_name, int flags,
355 const char **ret_domain, const char **ret_name,
356 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
358 char *qualified_name;
359 const char *p;
361 /* NB. No winbindd_separator here as lookup_name needs \\' */
362 if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
364 /* The name is already qualified with a domain. */
366 if (*lp_winbind_separator() != '\\') {
367 char *tmp;
369 /* lookup_name() needs '\\' as a separator */
371 tmp = talloc_strdup(mem_ctx, full_name);
372 if (!tmp) {
373 return false;
375 tmp[p - full_name] = '\\';
376 full_name = tmp;
379 return lookup_name(mem_ctx, full_name, flags,
380 ret_domain, ret_name,
381 ret_sid, ret_type);
384 /* Try with our own SAM name. */
385 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
386 get_global_sam_name(),
387 full_name );
388 if (!qualified_name) {
389 return false;
392 if (lookup_name(mem_ctx, qualified_name, flags,
393 ret_domain, ret_name,
394 ret_sid, ret_type)) {
395 return true;
398 /* Finally try with "Unix Users" or "Unix Group" */
399 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
400 flags & LOOKUP_NAME_GROUP ?
401 unix_groups_domain_name() :
402 unix_users_domain_name(),
403 full_name );
404 if (!qualified_name) {
405 return false;
408 return lookup_name(mem_ctx, qualified_name, flags,
409 ret_domain, ret_name,
410 ret_sid, ret_type);
413 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
414 const DOM_SID *domain_sid,
415 int num_rids, uint32 *rids,
416 const char **domain_name,
417 const char **names, enum lsa_SidType *types)
419 int i;
420 const char **my_names;
421 enum lsa_SidType *my_types;
422 TALLOC_CTX *tmp_ctx;
424 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
425 return false;
428 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
429 domain_name, &my_names, &my_types)) {
430 *domain_name = "";
431 for (i=0; i<num_rids; i++) {
432 names[i] = "";
433 types[i] = SID_NAME_UNKNOWN;
435 TALLOC_FREE(tmp_ctx);
436 return true;
439 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
440 TALLOC_FREE(tmp_ctx);
441 return false;
445 * winbind_lookup_rids allocates its own array. We've been given the
446 * array, so copy it over
449 for (i=0; i<num_rids; i++) {
450 if (my_names[i] == NULL) {
451 TALLOC_FREE(tmp_ctx);
452 return false;
454 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
455 TALLOC_FREE(tmp_ctx);
456 return false;
458 types[i] = my_types[i];
460 TALLOC_FREE(tmp_ctx);
461 return true;
464 static bool lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
465 int num_rids, uint32_t *rids,
466 const char **domain_name,
467 const char ***names, enum lsa_SidType **types)
469 int i;
471 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
472 sid_string_dbg(domain_sid)));
474 if (num_rids) {
475 *names = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
476 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
478 if ((*names == NULL) || (*types == NULL)) {
479 return false;
482 for (i = 0; i < num_rids; i++)
483 (*types)[i] = SID_NAME_UNKNOWN;
484 } else {
485 *names = NULL;
486 *types = NULL;
489 if (sid_check_is_domain(domain_sid)) {
490 NTSTATUS result;
492 if (*domain_name == NULL) {
493 *domain_name = talloc_strdup(
494 mem_ctx, get_global_sam_name());
497 if (*domain_name == NULL) {
498 return false;
501 become_root();
502 result = pdb_lookup_rids(domain_sid, num_rids, rids,
503 *names, *types);
504 unbecome_root();
506 return (NT_STATUS_IS_OK(result) ||
507 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
508 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
511 if (sid_check_is_builtin(domain_sid)) {
513 if (*domain_name == NULL) {
514 *domain_name = talloc_strdup(
515 mem_ctx, builtin_domain_name());
518 if (*domain_name == NULL) {
519 return false;
522 for (i=0; i<num_rids; i++) {
523 if (lookup_builtin_rid(*names, rids[i],
524 &(*names)[i])) {
525 if ((*names)[i] == NULL) {
526 return false;
528 (*types)[i] = SID_NAME_ALIAS;
529 } else {
530 (*types)[i] = SID_NAME_UNKNOWN;
533 return true;
536 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
537 for (i=0; i<num_rids; i++) {
538 DOM_SID sid;
539 sid_copy(&sid, domain_sid);
540 sid_append_rid(&sid, rids[i]);
541 if (lookup_wellknown_sid(mem_ctx, &sid,
542 domain_name, &(*names)[i])) {
543 if ((*names)[i] == NULL) {
544 return false;
546 (*types)[i] = SID_NAME_WKN_GRP;
547 } else {
548 (*types)[i] = SID_NAME_UNKNOWN;
551 return true;
554 if (sid_check_is_unix_users(domain_sid)) {
555 if (*domain_name == NULL) {
556 *domain_name = talloc_strdup(
557 mem_ctx, unix_users_domain_name());
558 if (*domain_name == NULL) {
559 return false;
562 for (i=0; i<num_rids; i++) {
563 (*names)[i] = talloc_strdup(
564 (*names), uidtoname(rids[i]));
565 if ((*names)[i] == NULL) {
566 return false;
568 (*types)[i] = SID_NAME_USER;
570 return true;
573 if (sid_check_is_unix_groups(domain_sid)) {
574 if (*domain_name == NULL) {
575 *domain_name = talloc_strdup(
576 mem_ctx, unix_groups_domain_name());
577 if (*domain_name == NULL) {
578 return false;
581 for (i=0; i<num_rids; i++) {
582 (*names)[i] = talloc_strdup(
583 (*names), gidtoname(rids[i]));
584 if ((*names)[i] == NULL) {
585 return false;
587 (*types)[i] = SID_NAME_DOM_GRP;
589 return true;
592 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
593 domain_name, *names, *types);
597 * Is the SID a domain as such? If yes, lookup its name.
600 static bool lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
601 const char **name)
603 const char *tmp;
604 enum lsa_SidType type;
606 if (sid_check_is_domain(sid)) {
607 *name = talloc_strdup(mem_ctx, get_global_sam_name());
608 return true;
611 if (sid_check_is_builtin(sid)) {
612 *name = talloc_strdup(mem_ctx, builtin_domain_name());
613 return true;
616 if (sid_check_is_wellknown_domain(sid, &tmp)) {
617 *name = talloc_strdup(mem_ctx, tmp);
618 return true;
621 if (sid_check_is_unix_users(sid)) {
622 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
623 return true;
626 if (sid_check_is_unix_groups(sid)) {
627 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
628 return true;
631 if (sid->num_auths != 4) {
632 /* This can't be a domain */
633 return false;
636 if (IS_DC) {
637 uint32 i, num_domains;
638 struct trustdom_info **domains;
640 /* This is relatively expensive, but it happens only on DCs
641 * and for SIDs that have 4 sub-authorities and thus look like
642 * domains */
644 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
645 &num_domains,
646 &domains))) {
647 return false;
650 for (i=0; i<num_domains; i++) {
651 if (sid_equal(sid, &domains[i]->sid)) {
652 *name = talloc_strdup(mem_ctx,
653 domains[i]->name);
654 return true;
657 return false;
660 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
661 (type == SID_NAME_DOMAIN)) {
662 *name = tmp;
663 return true;
666 return false;
670 * This tries to implement the rather weird rules for the lsa_lookup level
671 * parameter.
673 * This is as close as we can get to what W2k3 does. With this we survive the
674 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
675 * different, but I assume that's just being too liberal. For example, W2k3
676 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
677 * whereas NT4 does the same as level 1 (I think). I did not fully test that
678 * with NT4, this is what w2k3 does.
680 * Level 1: Ask everywhere
681 * Level 2: Ask domain and trusted domains, no builtin and wkn
682 * Level 3: Only ask domain
683 * Level 4: W2k3ad: Only ask AD trusts
684 * Level 5: Only ask transitive forest trusts
685 * Level 6: Like 4
688 static bool check_dom_sid_to_level(const DOM_SID *sid, int level)
690 int ret = false;
692 switch(level) {
693 case 1:
694 ret = true;
695 break;
696 case 2:
697 ret = (!sid_check_is_builtin(sid) &&
698 !sid_check_is_wellknown_domain(sid, NULL));
699 break;
700 case 3:
701 case 4:
702 case 6:
703 ret = sid_check_is_domain(sid);
704 break;
705 case 5:
706 ret = false;
707 break;
710 DEBUG(10, ("%s SID %s in level %d\n",
711 ret ? "Accepting" : "Rejecting",
712 sid_string_dbg(sid), level));
713 return ret;
717 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
718 * references to domains, it is explicitly made for this.
720 * This attempts to be as efficient as possible: It collects all SIDs
721 * belonging to a domain and hands them in bulk to the appropriate lookup
722 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
723 * *hugely* from this. Winbind is going to be extended with a lookup_rids
724 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
725 * appropriate DC.
728 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
729 const DOM_SID **sids, int level,
730 struct lsa_dom_info **ret_domains,
731 struct lsa_name_info **ret_names)
733 TALLOC_CTX *tmp_ctx;
734 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
735 struct lsa_name_info *name_infos;
736 struct lsa_dom_info *dom_infos = NULL;
738 int i, j;
740 if (!(tmp_ctx = talloc_new(mem_ctx))) {
741 DEBUG(0, ("talloc_new failed\n"));
742 return NT_STATUS_NO_MEMORY;
745 if (num_sids) {
746 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
747 if (name_infos == NULL) {
748 result = NT_STATUS_NO_MEMORY;
749 goto fail;
751 } else {
752 name_infos = NULL;
755 dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
756 LSA_REF_DOMAIN_LIST_MULTIPLIER);
757 if (dom_infos == NULL) {
758 result = NT_STATUS_NO_MEMORY;
759 goto fail;
762 /* First build up the data structures:
764 * dom_infos is a list of domains referenced in the list of
765 * SIDs. Later we will walk the list of domains and look up the RIDs
766 * in bulk.
768 * name_infos is a shadow-copy of the SIDs array to collect the real
769 * data.
771 * dom_info->idxs is an index into the name_infos array. The
772 * difficulty we have here is that we need to keep the SIDs the client
773 * asked for in the same order for the reply
776 for (i=0; i<num_sids; i++) {
777 DOM_SID sid;
778 uint32 rid;
779 const char *domain_name = NULL;
781 sid_copy(&sid, sids[i]);
782 name_infos[i].type = SID_NAME_USE_NONE;
784 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
785 /* We can't push that through the normal lookup
786 * process, as this would reference illegal
787 * domains.
789 * For example S-1-5-32 would end up referencing
790 * domain S-1-5- with RID 32 which is clearly wrong.
792 if (domain_name == NULL) {
793 result = NT_STATUS_NO_MEMORY;
794 goto fail;
797 name_infos[i].rid = 0;
798 name_infos[i].type = SID_NAME_DOMAIN;
799 name_infos[i].name = NULL;
801 if (sid_check_is_builtin(&sid)) {
802 /* Yes, W2k3 returns "BUILTIN" both as domain
803 * and name here */
804 name_infos[i].name = talloc_strdup(
805 name_infos, builtin_domain_name());
806 if (name_infos[i].name == NULL) {
807 result = NT_STATUS_NO_MEMORY;
808 goto fail;
811 } else {
812 /* This is a normal SID with rid component */
813 if (!sid_split_rid(&sid, &rid)) {
814 result = NT_STATUS_INVALID_SID;
815 goto fail;
819 if (!check_dom_sid_to_level(&sid, level)) {
820 name_infos[i].rid = 0;
821 name_infos[i].type = SID_NAME_UNKNOWN;
822 name_infos[i].name = NULL;
823 continue;
826 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
827 if (!dom_infos[j].valid) {
828 break;
830 if (sid_equal(&sid, &dom_infos[j].sid)) {
831 break;
835 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
836 /* TODO: What's the right error message here? */
837 result = NT_STATUS_NONE_MAPPED;
838 goto fail;
841 if (!dom_infos[j].valid) {
842 /* We found a domain not yet referenced, create a new
843 * ref. */
844 dom_infos[j].valid = true;
845 sid_copy(&dom_infos[j].sid, &sid);
847 if (domain_name != NULL) {
848 /* This name was being found above in the case
849 * when we found a domain SID */
850 dom_infos[j].name =
851 talloc_strdup(dom_infos, domain_name);
852 if (dom_infos[j].name == NULL) {
853 result = NT_STATUS_NO_MEMORY;
854 goto fail;
856 } else {
857 /* lookup_rids will take care of this */
858 dom_infos[j].name = NULL;
862 name_infos[i].dom_idx = j;
864 if (name_infos[i].type == SID_NAME_USE_NONE) {
865 name_infos[i].rid = rid;
867 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
868 &dom_infos[j].num_idxs);
870 if (dom_infos[j].idxs == NULL) {
871 result = NT_STATUS_NO_MEMORY;
872 goto fail;
877 /* Iterate over the domains found */
879 for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
880 uint32_t *rids;
881 const char *domain_name = NULL;
882 const char **names;
883 enum lsa_SidType *types;
884 struct lsa_dom_info *dom = &dom_infos[i];
886 if (!dom->valid) {
887 /* No domains left, we're done */
888 break;
891 if (dom->num_idxs) {
892 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
893 result = NT_STATUS_NO_MEMORY;
894 goto fail;
896 } else {
897 rids = NULL;
900 for (j=0; j<dom->num_idxs; j++) {
901 rids[j] = name_infos[dom->idxs[j]].rid;
904 if (!lookup_rids(tmp_ctx, &dom->sid,
905 dom->num_idxs, rids, &domain_name,
906 &names, &types)) {
907 result = NT_STATUS_NO_MEMORY;
908 goto fail;
911 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
912 result = NT_STATUS_NO_MEMORY;
913 goto fail;
916 for (j=0; j<dom->num_idxs; j++) {
917 int idx = dom->idxs[j];
918 name_infos[idx].type = types[j];
919 if (types[j] != SID_NAME_UNKNOWN) {
920 name_infos[idx].name =
921 talloc_strdup(name_infos, names[j]);
922 if (name_infos[idx].name == NULL) {
923 result = NT_STATUS_NO_MEMORY;
924 goto fail;
926 } else {
927 name_infos[idx].name = NULL;
932 *ret_domains = dom_infos;
933 *ret_names = name_infos;
934 TALLOC_FREE(tmp_ctx);
935 return NT_STATUS_OK;
937 fail:
938 TALLOC_FREE(dom_infos);
939 TALLOC_FREE(name_infos);
940 TALLOC_FREE(tmp_ctx);
941 return result;
944 /*****************************************************************
945 *THE CANONICAL* convert SID to name function.
946 *****************************************************************/
948 bool lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
949 const char **ret_domain, const char **ret_name,
950 enum lsa_SidType *ret_type)
952 struct lsa_dom_info *domain;
953 struct lsa_name_info *name;
954 TALLOC_CTX *tmp_ctx;
955 bool ret = false;
957 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
959 if (!(tmp_ctx = talloc_new(mem_ctx))) {
960 DEBUG(0, ("talloc_new failed\n"));
961 return false;
964 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
965 &domain, &name))) {
966 goto done;
969 if (name->type == SID_NAME_UNKNOWN) {
970 goto done;
973 if ((ret_domain != NULL) &&
974 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
975 goto done;
978 if ((ret_name != NULL) &&
979 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
980 goto done;
983 if (ret_type != NULL) {
984 *ret_type = name->type;
987 ret = true;
989 done:
990 if (ret) {
991 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
992 domain->name, name->name, name->type));
993 } else {
994 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
996 TALLOC_FREE(tmp_ctx);
997 return ret;
1000 /*****************************************************************
1001 Id mapping cache. This is to avoid Winbind mappings already
1002 seen by smbd to be queried too frequently, keeping winbindd
1003 busy, and blocking smbd while winbindd is busy with other
1004 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1005 modified to use linked lists by jra.
1006 *****************************************************************/
1008 /*****************************************************************
1009 Find a SID given a uid.
1010 *****************************************************************/
1012 static bool fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
1014 DATA_BLOB cache_value;
1016 if (!memcache_lookup(NULL, UID_SID_CACHE,
1017 data_blob_const(&uid, sizeof(uid)),
1018 &cache_value)) {
1019 return false;
1022 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1023 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1024 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, NULL, 0));
1026 return true;
1029 /*****************************************************************
1030 Find a uid given a SID.
1031 *****************************************************************/
1033 static bool fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
1035 DATA_BLOB cache_value;
1037 if (!memcache_lookup(NULL, SID_UID_CACHE,
1038 data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1039 &cache_value)) {
1040 return false;
1043 SMB_ASSERT(cache_value.length == sizeof(*puid));
1044 memcpy(puid, cache_value.data, sizeof(*puid));
1046 return true;
1049 /*****************************************************************
1050 Store uid to SID mapping in cache.
1051 *****************************************************************/
1053 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
1055 memcache_add(NULL, SID_UID_CACHE,
1056 data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1057 data_blob_const(&uid, sizeof(uid)));
1058 memcache_add(NULL, UID_SID_CACHE,
1059 data_blob_const(&uid, sizeof(uid)),
1060 data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)));
1063 /*****************************************************************
1064 Find a SID given a gid.
1065 *****************************************************************/
1067 static bool fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1069 DATA_BLOB cache_value;
1071 if (!memcache_lookup(NULL, GID_SID_CACHE,
1072 data_blob_const(&gid, sizeof(gid)),
1073 &cache_value)) {
1074 return false;
1077 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1078 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1079 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, NULL, 0));
1081 return true;
1084 /*****************************************************************
1085 Find a gid given a SID.
1086 *****************************************************************/
1088 static bool fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1090 DATA_BLOB cache_value;
1092 if (!memcache_lookup(NULL, SID_GID_CACHE,
1093 data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1094 &cache_value)) {
1095 return false;
1098 SMB_ASSERT(cache_value.length == sizeof(*pgid));
1099 memcpy(pgid, cache_value.data, sizeof(*pgid));
1101 return true;
1104 /*****************************************************************
1105 Store gid to SID mapping in cache.
1106 *****************************************************************/
1108 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1110 memcache_add(NULL, SID_GID_CACHE,
1111 data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1112 data_blob_const(&gid, sizeof(gid)));
1113 memcache_add(NULL, GID_SID_CACHE,
1114 data_blob_const(&gid, sizeof(gid)),
1115 data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)));
1118 /*****************************************************************
1119 *THE LEGACY* convert uid_t to SID function.
1120 *****************************************************************/
1122 static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
1124 uint32 rid;
1125 bool ret;
1127 ZERO_STRUCTP(psid);
1129 become_root();
1130 ret = pdb_uid_to_rid(uid, &rid);
1131 unbecome_root();
1133 if (ret) {
1134 /* This is a mapped user */
1135 sid_copy(psid, get_global_sam_sid());
1136 sid_append_rid(psid, rid);
1137 goto done;
1140 /* This is an unmapped user */
1142 uid_to_unix_users_sid(uid, psid);
1144 done:
1145 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1146 sid_string_dbg(psid)));
1148 store_uid_sid_cache(psid, uid);
1149 return;
1152 /*****************************************************************
1153 *THE LEGACY* convert gid_t to SID function.
1154 *****************************************************************/
1156 static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
1158 bool ret;
1160 ZERO_STRUCTP(psid);
1162 become_root();
1163 ret = pdb_gid_to_sid(gid, psid);
1164 unbecome_root();
1166 if (ret) {
1167 /* This is a mapped group */
1168 goto done;
1171 /* This is an unmapped group */
1173 gid_to_unix_groups_sid(gid, psid);
1175 done:
1176 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1177 sid_string_dbg(psid)));
1179 store_gid_sid_cache(psid, gid);
1180 return;
1183 /*****************************************************************
1184 *THE LEGACY* convert SID to uid function.
1185 *****************************************************************/
1187 static bool legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
1189 enum lsa_SidType type;
1190 uint32 rid;
1192 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1193 union unid_t id;
1194 bool ret;
1196 become_root();
1197 ret = pdb_sid_to_id(psid, &id, &type);
1198 unbecome_root();
1200 if (ret) {
1201 if (type != SID_NAME_USER) {
1202 DEBUG(5, ("sid %s is a %s, expected a user\n",
1203 sid_string_dbg(psid),
1204 sid_type_lookup(type)));
1205 return false;
1207 *puid = id.uid;
1208 goto done;
1211 /* This was ours, but it was not mapped. Fail */
1214 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1215 sid_string_dbg(psid)));
1216 return false;
1218 done:
1219 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_dbg(psid),
1220 (unsigned int)*puid ));
1222 store_uid_sid_cache(psid, *puid);
1223 return true;
1226 /*****************************************************************
1227 *THE LEGACY* convert SID to gid function.
1228 Group mapping is used for gids that maps to Wellknown SIDs
1229 *****************************************************************/
1231 static bool legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1233 uint32 rid;
1234 GROUP_MAP map;
1235 union unid_t id;
1236 enum lsa_SidType type;
1238 if ((sid_check_is_in_builtin(psid) ||
1239 sid_check_is_in_wellknown_domain(psid))) {
1240 bool ret;
1242 become_root();
1243 ret = pdb_getgrsid(&map, *psid);
1244 unbecome_root();
1246 if (ret) {
1247 *pgid = map.gid;
1248 goto done;
1250 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1251 sid_string_dbg(psid)));
1252 return false;
1255 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1256 bool ret;
1258 become_root();
1259 ret = pdb_sid_to_id(psid, &id, &type);
1260 unbecome_root();
1262 if (ret) {
1263 if ((type != SID_NAME_DOM_GRP) &&
1264 (type != SID_NAME_ALIAS)) {
1265 DEBUG(5, ("LEGACY: sid %s is a %s, expected "
1266 "a group\n", sid_string_dbg(psid),
1267 sid_type_lookup(type)));
1268 return false;
1270 *pgid = id.gid;
1271 goto done;
1274 /* This was ours, but it was not mapped. Fail */
1277 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1278 sid_string_dbg(psid)));
1279 return false;
1281 done:
1282 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_dbg(psid),
1283 (unsigned int)*pgid ));
1285 store_gid_sid_cache(psid, *pgid);
1287 return true;
1290 /*****************************************************************
1291 *THE CANONICAL* convert uid_t to SID function.
1292 *****************************************************************/
1294 void uid_to_sid(DOM_SID *psid, uid_t uid)
1296 bool expired = true;
1297 bool ret;
1298 ZERO_STRUCTP(psid);
1300 if (fetch_sid_from_uid_cache(psid, uid))
1301 return;
1303 /* Check the winbindd cache directly. */
1304 ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1306 if (ret && !expired && is_null_sid(psid)) {
1308 * Negative cache entry, we already asked.
1309 * do legacy.
1311 legacy_uid_to_sid(psid, uid);
1312 return;
1315 if (!ret || expired) {
1316 /* Not in cache. Ask winbindd. */
1317 if (!winbind_uid_to_sid(psid, uid)) {
1319 * We shouldn't return the NULL SID
1320 * here if winbind was running and
1321 * couldn't map, as winbind will have
1322 * added a negative entry that will
1323 * cause us to go though the
1324 * legacy_uid_to_sid()
1325 * function anyway in the case above
1326 * the next time we ask.
1328 DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1329 "for uid %u\n", (unsigned int)uid));
1331 legacy_uid_to_sid(psid, uid);
1332 return;
1336 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1337 sid_string_dbg(psid)));
1339 store_uid_sid_cache(psid, uid);
1340 return;
1343 /*****************************************************************
1344 *THE CANONICAL* convert gid_t to SID function.
1345 *****************************************************************/
1347 void gid_to_sid(DOM_SID *psid, gid_t gid)
1349 bool expired = true;
1350 bool ret;
1351 ZERO_STRUCTP(psid);
1353 if (fetch_sid_from_gid_cache(psid, gid))
1354 return;
1356 /* Check the winbindd cache directly. */
1357 ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1359 if (ret && !expired && is_null_sid(psid)) {
1361 * Negative cache entry, we already asked.
1362 * do legacy.
1364 legacy_gid_to_sid(psid, gid);
1365 return;
1368 if (!ret || expired) {
1369 /* Not in cache. Ask winbindd. */
1370 if (!winbind_gid_to_sid(psid, gid)) {
1372 * We shouldn't return the NULL SID
1373 * here if winbind was running and
1374 * couldn't map, as winbind will have
1375 * added a negative entry that will
1376 * cause us to go though the
1377 * legacy_gid_to_sid()
1378 * function anyway in the case above
1379 * the next time we ask.
1381 DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1382 "for gid %u\n", (unsigned int)gid));
1384 legacy_gid_to_sid(psid, gid);
1385 return;
1389 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1390 sid_string_dbg(psid)));
1392 store_gid_sid_cache(psid, gid);
1393 return;
1396 /*****************************************************************
1397 *THE CANONICAL* convert SID to uid function.
1398 *****************************************************************/
1400 bool sid_to_uid(const DOM_SID *psid, uid_t *puid)
1402 bool expired = true;
1403 bool ret;
1404 uint32 rid;
1405 gid_t gid;
1407 if (fetch_uid_from_cache(puid, psid))
1408 return true;
1410 if (fetch_gid_from_cache(&gid, psid)) {
1411 return false;
1414 /* Optimize for the Unix Users Domain
1415 * as the conversion is straightforward */
1416 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1417 uid_t uid = rid;
1418 *puid = uid;
1420 /* return here, don't cache */
1421 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1422 (unsigned int)*puid ));
1423 return true;
1426 /* Check the winbindd cache directly. */
1427 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1429 if (ret && !expired && (*puid == (uid_t)-1)) {
1431 * Negative cache entry, we already asked.
1432 * do legacy.
1434 return legacy_sid_to_uid(psid, puid);
1437 if (!ret || expired) {
1438 /* Not in cache. Ask winbindd. */
1439 if (!winbind_sid_to_uid(puid, psid)) {
1440 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1441 sid_string_dbg(psid)));
1442 /* winbind failed. do legacy */
1443 return legacy_sid_to_uid(psid, puid);
1447 /* TODO: Here would be the place to allocate both a gid and a uid for
1448 * the SID in question */
1450 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1451 (unsigned int)*puid ));
1453 store_uid_sid_cache(psid, *puid);
1454 return true;
1457 /*****************************************************************
1458 *THE CANONICAL* convert SID to gid function.
1459 Group mapping is used for gids that maps to Wellknown SIDs
1460 *****************************************************************/
1462 bool sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1464 bool expired = true;
1465 bool ret;
1466 uint32 rid;
1467 uid_t uid;
1469 if (fetch_gid_from_cache(pgid, psid))
1470 return true;
1472 if (fetch_uid_from_cache(&uid, psid))
1473 return false;
1475 /* Optimize for the Unix Groups Domain
1476 * as the conversion is straightforward */
1477 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1478 gid_t gid = rid;
1479 *pgid = gid;
1481 /* return here, don't cache */
1482 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1483 (unsigned int)*pgid ));
1484 return true;
1487 /* Check the winbindd cache directly. */
1488 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1490 if (ret && !expired && (*pgid == (gid_t)-1)) {
1492 * Negative cache entry, we already asked.
1493 * do legacy.
1495 return legacy_sid_to_gid(psid, pgid);
1498 if (!ret || expired) {
1499 /* Not in cache or negative. Ask winbindd. */
1500 /* Ask winbindd if it can map this sid to a gid.
1501 * (Idmap will check it is a valid SID and of the right type) */
1503 if ( !winbind_sid_to_gid(pgid, psid) ) {
1505 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1506 sid_string_dbg(psid)));
1507 /* winbind failed. do legacy */
1508 return legacy_sid_to_gid(psid, pgid);
1512 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1513 (unsigned int)*pgid ));
1515 store_gid_sid_cache(psid, *pgid);
1516 return true;