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 SID_NAME_USE
*ret_type
)
40 const char *domain
= NULL
;
41 const char *name
= NULL
;
44 enum SID_NAME_USE 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"));
71 if (strequal(domain
, get_global_sam_name())) {
73 /* It's our own domain, lookup the name in passdb */
74 if (lookup_global_sam_name(name
, flags
, &rid
, &type
)) {
75 sid_copy(&sid
, get_global_sam_sid());
76 sid_append_rid(&sid
, rid
);
82 if (strequal(domain
, builtin_domain_name())) {
84 /* Explicit request for a name in BUILTIN */
85 if (lookup_builtin_name(name
, &rid
)) {
86 sid_copy(&sid
, &global_sid_Builtin
);
87 sid_append_rid(&sid
, rid
);
88 type
= SID_NAME_ALIAS
;
94 /* Try the explicit winbind lookup first, don't let it guess the
95 * domain yet at this point yet. This comes later. */
97 if ((domain
[0] != '\0') &&
98 (winbind_lookup_name(domain
, name
, &sid
, &type
))) {
102 if (strequal(domain
, unix_users_domain_name())) {
103 if (lookup_unix_user_name(name
, &sid
)) {
104 type
= SID_NAME_USER
;
110 if (strequal(domain
, unix_groups_domain_name())) {
111 if (lookup_unix_group_name(name
, &sid
)) {
112 type
= SID_NAME_DOM_GRP
;
118 if ((domain
[0] == '\0') && (!(flags
& LOOKUP_NAME_ISOLATED
))) {
122 /* Now the guesswork begins, we haven't been given an explicit
123 * domain. Try the sequence as documented on
124 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
125 * November 27, 2005 */
127 /* 1. well-known names */
129 if (lookup_wellknown_name(tmp_ctx
, name
, &sid
, &domain
)) {
130 type
= SID_NAME_WKN_GRP
;
134 /* 2. Builtin domain as such */
136 if (strequal(name
, builtin_domain_name())) {
137 /* Swap domain and name */
138 tmp
= name
; name
= domain
; domain
= tmp
;
139 sid_copy(&sid
, &global_sid_Builtin
);
140 type
= SID_NAME_DOMAIN
;
144 /* 3. Account domain */
146 if (strequal(name
, get_global_sam_name())) {
147 if (!secrets_fetch_domain_sid(name
, &sid
)) {
148 DEBUG(3, ("Could not fetch my SID\n"));
151 /* Swap domain and name */
152 tmp
= name
; name
= domain
; domain
= tmp
;
153 type
= SID_NAME_DOMAIN
;
157 /* 4. Primary domain */
159 if (!IS_DC
&& strequal(name
, lp_workgroup())) {
160 if (!secrets_fetch_domain_sid(name
, &sid
)) {
161 DEBUG(3, ("Could not fetch the domain SID\n"));
164 /* Swap domain and name */
165 tmp
= name
; name
= domain
; domain
= tmp
;
166 type
= SID_NAME_DOMAIN
;
170 /* 5. Trusted domains as such, to me it looks as if members don't do
171 this, tested an XP workstation in a NT domain -- vl */
173 if (IS_DC
&& (secrets_fetch_trusted_domain_password(name
, NULL
,
175 /* Swap domain and name */
176 tmp
= name
; name
= domain
; domain
= tmp
;
177 type
= SID_NAME_DOMAIN
;
181 /* 6. Builtin aliases */
183 if (lookup_builtin_name(name
, &rid
)) {
184 domain
= talloc_strdup(tmp_ctx
, builtin_domain_name());
185 sid_copy(&sid
, &global_sid_Builtin
);
186 sid_append_rid(&sid
, rid
);
187 type
= SID_NAME_ALIAS
;
191 /* 7. Local systems' SAM (DCs don't have a local SAM) */
192 /* 8. Primary SAM (On members, this is the domain) */
194 /* Both cases are done by looking at our passdb */
196 if (lookup_global_sam_name(name
, flags
, &rid
, &type
)) {
197 domain
= talloc_strdup(tmp_ctx
, get_global_sam_name());
198 sid_copy(&sid
, get_global_sam_sid());
199 sid_append_rid(&sid
, rid
);
203 /* Now our local possibilities are exhausted. */
205 if (!(flags
& LOOKUP_NAME_REMOTE
)) {
209 /* If we are not a DC, we have to ask in our primary domain. Let
210 * winbind do that. */
213 (winbind_lookup_name(lp_workgroup(), name
, &sid
, &type
))) {
214 domain
= talloc_strdup(tmp_ctx
, lp_workgroup());
218 /* 9. Trusted domains */
220 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
221 * that (yet), but give it a chance. */
223 if (IS_DC
&& winbind_lookup_name("", name
, &sid
, &type
)) {
226 enum SID_NAME_USE domain_type
;
228 if (type
== SID_NAME_DOMAIN
) {
229 /* Swap name and type */
230 tmp
= name
; name
= domain
; domain
= tmp
;
234 /* Here we have to cope with a little deficiency in the
235 * winbind API: We have to ask it again for the name of the
236 * domain it figured out itself. Maybe fix that later... */
238 sid_copy(&dom_sid
, &sid
);
239 sid_split_rid(&dom_sid
, &tmp_rid
);
241 if (!winbind_lookup_sid(tmp_ctx
, &dom_sid
, &domain
, NULL
,
243 (domain_type
!= SID_NAME_DOMAIN
)) {
244 DEBUG(2, ("winbind could not find the domain's name "
245 "it just looked up for us\n"));
251 /* 10. Don't translate */
253 /* 11. Ok, windows would end here. Samba has two more options:
254 Unmapped users and unmapped groups */
256 if (lookup_unix_user_name(name
, &sid
)) {
257 domain
= talloc_strdup(tmp_ctx
, unix_users_domain_name());
258 type
= SID_NAME_USER
;
262 if (lookup_unix_group_name(name
, &sid
)) {
263 domain
= talloc_strdup(tmp_ctx
, unix_groups_domain_name());
264 type
= SID_NAME_DOM_GRP
;
269 TALLOC_FREE(tmp_ctx
);
273 if ((domain
== NULL
) || (name
== NULL
)) {
274 DEBUG(0, ("talloc failed\n"));
275 TALLOC_FREE(tmp_ctx
);
279 if (ret_name
!= NULL
) {
280 *ret_name
= talloc_steal(mem_ctx
, name
);
283 if (ret_domain
!= NULL
) {
284 char *tmp_dom
= talloc_strdup(tmp_ctx
, domain
);
286 *ret_domain
= talloc_steal(mem_ctx
, tmp_dom
);
289 if (ret_sid
!= NULL
) {
290 sid_copy(ret_sid
, &sid
);
293 if (ret_type
!= NULL
) {
297 TALLOC_FREE(tmp_ctx
);
301 /************************************************************************
302 Names from smb.conf can be unqualified. eg. valid users = foo
303 These names should never map to a remote name. Try global_sam_name()\foo,
304 and then "Unix Users"\foo (or "Unix Groups"\foo).
305 ************************************************************************/
307 BOOL
lookup_name_smbconf(TALLOC_CTX
*mem_ctx
,
308 const char *full_name
, int flags
,
309 const char **ret_domain
, const char **ret_name
,
310 DOM_SID
*ret_sid
, enum SID_NAME_USE
*ret_type
)
312 char *qualified_name
;
315 /* NB. No winbindd_separator here as lookup_name needs \\' */
316 if ((p
= strchr_m(full_name
, *lp_winbind_separator())) != NULL
) {
318 /* The name is already qualified with a domain. */
320 if (*lp_winbind_separator() != '\\') {
323 /* lookup_name() needs '\\' as a separator */
325 tmp
= talloc_strdup(mem_ctx
, full_name
);
329 tmp
[p
- full_name
] = '\\';
333 return lookup_name(mem_ctx
, full_name
, flags
,
334 ret_domain
, ret_name
,
338 /* Try with our own SAM name. */
339 qualified_name
= talloc_asprintf(mem_ctx
, "%s\\%s",
340 get_global_sam_name(),
342 if (!qualified_name
) {
346 if (lookup_name(mem_ctx
, qualified_name
, flags
,
347 ret_domain
, ret_name
,
348 ret_sid
, ret_type
)) {
352 /* Finally try with "Unix Users" or "Unix Group" */
353 qualified_name
= talloc_asprintf(mem_ctx
, "%s\\%s",
354 flags
& LOOKUP_NAME_GROUP
?
355 unix_groups_domain_name() :
356 unix_users_domain_name(),
358 if (!qualified_name
) {
362 return lookup_name(mem_ctx
, qualified_name
, flags
,
363 ret_domain
, ret_name
,
367 static BOOL
winbind_lookup_rids(TALLOC_CTX
*mem_ctx
,
368 const DOM_SID
*domain_sid
,
369 int num_rids
, uint32
*rids
,
370 const char **domain_name
,
371 const char **names
, uint32
*types
)
373 /* Unless the winbind interface is upgraded, fall back to ask for
374 * individual sids. I imagine introducing a lookuprids operation that
375 * directly proxies to lsa_lookupsids to the correct DC. -- vl */
378 for (i
=0; i
<num_rids
; i
++) {
381 sid_copy(&sid
, domain_sid
);
382 sid_append_rid(&sid
, rids
[i
]);
384 if (winbind_lookup_sid(mem_ctx
, &sid
,
385 *domain_name
== NULL
?
387 &names
[i
], &types
[i
])) {
388 if ((names
[i
] == NULL
) || ((*domain_name
) == NULL
)) {
392 types
[i
] = SID_NAME_UNKNOWN
;
398 static BOOL
lookup_rids(TALLOC_CTX
*mem_ctx
, const DOM_SID
*domain_sid
,
399 int num_rids
, uint32_t *rids
,
400 const char **domain_name
,
401 const char ***names
, enum SID_NAME_USE
**types
)
405 *names
= TALLOC_ARRAY(mem_ctx
, const char *, num_rids
);
406 *types
= TALLOC_ARRAY(mem_ctx
, enum SID_NAME_USE
, num_rids
);
408 if ((*names
== NULL
) || (*types
== NULL
)) {
412 if (sid_check_is_domain(domain_sid
)) {
415 if (*domain_name
== NULL
) {
416 *domain_name
= talloc_strdup(
417 mem_ctx
, get_global_sam_name());
420 if (*domain_name
== NULL
) {
425 result
= pdb_lookup_rids(domain_sid
, num_rids
, rids
,
429 return (NT_STATUS_IS_OK(result
) ||
430 NT_STATUS_EQUAL(result
, NT_STATUS_NONE_MAPPED
) ||
431 NT_STATUS_EQUAL(result
, STATUS_SOME_UNMAPPED
));
434 if (sid_check_is_builtin(domain_sid
)) {
436 if (*domain_name
== NULL
) {
437 *domain_name
= talloc_strdup(
438 mem_ctx
, builtin_domain_name());
441 if (*domain_name
== NULL
) {
445 for (i
=0; i
<num_rids
; i
++) {
446 if (lookup_builtin_rid(*names
, rids
[i
],
448 if ((*names
)[i
] == NULL
) {
451 (*types
)[i
] = SID_NAME_ALIAS
;
453 (*types
)[i
] = SID_NAME_UNKNOWN
;
459 if (sid_check_is_wellknown_domain(domain_sid
, NULL
)) {
460 for (i
=0; i
<num_rids
; i
++) {
462 sid_copy(&sid
, domain_sid
);
463 sid_append_rid(&sid
, rids
[i
]);
464 if (lookup_wellknown_sid(mem_ctx
, &sid
,
465 domain_name
, &(*names
)[i
])) {
466 if ((*names
)[i
] == NULL
) {
469 (*types
)[i
] = SID_NAME_WKN_GRP
;
471 (*types
)[i
] = SID_NAME_UNKNOWN
;
477 if (sid_check_is_unix_users(domain_sid
)) {
478 if (*domain_name
== NULL
) {
479 *domain_name
= talloc_strdup(
480 mem_ctx
, unix_users_domain_name());
482 for (i
=0; i
<num_rids
; i
++) {
483 (*names
)[i
] = talloc_strdup(
484 (*names
), uidtoname(rids
[i
]));
485 (*types
)[i
] = SID_NAME_USER
;
490 if (sid_check_is_unix_groups(domain_sid
)) {
491 if (*domain_name
== NULL
) {
492 *domain_name
= talloc_strdup(
493 mem_ctx
, unix_groups_domain_name());
495 for (i
=0; i
<num_rids
; i
++) {
496 (*names
)[i
] = talloc_strdup(
497 (*names
), gidtoname(rids
[i
]));
498 (*types
)[i
] = SID_NAME_DOM_GRP
;
503 return winbind_lookup_rids(mem_ctx
, domain_sid
, num_rids
, rids
,
504 domain_name
, *names
, *types
);
508 * Is the SID a domain as such? If yes, lookup its name.
511 static BOOL
lookup_as_domain(const DOM_SID
*sid
, TALLOC_CTX
*mem_ctx
,
515 enum SID_NAME_USE type
;
517 if (sid_check_is_domain(sid
)) {
518 *name
= talloc_strdup(mem_ctx
, get_global_sam_name());
522 if (sid_check_is_builtin(sid
)) {
523 *name
= talloc_strdup(mem_ctx
, builtin_domain_name());
527 if (sid_check_is_wellknown_domain(sid
, &tmp
)) {
528 *name
= talloc_strdup(mem_ctx
, tmp
);
532 if (sid
->num_auths
!= 4) {
533 /* This can't be a domain */
538 uint32 i
, num_domains
;
539 struct trustdom_info
**domains
;
541 /* This is relatively expensive, but it happens only on DCs
542 * and for SIDs that have 4 sub-authorities and thus look like
545 if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx
,
551 for (i
=0; i
<num_domains
; i
++) {
552 if (sid_equal(sid
, &domains
[i
]->sid
)) {
553 *name
= talloc_strdup(mem_ctx
,
561 if (winbind_lookup_sid(mem_ctx
, sid
, &tmp
, NULL
, &type
) &&
562 (type
== SID_NAME_DOMAIN
)) {
571 * This tries to implement the rather weird rules for the lsa_lookup level
574 * This is as close as we can get to what W2k3 does. With this we survive the
575 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
576 * different, but I assume that's just being too liberal. For example, W2k3
577 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
578 * whereas NT4 does the same as level 1 (I think). I did not fully test that
579 * with NT4, this is what w2k3 does.
581 * Level 1: Ask everywhere
582 * Level 2: Ask domain and trusted domains, no builtin and wkn
583 * Level 3: Only ask domain
584 * Level 4: W2k3ad: Only ask AD trusts
585 * Level 5: Don't lookup anything
589 static BOOL
check_dom_sid_to_level(const DOM_SID
*sid
, int level
)
598 ret
= (!sid_check_is_builtin(sid
) &&
599 !sid_check_is_wellknown_domain(sid
, NULL
));
604 ret
= sid_check_is_domain(sid
);
611 DEBUG(10, ("%s SID %s in level %d\n",
612 ret
? "Accepting" : "Rejecting",
613 sid_string_static(sid
), level
));
618 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
619 * references to domains, it is explicitly made for this.
621 * This attempts to be as efficient as possible: It collects all SIDs
622 * belonging to a domain and hands them in bulk to the appropriate lookup
623 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
624 * *hugely* from this. Winbind is going to be extended with a lookup_rids
625 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
629 NTSTATUS
lookup_sids(TALLOC_CTX
*mem_ctx
, int num_sids
,
630 const DOM_SID
**sids
, int level
,
631 struct lsa_dom_info
**ret_domains
,
632 struct lsa_name_info
**ret_names
)
635 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
636 struct lsa_name_info
*name_infos
;
637 struct lsa_dom_info
*dom_infos
;
641 tmp_ctx
= talloc_new(mem_ctx
);
642 if (tmp_ctx
== NULL
) {
643 DEBUG(0, ("talloc_new failed\n"));
644 return NT_STATUS_NO_MEMORY
;
647 name_infos
= TALLOC_ARRAY(tmp_ctx
, struct lsa_name_info
, num_sids
);
648 dom_infos
= TALLOC_ZERO_ARRAY(tmp_ctx
, struct lsa_dom_info
,
650 if ((name_infos
== NULL
) || (dom_infos
== NULL
)) {
651 result
= NT_STATUS_NO_MEMORY
;
655 /* First build up the data structures:
657 * dom_infos is a list of domains referenced in the list of
658 * SIDs. Later we will walk the list of domains and look up the RIDs
661 * name_infos is a shadow-copy of the SIDs array to collect the real
664 * dom_info->idxs is an index into the name_infos array. The
665 * difficulty we have here is that we need to keep the SIDs the client
666 * asked for in the same order for the reply
669 for (i
=0; i
<num_sids
; i
++) {
672 const char *domain_name
= NULL
;
674 sid_copy(&sid
, sids
[i
]);
675 name_infos
[i
].type
= SID_NAME_USE_NONE
;
677 if (lookup_as_domain(&sid
, name_infos
, &domain_name
)) {
678 /* We can't push that through the normal lookup
679 * process, as this would reference illegal
682 * For example S-1-5-32 would end up referencing
683 * domain S-1-5- with RID 32 which is clearly wrong.
685 if (domain_name
== NULL
) {
686 result
= NT_STATUS_NO_MEMORY
;
690 name_infos
[i
].rid
= 0;
691 name_infos
[i
].type
= SID_NAME_DOMAIN
;
692 name_infos
[i
].name
= NULL
;
694 if (sid_check_is_builtin(&sid
)) {
695 /* Yes, W2k3 returns "BUILTIN" both as domain
697 name_infos
[i
].name
= talloc_strdup(
698 name_infos
, builtin_domain_name());
699 if (name_infos
[i
].name
== NULL
) {
700 result
= NT_STATUS_NO_MEMORY
;
705 /* This is a normal SID with rid component */
706 if (!sid_split_rid(&sid
, &rid
)) {
707 result
= NT_STATUS_INVALID_PARAMETER
;
712 if (!check_dom_sid_to_level(&sid
, level
)) {
713 name_infos
[i
].rid
= 0;
714 name_infos
[i
].type
= SID_NAME_UNKNOWN
;
715 name_infos
[i
].name
= NULL
;
719 for (j
=0; j
<MAX_REF_DOMAINS
; j
++) {
720 if (!dom_infos
[j
].valid
) {
723 if (sid_equal(&sid
, &dom_infos
[j
].sid
)) {
728 if (j
== MAX_REF_DOMAINS
) {
729 /* TODO: What's the right error message here? */
730 result
= NT_STATUS_NONE_MAPPED
;
734 if (!dom_infos
[j
].valid
) {
735 /* We found a domain not yet referenced, create a new
737 dom_infos
[j
].valid
= True
;
738 sid_copy(&dom_infos
[j
].sid
, &sid
);
740 if (domain_name
!= NULL
) {
741 /* This name was being found above in the case
742 * when we found a domain SID */
744 talloc_steal(dom_infos
, domain_name
);
746 /* lookup_rids will take care of this */
747 dom_infos
[j
].name
= NULL
;
751 name_infos
[i
].dom_idx
= j
;
753 if (name_infos
[i
].type
== SID_NAME_USE_NONE
) {
754 name_infos
[i
].rid
= rid
;
756 ADD_TO_ARRAY(dom_infos
, int, i
, &dom_infos
[j
].idxs
,
757 &dom_infos
[j
].num_idxs
);
759 if (dom_infos
[j
].idxs
== NULL
) {
760 result
= NT_STATUS_NO_MEMORY
;
766 /* Iterate over the domains found */
768 for (i
=0; i
<MAX_REF_DOMAINS
; i
++) {
771 enum SID_NAME_USE
*types
;
772 struct lsa_dom_info
*dom
= &dom_infos
[i
];
775 /* No domains left, we're done */
779 rids
= TALLOC_ARRAY(tmp_ctx
, uint32
, dom
->num_idxs
);
782 result
= NT_STATUS_NO_MEMORY
;
786 for (j
=0; j
<dom
->num_idxs
; j
++) {
787 rids
[j
] = name_infos
[dom
->idxs
[j
]].rid
;
790 if (!lookup_rids(tmp_ctx
, &dom
->sid
,
791 dom
->num_idxs
, rids
, &dom
->name
,
793 result
= NT_STATUS_NO_MEMORY
;
797 talloc_steal(dom_infos
, dom
->name
);
799 for (j
=0; j
<dom
->num_idxs
; j
++) {
800 int idx
= dom
->idxs
[j
];
801 name_infos
[idx
].type
= types
[j
];
802 if (types
[j
] != SID_NAME_UNKNOWN
) {
803 name_infos
[idx
].name
=
804 talloc_steal(name_infos
, names
[j
]);
806 name_infos
[idx
].name
= NULL
;
811 *ret_domains
= talloc_steal(mem_ctx
, dom_infos
);
812 *ret_names
= talloc_steal(mem_ctx
, name_infos
);
813 result
= NT_STATUS_OK
;
816 TALLOC_FREE(tmp_ctx
);
820 /*****************************************************************
821 *THE CANONICAL* convert SID to name function.
822 *****************************************************************/
824 BOOL
lookup_sid(TALLOC_CTX
*mem_ctx
, const DOM_SID
*sid
,
825 const char **ret_domain
, const char **ret_name
,
826 enum SID_NAME_USE
*ret_type
)
828 struct lsa_dom_info
*domain
;
829 struct lsa_name_info
*name
;
833 tmp_ctx
= talloc_new(mem_ctx
);
835 if (tmp_ctx
== NULL
) {
836 DEBUG(0, ("talloc_new failed\n"));
840 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx
, 1, &sid
, 1,
845 if (name
->type
== SID_NAME_UNKNOWN
) {
849 if (ret_domain
!= NULL
) {
850 *ret_domain
= talloc_steal(mem_ctx
, domain
->name
);
853 if (ret_name
!= NULL
) {
854 *ret_name
= talloc_steal(mem_ctx
, name
->name
);
857 if (ret_type
!= NULL
) {
858 *ret_type
= name
->type
;
865 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
866 sid_string_static(sid
), domain
->name
,
867 name
->name
, name
->type
));
869 DEBUG(10, ("failed to lookup sid %s\n",
870 sid_string_static(sid
)));
872 TALLOC_FREE(tmp_ctx
);
876 /*****************************************************************
877 Id mapping cache. This is to avoid Winbind mappings already
878 seen by smbd to be queried too frequently, keeping winbindd
879 busy, and blocking smbd while winbindd is busy with other
880 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
881 modified to use linked lists by jra.
882 *****************************************************************/
884 #define MAX_UID_SID_CACHE_SIZE 100
885 #define TURNOVER_UID_SID_CACHE_SIZE 10
886 #define MAX_GID_SID_CACHE_SIZE 100
887 #define TURNOVER_GID_SID_CACHE_SIZE 10
889 static size_t n_uid_sid_cache
= 0;
890 static size_t n_gid_sid_cache
= 0;
892 static struct uid_sid_cache
{
893 struct uid_sid_cache
*next
, *prev
;
896 enum SID_NAME_USE sidtype
;
897 } *uid_sid_cache_head
;
899 static struct gid_sid_cache
{
900 struct gid_sid_cache
*next
, *prev
;
903 enum SID_NAME_USE sidtype
;
904 } *gid_sid_cache_head
;
906 /*****************************************************************
907 Find a SID given a uid.
908 *****************************************************************/
910 static BOOL
fetch_sid_from_uid_cache(DOM_SID
*psid
, uid_t uid
)
912 struct uid_sid_cache
*pc
;
914 for (pc
= uid_sid_cache_head
; pc
; pc
= pc
->next
) {
915 if (pc
->uid
== uid
) {
917 DEBUG(3,("fetch sid from uid cache %u -> %s\n",
918 (unsigned int)uid
, sid_string_static(psid
)));
919 DLIST_PROMOTE(uid_sid_cache_head
, pc
);
926 /*****************************************************************
927 Find a uid given a SID.
928 *****************************************************************/
930 static BOOL
fetch_uid_from_cache( uid_t
*puid
, const DOM_SID
*psid
)
932 struct uid_sid_cache
*pc
;
934 for (pc
= uid_sid_cache_head
; pc
; pc
= pc
->next
) {
935 if (sid_compare(&pc
->sid
, psid
) == 0) {
937 DEBUG(3,("fetch uid from cache %u -> %s\n",
938 (unsigned int)*puid
, sid_string_static(psid
)));
939 DLIST_PROMOTE(uid_sid_cache_head
, pc
);
946 /*****************************************************************
947 Store uid to SID mapping in cache.
948 *****************************************************************/
950 void store_uid_sid_cache(const DOM_SID
*psid
, uid_t uid
)
952 struct uid_sid_cache
*pc
;
954 /* do not store SIDs in the "Unix Group" domain */
956 if ( sid_check_is_in_unix_users( psid
) )
959 if (n_uid_sid_cache
>= MAX_UID_SID_CACHE_SIZE
&& n_uid_sid_cache
> TURNOVER_UID_SID_CACHE_SIZE
) {
960 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
961 struct uid_sid_cache
*pc_next
;
964 for (i
= 0, pc
= uid_sid_cache_head
; i
< (n_uid_sid_cache
- TURNOVER_UID_SID_CACHE_SIZE
); i
++, pc
= pc
->next
)
966 for(; pc
; pc
= pc_next
) {
968 DLIST_REMOVE(uid_sid_cache_head
,pc
);
974 pc
= SMB_MALLOC_P(struct uid_sid_cache
);
978 sid_copy(&pc
->sid
, psid
);
979 DLIST_ADD(uid_sid_cache_head
, pc
);
983 /*****************************************************************
984 Find a SID given a gid.
985 *****************************************************************/
987 static BOOL
fetch_sid_from_gid_cache(DOM_SID
*psid
, gid_t gid
)
989 struct gid_sid_cache
*pc
;
991 for (pc
= gid_sid_cache_head
; pc
; pc
= pc
->next
) {
992 if (pc
->gid
== gid
) {
994 DEBUG(3,("fetch sid from gid cache %u -> %s\n",
995 (unsigned int)gid
, sid_string_static(psid
)));
996 DLIST_PROMOTE(gid_sid_cache_head
, pc
);
1003 /*****************************************************************
1004 Find a gid given a SID.
1005 *****************************************************************/
1007 static BOOL
fetch_gid_from_cache(gid_t
*pgid
, const DOM_SID
*psid
)
1009 struct gid_sid_cache
*pc
;
1011 for (pc
= gid_sid_cache_head
; pc
; pc
= pc
->next
) {
1012 if (sid_compare(&pc
->sid
, psid
) == 0) {
1014 DEBUG(3,("fetch gid from cache %u -> %s\n",
1015 (unsigned int)*pgid
, sid_string_static(psid
)));
1016 DLIST_PROMOTE(gid_sid_cache_head
, pc
);
1023 /*****************************************************************
1024 Store gid to SID mapping in cache.
1025 *****************************************************************/
1027 void store_gid_sid_cache(const DOM_SID
*psid
, gid_t gid
)
1029 struct gid_sid_cache
*pc
;
1031 /* do not store SIDs in the "Unix Group" domain */
1033 if ( sid_check_is_in_unix_groups( psid
) )
1036 if (n_gid_sid_cache
>= MAX_GID_SID_CACHE_SIZE
&& n_gid_sid_cache
> TURNOVER_GID_SID_CACHE_SIZE
) {
1037 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
1038 struct gid_sid_cache
*pc_next
;
1041 for (i
= 0, pc
= gid_sid_cache_head
; i
< (n_gid_sid_cache
- TURNOVER_GID_SID_CACHE_SIZE
); i
++, pc
= pc
->next
)
1043 for(; pc
; pc
= pc_next
) {
1045 DLIST_REMOVE(gid_sid_cache_head
,pc
);
1051 pc
= SMB_MALLOC_P(struct gid_sid_cache
);
1055 sid_copy(&pc
->sid
, psid
);
1056 DLIST_ADD(gid_sid_cache_head
, pc
);
1058 DEBUG(3,("store_gid_sid_cache: gid %u in cache -> %s\n", (unsigned int)gid
,
1059 sid_string_static(psid
)));
1064 /*****************************************************************
1065 *THE CANONICAL* convert uid_t to SID function.
1066 *****************************************************************/
1068 void uid_to_sid(DOM_SID
*psid
, uid_t uid
)
1075 if (fetch_sid_from_uid_cache(psid
, uid
))
1078 if (lp_idmap_uid(&low
, &high
) && (uid
>= low
) && (uid
<= high
) &&
1079 winbind_uid_to_sid(psid
, uid
)) {
1081 DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
1082 (unsigned int)uid
, sid_string_static(psid
)));
1086 if (pdb_uid_to_rid(uid
, &rid
)) {
1087 /* This is a mapped user */
1088 sid_copy(psid
, get_global_sam_sid());
1089 sid_append_rid(psid
, rid
);
1093 /* This is an unmapped user */
1095 uid_to_unix_users_sid(uid
, psid
);
1098 DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid
,
1099 sid_string_static(psid
)));
1101 store_uid_sid_cache(psid
, uid
);
1105 /*****************************************************************
1106 *THE CANONICAL* convert gid_t to SID function.
1107 *****************************************************************/
1109 void gid_to_sid(DOM_SID
*psid
, gid_t gid
)
1115 if (fetch_sid_from_gid_cache(psid
, gid
))
1118 if (lp_idmap_gid(&low
, &high
) && (gid
>= low
) && (gid
<= high
) &&
1119 winbind_gid_to_sid(psid
, gid
)) {
1121 DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
1122 (unsigned int)gid
, sid_string_static(psid
)));
1126 if (pdb_gid_to_sid(gid
, psid
)) {
1127 /* This is a mapped group */
1131 /* This is an unmapped group */
1133 gid_to_unix_groups_sid(gid
, psid
);
1136 DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid
,
1137 sid_string_static(psid
)));
1139 store_gid_sid_cache(psid
, gid
);
1143 /*****************************************************************
1144 *THE CANONICAL* convert SID to uid function.
1145 *****************************************************************/
1147 BOOL
sid_to_uid(const DOM_SID
*psid
, uid_t
*puid
)
1149 enum SID_NAME_USE type
;
1153 if (fetch_uid_from_cache(puid
, psid
))
1156 if (fetch_gid_from_cache(&gid
, psid
)) {
1160 if (sid_peek_check_rid(&global_sid_Unix_Users
, psid
, &rid
)) {
1166 if (sid_peek_check_rid(get_global_sam_sid(), psid
, &rid
)) {
1169 if (pdb_sid_to_id(psid
, &id
, &type
)) {
1170 if (type
!= SID_NAME_USER
) {
1171 DEBUG(5, ("sid %s is a %s, expected a user\n",
1172 sid_string_static(psid
),
1173 sid_type_lookup(type
)));
1180 /* This was ours, but it was not mapped. Fail */
1185 if (winbind_lookup_sid(NULL
, psid
, NULL
, NULL
, &type
)) {
1187 if (type
!= SID_NAME_USER
) {
1188 DEBUG(10, ("sid_to_uid: sid %s is a %s\n",
1189 sid_string_static(psid
),
1190 sid_type_lookup(type
)));
1194 if (!winbind_sid_to_uid(puid
, psid
)) {
1195 DEBUG(5, ("sid_to_uid: winbind failed to allocate a "
1196 "new uid for sid %s\n",
1197 sid_string_static(psid
)));
1203 /* TODO: Here would be the place to allocate both a gid and a uid for
1204 * the SID in question */
1209 DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid
),
1210 (unsigned int)*puid
));
1212 store_uid_sid_cache(psid
, *puid
);
1216 /*****************************************************************
1217 *THE CANONICAL* convert SID to gid function.
1218 Group mapping is used for gids that maps to Wellknown SIDs
1219 *****************************************************************/
1221 BOOL
sid_to_gid(const DOM_SID
*psid
, gid_t
*pgid
)
1226 enum SID_NAME_USE type
;
1229 if (fetch_gid_from_cache(pgid
, psid
))
1232 if (fetch_uid_from_cache(&uid
, psid
))
1235 if (sid_peek_check_rid(&global_sid_Unix_Groups
, psid
, &rid
)) {
1241 if ((sid_check_is_in_builtin(psid
) ||
1242 sid_check_is_in_wellknown_domain(psid
))) {
1243 if (pdb_getgrsid(&map
, *psid
)) {
1250 if (sid_peek_check_rid(get_global_sam_sid(), psid
, &rid
)) {
1251 if (pdb_sid_to_id(psid
, &id
, &type
)) {
1252 if ((type
!= SID_NAME_DOM_GRP
) &&
1253 (type
!= SID_NAME_ALIAS
)) {
1254 DEBUG(5, ("sid %s is a %s, expected a group\n",
1255 sid_string_static(psid
),
1256 sid_type_lookup(type
)));
1263 /* This was ours, but it was not mapped. Fail */
1268 if (!winbind_lookup_sid(NULL
, psid
, NULL
, NULL
, &type
)) {
1269 DEBUG(11,("sid_to_gid: no one knows the SID %s (tried local, "
1270 "then winbind)\n", sid_string_static(psid
)));
1275 /* winbindd knows it; Ensure this is a group sid */
1277 if ((type
!= SID_NAME_DOM_GRP
) && (type
!= SID_NAME_ALIAS
) &&
1278 (type
!= SID_NAME_WKN_GRP
)) {
1279 DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is "
1280 "a %s\n", sid_type_lookup(type
)));
1284 /* winbindd knows it and it is a type of group; sid_to_gid must succeed
1285 or we are dead in the water */
1287 if ( !winbind_sid_to_gid(pgid
, psid
) ) {
1288 DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid "
1289 "for sid %s\n", sid_string_static(psid
)));
1294 DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid
),
1295 (unsigned int)*pgid
));
1297 store_gid_sid_cache(psid
, *pgid
);