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 if ((domain
== NULL
) || (name
== NULL
)) {
64 DEBUG(0, ("talloc failed\n"));
69 DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
70 full_name
, domain
, name
));
71 DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags
));
73 if ((flags
& LOOKUP_NAME_DOMAIN
) &&
74 strequal(domain
, get_global_sam_name()))
77 /* It's our own domain, lookup the name in passdb */
78 if (lookup_global_sam_name(name
, flags
, &rid
, &type
)) {
79 sid_copy(&sid
, get_global_sam_sid());
80 sid_append_rid(&sid
, rid
);
87 if ((flags
& LOOKUP_NAME_BUILTIN
) &&
88 strequal(domain
, builtin_domain_name()))
90 /* Explicit request for a name in BUILTIN */
91 if (lookup_builtin_name(name
, &rid
)) {
92 sid_copy(&sid
, &global_sid_Builtin
);
93 sid_append_rid(&sid
, rid
);
94 type
= SID_NAME_ALIAS
;
101 /* Try the explicit winbind lookup first, don't let it guess the
102 * domain yet at this point yet. This comes later. */
104 if ((domain
[0] != '\0') &&
105 (flags
& ~(LOOKUP_NAME_DOMAIN
|LOOKUP_NAME_ISOLATED
)) &&
106 (winbind_lookup_name(domain
, name
, &sid
, &type
))) {
110 if (strequal(domain
, unix_users_domain_name())) {
111 if (lookup_unix_user_name(name
, &sid
)) {
112 type
= SID_NAME_USER
;
115 TALLOC_FREE(tmp_ctx
);
119 if (strequal(domain
, unix_groups_domain_name())) {
120 if (lookup_unix_group_name(name
, &sid
)) {
121 type
= SID_NAME_DOM_GRP
;
124 TALLOC_FREE(tmp_ctx
);
128 if ((domain
[0] == '\0') && (!(flags
& LOOKUP_NAME_ISOLATED
))) {
129 TALLOC_FREE(tmp_ctx
);
133 /* Now the guesswork begins, we haven't been given an explicit
134 * domain. Try the sequence as documented on
135 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
136 * November 27, 2005 */
138 /* 1. well-known names */
140 if ((flags
& LOOKUP_NAME_WKN
) &&
141 lookup_wellknown_name(tmp_ctx
, name
, &sid
, &domain
))
143 type
= SID_NAME_WKN_GRP
;
147 /* 2. Builtin domain as such */
149 if ((flags
& (LOOKUP_NAME_BUILTIN
|LOOKUP_NAME_REMOTE
)) &&
150 strequal(name
, builtin_domain_name()))
152 /* Swap domain and name */
153 tmp
= name
; name
= domain
; domain
= tmp
;
154 sid_copy(&sid
, &global_sid_Builtin
);
155 type
= SID_NAME_DOMAIN
;
159 /* 3. Account domain */
161 if ((flags
& LOOKUP_NAME_DOMAIN
) &&
162 strequal(name
, get_global_sam_name()))
164 if (!secrets_fetch_domain_sid(name
, &sid
)) {
165 DEBUG(3, ("Could not fetch my SID\n"));
166 TALLOC_FREE(tmp_ctx
);
169 /* Swap domain and name */
170 tmp
= name
; name
= domain
; domain
= tmp
;
171 type
= SID_NAME_DOMAIN
;
175 /* 4. Primary domain */
177 if ((flags
& LOOKUP_NAME_DOMAIN
) && !IS_DC
&&
178 strequal(name
, lp_workgroup()))
180 if (!secrets_fetch_domain_sid(name
, &sid
)) {
181 DEBUG(3, ("Could not fetch the domain SID\n"));
182 TALLOC_FREE(tmp_ctx
);
185 /* Swap domain and name */
186 tmp
= name
; name
= domain
; domain
= tmp
;
187 type
= SID_NAME_DOMAIN
;
191 /* 5. Trusted domains as such, to me it looks as if members don't do
192 this, tested an XP workstation in a NT domain -- vl */
194 if ((flags
& LOOKUP_NAME_REMOTE
) && IS_DC
&&
195 (secrets_fetch_trusted_domain_password(name
, NULL
, &sid
, NULL
)))
197 /* Swap domain and name */
198 tmp
= name
; name
= domain
; domain
= tmp
;
199 type
= SID_NAME_DOMAIN
;
203 /* 6. Builtin aliases */
205 if ((flags
& LOOKUP_NAME_BUILTIN
) &&
206 lookup_builtin_name(name
, &rid
))
208 domain
= talloc_strdup(tmp_ctx
, builtin_domain_name());
209 sid_copy(&sid
, &global_sid_Builtin
);
210 sid_append_rid(&sid
, rid
);
211 type
= SID_NAME_ALIAS
;
215 /* 7. Local systems' SAM (DCs don't have a local SAM) */
216 /* 8. Primary SAM (On members, this is the domain) */
218 /* Both cases are done by looking at our passdb */
220 if ((flags
& LOOKUP_NAME_DOMAIN
) &&
221 lookup_global_sam_name(name
, flags
, &rid
, &type
))
223 domain
= talloc_strdup(tmp_ctx
, get_global_sam_name());
224 sid_copy(&sid
, get_global_sam_sid());
225 sid_append_rid(&sid
, rid
);
229 /* Now our local possibilities are exhausted. */
231 if (!(flags
& LOOKUP_NAME_REMOTE
)) {
232 TALLOC_FREE(tmp_ctx
);
236 /* If we are not a DC, we have to ask in our primary domain. Let
237 * winbind do that. */
240 (winbind_lookup_name(lp_workgroup(), name
, &sid
, &type
))) {
241 domain
= talloc_strdup(tmp_ctx
, lp_workgroup());
245 /* 9. Trusted domains */
247 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
248 * that (yet), but give it a chance. */
250 if (IS_DC
&& winbind_lookup_name("", name
, &sid
, &type
)) {
253 enum lsa_SidType domain_type
;
255 if (type
== SID_NAME_DOMAIN
) {
256 /* Swap name and type */
257 tmp
= name
; name
= domain
; domain
= tmp
;
261 /* Here we have to cope with a little deficiency in the
262 * winbind API: We have to ask it again for the name of the
263 * domain it figured out itself. Maybe fix that later... */
265 sid_copy(&dom_sid
, &sid
);
266 sid_split_rid(&dom_sid
, &tmp_rid
);
268 if (!winbind_lookup_sid(tmp_ctx
, &dom_sid
, &domain
, NULL
,
270 (domain_type
!= SID_NAME_DOMAIN
)) {
271 DEBUG(2, ("winbind could not find the domain's name "
272 "it just looked up for us\n"));
273 TALLOC_FREE(tmp_ctx
);
279 /* 10. Don't translate */
281 /* 11. Ok, windows would end here. Samba has two more options:
282 Unmapped users and unmapped groups */
284 if (lookup_unix_user_name(name
, &sid
)) {
285 domain
= talloc_strdup(tmp_ctx
, unix_users_domain_name());
286 type
= SID_NAME_USER
;
290 if (lookup_unix_group_name(name
, &sid
)) {
291 domain
= talloc_strdup(tmp_ctx
, unix_groups_domain_name());
292 type
= SID_NAME_DOM_GRP
;
297 * Ok, all possibilities tried. Fail.
300 TALLOC_FREE(tmp_ctx
);
304 if ((domain
== NULL
) || (name
== NULL
)) {
305 DEBUG(0, ("talloc failed\n"));
306 TALLOC_FREE(tmp_ctx
);
311 * Hand over the results to the talloc context we've been given.
314 if ((ret_name
!= NULL
) &&
315 !(*ret_name
= talloc_strdup(mem_ctx
, name
))) {
316 DEBUG(0, ("talloc failed\n"));
317 TALLOC_FREE(tmp_ctx
);
321 if (ret_domain
!= NULL
) {
323 if (!(tmp_dom
= talloc_strdup(mem_ctx
, domain
))) {
324 DEBUG(0, ("talloc failed\n"));
325 TALLOC_FREE(tmp_ctx
);
329 *ret_domain
= tmp_dom
;
332 if (ret_sid
!= NULL
) {
333 sid_copy(ret_sid
, &sid
);
336 if (ret_type
!= NULL
) {
340 TALLOC_FREE(tmp_ctx
);
344 /************************************************************************
345 Names from smb.conf can be unqualified. eg. valid users = foo
346 These names should never map to a remote name. Try global_sam_name()\foo,
347 and then "Unix Users"\foo (or "Unix Groups"\foo).
348 ************************************************************************/
350 BOOL
lookup_name_smbconf(TALLOC_CTX
*mem_ctx
,
351 const char *full_name
, int flags
,
352 const char **ret_domain
, const char **ret_name
,
353 DOM_SID
*ret_sid
, enum lsa_SidType
*ret_type
)
355 char *qualified_name
;
358 /* NB. No winbindd_separator here as lookup_name needs \\' */
359 if ((p
= strchr_m(full_name
, *lp_winbind_separator())) != NULL
) {
361 /* The name is already qualified with a domain. */
363 if (*lp_winbind_separator() != '\\') {
366 /* lookup_name() needs '\\' as a separator */
368 tmp
= talloc_strdup(mem_ctx
, full_name
);
372 tmp
[p
- full_name
] = '\\';
376 return lookup_name(mem_ctx
, full_name
, flags
,
377 ret_domain
, ret_name
,
381 /* Try with our own SAM name. */
382 qualified_name
= talloc_asprintf(mem_ctx
, "%s\\%s",
383 get_global_sam_name(),
385 if (!qualified_name
) {
389 if (lookup_name(mem_ctx
, qualified_name
, flags
,
390 ret_domain
, ret_name
,
391 ret_sid
, ret_type
)) {
395 /* Finally try with "Unix Users" or "Unix Group" */
396 qualified_name
= talloc_asprintf(mem_ctx
, "%s\\%s",
397 flags
& LOOKUP_NAME_GROUP
?
398 unix_groups_domain_name() :
399 unix_users_domain_name(),
401 if (!qualified_name
) {
405 return lookup_name(mem_ctx
, qualified_name
, flags
,
406 ret_domain
, ret_name
,
410 static BOOL
wb_lookup_rids(TALLOC_CTX
*mem_ctx
,
411 const DOM_SID
*domain_sid
,
412 int num_rids
, uint32
*rids
,
413 const char **domain_name
,
414 const char **names
, enum lsa_SidType
*types
)
417 const char **my_names
;
418 enum lsa_SidType
*my_types
;
421 if (!(tmp_ctx
= talloc_init("wb_lookup_rids"))) {
425 if (!winbind_lookup_rids(tmp_ctx
, domain_sid
, num_rids
, rids
,
426 domain_name
, &my_names
, &my_types
)) {
428 for (i
=0; i
<num_rids
; i
++) {
430 types
[i
] = SID_NAME_UNKNOWN
;
432 TALLOC_FREE(tmp_ctx
);
436 if (!(*domain_name
= talloc_strdup(mem_ctx
, *domain_name
))) {
437 TALLOC_FREE(tmp_ctx
);
442 * winbind_lookup_rids allocates its own array. We've been given the
443 * array, so copy it over
446 for (i
=0; i
<num_rids
; i
++) {
447 if (my_names
[i
] == NULL
) {
448 TALLOC_FREE(tmp_ctx
);
451 if (!(names
[i
] = talloc_strdup(names
, my_names
[i
]))) {
452 TALLOC_FREE(tmp_ctx
);
455 types
[i
] = my_types
[i
];
457 TALLOC_FREE(tmp_ctx
);
461 static BOOL
lookup_rids(TALLOC_CTX
*mem_ctx
, const DOM_SID
*domain_sid
,
462 int num_rids
, uint32_t *rids
,
463 const char **domain_name
,
464 const char ***names
, enum lsa_SidType
**types
)
469 *names
= TALLOC_ARRAY(mem_ctx
, const char *, num_rids
);
470 *types
= TALLOC_ARRAY(mem_ctx
, enum lsa_SidType
, num_rids
);
472 if ((*names
== NULL
) || (*types
== NULL
)) {
480 if (sid_check_is_domain(domain_sid
)) {
483 if (*domain_name
== NULL
) {
484 *domain_name
= talloc_strdup(
485 mem_ctx
, get_global_sam_name());
488 if (*domain_name
== NULL
) {
493 result
= pdb_lookup_rids(domain_sid
, num_rids
, rids
,
497 return (NT_STATUS_IS_OK(result
) ||
498 NT_STATUS_EQUAL(result
, NT_STATUS_NONE_MAPPED
) ||
499 NT_STATUS_EQUAL(result
, STATUS_SOME_UNMAPPED
));
502 if (sid_check_is_builtin(domain_sid
)) {
504 if (*domain_name
== NULL
) {
505 *domain_name
= talloc_strdup(
506 mem_ctx
, builtin_domain_name());
509 if (*domain_name
== NULL
) {
513 for (i
=0; i
<num_rids
; i
++) {
514 if (lookup_builtin_rid(*names
, rids
[i
],
516 if ((*names
)[i
] == NULL
) {
519 (*types
)[i
] = SID_NAME_ALIAS
;
521 (*types
)[i
] = SID_NAME_UNKNOWN
;
527 if (sid_check_is_wellknown_domain(domain_sid
, NULL
)) {
528 for (i
=0; i
<num_rids
; i
++) {
530 sid_copy(&sid
, domain_sid
);
531 sid_append_rid(&sid
, rids
[i
]);
532 if (lookup_wellknown_sid(mem_ctx
, &sid
,
533 domain_name
, &(*names
)[i
])) {
534 if ((*names
)[i
] == NULL
) {
537 (*types
)[i
] = SID_NAME_WKN_GRP
;
539 (*types
)[i
] = SID_NAME_UNKNOWN
;
545 if (sid_check_is_unix_users(domain_sid
)) {
546 if (*domain_name
== NULL
) {
547 *domain_name
= talloc_strdup(
548 mem_ctx
, unix_users_domain_name());
550 for (i
=0; i
<num_rids
; i
++) {
551 (*names
)[i
] = talloc_strdup(
552 (*names
), uidtoname(rids
[i
]));
553 (*types
)[i
] = SID_NAME_USER
;
558 if (sid_check_is_unix_groups(domain_sid
)) {
559 if (*domain_name
== NULL
) {
560 *domain_name
= talloc_strdup(
561 mem_ctx
, unix_groups_domain_name());
563 for (i
=0; i
<num_rids
; i
++) {
564 (*names
)[i
] = talloc_strdup(
565 (*names
), gidtoname(rids
[i
]));
566 (*types
)[i
] = SID_NAME_DOM_GRP
;
571 return wb_lookup_rids(mem_ctx
, domain_sid
, num_rids
, rids
,
572 domain_name
, *names
, *types
);
576 * Is the SID a domain as such? If yes, lookup its name.
579 static BOOL
lookup_as_domain(const DOM_SID
*sid
, TALLOC_CTX
*mem_ctx
,
583 enum lsa_SidType type
;
585 if (sid_check_is_domain(sid
)) {
586 *name
= talloc_strdup(mem_ctx
, get_global_sam_name());
590 if (sid_check_is_builtin(sid
)) {
591 *name
= talloc_strdup(mem_ctx
, builtin_domain_name());
595 if (sid_check_is_wellknown_domain(sid
, &tmp
)) {
596 *name
= talloc_strdup(mem_ctx
, tmp
);
600 if (sid
->num_auths
!= 4) {
601 /* This can't be a domain */
606 uint32 i
, num_domains
;
607 struct trustdom_info
**domains
;
609 /* This is relatively expensive, but it happens only on DCs
610 * and for SIDs that have 4 sub-authorities and thus look like
613 if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx
,
619 for (i
=0; i
<num_domains
; i
++) {
620 if (sid_equal(sid
, &domains
[i
]->sid
)) {
621 *name
= talloc_strdup(mem_ctx
,
629 if (winbind_lookup_sid(mem_ctx
, sid
, &tmp
, NULL
, &type
) &&
630 (type
== SID_NAME_DOMAIN
)) {
639 * This tries to implement the rather weird rules for the lsa_lookup level
642 * This is as close as we can get to what W2k3 does. With this we survive the
643 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
644 * different, but I assume that's just being too liberal. For example, W2k3
645 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
646 * whereas NT4 does the same as level 1 (I think). I did not fully test that
647 * with NT4, this is what w2k3 does.
649 * Level 1: Ask everywhere
650 * Level 2: Ask domain and trusted domains, no builtin and wkn
651 * Level 3: Only ask domain
652 * Level 4: W2k3ad: Only ask AD trusts
653 * Level 5: Don't lookup anything
657 static BOOL
check_dom_sid_to_level(const DOM_SID
*sid
, int level
)
666 ret
= (!sid_check_is_builtin(sid
) &&
667 !sid_check_is_wellknown_domain(sid
, NULL
));
672 ret
= sid_check_is_domain(sid
);
679 DEBUG(10, ("%s SID %s in level %d\n",
680 ret
? "Accepting" : "Rejecting",
681 sid_string_static(sid
), level
));
686 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
687 * references to domains, it is explicitly made for this.
689 * This attempts to be as efficient as possible: It collects all SIDs
690 * belonging to a domain and hands them in bulk to the appropriate lookup
691 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
692 * *hugely* from this. Winbind is going to be extended with a lookup_rids
693 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
697 NTSTATUS
lookup_sids(TALLOC_CTX
*mem_ctx
, int num_sids
,
698 const DOM_SID
**sids
, int level
,
699 struct lsa_dom_info
**ret_domains
,
700 struct lsa_name_info
**ret_names
)
703 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
704 struct lsa_name_info
*name_infos
;
705 struct lsa_dom_info
*dom_infos
= NULL
;
709 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
710 DEBUG(0, ("talloc_new failed\n"));
711 return NT_STATUS_NO_MEMORY
;
715 name_infos
= TALLOC_ARRAY(mem_ctx
, struct lsa_name_info
, num_sids
);
716 if (name_infos
== NULL
) {
717 result
= NT_STATUS_NO_MEMORY
;
724 dom_infos
= TALLOC_ZERO_ARRAY(mem_ctx
, struct lsa_dom_info
,
726 if (dom_infos
== NULL
) {
727 result
= NT_STATUS_NO_MEMORY
;
731 /* First build up the data structures:
733 * dom_infos is a list of domains referenced in the list of
734 * SIDs. Later we will walk the list of domains and look up the RIDs
737 * name_infos is a shadow-copy of the SIDs array to collect the real
740 * dom_info->idxs is an index into the name_infos array. The
741 * difficulty we have here is that we need to keep the SIDs the client
742 * asked for in the same order for the reply
745 for (i
=0; i
<num_sids
; i
++) {
748 const char *domain_name
= NULL
;
750 sid_copy(&sid
, sids
[i
]);
751 name_infos
[i
].type
= SID_NAME_USE_NONE
;
753 if (lookup_as_domain(&sid
, name_infos
, &domain_name
)) {
754 /* We can't push that through the normal lookup
755 * process, as this would reference illegal
758 * For example S-1-5-32 would end up referencing
759 * domain S-1-5- with RID 32 which is clearly wrong.
761 if (domain_name
== NULL
) {
762 result
= NT_STATUS_NO_MEMORY
;
766 name_infos
[i
].rid
= 0;
767 name_infos
[i
].type
= SID_NAME_DOMAIN
;
768 name_infos
[i
].name
= NULL
;
770 if (sid_check_is_builtin(&sid
)) {
771 /* Yes, W2k3 returns "BUILTIN" both as domain
773 name_infos
[i
].name
= talloc_strdup(
774 name_infos
, builtin_domain_name());
775 if (name_infos
[i
].name
== NULL
) {
776 result
= NT_STATUS_NO_MEMORY
;
781 /* This is a normal SID with rid component */
782 if (!sid_split_rid(&sid
, &rid
)) {
783 result
= NT_STATUS_INVALID_PARAMETER
;
788 if (!check_dom_sid_to_level(&sid
, level
)) {
789 name_infos
[i
].rid
= 0;
790 name_infos
[i
].type
= SID_NAME_UNKNOWN
;
791 name_infos
[i
].name
= NULL
;
795 for (j
=0; j
<MAX_REF_DOMAINS
; j
++) {
796 if (!dom_infos
[j
].valid
) {
799 if (sid_equal(&sid
, &dom_infos
[j
].sid
)) {
804 if (j
== MAX_REF_DOMAINS
) {
805 /* TODO: What's the right error message here? */
806 result
= NT_STATUS_NONE_MAPPED
;
810 if (!dom_infos
[j
].valid
) {
811 /* We found a domain not yet referenced, create a new
813 dom_infos
[j
].valid
= True
;
814 sid_copy(&dom_infos
[j
].sid
, &sid
);
816 if (domain_name
!= NULL
) {
817 /* This name was being found above in the case
818 * when we found a domain SID */
820 talloc_strdup(dom_infos
, domain_name
);
821 if (dom_infos
[j
].name
== NULL
) {
822 result
= NT_STATUS_NO_MEMORY
;
826 /* lookup_rids will take care of this */
827 dom_infos
[j
].name
= NULL
;
831 name_infos
[i
].dom_idx
= j
;
833 if (name_infos
[i
].type
== SID_NAME_USE_NONE
) {
834 name_infos
[i
].rid
= rid
;
836 ADD_TO_ARRAY(dom_infos
, int, i
, &dom_infos
[j
].idxs
,
837 &dom_infos
[j
].num_idxs
);
839 if (dom_infos
[j
].idxs
== NULL
) {
840 result
= NT_STATUS_NO_MEMORY
;
846 /* Iterate over the domains found */
848 for (i
=0; i
<MAX_REF_DOMAINS
; i
++) {
850 const char *domain_name
= NULL
;
852 enum lsa_SidType
*types
;
853 struct lsa_dom_info
*dom
= &dom_infos
[i
];
856 /* No domains left, we're done */
861 if (!(rids
= TALLOC_ARRAY(tmp_ctx
, uint32
, dom
->num_idxs
))) {
862 result
= NT_STATUS_NO_MEMORY
;
869 for (j
=0; j
<dom
->num_idxs
; j
++) {
870 rids
[j
] = name_infos
[dom
->idxs
[j
]].rid
;
873 if (!lookup_rids(tmp_ctx
, &dom
->sid
,
874 dom
->num_idxs
, rids
, &domain_name
,
876 result
= NT_STATUS_NO_MEMORY
;
880 if (!(dom
->name
= talloc_strdup(dom_infos
, domain_name
))) {
881 result
= NT_STATUS_NO_MEMORY
;
885 for (j
=0; j
<dom
->num_idxs
; j
++) {
886 int idx
= dom
->idxs
[j
];
887 name_infos
[idx
].type
= types
[j
];
888 if (types
[j
] != SID_NAME_UNKNOWN
) {
889 name_infos
[idx
].name
=
890 talloc_strdup(name_infos
, names
[j
]);
891 if (name_infos
[idx
].name
== NULL
) {
892 result
= NT_STATUS_NO_MEMORY
;
896 name_infos
[idx
].name
= NULL
;
901 *ret_domains
= dom_infos
;
902 *ret_names
= name_infos
;
906 TALLOC_FREE(dom_infos
);
907 TALLOC_FREE(name_infos
);
908 TALLOC_FREE(tmp_ctx
);
912 /*****************************************************************
913 *THE CANONICAL* convert SID to name function.
914 *****************************************************************/
916 BOOL
lookup_sid(TALLOC_CTX
*mem_ctx
, const DOM_SID
*sid
,
917 const char **ret_domain
, const char **ret_name
,
918 enum lsa_SidType
*ret_type
)
920 struct lsa_dom_info
*domain
;
921 struct lsa_name_info
*name
;
925 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
926 DEBUG(0, ("talloc_new failed\n"));
930 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx
, 1, &sid
, 1,
935 if (name
->type
== SID_NAME_UNKNOWN
) {
939 if ((ret_domain
!= NULL
) &&
940 !(*ret_domain
= talloc_strdup(mem_ctx
, domain
->name
))) {
944 if ((ret_name
!= NULL
) &&
945 !(*ret_name
= talloc_strdup(mem_ctx
, name
->name
))) {
949 if (ret_type
!= NULL
) {
950 *ret_type
= name
->type
;
957 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
958 sid_string_static(sid
), domain
->name
,
959 name
->name
, name
->type
));
961 DEBUG(10, ("failed to lookup sid %s\n",
962 sid_string_static(sid
)));
964 TALLOC_FREE(tmp_ctx
);
968 /*****************************************************************
969 Id mapping cache. This is to avoid Winbind mappings already
970 seen by smbd to be queried too frequently, keeping winbindd
971 busy, and blocking smbd while winbindd is busy with other
972 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
973 modified to use linked lists by jra.
974 *****************************************************************/
976 #define MAX_UID_SID_CACHE_SIZE 100
977 #define TURNOVER_UID_SID_CACHE_SIZE 10
978 #define MAX_GID_SID_CACHE_SIZE 100
979 #define TURNOVER_GID_SID_CACHE_SIZE 10
981 static size_t n_uid_sid_cache
= 0;
982 static size_t n_gid_sid_cache
= 0;
984 static struct uid_sid_cache
{
985 struct uid_sid_cache
*next
, *prev
;
988 enum lsa_SidType sidtype
;
989 } *uid_sid_cache_head
;
991 static struct gid_sid_cache
{
992 struct gid_sid_cache
*next
, *prev
;
995 enum lsa_SidType sidtype
;
996 } *gid_sid_cache_head
;
998 /*****************************************************************
999 Find a SID given a uid.
1000 *****************************************************************/
1002 static BOOL
fetch_sid_from_uid_cache(DOM_SID
*psid
, uid_t uid
)
1004 struct uid_sid_cache
*pc
;
1006 for (pc
= uid_sid_cache_head
; pc
; pc
= pc
->next
) {
1007 if (pc
->uid
== uid
) {
1009 DEBUG(3,("fetch sid from uid cache %u -> %s\n",
1010 (unsigned int)uid
, sid_string_static(psid
)));
1011 DLIST_PROMOTE(uid_sid_cache_head
, pc
);
1018 /*****************************************************************
1019 Find a uid given a SID.
1020 *****************************************************************/
1022 static BOOL
fetch_uid_from_cache( uid_t
*puid
, const DOM_SID
*psid
)
1024 struct uid_sid_cache
*pc
;
1026 for (pc
= uid_sid_cache_head
; pc
; pc
= pc
->next
) {
1027 if (sid_compare(&pc
->sid
, psid
) == 0) {
1029 DEBUG(3,("fetch uid from cache %u -> %s\n",
1030 (unsigned int)*puid
, sid_string_static(psid
)));
1031 DLIST_PROMOTE(uid_sid_cache_head
, pc
);
1038 /*****************************************************************
1039 Store uid to SID mapping in cache.
1040 *****************************************************************/
1042 void store_uid_sid_cache(const DOM_SID
*psid
, uid_t uid
)
1044 struct uid_sid_cache
*pc
;
1046 /* do not store SIDs in the "Unix Group" domain */
1048 if ( sid_check_is_in_unix_users( psid
) )
1051 if (n_uid_sid_cache
>= MAX_UID_SID_CACHE_SIZE
&& n_uid_sid_cache
> TURNOVER_UID_SID_CACHE_SIZE
) {
1052 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
1053 struct uid_sid_cache
*pc_next
;
1056 for (i
= 0, pc
= uid_sid_cache_head
; i
< (n_uid_sid_cache
- TURNOVER_UID_SID_CACHE_SIZE
); i
++, pc
= pc
->next
)
1058 for(; pc
; pc
= pc_next
) {
1060 DLIST_REMOVE(uid_sid_cache_head
,pc
);
1066 pc
= SMB_MALLOC_P(struct uid_sid_cache
);
1070 sid_copy(&pc
->sid
, psid
);
1071 DLIST_ADD(uid_sid_cache_head
, pc
);
1075 /*****************************************************************
1076 Find a SID given a gid.
1077 *****************************************************************/
1079 static BOOL
fetch_sid_from_gid_cache(DOM_SID
*psid
, gid_t gid
)
1081 struct gid_sid_cache
*pc
;
1083 for (pc
= gid_sid_cache_head
; pc
; pc
= pc
->next
) {
1084 if (pc
->gid
== gid
) {
1086 DEBUG(3,("fetch sid from gid cache %u -> %s\n",
1087 (unsigned int)gid
, sid_string_static(psid
)));
1088 DLIST_PROMOTE(gid_sid_cache_head
, pc
);
1095 /*****************************************************************
1096 Find a gid given a SID.
1097 *****************************************************************/
1099 static BOOL
fetch_gid_from_cache(gid_t
*pgid
, const DOM_SID
*psid
)
1101 struct gid_sid_cache
*pc
;
1103 for (pc
= gid_sid_cache_head
; pc
; pc
= pc
->next
) {
1104 if (sid_compare(&pc
->sid
, psid
) == 0) {
1106 DEBUG(3,("fetch gid from cache %u -> %s\n",
1107 (unsigned int)*pgid
, sid_string_static(psid
)));
1108 DLIST_PROMOTE(gid_sid_cache_head
, pc
);
1115 /*****************************************************************
1116 Store gid to SID mapping in cache.
1117 *****************************************************************/
1119 void store_gid_sid_cache(const DOM_SID
*psid
, gid_t gid
)
1121 struct gid_sid_cache
*pc
;
1123 /* do not store SIDs in the "Unix Group" domain */
1125 if ( sid_check_is_in_unix_groups( psid
) )
1128 if (n_gid_sid_cache
>= MAX_GID_SID_CACHE_SIZE
&& n_gid_sid_cache
> TURNOVER_GID_SID_CACHE_SIZE
) {
1129 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
1130 struct gid_sid_cache
*pc_next
;
1133 for (i
= 0, pc
= gid_sid_cache_head
; i
< (n_gid_sid_cache
- TURNOVER_GID_SID_CACHE_SIZE
); i
++, pc
= pc
->next
)
1135 for(; pc
; pc
= pc_next
) {
1137 DLIST_REMOVE(gid_sid_cache_head
,pc
);
1143 pc
= SMB_MALLOC_P(struct gid_sid_cache
);
1147 sid_copy(&pc
->sid
, psid
);
1148 DLIST_ADD(gid_sid_cache_head
, pc
);
1150 DEBUG(3,("store_gid_sid_cache: gid %u in cache -> %s\n", (unsigned int)gid
,
1151 sid_string_static(psid
)));
1156 /*****************************************************************
1157 *THE LEGACY* convert uid_t to SID function.
1158 *****************************************************************/
1160 static void legacy_uid_to_sid(DOM_SID
*psid
, uid_t uid
)
1168 ret
= pdb_uid_to_rid(uid
, &rid
);
1172 /* This is a mapped user */
1173 sid_copy(psid
, get_global_sam_sid());
1174 sid_append_rid(psid
, rid
);
1178 /* This is an unmapped user */
1180 uid_to_unix_users_sid(uid
, psid
);
1183 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid
,
1184 sid_string_static(psid
)));
1186 store_uid_sid_cache(psid
, uid
);
1190 /*****************************************************************
1191 *THE LEGACY* convert gid_t to SID function.
1192 *****************************************************************/
1194 static void legacy_gid_to_sid(DOM_SID
*psid
, gid_t gid
)
1201 ret
= pdb_gid_to_sid(gid
, psid
);
1205 /* This is a mapped group */
1209 /* This is an unmapped group */
1211 gid_to_unix_groups_sid(gid
, psid
);
1214 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid
,
1215 sid_string_static(psid
)));
1217 store_gid_sid_cache(psid
, gid
);
1221 /*****************************************************************
1222 *THE LEGACY* convert SID to uid function.
1223 *****************************************************************/
1225 static BOOL
legacy_sid_to_uid(const DOM_SID
*psid
, uid_t
*puid
)
1227 enum lsa_SidType type
;
1230 if (sid_peek_check_rid(get_global_sam_sid(), psid
, &rid
)) {
1235 ret
= pdb_sid_to_id(psid
, &id
, &type
);
1239 if (type
!= SID_NAME_USER
) {
1240 DEBUG(5, ("sid %s is a %s, expected a user\n",
1241 sid_string_static(psid
),
1242 sid_type_lookup(type
)));
1249 /* This was ours, but it was not mapped. Fail */
1252 DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid
)));
1256 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_static(psid
),
1257 (unsigned int)*puid
));
1259 store_uid_sid_cache(psid
, *puid
);
1263 /*****************************************************************
1264 *THE LEGACY* convert SID to gid function.
1265 Group mapping is used for gids that maps to Wellknown SIDs
1266 *****************************************************************/
1268 static BOOL
legacy_sid_to_gid(const DOM_SID
*psid
, gid_t
*pgid
)
1273 enum lsa_SidType type
;
1275 if ((sid_check_is_in_builtin(psid
) ||
1276 sid_check_is_in_wellknown_domain(psid
))) {
1280 ret
= pdb_getgrsid(&map
, *psid
);
1287 DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid
)));
1291 if (sid_peek_check_rid(get_global_sam_sid(), psid
, &rid
)) {
1295 ret
= pdb_sid_to_id(psid
, &id
, &type
);
1299 if ((type
!= SID_NAME_DOM_GRP
) &&
1300 (type
!= SID_NAME_ALIAS
)) {
1301 DEBUG(5, ("LEGACY: sid %s is a %s, expected a group\n",
1302 sid_string_static(psid
),
1303 sid_type_lookup(type
)));
1310 /* This was ours, but it was not mapped. Fail */
1313 DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid
)));
1317 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_static(psid
),
1318 (unsigned int)*pgid
));
1320 store_gid_sid_cache(psid
, *pgid
);
1325 /*****************************************************************
1326 *THE CANONICAL* convert uid_t to SID function.
1327 *****************************************************************/
1329 void uid_to_sid(DOM_SID
*psid
, uid_t uid
)
1333 if (fetch_sid_from_uid_cache(psid
, uid
))
1336 if (!winbind_uid_to_sid(psid
, uid
)) {
1337 if (!winbind_ping()) {
1338 legacy_uid_to_sid(psid
, uid
);
1342 DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n",
1347 DEBUG(10,("uid %u -> sid %s\n",
1348 (unsigned int)uid
, sid_string_static(psid
)));
1350 store_uid_sid_cache(psid
, uid
);
1354 /*****************************************************************
1355 *THE CANONICAL* convert gid_t to SID function.
1356 *****************************************************************/
1358 void gid_to_sid(DOM_SID
*psid
, gid_t gid
)
1362 if (fetch_sid_from_gid_cache(psid
, gid
))
1365 if (!winbind_gid_to_sid(psid
, gid
)) {
1366 if (!winbind_ping()) {
1367 legacy_gid_to_sid(psid
, gid
);
1371 DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n",
1376 DEBUG(10,("gid %u -> sid %s\n",
1377 (unsigned int)gid
, sid_string_static(psid
)));
1379 store_gid_sid_cache(psid
, gid
);
1383 /*****************************************************************
1384 *THE CANONICAL* convert SID to uid function.
1385 *****************************************************************/
1387 BOOL
sid_to_uid(const DOM_SID
*psid
, uid_t
*puid
)
1392 if (fetch_uid_from_cache(puid
, psid
))
1395 if (fetch_gid_from_cache(&gid
, psid
)) {
1399 /* Optimize for the Unix Users Domain
1400 * as the conversion is straightforward */
1401 if (sid_peek_check_rid(&global_sid_Unix_Users
, psid
, &rid
)) {
1405 /* return here, don't cache */
1406 DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid
),
1407 (unsigned int)*puid
));
1411 if (!winbind_sid_to_uid(puid
, psid
)) {
1412 if (!winbind_ping()) {
1413 return legacy_sid_to_uid(psid
, puid
);
1416 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1417 sid_string_static(psid
)));
1421 /* TODO: Here would be the place to allocate both a gid and a uid for
1422 * the SID in question */
1424 DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid
),
1425 (unsigned int)*puid
));
1427 store_uid_sid_cache(psid
, *puid
);
1431 /*****************************************************************
1432 *THE CANONICAL* convert SID to gid function.
1433 Group mapping is used for gids that maps to Wellknown SIDs
1434 *****************************************************************/
1436 BOOL
sid_to_gid(const DOM_SID
*psid
, gid_t
*pgid
)
1441 if (fetch_gid_from_cache(pgid
, psid
))
1444 if (fetch_uid_from_cache(&uid
, psid
))
1447 /* Optimize for the Unix Groups Domain
1448 * as the conversion is straightforward */
1449 if (sid_peek_check_rid(&global_sid_Unix_Groups
, psid
, &rid
)) {
1453 /* return here, don't cache */
1454 DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid
),
1455 (unsigned int)*pgid
));
1459 /* Ask winbindd if it can map this sid to a gid.
1460 * (Idmap will check it is a valid SID and of the right type) */
1462 if ( !winbind_sid_to_gid(pgid
, psid
) ) {
1463 if (!winbind_ping()) {
1464 return legacy_sid_to_gid(psid
, pgid
);
1467 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1468 sid_string_static(psid
)));
1472 DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid
),
1473 (unsigned int)*pgid
));
1475 store_gid_sid_cache(psid
, *pgid
);