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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /*****************************************************************
26 Dissect a user-provided name into domain, name, sid and type.
28 If an explicit domain name was given in the form domain\user, it
29 has to try that. If no explicit domain name was given, we have
31 *****************************************************************/
33 BOOL
lookup_name(TALLOC_CTX
*mem_ctx
,
34 const char *full_name
, int flags
,
35 const char **ret_domain
, const char **ret_name
,
36 DOM_SID
*ret_sid
, enum lsa_SidType
*ret_type
)
40 const char *domain
= NULL
;
41 const char *name
= NULL
;
44 enum lsa_SidType type
;
45 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
47 if (tmp_ctx
== NULL
) {
48 DEBUG(0, ("talloc_new failed\n"));
52 p
= strchr_m(full_name
, '\\');
55 domain
= talloc_strndup(tmp_ctx
, full_name
,
56 PTR_DIFF(p
, full_name
));
57 name
= talloc_strdup(tmp_ctx
, p
+1);
59 domain
= talloc_strdup(tmp_ctx
, "");
60 name
= talloc_strdup(tmp_ctx
, full_name
);
63 DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
64 full_name
, domain
, name
));
66 if ((domain
== NULL
) || (name
== NULL
)) {
67 DEBUG(0, ("talloc failed\n"));
72 if (strequal(domain
, get_global_sam_name())) {
74 /* It's our own domain, lookup the name in passdb */
75 if (lookup_global_sam_name(name
, flags
, &rid
, &type
)) {
76 sid_copy(&sid
, get_global_sam_sid());
77 sid_append_rid(&sid
, rid
);
84 if (strequal(domain
, builtin_domain_name())) {
86 /* Explicit request for a name in BUILTIN */
87 if (lookup_builtin_name(name
, &rid
)) {
88 sid_copy(&sid
, &global_sid_Builtin
);
89 sid_append_rid(&sid
, rid
);
90 type
= SID_NAME_ALIAS
;
97 /* Try the explicit winbind lookup first, don't let it guess the
98 * domain yet at this point yet. This comes later. */
100 if ((domain
[0] != '\0') &&
101 (winbind_lookup_name(domain
, name
, &sid
, &type
))) {
105 if (strequal(domain
, unix_users_domain_name())) {
106 if (lookup_unix_user_name(name
, &sid
)) {
107 type
= SID_NAME_USER
;
110 TALLOC_FREE(tmp_ctx
);
114 if (strequal(domain
, unix_groups_domain_name())) {
115 if (lookup_unix_group_name(name
, &sid
)) {
116 type
= SID_NAME_DOM_GRP
;
119 TALLOC_FREE(tmp_ctx
);
123 if ((domain
[0] == '\0') && (!(flags
& LOOKUP_NAME_ISOLATED
))) {
124 TALLOC_FREE(tmp_ctx
);
128 /* Now the guesswork begins, we haven't been given an explicit
129 * domain. Try the sequence as documented on
130 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
131 * November 27, 2005 */
133 /* 1. well-known names */
135 if (lookup_wellknown_name(tmp_ctx
, name
, &sid
, &domain
)) {
136 type
= SID_NAME_WKN_GRP
;
140 /* 2. Builtin domain as such */
142 if (strequal(name
, builtin_domain_name())) {
143 /* Swap domain and name */
144 tmp
= name
; name
= domain
; domain
= tmp
;
145 sid_copy(&sid
, &global_sid_Builtin
);
146 type
= SID_NAME_DOMAIN
;
150 /* 3. Account domain */
152 if (strequal(name
, get_global_sam_name())) {
153 if (!secrets_fetch_domain_sid(name
, &sid
)) {
154 DEBUG(3, ("Could not fetch my SID\n"));
155 TALLOC_FREE(tmp_ctx
);
158 /* Swap domain and name */
159 tmp
= name
; name
= domain
; domain
= tmp
;
160 type
= SID_NAME_DOMAIN
;
164 /* 4. Primary domain */
166 if (!IS_DC
&& strequal(name
, lp_workgroup())) {
167 if (!secrets_fetch_domain_sid(name
, &sid
)) {
168 DEBUG(3, ("Could not fetch the domain SID\n"));
169 TALLOC_FREE(tmp_ctx
);
172 /* Swap domain and name */
173 tmp
= name
; name
= domain
; domain
= tmp
;
174 type
= SID_NAME_DOMAIN
;
178 /* 5. Trusted domains as such, to me it looks as if members don't do
179 this, tested an XP workstation in a NT domain -- vl */
181 if (IS_DC
&& (secrets_fetch_trusted_domain_password(name
, NULL
,
183 /* Swap domain and name */
184 tmp
= name
; name
= domain
; domain
= tmp
;
185 type
= SID_NAME_DOMAIN
;
189 /* 6. Builtin aliases */
191 if (lookup_builtin_name(name
, &rid
)) {
192 domain
= talloc_strdup(tmp_ctx
, builtin_domain_name());
193 sid_copy(&sid
, &global_sid_Builtin
);
194 sid_append_rid(&sid
, rid
);
195 type
= SID_NAME_ALIAS
;
199 /* 7. Local systems' SAM (DCs don't have a local SAM) */
200 /* 8. Primary SAM (On members, this is the domain) */
202 /* Both cases are done by looking at our passdb */
204 if (lookup_global_sam_name(name
, flags
, &rid
, &type
)) {
205 domain
= talloc_strdup(tmp_ctx
, get_global_sam_name());
206 sid_copy(&sid
, get_global_sam_sid());
207 sid_append_rid(&sid
, rid
);
211 /* Now our local possibilities are exhausted. */
213 if (!(flags
& LOOKUP_NAME_REMOTE
)) {
214 TALLOC_FREE(tmp_ctx
);
218 /* If we are not a DC, we have to ask in our primary domain. Let
219 * winbind do that. */
222 (winbind_lookup_name(lp_workgroup(), name
, &sid
, &type
))) {
223 domain
= talloc_strdup(tmp_ctx
, lp_workgroup());
227 /* 9. Trusted domains */
229 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
230 * that (yet), but give it a chance. */
232 if (IS_DC
&& winbind_lookup_name("", name
, &sid
, &type
)) {
235 enum lsa_SidType domain_type
;
237 if (type
== SID_NAME_DOMAIN
) {
238 /* Swap name and type */
239 tmp
= name
; name
= domain
; domain
= tmp
;
243 /* Here we have to cope with a little deficiency in the
244 * winbind API: We have to ask it again for the name of the
245 * domain it figured out itself. Maybe fix that later... */
247 sid_copy(&dom_sid
, &sid
);
248 sid_split_rid(&dom_sid
, &tmp_rid
);
250 if (!winbind_lookup_sid(tmp_ctx
, &dom_sid
, &domain
, NULL
,
252 (domain_type
!= SID_NAME_DOMAIN
)) {
253 DEBUG(2, ("winbind could not find the domain's name "
254 "it just looked up for us\n"));
255 TALLOC_FREE(tmp_ctx
);
261 /* 10. Don't translate */
263 /* 11. Ok, windows would end here. Samba has two more options:
264 Unmapped users and unmapped groups */
266 if (lookup_unix_user_name(name
, &sid
)) {
267 domain
= talloc_strdup(tmp_ctx
, unix_users_domain_name());
268 type
= SID_NAME_USER
;
272 if (lookup_unix_group_name(name
, &sid
)) {
273 domain
= talloc_strdup(tmp_ctx
, unix_groups_domain_name());
274 type
= SID_NAME_DOM_GRP
;
279 * Ok, all possibilities tried. Fail.
282 TALLOC_FREE(tmp_ctx
);
286 if ((domain
== NULL
) || (name
== NULL
)) {
287 DEBUG(0, ("talloc failed\n"));
288 TALLOC_FREE(tmp_ctx
);
293 * Hand over the results to the talloc context we've been given.
296 if ((ret_name
!= NULL
) &&
297 !(*ret_name
= talloc_strdup(mem_ctx
, name
))) {
298 DEBUG(0, ("talloc failed\n"));
299 TALLOC_FREE(tmp_ctx
);
303 if (ret_domain
!= NULL
) {
305 if (!(tmp_dom
= talloc_strdup(mem_ctx
, domain
))) {
306 DEBUG(0, ("talloc failed\n"));
307 TALLOC_FREE(tmp_ctx
);
311 *ret_domain
= tmp_dom
;
314 if (ret_sid
!= NULL
) {
315 sid_copy(ret_sid
, &sid
);
318 if (ret_type
!= NULL
) {
322 TALLOC_FREE(tmp_ctx
);
326 /************************************************************************
327 Names from smb.conf can be unqualified. eg. valid users = foo
328 These names should never map to a remote name. Try global_sam_name()\foo,
329 and then "Unix Users"\foo (or "Unix Groups"\foo).
330 ************************************************************************/
332 BOOL
lookup_name_smbconf(TALLOC_CTX
*mem_ctx
,
333 const char *full_name
, int flags
,
334 const char **ret_domain
, const char **ret_name
,
335 DOM_SID
*ret_sid
, enum lsa_SidType
*ret_type
)
337 char *qualified_name
;
340 /* NB. No winbindd_separator here as lookup_name needs \\' */
341 if ((p
= strchr_m(full_name
, *lp_winbind_separator())) != NULL
) {
343 /* The name is already qualified with a domain. */
345 if (*lp_winbind_separator() != '\\') {
348 /* lookup_name() needs '\\' as a separator */
350 tmp
= talloc_strdup(mem_ctx
, full_name
);
354 tmp
[p
- full_name
] = '\\';
358 return lookup_name(mem_ctx
, full_name
, flags
,
359 ret_domain
, ret_name
,
363 /* Try with our own SAM name. */
364 qualified_name
= talloc_asprintf(mem_ctx
, "%s\\%s",
365 get_global_sam_name(),
367 if (!qualified_name
) {
371 if (lookup_name(mem_ctx
, qualified_name
, flags
,
372 ret_domain
, ret_name
,
373 ret_sid
, ret_type
)) {
377 /* Finally try with "Unix Users" or "Unix Group" */
378 qualified_name
= talloc_asprintf(mem_ctx
, "%s\\%s",
379 flags
& LOOKUP_NAME_GROUP
?
380 unix_groups_domain_name() :
381 unix_users_domain_name(),
383 if (!qualified_name
) {
387 return lookup_name(mem_ctx
, qualified_name
, flags
,
388 ret_domain
, ret_name
,
392 static BOOL
wb_lookup_rids(TALLOC_CTX
*mem_ctx
,
393 const DOM_SID
*domain_sid
,
394 int num_rids
, uint32
*rids
,
395 const char **domain_name
,
396 const char **names
, enum lsa_SidType
*types
)
399 const char **my_names
;
400 enum lsa_SidType
*my_types
;
403 if (!(tmp_ctx
= talloc_init("wb_lookup_rids"))) {
407 if (!winbind_lookup_rids(tmp_ctx
, domain_sid
, num_rids
, rids
,
408 domain_name
, &my_names
, &my_types
)) {
410 for (i
=0; i
<num_rids
; i
++) {
412 types
[i
] = SID_NAME_UNKNOWN
;
414 TALLOC_FREE(tmp_ctx
);
418 if (!(*domain_name
= talloc_strdup(mem_ctx
, *domain_name
))) {
419 TALLOC_FREE(tmp_ctx
);
424 * winbind_lookup_rids allocates its own array. We've been given the
425 * array, so copy it over
428 for (i
=0; i
<num_rids
; i
++) {
429 if (my_names
[i
] == NULL
) {
430 TALLOC_FREE(tmp_ctx
);
433 if (!(names
[i
] = talloc_strdup(names
, my_names
[i
]))) {
434 TALLOC_FREE(tmp_ctx
);
437 types
[i
] = my_types
[i
];
439 TALLOC_FREE(tmp_ctx
);
443 static BOOL
lookup_rids(TALLOC_CTX
*mem_ctx
, const DOM_SID
*domain_sid
,
444 int num_rids
, uint32_t *rids
,
445 const char **domain_name
,
446 const char ***names
, enum lsa_SidType
**types
)
451 *names
= TALLOC_ARRAY(mem_ctx
, const char *, num_rids
);
452 *types
= TALLOC_ARRAY(mem_ctx
, enum lsa_SidType
, num_rids
);
454 if ((*names
== NULL
) || (*types
== NULL
)) {
462 if (sid_check_is_domain(domain_sid
)) {
465 if (*domain_name
== NULL
) {
466 *domain_name
= talloc_strdup(
467 mem_ctx
, get_global_sam_name());
470 if (*domain_name
== NULL
) {
475 result
= pdb_lookup_rids(domain_sid
, num_rids
, rids
,
479 return (NT_STATUS_IS_OK(result
) ||
480 NT_STATUS_EQUAL(result
, NT_STATUS_NONE_MAPPED
) ||
481 NT_STATUS_EQUAL(result
, STATUS_SOME_UNMAPPED
));
484 if (sid_check_is_builtin(domain_sid
)) {
486 if (*domain_name
== NULL
) {
487 *domain_name
= talloc_strdup(
488 mem_ctx
, builtin_domain_name());
491 if (*domain_name
== NULL
) {
495 for (i
=0; i
<num_rids
; i
++) {
496 if (lookup_builtin_rid(*names
, rids
[i
],
498 if ((*names
)[i
] == NULL
) {
501 (*types
)[i
] = SID_NAME_ALIAS
;
503 (*types
)[i
] = SID_NAME_UNKNOWN
;
509 if (sid_check_is_wellknown_domain(domain_sid
, NULL
)) {
510 for (i
=0; i
<num_rids
; i
++) {
512 sid_copy(&sid
, domain_sid
);
513 sid_append_rid(&sid
, rids
[i
]);
514 if (lookup_wellknown_sid(mem_ctx
, &sid
,
515 domain_name
, &(*names
)[i
])) {
516 if ((*names
)[i
] == NULL
) {
519 (*types
)[i
] = SID_NAME_WKN_GRP
;
521 (*types
)[i
] = SID_NAME_UNKNOWN
;
527 if (sid_check_is_unix_users(domain_sid
)) {
528 if (*domain_name
== NULL
) {
529 *domain_name
= talloc_strdup(
530 mem_ctx
, unix_users_domain_name());
532 for (i
=0; i
<num_rids
; i
++) {
533 (*names
)[i
] = talloc_strdup(
534 (*names
), uidtoname(rids
[i
]));
535 (*types
)[i
] = SID_NAME_USER
;
540 if (sid_check_is_unix_groups(domain_sid
)) {
541 if (*domain_name
== NULL
) {
542 *domain_name
= talloc_strdup(
543 mem_ctx
, unix_groups_domain_name());
545 for (i
=0; i
<num_rids
; i
++) {
546 (*names
)[i
] = talloc_strdup(
547 (*names
), gidtoname(rids
[i
]));
548 (*types
)[i
] = SID_NAME_DOM_GRP
;
553 return wb_lookup_rids(mem_ctx
, domain_sid
, num_rids
, rids
,
554 domain_name
, *names
, *types
);
558 * Is the SID a domain as such? If yes, lookup its name.
561 static BOOL
lookup_as_domain(const DOM_SID
*sid
, TALLOC_CTX
*mem_ctx
,
565 enum lsa_SidType type
;
567 if (sid_check_is_domain(sid
)) {
568 *name
= talloc_strdup(mem_ctx
, get_global_sam_name());
572 if (sid_check_is_builtin(sid
)) {
573 *name
= talloc_strdup(mem_ctx
, builtin_domain_name());
577 if (sid_check_is_wellknown_domain(sid
, &tmp
)) {
578 *name
= talloc_strdup(mem_ctx
, tmp
);
582 if (sid
->num_auths
!= 4) {
583 /* This can't be a domain */
588 uint32 i
, num_domains
;
589 struct trustdom_info
**domains
;
591 /* This is relatively expensive, but it happens only on DCs
592 * and for SIDs that have 4 sub-authorities and thus look like
595 if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx
,
601 for (i
=0; i
<num_domains
; i
++) {
602 if (sid_equal(sid
, &domains
[i
]->sid
)) {
603 *name
= talloc_strdup(mem_ctx
,
611 if (winbind_lookup_sid(mem_ctx
, sid
, &tmp
, NULL
, &type
) &&
612 (type
== SID_NAME_DOMAIN
)) {
621 * This tries to implement the rather weird rules for the lsa_lookup level
624 * This is as close as we can get to what W2k3 does. With this we survive the
625 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
626 * different, but I assume that's just being too liberal. For example, W2k3
627 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
628 * whereas NT4 does the same as level 1 (I think). I did not fully test that
629 * with NT4, this is what w2k3 does.
631 * Level 1: Ask everywhere
632 * Level 2: Ask domain and trusted domains, no builtin and wkn
633 * Level 3: Only ask domain
634 * Level 4: W2k3ad: Only ask AD trusts
635 * Level 5: Don't lookup anything
639 static BOOL
check_dom_sid_to_level(const DOM_SID
*sid
, int level
)
648 ret
= (!sid_check_is_builtin(sid
) &&
649 !sid_check_is_wellknown_domain(sid
, NULL
));
654 ret
= sid_check_is_domain(sid
);
661 DEBUG(10, ("%s SID %s in level %d\n",
662 ret
? "Accepting" : "Rejecting",
663 sid_string_static(sid
), level
));
668 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
669 * references to domains, it is explicitly made for this.
671 * This attempts to be as efficient as possible: It collects all SIDs
672 * belonging to a domain and hands them in bulk to the appropriate lookup
673 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
674 * *hugely* from this. Winbind is going to be extended with a lookup_rids
675 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
679 NTSTATUS
lookup_sids(TALLOC_CTX
*mem_ctx
, int num_sids
,
680 const DOM_SID
**sids
, int level
,
681 struct lsa_dom_info
**ret_domains
,
682 struct lsa_name_info
**ret_names
)
685 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
686 struct lsa_name_info
*name_infos
;
687 struct lsa_dom_info
*dom_infos
= NULL
;
691 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
692 DEBUG(0, ("talloc_new failed\n"));
693 return NT_STATUS_NO_MEMORY
;
697 name_infos
= TALLOC_ARRAY(mem_ctx
, struct lsa_name_info
, num_sids
);
698 if (name_infos
== NULL
) {
699 result
= NT_STATUS_NO_MEMORY
;
706 dom_infos
= TALLOC_ZERO_ARRAY(mem_ctx
, struct lsa_dom_info
,
708 if (dom_infos
== NULL
) {
709 result
= NT_STATUS_NO_MEMORY
;
713 /* First build up the data structures:
715 * dom_infos is a list of domains referenced in the list of
716 * SIDs. Later we will walk the list of domains and look up the RIDs
719 * name_infos is a shadow-copy of the SIDs array to collect the real
722 * dom_info->idxs is an index into the name_infos array. The
723 * difficulty we have here is that we need to keep the SIDs the client
724 * asked for in the same order for the reply
727 for (i
=0; i
<num_sids
; i
++) {
730 const char *domain_name
= NULL
;
732 sid_copy(&sid
, sids
[i
]);
733 name_infos
[i
].type
= SID_NAME_USE_NONE
;
735 if (lookup_as_domain(&sid
, name_infos
, &domain_name
)) {
736 /* We can't push that through the normal lookup
737 * process, as this would reference illegal
740 * For example S-1-5-32 would end up referencing
741 * domain S-1-5- with RID 32 which is clearly wrong.
743 if (domain_name
== NULL
) {
744 result
= NT_STATUS_NO_MEMORY
;
748 name_infos
[i
].rid
= 0;
749 name_infos
[i
].type
= SID_NAME_DOMAIN
;
750 name_infos
[i
].name
= NULL
;
752 if (sid_check_is_builtin(&sid
)) {
753 /* Yes, W2k3 returns "BUILTIN" both as domain
755 name_infos
[i
].name
= talloc_strdup(
756 name_infos
, builtin_domain_name());
757 if (name_infos
[i
].name
== NULL
) {
758 result
= NT_STATUS_NO_MEMORY
;
763 /* This is a normal SID with rid component */
764 if (!sid_split_rid(&sid
, &rid
)) {
765 result
= NT_STATUS_INVALID_PARAMETER
;
770 if (!check_dom_sid_to_level(&sid
, level
)) {
771 name_infos
[i
].rid
= 0;
772 name_infos
[i
].type
= SID_NAME_UNKNOWN
;
773 name_infos
[i
].name
= NULL
;
777 for (j
=0; j
<MAX_REF_DOMAINS
; j
++) {
778 if (!dom_infos
[j
].valid
) {
781 if (sid_equal(&sid
, &dom_infos
[j
].sid
)) {
786 if (j
== MAX_REF_DOMAINS
) {
787 /* TODO: What's the right error message here? */
788 result
= NT_STATUS_NONE_MAPPED
;
792 if (!dom_infos
[j
].valid
) {
793 /* We found a domain not yet referenced, create a new
795 dom_infos
[j
].valid
= True
;
796 sid_copy(&dom_infos
[j
].sid
, &sid
);
798 if (domain_name
!= NULL
) {
799 /* This name was being found above in the case
800 * when we found a domain SID */
802 talloc_strdup(dom_infos
, domain_name
);
803 if (dom_infos
[j
].name
== NULL
) {
804 result
= NT_STATUS_NO_MEMORY
;
808 /* lookup_rids will take care of this */
809 dom_infos
[j
].name
= NULL
;
813 name_infos
[i
].dom_idx
= j
;
815 if (name_infos
[i
].type
== SID_NAME_USE_NONE
) {
816 name_infos
[i
].rid
= rid
;
818 ADD_TO_ARRAY(dom_infos
, int, i
, &dom_infos
[j
].idxs
,
819 &dom_infos
[j
].num_idxs
);
821 if (dom_infos
[j
].idxs
== NULL
) {
822 result
= NT_STATUS_NO_MEMORY
;
828 /* Iterate over the domains found */
830 for (i
=0; i
<MAX_REF_DOMAINS
; i
++) {
832 const char *domain_name
= NULL
;
834 enum lsa_SidType
*types
;
835 struct lsa_dom_info
*dom
= &dom_infos
[i
];
838 /* No domains left, we're done */
843 if (!(rids
= TALLOC_ARRAY(tmp_ctx
, uint32
, dom
->num_idxs
))) {
844 result
= NT_STATUS_NO_MEMORY
;
851 for (j
=0; j
<dom
->num_idxs
; j
++) {
852 rids
[j
] = name_infos
[dom
->idxs
[j
]].rid
;
855 if (!lookup_rids(tmp_ctx
, &dom
->sid
,
856 dom
->num_idxs
, rids
, &domain_name
,
858 result
= NT_STATUS_NO_MEMORY
;
862 if (!(dom
->name
= talloc_strdup(dom_infos
, domain_name
))) {
863 result
= NT_STATUS_NO_MEMORY
;
867 for (j
=0; j
<dom
->num_idxs
; j
++) {
868 int idx
= dom
->idxs
[j
];
869 name_infos
[idx
].type
= types
[j
];
870 if (types
[j
] != SID_NAME_UNKNOWN
) {
871 name_infos
[idx
].name
=
872 talloc_strdup(name_infos
, names
[j
]);
873 if (name_infos
[idx
].name
== NULL
) {
874 result
= NT_STATUS_NO_MEMORY
;
878 name_infos
[idx
].name
= NULL
;
883 *ret_domains
= dom_infos
;
884 *ret_names
= name_infos
;
888 TALLOC_FREE(dom_infos
);
889 TALLOC_FREE(name_infos
);
890 TALLOC_FREE(tmp_ctx
);
894 /*****************************************************************
895 *THE CANONICAL* convert SID to name function.
896 *****************************************************************/
898 BOOL
lookup_sid(TALLOC_CTX
*mem_ctx
, const DOM_SID
*sid
,
899 const char **ret_domain
, const char **ret_name
,
900 enum lsa_SidType
*ret_type
)
902 struct lsa_dom_info
*domain
;
903 struct lsa_name_info
*name
;
907 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
908 DEBUG(0, ("talloc_new failed\n"));
912 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx
, 1, &sid
, 1,
917 if (name
->type
== SID_NAME_UNKNOWN
) {
921 if ((ret_domain
!= NULL
) &&
922 !(*ret_domain
= talloc_strdup(mem_ctx
, domain
->name
))) {
926 if ((ret_name
!= NULL
) &&
927 !(*ret_name
= talloc_strdup(mem_ctx
, name
->name
))) {
931 if (ret_type
!= NULL
) {
932 *ret_type
= name
->type
;
939 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
940 sid_string_static(sid
), domain
->name
,
941 name
->name
, name
->type
));
943 DEBUG(10, ("failed to lookup sid %s\n",
944 sid_string_static(sid
)));
946 TALLOC_FREE(tmp_ctx
);
950 /*****************************************************************
951 Id mapping cache. This is to avoid Winbind mappings already
952 seen by smbd to be queried too frequently, keeping winbindd
953 busy, and blocking smbd while winbindd is busy with other
954 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
955 modified to use linked lists by jra.
956 *****************************************************************/
958 #define MAX_UID_SID_CACHE_SIZE 100
959 #define TURNOVER_UID_SID_CACHE_SIZE 10
960 #define MAX_GID_SID_CACHE_SIZE 100
961 #define TURNOVER_GID_SID_CACHE_SIZE 10
963 static size_t n_uid_sid_cache
= 0;
964 static size_t n_gid_sid_cache
= 0;
966 static struct uid_sid_cache
{
967 struct uid_sid_cache
*next
, *prev
;
970 enum lsa_SidType sidtype
;
971 } *uid_sid_cache_head
;
973 static struct gid_sid_cache
{
974 struct gid_sid_cache
*next
, *prev
;
977 enum lsa_SidType sidtype
;
978 } *gid_sid_cache_head
;
980 /*****************************************************************
981 Find a SID given a uid.
982 *****************************************************************/
984 static BOOL
fetch_sid_from_uid_cache(DOM_SID
*psid
, uid_t uid
)
986 struct uid_sid_cache
*pc
;
988 for (pc
= uid_sid_cache_head
; pc
; pc
= pc
->next
) {
989 if (pc
->uid
== uid
) {
991 DEBUG(3,("fetch sid from uid cache %u -> %s\n",
992 (unsigned int)uid
, sid_string_static(psid
)));
993 DLIST_PROMOTE(uid_sid_cache_head
, pc
);
1000 /*****************************************************************
1001 Find a uid given a SID.
1002 *****************************************************************/
1004 static BOOL
fetch_uid_from_cache( uid_t
*puid
, const DOM_SID
*psid
)
1006 struct uid_sid_cache
*pc
;
1008 for (pc
= uid_sid_cache_head
; pc
; pc
= pc
->next
) {
1009 if (sid_compare(&pc
->sid
, psid
) == 0) {
1011 DEBUG(3,("fetch uid from cache %u -> %s\n",
1012 (unsigned int)*puid
, sid_string_static(psid
)));
1013 DLIST_PROMOTE(uid_sid_cache_head
, pc
);
1020 /*****************************************************************
1021 Store uid to SID mapping in cache.
1022 *****************************************************************/
1024 void store_uid_sid_cache(const DOM_SID
*psid
, uid_t uid
)
1026 struct uid_sid_cache
*pc
;
1028 /* do not store SIDs in the "Unix Group" domain */
1030 if ( sid_check_is_in_unix_users( psid
) )
1033 if (n_uid_sid_cache
>= MAX_UID_SID_CACHE_SIZE
&& n_uid_sid_cache
> TURNOVER_UID_SID_CACHE_SIZE
) {
1034 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
1035 struct uid_sid_cache
*pc_next
;
1038 for (i
= 0, pc
= uid_sid_cache_head
; i
< (n_uid_sid_cache
- TURNOVER_UID_SID_CACHE_SIZE
); i
++, pc
= pc
->next
)
1040 for(; pc
; pc
= pc_next
) {
1042 DLIST_REMOVE(uid_sid_cache_head
,pc
);
1048 pc
= SMB_MALLOC_P(struct uid_sid_cache
);
1052 sid_copy(&pc
->sid
, psid
);
1053 DLIST_ADD(uid_sid_cache_head
, pc
);
1057 /*****************************************************************
1058 Find a SID given a gid.
1059 *****************************************************************/
1061 static BOOL
fetch_sid_from_gid_cache(DOM_SID
*psid
, gid_t gid
)
1063 struct gid_sid_cache
*pc
;
1065 for (pc
= gid_sid_cache_head
; pc
; pc
= pc
->next
) {
1066 if (pc
->gid
== gid
) {
1068 DEBUG(3,("fetch sid from gid cache %u -> %s\n",
1069 (unsigned int)gid
, sid_string_static(psid
)));
1070 DLIST_PROMOTE(gid_sid_cache_head
, pc
);
1077 /*****************************************************************
1078 Find a gid given a SID.
1079 *****************************************************************/
1081 static BOOL
fetch_gid_from_cache(gid_t
*pgid
, const DOM_SID
*psid
)
1083 struct gid_sid_cache
*pc
;
1085 for (pc
= gid_sid_cache_head
; pc
; pc
= pc
->next
) {
1086 if (sid_compare(&pc
->sid
, psid
) == 0) {
1088 DEBUG(3,("fetch gid from cache %u -> %s\n",
1089 (unsigned int)*pgid
, sid_string_static(psid
)));
1090 DLIST_PROMOTE(gid_sid_cache_head
, pc
);
1097 /*****************************************************************
1098 Store gid to SID mapping in cache.
1099 *****************************************************************/
1101 void store_gid_sid_cache(const DOM_SID
*psid
, gid_t gid
)
1103 struct gid_sid_cache
*pc
;
1105 /* do not store SIDs in the "Unix Group" domain */
1107 if ( sid_check_is_in_unix_groups( psid
) )
1110 if (n_gid_sid_cache
>= MAX_GID_SID_CACHE_SIZE
&& n_gid_sid_cache
> TURNOVER_GID_SID_CACHE_SIZE
) {
1111 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
1112 struct gid_sid_cache
*pc_next
;
1115 for (i
= 0, pc
= gid_sid_cache_head
; i
< (n_gid_sid_cache
- TURNOVER_GID_SID_CACHE_SIZE
); i
++, pc
= pc
->next
)
1117 for(; pc
; pc
= pc_next
) {
1119 DLIST_REMOVE(gid_sid_cache_head
,pc
);
1125 pc
= SMB_MALLOC_P(struct gid_sid_cache
);
1129 sid_copy(&pc
->sid
, psid
);
1130 DLIST_ADD(gid_sid_cache_head
, pc
);
1132 DEBUG(3,("store_gid_sid_cache: gid %u in cache -> %s\n", (unsigned int)gid
,
1133 sid_string_static(psid
)));
1138 /*****************************************************************
1139 *THE LEGACY* convert uid_t to SID function.
1140 *****************************************************************/
1142 static void legacy_uid_to_sid(DOM_SID
*psid
, uid_t uid
)
1150 ret
= pdb_uid_to_rid(uid
, &rid
);
1154 /* This is a mapped user */
1155 sid_copy(psid
, get_global_sam_sid());
1156 sid_append_rid(psid
, rid
);
1160 /* This is an unmapped user */
1162 uid_to_unix_users_sid(uid
, psid
);
1165 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid
,
1166 sid_string_static(psid
)));
1168 store_uid_sid_cache(psid
, uid
);
1172 /*****************************************************************
1173 *THE LEGACY* convert gid_t to SID function.
1174 *****************************************************************/
1176 static void legacy_gid_to_sid(DOM_SID
*psid
, gid_t gid
)
1183 ret
= pdb_gid_to_sid(gid
, psid
);
1187 /* This is a mapped group */
1191 /* This is an unmapped group */
1193 gid_to_unix_groups_sid(gid
, psid
);
1196 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid
,
1197 sid_string_static(psid
)));
1199 store_gid_sid_cache(psid
, gid
);
1203 /*****************************************************************
1204 *THE LEGACY* convert SID to uid function.
1205 *****************************************************************/
1207 static BOOL
legacy_sid_to_uid(const DOM_SID
*psid
, uid_t
*puid
)
1209 enum lsa_SidType type
;
1212 if (sid_peek_check_rid(get_global_sam_sid(), psid
, &rid
)) {
1217 ret
= pdb_sid_to_id(psid
, &id
, &type
);
1221 if (type
!= SID_NAME_USER
) {
1222 DEBUG(5, ("sid %s is a %s, expected a user\n",
1223 sid_string_static(psid
),
1224 sid_type_lookup(type
)));
1231 /* This was ours, but it was not mapped. Fail */
1234 DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid
)));
1238 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_static(psid
),
1239 (unsigned int)*puid
));
1241 store_uid_sid_cache(psid
, *puid
);
1245 /*****************************************************************
1246 *THE LEGACY* convert SID to gid function.
1247 Group mapping is used for gids that maps to Wellknown SIDs
1248 *****************************************************************/
1250 static BOOL
legacy_sid_to_gid(const DOM_SID
*psid
, gid_t
*pgid
)
1255 enum lsa_SidType type
;
1257 if ((sid_check_is_in_builtin(psid
) ||
1258 sid_check_is_in_wellknown_domain(psid
))) {
1262 ret
= pdb_getgrsid(&map
, *psid
);
1269 DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid
)));
1273 if (sid_peek_check_rid(get_global_sam_sid(), psid
, &rid
)) {
1277 ret
= pdb_sid_to_id(psid
, &id
, &type
);
1281 if ((type
!= SID_NAME_DOM_GRP
) &&
1282 (type
!= SID_NAME_ALIAS
)) {
1283 DEBUG(5, ("LEGACY: sid %s is a %s, expected a group\n",
1284 sid_string_static(psid
),
1285 sid_type_lookup(type
)));
1292 /* This was ours, but it was not mapped. Fail */
1295 DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid
)));
1299 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_static(psid
),
1300 (unsigned int)*pgid
));
1302 store_gid_sid_cache(psid
, *pgid
);
1307 /*****************************************************************
1308 *THE CANONICAL* convert uid_t to SID function.
1309 *****************************************************************/
1311 void uid_to_sid(DOM_SID
*psid
, uid_t uid
)
1315 if (fetch_sid_from_uid_cache(psid
, uid
))
1318 if (!winbind_uid_to_sid(psid
, uid
)) {
1319 if (!winbind_ping()) {
1320 legacy_uid_to_sid(psid
, uid
);
1324 DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n",
1329 DEBUG(10,("uid %u -> sid %s\n",
1330 (unsigned int)uid
, sid_string_static(psid
)));
1332 store_uid_sid_cache(psid
, uid
);
1336 /*****************************************************************
1337 *THE CANONICAL* convert gid_t to SID function.
1338 *****************************************************************/
1340 void gid_to_sid(DOM_SID
*psid
, gid_t gid
)
1344 if (fetch_sid_from_gid_cache(psid
, gid
))
1347 if (!winbind_gid_to_sid(psid
, gid
)) {
1348 if (!winbind_ping()) {
1349 legacy_gid_to_sid(psid
, gid
);
1353 DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n",
1358 DEBUG(10,("gid %u -> sid %s\n",
1359 (unsigned int)gid
, sid_string_static(psid
)));
1361 store_gid_sid_cache(psid
, gid
);
1365 /*****************************************************************
1366 *THE CANONICAL* convert SID to uid function.
1367 *****************************************************************/
1369 BOOL
sid_to_uid(const DOM_SID
*psid
, uid_t
*puid
)
1374 if (fetch_uid_from_cache(puid
, psid
))
1377 if (fetch_gid_from_cache(&gid
, psid
)) {
1381 /* Optimize for the Unix Users Domain
1382 * as the conversion is straightforward */
1383 if (sid_peek_check_rid(&global_sid_Unix_Users
, psid
, &rid
)) {
1387 /* return here, don't cache */
1388 DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid
),
1389 (unsigned int)*puid
));
1393 if (!winbind_sid_to_uid(puid
, psid
)) {
1394 if (!winbind_ping()) {
1395 return legacy_sid_to_uid(psid
, puid
);
1398 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1399 sid_string_static(psid
)));
1403 /* TODO: Here would be the place to allocate both a gid and a uid for
1404 * the SID in question */
1406 DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid
),
1407 (unsigned int)*puid
));
1409 store_uid_sid_cache(psid
, *puid
);
1413 /*****************************************************************
1414 *THE CANONICAL* convert SID to gid function.
1415 Group mapping is used for gids that maps to Wellknown SIDs
1416 *****************************************************************/
1418 BOOL
sid_to_gid(const DOM_SID
*psid
, gid_t
*pgid
)
1423 if (fetch_gid_from_cache(pgid
, psid
))
1426 if (fetch_uid_from_cache(&uid
, psid
))
1429 /* Optimize for the Unix Groups Domain
1430 * as the conversion is straightforward */
1431 if (sid_peek_check_rid(&global_sid_Unix_Groups
, psid
, &rid
)) {
1435 /* return here, don't cache */
1436 DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid
),
1437 (unsigned int)*pgid
));
1441 /* Ask winbindd if it can map this sid to a gid.
1442 * (Idmap will check it is a valid SID and of the right type) */
1444 if ( !winbind_sid_to_gid(pgid
, psid
) ) {
1445 if (!winbind_ping()) {
1446 return legacy_sid_to_gid(psid
, pgid
);
1449 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1450 sid_string_static(psid
)));
1454 DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid
),
1455 (unsigned int)*pgid
));
1457 store_gid_sid_cache(psid
, *pgid
);