build: format the header check for netinet/ip.h more nicely
[Samba/bb.git] / source / passdb / lookup_sid.c
blob2a5eacd4601fc42c72ab71a5a8732bb715ba548d
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_EXPLICIT) && strequal(domain, unix_users_domain_name())) {
110 if (lookup_unix_user_name(name, &sid)) {
111 type = SID_NAME_USER;
112 goto ok;
114 TALLOC_FREE(tmp_ctx);
115 return false;
118 if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_groups_domain_name())) {
119 if (lookup_unix_group_name(name, &sid)) {
120 type = SID_NAME_DOM_GRP;
121 goto ok;
123 TALLOC_FREE(tmp_ctx);
124 return false;
127 if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
128 TALLOC_FREE(tmp_ctx);
129 return false;
132 /* Now the guesswork begins, we haven't been given an explicit
133 * domain. Try the sequence as documented on
134 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
135 * November 27, 2005 */
137 /* 1. well-known names */
139 if ((flags & LOOKUP_NAME_WKN) &&
140 lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
142 type = SID_NAME_WKN_GRP;
143 goto ok;
146 /* 2. Builtin domain as such */
148 if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
149 strequal(name, builtin_domain_name()))
151 /* Swap domain and name */
152 tmp = name; name = domain; domain = tmp;
153 sid_copy(&sid, &global_sid_Builtin);
154 type = SID_NAME_DOMAIN;
155 goto ok;
158 /* 3. Account domain */
160 if ((flags & LOOKUP_NAME_DOMAIN) &&
161 strequal(name, get_global_sam_name()))
163 if (!secrets_fetch_domain_sid(name, &sid)) {
164 DEBUG(3, ("Could not fetch my SID\n"));
165 TALLOC_FREE(tmp_ctx);
166 return false;
168 /* Swap domain and name */
169 tmp = name; name = domain; domain = tmp;
170 type = SID_NAME_DOMAIN;
171 goto ok;
174 /* 4. Primary domain */
176 if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
177 strequal(name, lp_workgroup()))
179 if (!secrets_fetch_domain_sid(name, &sid)) {
180 DEBUG(3, ("Could not fetch the domain SID\n"));
181 TALLOC_FREE(tmp_ctx);
182 return false;
184 /* Swap domain and name */
185 tmp = name; name = domain; domain = tmp;
186 type = SID_NAME_DOMAIN;
187 goto ok;
190 /* 5. Trusted domains as such, to me it looks as if members don't do
191 this, tested an XP workstation in a NT domain -- vl */
193 if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
194 (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
196 /* Swap domain and name */
197 tmp = name; name = domain; domain = tmp;
198 type = SID_NAME_DOMAIN;
199 goto ok;
202 /* 6. Builtin aliases */
204 if ((flags & LOOKUP_NAME_BUILTIN) &&
205 lookup_builtin_name(name, &rid))
207 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
208 sid_copy(&sid, &global_sid_Builtin);
209 sid_append_rid(&sid, rid);
210 type = SID_NAME_ALIAS;
211 goto ok;
214 /* 7. Local systems' SAM (DCs don't have a local SAM) */
215 /* 8. Primary SAM (On members, this is the domain) */
217 /* Both cases are done by looking at our passdb */
219 if ((flags & LOOKUP_NAME_DOMAIN) &&
220 lookup_global_sam_name(name, flags, &rid, &type))
222 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
223 sid_copy(&sid, get_global_sam_sid());
224 sid_append_rid(&sid, rid);
225 goto ok;
228 /* Now our local possibilities are exhausted. */
230 if (!(flags & LOOKUP_NAME_REMOTE)) {
231 TALLOC_FREE(tmp_ctx);
232 return false;
235 /* If we are not a DC, we have to ask in our primary domain. Let
236 * winbind do that. */
238 if (!IS_DC &&
239 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
240 domain = talloc_strdup(tmp_ctx, lp_workgroup());
241 goto ok;
244 /* 9. Trusted domains */
246 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
247 * that (yet), but give it a chance. */
249 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
250 DOM_SID dom_sid;
251 uint32 tmp_rid;
252 enum lsa_SidType domain_type;
254 if (type == SID_NAME_DOMAIN) {
255 /* Swap name and type */
256 tmp = name; name = domain; domain = tmp;
257 goto ok;
260 /* Here we have to cope with a little deficiency in the
261 * winbind API: We have to ask it again for the name of the
262 * domain it figured out itself. Maybe fix that later... */
264 sid_copy(&dom_sid, &sid);
265 sid_split_rid(&dom_sid, &tmp_rid);
267 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
268 &domain_type) ||
269 (domain_type != SID_NAME_DOMAIN)) {
270 DEBUG(2, ("winbind could not find the domain's name "
271 "it just looked up for us\n"));
272 TALLOC_FREE(tmp_ctx);
273 return false;
275 goto ok;
278 /* 10. Don't translate */
280 /* 11. Ok, windows would end here. Samba has two more options:
281 Unmapped users and unmapped groups */
283 if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_user_name(name, &sid)) {
284 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
285 type = SID_NAME_USER;
286 goto ok;
289 if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_group_name(name, &sid)) {
290 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
291 type = SID_NAME_DOM_GRP;
292 goto ok;
296 * Ok, all possibilities tried. Fail.
299 TALLOC_FREE(tmp_ctx);
300 return false;
303 if ((domain == NULL) || (name == NULL)) {
304 DEBUG(0, ("talloc failed\n"));
305 TALLOC_FREE(tmp_ctx);
306 return false;
310 * Hand over the results to the talloc context we've been given.
313 if ((ret_name != NULL) &&
314 !(*ret_name = talloc_strdup(mem_ctx, name))) {
315 DEBUG(0, ("talloc failed\n"));
316 TALLOC_FREE(tmp_ctx);
317 return false;
320 if (ret_domain != NULL) {
321 char *tmp_dom;
322 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
323 DEBUG(0, ("talloc failed\n"));
324 TALLOC_FREE(tmp_ctx);
325 return false;
327 strupper_m(tmp_dom);
328 *ret_domain = tmp_dom;
331 if (ret_sid != NULL) {
332 sid_copy(ret_sid, &sid);
335 if (ret_type != NULL) {
336 *ret_type = type;
339 TALLOC_FREE(tmp_ctx);
340 return true;
343 /************************************************************************
344 Names from smb.conf can be unqualified. eg. valid users = foo
345 These names should never map to a remote name. Try global_sam_name()\foo,
346 and then "Unix Users"\foo (or "Unix Groups"\foo).
347 ************************************************************************/
349 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
350 const char *full_name, int flags,
351 const char **ret_domain, const char **ret_name,
352 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
354 char *qualified_name;
355 const char *p;
357 /* NB. No winbindd_separator here as lookup_name needs \\' */
358 if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
360 /* The name is already qualified with a domain. */
362 if (*lp_winbind_separator() != '\\') {
363 char *tmp;
365 /* lookup_name() needs '\\' as a separator */
367 tmp = talloc_strdup(mem_ctx, full_name);
368 if (!tmp) {
369 return false;
371 tmp[p - full_name] = '\\';
372 full_name = tmp;
375 return lookup_name(mem_ctx, full_name, flags,
376 ret_domain, ret_name,
377 ret_sid, ret_type);
380 /* Try with our own SAM name. */
381 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
382 get_global_sam_name(),
383 full_name );
384 if (!qualified_name) {
385 return false;
388 if (lookup_name(mem_ctx, qualified_name, flags,
389 ret_domain, ret_name,
390 ret_sid, ret_type)) {
391 return true;
394 /* Finally try with "Unix Users" or "Unix Group" */
395 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
396 flags & LOOKUP_NAME_GROUP ?
397 unix_groups_domain_name() :
398 unix_users_domain_name(),
399 full_name );
400 if (!qualified_name) {
401 return false;
404 return lookup_name(mem_ctx, qualified_name, flags,
405 ret_domain, ret_name,
406 ret_sid, ret_type);
409 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
410 const DOM_SID *domain_sid,
411 int num_rids, uint32 *rids,
412 const char **domain_name,
413 const char **names, enum lsa_SidType *types)
415 int i;
416 const char **my_names;
417 enum lsa_SidType *my_types;
418 TALLOC_CTX *tmp_ctx;
420 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
421 return false;
424 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
425 domain_name, &my_names, &my_types)) {
426 *domain_name = "";
427 for (i=0; i<num_rids; i++) {
428 names[i] = "";
429 types[i] = SID_NAME_UNKNOWN;
431 TALLOC_FREE(tmp_ctx);
432 return true;
435 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
436 TALLOC_FREE(tmp_ctx);
437 return false;
441 * winbind_lookup_rids allocates its own array. We've been given the
442 * array, so copy it over
445 for (i=0; i<num_rids; i++) {
446 if (my_names[i] == NULL) {
447 TALLOC_FREE(tmp_ctx);
448 return false;
450 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
451 TALLOC_FREE(tmp_ctx);
452 return false;
454 types[i] = my_types[i];
456 TALLOC_FREE(tmp_ctx);
457 return true;
460 static bool lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
461 int num_rids, uint32_t *rids,
462 const char **domain_name,
463 const char ***names, enum lsa_SidType **types)
465 int i;
467 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
468 sid_string_dbg(domain_sid)));
470 if (num_rids) {
471 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
472 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
474 if ((*names == NULL) || (*types == NULL)) {
475 return false;
477 } else {
478 *names = NULL;
479 *types = NULL;
482 if (sid_check_is_domain(domain_sid)) {
483 NTSTATUS result;
485 if (*domain_name == NULL) {
486 *domain_name = talloc_strdup(
487 mem_ctx, get_global_sam_name());
490 if (*domain_name == NULL) {
491 return false;
494 become_root();
495 result = pdb_lookup_rids(domain_sid, num_rids, rids,
496 *names, *types);
497 unbecome_root();
499 return (NT_STATUS_IS_OK(result) ||
500 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
501 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
504 if (sid_check_is_builtin(domain_sid)) {
506 if (*domain_name == NULL) {
507 *domain_name = talloc_strdup(
508 mem_ctx, builtin_domain_name());
511 if (*domain_name == NULL) {
512 return false;
515 for (i=0; i<num_rids; i++) {
516 if (lookup_builtin_rid(*names, rids[i],
517 &(*names)[i])) {
518 if ((*names)[i] == NULL) {
519 return false;
521 (*types)[i] = SID_NAME_ALIAS;
522 } else {
523 (*types)[i] = SID_NAME_UNKNOWN;
526 return true;
529 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
530 for (i=0; i<num_rids; i++) {
531 DOM_SID sid;
532 sid_copy(&sid, domain_sid);
533 sid_append_rid(&sid, rids[i]);
534 if (lookup_wellknown_sid(mem_ctx, &sid,
535 domain_name, &(*names)[i])) {
536 if ((*names)[i] == NULL) {
537 return false;
539 (*types)[i] = SID_NAME_WKN_GRP;
540 } else {
541 (*types)[i] = SID_NAME_UNKNOWN;
544 return true;
547 if (sid_check_is_unix_users(domain_sid)) {
548 if (*domain_name == NULL) {
549 *domain_name = talloc_strdup(
550 mem_ctx, unix_users_domain_name());
551 if (*domain_name == NULL) {
552 return false;
555 for (i=0; i<num_rids; i++) {
556 (*names)[i] = talloc_strdup(
557 (*names), uidtoname(rids[i]));
558 if ((*names)[i] == NULL) {
559 return false;
561 (*types)[i] = SID_NAME_USER;
563 return true;
566 if (sid_check_is_unix_groups(domain_sid)) {
567 if (*domain_name == NULL) {
568 *domain_name = talloc_strdup(
569 mem_ctx, unix_groups_domain_name());
570 if (*domain_name == NULL) {
571 return false;
574 for (i=0; i<num_rids; i++) {
575 (*names)[i] = talloc_strdup(
576 (*names), gidtoname(rids[i]));
577 if ((*names)[i] == NULL) {
578 return false;
580 (*types)[i] = SID_NAME_DOM_GRP;
582 return true;
585 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
586 domain_name, *names, *types);
590 * Is the SID a domain as such? If yes, lookup its name.
593 static bool lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
594 const char **name)
596 const char *tmp;
597 enum lsa_SidType type;
599 if (sid_check_is_domain(sid)) {
600 *name = talloc_strdup(mem_ctx, get_global_sam_name());
601 return true;
604 if (sid_check_is_builtin(sid)) {
605 *name = talloc_strdup(mem_ctx, builtin_domain_name());
606 return true;
609 if (sid_check_is_wellknown_domain(sid, &tmp)) {
610 *name = talloc_strdup(mem_ctx, tmp);
611 return true;
614 if (sid_check_is_unix_users(sid)) {
615 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
616 return true;
619 if (sid_check_is_unix_groups(sid)) {
620 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
621 return true;
624 if (sid->num_auths != 4) {
625 /* This can't be a domain */
626 return false;
629 if (IS_DC) {
630 uint32 i, num_domains;
631 struct trustdom_info **domains;
633 /* This is relatively expensive, but it happens only on DCs
634 * and for SIDs that have 4 sub-authorities and thus look like
635 * domains */
637 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
638 &num_domains,
639 &domains))) {
640 return false;
643 for (i=0; i<num_domains; i++) {
644 if (sid_equal(sid, &domains[i]->sid)) {
645 *name = talloc_strdup(mem_ctx,
646 domains[i]->name);
647 return true;
650 return false;
653 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
654 (type == SID_NAME_DOMAIN)) {
655 *name = tmp;
656 return true;
659 return false;
663 * This tries to implement the rather weird rules for the lsa_lookup level
664 * parameter.
666 * This is as close as we can get to what W2k3 does. With this we survive the
667 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
668 * different, but I assume that's just being too liberal. For example, W2k3
669 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
670 * whereas NT4 does the same as level 1 (I think). I did not fully test that
671 * with NT4, this is what w2k3 does.
673 * Level 1: Ask everywhere
674 * Level 2: Ask domain and trusted domains, no builtin and wkn
675 * Level 3: Only ask domain
676 * Level 4: W2k3ad: Only ask AD trusts
677 * Level 5: Only ask transitive forest trusts
678 * Level 6: Like 4
681 static bool check_dom_sid_to_level(const DOM_SID *sid, int level)
683 int ret = false;
685 switch(level) {
686 case 1:
687 ret = true;
688 break;
689 case 2:
690 ret = (!sid_check_is_builtin(sid) &&
691 !sid_check_is_wellknown_domain(sid, NULL));
692 break;
693 case 3:
694 case 4:
695 case 6:
696 ret = sid_check_is_domain(sid);
697 break;
698 case 5:
699 ret = false;
700 break;
703 DEBUG(10, ("%s SID %s in level %d\n",
704 ret ? "Accepting" : "Rejecting",
705 sid_string_dbg(sid), level));
706 return ret;
710 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
711 * references to domains, it is explicitly made for this.
713 * This attempts to be as efficient as possible: It collects all SIDs
714 * belonging to a domain and hands them in bulk to the appropriate lookup
715 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
716 * *hugely* from this. Winbind is going to be extended with a lookup_rids
717 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
718 * appropriate DC.
721 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
722 const DOM_SID **sids, int level,
723 struct lsa_dom_info **ret_domains,
724 struct lsa_name_info **ret_names)
726 TALLOC_CTX *tmp_ctx;
727 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
728 struct lsa_name_info *name_infos;
729 struct lsa_dom_info *dom_infos = NULL;
731 int i, j;
733 if (!(tmp_ctx = talloc_new(mem_ctx))) {
734 DEBUG(0, ("talloc_new failed\n"));
735 return NT_STATUS_NO_MEMORY;
738 if (num_sids) {
739 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
740 if (name_infos == NULL) {
741 result = NT_STATUS_NO_MEMORY;
742 goto fail;
744 } else {
745 name_infos = NULL;
748 dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
749 MAX_REF_DOMAINS);
750 if (dom_infos == NULL) {
751 result = NT_STATUS_NO_MEMORY;
752 goto fail;
755 /* First build up the data structures:
757 * dom_infos is a list of domains referenced in the list of
758 * SIDs. Later we will walk the list of domains and look up the RIDs
759 * in bulk.
761 * name_infos is a shadow-copy of the SIDs array to collect the real
762 * data.
764 * dom_info->idxs is an index into the name_infos array. The
765 * difficulty we have here is that we need to keep the SIDs the client
766 * asked for in the same order for the reply
769 for (i=0; i<num_sids; i++) {
770 DOM_SID sid;
771 uint32 rid;
772 const char *domain_name = NULL;
774 sid_copy(&sid, sids[i]);
775 name_infos[i].type = SID_NAME_USE_NONE;
777 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
778 /* We can't push that through the normal lookup
779 * process, as this would reference illegal
780 * domains.
782 * For example S-1-5-32 would end up referencing
783 * domain S-1-5- with RID 32 which is clearly wrong.
785 if (domain_name == NULL) {
786 result = NT_STATUS_NO_MEMORY;
787 goto fail;
790 name_infos[i].rid = 0;
791 name_infos[i].type = SID_NAME_DOMAIN;
792 name_infos[i].name = NULL;
794 if (sid_check_is_builtin(&sid)) {
795 /* Yes, W2k3 returns "BUILTIN" both as domain
796 * and name here */
797 name_infos[i].name = talloc_strdup(
798 name_infos, builtin_domain_name());
799 if (name_infos[i].name == NULL) {
800 result = NT_STATUS_NO_MEMORY;
801 goto fail;
804 } else {
805 /* This is a normal SID with rid component */
806 if (!sid_split_rid(&sid, &rid)) {
807 result = NT_STATUS_INVALID_PARAMETER;
808 goto fail;
812 if (!check_dom_sid_to_level(&sid, level)) {
813 name_infos[i].rid = 0;
814 name_infos[i].type = SID_NAME_UNKNOWN;
815 name_infos[i].name = NULL;
816 continue;
819 for (j=0; j<MAX_REF_DOMAINS; j++) {
820 if (!dom_infos[j].valid) {
821 break;
823 if (sid_equal(&sid, &dom_infos[j].sid)) {
824 break;
828 if (j == MAX_REF_DOMAINS) {
829 /* TODO: What's the right error message here? */
830 result = NT_STATUS_NONE_MAPPED;
831 goto fail;
834 if (!dom_infos[j].valid) {
835 /* We found a domain not yet referenced, create a new
836 * ref. */
837 dom_infos[j].valid = true;
838 sid_copy(&dom_infos[j].sid, &sid);
840 if (domain_name != NULL) {
841 /* This name was being found above in the case
842 * when we found a domain SID */
843 dom_infos[j].name =
844 talloc_strdup(dom_infos, domain_name);
845 if (dom_infos[j].name == NULL) {
846 result = NT_STATUS_NO_MEMORY;
847 goto fail;
849 } else {
850 /* lookup_rids will take care of this */
851 dom_infos[j].name = NULL;
855 name_infos[i].dom_idx = j;
857 if (name_infos[i].type == SID_NAME_USE_NONE) {
858 name_infos[i].rid = rid;
860 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
861 &dom_infos[j].num_idxs);
863 if (dom_infos[j].idxs == NULL) {
864 result = NT_STATUS_NO_MEMORY;
865 goto fail;
870 /* Iterate over the domains found */
872 for (i=0; i<MAX_REF_DOMAINS; i++) {
873 uint32_t *rids;
874 const char *domain_name = NULL;
875 const char **names;
876 enum lsa_SidType *types;
877 struct lsa_dom_info *dom = &dom_infos[i];
879 if (!dom->valid) {
880 /* No domains left, we're done */
881 break;
884 if (dom->num_idxs) {
885 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
886 result = NT_STATUS_NO_MEMORY;
887 goto fail;
889 } else {
890 rids = NULL;
893 for (j=0; j<dom->num_idxs; j++) {
894 rids[j] = name_infos[dom->idxs[j]].rid;
897 if (!lookup_rids(tmp_ctx, &dom->sid,
898 dom->num_idxs, rids, &domain_name,
899 &names, &types)) {
900 result = NT_STATUS_NO_MEMORY;
901 goto fail;
904 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
905 result = NT_STATUS_NO_MEMORY;
906 goto fail;
909 for (j=0; j<dom->num_idxs; j++) {
910 int idx = dom->idxs[j];
911 name_infos[idx].type = types[j];
912 if (types[j] != SID_NAME_UNKNOWN) {
913 name_infos[idx].name =
914 talloc_strdup(name_infos, names[j]);
915 if (name_infos[idx].name == NULL) {
916 result = NT_STATUS_NO_MEMORY;
917 goto fail;
919 } else {
920 name_infos[idx].name = NULL;
925 *ret_domains = dom_infos;
926 *ret_names = name_infos;
927 TALLOC_FREE(tmp_ctx);
928 return NT_STATUS_OK;
930 fail:
931 TALLOC_FREE(dom_infos);
932 TALLOC_FREE(name_infos);
933 TALLOC_FREE(tmp_ctx);
934 return result;
937 /*****************************************************************
938 *THE CANONICAL* convert SID to name function.
939 *****************************************************************/
941 bool lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
942 const char **ret_domain, const char **ret_name,
943 enum lsa_SidType *ret_type)
945 struct lsa_dom_info *domain;
946 struct lsa_name_info *name;
947 TALLOC_CTX *tmp_ctx;
948 bool ret = false;
950 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
952 if (!(tmp_ctx = talloc_new(mem_ctx))) {
953 DEBUG(0, ("talloc_new failed\n"));
954 return false;
957 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
958 &domain, &name))) {
959 goto done;
962 if (name->type == SID_NAME_UNKNOWN) {
963 goto done;
966 if ((ret_domain != NULL) &&
967 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
968 goto done;
971 if ((ret_name != NULL) &&
972 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
973 goto done;
976 if (ret_type != NULL) {
977 *ret_type = name->type;
980 ret = true;
982 done:
983 if (ret) {
984 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
985 domain->name, name->name, name->type));
986 } else {
987 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
989 TALLOC_FREE(tmp_ctx);
990 return ret;
993 /*****************************************************************
994 Id mapping cache. This is to avoid Winbind mappings already
995 seen by smbd to be queried too frequently, keeping winbindd
996 busy, and blocking smbd while winbindd is busy with other
997 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
998 modified to use linked lists by jra.
999 *****************************************************************/
1001 /*****************************************************************
1002 Find a SID given a uid.
1003 *****************************************************************/
1005 static bool fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
1007 DATA_BLOB cache_value;
1009 if (!memcache_lookup(NULL, UID_SID_CACHE,
1010 data_blob_const(&uid, sizeof(uid)),
1011 &cache_value)) {
1012 return false;
1015 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1016 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1017 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, 0));
1019 return true;
1022 /*****************************************************************
1023 Find a uid given a SID.
1024 *****************************************************************/
1026 static bool fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
1028 DATA_BLOB cache_value;
1030 if (!memcache_lookup(NULL, SID_UID_CACHE,
1031 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1032 &cache_value)) {
1033 return false;
1036 SMB_ASSERT(cache_value.length == sizeof(*puid));
1037 memcpy(puid, cache_value.data, sizeof(*puid));
1039 return true;
1042 /*****************************************************************
1043 Store uid to SID mapping in cache.
1044 *****************************************************************/
1046 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
1048 memcache_add(NULL, SID_UID_CACHE,
1049 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1050 data_blob_const(&uid, sizeof(uid)));
1051 memcache_add(NULL, UID_SID_CACHE,
1052 data_blob_const(&uid, sizeof(uid)),
1053 data_blob_const(psid, ndr_size_dom_sid(psid, 0)));
1056 /*****************************************************************
1057 Find a SID given a gid.
1058 *****************************************************************/
1060 static bool fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1062 DATA_BLOB cache_value;
1064 if (!memcache_lookup(NULL, GID_SID_CACHE,
1065 data_blob_const(&gid, sizeof(gid)),
1066 &cache_value)) {
1067 return false;
1070 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1071 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1072 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, 0));
1074 return true;
1077 /*****************************************************************
1078 Find a gid given a SID.
1079 *****************************************************************/
1081 static bool fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1083 DATA_BLOB cache_value;
1085 if (!memcache_lookup(NULL, SID_UID_CACHE,
1086 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1087 &cache_value)) {
1088 return false;
1091 SMB_ASSERT(cache_value.length == sizeof(*pgid));
1092 memcpy(pgid, cache_value.data, sizeof(*pgid));
1094 return true;
1097 /*****************************************************************
1098 Store gid to SID mapping in cache.
1099 *****************************************************************/
1101 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1103 memcache_add(NULL, SID_GID_CACHE,
1104 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1105 data_blob_const(&gid, sizeof(gid)));
1106 memcache_add(NULL, GID_SID_CACHE,
1107 data_blob_const(&gid, sizeof(gid)),
1108 data_blob_const(psid, ndr_size_dom_sid(psid, 0)));
1111 /*****************************************************************
1112 *THE LEGACY* convert uid_t to SID function.
1113 *****************************************************************/
1115 static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
1117 uint32 rid;
1118 bool ret;
1120 ZERO_STRUCTP(psid);
1122 become_root();
1123 ret = pdb_uid_to_rid(uid, &rid);
1124 unbecome_root();
1126 if (ret) {
1127 /* This is a mapped user */
1128 sid_copy(psid, get_global_sam_sid());
1129 sid_append_rid(psid, rid);
1130 goto done;
1133 /* This is an unmapped user */
1135 uid_to_unix_users_sid(uid, psid);
1137 done:
1138 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1139 sid_string_dbg(psid)));
1141 store_uid_sid_cache(psid, uid);
1142 return;
1145 /*****************************************************************
1146 *THE LEGACY* convert gid_t to SID function.
1147 *****************************************************************/
1149 static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
1151 bool ret;
1153 ZERO_STRUCTP(psid);
1155 become_root();
1156 ret = pdb_gid_to_sid(gid, psid);
1157 unbecome_root();
1159 if (ret) {
1160 /* This is a mapped group */
1161 goto done;
1164 /* This is an unmapped group */
1166 gid_to_unix_groups_sid(gid, psid);
1168 done:
1169 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1170 sid_string_dbg(psid)));
1172 store_gid_sid_cache(psid, gid);
1173 return;
1176 /*****************************************************************
1177 *THE LEGACY* convert SID to uid function.
1178 *****************************************************************/
1180 static bool legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
1182 enum lsa_SidType type;
1183 uint32 rid;
1185 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1186 union unid_t id;
1187 bool ret;
1189 become_root();
1190 ret = pdb_sid_to_id(psid, &id, &type);
1191 unbecome_root();
1193 if (ret) {
1194 if (type != SID_NAME_USER) {
1195 DEBUG(5, ("sid %s is a %s, expected a user\n",
1196 sid_string_dbg(psid),
1197 sid_type_lookup(type)));
1198 return false;
1200 *puid = id.uid;
1201 goto done;
1204 /* This was ours, but it was not mapped. Fail */
1207 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1208 sid_string_dbg(psid)));
1209 return false;
1211 done:
1212 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_dbg(psid),
1213 (unsigned int)*puid ));
1215 store_uid_sid_cache(psid, *puid);
1216 return true;
1219 /*****************************************************************
1220 *THE LEGACY* convert SID to gid function.
1221 Group mapping is used for gids that maps to Wellknown SIDs
1222 *****************************************************************/
1224 static bool legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1226 uint32 rid;
1227 GROUP_MAP map;
1228 union unid_t id;
1229 enum lsa_SidType type;
1231 if ((sid_check_is_in_builtin(psid) ||
1232 sid_check_is_in_wellknown_domain(psid))) {
1233 bool ret;
1235 become_root();
1236 ret = pdb_getgrsid(&map, *psid);
1237 unbecome_root();
1239 if (ret) {
1240 *pgid = map.gid;
1241 goto done;
1243 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1244 sid_string_dbg(psid)));
1245 return false;
1248 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1249 bool ret;
1251 become_root();
1252 ret = pdb_sid_to_id(psid, &id, &type);
1253 unbecome_root();
1255 if (ret) {
1256 if ((type != SID_NAME_DOM_GRP) &&
1257 (type != SID_NAME_ALIAS)) {
1258 DEBUG(5, ("LEGACY: sid %s is a %s, expected "
1259 "a group\n", sid_string_dbg(psid),
1260 sid_type_lookup(type)));
1261 return false;
1263 *pgid = id.gid;
1264 goto done;
1267 /* This was ours, but it was not mapped. Fail */
1270 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1271 sid_string_dbg(psid)));
1272 return false;
1274 done:
1275 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_dbg(psid),
1276 (unsigned int)*pgid ));
1278 store_gid_sid_cache(psid, *pgid);
1280 return true;
1283 /*****************************************************************
1284 *THE CANONICAL* convert uid_t to SID function.
1285 *****************************************************************/
1287 void uid_to_sid(DOM_SID *psid, uid_t uid)
1289 bool expired = true;
1290 bool ret;
1291 ZERO_STRUCTP(psid);
1293 if (fetch_sid_from_uid_cache(psid, uid))
1294 return;
1296 /* Check the winbindd cache directly. */
1297 ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1299 if (ret && !expired && is_null_sid(psid)) {
1301 * Negative cache entry, we already asked.
1302 * do legacy.
1304 legacy_uid_to_sid(psid, uid);
1305 return;
1308 if (!ret || expired) {
1309 /* Not in cache. Ask winbindd. */
1310 if (!winbind_uid_to_sid(psid, uid)) {
1312 * We shouldn't return the NULL SID
1313 * here if winbind was running and
1314 * couldn't map, as winbind will have
1315 * added a negative entry that will
1316 * cause us to go though the
1317 * legacy_uid_to_sid()
1318 * function anyway in the case above
1319 * the next time we ask.
1321 DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1322 "for uid %u\n", uid));
1324 legacy_uid_to_sid(psid, uid);
1325 return;
1329 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1330 sid_string_dbg(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 bool expired = true;
1343 bool ret;
1344 ZERO_STRUCTP(psid);
1346 if (fetch_sid_from_gid_cache(psid, gid))
1347 return;
1349 /* Check the winbindd cache directly. */
1350 ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1352 if (ret && !expired && is_null_sid(psid)) {
1354 * Negative cache entry, we already asked.
1355 * do legacy.
1357 legacy_gid_to_sid(psid, gid);
1358 return;
1361 if (!ret || expired) {
1362 /* Not in cache. Ask winbindd. */
1363 if (!winbind_gid_to_sid(psid, gid)) {
1365 * We shouldn't return the NULL SID
1366 * here if winbind was running and
1367 * couldn't map, as winbind will have
1368 * added a negative entry that will
1369 * cause us to go though the
1370 * legacy_gid_to_sid()
1371 * function anyway in the case above
1372 * the next time we ask.
1374 DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1375 "for gid %u\n", gid));
1377 legacy_gid_to_sid(psid, gid);
1378 return;
1382 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1383 sid_string_dbg(psid)));
1385 store_gid_sid_cache(psid, gid);
1386 return;
1389 /*****************************************************************
1390 *THE CANONICAL* convert SID to uid function.
1391 *****************************************************************/
1393 bool sid_to_uid(const DOM_SID *psid, uid_t *puid)
1395 bool expired = true;
1396 bool ret;
1397 uint32 rid;
1398 gid_t gid;
1400 if (fetch_uid_from_cache(puid, psid))
1401 return true;
1403 if (fetch_gid_from_cache(&gid, psid)) {
1404 return false;
1407 /* Optimize for the Unix Users Domain
1408 * as the conversion is straightforward */
1409 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1410 uid_t uid = rid;
1411 *puid = uid;
1413 /* return here, don't cache */
1414 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1415 (unsigned int)*puid ));
1416 return true;
1419 /* Check the winbindd cache directly. */
1420 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1422 if (ret && !expired && (*puid == (uid_t)-1)) {
1424 * Negative cache entry, we already asked.
1425 * do legacy.
1427 return legacy_sid_to_uid(psid, puid);
1430 if (!ret || expired) {
1431 /* Not in cache. Ask winbindd. */
1432 if (!winbind_sid_to_uid(puid, psid)) {
1433 if (!winbind_ping()) {
1434 return legacy_sid_to_uid(psid, puid);
1437 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1438 sid_string_dbg(psid)));
1439 return false;
1443 /* TODO: Here would be the place to allocate both a gid and a uid for
1444 * the SID in question */
1446 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1447 (unsigned int)*puid ));
1449 store_uid_sid_cache(psid, *puid);
1450 return true;
1453 /*****************************************************************
1454 *THE CANONICAL* convert SID to gid function.
1455 Group mapping is used for gids that maps to Wellknown SIDs
1456 *****************************************************************/
1458 bool sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1460 bool expired = true;
1461 bool ret;
1462 uint32 rid;
1463 uid_t uid;
1465 if (fetch_gid_from_cache(pgid, psid))
1466 return true;
1468 if (fetch_uid_from_cache(&uid, psid))
1469 return false;
1471 /* Optimize for the Unix Groups Domain
1472 * as the conversion is straightforward */
1473 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1474 gid_t gid = rid;
1475 *pgid = gid;
1477 /* return here, don't cache */
1478 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1479 (unsigned int)*pgid ));
1480 return true;
1483 /* Check the winbindd cache directly. */
1484 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1486 if (ret && !expired && (*pgid == (gid_t)-1)) {
1488 * Negative cache entry, we already asked.
1489 * do legacy.
1491 return legacy_sid_to_gid(psid, pgid);
1494 if (!ret || expired) {
1495 /* Not in cache or negative. Ask winbindd. */
1496 /* Ask winbindd if it can map this sid to a gid.
1497 * (Idmap will check it is a valid SID and of the right type) */
1499 if ( !winbind_sid_to_gid(pgid, psid) ) {
1500 if (!winbind_ping()) {
1501 return legacy_sid_to_gid(psid, pgid);
1504 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1505 sid_string_dbg(psid)));
1506 return false;
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;