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 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
)
39 const char *domain
= NULL
;
40 const char *name
= NULL
;
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"));
51 p
= strchr_m(full_name
, '\\');
54 domain
= talloc_strndup(tmp_ctx
, full_name
,
55 PTR_DIFF(p
, full_name
));
56 name
= talloc_strdup(tmp_ctx
, p
+1);
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"));
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
);
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
;
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
))) {
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
;
114 TALLOC_FREE(tmp_ctx
);
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
;
123 TALLOC_FREE(tmp_ctx
);
127 if ((domain
[0] == '\0') && (!(flags
& LOOKUP_NAME_ISOLATED
))) {
128 TALLOC_FREE(tmp_ctx
);
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
;
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
;
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
);
168 /* Swap domain and name */
169 tmp
= name
; name
= domain
; domain
= tmp
;
170 type
= SID_NAME_DOMAIN
;
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
);
184 /* Swap domain and name */
185 tmp
= name
; name
= domain
; domain
= tmp
;
186 type
= SID_NAME_DOMAIN
;
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
;
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
;
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
);
228 /* Now our local possibilities are exhausted. */
230 if (!(flags
& LOOKUP_NAME_REMOTE
)) {
231 TALLOC_FREE(tmp_ctx
);
235 /* If we are not a DC, we have to ask in our primary domain. Let
236 * winbind do that. */
239 (winbind_lookup_name(lp_workgroup(), name
, &sid
, &type
))) {
240 domain
= talloc_strdup(tmp_ctx
, lp_workgroup());
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
)) {
252 enum lsa_SidType domain_type
;
254 if (type
== SID_NAME_DOMAIN
) {
255 /* Swap name and type */
256 tmp
= name
; name
= domain
; domain
= tmp
;
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
,
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
);
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
;
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
;
296 * Ok, all possibilities tried. Fail.
299 TALLOC_FREE(tmp_ctx
);
303 if ((domain
== NULL
) || (name
== NULL
)) {
304 DEBUG(0, ("talloc failed\n"));
305 TALLOC_FREE(tmp_ctx
);
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
);
320 if (ret_domain
!= NULL
) {
322 if (!(tmp_dom
= talloc_strdup(mem_ctx
, domain
))) {
323 DEBUG(0, ("talloc failed\n"));
324 TALLOC_FREE(tmp_ctx
);
328 *ret_domain
= tmp_dom
;
331 if (ret_sid
!= NULL
) {
332 sid_copy(ret_sid
, &sid
);
335 if (ret_type
!= NULL
) {
339 TALLOC_FREE(tmp_ctx
);
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
;
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() != '\\') {
365 /* lookup_name() needs '\\' as a separator */
367 tmp
= talloc_strdup(mem_ctx
, full_name
);
371 tmp
[p
- full_name
] = '\\';
375 return lookup_name(mem_ctx
, full_name
, flags
,
376 ret_domain
, ret_name
,
380 /* Try with our own SAM name. */
381 qualified_name
= talloc_asprintf(mem_ctx
, "%s\\%s",
382 get_global_sam_name(),
384 if (!qualified_name
) {
388 if (lookup_name(mem_ctx
, qualified_name
, flags
,
389 ret_domain
, ret_name
,
390 ret_sid
, ret_type
)) {
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(),
400 if (!qualified_name
) {
404 return lookup_name(mem_ctx
, qualified_name
, flags
,
405 ret_domain
, ret_name
,
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
)
416 const char **my_names
;
417 enum lsa_SidType
*my_types
;
420 if (!(tmp_ctx
= talloc_init("wb_lookup_rids"))) {
424 if (!winbind_lookup_rids(tmp_ctx
, domain_sid
, num_rids
, rids
,
425 domain_name
, &my_names
, &my_types
)) {
427 for (i
=0; i
<num_rids
; i
++) {
429 types
[i
] = SID_NAME_UNKNOWN
;
431 TALLOC_FREE(tmp_ctx
);
435 if (!(*domain_name
= talloc_strdup(mem_ctx
, *domain_name
))) {
436 TALLOC_FREE(tmp_ctx
);
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
);
450 if (!(names
[i
] = talloc_strdup(names
, my_names
[i
]))) {
451 TALLOC_FREE(tmp_ctx
);
454 types
[i
] = my_types
[i
];
456 TALLOC_FREE(tmp_ctx
);
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
)
467 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
468 sid_string_dbg(domain_sid
)));
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
)) {
478 for (i
= 0; i
< num_rids
; i
++)
479 (*types
)[i
] = SID_NAME_UNKNOWN
;
485 if (sid_check_is_domain(domain_sid
)) {
488 if (*domain_name
== NULL
) {
489 *domain_name
= talloc_strdup(
490 mem_ctx
, get_global_sam_name());
493 if (*domain_name
== NULL
) {
498 result
= pdb_lookup_rids(domain_sid
, num_rids
, rids
,
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
) {
518 for (i
=0; i
<num_rids
; i
++) {
519 if (lookup_builtin_rid(*names
, rids
[i
],
521 if ((*names
)[i
] == NULL
) {
524 (*types
)[i
] = SID_NAME_ALIAS
;
526 (*types
)[i
] = SID_NAME_UNKNOWN
;
532 if (sid_check_is_wellknown_domain(domain_sid
, NULL
)) {
533 for (i
=0; i
<num_rids
; i
++) {
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
) {
542 (*types
)[i
] = SID_NAME_WKN_GRP
;
544 (*types
)[i
] = SID_NAME_UNKNOWN
;
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
) {
558 for (i
=0; i
<num_rids
; i
++) {
559 (*names
)[i
] = talloc_strdup(
560 (*names
), uidtoname(rids
[i
]));
561 if ((*names
)[i
] == NULL
) {
564 (*types
)[i
] = SID_NAME_USER
;
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
) {
577 for (i
=0; i
<num_rids
; i
++) {
578 (*names
)[i
] = talloc_strdup(
579 (*names
), gidtoname(rids
[i
]));
580 if ((*names
)[i
] == NULL
) {
583 (*types
)[i
] = SID_NAME_DOM_GRP
;
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
,
600 enum lsa_SidType type
;
602 if (sid_check_is_domain(sid
)) {
603 *name
= talloc_strdup(mem_ctx
, get_global_sam_name());
607 if (sid_check_is_builtin(sid
)) {
608 *name
= talloc_strdup(mem_ctx
, builtin_domain_name());
612 if (sid_check_is_wellknown_domain(sid
, &tmp
)) {
613 *name
= talloc_strdup(mem_ctx
, tmp
);
617 if (sid_check_is_unix_users(sid
)) {
618 *name
= talloc_strdup(mem_ctx
, unix_users_domain_name());
622 if (sid_check_is_unix_groups(sid
)) {
623 *name
= talloc_strdup(mem_ctx
, unix_groups_domain_name());
627 if (sid
->num_auths
!= 4) {
628 /* This can't be a domain */
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
640 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx
,
646 for (i
=0; i
<num_domains
; i
++) {
647 if (sid_equal(sid
, &domains
[i
]->sid
)) {
648 *name
= talloc_strdup(mem_ctx
,
656 if (winbind_lookup_sid(mem_ctx
, sid
, &tmp
, NULL
, &type
) &&
657 (type
== SID_NAME_DOMAIN
)) {
666 * This tries to implement the rather weird rules for the lsa_lookup level
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
684 static bool check_dom_sid_to_level(const DOM_SID
*sid
, int level
)
693 ret
= (!sid_check_is_builtin(sid
) &&
694 !sid_check_is_wellknown_domain(sid
, NULL
));
699 ret
= sid_check_is_domain(sid
);
706 DEBUG(10, ("%s SID %s in level %d\n",
707 ret
? "Accepting" : "Rejecting",
708 sid_string_dbg(sid
), level
));
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
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
)
730 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
731 struct lsa_name_info
*name_infos
;
732 struct lsa_dom_info
*dom_infos
= NULL
;
736 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
737 DEBUG(0, ("talloc_new failed\n"));
738 return NT_STATUS_NO_MEMORY
;
742 name_infos
= TALLOC_ARRAY(mem_ctx
, struct lsa_name_info
, num_sids
);
743 if (name_infos
== NULL
) {
744 result
= NT_STATUS_NO_MEMORY
;
751 dom_infos
= TALLOC_ZERO_ARRAY(mem_ctx
, struct lsa_dom_info
,
752 LSA_REF_DOMAIN_LIST_MULTIPLIER
);
753 if (dom_infos
== NULL
) {
754 result
= NT_STATUS_NO_MEMORY
;
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
764 * name_infos is a shadow-copy of the SIDs array to collect the real
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
++) {
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
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
;
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
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
;
808 /* This is a normal SID with rid component */
809 if (!sid_split_rid(&sid
, &rid
)) {
810 result
= NT_STATUS_INVALID_SID
;
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
;
822 for (j
=0; j
<LSA_REF_DOMAIN_LIST_MULTIPLIER
; j
++) {
823 if (!dom_infos
[j
].valid
) {
826 if (sid_equal(&sid
, &dom_infos
[j
].sid
)) {
831 if (j
== LSA_REF_DOMAIN_LIST_MULTIPLIER
) {
832 /* TODO: What's the right error message here? */
833 result
= NT_STATUS_NONE_MAPPED
;
837 if (!dom_infos
[j
].valid
) {
838 /* We found a domain not yet referenced, create a new
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 */
847 talloc_strdup(dom_infos
, domain_name
);
848 if (dom_infos
[j
].name
== NULL
) {
849 result
= NT_STATUS_NO_MEMORY
;
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
;
873 /* Iterate over the domains found */
875 for (i
=0; i
<LSA_REF_DOMAIN_LIST_MULTIPLIER
; i
++) {
877 const char *domain_name
= NULL
;
879 enum lsa_SidType
*types
;
880 struct lsa_dom_info
*dom
= &dom_infos
[i
];
883 /* No domains left, we're done */
888 if (!(rids
= TALLOC_ARRAY(tmp_ctx
, uint32
, dom
->num_idxs
))) {
889 result
= NT_STATUS_NO_MEMORY
;
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
,
903 result
= NT_STATUS_NO_MEMORY
;
907 if (!(dom
->name
= talloc_strdup(dom_infos
, domain_name
))) {
908 result
= NT_STATUS_NO_MEMORY
;
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
;
923 name_infos
[idx
].name
= NULL
;
928 *ret_domains
= dom_infos
;
929 *ret_names
= name_infos
;
930 TALLOC_FREE(tmp_ctx
);
934 TALLOC_FREE(dom_infos
);
935 TALLOC_FREE(name_infos
);
936 TALLOC_FREE(tmp_ctx
);
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
;
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"));
960 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx
, 1, &sid
, 1,
965 if (name
->type
== SID_NAME_UNKNOWN
) {
969 if ((ret_domain
!= NULL
) &&
970 !(*ret_domain
= talloc_strdup(mem_ctx
, domain
->name
))) {
974 if ((ret_name
!= NULL
) &&
975 !(*ret_name
= talloc_strdup(mem_ctx
, name
->name
))) {
979 if (ret_type
!= NULL
) {
980 *ret_type
= name
->type
;
987 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid
),
988 domain
->name
, name
->name
, name
->type
));
990 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid
)));
992 TALLOC_FREE(tmp_ctx
);
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
)),
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
, NULL
, 0));
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
, NULL
, 0)),
1039 SMB_ASSERT(cache_value
.length
== sizeof(*puid
));
1040 memcpy(puid
, cache_value
.data
, sizeof(*puid
));
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
, NULL
, 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
, NULL
, 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
)),
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
, NULL
, 0));
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_UID_CACHE
,
1089 data_blob_const(psid
, ndr_size_dom_sid(psid
, NULL
, 0)),
1094 SMB_ASSERT(cache_value
.length
== sizeof(*pgid
));
1095 memcpy(pgid
, cache_value
.data
, sizeof(*pgid
));
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
, NULL
, 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
, NULL
, 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
)
1126 ret
= pdb_uid_to_rid(uid
, &rid
);
1130 /* This is a mapped user */
1131 sid_copy(psid
, get_global_sam_sid());
1132 sid_append_rid(psid
, rid
);
1136 /* This is an unmapped user */
1138 uid_to_unix_users_sid(uid
, psid
);
1141 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid
,
1142 sid_string_dbg(psid
)));
1144 store_uid_sid_cache(psid
, uid
);
1148 /*****************************************************************
1149 *THE LEGACY* convert gid_t to SID function.
1150 *****************************************************************/
1152 static void legacy_gid_to_sid(DOM_SID
*psid
, gid_t gid
)
1159 ret
= pdb_gid_to_sid(gid
, psid
);
1163 /* This is a mapped group */
1167 /* This is an unmapped group */
1169 gid_to_unix_groups_sid(gid
, psid
);
1172 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid
,
1173 sid_string_dbg(psid
)));
1175 store_gid_sid_cache(psid
, gid
);
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
;
1188 if (sid_peek_check_rid(get_global_sam_sid(), psid
, &rid
)) {
1193 ret
= pdb_sid_to_id(psid
, &id
, &type
);
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
)));
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
)));
1215 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_dbg(psid
),
1216 (unsigned int)*puid
));
1218 store_uid_sid_cache(psid
, *puid
);
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
)
1232 enum lsa_SidType type
;
1234 if ((sid_check_is_in_builtin(psid
) ||
1235 sid_check_is_in_wellknown_domain(psid
))) {
1239 ret
= pdb_getgrsid(&map
, *psid
);
1246 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1247 sid_string_dbg(psid
)));
1251 if (sid_peek_check_rid(get_global_sam_sid(), psid
, &rid
)) {
1255 ret
= pdb_sid_to_id(psid
, &id
, &type
);
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
)));
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
)));
1278 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_dbg(psid
),
1279 (unsigned int)*pgid
));
1281 store_gid_sid_cache(psid
, *pgid
);
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;
1296 if (fetch_sid_from_uid_cache(psid
, uid
))
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.
1307 legacy_uid_to_sid(psid
, uid
);
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", (unsigned int)uid
));
1327 legacy_uid_to_sid(psid
, uid
);
1332 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid
,
1333 sid_string_dbg(psid
)));
1335 store_uid_sid_cache(psid
, uid
);
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;
1349 if (fetch_sid_from_gid_cache(psid
, gid
))
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.
1360 legacy_gid_to_sid(psid
, gid
);
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", (unsigned int)gid
));
1380 legacy_gid_to_sid(psid
, gid
);
1385 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid
,
1386 sid_string_dbg(psid
)));
1388 store_gid_sid_cache(psid
, gid
);
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;
1403 if (fetch_uid_from_cache(puid
, psid
))
1406 if (fetch_gid_from_cache(&gid
, psid
)) {
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
)) {
1416 /* return here, don't cache */
1417 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid
),
1418 (unsigned int)*puid
));
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.
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 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1437 sid_string_dbg(psid
)));
1438 /* winbind failed. do legacy */
1439 return legacy_sid_to_uid(psid
, puid
);
1443 /* TODO: Here would be the place to allocate both a gid and a uid for
1444 * the SID in question */
1446 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid
),
1447 (unsigned int)*puid
));
1449 store_uid_sid_cache(psid
, *puid
);
1453 /*****************************************************************
1454 *THE CANONICAL* convert SID to gid function.
1455 Group mapping is used for gids that maps to Wellknown SIDs
1456 *****************************************************************/
1458 bool sid_to_gid(const DOM_SID
*psid
, gid_t
*pgid
)
1460 bool expired
= true;
1465 if (fetch_gid_from_cache(pgid
, psid
))
1468 if (fetch_uid_from_cache(&uid
, psid
))
1471 /* Optimize for the Unix Groups Domain
1472 * as the conversion is straightforward */
1473 if (sid_peek_check_rid(&global_sid_Unix_Groups
, psid
, &rid
)) {
1477 /* return here, don't cache */
1478 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid
),
1479 (unsigned int)*pgid
));
1483 /* Check the winbindd cache directly. */
1484 ret
= idmap_cache_find_sid2gid(psid
, pgid
, &expired
);
1486 if (ret
&& !expired
&& (*pgid
== (gid_t
)-1)) {
1488 * Negative cache entry, we already asked.
1491 return legacy_sid_to_gid(psid
, pgid
);
1494 if (!ret
|| expired
) {
1495 /* Not in cache or negative. Ask winbindd. */
1496 /* Ask winbindd if it can map this sid to a gid.
1497 * (Idmap will check it is a valid SID and of the right type) */
1499 if ( !winbind_sid_to_gid(pgid
, psid
) ) {
1501 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1502 sid_string_dbg(psid
)));
1503 /* winbind failed. do legacy */
1504 return legacy_sid_to_gid(psid
, pgid
);
1508 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid
),
1509 (unsigned int)*pgid
));
1511 store_gid_sid_cache(psid
, *pgid
);