ctdb-server: Remove duplicate logic
[samba4-gss.git] / source3 / passdb / lookup_sid.c
blob7a29bb1abb5becf30dca26818e0abf94d9a76d37
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"
23 #include "passdb.h"
24 #include "lib/util_unixsids.h"
25 #include "../librpc/gen_ndr/ndr_security.h"
26 #include "secrets.h"
27 #include "../lib/util/memcache.h"
28 #include "idmap_cache.h"
29 #include "../libcli/security/security.h"
30 #include "lib/winbind_util.h"
31 #include "../librpc/gen_ndr/idmap.h"
32 #include "lib/util/bitmap.h"
34 static bool lookup_unix_user_name(const char *name, struct dom_sid *sid)
36 struct passwd *pwd;
37 bool ret;
39 pwd = Get_Pwnam_alloc(talloc_tos(), name);
40 if (pwd == NULL) {
41 return False;
45 * For 64-bit uid's we have enough space in the whole SID,
46 * should they become necessary
48 ret = sid_compose(sid, &global_sid_Unix_Users, pwd->pw_uid);
49 TALLOC_FREE(pwd);
50 return ret;
53 static bool lookup_unix_group_name(const char *name, struct dom_sid *sid)
55 struct group *grp;
57 grp = getgrnam(name);
58 if (grp == NULL) {
59 return False;
63 * For 64-bit gid's we have enough space in the whole SID,
64 * should they become necessary
66 return sid_compose(sid, &global_sid_Unix_Groups, grp->gr_gid);
69 /*****************************************************************
70 Dissect a user-provided name into domain, name, sid and type.
72 If an explicit domain name was given in the form domain\user, it
73 has to try that. If no explicit domain name was given, we have
74 to do guesswork.
75 *****************************************************************/
77 static NTSTATUS lookup_name_internal(TALLOC_CTX *mem_ctx,
78 const char *full_name,
79 int flags,
80 const char **ret_domain,
81 const char **ret_name,
82 struct dom_sid *ret_sid,
83 enum lsa_SidType *ret_type)
85 char *p;
86 const char *tmp;
87 const char *domain = NULL;
88 const char *name = NULL;
89 uint32_t rid;
90 struct dom_sid sid;
91 enum lsa_SidType type;
92 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
93 NTSTATUS status;
95 if (tmp_ctx == NULL) {
96 DEBUG(0, ("talloc_new failed\n"));
97 return NT_STATUS_NO_MEMORY;
100 p = strchr_m(full_name, '\\');
102 if (p != NULL) {
103 domain = talloc_strndup(tmp_ctx, full_name,
104 PTR_DIFF(p, full_name));
105 name = talloc_strdup(tmp_ctx, p+1);
106 } else {
107 char *q = strchr_m(full_name, '@');
109 /* Set the domain for UPNs */
110 if (q != NULL) {
111 name = talloc_strndup(tmp_ctx,
112 full_name,
113 PTR_DIFF(q, full_name));
114 domain = talloc_strdup(tmp_ctx, q + 1);
115 } else {
116 domain = talloc_strdup(tmp_ctx, "");
117 name = talloc_strdup(tmp_ctx, full_name);
121 if ((domain == NULL) || (name == NULL)) {
122 DEBUG(0, ("talloc failed\n"));
123 TALLOC_FREE(tmp_ctx);
124 return NT_STATUS_NO_MEMORY;
127 DEBUG(10,("lookup_name: %s => domain=[%s], name=[%s]\n",
128 full_name, domain, name));
129 DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
131 if ((flags & LOOKUP_NAME_DOMAIN) || (flags == 0)) {
132 bool check_global_sam = false;
134 check_global_sam = strequal(domain, get_global_sam_name());
136 /* If we are running on a DC that has PASSDB module with domain
137 * information, check if DNS forest name is matching the domain
138 * name. This is the case of IPA domain controller when
139 * trusted AD DC looks up users found in a Global Catalog of
140 * the forest root domain. */
141 if (!check_global_sam && (IS_DC)) {
142 struct pdb_domain_info *dom_info = NULL;
143 dom_info = pdb_get_domain_info(tmp_ctx);
145 if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) {
146 check_global_sam = strequal(domain, dom_info->dns_forest);
149 TALLOC_FREE(dom_info);
152 if (check_global_sam) {
153 /* It's our own domain, lookup the name in passdb */
154 if (lookup_global_sam_name(name, flags, &rid, &type)) {
155 sid_compose(&sid, get_global_sam_sid(), rid);
156 goto ok;
158 TALLOC_FREE(tmp_ctx);
159 *ret_type = SID_NAME_UNKNOWN;
160 return NT_STATUS_OK;
164 if ((flags & LOOKUP_NAME_BUILTIN) &&
165 strequal(domain, builtin_domain_name()))
167 if (strlen(name) == 0) {
168 /* Swap domain and name */
169 tmp = name; name = domain; domain = tmp;
170 sid_copy(&sid, &global_sid_Builtin);
171 type = SID_NAME_DOMAIN;
172 goto ok;
175 /* Explicit request for a name in BUILTIN */
176 if (lookup_builtin_name(name, &rid)) {
177 sid_compose(&sid, &global_sid_Builtin, rid);
178 type = SID_NAME_ALIAS;
179 goto ok;
181 TALLOC_FREE(tmp_ctx);
182 *ret_type = SID_NAME_UNKNOWN;
183 return NT_STATUS_OK;
186 /* Try the explicit winbind lookup first, don't let it guess the
187 * domain yet at this point yet. This comes later. */
189 if ((domain[0] != '\0') &&
190 (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)))
192 status = winbind_lookup_name_ex(domain, name, &sid, &type);
193 if (!NT_STATUS_IS_OK(status)) {
194 return status;
196 if (type != SID_NAME_UNKNOWN) {
197 goto ok;
201 if (((flags & (LOOKUP_NAME_NO_NSS|LOOKUP_NAME_GROUP)) == 0)
202 && strequal(domain, unix_users_domain_name())) {
203 if (lookup_unix_user_name(name, &sid)) {
204 type = SID_NAME_USER;
205 goto ok;
207 TALLOC_FREE(tmp_ctx);
208 *ret_type = SID_NAME_UNKNOWN;
209 return NT_STATUS_OK;
212 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
213 && strequal(domain, unix_groups_domain_name())) {
214 if (lookup_unix_group_name(name, &sid)) {
215 type = SID_NAME_DOM_GRP;
216 goto ok;
218 TALLOC_FREE(tmp_ctx);
219 *ret_type = SID_NAME_UNKNOWN;
220 return NT_STATUS_OK;
224 * Finally check for a well known domain name ("NT Authority"),
225 * this is being taken care of in lookup_wellknown_name().
227 if ((domain[0] != '\0') &&
228 (flags & LOOKUP_NAME_WKN) &&
229 lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
231 type = SID_NAME_WKN_GRP;
232 goto ok;
236 * If we're told not to look up 'isolated' names then we're
237 * done.
239 if (!(flags & LOOKUP_NAME_ISOLATED)) {
240 TALLOC_FREE(tmp_ctx);
241 *ret_type = SID_NAME_UNKNOWN;
242 return NT_STATUS_OK;
246 * No domain names beyond this point
248 if (domain[0] != '\0') {
249 TALLOC_FREE(tmp_ctx);
250 *ret_type = SID_NAME_UNKNOWN;
251 return NT_STATUS_OK;
254 /* Now the guesswork begins, we haven't been given an explicit
255 * domain. Try the sequence as documented on
256 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
257 * November 27, 2005 */
259 /* 1. well-known names */
262 * Check for well known names without a domain name.
263 * e.g. \Creator Owner.
266 if ((flags & LOOKUP_NAME_WKN) &&
267 lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
269 type = SID_NAME_WKN_GRP;
270 goto ok;
273 /* 2. Builtin domain as such */
275 if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
276 strequal(name, builtin_domain_name()))
278 /* Swap domain and name */
279 tmp = name; name = domain; domain = tmp;
280 sid_copy(&sid, &global_sid_Builtin);
281 type = SID_NAME_DOMAIN;
282 goto ok;
285 /* 3. Account domain */
287 if ((flags & LOOKUP_NAME_DOMAIN) &&
288 strequal(name, get_global_sam_name()))
290 if (!secrets_fetch_domain_sid(name, &sid)) {
291 DEBUG(3, ("Could not fetch my SID\n"));
292 TALLOC_FREE(tmp_ctx);
293 return NT_STATUS_INTERNAL_DB_CORRUPTION;
295 /* Swap domain and name */
296 tmp = name; name = domain; domain = tmp;
297 type = SID_NAME_DOMAIN;
298 goto ok;
301 /* 4. Primary domain */
303 if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
304 strequal(name, lp_workgroup()))
306 if (!secrets_fetch_domain_sid(name, &sid)) {
307 DEBUG(3, ("Could not fetch the domain SID\n"));
308 TALLOC_FREE(tmp_ctx);
309 return NT_STATUS_INTERNAL_DB_CORRUPTION;
311 /* Swap domain and name */
312 tmp = name; name = domain; domain = tmp;
313 type = SID_NAME_DOMAIN;
314 goto ok;
317 /* 5. Trusted domains as such, to me it looks as if members don't do
318 this, tested an XP workstation in a NT domain -- vl */
320 if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
321 (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
323 /* Swap domain and name */
324 tmp = name; name = domain; domain = tmp;
325 type = SID_NAME_DOMAIN;
326 goto ok;
329 /* 6. Builtin aliases */
331 if ((flags & LOOKUP_NAME_BUILTIN) &&
332 lookup_builtin_name(name, &rid))
334 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
335 sid_compose(&sid, &global_sid_Builtin, rid);
336 type = SID_NAME_ALIAS;
337 goto ok;
340 /* 7. Local systems' SAM (DCs don't have a local SAM) */
341 /* 8. Primary SAM (On members, this is the domain) */
343 /* Both cases are done by looking at our passdb */
345 if ((flags & LOOKUP_NAME_DOMAIN) &&
346 lookup_global_sam_name(name, flags, &rid, &type))
348 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
349 sid_compose(&sid, get_global_sam_sid(), rid);
350 goto ok;
353 /* Now our local possibilities are exhausted. */
355 if (!(flags & LOOKUP_NAME_REMOTE)) {
356 TALLOC_FREE(tmp_ctx);
357 *ret_type = SID_NAME_UNKNOWN;
358 return NT_STATUS_OK;
361 /* If we are not a DC, we have to ask in our primary domain. Let
362 * winbind do that. */
364 if (!IS_DC) {
365 status = winbind_lookup_name_ex(lp_workgroup(), name, &sid, &type);
366 if (!NT_STATUS_IS_OK(status)) {
367 return status;
369 if (type != SID_NAME_UNKNOWN) {
370 goto ok;
374 /* 9. Trusted domains */
376 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
377 * that (yet), but give it a chance. */
379 if (IS_DC) {
380 struct dom_sid dom_sid;
381 enum lsa_SidType domain_type;
383 status = winbind_lookup_name_ex("", name, &sid, &type);
384 if (!NT_STATUS_IS_OK(status)) {
385 return status;
387 if (type != SID_NAME_UNKNOWN) {
388 if (type == SID_NAME_DOMAIN) {
389 /* Swap name and type */
390 tmp = name; name = domain; domain = tmp;
391 goto ok;
394 /* Here we have to cope with a little deficiency
395 * in the winbind API: We have to ask it again
396 * for the name of the domain it figured out
397 * itself. Maybe fix that later... */
399 sid_copy(&dom_sid, &sid);
400 sid_split_rid(&dom_sid, NULL);
402 if (!winbind_lookup_sid(tmp_ctx, &dom_sid,
403 &domain, NULL,
404 &domain_type) ||
405 (domain_type != SID_NAME_DOMAIN))
407 DBG_INFO("winbind could not find the "
408 "domain's name it just looked "
409 "up for us\n");
410 TALLOC_FREE(tmp_ctx);
411 *ret_type = SID_NAME_UNKNOWN;
412 return NT_STATUS_OK;
414 goto ok;
418 /* 10. Don't translate */
420 /* 11. Ok, windows would end here. Samba has two more options:
421 Unmapped users and unmapped groups */
423 if (((flags & (LOOKUP_NAME_NO_NSS|LOOKUP_NAME_GROUP)) == 0)
424 && lookup_unix_user_name(name, &sid)) {
425 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
426 type = SID_NAME_USER;
427 goto ok;
430 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
431 && lookup_unix_group_name(name, &sid)) {
432 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
433 type = SID_NAME_DOM_GRP;
434 goto ok;
438 * Ok, all possibilities tried. Fail.
441 TALLOC_FREE(tmp_ctx);
442 *ret_type = SID_NAME_UNKNOWN;
443 return NT_STATUS_OK;
446 if ((domain == NULL) || (name == NULL)) {
447 DEBUG(0, ("talloc failed\n"));
448 TALLOC_FREE(tmp_ctx);
449 return NT_STATUS_NO_MEMORY;
453 * Hand over the results to the talloc context we've been given.
456 if ((ret_name != NULL) &&
457 !(*ret_name = talloc_strdup(mem_ctx, name))) {
458 DEBUG(0, ("talloc failed\n"));
459 TALLOC_FREE(tmp_ctx);
460 return NT_STATUS_NO_MEMORY;
463 if (ret_domain != NULL) {
464 char *tmp_dom;
465 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
466 DEBUG(0, ("talloc failed\n"));
467 TALLOC_FREE(tmp_ctx);
468 return NT_STATUS_NO_MEMORY;
470 if (!strupper_m(tmp_dom)) {
471 TALLOC_FREE(tmp_ctx);
472 return NT_STATUS_INTERNAL_ERROR;
474 *ret_domain = tmp_dom;
477 if (ret_sid != NULL) {
478 sid_copy(ret_sid, &sid);
481 *ret_type = type;
483 TALLOC_FREE(tmp_ctx);
484 return NT_STATUS_OK;
487 bool lookup_name(TALLOC_CTX *mem_ctx,
488 const char *full_name,
489 int flags,
490 const char **ret_domain,
491 const char **ret_name,
492 struct dom_sid *ret_sid,
493 enum lsa_SidType *ret_type)
495 enum lsa_SidType type;
496 NTSTATUS status;
498 status = lookup_name_internal(mem_ctx,
499 full_name,
500 flags,
501 ret_domain,
502 ret_name,
503 ret_sid,
504 &type);
505 if (!NT_STATUS_IS_OK(status)) {
506 return false;
508 if (ret_type != NULL) {
509 *ret_type = type;
511 if (type == SID_NAME_UNKNOWN) {
512 return false;
514 return true;
517 /************************************************************************
518 Names from smb.conf can be unqualified. eg. valid users = foo
519 These names should never map to a remote name. Try global_sam_name()\foo,
520 and then "Unix Users"\foo (or "Unix Groups"\foo).
521 ************************************************************************/
523 NTSTATUS lookup_name_smbconf_ex(TALLOC_CTX *mem_ctx,
524 const char *full_name,
525 int flags,
526 const char **ret_domain,
527 const char **ret_name,
528 struct dom_sid *ret_sid,
529 enum lsa_SidType *ret_type)
531 char *qualified_name = NULL;
532 const char *p = strchr_m(full_name, *lp_winbind_separator());
533 bool is_qualified = p != NULL || strchr_m(full_name, '@') != NULL;
534 NTSTATUS status;
536 /* For DOMAIN\user or user@REALM directly call lookup_name(). */
537 if (is_qualified) {
539 /* The name is already qualified with a domain. */
541 if (p != NULL && *lp_winbind_separator() != '\\') {
542 /* lookup_name() needs '\\' as a separator */
544 qualified_name = talloc_strdup(mem_ctx, full_name);
545 if (qualified_name == NULL) {
546 return NT_STATUS_NO_MEMORY;
548 qualified_name[p - full_name] = '\\';
549 full_name = qualified_name;
552 return lookup_name_internal(mem_ctx,
553 full_name,
554 flags,
555 ret_domain,
556 ret_name,
557 ret_sid,
558 ret_type);
561 /* Try with winbind default domain name. */
562 if (lp_winbind_use_default_domain()) {
563 qualified_name = talloc_asprintf(mem_ctx,
564 "%s\\%s",
565 lp_workgroup(),
566 full_name);
567 if (qualified_name == NULL) {
568 return NT_STATUS_NO_MEMORY;
571 status= lookup_name_internal(mem_ctx,
572 qualified_name,
573 flags,
574 ret_domain,
575 ret_name,
576 ret_sid,
577 ret_type);
578 if (NT_STATUS_IS_OK(status) &&
579 *ret_type != SID_NAME_UNKNOWN)
581 return NT_STATUS_OK;
585 /* Try with our own SAM name. */
586 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
587 get_global_sam_name(),
588 full_name );
589 if (!qualified_name) {
590 return NT_STATUS_NO_MEMORY;
593 status = lookup_name_internal(mem_ctx,
594 qualified_name,
595 flags,
596 ret_domain,
597 ret_name,
598 ret_sid,
599 ret_type);
600 if (NT_STATUS_IS_OK(status) &&
601 *ret_type != SID_NAME_UNKNOWN)
603 return NT_STATUS_OK;
606 /* Finally try with "Unix Users" or "Unix Group" */
607 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
608 flags & LOOKUP_NAME_GROUP ?
609 unix_groups_domain_name() :
610 unix_users_domain_name(),
611 full_name );
612 if (!qualified_name) {
613 return NT_STATUS_NO_MEMORY;
616 return lookup_name_internal(mem_ctx,
617 qualified_name,
618 flags,
619 ret_domain,
620 ret_name,
621 ret_sid,
622 ret_type);
625 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
626 const char *full_name, int flags,
627 const char **ret_domain, const char **ret_name,
628 struct dom_sid *ret_sid, enum lsa_SidType *ret_type)
630 enum lsa_SidType type;
631 NTSTATUS status;
633 status = lookup_name_smbconf_ex(mem_ctx,
634 full_name,
635 flags,
636 ret_domain,
637 ret_name,
638 ret_sid,
639 &type);
640 if (!NT_STATUS_IS_OK(status)) {
641 return false;
643 if (ret_type != NULL) {
644 *ret_type = type;
646 if (type == SID_NAME_UNKNOWN) {
647 return false;
649 return true;
652 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
653 const struct dom_sid *domain_sid,
654 int num_rids, uint32_t *rids,
655 const char **domain_name,
656 const char **names, enum lsa_SidType *types)
658 int i;
659 const char **my_names;
660 enum lsa_SidType *my_types;
661 TALLOC_CTX *tmp_ctx;
663 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
664 return false;
667 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
668 domain_name, &my_names, &my_types)) {
669 *domain_name = "";
670 for (i=0; i<num_rids; i++) {
671 names[i] = "";
672 types[i] = SID_NAME_UNKNOWN;
674 TALLOC_FREE(tmp_ctx);
675 return true;
678 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
679 TALLOC_FREE(tmp_ctx);
680 return false;
684 * winbind_lookup_rids allocates its own array. We've been given the
685 * array, so copy it over
688 for (i=0; i<num_rids; i++) {
689 if (my_names[i] == NULL) {
690 TALLOC_FREE(tmp_ctx);
691 return false;
693 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
694 TALLOC_FREE(tmp_ctx);
695 return false;
697 types[i] = my_types[i];
699 TALLOC_FREE(tmp_ctx);
700 return true;
703 static bool lookup_rids(TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid,
704 int num_rids, uint32_t *rids,
705 const char **domain_name,
706 const char ***names, enum lsa_SidType **types)
708 int i;
709 struct dom_sid_buf buf;
711 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
712 dom_sid_str_buf(domain_sid, &buf)));
714 if (num_rids) {
715 *names = talloc_zero_array(mem_ctx, const char *, num_rids);
716 *types = talloc_array(mem_ctx, enum lsa_SidType, num_rids);
718 if ((*names == NULL) || (*types == NULL)) {
719 return false;
722 for (i = 0; i < num_rids; i++)
723 (*types)[i] = SID_NAME_UNKNOWN;
724 } else {
725 *names = NULL;
726 *types = NULL;
729 if (sid_check_is_our_sam(domain_sid)) {
730 NTSTATUS result;
732 if (*domain_name == NULL) {
733 *domain_name = talloc_strdup(
734 mem_ctx, get_global_sam_name());
737 if (*domain_name == NULL) {
738 return false;
741 become_root();
742 result = pdb_lookup_rids(domain_sid, num_rids, rids,
743 *names, *types);
744 unbecome_root();
746 return (NT_STATUS_IS_OK(result) ||
747 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
748 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
751 if (sid_check_is_builtin(domain_sid)) {
753 if (*domain_name == NULL) {
754 *domain_name = talloc_strdup(
755 mem_ctx, builtin_domain_name());
758 if (*domain_name == NULL) {
759 return false;
762 for (i=0; i<num_rids; i++) {
763 if (lookup_builtin_rid(*names, rids[i],
764 &(*names)[i])) {
765 if ((*names)[i] == NULL) {
766 return false;
768 (*types)[i] = SID_NAME_ALIAS;
769 } else {
770 (*types)[i] = SID_NAME_UNKNOWN;
773 return true;
776 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
777 for (i=0; i<num_rids; i++) {
778 struct dom_sid sid;
779 sid_compose(&sid, domain_sid, rids[i]);
780 if (lookup_wellknown_sid(mem_ctx, &sid,
781 domain_name, &(*names)[i])) {
782 if ((*names)[i] == NULL) {
783 return false;
785 (*types)[i] = SID_NAME_WKN_GRP;
786 } else {
787 (*types)[i] = SID_NAME_UNKNOWN;
790 return true;
793 if (sid_check_is_unix_users(domain_sid)) {
794 if (*domain_name == NULL) {
795 *domain_name = talloc_strdup(
796 mem_ctx, unix_users_domain_name());
797 if (*domain_name == NULL) {
798 return false;
801 for (i=0; i<num_rids; i++) {
802 (*names)[i] = talloc_strdup(
803 (*names), uidtoname(rids[i]));
804 if ((*names)[i] == NULL) {
805 return false;
807 (*types)[i] = SID_NAME_USER;
809 return true;
812 if (sid_check_is_unix_groups(domain_sid)) {
813 if (*domain_name == NULL) {
814 *domain_name = talloc_strdup(
815 mem_ctx, unix_groups_domain_name());
816 if (*domain_name == NULL) {
817 return false;
820 for (i=0; i<num_rids; i++) {
821 (*names)[i] = talloc_strdup(
822 (*names), gidtoname(rids[i]));
823 if ((*names)[i] == NULL) {
824 return false;
826 (*types)[i] = SID_NAME_DOM_GRP;
828 return true;
831 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
832 domain_name, *names, *types);
836 * Is the SID a domain as such? If yes, lookup its name.
839 static bool lookup_as_domain(const struct dom_sid *sid, TALLOC_CTX *mem_ctx,
840 const char **name)
842 const char *tmp;
843 enum lsa_SidType type;
845 if (sid_check_is_our_sam(sid)) {
846 *name = talloc_strdup(mem_ctx, get_global_sam_name());
847 return true;
850 if (sid_check_is_builtin(sid)) {
851 *name = talloc_strdup(mem_ctx, builtin_domain_name());
852 return true;
855 if (sid_check_is_wellknown_domain(sid, &tmp)) {
856 *name = talloc_strdup(mem_ctx, tmp);
857 return true;
860 if (sid_check_is_unix_users(sid)) {
861 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
862 return true;
865 if (sid_check_is_unix_groups(sid)) {
866 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
867 return true;
870 if (sid->num_auths != 4) {
871 /* This can't be a domain */
872 return false;
875 if (IS_DC) {
876 uint32_t i, num_domains;
877 struct trustdom_info **domains;
879 /* This is relatively expensive, but it happens only on DCs
880 * and for SIDs that have 4 sub-authorities and thus look like
881 * domains */
883 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
884 &num_domains,
885 &domains))) {
886 return false;
889 for (i=0; i<num_domains; i++) {
890 if (dom_sid_equal(sid, &domains[i]->sid)) {
891 *name = talloc_strdup(mem_ctx,
892 domains[i]->name);
893 return true;
896 return false;
899 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
900 (type == SID_NAME_DOMAIN)) {
901 *name = tmp;
902 return true;
905 return false;
909 * This tries to implement the rather weird rules for the lsa_lookup level
910 * parameter.
912 * This is as close as we can get to what W2k3 does. With this we survive the
913 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
914 * different, but I assume that's just being too liberal. For example, W2k3
915 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
916 * whereas NT4 does the same as level 1 (I think). I did not fully test that
917 * with NT4, this is what w2k3 does.
919 * Level 1: Ask everywhere
920 * Level 2: Ask domain and trusted domains, no builtin and wkn
921 * Level 3: Only ask domain
922 * Level 4: W2k3ad: Only ask AD trusts
923 * Level 5: Only ask transitive forest trusts
924 * Level 6: Like 4
927 static bool check_dom_sid_to_level(const struct dom_sid *sid, int level)
929 struct dom_sid_buf buf;
930 int ret = false;
932 switch(level) {
933 case 1:
934 ret = true;
935 break;
936 case 2:
937 ret = (!sid_check_is_builtin(sid) &&
938 !sid_check_is_wellknown_domain(sid, NULL));
939 break;
940 case 3:
941 case 4:
942 case 6:
943 ret = sid_check_is_our_sam(sid);
944 break;
945 case 5:
946 ret = false;
947 break;
950 DEBUG(10, ("%s SID %s in level %d\n",
951 ret ? "Accepting" : "Rejecting",
952 dom_sid_str_buf(sid, &buf),
953 level));
954 return ret;
958 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
959 * references to domains, it is explicitly made for this.
961 * This attempts to be as efficient as possible: It collects all SIDs
962 * belonging to a domain and hands them in bulk to the appropriate lookup
963 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
964 * *hugely* from this.
967 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
968 const struct dom_sid **sids, int level,
969 struct lsa_dom_info **ret_domains,
970 struct lsa_name_info **ret_names)
972 TALLOC_CTX *tmp_ctx;
973 NTSTATUS result;
974 struct lsa_name_info *name_infos;
975 struct lsa_dom_info *dom_infos = NULL;
977 int i, j;
979 if (!(tmp_ctx = talloc_new(mem_ctx))) {
980 DEBUG(0, ("talloc_new failed\n"));
981 return NT_STATUS_NO_MEMORY;
984 if (num_sids) {
985 name_infos = talloc_array(mem_ctx, struct lsa_name_info, num_sids);
986 if (name_infos == NULL) {
987 result = NT_STATUS_NO_MEMORY;
988 goto fail;
990 } else {
991 name_infos = NULL;
994 dom_infos = talloc_zero_array(mem_ctx, struct lsa_dom_info,
995 LSA_REF_DOMAIN_LIST_MULTIPLIER);
996 if (dom_infos == NULL) {
997 result = NT_STATUS_NO_MEMORY;
998 goto fail;
1001 /* First build up the data structures:
1003 * dom_infos is a list of domains referenced in the list of
1004 * SIDs. Later we will walk the list of domains and look up the RIDs
1005 * in bulk.
1007 * name_infos is a shadow-copy of the SIDs array to collect the real
1008 * data.
1010 * dom_info->idxs is an index into the name_infos array. The
1011 * difficulty we have here is that we need to keep the SIDs the client
1012 * asked for in the same order for the reply
1015 for (i=0; i<num_sids; i++) {
1016 struct dom_sid sid;
1017 uint32_t rid = 0;
1018 const char *domain_name = NULL;
1020 sid_copy(&sid, sids[i]);
1021 name_infos[i].type = SID_NAME_USE_NONE;
1023 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
1024 /* We can't push that through the normal lookup
1025 * process, as this would reference illegal
1026 * domains.
1028 * For example S-1-5-32 would end up referencing
1029 * domain S-1-5- with RID 32 which is clearly wrong.
1031 if (domain_name == NULL) {
1032 result = NT_STATUS_NO_MEMORY;
1033 goto fail;
1036 name_infos[i].rid = 0;
1037 name_infos[i].type = SID_NAME_DOMAIN;
1038 name_infos[i].name = NULL;
1040 if (sid_check_is_builtin(&sid)) {
1041 /* Yes, W2k3 returns "BUILTIN" both as domain
1042 * and name here */
1043 name_infos[i].name = talloc_strdup(
1044 name_infos, builtin_domain_name());
1045 if (name_infos[i].name == NULL) {
1046 result = NT_STATUS_NO_MEMORY;
1047 goto fail;
1050 } else {
1051 /* This is a normal SID with rid component */
1052 if (!sid_split_rid(&sid, &rid)) {
1053 result = NT_STATUS_INVALID_SID;
1054 goto fail;
1058 if (!check_dom_sid_to_level(&sid, level)) {
1059 name_infos[i].rid = 0;
1060 name_infos[i].type = SID_NAME_UNKNOWN;
1061 name_infos[i].name = NULL;
1062 continue;
1065 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
1066 if (!dom_infos[j].valid) {
1067 break;
1069 if (dom_sid_equal(&sid, &dom_infos[j].sid)) {
1070 break;
1074 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
1075 /* TODO: What's the right error message here? */
1076 result = NT_STATUS_NONE_MAPPED;
1077 goto fail;
1080 if (!dom_infos[j].valid) {
1081 /* We found a domain not yet referenced, create a new
1082 * ref. */
1083 dom_infos[j].valid = true;
1084 sid_copy(&dom_infos[j].sid, &sid);
1086 if (domain_name != NULL) {
1087 /* This name was being found above in the case
1088 * when we found a domain SID */
1089 dom_infos[j].name =
1090 talloc_strdup(dom_infos, domain_name);
1091 if (dom_infos[j].name == NULL) {
1092 result = NT_STATUS_NO_MEMORY;
1093 goto fail;
1095 } else {
1096 /* lookup_rids will take care of this */
1097 dom_infos[j].name = NULL;
1101 name_infos[i].dom_idx = j;
1103 if (name_infos[i].type == SID_NAME_USE_NONE) {
1104 name_infos[i].rid = rid;
1106 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
1107 &dom_infos[j].num_idxs);
1109 if (dom_infos[j].idxs == NULL) {
1110 result = NT_STATUS_NO_MEMORY;
1111 goto fail;
1116 /* Iterate over the domains found */
1118 for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
1119 uint32_t *rids;
1120 const char *domain_name = NULL;
1121 const char **names;
1122 enum lsa_SidType *types;
1123 struct lsa_dom_info *dom = &dom_infos[i];
1125 if (!dom->valid) {
1126 /* No domains left, we're done */
1127 break;
1130 if (dom->num_idxs == 0) {
1132 * This happens only if the only sid related to
1133 * this domain is the domain sid itself, which
1134 * is mapped to SID_NAME_DOMAIN above.
1136 continue;
1139 if (!(rids = talloc_array(tmp_ctx, uint32_t, dom->num_idxs))) {
1140 result = NT_STATUS_NO_MEMORY;
1141 goto fail;
1144 for (j=0; j<dom->num_idxs; j++) {
1145 rids[j] = name_infos[dom->idxs[j]].rid;
1148 if (!lookup_rids(tmp_ctx, &dom->sid,
1149 dom->num_idxs, rids, &domain_name,
1150 &names, &types)) {
1151 result = NT_STATUS_NO_MEMORY;
1152 goto fail;
1155 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
1156 result = NT_STATUS_NO_MEMORY;
1157 goto fail;
1160 for (j=0; j<dom->num_idxs; j++) {
1161 int idx = dom->idxs[j];
1162 name_infos[idx].type = types[j];
1163 if (types[j] != SID_NAME_UNKNOWN) {
1164 name_infos[idx].name =
1165 talloc_strdup(name_infos, names[j]);
1166 if (name_infos[idx].name == NULL) {
1167 result = NT_STATUS_NO_MEMORY;
1168 goto fail;
1170 } else {
1171 name_infos[idx].name = NULL;
1176 *ret_domains = dom_infos;
1177 *ret_names = name_infos;
1178 TALLOC_FREE(tmp_ctx);
1179 return NT_STATUS_OK;
1181 fail:
1182 TALLOC_FREE(dom_infos);
1183 TALLOC_FREE(name_infos);
1184 TALLOC_FREE(tmp_ctx);
1185 return result;
1188 /*****************************************************************
1189 *THE CANONICAL* convert SID to name function.
1190 *****************************************************************/
1192 bool lookup_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
1193 const char **ret_domain, const char **ret_name,
1194 enum lsa_SidType *ret_type)
1196 struct lsa_dom_info *domain;
1197 struct lsa_name_info *name;
1198 struct dom_sid_buf buf;
1199 TALLOC_CTX *tmp_ctx;
1200 bool ret = false;
1202 DEBUG(10, ("lookup_sid called for SID '%s'\n",
1203 dom_sid_str_buf(sid, &buf)));
1205 if (!(tmp_ctx = talloc_new(mem_ctx))) {
1206 DEBUG(0, ("talloc_new failed\n"));
1207 return false;
1210 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
1211 &domain, &name))) {
1212 goto done;
1215 if (name->type == SID_NAME_UNKNOWN) {
1216 goto done;
1219 if ((ret_domain != NULL) &&
1220 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
1221 goto done;
1224 if ((ret_name != NULL) &&
1225 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
1226 goto done;
1229 if (ret_type != NULL) {
1230 *ret_type = name->type;
1233 ret = true;
1235 done:
1236 if (ret) {
1237 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
1238 dom_sid_str_buf(sid, &buf),
1239 domain->name, name->name, name->type));
1240 } else {
1241 DEBUG(10, ("failed to lookup sid %s\n",
1242 dom_sid_str_buf(sid, &buf)));
1244 TALLOC_FREE(tmp_ctx);
1245 return ret;
1248 /*****************************************************************
1249 *THE LEGACY* convert SID to id function.
1250 *****************************************************************/
1252 static bool legacy_sid_to_unixid(const struct dom_sid *psid, struct unixid *id)
1254 bool ret;
1256 become_root();
1257 ret = pdb_sid_to_id(psid, id);
1258 unbecome_root();
1260 if (!ret) {
1261 struct dom_sid_buf buf;
1262 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1263 dom_sid_str_buf(psid, &buf)));
1264 return false;
1267 return true;
1270 static bool legacy_sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1272 struct unixid id;
1273 if (!legacy_sid_to_unixid(psid, &id)) {
1274 return false;
1276 if (id.type == ID_TYPE_GID || id.type == ID_TYPE_BOTH) {
1277 *pgid = id.id;
1278 return true;
1280 return false;
1283 static bool legacy_sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1285 struct unixid id;
1286 if (!legacy_sid_to_unixid(psid, &id)) {
1287 return false;
1289 if (id.type == ID_TYPE_UID || id.type == ID_TYPE_BOTH) {
1290 *puid = id.id;
1291 return true;
1293 return false;
1296 void xid_to_sid(struct dom_sid *psid, const struct unixid *xid)
1298 bool expired = true;
1299 bool ret;
1300 struct dom_sid_buf buf;
1302 SMB_ASSERT(xid->type == ID_TYPE_UID || xid->type == ID_TYPE_GID);
1304 *psid = (struct dom_sid) {0};
1306 ret = idmap_cache_find_xid2sid(xid, psid, &expired);
1307 if (ret && !expired) {
1308 DBG_DEBUG("%cID %"PRIu32" -> %s from cache\n",
1309 xid->type == ID_TYPE_UID ? 'U' : 'G',
1310 xid->id,
1311 dom_sid_str_buf(psid, &buf));
1312 goto done;
1315 ret = winbind_xid_to_sid(psid, xid);
1316 if (ret) {
1318 * winbind can return an explicit negative mapping
1319 * here. It's up to winbind to prime the cache either
1320 * positively or negatively, don't mess with the cache
1321 * here.
1323 DBG_DEBUG("%cID %"PRIu32" -> %s from cache\n",
1324 xid->type == ID_TYPE_UID ? 'U' : 'G',
1325 xid->id,
1326 dom_sid_str_buf(psid, &buf));
1327 goto done;
1332 * Make a copy, pdb_id_to_sid might want to turn
1333 * xid->type into ID_TYPE_BOTH, which we ignore here.
1335 struct unixid rw_xid = *xid;
1337 become_root();
1338 ret = pdb_id_to_sid(&rw_xid, psid);
1339 unbecome_root();
1342 if (ret) {
1343 DBG_DEBUG("%cID %"PRIu32" -> %s from passdb\n",
1344 xid->type == ID_TYPE_UID ? 'U' : 'G',
1345 xid->id,
1346 dom_sid_str_buf(psid, &buf));
1347 goto done;
1350 done:
1351 if (is_null_sid(psid)) {
1353 * Nobody found anything: Return S-1-22-xx-yy. Don't
1354 * store that in caches, this is up to the layers
1355 * beneath us.
1357 if (xid->type == ID_TYPE_UID) {
1358 uid_to_unix_users_sid(xid->id, psid);
1359 } else {
1360 gid_to_unix_groups_sid(xid->id, psid);
1363 DBG_DEBUG("%cID %"PRIu32" -> %s fallback\n",
1364 xid->type == ID_TYPE_UID ? 'U' : 'G',
1365 xid->id,
1366 dom_sid_str_buf(psid, &buf));
1370 void uid_to_sid(struct dom_sid *psid, uid_t uid)
1372 struct unixid xid = { .type = ID_TYPE_UID, .id = uid};
1373 xid_to_sid(psid, &xid);
1376 void gid_to_sid(struct dom_sid *psid, gid_t gid)
1378 struct unixid xid = { .type = ID_TYPE_GID, .id = gid};
1379 xid_to_sid(psid, &xid);
1382 bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
1383 struct unixid *ids)
1385 struct wbcDomainSid *wbc_sids = NULL;
1386 struct wbcUnixId *wbc_ids = NULL;
1387 struct bitmap *found = NULL;
1388 uint32_t i, num_not_cached;
1389 uint32_t wbc_ids_size = 0;
1390 wbcErr err;
1391 bool ret = false;
1393 wbc_sids = talloc_array(talloc_tos(), struct wbcDomainSid, num_sids);
1394 if (wbc_sids == NULL) {
1395 return false;
1397 found = bitmap_talloc(wbc_sids, num_sids);
1398 if (found == NULL) {
1399 goto fail;
1403 * We go through the requested SID array three times.
1404 * First time to look for global_sid_Unix_Users
1405 * and global_sid_Unix_Groups SIDS, and to look
1406 * for mappings cached in the idmap_cache.
1408 * Use bitmap_set() to mark an ids[] array entry as
1409 * being mapped.
1412 num_not_cached = 0;
1414 for (i=0; i<num_sids; i++) {
1415 bool expired;
1416 uint32_t rid;
1418 if (sid_peek_check_rid(&global_sid_Unix_Users,
1419 &sids[i], &rid)) {
1420 ids[i].type = ID_TYPE_UID;
1421 ids[i].id = rid;
1422 bitmap_set(found, i);
1423 continue;
1425 if (sid_peek_check_rid(&global_sid_Unix_Groups,
1426 &sids[i], &rid)) {
1427 ids[i].type = ID_TYPE_GID;
1428 ids[i].id = rid;
1429 bitmap_set(found, i);
1430 continue;
1432 if (idmap_cache_find_sid2unixid(&sids[i], &ids[i], &expired)
1433 && !expired)
1435 bitmap_set(found, i);
1436 continue;
1438 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1439 memcpy(&wbc_sids[num_not_cached], &sids[i],
1440 ndr_size_dom_sid(&sids[i], 0));
1441 num_not_cached += 1;
1443 if (num_not_cached == 0) {
1444 goto done;
1448 * For the ones that we couldn't map in the loop above, query winbindd
1449 * via wbcSidsToUnixIds().
1452 wbc_ids_size = num_not_cached;
1453 wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, wbc_ids_size);
1454 if (wbc_ids == NULL) {
1455 goto fail;
1457 for (i=0; i<wbc_ids_size; i++) {
1458 wbc_ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1459 wbc_ids[i].id.gid = (uint32_t)-1;
1461 err = wbcSidsToUnixIds(wbc_sids, wbc_ids_size, wbc_ids);
1462 if (!WBC_ERROR_IS_OK(err)) {
1463 DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
1464 wbcErrorString(err)));
1468 * Second time through the SID array, replace
1469 * the ids[] entries that wbcSidsToUnixIds() was able to
1470 * map.
1472 * Use bitmap_set() to mark an ids[] array entry as
1473 * being mapped.
1476 num_not_cached = 0;
1478 for (i=0; i<num_sids; i++) {
1479 if (bitmap_query(found, i)) {
1480 continue;
1483 SMB_ASSERT(num_not_cached < wbc_ids_size);
1485 switch (wbc_ids[num_not_cached].type) {
1486 case WBC_ID_TYPE_UID:
1487 ids[i].type = ID_TYPE_UID;
1488 ids[i].id = wbc_ids[num_not_cached].id.uid;
1489 bitmap_set(found, i);
1490 break;
1491 case WBC_ID_TYPE_GID:
1492 ids[i].type = ID_TYPE_GID;
1493 ids[i].id = wbc_ids[num_not_cached].id.gid;
1494 bitmap_set(found, i);
1495 break;
1496 case WBC_ID_TYPE_BOTH:
1497 ids[i].type = ID_TYPE_BOTH;
1498 ids[i].id = wbc_ids[num_not_cached].id.uid;
1499 bitmap_set(found, i);
1500 break;
1501 case WBC_ID_TYPE_NOT_SPECIFIED:
1503 * wbcSidsToUnixIds() wasn't able to map this
1504 * so we still need to check legacy_sid_to_XXX()
1505 * below. Don't mark the bitmap entry
1506 * as being found so the final loop knows
1507 * to try and map this entry.
1509 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1510 ids[i].id = (uint32_t)-1;
1511 break;
1512 default:
1514 * A successful return from wbcSidsToUnixIds()
1515 * cannot return anything other than the values
1516 * checked for above. Ensure this is so.
1518 smb_panic(__location__);
1519 break;
1521 num_not_cached += 1;
1525 * Third and final time through the SID array,
1526 * try legacy_sid_to_gid()/legacy_sid_to_uid()
1527 * for entries we haven't already been able to
1528 * map.
1530 * Use bitmap_set() to mark an ids[] array entry as
1531 * being mapped.
1534 for (i=0; i<num_sids; i++) {
1535 if (bitmap_query(found, i)) {
1536 continue;
1538 if (legacy_sid_to_gid(&sids[i], &ids[i].id)) {
1539 ids[i].type = ID_TYPE_GID;
1540 bitmap_set(found, i);
1541 continue;
1543 if (legacy_sid_to_uid(&sids[i], &ids[i].id)) {
1544 ids[i].type = ID_TYPE_UID;
1545 bitmap_set(found, i);
1546 continue;
1549 done:
1551 * Pass through the return array for consistency.
1552 * Any ids[].id mapped to (uint32_t)-1 must be returned
1553 * as ID_TYPE_NOT_SPECIFIED.
1555 for (i=0; i<num_sids; i++) {
1556 switch(ids[i].type) {
1557 case ID_TYPE_GID:
1558 case ID_TYPE_UID:
1559 case ID_TYPE_BOTH:
1560 if (ids[i].id == (uint32_t)-1) {
1561 ids[i].type = ID_TYPE_NOT_SPECIFIED;
1563 break;
1564 case ID_TYPE_NOT_SPECIFIED:
1565 break;
1566 case ID_TYPE_WB_REQUIRE_TYPE:
1568 * these are internal between winbindd
1569 * parent and child.
1571 smb_panic(__location__);
1572 break;
1576 ret = true;
1577 fail:
1578 TALLOC_FREE(wbc_ids);
1579 TALLOC_FREE(wbc_sids);
1580 return ret;
1583 /*****************************************************************
1584 *THE CANONICAL* convert SID to uid function.
1585 *****************************************************************/
1587 bool sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1589 bool expired = true;
1590 bool ret;
1591 uint32_t rid;
1592 struct dom_sid_buf buf;
1594 /* Optimize for the Unix Users Domain
1595 * as the conversion is straightforward */
1596 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1597 uid_t uid = rid;
1598 *puid = uid;
1600 /* return here, don't cache */
1601 DEBUG(10,("sid %s -> uid %u\n",
1602 dom_sid_str_buf(psid, &buf),
1603 (unsigned int)*puid ));
1604 return true;
1607 if (sid_check_is_in_unix_groups(psid)) {
1608 DBG_DEBUG("SID %s is a group, failing\n",
1609 dom_sid_str_buf(psid, &buf));
1610 return false;
1613 /* Check the winbindd cache directly. */
1614 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1616 if (ret && !expired && (*puid == (uid_t)-1)) {
1618 * Negative cache entry, we already asked.
1619 * do legacy.
1621 return legacy_sid_to_uid(psid, puid);
1624 if (!ret || expired) {
1625 /* Not in cache. Ask winbindd. */
1626 if (!winbind_sid_to_uid(puid, psid)) {
1627 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1628 dom_sid_str_buf(psid, &buf)));
1629 /* winbind failed. do legacy */
1630 return legacy_sid_to_uid(psid, puid);
1634 /* TODO: Here would be the place to allocate both a gid and a uid for
1635 * the SID in question */
1637 DEBUG(10,("sid %s -> uid %u\n",
1638 dom_sid_str_buf(psid, &buf),
1639 (unsigned int)*puid ));
1641 return true;
1644 /*****************************************************************
1645 *THE CANONICAL* convert SID to gid function.
1646 Group mapping is used for gids that maps to Wellknown SIDs
1647 *****************************************************************/
1649 bool sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1651 bool expired = true;
1652 bool ret;
1653 uint32_t rid;
1654 struct dom_sid_buf buf;
1656 /* Optimize for the Unix Groups Domain
1657 * as the conversion is straightforward */
1658 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1659 gid_t gid = rid;
1660 *pgid = gid;
1662 /* return here, don't cache */
1663 DEBUG(10,("sid %s -> gid %u\n",
1664 dom_sid_str_buf(psid, &buf),
1665 (unsigned int)*pgid ));
1666 return true;
1669 if (sid_check_is_in_unix_users(psid)) {
1670 DBG_DEBUG("SID %s is a user, failing\n",
1671 dom_sid_str_buf(psid, &buf));
1672 return false;
1675 /* Check the winbindd cache directly. */
1676 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1678 if (ret && !expired && (*pgid == (gid_t)-1)) {
1680 * Negative cache entry, we already asked.
1681 * do legacy.
1683 return legacy_sid_to_gid(psid, pgid);
1686 if (!ret || expired) {
1687 /* Not in cache or negative. Ask winbindd. */
1688 /* Ask winbindd if it can map this sid to a gid.
1689 * (Idmap will check it is a valid SID and of the right type) */
1691 if ( !winbind_sid_to_gid(pgid, psid) ) {
1693 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1694 dom_sid_str_buf(psid, &buf)));
1695 /* winbind failed. do legacy */
1696 return legacy_sid_to_gid(psid, pgid);
1700 DEBUG(10,("sid %s -> gid %u\n",
1701 dom_sid_str_buf(psid, &buf),
1702 (unsigned int)*pgid ));
1704 return true;
1708 * @brief This function gets the primary group SID mapping the primary
1709 * GID of the user as obtained by an actual getpwnam() call.
1710 * This is necessary to avoid issues with arbitrary group SIDs
1711 * stored in passdb. We try as hard as we can to get the SID
1712 * corresponding to the GID, including trying group mapping.
1713 * If nothing else works, we will force "Domain Users" as the
1714 * primary group.
1715 * This is needed because we must always be able to lookup the
1716 * primary group SID, so we cannot settle for an arbitrary SID.
1718 * This call can be expensive. Use with moderation.
1719 * If you have a "samu" struct around use pdb_get_group_sid()
1720 * instead as it does properly cache results.
1722 * @param mem_ctx[in] The memory context iused to allocate the result.
1723 * @param username[in] The user's name
1724 * @param _pwd[in|out] If available, pass in user's passwd struct.
1725 * It will contain a tallocated passwd if NULL was
1726 * passed in.
1727 * @param _group_sid[out] The user's Primary Group SID
1729 * @return NTSTATUS error code.
1731 NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx,
1732 const char *username,
1733 struct passwd **_pwd,
1734 struct dom_sid **_group_sid)
1736 TALLOC_CTX *tmp_ctx;
1737 bool need_lookup_sid = false;
1738 struct dom_sid *group_sid;
1739 struct passwd *pwd = *_pwd;
1741 tmp_ctx = talloc_new(mem_ctx);
1742 if (!tmp_ctx) {
1743 return NT_STATUS_NO_MEMORY;
1746 if (!pwd) {
1747 pwd = Get_Pwnam_alloc(mem_ctx, username);
1748 if (!pwd) {
1749 DEBUG(0, ("Failed to find a Unix account for %s\n",
1750 username));
1751 TALLOC_FREE(tmp_ctx);
1752 return NT_STATUS_NO_SUCH_USER;
1756 group_sid = talloc_zero(mem_ctx, struct dom_sid);
1757 if (!group_sid) {
1758 TALLOC_FREE(tmp_ctx);
1759 return NT_STATUS_NO_MEMORY;
1762 gid_to_sid(group_sid, pwd->pw_gid);
1763 if (!is_null_sid(group_sid)) {
1764 struct dom_sid domain_sid;
1765 uint32_t rid;
1767 /* We need a sid within our domain */
1768 sid_copy(&domain_sid, group_sid);
1769 sid_split_rid(&domain_sid, &rid);
1770 if (dom_sid_equal(&domain_sid, get_global_sam_sid())) {
1772 * As shortcut for the expensive lookup_sid call
1773 * compare the domain sid part
1775 switch (rid) {
1776 case DOMAIN_RID_ADMINS:
1777 case DOMAIN_RID_USERS:
1778 goto done;
1779 default:
1780 need_lookup_sid = true;
1781 break;
1783 } else {
1784 /* Try group mapping */
1785 struct unixid id;
1787 id.id = pwd->pw_gid;
1788 id.type = ID_TYPE_GID;
1790 ZERO_STRUCTP(group_sid);
1791 if (pdb_id_to_sid(&id, group_sid)) {
1792 need_lookup_sid = true;
1797 /* We must verify that this is a valid SID that resolves to a
1798 * group of the correct type */
1799 if (need_lookup_sid) {
1800 enum lsa_SidType type = SID_NAME_UNKNOWN;
1801 bool lookup_ret;
1802 struct dom_sid_buf buf;
1804 DEBUG(10, ("do lookup_sid(%s) for group of user %s\n",
1805 dom_sid_str_buf(group_sid, &buf),
1806 username));
1808 /* Now check that it's actually a domain group and
1809 * not something else */
1810 lookup_ret = lookup_sid(tmp_ctx, group_sid,
1811 NULL, NULL, &type);
1813 if (lookup_ret && (type == SID_NAME_DOM_GRP)) {
1814 goto done;
1817 DEBUG(3, ("Primary group %s for user %s is"
1818 " a %s and not a domain group\n",
1819 dom_sid_str_buf(group_sid, &buf),
1820 username,
1821 sid_type_lookup(type)));
1824 /* Everything else, failed.
1825 * Just set it to the 'Domain Users' RID of 513 which will
1826 always resolve to a name */
1827 DEBUG(3, ("Forcing Primary Group to 'Domain Users' for %s\n",
1828 username));
1830 sid_compose(group_sid, get_global_sam_sid(), DOMAIN_RID_USERS);
1832 done:
1833 *_pwd = talloc_move(mem_ctx, &pwd);
1834 *_group_sid = talloc_move(mem_ctx, &group_sid);
1835 TALLOC_FREE(tmp_ctx);
1836 return NT_STATUS_OK;