s3:docs: Document "ldap page size".
[Samba/bb.git] / source / passdb / lookup_sid.c
blob10f6cc6830f2a1c0d6a157c440a9003b94450641
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_ZERO_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;
478 for (i = 0; i < num_rids; i++)
479 (*types)[i] = SID_NAME_UNKNOWN;
480 } else {
481 *names = NULL;
482 *types = NULL;
485 if (sid_check_is_domain(domain_sid)) {
486 NTSTATUS result;
488 if (*domain_name == NULL) {
489 *domain_name = talloc_strdup(
490 mem_ctx, get_global_sam_name());
493 if (*domain_name == NULL) {
494 return false;
497 become_root();
498 result = pdb_lookup_rids(domain_sid, num_rids, rids,
499 *names, *types);
500 unbecome_root();
502 return (NT_STATUS_IS_OK(result) ||
503 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
504 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
507 if (sid_check_is_builtin(domain_sid)) {
509 if (*domain_name == NULL) {
510 *domain_name = talloc_strdup(
511 mem_ctx, builtin_domain_name());
514 if (*domain_name == NULL) {
515 return false;
518 for (i=0; i<num_rids; i++) {
519 if (lookup_builtin_rid(*names, rids[i],
520 &(*names)[i])) {
521 if ((*names)[i] == NULL) {
522 return false;
524 (*types)[i] = SID_NAME_ALIAS;
525 } else {
526 (*types)[i] = SID_NAME_UNKNOWN;
529 return true;
532 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
533 for (i=0; i<num_rids; i++) {
534 DOM_SID sid;
535 sid_copy(&sid, domain_sid);
536 sid_append_rid(&sid, rids[i]);
537 if (lookup_wellknown_sid(mem_ctx, &sid,
538 domain_name, &(*names)[i])) {
539 if ((*names)[i] == NULL) {
540 return false;
542 (*types)[i] = SID_NAME_WKN_GRP;
543 } else {
544 (*types)[i] = SID_NAME_UNKNOWN;
547 return true;
550 if (sid_check_is_unix_users(domain_sid)) {
551 if (*domain_name == NULL) {
552 *domain_name = talloc_strdup(
553 mem_ctx, unix_users_domain_name());
554 if (*domain_name == NULL) {
555 return false;
558 for (i=0; i<num_rids; i++) {
559 (*names)[i] = talloc_strdup(
560 (*names), uidtoname(rids[i]));
561 if ((*names)[i] == NULL) {
562 return false;
564 (*types)[i] = SID_NAME_USER;
566 return true;
569 if (sid_check_is_unix_groups(domain_sid)) {
570 if (*domain_name == NULL) {
571 *domain_name = talloc_strdup(
572 mem_ctx, unix_groups_domain_name());
573 if (*domain_name == NULL) {
574 return false;
577 for (i=0; i<num_rids; i++) {
578 (*names)[i] = talloc_strdup(
579 (*names), gidtoname(rids[i]));
580 if ((*names)[i] == NULL) {
581 return false;
583 (*types)[i] = SID_NAME_DOM_GRP;
585 return true;
588 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
589 domain_name, *names, *types);
593 * Is the SID a domain as such? If yes, lookup its name.
596 static bool lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
597 const char **name)
599 const char *tmp;
600 enum lsa_SidType type;
602 if (sid_check_is_domain(sid)) {
603 *name = talloc_strdup(mem_ctx, get_global_sam_name());
604 return true;
607 if (sid_check_is_builtin(sid)) {
608 *name = talloc_strdup(mem_ctx, builtin_domain_name());
609 return true;
612 if (sid_check_is_wellknown_domain(sid, &tmp)) {
613 *name = talloc_strdup(mem_ctx, tmp);
614 return true;
617 if (sid_check_is_unix_users(sid)) {
618 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
619 return true;
622 if (sid_check_is_unix_groups(sid)) {
623 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
624 return true;
627 if (sid->num_auths != 4) {
628 /* This can't be a domain */
629 return false;
632 if (IS_DC) {
633 uint32 i, num_domains;
634 struct trustdom_info **domains;
636 /* This is relatively expensive, but it happens only on DCs
637 * and for SIDs that have 4 sub-authorities and thus look like
638 * domains */
640 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
641 &num_domains,
642 &domains))) {
643 return false;
646 for (i=0; i<num_domains; i++) {
647 if (sid_equal(sid, &domains[i]->sid)) {
648 *name = talloc_strdup(mem_ctx,
649 domains[i]->name);
650 return true;
653 return false;
656 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
657 (type == SID_NAME_DOMAIN)) {
658 *name = tmp;
659 return true;
662 return false;
666 * This tries to implement the rather weird rules for the lsa_lookup level
667 * parameter.
669 * This is as close as we can get to what W2k3 does. With this we survive the
670 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
671 * different, but I assume that's just being too liberal. For example, W2k3
672 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
673 * whereas NT4 does the same as level 1 (I think). I did not fully test that
674 * with NT4, this is what w2k3 does.
676 * Level 1: Ask everywhere
677 * Level 2: Ask domain and trusted domains, no builtin and wkn
678 * Level 3: Only ask domain
679 * Level 4: W2k3ad: Only ask AD trusts
680 * Level 5: Only ask transitive forest trusts
681 * Level 6: Like 4
684 static bool check_dom_sid_to_level(const DOM_SID *sid, int level)
686 int ret = false;
688 switch(level) {
689 case 1:
690 ret = true;
691 break;
692 case 2:
693 ret = (!sid_check_is_builtin(sid) &&
694 !sid_check_is_wellknown_domain(sid, NULL));
695 break;
696 case 3:
697 case 4:
698 case 6:
699 ret = sid_check_is_domain(sid);
700 break;
701 case 5:
702 ret = false;
703 break;
706 DEBUG(10, ("%s SID %s in level %d\n",
707 ret ? "Accepting" : "Rejecting",
708 sid_string_dbg(sid), level));
709 return ret;
713 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
714 * references to domains, it is explicitly made for this.
716 * This attempts to be as efficient as possible: It collects all SIDs
717 * belonging to a domain and hands them in bulk to the appropriate lookup
718 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
719 * *hugely* from this. Winbind is going to be extended with a lookup_rids
720 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
721 * appropriate DC.
724 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
725 const DOM_SID **sids, int level,
726 struct lsa_dom_info **ret_domains,
727 struct lsa_name_info **ret_names)
729 TALLOC_CTX *tmp_ctx;
730 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
731 struct lsa_name_info *name_infos;
732 struct lsa_dom_info *dom_infos = NULL;
734 int i, j;
736 if (!(tmp_ctx = talloc_new(mem_ctx))) {
737 DEBUG(0, ("talloc_new failed\n"));
738 return NT_STATUS_NO_MEMORY;
741 if (num_sids) {
742 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
743 if (name_infos == NULL) {
744 result = NT_STATUS_NO_MEMORY;
745 goto fail;
747 } else {
748 name_infos = NULL;
751 dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
752 MAX_REF_DOMAINS);
753 if (dom_infos == NULL) {
754 result = NT_STATUS_NO_MEMORY;
755 goto fail;
758 /* First build up the data structures:
760 * dom_infos is a list of domains referenced in the list of
761 * SIDs. Later we will walk the list of domains and look up the RIDs
762 * in bulk.
764 * name_infos is a shadow-copy of the SIDs array to collect the real
765 * data.
767 * dom_info->idxs is an index into the name_infos array. The
768 * difficulty we have here is that we need to keep the SIDs the client
769 * asked for in the same order for the reply
772 for (i=0; i<num_sids; i++) {
773 DOM_SID sid;
774 uint32 rid;
775 const char *domain_name = NULL;
777 sid_copy(&sid, sids[i]);
778 name_infos[i].type = SID_NAME_USE_NONE;
780 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
781 /* We can't push that through the normal lookup
782 * process, as this would reference illegal
783 * domains.
785 * For example S-1-5-32 would end up referencing
786 * domain S-1-5- with RID 32 which is clearly wrong.
788 if (domain_name == NULL) {
789 result = NT_STATUS_NO_MEMORY;
790 goto fail;
793 name_infos[i].rid = 0;
794 name_infos[i].type = SID_NAME_DOMAIN;
795 name_infos[i].name = NULL;
797 if (sid_check_is_builtin(&sid)) {
798 /* Yes, W2k3 returns "BUILTIN" both as domain
799 * and name here */
800 name_infos[i].name = talloc_strdup(
801 name_infos, builtin_domain_name());
802 if (name_infos[i].name == NULL) {
803 result = NT_STATUS_NO_MEMORY;
804 goto fail;
807 } else {
808 /* This is a normal SID with rid component */
809 if (!sid_split_rid(&sid, &rid)) {
810 result = NT_STATUS_INVALID_SID;
811 goto fail;
815 if (!check_dom_sid_to_level(&sid, level)) {
816 name_infos[i].rid = 0;
817 name_infos[i].type = SID_NAME_UNKNOWN;
818 name_infos[i].name = NULL;
819 continue;
822 for (j=0; j<MAX_REF_DOMAINS; j++) {
823 if (!dom_infos[j].valid) {
824 break;
826 if (sid_equal(&sid, &dom_infos[j].sid)) {
827 break;
831 if (j == MAX_REF_DOMAINS) {
832 /* TODO: What's the right error message here? */
833 result = NT_STATUS_NONE_MAPPED;
834 goto fail;
837 if (!dom_infos[j].valid) {
838 /* We found a domain not yet referenced, create a new
839 * ref. */
840 dom_infos[j].valid = true;
841 sid_copy(&dom_infos[j].sid, &sid);
843 if (domain_name != NULL) {
844 /* This name was being found above in the case
845 * when we found a domain SID */
846 dom_infos[j].name =
847 talloc_strdup(dom_infos, domain_name);
848 if (dom_infos[j].name == NULL) {
849 result = NT_STATUS_NO_MEMORY;
850 goto fail;
852 } else {
853 /* lookup_rids will take care of this */
854 dom_infos[j].name = NULL;
858 name_infos[i].dom_idx = j;
860 if (name_infos[i].type == SID_NAME_USE_NONE) {
861 name_infos[i].rid = rid;
863 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
864 &dom_infos[j].num_idxs);
866 if (dom_infos[j].idxs == NULL) {
867 result = NT_STATUS_NO_MEMORY;
868 goto fail;
873 /* Iterate over the domains found */
875 for (i=0; i<MAX_REF_DOMAINS; i++) {
876 uint32_t *rids;
877 const char *domain_name = NULL;
878 const char **names;
879 enum lsa_SidType *types;
880 struct lsa_dom_info *dom = &dom_infos[i];
882 if (!dom->valid) {
883 /* No domains left, we're done */
884 break;
887 if (dom->num_idxs) {
888 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
889 result = NT_STATUS_NO_MEMORY;
890 goto fail;
892 } else {
893 rids = NULL;
896 for (j=0; j<dom->num_idxs; j++) {
897 rids[j] = name_infos[dom->idxs[j]].rid;
900 if (!lookup_rids(tmp_ctx, &dom->sid,
901 dom->num_idxs, rids, &domain_name,
902 &names, &types)) {
903 result = NT_STATUS_NO_MEMORY;
904 goto fail;
907 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
908 result = NT_STATUS_NO_MEMORY;
909 goto fail;
912 for (j=0; j<dom->num_idxs; j++) {
913 int idx = dom->idxs[j];
914 name_infos[idx].type = types[j];
915 if (types[j] != SID_NAME_UNKNOWN) {
916 name_infos[idx].name =
917 talloc_strdup(name_infos, names[j]);
918 if (name_infos[idx].name == NULL) {
919 result = NT_STATUS_NO_MEMORY;
920 goto fail;
922 } else {
923 name_infos[idx].name = NULL;
928 *ret_domains = dom_infos;
929 *ret_names = name_infos;
930 TALLOC_FREE(tmp_ctx);
931 return NT_STATUS_OK;
933 fail:
934 TALLOC_FREE(dom_infos);
935 TALLOC_FREE(name_infos);
936 TALLOC_FREE(tmp_ctx);
937 return result;
940 /*****************************************************************
941 *THE CANONICAL* convert SID to name function.
942 *****************************************************************/
944 bool lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
945 const char **ret_domain, const char **ret_name,
946 enum lsa_SidType *ret_type)
948 struct lsa_dom_info *domain;
949 struct lsa_name_info *name;
950 TALLOC_CTX *tmp_ctx;
951 bool ret = false;
953 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
955 if (!(tmp_ctx = talloc_new(mem_ctx))) {
956 DEBUG(0, ("talloc_new failed\n"));
957 return false;
960 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
961 &domain, &name))) {
962 goto done;
965 if (name->type == SID_NAME_UNKNOWN) {
966 goto done;
969 if ((ret_domain != NULL) &&
970 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
971 goto done;
974 if ((ret_name != NULL) &&
975 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
976 goto done;
979 if (ret_type != NULL) {
980 *ret_type = name->type;
983 ret = true;
985 done:
986 if (ret) {
987 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
988 domain->name, name->name, name->type));
989 } else {
990 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
992 TALLOC_FREE(tmp_ctx);
993 return ret;
996 /*****************************************************************
997 Id mapping cache. This is to avoid Winbind mappings already
998 seen by smbd to be queried too frequently, keeping winbindd
999 busy, and blocking smbd while winbindd is busy with other
1000 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1001 modified to use linked lists by jra.
1002 *****************************************************************/
1004 /*****************************************************************
1005 Find a SID given a uid.
1006 *****************************************************************/
1008 static bool fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
1010 DATA_BLOB cache_value;
1012 if (!memcache_lookup(NULL, UID_SID_CACHE,
1013 data_blob_const(&uid, sizeof(uid)),
1014 &cache_value)) {
1015 return false;
1018 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1019 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1020 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, 0));
1022 return true;
1025 /*****************************************************************
1026 Find a uid given a SID.
1027 *****************************************************************/
1029 static bool fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
1031 DATA_BLOB cache_value;
1033 if (!memcache_lookup(NULL, SID_UID_CACHE,
1034 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1035 &cache_value)) {
1036 return false;
1039 SMB_ASSERT(cache_value.length == sizeof(*puid));
1040 memcpy(puid, cache_value.data, sizeof(*puid));
1042 return true;
1045 /*****************************************************************
1046 Store uid to SID mapping in cache.
1047 *****************************************************************/
1049 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
1051 memcache_add(NULL, SID_UID_CACHE,
1052 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1053 data_blob_const(&uid, sizeof(uid)));
1054 memcache_add(NULL, UID_SID_CACHE,
1055 data_blob_const(&uid, sizeof(uid)),
1056 data_blob_const(psid, ndr_size_dom_sid(psid, 0)));
1059 /*****************************************************************
1060 Find a SID given a gid.
1061 *****************************************************************/
1063 static bool fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1065 DATA_BLOB cache_value;
1067 if (!memcache_lookup(NULL, GID_SID_CACHE,
1068 data_blob_const(&gid, sizeof(gid)),
1069 &cache_value)) {
1070 return false;
1073 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1074 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1075 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, 0));
1077 return true;
1080 /*****************************************************************
1081 Find a gid given a SID.
1082 *****************************************************************/
1084 static bool fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1086 DATA_BLOB cache_value;
1088 if (!memcache_lookup(NULL, SID_GID_CACHE,
1089 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1090 &cache_value)) {
1091 return false;
1094 SMB_ASSERT(cache_value.length == sizeof(*pgid));
1095 memcpy(pgid, cache_value.data, sizeof(*pgid));
1097 return true;
1100 /*****************************************************************
1101 Store gid to SID mapping in cache.
1102 *****************************************************************/
1104 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1106 memcache_add(NULL, SID_GID_CACHE,
1107 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1108 data_blob_const(&gid, sizeof(gid)));
1109 memcache_add(NULL, GID_SID_CACHE,
1110 data_blob_const(&gid, sizeof(gid)),
1111 data_blob_const(psid, ndr_size_dom_sid(psid, 0)));
1114 /*****************************************************************
1115 *THE LEGACY* convert uid_t to SID function.
1116 *****************************************************************/
1118 static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
1120 uint32 rid;
1121 bool ret;
1123 ZERO_STRUCTP(psid);
1125 become_root();
1126 ret = pdb_uid_to_rid(uid, &rid);
1127 unbecome_root();
1129 if (ret) {
1130 /* This is a mapped user */
1131 sid_copy(psid, get_global_sam_sid());
1132 sid_append_rid(psid, rid);
1133 goto done;
1136 /* This is an unmapped user */
1138 uid_to_unix_users_sid(uid, psid);
1140 done:
1141 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1142 sid_string_dbg(psid)));
1144 store_uid_sid_cache(psid, uid);
1145 return;
1148 /*****************************************************************
1149 *THE LEGACY* convert gid_t to SID function.
1150 *****************************************************************/
1152 static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
1154 bool ret;
1156 ZERO_STRUCTP(psid);
1158 become_root();
1159 ret = pdb_gid_to_sid(gid, psid);
1160 unbecome_root();
1162 if (ret) {
1163 /* This is a mapped group */
1164 goto done;
1167 /* This is an unmapped group */
1169 gid_to_unix_groups_sid(gid, psid);
1171 done:
1172 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1173 sid_string_dbg(psid)));
1175 store_gid_sid_cache(psid, gid);
1176 return;
1179 /*****************************************************************
1180 *THE LEGACY* convert SID to uid function.
1181 *****************************************************************/
1183 static bool legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
1185 enum lsa_SidType type;
1186 uint32 rid;
1188 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1189 union unid_t id;
1190 bool ret;
1192 become_root();
1193 ret = pdb_sid_to_id(psid, &id, &type);
1194 unbecome_root();
1196 if (ret) {
1197 if (type != SID_NAME_USER) {
1198 DEBUG(5, ("sid %s is a %s, expected a user\n",
1199 sid_string_dbg(psid),
1200 sid_type_lookup(type)));
1201 return false;
1203 *puid = id.uid;
1204 goto done;
1207 /* This was ours, but it was not mapped. Fail */
1210 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1211 sid_string_dbg(psid)));
1212 return false;
1214 done:
1215 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_dbg(psid),
1216 (unsigned int)*puid ));
1218 store_uid_sid_cache(psid, *puid);
1219 return true;
1222 /*****************************************************************
1223 *THE LEGACY* convert SID to gid function.
1224 Group mapping is used for gids that maps to Wellknown SIDs
1225 *****************************************************************/
1227 static bool legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1229 uint32 rid;
1230 GROUP_MAP map;
1231 union unid_t id;
1232 enum lsa_SidType type;
1234 if ((sid_check_is_in_builtin(psid) ||
1235 sid_check_is_in_wellknown_domain(psid))) {
1236 bool ret;
1238 become_root();
1239 ret = pdb_getgrsid(&map, *psid);
1240 unbecome_root();
1242 if (ret) {
1243 *pgid = map.gid;
1244 goto done;
1246 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1247 sid_string_dbg(psid)));
1248 return false;
1251 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1252 bool ret;
1254 become_root();
1255 ret = pdb_sid_to_id(psid, &id, &type);
1256 unbecome_root();
1258 if (ret) {
1259 if ((type != SID_NAME_DOM_GRP) &&
1260 (type != SID_NAME_ALIAS)) {
1261 DEBUG(5, ("LEGACY: sid %s is a %s, expected "
1262 "a group\n", sid_string_dbg(psid),
1263 sid_type_lookup(type)));
1264 return false;
1266 *pgid = id.gid;
1267 goto done;
1270 /* This was ours, but it was not mapped. Fail */
1273 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1274 sid_string_dbg(psid)));
1275 return false;
1277 done:
1278 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_dbg(psid),
1279 (unsigned int)*pgid ));
1281 store_gid_sid_cache(psid, *pgid);
1283 return true;
1286 /*****************************************************************
1287 *THE CANONICAL* convert uid_t to SID function.
1288 *****************************************************************/
1290 void uid_to_sid(DOM_SID *psid, uid_t uid)
1292 bool expired = true;
1293 bool ret;
1294 ZERO_STRUCTP(psid);
1296 if (fetch_sid_from_uid_cache(psid, uid))
1297 return;
1299 /* Check the winbindd cache directly. */
1300 ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1302 if (ret && !expired && is_null_sid(psid)) {
1304 * Negative cache entry, we already asked.
1305 * do legacy.
1307 legacy_uid_to_sid(psid, uid);
1308 return;
1311 if (!ret || expired) {
1312 /* Not in cache. Ask winbindd. */
1313 if (!winbind_uid_to_sid(psid, uid)) {
1315 * We shouldn't return the NULL SID
1316 * here if winbind was running and
1317 * couldn't map, as winbind will have
1318 * added a negative entry that will
1319 * cause us to go though the
1320 * legacy_uid_to_sid()
1321 * function anyway in the case above
1322 * the next time we ask.
1324 DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1325 "for uid %u\n", uid));
1327 legacy_uid_to_sid(psid, uid);
1328 return;
1332 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1333 sid_string_dbg(psid)));
1335 store_uid_sid_cache(psid, uid);
1336 return;
1339 /*****************************************************************
1340 *THE CANONICAL* convert gid_t to SID function.
1341 *****************************************************************/
1343 void gid_to_sid(DOM_SID *psid, gid_t gid)
1345 bool expired = true;
1346 bool ret;
1347 ZERO_STRUCTP(psid);
1349 if (fetch_sid_from_gid_cache(psid, gid))
1350 return;
1352 /* Check the winbindd cache directly. */
1353 ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1355 if (ret && !expired && is_null_sid(psid)) {
1357 * Negative cache entry, we already asked.
1358 * do legacy.
1360 legacy_gid_to_sid(psid, gid);
1361 return;
1364 if (!ret || expired) {
1365 /* Not in cache. Ask winbindd. */
1366 if (!winbind_gid_to_sid(psid, gid)) {
1368 * We shouldn't return the NULL SID
1369 * here if winbind was running and
1370 * couldn't map, as winbind will have
1371 * added a negative entry that will
1372 * cause us to go though the
1373 * legacy_gid_to_sid()
1374 * function anyway in the case above
1375 * the next time we ask.
1377 DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1378 "for gid %u\n", gid));
1380 legacy_gid_to_sid(psid, gid);
1381 return;
1385 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1386 sid_string_dbg(psid)));
1388 store_gid_sid_cache(psid, gid);
1389 return;
1392 /*****************************************************************
1393 *THE CANONICAL* convert SID to uid function.
1394 *****************************************************************/
1396 bool sid_to_uid(const DOM_SID *psid, uid_t *puid)
1398 bool expired = true;
1399 bool ret;
1400 uint32 rid;
1401 gid_t gid;
1403 if (fetch_uid_from_cache(puid, psid))
1404 return true;
1406 if (fetch_gid_from_cache(&gid, psid)) {
1407 return false;
1410 /* Optimize for the Unix Users Domain
1411 * as the conversion is straightforward */
1412 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1413 uid_t uid = rid;
1414 *puid = uid;
1416 /* return here, don't cache */
1417 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1418 (unsigned int)*puid ));
1419 return true;
1422 /* Check the winbindd cache directly. */
1423 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1425 if (ret && !expired && (*puid == (uid_t)-1)) {
1427 * Negative cache entry, we already asked.
1428 * do legacy.
1430 return legacy_sid_to_uid(psid, puid);
1433 if (!ret || expired) {
1434 /* Not in cache. Ask winbindd. */
1435 if (!winbind_sid_to_uid(puid, psid)) {
1436 if (!winbind_ping()) {
1437 return legacy_sid_to_uid(psid, puid);
1440 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1441 sid_string_dbg(psid)));
1442 return false;
1446 /* TODO: Here would be the place to allocate both a gid and a uid for
1447 * the SID in question */
1449 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1450 (unsigned int)*puid ));
1452 store_uid_sid_cache(psid, *puid);
1453 return true;
1456 /*****************************************************************
1457 *THE CANONICAL* convert SID to gid function.
1458 Group mapping is used for gids that maps to Wellknown SIDs
1459 *****************************************************************/
1461 bool sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1463 bool expired = true;
1464 bool ret;
1465 uint32 rid;
1466 uid_t uid;
1468 if (fetch_gid_from_cache(pgid, psid))
1469 return true;
1471 if (fetch_uid_from_cache(&uid, psid))
1472 return false;
1474 /* Optimize for the Unix Groups Domain
1475 * as the conversion is straightforward */
1476 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1477 gid_t gid = rid;
1478 *pgid = gid;
1480 /* return here, don't cache */
1481 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1482 (unsigned int)*pgid ));
1483 return true;
1486 /* Check the winbindd cache directly. */
1487 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1489 if (ret && !expired && (*pgid == (gid_t)-1)) {
1491 * Negative cache entry, we already asked.
1492 * do legacy.
1494 return legacy_sid_to_gid(psid, pgid);
1497 if (!ret || expired) {
1498 /* Not in cache or negative. Ask winbindd. */
1499 /* Ask winbindd if it can map this sid to a gid.
1500 * (Idmap will check it is a valid SID and of the right type) */
1502 if ( !winbind_sid_to_gid(pgid, psid) ) {
1503 if (!winbind_ping()) {
1504 return legacy_sid_to_gid(psid, pgid);
1507 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1508 sid_string_dbg(psid)));
1509 return false;
1513 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1514 (unsigned int)*pgid ));
1516 store_gid_sid_cache(psid, *pgid);
1517 return true;