2 Unix SMB/CIFS implementation.
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/>.
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
30 *****************************************************************/
32 #define LN_CHECK_TALLOC(var, memctx) do { \
34 DEBUG(0, ("talloc failed\n")); \
35 TALLOC_FREE(memctx); \
40 bool lookup_name(TALLOC_CTX *mem_ctx,
41 const char *full_name, int flags,
42 const char **ret_domain, const char **ret_name,
43 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
49 p = strchr_m(full_name, '\\');
52 domain = talloc_strndup(mem_ctx, full_name,
53 PTR_DIFF(p, full_name));
54 name = talloc_strdup(mem_ctx, p+1);
57 name = talloc_strdup(mem_ctx, full_name);
60 if (((p != NULL) && (domain == NULL)) || (name == NULL)) {
61 DEBUG(0, ("talloc failed\n"));
65 DEBUG(10,("lookup_domain_name: %s => %s (domain), %s (name)\n",
66 full_name, domain, name));
68 res = lookup_domain_name(mem_ctx, domain, name, flags,
69 ret_domain, ret_name, ret_sid, ret_type);
77 bool lookup_domain_name(TALLOC_CTX *mem_ctx,
78 const char *domain, const char *name, int flags,
79 const char **ret_domain, const char **ret_name,
80 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
83 const char *domain_new = NULL;
86 enum lsa_SidType type;
89 tmp_ctx = talloc_new(mem_ctx);
90 if (tmp_ctx == NULL) {
91 DEBUG(0, ("talloc_new failed\n"));
95 if (!domain) domain = talloc_strdup(tmp_ctx, "");
96 LN_CHECK_TALLOC(domain, tmp_ctx);
98 DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
100 if ((flags & LOOKUP_NAME_DOMAIN) &&
101 strequal(domain, get_global_sam_name()))
104 /* It's our own domain, lookup the name in passdb */
105 if (lookup_global_sam_name(name, flags, &rid, &type)) {
106 sid_copy(&sid, get_global_sam_sid());
107 sid_append_rid(&sid, rid);
110 TALLOC_FREE(tmp_ctx);
114 if ((flags & LOOKUP_NAME_BUILTIN) &&
115 strequal(domain, builtin_domain_name()))
117 /* Explicit request for a name in BUILTIN */
118 if (lookup_builtin_name(name, &rid)) {
119 sid_copy(&sid, &global_sid_Builtin);
120 sid_append_rid(&sid, rid);
121 type = SID_NAME_ALIAS;
124 TALLOC_FREE(tmp_ctx);
128 /* Try the explicit winbind lookup first, don't let it guess the
129 * domain at this point yet. This comes later. */
131 if ((domain[0] != '\0') &&
132 (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
133 (winbind_lookup_name(domain, name, &sid, &type))) {
137 if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_users_domain_name())) {
138 if (lookup_unix_user_name(name, &sid)) {
139 type = SID_NAME_USER;
142 TALLOC_FREE(tmp_ctx);
146 if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_groups_domain_name())) {
147 if (lookup_unix_group_name(name, &sid)) {
148 type = SID_NAME_DOM_GRP;
151 TALLOC_FREE(tmp_ctx);
155 if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
156 TALLOC_FREE(tmp_ctx);
160 /* Now the guesswork begins, we haven't been given an explicit
161 * domain. Try the sequence as documented on
162 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
163 * November 27, 2005 */
165 /* 1. well-known names */
167 if ((flags & LOOKUP_NAME_WKN) &&
168 lookup_wellknown_name(tmp_ctx, name, &sid, &domain_new))
170 type = SID_NAME_WKN_GRP;
171 LN_CHECK_TALLOC(domain_new, tmp_ctx);
175 /* 2. Builtin domain as such */
177 if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
178 strequal(name, builtin_domain_name()))
180 /* Swap domain and name */
181 tmp = name; name = domain; domain = tmp;
182 sid_copy(&sid, &global_sid_Builtin);
183 type = SID_NAME_DOMAIN;
187 /* 3. Account domain */
189 if ((flags & LOOKUP_NAME_DOMAIN) &&
190 strequal(name, get_global_sam_name()))
192 if (!secrets_fetch_domain_sid(name, &sid)) {
193 DEBUG(3, ("Could not fetch my SID\n"));
194 TALLOC_FREE(tmp_ctx);
197 /* Swap domain and name */
198 tmp = name; name = domain; domain = tmp;
199 type = SID_NAME_DOMAIN;
203 /* 4. Primary domain */
205 if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
206 strequal(name, lp_workgroup()))
208 if (!secrets_fetch_domain_sid(name, &sid)) {
209 DEBUG(3, ("Could not fetch the domain SID\n"));
210 TALLOC_FREE(tmp_ctx);
213 /* Swap domain and name */
214 tmp = name; name = domain; domain = tmp;
215 type = SID_NAME_DOMAIN;
219 /* 5. Trusted domains as such, to me it looks as if members don't do
220 this, tested an XP workstation in a NT domain -- vl */
222 if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
223 (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
225 /* Swap domain and name */
226 tmp = name; name = domain; domain = tmp;
227 type = SID_NAME_DOMAIN;
231 /* 6. Builtin aliases */
233 if ((flags & LOOKUP_NAME_BUILTIN) &&
234 lookup_builtin_name(name, &rid))
236 domain_new = talloc_strdup(tmp_ctx, builtin_domain_name());
237 LN_CHECK_TALLOC(domain_new, tmp_ctx);
238 sid_copy(&sid, &global_sid_Builtin);
239 sid_append_rid(&sid, rid);
240 type = SID_NAME_ALIAS;
244 /* 7. Local systems' SAM (DCs don't have a local SAM) */
245 /* 8. Primary SAM (On members, this is the domain) */
247 /* Both cases are done by looking at our passdb */
249 if ((flags & LOOKUP_NAME_DOMAIN) &&
250 lookup_global_sam_name(name, flags, &rid, &type))
252 domain_new = talloc_strdup(tmp_ctx, get_global_sam_name());
253 LN_CHECK_TALLOC(domain_new, tmp_ctx);
254 sid_copy(&sid, get_global_sam_sid());
255 sid_append_rid(&sid, rid);
259 /* Now our local possibilities are exhausted. */
261 if (!(flags & LOOKUP_NAME_REMOTE)) {
262 TALLOC_FREE(tmp_ctx);
266 /* If we are not a DC, we have to ask in our primary domain. Let
267 * winbind do that. */
270 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
271 domain_new = talloc_strdup(tmp_ctx, lp_workgroup());
272 LN_CHECK_TALLOC(domain_new, tmp_ctx);
276 /* 9. Trusted domains */
278 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
279 * that (yet), but give it a chance. */
281 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
284 enum lsa_SidType domain_type;
286 if (type == SID_NAME_DOMAIN) {
287 /* Swap name and type */
288 tmp = name; name = domain; domain = tmp;
292 /* Here we have to cope with a little deficiency in the
293 * winbind API: We have to ask it again for the name of the
294 * domain it figured out itself. Maybe fix that later... */
296 sid_copy(&dom_sid, &sid);
297 sid_split_rid(&dom_sid, &tmp_rid);
299 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
301 (domain_type != SID_NAME_DOMAIN)) {
302 DEBUG(2, ("winbind could not find the domain's name "
303 "it just looked up for us\n"));
304 TALLOC_FREE(tmp_ctx);
307 LN_CHECK_TALLOC(domain_new, tmp_ctx);
311 /* 10. Don't translate */
313 /* 11. Ok, windows would end here. Samba has two more options:
314 Unmapped users and unmapped groups */
316 if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_user_name(name, &sid)) {
317 domain_new = talloc_strdup(tmp_ctx, unix_users_domain_name());
318 LN_CHECK_TALLOC(domain_new, tmp_ctx);
319 type = SID_NAME_USER;
323 if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_group_name(name, &sid)) {
324 domain_new = talloc_strdup(tmp_ctx, unix_groups_domain_name());
325 LN_CHECK_TALLOC(domain_new, tmp_ctx);
326 type = SID_NAME_DOM_GRP;
331 * Ok, all possibilities tried. Fail.
334 TALLOC_FREE(tmp_ctx);
339 * Hand over the results to the talloc context we've been given.
342 if ((ret_name != NULL) &&
343 !(*ret_name = talloc_strdup(mem_ctx, name))) {
344 DEBUG(0, ("talloc failed\n"));
345 TALLOC_FREE(tmp_ctx);
349 if (ret_domain != NULL) {
353 tmp_dom = talloc_steal(mem_ctx, (char *)domain_new);
355 tmp_dom = talloc_strdup(mem_ctx, domain);
357 LN_CHECK_TALLOC(tmp_dom, tmp_ctx);
360 *ret_domain = tmp_dom;
363 if (ret_sid != NULL) {
364 sid_copy(ret_sid, &sid);
367 if (ret_type != NULL) {
371 TALLOC_FREE(tmp_ctx);
375 /************************************************************************
376 Names from smb.conf can be unqualified. eg. valid users = foo
377 These names should never map to a remote name. Try global_sam_name()\foo,
378 and then "Unix Users"\foo (or "Unix Groups"\foo).
379 ************************************************************************/
381 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
382 const char *full_name, int flags,
383 const char **ret_domain, const char **ret_name,
384 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
388 p = strchr_m(full_name, *lp_winbind_separator());
393 name = talloc_strdup(mem_ctx, full_name);
395 DEBUG(0, ("Out of memory!\n"));
398 name[PTR_DIFF(p, full_name)] = '\\';
400 res = lookup_name(mem_ctx, name, flags,
401 ret_domain, ret_name,
407 /* Try with our own SAM name. */
408 if (lookup_domain_name(mem_ctx,
409 get_global_sam_name(), full_name, flags,
410 ret_domain, ret_name, ret_sid, ret_type)) {
414 /* Finally try with "Unix Users" or "Unix Group" */
415 return lookup_domain_name(mem_ctx,
416 flags & LOOKUP_NAME_GROUP ?
417 unix_groups_domain_name() :
418 unix_users_domain_name(),
420 ret_domain, ret_name, ret_sid, ret_type);
424 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
425 const DOM_SID *domain_sid,
426 int num_rids, uint32 *rids,
427 const char **domain_name,
428 const char **names, enum lsa_SidType *types)
431 const char **my_names;
432 enum lsa_SidType *my_types;
435 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
439 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
440 domain_name, &my_names, &my_types)) {
442 for (i=0; i<num_rids; i++) {
444 types[i] = SID_NAME_UNKNOWN;
446 TALLOC_FREE(tmp_ctx);
450 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
451 TALLOC_FREE(tmp_ctx);
456 * winbind_lookup_rids allocates its own array. We've been given the
457 * array, so copy it over
460 for (i=0; i<num_rids; i++) {
461 if (my_names[i] == NULL) {
462 TALLOC_FREE(tmp_ctx);
465 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
466 TALLOC_FREE(tmp_ctx);
469 types[i] = my_types[i];
471 TALLOC_FREE(tmp_ctx);
475 static bool lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
476 int num_rids, uint32_t *rids,
477 const char **domain_name,
478 const char ***names, enum lsa_SidType **types)
482 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
483 sid_string_dbg(domain_sid)));
486 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
487 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
489 if ((*names == NULL) || (*types == NULL)) {
497 if (sid_check_is_domain(domain_sid)) {
500 if (*domain_name == NULL) {
501 *domain_name = talloc_strdup(
502 mem_ctx, get_global_sam_name());
505 if (*domain_name == NULL) {
510 result = pdb_lookup_rids(domain_sid, num_rids, rids,
514 return (NT_STATUS_IS_OK(result) ||
515 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
516 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
519 if (sid_check_is_builtin(domain_sid)) {
521 if (*domain_name == NULL) {
522 *domain_name = talloc_strdup(
523 mem_ctx, builtin_domain_name());
526 if (*domain_name == NULL) {
530 for (i=0; i<num_rids; i++) {
531 if (lookup_builtin_rid(*names, rids[i],
533 if ((*names)[i] == NULL) {
536 (*types)[i] = SID_NAME_ALIAS;
538 (*types)[i] = SID_NAME_UNKNOWN;
544 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
545 for (i=0; i<num_rids; i++) {
547 sid_copy(&sid, domain_sid);
548 sid_append_rid(&sid, rids[i]);
549 if (lookup_wellknown_sid(mem_ctx, &sid,
550 domain_name, &(*names)[i])) {
551 if ((*names)[i] == NULL) {
554 (*types)[i] = SID_NAME_WKN_GRP;
556 (*types)[i] = SID_NAME_UNKNOWN;
562 if (sid_check_is_unix_users(domain_sid)) {
563 if (*domain_name == NULL) {
564 *domain_name = talloc_strdup(
565 mem_ctx, unix_users_domain_name());
566 if (*domain_name == NULL) {
570 for (i=0; i<num_rids; i++) {
571 (*names)[i] = talloc_strdup(
572 (*names), uidtoname(rids[i]));
573 if ((*names)[i] == NULL) {
576 (*types)[i] = SID_NAME_USER;
581 if (sid_check_is_unix_groups(domain_sid)) {
582 if (*domain_name == NULL) {
583 *domain_name = talloc_strdup(
584 mem_ctx, unix_groups_domain_name());
585 if (*domain_name == NULL) {
589 for (i=0; i<num_rids; i++) {
590 (*names)[i] = talloc_strdup(
591 (*names), gidtoname(rids[i]));
592 if ((*names)[i] == NULL) {
595 (*types)[i] = SID_NAME_DOM_GRP;
600 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
601 domain_name, *names, *types);
605 * Is the SID a domain as such? If yes, lookup its name.
608 static bool lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
612 enum lsa_SidType type;
614 if (sid_check_is_domain(sid)) {
615 *name = talloc_strdup(mem_ctx, get_global_sam_name());
619 if (sid_check_is_builtin(sid)) {
620 *name = talloc_strdup(mem_ctx, builtin_domain_name());
624 if (sid_check_is_wellknown_domain(sid, &tmp)) {
625 *name = talloc_strdup(mem_ctx, tmp);
629 if (sid_check_is_unix_users(sid)) {
630 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
634 if (sid_check_is_unix_groups(sid)) {
635 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
639 if (sid->num_auths != 4) {
640 /* This can't be a domain */
645 uint32 i, num_domains;
646 struct trustdom_info **domains;
648 /* This is relatively expensive, but it happens only on DCs
649 * and for SIDs that have 4 sub-authorities and thus look like
652 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
658 for (i=0; i<num_domains; i++) {
659 if (sid_equal(sid, &domains[i]->sid)) {
660 *name = talloc_strdup(mem_ctx,
668 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
669 (type == SID_NAME_DOMAIN)) {
678 * This tries to implement the rather weird rules for the lsa_lookup level
681 * This is as close as we can get to what W2k3 does. With this we survive the
682 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
683 * different, but I assume that's just being too liberal. For example, W2k3
684 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
685 * whereas NT4 does the same as level 1 (I think). I did not fully test that
686 * with NT4, this is what w2k3 does.
688 * Level 1: Ask everywhere
689 * Level 2: Ask domain and trusted domains, no builtin and wkn
690 * Level 3: Only ask domain
691 * Level 4: W2k3ad: Only ask AD trusts
692 * Level 5: Only ask transitive forest trusts
696 static bool check_dom_sid_to_level(const DOM_SID *sid, int level)
705 ret = (!sid_check_is_builtin(sid) &&
706 !sid_check_is_wellknown_domain(sid, NULL));
711 ret = sid_check_is_domain(sid);
718 DEBUG(10, ("%s SID %s in level %d\n",
719 ret ? "Accepting" : "Rejecting",
720 sid_string_dbg(sid), level));
725 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
726 * references to domains, it is explicitly made for this.
728 * This attempts to be as efficient as possible: It collects all SIDs
729 * belonging to a domain and hands them in bulk to the appropriate lookup
730 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
731 * *hugely* from this. Winbind is going to be extended with a lookup_rids
732 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
736 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
737 const DOM_SID **sids, int level,
738 struct lsa_dom_info **ret_domains,
739 struct lsa_name_info **ret_names)
742 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
743 struct lsa_name_info *name_infos;
744 struct lsa_dom_info *dom_infos = NULL;
748 if (!(tmp_ctx = talloc_new(mem_ctx))) {
749 DEBUG(0, ("talloc_new failed\n"));
750 return NT_STATUS_NO_MEMORY;
754 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
755 if (name_infos == NULL) {
756 result = NT_STATUS_NO_MEMORY;
763 dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
765 if (dom_infos == NULL) {
766 result = NT_STATUS_NO_MEMORY;
770 /* First build up the data structures:
772 * dom_infos is a list of domains referenced in the list of
773 * SIDs. Later we will walk the list of domains and look up the RIDs
776 * name_infos is a shadow-copy of the SIDs array to collect the real
779 * dom_info->idxs is an index into the name_infos array. The
780 * difficulty we have here is that we need to keep the SIDs the client
781 * asked for in the same order for the reply
784 for (i=0; i<num_sids; i++) {
787 const char *domain_name = NULL;
789 sid_copy(&sid, sids[i]);
790 name_infos[i].type = SID_NAME_USE_NONE;
792 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
793 /* We can't push that through the normal lookup
794 * process, as this would reference illegal
797 * For example S-1-5-32 would end up referencing
798 * domain S-1-5- with RID 32 which is clearly wrong.
800 if (domain_name == NULL) {
801 result = NT_STATUS_NO_MEMORY;
805 name_infos[i].rid = 0;
806 name_infos[i].type = SID_NAME_DOMAIN;
807 name_infos[i].name = NULL;
809 if (sid_check_is_builtin(&sid)) {
810 /* Yes, W2k3 returns "BUILTIN" both as domain
812 name_infos[i].name = talloc_strdup(
813 name_infos, builtin_domain_name());
814 if (name_infos[i].name == NULL) {
815 result = NT_STATUS_NO_MEMORY;
820 /* This is a normal SID with rid component */
821 if (!sid_split_rid(&sid, &rid)) {
822 result = NT_STATUS_INVALID_PARAMETER;
827 if (!check_dom_sid_to_level(&sid, level)) {
828 name_infos[i].rid = 0;
829 name_infos[i].type = SID_NAME_UNKNOWN;
830 name_infos[i].name = NULL;
834 for (j=0; j<MAX_REF_DOMAINS; j++) {
835 if (!dom_infos[j].valid) {
838 if (sid_equal(&sid, &dom_infos[j].sid)) {
843 if (j == MAX_REF_DOMAINS) {
844 /* TODO: What's the right error message here? */
845 result = NT_STATUS_NONE_MAPPED;
849 if (!dom_infos[j].valid) {
850 /* We found a domain not yet referenced, create a new
852 dom_infos[j].valid = true;
853 sid_copy(&dom_infos[j].sid, &sid);
855 if (domain_name != NULL) {
856 /* This name was being found above in the case
857 * when we found a domain SID */
859 talloc_strdup(dom_infos, domain_name);
860 if (dom_infos[j].name == NULL) {
861 result = NT_STATUS_NO_MEMORY;
865 /* lookup_rids will take care of this */
866 dom_infos[j].name = NULL;
870 name_infos[i].dom_idx = j;
872 if (name_infos[i].type == SID_NAME_USE_NONE) {
873 name_infos[i].rid = rid;
875 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
876 &dom_infos[j].num_idxs);
878 if (dom_infos[j].idxs == NULL) {
879 result = NT_STATUS_NO_MEMORY;
885 /* Iterate over the domains found */
887 for (i=0; i<MAX_REF_DOMAINS; i++) {
889 const char *domain_name = NULL;
891 enum lsa_SidType *types;
892 struct lsa_dom_info *dom = &dom_infos[i];
895 /* No domains left, we're done */
900 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
901 result = NT_STATUS_NO_MEMORY;
908 for (j=0; j<dom->num_idxs; j++) {
909 rids[j] = name_infos[dom->idxs[j]].rid;
912 if (!lookup_rids(tmp_ctx, &dom->sid,
913 dom->num_idxs, rids, &domain_name,
915 result = NT_STATUS_NO_MEMORY;
919 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
920 result = NT_STATUS_NO_MEMORY;
924 for (j=0; j<dom->num_idxs; j++) {
925 int idx = dom->idxs[j];
926 name_infos[idx].type = types[j];
927 if (types[j] != SID_NAME_UNKNOWN) {
928 name_infos[idx].name =
929 talloc_strdup(name_infos, names[j]);
930 if (name_infos[idx].name == NULL) {
931 result = NT_STATUS_NO_MEMORY;
935 name_infos[idx].name = NULL;
940 *ret_domains = dom_infos;
941 *ret_names = name_infos;
942 TALLOC_FREE(tmp_ctx);
946 TALLOC_FREE(dom_infos);
947 TALLOC_FREE(name_infos);
948 TALLOC_FREE(tmp_ctx);
952 /*****************************************************************
953 *THE CANONICAL* convert SID to name function.
954 *****************************************************************/
956 bool lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
957 const char **ret_domain, const char **ret_name,
958 enum lsa_SidType *ret_type)
960 struct lsa_dom_info *domain;
961 struct lsa_name_info *name;
965 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
967 if (!(tmp_ctx = talloc_new(mem_ctx))) {
968 DEBUG(0, ("talloc_new failed\n"));
972 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
977 if (name->type == SID_NAME_UNKNOWN) {
981 if ((ret_domain != NULL) &&
982 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
986 if ((ret_name != NULL) &&
987 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
991 if (ret_type != NULL) {
992 *ret_type = name->type;
999 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
1000 domain->name, name->name, name->type));
1002 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
1004 TALLOC_FREE(tmp_ctx);
1008 /*****************************************************************
1009 Id mapping cache. This is to avoid Winbind mappings already
1010 seen by smbd to be queried too frequently, keeping winbindd
1011 busy, and blocking smbd while winbindd is busy with other
1012 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1013 modified to use linked lists by jra.
1014 *****************************************************************/
1016 /*****************************************************************
1017 Find a SID given a uid.
1018 *****************************************************************/
1020 static bool fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
1022 DATA_BLOB cache_value;
1024 if (!memcache_lookup(NULL, UID_SID_CACHE,
1025 data_blob_const(&uid, sizeof(uid)),
1030 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1031 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1032 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, 0));
1037 /*****************************************************************
1038 Find a uid given a SID.
1039 *****************************************************************/
1041 static bool fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
1043 DATA_BLOB cache_value;
1045 if (!memcache_lookup(NULL, SID_UID_CACHE,
1046 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1051 SMB_ASSERT(cache_value.length == sizeof(*puid));
1052 memcpy(puid, cache_value.data, sizeof(*puid));
1057 /*****************************************************************
1058 Store uid to SID mapping in cache.
1059 *****************************************************************/
1061 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
1063 memcache_add(NULL, SID_UID_CACHE,
1064 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1065 data_blob_const(&uid, sizeof(uid)));
1066 memcache_add(NULL, UID_SID_CACHE,
1067 data_blob_const(&uid, sizeof(uid)),
1068 data_blob_const(psid, ndr_size_dom_sid(psid, 0)));
1071 /*****************************************************************
1072 Find a SID given a gid.
1073 *****************************************************************/
1075 static bool fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1077 DATA_BLOB cache_value;
1079 if (!memcache_lookup(NULL, GID_SID_CACHE,
1080 data_blob_const(&gid, sizeof(gid)),
1085 memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1086 SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1087 SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, 0));
1092 /*****************************************************************
1093 Find a gid given a SID.
1094 *****************************************************************/
1096 static bool fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1098 DATA_BLOB cache_value;
1100 if (!memcache_lookup(NULL, SID_UID_CACHE,
1101 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1106 SMB_ASSERT(cache_value.length == sizeof(*pgid));
1107 memcpy(pgid, cache_value.data, sizeof(*pgid));
1112 /*****************************************************************
1113 Store gid to SID mapping in cache.
1114 *****************************************************************/
1116 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1118 memcache_add(NULL, SID_GID_CACHE,
1119 data_blob_const(psid, ndr_size_dom_sid(psid, 0)),
1120 data_blob_const(&gid, sizeof(gid)));
1121 memcache_add(NULL, GID_SID_CACHE,
1122 data_blob_const(&gid, sizeof(gid)),
1123 data_blob_const(psid, ndr_size_dom_sid(psid, 0)));
1126 /*****************************************************************
1127 *THE LEGACY* convert uid_t to SID function.
1128 *****************************************************************/
1130 static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
1138 ret = pdb_uid_to_rid(uid, &rid);
1142 /* This is a mapped user */
1143 sid_copy(psid, get_global_sam_sid());
1144 sid_append_rid(psid, rid);
1148 /* This is an unmapped user */
1150 uid_to_unix_users_sid(uid, psid);
1153 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1154 sid_string_dbg(psid)));
1156 store_uid_sid_cache(psid, uid);
1160 /*****************************************************************
1161 *THE LEGACY* convert gid_t to SID function.
1162 *****************************************************************/
1164 static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
1171 ret = pdb_gid_to_sid(gid, psid);
1175 /* This is a mapped group */
1179 /* This is an unmapped group */
1181 gid_to_unix_groups_sid(gid, psid);
1184 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1185 sid_string_dbg(psid)));
1187 store_gid_sid_cache(psid, gid);
1191 /*****************************************************************
1192 *THE LEGACY* convert SID to uid function.
1193 *****************************************************************/
1195 static bool legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
1197 enum lsa_SidType type;
1200 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1205 ret = pdb_sid_to_id(psid, &id, &type);
1209 if (type != SID_NAME_USER) {
1210 DEBUG(5, ("sid %s is a %s, expected a user\n",
1211 sid_string_dbg(psid),
1212 sid_type_lookup(type)));
1219 /* This was ours, but it was not mapped. Fail */
1222 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1223 sid_string_dbg(psid)));
1227 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_dbg(psid),
1228 (unsigned int)*puid ));
1230 store_uid_sid_cache(psid, *puid);
1234 /*****************************************************************
1235 *THE LEGACY* convert SID to gid function.
1236 Group mapping is used for gids that maps to Wellknown SIDs
1237 *****************************************************************/
1239 static bool legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1244 enum lsa_SidType type;
1246 if ((sid_check_is_in_builtin(psid) ||
1247 sid_check_is_in_wellknown_domain(psid))) {
1251 ret = pdb_getgrsid(&map, *psid);
1258 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1259 sid_string_dbg(psid)));
1263 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1267 ret = pdb_sid_to_id(psid, &id, &type);
1271 if ((type != SID_NAME_DOM_GRP) &&
1272 (type != SID_NAME_ALIAS)) {
1273 DEBUG(5, ("LEGACY: sid %s is a %s, expected "
1274 "a group\n", sid_string_dbg(psid),
1275 sid_type_lookup(type)));
1282 /* This was ours, but it was not mapped. Fail */
1285 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1286 sid_string_dbg(psid)));
1290 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_dbg(psid),
1291 (unsigned int)*pgid ));
1293 store_gid_sid_cache(psid, *pgid);
1298 /*****************************************************************
1299 *THE CANONICAL* convert uid_t to SID function.
1300 *****************************************************************/
1302 void uid_to_sid(DOM_SID *psid, uid_t uid)
1304 bool expired = true;
1308 if (fetch_sid_from_uid_cache(psid, uid))
1311 /* Check the winbindd cache directly. */
1312 ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1314 if (!ret || expired || (ret && is_null_sid(psid))) {
1315 /* Not in cache. Ask winbindd. */
1316 if (!winbind_uid_to_sid(psid, uid)) {
1317 if (!winbind_ping()) {
1318 legacy_uid_to_sid(psid, uid);
1322 DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n",
1328 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1329 sid_string_dbg(psid)));
1331 store_uid_sid_cache(psid, uid);
1335 /*****************************************************************
1336 *THE CANONICAL* convert gid_t to SID function.
1337 *****************************************************************/
1339 void gid_to_sid(DOM_SID *psid, gid_t gid)
1341 bool expired = true;
1345 if (fetch_sid_from_gid_cache(psid, gid))
1348 /* Check the winbindd cache directly. */
1349 ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1351 if (!ret || expired || (ret && is_null_sid(psid))) {
1352 /* Not in cache. Ask winbindd. */
1353 if (!winbind_gid_to_sid(psid, gid)) {
1354 if (!winbind_ping()) {
1355 legacy_gid_to_sid(psid, gid);
1359 DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n",
1365 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1366 sid_string_dbg(psid)));
1368 store_gid_sid_cache(psid, gid);
1372 /*****************************************************************
1373 *THE CANONICAL* convert SID to uid function.
1374 *****************************************************************/
1376 bool sid_to_uid(const DOM_SID *psid, uid_t *puid)
1378 bool expired = true;
1383 if (fetch_uid_from_cache(puid, psid))
1386 if (fetch_gid_from_cache(&gid, psid)) {
1390 /* Optimize for the Unix Users Domain
1391 * as the conversion is straightforward */
1392 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1396 /* return here, don't cache */
1397 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1398 (unsigned int)*puid ));
1402 /* Check the winbindd cache directly. */
1403 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1405 if (!ret || expired || (ret && (*puid == (uid_t)-1))) {
1406 /* Not in cache. Ask winbindd. */
1407 if (!winbind_sid_to_uid(puid, psid)) {
1408 if (!winbind_ping()) {
1409 return legacy_sid_to_uid(psid, puid);
1412 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1413 sid_string_dbg(psid)));
1418 /* TODO: Here would be the place to allocate both a gid and a uid for
1419 * the SID in question */
1421 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1422 (unsigned int)*puid ));
1424 store_uid_sid_cache(psid, *puid);
1428 /*****************************************************************
1429 *THE CANONICAL* convert SID to gid function.
1430 Group mapping is used for gids that maps to Wellknown SIDs
1431 *****************************************************************/
1433 bool sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1435 bool expired = true;
1440 if (fetch_gid_from_cache(pgid, psid))
1443 if (fetch_uid_from_cache(&uid, psid))
1446 /* Optimize for the Unix Groups Domain
1447 * as the conversion is straightforward */
1448 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1452 /* return here, don't cache */
1453 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1454 (unsigned int)*pgid ));
1458 /* Check the winbindd cache directly. */
1459 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1461 if (!ret || expired || (ret && (*pgid == (gid_t)-1))) {
1462 /* Not in cache or negative. Ask winbindd. */
1463 /* Ask winbindd if it can map this sid to a gid.
1464 * (Idmap will check it is a valid SID and of the right type) */
1466 if ( !winbind_sid_to_gid(pgid, psid) ) {
1467 if (!winbind_ping()) {
1468 return legacy_sid_to_gid(psid, pgid);
1471 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1472 sid_string_dbg(psid)));
1477 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1478 (unsigned int)*pgid ));
1480 store_gid_sid_cache(psid, *pgid);