s3-spoolss: Sorted the builtin forms alphabetically.
[Samba/gebeck_regimport.git] / source3 / passdb / lookup_sid.c
blobff8777493ae2b4e2cb1a950e679c5771e1342e74
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 => domain=[%s], name=[%s]\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_compose(&sid, get_global_sam_sid(), rid);
79 goto ok;
81 TALLOC_FREE(tmp_ctx);
82 return false;
85 if ((flags & LOOKUP_NAME_BUILTIN) &&
86 strequal(domain, builtin_domain_name()))
88 if (strlen(name) == 0) {
89 /* Swap domain and name */
90 tmp = name; name = domain; domain = tmp;
91 sid_copy(&sid, &global_sid_Builtin);
92 type = SID_NAME_DOMAIN;
93 goto ok;
96 /* Explicit request for a name in BUILTIN */
97 if (lookup_builtin_name(name, &rid)) {
98 sid_compose(&sid, &global_sid_Builtin, rid);
99 type = SID_NAME_ALIAS;
100 goto ok;
102 TALLOC_FREE(tmp_ctx);
103 return false;
106 /* Try the explicit winbind lookup first, don't let it guess the
107 * domain yet at this point yet. This comes later. */
109 if ((domain[0] != '\0') &&
110 (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
111 (winbind_lookup_name(domain, name, &sid, &type))) {
112 goto ok;
115 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
116 && strequal(domain, unix_users_domain_name())) {
117 if (lookup_unix_user_name(name, &sid)) {
118 type = SID_NAME_USER;
119 goto ok;
121 TALLOC_FREE(tmp_ctx);
122 return false;
125 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
126 && strequal(domain, unix_groups_domain_name())) {
127 if (lookup_unix_group_name(name, &sid)) {
128 type = SID_NAME_DOM_GRP;
129 goto ok;
131 TALLOC_FREE(tmp_ctx);
132 return false;
135 if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
136 TALLOC_FREE(tmp_ctx);
137 return false;
140 /* Now the guesswork begins, we haven't been given an explicit
141 * domain. Try the sequence as documented on
142 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
143 * November 27, 2005 */
145 /* 1. well-known names */
147 if ((flags & LOOKUP_NAME_WKN) &&
148 lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
150 type = SID_NAME_WKN_GRP;
151 goto ok;
154 /* 2. Builtin domain as such */
156 if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
157 strequal(name, builtin_domain_name()))
159 /* Swap domain and name */
160 tmp = name; name = domain; domain = tmp;
161 sid_copy(&sid, &global_sid_Builtin);
162 type = SID_NAME_DOMAIN;
163 goto ok;
166 /* 3. Account domain */
168 if ((flags & LOOKUP_NAME_DOMAIN) &&
169 strequal(name, get_global_sam_name()))
171 if (!secrets_fetch_domain_sid(name, &sid)) {
172 DEBUG(3, ("Could not fetch my SID\n"));
173 TALLOC_FREE(tmp_ctx);
174 return false;
176 /* Swap domain and name */
177 tmp = name; name = domain; domain = tmp;
178 type = SID_NAME_DOMAIN;
179 goto ok;
182 /* 4. Primary domain */
184 if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
185 strequal(name, lp_workgroup()))
187 if (!secrets_fetch_domain_sid(name, &sid)) {
188 DEBUG(3, ("Could not fetch the domain SID\n"));
189 TALLOC_FREE(tmp_ctx);
190 return false;
192 /* Swap domain and name */
193 tmp = name; name = domain; domain = tmp;
194 type = SID_NAME_DOMAIN;
195 goto ok;
198 /* 5. Trusted domains as such, to me it looks as if members don't do
199 this, tested an XP workstation in a NT domain -- vl */
201 if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
202 (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
204 /* Swap domain and name */
205 tmp = name; name = domain; domain = tmp;
206 type = SID_NAME_DOMAIN;
207 goto ok;
210 /* 6. Builtin aliases */
212 if ((flags & LOOKUP_NAME_BUILTIN) &&
213 lookup_builtin_name(name, &rid))
215 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
216 sid_compose(&sid, &global_sid_Builtin, rid);
217 type = SID_NAME_ALIAS;
218 goto ok;
221 /* 7. Local systems' SAM (DCs don't have a local SAM) */
222 /* 8. Primary SAM (On members, this is the domain) */
224 /* Both cases are done by looking at our passdb */
226 if ((flags & LOOKUP_NAME_DOMAIN) &&
227 lookup_global_sam_name(name, flags, &rid, &type))
229 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
230 sid_compose(&sid, get_global_sam_sid(), rid);
231 goto ok;
234 /* Now our local possibilities are exhausted. */
236 if (!(flags & LOOKUP_NAME_REMOTE)) {
237 TALLOC_FREE(tmp_ctx);
238 return false;
241 /* If we are not a DC, we have to ask in our primary domain. Let
242 * winbind do that. */
244 if (!IS_DC &&
245 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
246 domain = talloc_strdup(tmp_ctx, lp_workgroup());
247 goto ok;
250 /* 9. Trusted domains */
252 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
253 * that (yet), but give it a chance. */
255 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
256 DOM_SID dom_sid;
257 uint32 tmp_rid;
258 enum lsa_SidType domain_type;
260 if (type == SID_NAME_DOMAIN) {
261 /* Swap name and type */
262 tmp = name; name = domain; domain = tmp;
263 goto ok;
266 /* Here we have to cope with a little deficiency in the
267 * winbind API: We have to ask it again for the name of the
268 * domain it figured out itself. Maybe fix that later... */
270 sid_copy(&dom_sid, &sid);
271 sid_split_rid(&dom_sid, &tmp_rid);
273 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
274 &domain_type) ||
275 (domain_type != SID_NAME_DOMAIN)) {
276 DEBUG(2, ("winbind could not find the domain's name "
277 "it just looked up for us\n"));
278 TALLOC_FREE(tmp_ctx);
279 return false;
281 goto ok;
284 /* 10. Don't translate */
286 /* 11. Ok, windows would end here. Samba has two more options:
287 Unmapped users and unmapped groups */
289 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
290 && lookup_unix_user_name(name, &sid)) {
291 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
292 type = SID_NAME_USER;
293 goto ok;
296 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
297 && lookup_unix_group_name(name, &sid)) {
298 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
299 type = SID_NAME_DOM_GRP;
300 goto ok;
304 * Ok, all possibilities tried. Fail.
307 TALLOC_FREE(tmp_ctx);
308 return false;
311 if ((domain == NULL) || (name == NULL)) {
312 DEBUG(0, ("talloc failed\n"));
313 TALLOC_FREE(tmp_ctx);
314 return false;
318 * Hand over the results to the talloc context we've been given.
321 if ((ret_name != NULL) &&
322 !(*ret_name = talloc_strdup(mem_ctx, name))) {
323 DEBUG(0, ("talloc failed\n"));
324 TALLOC_FREE(tmp_ctx);
325 return false;
328 if (ret_domain != NULL) {
329 char *tmp_dom;
330 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
331 DEBUG(0, ("talloc failed\n"));
332 TALLOC_FREE(tmp_ctx);
333 return false;
335 strupper_m(tmp_dom);
336 *ret_domain = tmp_dom;
339 if (ret_sid != NULL) {
340 sid_copy(ret_sid, &sid);
343 if (ret_type != NULL) {
344 *ret_type = type;
347 TALLOC_FREE(tmp_ctx);
348 return true;
351 /************************************************************************
352 Names from smb.conf can be unqualified. eg. valid users = foo
353 These names should never map to a remote name. Try global_sam_name()\foo,
354 and then "Unix Users"\foo (or "Unix Groups"\foo).
355 ************************************************************************/
357 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
358 const char *full_name, int flags,
359 const char **ret_domain, const char **ret_name,
360 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
362 char *qualified_name;
363 const char *p;
365 /* NB. No winbindd_separator here as lookup_name needs \\' */
366 if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
368 /* The name is already qualified with a domain. */
370 if (*lp_winbind_separator() != '\\') {
371 char *tmp;
373 /* lookup_name() needs '\\' as a separator */
375 tmp = talloc_strdup(mem_ctx, full_name);
376 if (!tmp) {
377 return false;
379 tmp[p - full_name] = '\\';
380 full_name = tmp;
383 return lookup_name(mem_ctx, full_name, flags,
384 ret_domain, ret_name,
385 ret_sid, ret_type);
388 /* Try with our own SAM name. */
389 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
390 get_global_sam_name(),
391 full_name );
392 if (!qualified_name) {
393 return false;
396 if (lookup_name(mem_ctx, qualified_name, flags,
397 ret_domain, ret_name,
398 ret_sid, ret_type)) {
399 return true;
402 /* Finally try with "Unix Users" or "Unix Group" */
403 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
404 flags & LOOKUP_NAME_GROUP ?
405 unix_groups_domain_name() :
406 unix_users_domain_name(),
407 full_name );
408 if (!qualified_name) {
409 return false;
412 return lookup_name(mem_ctx, qualified_name, flags,
413 ret_domain, ret_name,
414 ret_sid, ret_type);
417 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
418 const DOM_SID *domain_sid,
419 int num_rids, uint32 *rids,
420 const char **domain_name,
421 const char **names, enum lsa_SidType *types)
423 int i;
424 const char **my_names;
425 enum lsa_SidType *my_types;
426 TALLOC_CTX *tmp_ctx;
428 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
429 return false;
432 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
433 domain_name, &my_names, &my_types)) {
434 *domain_name = "";
435 for (i=0; i<num_rids; i++) {
436 names[i] = "";
437 types[i] = SID_NAME_UNKNOWN;
439 TALLOC_FREE(tmp_ctx);
440 return true;
443 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
444 TALLOC_FREE(tmp_ctx);
445 return false;
449 * winbind_lookup_rids allocates its own array. We've been given the
450 * array, so copy it over
453 for (i=0; i<num_rids; i++) {
454 if (my_names[i] == NULL) {
455 TALLOC_FREE(tmp_ctx);
456 return false;
458 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
459 TALLOC_FREE(tmp_ctx);
460 return false;
462 types[i] = my_types[i];
464 TALLOC_FREE(tmp_ctx);
465 return true;
468 static bool lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
469 int num_rids, uint32_t *rids,
470 const char **domain_name,
471 const char ***names, enum lsa_SidType **types)
473 int i;
475 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
476 sid_string_dbg(domain_sid)));
478 if (num_rids) {
479 *names = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
480 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
482 if ((*names == NULL) || (*types == NULL)) {
483 return false;
486 for (i = 0; i < num_rids; i++)
487 (*types)[i] = SID_NAME_UNKNOWN;
488 } else {
489 *names = NULL;
490 *types = NULL;
493 if (sid_check_is_domain(domain_sid)) {
494 NTSTATUS result;
496 if (*domain_name == NULL) {
497 *domain_name = talloc_strdup(
498 mem_ctx, get_global_sam_name());
501 if (*domain_name == NULL) {
502 return false;
505 become_root();
506 result = pdb_lookup_rids(domain_sid, num_rids, rids,
507 *names, *types);
508 unbecome_root();
510 return (NT_STATUS_IS_OK(result) ||
511 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
512 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
515 if (sid_check_is_builtin(domain_sid)) {
517 if (*domain_name == NULL) {
518 *domain_name = talloc_strdup(
519 mem_ctx, builtin_domain_name());
522 if (*domain_name == NULL) {
523 return false;
526 for (i=0; i<num_rids; i++) {
527 if (lookup_builtin_rid(*names, rids[i],
528 &(*names)[i])) {
529 if ((*names)[i] == NULL) {
530 return false;
532 (*types)[i] = SID_NAME_ALIAS;
533 } else {
534 (*types)[i] = SID_NAME_UNKNOWN;
537 return true;
540 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
541 for (i=0; i<num_rids; i++) {
542 DOM_SID sid;
543 sid_compose(&sid, domain_sid, rids[i]);
544 if (lookup_wellknown_sid(mem_ctx, &sid,
545 domain_name, &(*names)[i])) {
546 if ((*names)[i] == NULL) {
547 return false;
549 (*types)[i] = SID_NAME_WKN_GRP;
550 } else {
551 (*types)[i] = SID_NAME_UNKNOWN;
554 return true;
557 if (sid_check_is_unix_users(domain_sid)) {
558 if (*domain_name == NULL) {
559 *domain_name = talloc_strdup(
560 mem_ctx, unix_users_domain_name());
561 if (*domain_name == NULL) {
562 return false;
565 for (i=0; i<num_rids; i++) {
566 (*names)[i] = talloc_strdup(
567 (*names), uidtoname(rids[i]));
568 if ((*names)[i] == NULL) {
569 return false;
571 (*types)[i] = SID_NAME_USER;
573 return true;
576 if (sid_check_is_unix_groups(domain_sid)) {
577 if (*domain_name == NULL) {
578 *domain_name = talloc_strdup(
579 mem_ctx, unix_groups_domain_name());
580 if (*domain_name == NULL) {
581 return false;
584 for (i=0; i<num_rids; i++) {
585 (*names)[i] = talloc_strdup(
586 (*names), gidtoname(rids[i]));
587 if ((*names)[i] == NULL) {
588 return false;
590 (*types)[i] = SID_NAME_DOM_GRP;
592 return true;
595 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
596 domain_name, *names, *types);
600 * Is the SID a domain as such? If yes, lookup its name.
603 static bool lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
604 const char **name)
606 const char *tmp;
607 enum lsa_SidType type;
609 if (sid_check_is_domain(sid)) {
610 *name = talloc_strdup(mem_ctx, get_global_sam_name());
611 return true;
614 if (sid_check_is_builtin(sid)) {
615 *name = talloc_strdup(mem_ctx, builtin_domain_name());
616 return true;
619 if (sid_check_is_wellknown_domain(sid, &tmp)) {
620 *name = talloc_strdup(mem_ctx, tmp);
621 return true;
624 if (sid_check_is_unix_users(sid)) {
625 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
626 return true;
629 if (sid_check_is_unix_groups(sid)) {
630 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
631 return true;
634 if (sid->num_auths != 4) {
635 /* This can't be a domain */
636 return false;
639 if (IS_DC) {
640 uint32 i, num_domains;
641 struct trustdom_info **domains;
643 /* This is relatively expensive, but it happens only on DCs
644 * and for SIDs that have 4 sub-authorities and thus look like
645 * domains */
647 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
648 &num_domains,
649 &domains))) {
650 return false;
653 for (i=0; i<num_domains; i++) {
654 if (sid_equal(sid, &domains[i]->sid)) {
655 *name = talloc_strdup(mem_ctx,
656 domains[i]->name);
657 return true;
660 return false;
663 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
664 (type == SID_NAME_DOMAIN)) {
665 *name = tmp;
666 return true;
669 return false;
673 * This tries to implement the rather weird rules for the lsa_lookup level
674 * parameter.
676 * This is as close as we can get to what W2k3 does. With this we survive the
677 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
678 * different, but I assume that's just being too liberal. For example, W2k3
679 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
680 * whereas NT4 does the same as level 1 (I think). I did not fully test that
681 * with NT4, this is what w2k3 does.
683 * Level 1: Ask everywhere
684 * Level 2: Ask domain and trusted domains, no builtin and wkn
685 * Level 3: Only ask domain
686 * Level 4: W2k3ad: Only ask AD trusts
687 * Level 5: Only ask transitive forest trusts
688 * Level 6: Like 4
691 static bool check_dom_sid_to_level(const DOM_SID *sid, int level)
693 int ret = false;
695 switch(level) {
696 case 1:
697 ret = true;
698 break;
699 case 2:
700 ret = (!sid_check_is_builtin(sid) &&
701 !sid_check_is_wellknown_domain(sid, NULL));
702 break;
703 case 3:
704 case 4:
705 case 6:
706 ret = sid_check_is_domain(sid);
707 break;
708 case 5:
709 ret = false;
710 break;
713 DEBUG(10, ("%s SID %s in level %d\n",
714 ret ? "Accepting" : "Rejecting",
715 sid_string_dbg(sid), level));
716 return ret;
720 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
721 * references to domains, it is explicitly made for this.
723 * This attempts to be as efficient as possible: It collects all SIDs
724 * belonging to a domain and hands them in bulk to the appropriate lookup
725 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
726 * *hugely* from this. Winbind is going to be extended with a lookup_rids
727 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
728 * appropriate DC.
731 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
732 const DOM_SID **sids, int level,
733 struct lsa_dom_info **ret_domains,
734 struct lsa_name_info **ret_names)
736 TALLOC_CTX *tmp_ctx;
737 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
738 struct lsa_name_info *name_infos;
739 struct lsa_dom_info *dom_infos = NULL;
741 int i, j;
743 if (!(tmp_ctx = talloc_new(mem_ctx))) {
744 DEBUG(0, ("talloc_new failed\n"));
745 return NT_STATUS_NO_MEMORY;
748 if (num_sids) {
749 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
750 if (name_infos == NULL) {
751 result = NT_STATUS_NO_MEMORY;
752 goto fail;
754 } else {
755 name_infos = NULL;
758 dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
759 LSA_REF_DOMAIN_LIST_MULTIPLIER);
760 if (dom_infos == NULL) {
761 result = NT_STATUS_NO_MEMORY;
762 goto fail;
765 /* First build up the data structures:
767 * dom_infos is a list of domains referenced in the list of
768 * SIDs. Later we will walk the list of domains and look up the RIDs
769 * in bulk.
771 * name_infos is a shadow-copy of the SIDs array to collect the real
772 * data.
774 * dom_info->idxs is an index into the name_infos array. The
775 * difficulty we have here is that we need to keep the SIDs the client
776 * asked for in the same order for the reply
779 for (i=0; i<num_sids; i++) {
780 DOM_SID sid;
781 uint32 rid;
782 const char *domain_name = NULL;
784 sid_copy(&sid, sids[i]);
785 name_infos[i].type = SID_NAME_USE_NONE;
787 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
788 /* We can't push that through the normal lookup
789 * process, as this would reference illegal
790 * domains.
792 * For example S-1-5-32 would end up referencing
793 * domain S-1-5- with RID 32 which is clearly wrong.
795 if (domain_name == NULL) {
796 result = NT_STATUS_NO_MEMORY;
797 goto fail;
800 name_infos[i].rid = 0;
801 name_infos[i].type = SID_NAME_DOMAIN;
802 name_infos[i].name = NULL;
804 if (sid_check_is_builtin(&sid)) {
805 /* Yes, W2k3 returns "BUILTIN" both as domain
806 * and name here */
807 name_infos[i].name = talloc_strdup(
808 name_infos, builtin_domain_name());
809 if (name_infos[i].name == NULL) {
810 result = NT_STATUS_NO_MEMORY;
811 goto fail;
814 } else {
815 /* This is a normal SID with rid component */
816 if (!sid_split_rid(&sid, &rid)) {
817 result = NT_STATUS_INVALID_SID;
818 goto fail;
822 if (!check_dom_sid_to_level(&sid, level)) {
823 name_infos[i].rid = 0;
824 name_infos[i].type = SID_NAME_UNKNOWN;
825 name_infos[i].name = NULL;
826 continue;
829 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
830 if (!dom_infos[j].valid) {
831 break;
833 if (sid_equal(&sid, &dom_infos[j].sid)) {
834 break;
838 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
839 /* TODO: What's the right error message here? */
840 result = NT_STATUS_NONE_MAPPED;
841 goto fail;
844 if (!dom_infos[j].valid) {
845 /* We found a domain not yet referenced, create a new
846 * ref. */
847 dom_infos[j].valid = true;
848 sid_copy(&dom_infos[j].sid, &sid);
850 if (domain_name != NULL) {
851 /* This name was being found above in the case
852 * when we found a domain SID */
853 dom_infos[j].name =
854 talloc_strdup(dom_infos, domain_name);
855 if (dom_infos[j].name == NULL) {
856 result = NT_STATUS_NO_MEMORY;
857 goto fail;
859 } else {
860 /* lookup_rids will take care of this */
861 dom_infos[j].name = NULL;
865 name_infos[i].dom_idx = j;
867 if (name_infos[i].type == SID_NAME_USE_NONE) {
868 name_infos[i].rid = rid;
870 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
871 &dom_infos[j].num_idxs);
873 if (dom_infos[j].idxs == NULL) {
874 result = NT_STATUS_NO_MEMORY;
875 goto fail;
880 /* Iterate over the domains found */
882 for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
883 uint32_t *rids;
884 const char *domain_name = NULL;
885 const char **names;
886 enum lsa_SidType *types;
887 struct lsa_dom_info *dom = &dom_infos[i];
889 if (!dom->valid) {
890 /* No domains left, we're done */
891 break;
894 if (dom->num_idxs) {
895 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
896 result = NT_STATUS_NO_MEMORY;
897 goto fail;
899 } else {
900 rids = NULL;
903 for (j=0; j<dom->num_idxs; j++) {
904 rids[j] = name_infos[dom->idxs[j]].rid;
907 if (!lookup_rids(tmp_ctx, &dom->sid,
908 dom->num_idxs, rids, &domain_name,
909 &names, &types)) {
910 result = NT_STATUS_NO_MEMORY;
911 goto fail;
914 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
915 result = NT_STATUS_NO_MEMORY;
916 goto fail;
919 for (j=0; j<dom->num_idxs; j++) {
920 int idx = dom->idxs[j];
921 name_infos[idx].type = types[j];
922 if (types[j] != SID_NAME_UNKNOWN) {
923 name_infos[idx].name =
924 talloc_strdup(name_infos, names[j]);
925 if (name_infos[idx].name == NULL) {
926 result = NT_STATUS_NO_MEMORY;
927 goto fail;
929 } else {
930 name_infos[idx].name = NULL;
935 *ret_domains = dom_infos;
936 *ret_names = name_infos;
937 TALLOC_FREE(tmp_ctx);
938 return NT_STATUS_OK;
940 fail:
941 TALLOC_FREE(dom_infos);
942 TALLOC_FREE(name_infos);
943 TALLOC_FREE(tmp_ctx);
944 return result;
947 /*****************************************************************
948 *THE CANONICAL* convert SID to name function.
949 *****************************************************************/
951 bool lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
952 const char **ret_domain, const char **ret_name,
953 enum lsa_SidType *ret_type)
955 struct lsa_dom_info *domain;
956 struct lsa_name_info *name;
957 TALLOC_CTX *tmp_ctx;
958 bool ret = false;
960 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
962 if (!(tmp_ctx = talloc_new(mem_ctx))) {
963 DEBUG(0, ("talloc_new failed\n"));
964 return false;
967 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
968 &domain, &name))) {
969 goto done;
972 if (name->type == SID_NAME_UNKNOWN) {
973 goto done;
976 if ((ret_domain != NULL) &&
977 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
978 goto done;
981 if ((ret_name != NULL) &&
982 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
983 goto done;
986 if (ret_type != NULL) {
987 *ret_type = name->type;
990 ret = true;
992 done:
993 if (ret) {
994 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
995 domain->name, name->name, name->type));
996 } else {
997 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
999 TALLOC_FREE(tmp_ctx);
1000 return ret;
1003 /*****************************************************************
1004 Id mapping cache. This is to avoid Winbind mappings already
1005 seen by smbd to be queried too frequently, keeping winbindd
1006 busy, and blocking smbd while winbindd is busy with other
1007 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1008 modified to use linked lists by jra.
1009 *****************************************************************/
1011 /*****************************************************************
1012 Find a SID given a uid.
1013 *****************************************************************/
1015 static bool fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
1017 DATA_BLOB cache_value;
1019 if (!memcache_lookup(NULL, UID_SID_CACHE,
1020 data_blob_const(&uid, sizeof(uid)),
1021 &cache_value)) {
1022 return false;
1025 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1026 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1027 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, 0));
1029 return true;
1032 /*****************************************************************
1033 Find a uid given a SID.
1034 *****************************************************************/
1036 static bool fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
1038 DATA_BLOB cache_value;
1040 if (!memcache_lookup(NULL, SID_UID_CACHE,
1041 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1042 &cache_value)) {
1043 return false;
1046 SMB_ASSERT(cache_value.length == sizeof(*puid));
1047 memcpy(puid, cache_value.data, sizeof(*puid));
1049 return true;
1052 /*****************************************************************
1053 Store uid to SID mapping in cache.
1054 *****************************************************************/
1056 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
1058 memcache_add(NULL, SID_UID_CACHE,
1059 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1060 data_blob_const(&uid, sizeof(uid)));
1061 memcache_add(NULL, UID_SID_CACHE,
1062 data_blob_const(&uid, sizeof(uid)),
1063 data_blob_const(psid, ndr_size_dom_sid(psid, 0)));
1066 /*****************************************************************
1067 Find a SID given a gid.
1068 *****************************************************************/
1070 static bool fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1072 DATA_BLOB cache_value;
1074 if (!memcache_lookup(NULL, GID_SID_CACHE,
1075 data_blob_const(&gid, sizeof(gid)),
1076 &cache_value)) {
1077 return false;
1080 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1081 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1082 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, 0));
1084 return true;
1087 /*****************************************************************
1088 Find a gid given a SID.
1089 *****************************************************************/
1091 static bool fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1093 DATA_BLOB cache_value;
1095 if (!memcache_lookup(NULL, SID_GID_CACHE,
1096 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1097 &cache_value)) {
1098 return false;
1101 SMB_ASSERT(cache_value.length == sizeof(*pgid));
1102 memcpy(pgid, cache_value.data, sizeof(*pgid));
1104 return true;
1107 /*****************************************************************
1108 Store gid to SID mapping in cache.
1109 *****************************************************************/
1111 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1113 memcache_add(NULL, SID_GID_CACHE,
1114 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1115 data_blob_const(&gid, sizeof(gid)));
1116 memcache_add(NULL, GID_SID_CACHE,
1117 data_blob_const(&gid, sizeof(gid)),
1118 data_blob_const(psid, ndr_size_dom_sid(psid, 0)));
1121 /*****************************************************************
1122 *THE LEGACY* convert uid_t to SID function.
1123 *****************************************************************/
1125 static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
1127 bool ret;
1129 ZERO_STRUCTP(psid);
1131 become_root();
1132 ret = pdb_uid_to_sid(uid, psid);
1133 unbecome_root();
1135 if (ret) {
1136 /* This is a mapped user */
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;
1191 if (sid_check_is_in_our_domain(psid)) {
1192 union unid_t id;
1193 bool ret;
1195 become_root();
1196 ret = pdb_sid_to_id(psid, &id, &type);
1197 unbecome_root();
1199 if (ret) {
1200 if (type != SID_NAME_USER) {
1201 DEBUG(5, ("sid %s is a %s, expected a user\n",
1202 sid_string_dbg(psid),
1203 sid_type_lookup(type)));
1204 return false;
1206 *puid = id.uid;
1207 goto done;
1210 /* This was ours, but it was not mapped. Fail */
1213 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1214 sid_string_dbg(psid)));
1215 return false;
1217 done:
1218 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_dbg(psid),
1219 (unsigned int)*puid ));
1221 store_uid_sid_cache(psid, *puid);
1222 return true;
1225 /*****************************************************************
1226 *THE LEGACY* convert SID to gid function.
1227 Group mapping is used for gids that maps to Wellknown SIDs
1228 *****************************************************************/
1230 static bool legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1232 GROUP_MAP map;
1233 union unid_t id;
1234 enum lsa_SidType type;
1236 if ((sid_check_is_in_builtin(psid) ||
1237 sid_check_is_in_wellknown_domain(psid))) {
1238 bool ret;
1240 become_root();
1241 ret = pdb_getgrsid(&map, *psid);
1242 unbecome_root();
1244 if (ret) {
1245 *pgid = map.gid;
1246 goto done;
1248 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1249 sid_string_dbg(psid)));
1250 return false;
1253 if (sid_check_is_in_our_domain(psid)) {
1254 bool ret;
1256 become_root();
1257 ret = pdb_sid_to_id(psid, &id, &type);
1258 unbecome_root();
1260 if (ret) {
1261 if ((type != SID_NAME_DOM_GRP) &&
1262 (type != SID_NAME_ALIAS)) {
1263 DEBUG(5, ("LEGACY: sid %s is a %s, expected "
1264 "a group\n", sid_string_dbg(psid),
1265 sid_type_lookup(type)));
1266 return false;
1268 *pgid = id.gid;
1269 goto done;
1272 /* This was ours, but it was not mapped. Fail */
1275 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1276 sid_string_dbg(psid)));
1277 return false;
1279 done:
1280 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_dbg(psid),
1281 (unsigned int)*pgid ));
1283 store_gid_sid_cache(psid, *pgid);
1285 return true;
1288 /*****************************************************************
1289 *THE CANONICAL* convert uid_t to SID function.
1290 *****************************************************************/
1292 void uid_to_sid(DOM_SID *psid, uid_t uid)
1294 bool expired = true;
1295 bool ret;
1296 ZERO_STRUCTP(psid);
1298 if (fetch_sid_from_uid_cache(psid, uid))
1299 return;
1301 /* Check the winbindd cache directly. */
1302 ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1304 if (ret && !expired && is_null_sid(psid)) {
1306 * Negative cache entry, we already asked.
1307 * do legacy.
1309 legacy_uid_to_sid(psid, uid);
1310 return;
1313 if (!ret || expired) {
1314 /* Not in cache. Ask winbindd. */
1315 if (!winbind_uid_to_sid(psid, uid)) {
1317 * We shouldn't return the NULL SID
1318 * here if winbind was running and
1319 * couldn't map, as winbind will have
1320 * added a negative entry that will
1321 * cause us to go though the
1322 * legacy_uid_to_sid()
1323 * function anyway in the case above
1324 * the next time we ask.
1326 DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1327 "for uid %u\n", (unsigned int)uid));
1329 legacy_uid_to_sid(psid, uid);
1330 return;
1334 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1335 sid_string_dbg(psid)));
1337 store_uid_sid_cache(psid, uid);
1338 return;
1341 /*****************************************************************
1342 *THE CANONICAL* convert gid_t to SID function.
1343 *****************************************************************/
1345 void gid_to_sid(DOM_SID *psid, gid_t gid)
1347 bool expired = true;
1348 bool ret;
1349 ZERO_STRUCTP(psid);
1351 if (fetch_sid_from_gid_cache(psid, gid))
1352 return;
1354 /* Check the winbindd cache directly. */
1355 ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1357 if (ret && !expired && is_null_sid(psid)) {
1359 * Negative cache entry, we already asked.
1360 * do legacy.
1362 legacy_gid_to_sid(psid, gid);
1363 return;
1366 if (!ret || expired) {
1367 /* Not in cache. Ask winbindd. */
1368 if (!winbind_gid_to_sid(psid, gid)) {
1370 * We shouldn't return the NULL SID
1371 * here if winbind was running and
1372 * couldn't map, as winbind will have
1373 * added a negative entry that will
1374 * cause us to go though the
1375 * legacy_gid_to_sid()
1376 * function anyway in the case above
1377 * the next time we ask.
1379 DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1380 "for gid %u\n", (unsigned int)gid));
1382 legacy_gid_to_sid(psid, gid);
1383 return;
1387 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1388 sid_string_dbg(psid)));
1390 store_gid_sid_cache(psid, gid);
1391 return;
1394 /*****************************************************************
1395 *THE CANONICAL* convert SID to uid function.
1396 *****************************************************************/
1398 bool sid_to_uid(const DOM_SID *psid, uid_t *puid)
1400 bool expired = true;
1401 bool ret;
1402 uint32 rid;
1403 gid_t gid;
1405 if (fetch_uid_from_cache(puid, psid))
1406 return true;
1408 if (fetch_gid_from_cache(&gid, psid)) {
1409 return false;
1412 /* Optimize for the Unix Users Domain
1413 * as the conversion is straightforward */
1414 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1415 uid_t uid = rid;
1416 *puid = uid;
1418 /* return here, don't cache */
1419 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1420 (unsigned int)*puid ));
1421 return true;
1424 /* Check the winbindd cache directly. */
1425 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1427 if (ret && !expired && (*puid == (uid_t)-1)) {
1429 * Negative cache entry, we already asked.
1430 * do legacy.
1432 return legacy_sid_to_uid(psid, puid);
1435 if (!ret || expired) {
1436 /* Not in cache. Ask winbindd. */
1437 if (!winbind_sid_to_uid(puid, psid)) {
1438 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1439 sid_string_dbg(psid)));
1440 /* winbind failed. do legacy */
1441 return legacy_sid_to_uid(psid, puid);
1445 /* TODO: Here would be the place to allocate both a gid and a uid for
1446 * the SID in question */
1448 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1449 (unsigned int)*puid ));
1451 store_uid_sid_cache(psid, *puid);
1452 return true;
1455 /*****************************************************************
1456 *THE CANONICAL* convert SID to gid function.
1457 Group mapping is used for gids that maps to Wellknown SIDs
1458 *****************************************************************/
1460 bool sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1462 bool expired = true;
1463 bool ret;
1464 uint32 rid;
1465 uid_t uid;
1467 if (fetch_gid_from_cache(pgid, psid))
1468 return true;
1470 if (fetch_uid_from_cache(&uid, psid))
1471 return false;
1473 /* Optimize for the Unix Groups Domain
1474 * as the conversion is straightforward */
1475 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1476 gid_t gid = rid;
1477 *pgid = gid;
1479 /* return here, don't cache */
1480 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1481 (unsigned int)*pgid ));
1482 return true;
1485 /* Check the winbindd cache directly. */
1486 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1488 if (ret && !expired && (*pgid == (gid_t)-1)) {
1490 * Negative cache entry, we already asked.
1491 * do legacy.
1493 return legacy_sid_to_gid(psid, pgid);
1496 if (!ret || expired) {
1497 /* Not in cache or negative. Ask winbindd. */
1498 /* Ask winbindd if it can map this sid to a gid.
1499 * (Idmap will check it is a valid SID and of the right type) */
1501 if ( !winbind_sid_to_gid(pgid, psid) ) {
1503 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1504 sid_string_dbg(psid)));
1505 /* winbind failed. do legacy */
1506 return legacy_sid_to_gid(psid, pgid);
1510 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1511 (unsigned int)*pgid ));
1513 store_gid_sid_cache(psid, *pgid);
1514 return true;