[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / passdb / lookup_sid.c
blob37285f01d2364694ea58d21a677eba67dd433da7
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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 /*****************************************************************
26 Dissect a user-provided name into domain, name, sid and type.
28 If an explicit domain name was given in the form domain\user, it
29 has to try that. If no explicit domain name was given, we have
30 to do guesswork.
31 *****************************************************************/
33 BOOL lookup_name(TALLOC_CTX *mem_ctx,
34 const char *full_name, int flags,
35 const char **ret_domain, const char **ret_name,
36 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
38 char *p;
39 const char *tmp;
40 const char *domain = NULL;
41 const char *name = NULL;
42 uint32 rid;
43 DOM_SID sid;
44 enum lsa_SidType type;
45 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
47 if (tmp_ctx == NULL) {
48 DEBUG(0, ("talloc_new failed\n"));
49 return False;
52 p = strchr_m(full_name, '\\');
54 if (p != NULL) {
55 domain = talloc_strndup(tmp_ctx, full_name,
56 PTR_DIFF(p, full_name));
57 name = talloc_strdup(tmp_ctx, p+1);
58 } else {
59 domain = talloc_strdup(tmp_ctx, "");
60 name = talloc_strdup(tmp_ctx, full_name);
63 DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
64 full_name, domain, name));
66 if ((domain == NULL) || (name == NULL)) {
67 DEBUG(0, ("talloc failed\n"));
68 TALLOC_FREE(tmp_ctx);
69 return False;
72 if (strequal(domain, get_global_sam_name())) {
74 /* It's our own domain, lookup the name in passdb */
75 if (lookup_global_sam_name(name, flags, &rid, &type)) {
76 sid_copy(&sid, get_global_sam_sid());
77 sid_append_rid(&sid, rid);
78 goto ok;
80 TALLOC_FREE(tmp_ctx);
81 return False;
84 if (strequal(domain, builtin_domain_name())) {
86 /* Explicit request for a name in BUILTIN */
87 if (lookup_builtin_name(name, &rid)) {
88 sid_copy(&sid, &global_sid_Builtin);
89 sid_append_rid(&sid, rid);
90 type = SID_NAME_ALIAS;
91 goto ok;
93 TALLOC_FREE(tmp_ctx);
94 return False;
97 /* Try the explicit winbind lookup first, don't let it guess the
98 * domain yet at this point yet. This comes later. */
100 if ((domain[0] != '\0') &&
101 (winbind_lookup_name(domain, name, &sid, &type))) {
102 goto ok;
105 if (strequal(domain, unix_users_domain_name())) {
106 if (lookup_unix_user_name(name, &sid)) {
107 type = SID_NAME_USER;
108 goto ok;
110 TALLOC_FREE(tmp_ctx);
111 return False;
114 if (strequal(domain, unix_groups_domain_name())) {
115 if (lookup_unix_group_name(name, &sid)) {
116 type = SID_NAME_DOM_GRP;
117 goto ok;
119 TALLOC_FREE(tmp_ctx);
120 return False;
123 if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
124 TALLOC_FREE(tmp_ctx);
125 return False;
128 /* Now the guesswork begins, we haven't been given an explicit
129 * domain. Try the sequence as documented on
130 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
131 * November 27, 2005 */
133 /* 1. well-known names */
135 if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) {
136 type = SID_NAME_WKN_GRP;
137 goto ok;
140 /* 2. Builtin domain as such */
142 if (strequal(name, builtin_domain_name())) {
143 /* Swap domain and name */
144 tmp = name; name = domain; domain = tmp;
145 sid_copy(&sid, &global_sid_Builtin);
146 type = SID_NAME_DOMAIN;
147 goto ok;
150 /* 3. Account domain */
152 if (strequal(name, get_global_sam_name())) {
153 if (!secrets_fetch_domain_sid(name, &sid)) {
154 DEBUG(3, ("Could not fetch my SID\n"));
155 TALLOC_FREE(tmp_ctx);
156 return False;
158 /* Swap domain and name */
159 tmp = name; name = domain; domain = tmp;
160 type = SID_NAME_DOMAIN;
161 goto ok;
164 /* 4. Primary domain */
166 if (!IS_DC && strequal(name, lp_workgroup())) {
167 if (!secrets_fetch_domain_sid(name, &sid)) {
168 DEBUG(3, ("Could not fetch the domain SID\n"));
169 TALLOC_FREE(tmp_ctx);
170 return False;
172 /* Swap domain and name */
173 tmp = name; name = domain; domain = tmp;
174 type = SID_NAME_DOMAIN;
175 goto ok;
178 /* 5. Trusted domains as such, to me it looks as if members don't do
179 this, tested an XP workstation in a NT domain -- vl */
181 if (IS_DC && (secrets_fetch_trusted_domain_password(name, NULL,
182 &sid, NULL))) {
183 /* Swap domain and name */
184 tmp = name; name = domain; domain = tmp;
185 type = SID_NAME_DOMAIN;
186 goto ok;
189 /* 6. Builtin aliases */
191 if (lookup_builtin_name(name, &rid)) {
192 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
193 sid_copy(&sid, &global_sid_Builtin);
194 sid_append_rid(&sid, rid);
195 type = SID_NAME_ALIAS;
196 goto ok;
199 /* 7. Local systems' SAM (DCs don't have a local SAM) */
200 /* 8. Primary SAM (On members, this is the domain) */
202 /* Both cases are done by looking at our passdb */
204 if (lookup_global_sam_name(name, flags, &rid, &type)) {
205 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
206 sid_copy(&sid, get_global_sam_sid());
207 sid_append_rid(&sid, rid);
208 goto ok;
211 /* Now our local possibilities are exhausted. */
213 if (!(flags & LOOKUP_NAME_REMOTE)) {
214 TALLOC_FREE(tmp_ctx);
215 return False;
218 /* If we are not a DC, we have to ask in our primary domain. Let
219 * winbind do that. */
221 if (!IS_DC &&
222 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
223 domain = talloc_strdup(tmp_ctx, lp_workgroup());
224 goto ok;
227 /* 9. Trusted domains */
229 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
230 * that (yet), but give it a chance. */
232 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
233 DOM_SID dom_sid;
234 uint32 tmp_rid;
235 enum lsa_SidType domain_type;
237 if (type == SID_NAME_DOMAIN) {
238 /* Swap name and type */
239 tmp = name; name = domain; domain = tmp;
240 goto ok;
243 /* Here we have to cope with a little deficiency in the
244 * winbind API: We have to ask it again for the name of the
245 * domain it figured out itself. Maybe fix that later... */
247 sid_copy(&dom_sid, &sid);
248 sid_split_rid(&dom_sid, &tmp_rid);
250 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
251 &domain_type) ||
252 (domain_type != SID_NAME_DOMAIN)) {
253 DEBUG(2, ("winbind could not find the domain's name "
254 "it just looked up for us\n"));
255 TALLOC_FREE(tmp_ctx);
256 return False;
258 goto ok;
261 /* 10. Don't translate */
263 /* 11. Ok, windows would end here. Samba has two more options:
264 Unmapped users and unmapped groups */
266 if (lookup_unix_user_name(name, &sid)) {
267 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
268 type = SID_NAME_USER;
269 goto ok;
272 if (lookup_unix_group_name(name, &sid)) {
273 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
274 type = SID_NAME_DOM_GRP;
275 goto ok;
279 * Ok, all possibilities tried. Fail.
282 TALLOC_FREE(tmp_ctx);
283 return False;
286 if ((domain == NULL) || (name == NULL)) {
287 DEBUG(0, ("talloc failed\n"));
288 TALLOC_FREE(tmp_ctx);
289 return False;
293 * Hand over the results to the talloc context we've been given.
296 if ((ret_name != NULL) &&
297 !(*ret_name = talloc_strdup(mem_ctx, name))) {
298 DEBUG(0, ("talloc failed\n"));
299 TALLOC_FREE(tmp_ctx);
300 return False;
303 if (ret_domain != NULL) {
304 char *tmp_dom;
305 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
306 DEBUG(0, ("talloc failed\n"));
307 TALLOC_FREE(tmp_ctx);
308 return False;
310 strupper_m(tmp_dom);
311 *ret_domain = tmp_dom;
314 if (ret_sid != NULL) {
315 sid_copy(ret_sid, &sid);
318 if (ret_type != NULL) {
319 *ret_type = type;
322 TALLOC_FREE(tmp_ctx);
323 return True;
326 /************************************************************************
327 Names from smb.conf can be unqualified. eg. valid users = foo
328 These names should never map to a remote name. Try global_sam_name()\foo,
329 and then "Unix Users"\foo (or "Unix Groups"\foo).
330 ************************************************************************/
332 BOOL lookup_name_smbconf(TALLOC_CTX *mem_ctx,
333 const char *full_name, int flags,
334 const char **ret_domain, const char **ret_name,
335 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
337 char *qualified_name;
338 const char *p;
340 /* NB. No winbindd_separator here as lookup_name needs \\' */
341 if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
343 /* The name is already qualified with a domain. */
345 if (*lp_winbind_separator() != '\\') {
346 char *tmp;
348 /* lookup_name() needs '\\' as a separator */
350 tmp = talloc_strdup(mem_ctx, full_name);
351 if (!tmp) {
352 return False;
354 tmp[p - full_name] = '\\';
355 full_name = tmp;
358 return lookup_name(mem_ctx, full_name, flags,
359 ret_domain, ret_name,
360 ret_sid, ret_type);
363 /* Try with our own SAM name. */
364 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
365 get_global_sam_name(),
366 full_name );
367 if (!qualified_name) {
368 return False;
371 if (lookup_name(mem_ctx, qualified_name, flags,
372 ret_domain, ret_name,
373 ret_sid, ret_type)) {
374 return True;
377 /* Finally try with "Unix Users" or "Unix Group" */
378 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
379 flags & LOOKUP_NAME_GROUP ?
380 unix_groups_domain_name() :
381 unix_users_domain_name(),
382 full_name );
383 if (!qualified_name) {
384 return False;
387 return lookup_name(mem_ctx, qualified_name, flags,
388 ret_domain, ret_name,
389 ret_sid, ret_type);
392 static BOOL wb_lookup_rids(TALLOC_CTX *mem_ctx,
393 const DOM_SID *domain_sid,
394 int num_rids, uint32 *rids,
395 const char **domain_name,
396 const char **names, enum lsa_SidType *types)
398 int i;
399 const char **my_names;
400 enum lsa_SidType *my_types;
401 TALLOC_CTX *tmp_ctx;
403 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
404 return False;
407 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
408 domain_name, &my_names, &my_types)) {
409 *domain_name = "";
410 for (i=0; i<num_rids; i++) {
411 names[i] = "";
412 types[i] = SID_NAME_UNKNOWN;
414 TALLOC_FREE(tmp_ctx);
415 return True;
418 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
419 TALLOC_FREE(tmp_ctx);
420 return False;
424 * winbind_lookup_rids allocates its own array. We've been given the
425 * array, so copy it over
428 for (i=0; i<num_rids; i++) {
429 if (my_names[i] == NULL) {
430 TALLOC_FREE(tmp_ctx);
431 return False;
433 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
434 TALLOC_FREE(tmp_ctx);
435 return False;
437 types[i] = my_types[i];
439 TALLOC_FREE(tmp_ctx);
440 return True;
443 static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
444 int num_rids, uint32_t *rids,
445 const char **domain_name,
446 const char ***names, enum lsa_SidType **types)
448 int i;
450 if (num_rids) {
451 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
452 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
454 if ((*names == NULL) || (*types == NULL)) {
455 return False;
457 } else {
458 *names = NULL;
459 *types = NULL;
462 if (sid_check_is_domain(domain_sid)) {
463 NTSTATUS result;
465 if (*domain_name == NULL) {
466 *domain_name = talloc_strdup(
467 mem_ctx, get_global_sam_name());
470 if (*domain_name == NULL) {
471 return False;
474 become_root();
475 result = pdb_lookup_rids(domain_sid, num_rids, rids,
476 *names, *types);
477 unbecome_root();
479 return (NT_STATUS_IS_OK(result) ||
480 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
481 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
484 if (sid_check_is_builtin(domain_sid)) {
486 if (*domain_name == NULL) {
487 *domain_name = talloc_strdup(
488 mem_ctx, builtin_domain_name());
491 if (*domain_name == NULL) {
492 return False;
495 for (i=0; i<num_rids; i++) {
496 if (lookup_builtin_rid(*names, rids[i],
497 &(*names)[i])) {
498 if ((*names)[i] == NULL) {
499 return False;
501 (*types)[i] = SID_NAME_ALIAS;
502 } else {
503 (*types)[i] = SID_NAME_UNKNOWN;
506 return True;
509 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
510 for (i=0; i<num_rids; i++) {
511 DOM_SID sid;
512 sid_copy(&sid, domain_sid);
513 sid_append_rid(&sid, rids[i]);
514 if (lookup_wellknown_sid(mem_ctx, &sid,
515 domain_name, &(*names)[i])) {
516 if ((*names)[i] == NULL) {
517 return False;
519 (*types)[i] = SID_NAME_WKN_GRP;
520 } else {
521 (*types)[i] = SID_NAME_UNKNOWN;
524 return True;
527 if (sid_check_is_unix_users(domain_sid)) {
528 if (*domain_name == NULL) {
529 *domain_name = talloc_strdup(
530 mem_ctx, unix_users_domain_name());
532 for (i=0; i<num_rids; i++) {
533 (*names)[i] = talloc_strdup(
534 (*names), uidtoname(rids[i]));
535 (*types)[i] = SID_NAME_USER;
537 return True;
540 if (sid_check_is_unix_groups(domain_sid)) {
541 if (*domain_name == NULL) {
542 *domain_name = talloc_strdup(
543 mem_ctx, unix_groups_domain_name());
545 for (i=0; i<num_rids; i++) {
546 (*names)[i] = talloc_strdup(
547 (*names), gidtoname(rids[i]));
548 (*types)[i] = SID_NAME_DOM_GRP;
550 return True;
553 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
554 domain_name, *names, *types);
558 * Is the SID a domain as such? If yes, lookup its name.
561 static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
562 const char **name)
564 const char *tmp;
565 enum lsa_SidType type;
567 if (sid_check_is_domain(sid)) {
568 *name = talloc_strdup(mem_ctx, get_global_sam_name());
569 return True;
572 if (sid_check_is_builtin(sid)) {
573 *name = talloc_strdup(mem_ctx, builtin_domain_name());
574 return True;
577 if (sid_check_is_wellknown_domain(sid, &tmp)) {
578 *name = talloc_strdup(mem_ctx, tmp);
579 return True;
582 if (sid->num_auths != 4) {
583 /* This can't be a domain */
584 return False;
587 if (IS_DC) {
588 uint32 i, num_domains;
589 struct trustdom_info **domains;
591 /* This is relatively expensive, but it happens only on DCs
592 * and for SIDs that have 4 sub-authorities and thus look like
593 * domains */
595 if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx,
596 &num_domains,
597 &domains))) {
598 return False;
601 for (i=0; i<num_domains; i++) {
602 if (sid_equal(sid, &domains[i]->sid)) {
603 *name = talloc_strdup(mem_ctx,
604 domains[i]->name);
605 return True;
608 return False;
611 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
612 (type == SID_NAME_DOMAIN)) {
613 *name = tmp;
614 return True;
617 return False;
621 * This tries to implement the rather weird rules for the lsa_lookup level
622 * parameter.
624 * This is as close as we can get to what W2k3 does. With this we survive the
625 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
626 * different, but I assume that's just being too liberal. For example, W2k3
627 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
628 * whereas NT4 does the same as level 1 (I think). I did not fully test that
629 * with NT4, this is what w2k3 does.
631 * Level 1: Ask everywhere
632 * Level 2: Ask domain and trusted domains, no builtin and wkn
633 * Level 3: Only ask domain
634 * Level 4: W2k3ad: Only ask AD trusts
635 * Level 5: Don't lookup anything
636 * Level 6: Like 4
639 static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
641 int ret = False;
643 switch(level) {
644 case 1:
645 ret = True;
646 break;
647 case 2:
648 ret = (!sid_check_is_builtin(sid) &&
649 !sid_check_is_wellknown_domain(sid, NULL));
650 break;
651 case 3:
652 case 4:
653 case 6:
654 ret = sid_check_is_domain(sid);
655 break;
656 case 5:
657 ret = False;
658 break;
661 DEBUG(10, ("%s SID %s in level %d\n",
662 ret ? "Accepting" : "Rejecting",
663 sid_string_static(sid), level));
664 return ret;
668 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
669 * references to domains, it is explicitly made for this.
671 * This attempts to be as efficient as possible: It collects all SIDs
672 * belonging to a domain and hands them in bulk to the appropriate lookup
673 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
674 * *hugely* from this. Winbind is going to be extended with a lookup_rids
675 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
676 * appropriate DC.
679 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
680 const DOM_SID **sids, int level,
681 struct lsa_dom_info **ret_domains,
682 struct lsa_name_info **ret_names)
684 TALLOC_CTX *tmp_ctx;
685 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
686 struct lsa_name_info *name_infos;
687 struct lsa_dom_info *dom_infos = NULL;
689 int i, j;
691 if (!(tmp_ctx = talloc_new(mem_ctx))) {
692 DEBUG(0, ("talloc_new failed\n"));
693 return NT_STATUS_NO_MEMORY;
696 if (num_sids) {
697 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
698 if (name_infos == NULL) {
699 result = NT_STATUS_NO_MEMORY;
700 goto fail;
702 } else {
703 name_infos = NULL;
706 dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
707 MAX_REF_DOMAINS);
708 if (dom_infos == NULL) {
709 result = NT_STATUS_NO_MEMORY;
710 goto fail;
713 /* First build up the data structures:
715 * dom_infos is a list of domains referenced in the list of
716 * SIDs. Later we will walk the list of domains and look up the RIDs
717 * in bulk.
719 * name_infos is a shadow-copy of the SIDs array to collect the real
720 * data.
722 * dom_info->idxs is an index into the name_infos array. The
723 * difficulty we have here is that we need to keep the SIDs the client
724 * asked for in the same order for the reply
727 for (i=0; i<num_sids; i++) {
728 DOM_SID sid;
729 uint32 rid;
730 const char *domain_name = NULL;
732 sid_copy(&sid, sids[i]);
733 name_infos[i].type = SID_NAME_USE_NONE;
735 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
736 /* We can't push that through the normal lookup
737 * process, as this would reference illegal
738 * domains.
740 * For example S-1-5-32 would end up referencing
741 * domain S-1-5- with RID 32 which is clearly wrong.
743 if (domain_name == NULL) {
744 result = NT_STATUS_NO_MEMORY;
745 goto fail;
748 name_infos[i].rid = 0;
749 name_infos[i].type = SID_NAME_DOMAIN;
750 name_infos[i].name = NULL;
752 if (sid_check_is_builtin(&sid)) {
753 /* Yes, W2k3 returns "BUILTIN" both as domain
754 * and name here */
755 name_infos[i].name = talloc_strdup(
756 name_infos, builtin_domain_name());
757 if (name_infos[i].name == NULL) {
758 result = NT_STATUS_NO_MEMORY;
759 goto fail;
762 } else {
763 /* This is a normal SID with rid component */
764 if (!sid_split_rid(&sid, &rid)) {
765 result = NT_STATUS_INVALID_PARAMETER;
766 goto fail;
770 if (!check_dom_sid_to_level(&sid, level)) {
771 name_infos[i].rid = 0;
772 name_infos[i].type = SID_NAME_UNKNOWN;
773 name_infos[i].name = NULL;
774 continue;
777 for (j=0; j<MAX_REF_DOMAINS; j++) {
778 if (!dom_infos[j].valid) {
779 break;
781 if (sid_equal(&sid, &dom_infos[j].sid)) {
782 break;
786 if (j == MAX_REF_DOMAINS) {
787 /* TODO: What's the right error message here? */
788 result = NT_STATUS_NONE_MAPPED;
789 goto fail;
792 if (!dom_infos[j].valid) {
793 /* We found a domain not yet referenced, create a new
794 * ref. */
795 dom_infos[j].valid = True;
796 sid_copy(&dom_infos[j].sid, &sid);
798 if (domain_name != NULL) {
799 /* This name was being found above in the case
800 * when we found a domain SID */
801 dom_infos[j].name =
802 talloc_strdup(dom_infos, domain_name);
803 if (dom_infos[j].name == NULL) {
804 result = NT_STATUS_NO_MEMORY;
805 goto fail;
807 } else {
808 /* lookup_rids will take care of this */
809 dom_infos[j].name = NULL;
813 name_infos[i].dom_idx = j;
815 if (name_infos[i].type == SID_NAME_USE_NONE) {
816 name_infos[i].rid = rid;
818 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
819 &dom_infos[j].num_idxs);
821 if (dom_infos[j].idxs == NULL) {
822 result = NT_STATUS_NO_MEMORY;
823 goto fail;
828 /* Iterate over the domains found */
830 for (i=0; i<MAX_REF_DOMAINS; i++) {
831 uint32_t *rids;
832 const char *domain_name = NULL;
833 const char **names;
834 enum lsa_SidType *types;
835 struct lsa_dom_info *dom = &dom_infos[i];
837 if (!dom->valid) {
838 /* No domains left, we're done */
839 break;
842 if (dom->num_idxs) {
843 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
844 result = NT_STATUS_NO_MEMORY;
845 goto fail;
847 } else {
848 rids = NULL;
851 for (j=0; j<dom->num_idxs; j++) {
852 rids[j] = name_infos[dom->idxs[j]].rid;
855 if (!lookup_rids(tmp_ctx, &dom->sid,
856 dom->num_idxs, rids, &domain_name,
857 &names, &types)) {
858 result = NT_STATUS_NO_MEMORY;
859 goto fail;
862 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
863 result = NT_STATUS_NO_MEMORY;
864 goto fail;
867 for (j=0; j<dom->num_idxs; j++) {
868 int idx = dom->idxs[j];
869 name_infos[idx].type = types[j];
870 if (types[j] != SID_NAME_UNKNOWN) {
871 name_infos[idx].name =
872 talloc_strdup(name_infos, names[j]);
873 if (name_infos[idx].name == NULL) {
874 result = NT_STATUS_NO_MEMORY;
875 goto fail;
877 } else {
878 name_infos[idx].name = NULL;
883 *ret_domains = dom_infos;
884 *ret_names = name_infos;
885 return NT_STATUS_OK;
887 fail:
888 TALLOC_FREE(dom_infos);
889 TALLOC_FREE(name_infos);
890 TALLOC_FREE(tmp_ctx);
891 return result;
894 /*****************************************************************
895 *THE CANONICAL* convert SID to name function.
896 *****************************************************************/
898 BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
899 const char **ret_domain, const char **ret_name,
900 enum lsa_SidType *ret_type)
902 struct lsa_dom_info *domain;
903 struct lsa_name_info *name;
904 TALLOC_CTX *tmp_ctx;
905 BOOL ret = False;
907 if (!(tmp_ctx = talloc_new(mem_ctx))) {
908 DEBUG(0, ("talloc_new failed\n"));
909 return False;
912 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
913 &domain, &name))) {
914 goto done;
917 if (name->type == SID_NAME_UNKNOWN) {
918 goto done;
921 if ((ret_domain != NULL) &&
922 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
923 goto done;
926 if ((ret_name != NULL) &&
927 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
928 goto done;
931 if (ret_type != NULL) {
932 *ret_type = name->type;
935 ret = True;
937 done:
938 if (ret) {
939 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
940 sid_string_static(sid), domain->name,
941 name->name, name->type));
942 } else {
943 DEBUG(10, ("failed to lookup sid %s\n",
944 sid_string_static(sid)));
946 TALLOC_FREE(tmp_ctx);
947 return ret;
950 /*****************************************************************
951 Id mapping cache. This is to avoid Winbind mappings already
952 seen by smbd to be queried too frequently, keeping winbindd
953 busy, and blocking smbd while winbindd is busy with other
954 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
955 modified to use linked lists by jra.
956 *****************************************************************/
958 #define MAX_UID_SID_CACHE_SIZE 100
959 #define TURNOVER_UID_SID_CACHE_SIZE 10
960 #define MAX_GID_SID_CACHE_SIZE 100
961 #define TURNOVER_GID_SID_CACHE_SIZE 10
963 static size_t n_uid_sid_cache = 0;
964 static size_t n_gid_sid_cache = 0;
966 static struct uid_sid_cache {
967 struct uid_sid_cache *next, *prev;
968 uid_t uid;
969 DOM_SID sid;
970 enum lsa_SidType sidtype;
971 } *uid_sid_cache_head;
973 static struct gid_sid_cache {
974 struct gid_sid_cache *next, *prev;
975 gid_t gid;
976 DOM_SID sid;
977 enum lsa_SidType sidtype;
978 } *gid_sid_cache_head;
980 /*****************************************************************
981 Find a SID given a uid.
982 *****************************************************************/
984 static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
986 struct uid_sid_cache *pc;
988 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
989 if (pc->uid == uid) {
990 *psid = pc->sid;
991 DEBUG(3,("fetch sid from uid cache %u -> %s\n",
992 (unsigned int)uid, sid_string_static(psid)));
993 DLIST_PROMOTE(uid_sid_cache_head, pc);
994 return True;
997 return False;
1000 /*****************************************************************
1001 Find a uid given a SID.
1002 *****************************************************************/
1004 static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
1006 struct uid_sid_cache *pc;
1008 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
1009 if (sid_compare(&pc->sid, psid) == 0) {
1010 *puid = pc->uid;
1011 DEBUG(3,("fetch uid from cache %u -> %s\n",
1012 (unsigned int)*puid, sid_string_static(psid)));
1013 DLIST_PROMOTE(uid_sid_cache_head, pc);
1014 return True;
1017 return False;
1020 /*****************************************************************
1021 Store uid to SID mapping in cache.
1022 *****************************************************************/
1024 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
1026 struct uid_sid_cache *pc;
1028 /* do not store SIDs in the "Unix Group" domain */
1030 if ( sid_check_is_in_unix_users( psid ) )
1031 return;
1033 if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
1034 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
1035 struct uid_sid_cache *pc_next;
1036 size_t i;
1038 for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
1040 for(; pc; pc = pc_next) {
1041 pc_next = pc->next;
1042 DLIST_REMOVE(uid_sid_cache_head,pc);
1043 SAFE_FREE(pc);
1044 n_uid_sid_cache--;
1048 pc = SMB_MALLOC_P(struct uid_sid_cache);
1049 if (!pc)
1050 return;
1051 pc->uid = uid;
1052 sid_copy(&pc->sid, psid);
1053 DLIST_ADD(uid_sid_cache_head, pc);
1054 n_uid_sid_cache++;
1057 /*****************************************************************
1058 Find a SID given a gid.
1059 *****************************************************************/
1061 static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1063 struct gid_sid_cache *pc;
1065 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
1066 if (pc->gid == gid) {
1067 *psid = pc->sid;
1068 DEBUG(3,("fetch sid from gid cache %u -> %s\n",
1069 (unsigned int)gid, sid_string_static(psid)));
1070 DLIST_PROMOTE(gid_sid_cache_head, pc);
1071 return True;
1074 return False;
1077 /*****************************************************************
1078 Find a gid given a SID.
1079 *****************************************************************/
1081 static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1083 struct gid_sid_cache *pc;
1085 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
1086 if (sid_compare(&pc->sid, psid) == 0) {
1087 *pgid = pc->gid;
1088 DEBUG(3,("fetch gid from cache %u -> %s\n",
1089 (unsigned int)*pgid, sid_string_static(psid)));
1090 DLIST_PROMOTE(gid_sid_cache_head, pc);
1091 return True;
1094 return False;
1097 /*****************************************************************
1098 Store gid to SID mapping in cache.
1099 *****************************************************************/
1101 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1103 struct gid_sid_cache *pc;
1105 /* do not store SIDs in the "Unix Group" domain */
1107 if ( sid_check_is_in_unix_groups( psid ) )
1108 return;
1110 if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
1111 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
1112 struct gid_sid_cache *pc_next;
1113 size_t i;
1115 for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
1117 for(; pc; pc = pc_next) {
1118 pc_next = pc->next;
1119 DLIST_REMOVE(gid_sid_cache_head,pc);
1120 SAFE_FREE(pc);
1121 n_gid_sid_cache--;
1125 pc = SMB_MALLOC_P(struct gid_sid_cache);
1126 if (!pc)
1127 return;
1128 pc->gid = gid;
1129 sid_copy(&pc->sid, psid);
1130 DLIST_ADD(gid_sid_cache_head, pc);
1132 DEBUG(3,("store_gid_sid_cache: gid %u in cache -> %s\n", (unsigned int)gid,
1133 sid_string_static(psid)));
1135 n_gid_sid_cache++;
1138 /*****************************************************************
1139 *THE LEGACY* convert uid_t to SID function.
1140 *****************************************************************/
1142 static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
1144 uint32 rid;
1145 BOOL ret;
1147 ZERO_STRUCTP(psid);
1149 become_root();
1150 ret = pdb_uid_to_rid(uid, &rid);
1151 unbecome_root();
1153 if (ret) {
1154 /* This is a mapped user */
1155 sid_copy(psid, get_global_sam_sid());
1156 sid_append_rid(psid, rid);
1157 goto done;
1160 /* This is an unmapped user */
1162 uid_to_unix_users_sid(uid, psid);
1164 done:
1165 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1166 sid_string_static(psid)));
1168 store_uid_sid_cache(psid, uid);
1169 return;
1172 /*****************************************************************
1173 *THE LEGACY* convert gid_t to SID function.
1174 *****************************************************************/
1176 static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
1178 BOOL ret;
1180 ZERO_STRUCTP(psid);
1182 become_root();
1183 ret = pdb_gid_to_sid(gid, psid);
1184 unbecome_root();
1186 if (ret) {
1187 /* This is a mapped group */
1188 goto done;
1191 /* This is an unmapped group */
1193 gid_to_unix_groups_sid(gid, psid);
1195 done:
1196 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1197 sid_string_static(psid)));
1199 store_gid_sid_cache(psid, gid);
1200 return;
1203 /*****************************************************************
1204 *THE LEGACY* convert SID to uid function.
1205 *****************************************************************/
1207 static BOOL legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
1209 enum lsa_SidType type;
1210 uint32 rid;
1212 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1213 union unid_t id;
1214 BOOL ret;
1216 become_root();
1217 ret = pdb_sid_to_id(psid, &id, &type);
1218 unbecome_root();
1220 if (ret) {
1221 if (type != SID_NAME_USER) {
1222 DEBUG(5, ("sid %s is a %s, expected a user\n",
1223 sid_string_static(psid),
1224 sid_type_lookup(type)));
1225 return False;
1227 *puid = id.uid;
1228 goto done;
1231 /* This was ours, but it was not mapped. Fail */
1234 DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
1235 return False;
1237 done:
1238 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_static(psid),
1239 (unsigned int)*puid ));
1241 store_uid_sid_cache(psid, *puid);
1242 return True;
1245 /*****************************************************************
1246 *THE LEGACY* convert SID to gid function.
1247 Group mapping is used for gids that maps to Wellknown SIDs
1248 *****************************************************************/
1250 static BOOL legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1252 uint32 rid;
1253 GROUP_MAP map;
1254 union unid_t id;
1255 enum lsa_SidType type;
1257 if ((sid_check_is_in_builtin(psid) ||
1258 sid_check_is_in_wellknown_domain(psid))) {
1259 BOOL ret;
1261 become_root();
1262 ret = pdb_getgrsid(&map, *psid);
1263 unbecome_root();
1265 if (ret) {
1266 *pgid = map.gid;
1267 goto done;
1269 DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
1270 return False;
1273 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1274 BOOL ret;
1276 become_root();
1277 ret = pdb_sid_to_id(psid, &id, &type);
1278 unbecome_root();
1280 if (ret) {
1281 if ((type != SID_NAME_DOM_GRP) &&
1282 (type != SID_NAME_ALIAS)) {
1283 DEBUG(5, ("LEGACY: sid %s is a %s, expected a group\n",
1284 sid_string_static(psid),
1285 sid_type_lookup(type)));
1286 return False;
1288 *pgid = id.gid;
1289 goto done;
1292 /* This was ours, but it was not mapped. Fail */
1295 DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
1296 return False;
1298 done:
1299 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_static(psid),
1300 (unsigned int)*pgid ));
1302 store_gid_sid_cache(psid, *pgid);
1304 return True;
1307 /*****************************************************************
1308 *THE CANONICAL* convert uid_t to SID function.
1309 *****************************************************************/
1311 void uid_to_sid(DOM_SID *psid, uid_t uid)
1313 ZERO_STRUCTP(psid);
1315 if (fetch_sid_from_uid_cache(psid, uid))
1316 return;
1318 if (!winbind_uid_to_sid(psid, uid)) {
1319 if (!winbind_ping()) {
1320 legacy_uid_to_sid(psid, uid);
1321 return;
1324 DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n",
1325 uid));
1326 return;
1329 DEBUG(10,("uid %u -> sid %s\n",
1330 (unsigned int)uid, sid_string_static(psid)));
1332 store_uid_sid_cache(psid, uid);
1333 return;
1336 /*****************************************************************
1337 *THE CANONICAL* convert gid_t to SID function.
1338 *****************************************************************/
1340 void gid_to_sid(DOM_SID *psid, gid_t gid)
1342 ZERO_STRUCTP(psid);
1344 if (fetch_sid_from_gid_cache(psid, gid))
1345 return;
1347 if (!winbind_gid_to_sid(psid, gid)) {
1348 if (!winbind_ping()) {
1349 legacy_gid_to_sid(psid, gid);
1350 return;
1353 DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n",
1354 gid));
1355 return;
1358 DEBUG(10,("gid %u -> sid %s\n",
1359 (unsigned int)gid, sid_string_static(psid)));
1361 store_gid_sid_cache(psid, gid);
1362 return;
1365 /*****************************************************************
1366 *THE CANONICAL* convert SID to uid function.
1367 *****************************************************************/
1369 BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
1371 uint32 rid;
1372 gid_t gid;
1374 if (fetch_uid_from_cache(puid, psid))
1375 return True;
1377 if (fetch_gid_from_cache(&gid, psid)) {
1378 return False;
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_static(psid),
1389 (unsigned int)*puid ));
1390 return True;
1393 if (!winbind_sid_to_uid(puid, psid)) {
1394 if (!winbind_ping()) {
1395 return legacy_sid_to_uid(psid, puid);
1398 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1399 sid_string_static(psid)));
1400 return False;
1403 /* TODO: Here would be the place to allocate both a gid and a uid for
1404 * the SID in question */
1406 DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid),
1407 (unsigned int)*puid ));
1409 store_uid_sid_cache(psid, *puid);
1410 return True;
1413 /*****************************************************************
1414 *THE CANONICAL* convert SID to gid function.
1415 Group mapping is used for gids that maps to Wellknown SIDs
1416 *****************************************************************/
1418 BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1420 uint32 rid;
1421 uid_t uid;
1423 if (fetch_gid_from_cache(pgid, psid))
1424 return True;
1426 if (fetch_uid_from_cache(&uid, psid))
1427 return False;
1429 /* Optimize for the Unix Groups Domain
1430 * as the conversion is straightforward */
1431 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1432 gid_t gid = rid;
1433 *pgid = gid;
1435 /* return here, don't cache */
1436 DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid),
1437 (unsigned int)*pgid ));
1438 return True;
1441 /* Ask winbindd if it can map this sid to a gid.
1442 * (Idmap will check it is a valid SID and of the right type) */
1444 if ( !winbind_sid_to_gid(pgid, psid) ) {
1445 if (!winbind_ping()) {
1446 return legacy_sid_to_gid(psid, pgid);
1449 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1450 sid_string_static(psid)));
1451 return False;
1454 DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid),
1455 (unsigned int)*pgid ));
1457 store_gid_sid_cache(psid, *pgid);
1459 return True;