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"));
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 SID_NAME_USE 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 SID_NAME_USE *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 SID_NAME_USE *types)
399 const char **my_names;
400 enum SID_NAME_USE *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)) {
409 for (i=0; i<num_rids; i++) {
410 types[i] = SID_NAME_UNKNOWN;
416 * winbind_lookup_rids allocates its own array. We've been given the
417 * array, so copy it over
420 for (i=0; i<num_rids; i++) {
421 if (my_names[i] == NULL) {
422 TALLOC_FREE(tmp_ctx);
425 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
426 TALLOC_FREE(tmp_ctx);
429 types[i] = my_types[i];
431 TALLOC_FREE(tmp_ctx);
435 static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
436 int num_rids, uint32_t *rids,
437 const char **domain_name,
438 const char ***names, enum SID_NAME_USE **types)
442 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
443 *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids);
445 if ((*names == NULL) || (*types == NULL)) {
449 if (sid_check_is_domain(domain_sid)) {
452 if (*domain_name == NULL) {
453 *domain_name = talloc_strdup(
454 mem_ctx, get_global_sam_name());
457 if (*domain_name == NULL) {
462 result = pdb_lookup_rids(domain_sid, num_rids, rids,
466 return (NT_STATUS_IS_OK(result) ||
467 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
468 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
471 if (sid_check_is_builtin(domain_sid)) {
473 if (*domain_name == NULL) {
474 *domain_name = talloc_strdup(
475 mem_ctx, builtin_domain_name());
478 if (*domain_name == NULL) {
482 for (i=0; i<num_rids; i++) {
483 if (lookup_builtin_rid(*names, rids[i],
485 if ((*names)[i] == NULL) {
488 (*types)[i] = SID_NAME_ALIAS;
490 (*types)[i] = SID_NAME_UNKNOWN;
496 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
497 for (i=0; i<num_rids; i++) {
499 sid_copy(&sid, domain_sid);
500 sid_append_rid(&sid, rids[i]);
501 if (lookup_wellknown_sid(mem_ctx, &sid,
502 domain_name, &(*names)[i])) {
503 if ((*names)[i] == NULL) {
506 (*types)[i] = SID_NAME_WKN_GRP;
508 (*types)[i] = SID_NAME_UNKNOWN;
514 if (sid_check_is_unix_users(domain_sid)) {
515 if (*domain_name == NULL) {
516 *domain_name = talloc_strdup(
517 mem_ctx, unix_users_domain_name());
519 for (i=0; i<num_rids; i++) {
520 (*names)[i] = talloc_strdup(
521 (*names), uidtoname(rids[i]));
522 (*types)[i] = SID_NAME_USER;
527 if (sid_check_is_unix_groups(domain_sid)) {
528 if (*domain_name == NULL) {
529 *domain_name = talloc_strdup(
530 mem_ctx, unix_groups_domain_name());
532 for (i=0; i<num_rids; i++) {
533 (*names)[i] = talloc_strdup(
534 (*names), gidtoname(rids[i]));
535 (*types)[i] = SID_NAME_DOM_GRP;
540 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
541 domain_name, *names, *types);
545 * Is the SID a domain as such? If yes, lookup its name.
548 static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
552 enum SID_NAME_USE type;
554 if (sid_check_is_domain(sid)) {
555 *name = talloc_strdup(mem_ctx, get_global_sam_name());
559 if (sid_check_is_builtin(sid)) {
560 *name = talloc_strdup(mem_ctx, builtin_domain_name());
564 if (sid_check_is_wellknown_domain(sid, &tmp)) {
565 *name = talloc_strdup(mem_ctx, tmp);
569 if (sid->num_auths != 4) {
570 /* This can't be a domain */
575 uint32 i, num_domains;
576 struct trustdom_info **domains;
578 /* This is relatively expensive, but it happens only on DCs
579 * and for SIDs that have 4 sub-authorities and thus look like
582 if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx,
588 for (i=0; i<num_domains; i++) {
589 if (sid_equal(sid, &domains[i]->sid)) {
590 *name = talloc_strdup(mem_ctx,
598 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
599 (type == SID_NAME_DOMAIN)) {
608 * This tries to implement the rather weird rules for the lsa_lookup level
611 * This is as close as we can get to what W2k3 does. With this we survive the
612 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
613 * different, but I assume that's just being too liberal. For example, W2k3
614 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
615 * whereas NT4 does the same as level 1 (I think). I did not fully test that
616 * with NT4, this is what w2k3 does.
618 * Level 1: Ask everywhere
619 * Level 2: Ask domain and trusted domains, no builtin and wkn
620 * Level 3: Only ask domain
621 * Level 4: W2k3ad: Only ask AD trusts
622 * Level 5: Don't lookup anything
626 static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
635 ret = (!sid_check_is_builtin(sid) &&
636 !sid_check_is_wellknown_domain(sid, NULL));
641 ret = sid_check_is_domain(sid);
648 DEBUG(10, ("%s SID %s in level %d\n",
649 ret ? "Accepting" : "Rejecting",
650 sid_string_static(sid), level));
655 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
656 * references to domains, it is explicitly made for this.
658 * This attempts to be as efficient as possible: It collects all SIDs
659 * belonging to a domain and hands them in bulk to the appropriate lookup
660 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
661 * *hugely* from this. Winbind is going to be extended with a lookup_rids
662 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
666 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
667 const DOM_SID **sids, int level,
668 struct lsa_dom_info **ret_domains,
669 struct lsa_name_info **ret_names)
672 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
673 struct lsa_name_info *name_infos;
674 struct lsa_dom_info *dom_infos;
678 if (!(tmp_ctx = talloc_new(mem_ctx))) {
679 DEBUG(0, ("talloc_new failed\n"));
680 return NT_STATUS_NO_MEMORY;
683 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
684 dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
686 if ((name_infos == NULL) || (dom_infos == NULL)) {
687 result = NT_STATUS_NO_MEMORY;
691 /* First build up the data structures:
693 * dom_infos is a list of domains referenced in the list of
694 * SIDs. Later we will walk the list of domains and look up the RIDs
697 * name_infos is a shadow-copy of the SIDs array to collect the real
700 * dom_info->idxs is an index into the name_infos array. The
701 * difficulty we have here is that we need to keep the SIDs the client
702 * asked for in the same order for the reply
705 for (i=0; i<num_sids; i++) {
708 const char *domain_name = NULL;
710 sid_copy(&sid, sids[i]);
711 name_infos[i].type = SID_NAME_USE_NONE;
713 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
714 /* We can't push that through the normal lookup
715 * process, as this would reference illegal
718 * For example S-1-5-32 would end up referencing
719 * domain S-1-5- with RID 32 which is clearly wrong.
721 if (domain_name == NULL) {
722 result = NT_STATUS_NO_MEMORY;
726 name_infos[i].rid = 0;
727 name_infos[i].type = SID_NAME_DOMAIN;
728 name_infos[i].name = NULL;
730 if (sid_check_is_builtin(&sid)) {
731 /* Yes, W2k3 returns "BUILTIN" both as domain
733 name_infos[i].name = talloc_strdup(
734 name_infos, builtin_domain_name());
735 if (name_infos[i].name == NULL) {
736 result = NT_STATUS_NO_MEMORY;
741 /* This is a normal SID with rid component */
742 if (!sid_split_rid(&sid, &rid)) {
743 result = NT_STATUS_INVALID_PARAMETER;
748 if (!check_dom_sid_to_level(&sid, level)) {
749 name_infos[i].rid = 0;
750 name_infos[i].type = SID_NAME_UNKNOWN;
751 name_infos[i].name = NULL;
755 for (j=0; j<MAX_REF_DOMAINS; j++) {
756 if (!dom_infos[j].valid) {
759 if (sid_equal(&sid, &dom_infos[j].sid)) {
764 if (j == MAX_REF_DOMAINS) {
765 /* TODO: What's the right error message here? */
766 result = NT_STATUS_NONE_MAPPED;
770 if (!dom_infos[j].valid) {
771 /* We found a domain not yet referenced, create a new
773 dom_infos[j].valid = True;
774 sid_copy(&dom_infos[j].sid, &sid);
776 if (domain_name != NULL) {
777 /* This name was being found above in the case
778 * when we found a domain SID */
780 talloc_strdup(dom_infos, domain_name);
781 if (dom_infos[j].name == NULL) {
782 result = NT_STATUS_NO_MEMORY;
786 /* lookup_rids will take care of this */
787 dom_infos[j].name = NULL;
791 name_infos[i].dom_idx = j;
793 if (name_infos[i].type == SID_NAME_USE_NONE) {
794 name_infos[i].rid = rid;
796 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
797 &dom_infos[j].num_idxs);
799 if (dom_infos[j].idxs == NULL) {
800 result = NT_STATUS_NO_MEMORY;
806 /* Iterate over the domains found */
808 for (i=0; i<MAX_REF_DOMAINS; i++) {
810 const char *domain_name = NULL;
812 enum SID_NAME_USE *types;
813 struct lsa_dom_info *dom = &dom_infos[i];
816 /* No domains left, we're done */
820 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
821 result = NT_STATUS_NO_MEMORY;
825 for (j=0; j<dom->num_idxs; j++) {
826 rids[j] = name_infos[dom->idxs[j]].rid;
829 if (!lookup_rids(tmp_ctx, &dom->sid,
830 dom->num_idxs, rids, &domain_name,
832 result = NT_STATUS_NO_MEMORY;
836 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
837 result = NT_STATUS_NO_MEMORY;
841 for (j=0; j<dom->num_idxs; j++) {
842 int idx = dom->idxs[j];
843 name_infos[idx].type = types[j];
844 if (types[j] != SID_NAME_UNKNOWN) {
845 name_infos[idx].name =
846 talloc_strdup(name_infos, names[j]);
847 if (name_infos[idx].name == NULL) {
848 result = NT_STATUS_NO_MEMORY;
852 name_infos[idx].name = NULL;
857 *ret_domains = dom_infos;
858 *ret_names = name_infos;
862 TALLOC_FREE(dom_infos);
863 TALLOC_FREE(name_infos);
864 TALLOC_FREE(tmp_ctx);
868 /*****************************************************************
869 *THE CANONICAL* convert SID to name function.
870 *****************************************************************/
872 BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
873 const char **ret_domain, const char **ret_name,
874 enum SID_NAME_USE *ret_type)
876 struct lsa_dom_info *domain;
877 struct lsa_name_info *name;
881 if (!(tmp_ctx = talloc_new(mem_ctx))) {
882 DEBUG(0, ("talloc_new failed\n"));
886 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
891 if (name->type == SID_NAME_UNKNOWN) {
895 if ((ret_domain != NULL) &&
896 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
900 if ((ret_name != NULL) &&
901 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
905 if (ret_type != NULL) {
906 *ret_type = name->type;
913 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
914 sid_string_static(sid), domain->name,
915 name->name, name->type));
917 DEBUG(10, ("failed to lookup sid %s\n",
918 sid_string_static(sid)));
920 TALLOC_FREE(tmp_ctx);
924 /*****************************************************************
925 Id mapping cache. This is to avoid Winbind mappings already
926 seen by smbd to be queried too frequently, keeping winbindd
927 busy, and blocking smbd while winbindd is busy with other
928 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
929 modified to use linked lists by jra.
930 *****************************************************************/
932 #define MAX_UID_SID_CACHE_SIZE 100
933 #define TURNOVER_UID_SID_CACHE_SIZE 10
934 #define MAX_GID_SID_CACHE_SIZE 100
935 #define TURNOVER_GID_SID_CACHE_SIZE 10
937 static size_t n_uid_sid_cache = 0;
938 static size_t n_gid_sid_cache = 0;
940 static struct uid_sid_cache {
941 struct uid_sid_cache *next, *prev;
944 enum SID_NAME_USE sidtype;
945 } *uid_sid_cache_head;
947 static struct gid_sid_cache {
948 struct gid_sid_cache *next, *prev;
951 enum SID_NAME_USE sidtype;
952 } *gid_sid_cache_head;
954 /*****************************************************************
955 Find a SID given a uid.
956 *****************************************************************/
958 static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
960 struct uid_sid_cache *pc;
962 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
963 if (pc->uid == uid) {
965 DEBUG(3,("fetch sid from uid cache %u -> %s\n",
966 (unsigned int)uid, sid_string_static(psid)));
967 DLIST_PROMOTE(uid_sid_cache_head, pc);
974 /*****************************************************************
975 Find a uid given a SID.
976 *****************************************************************/
978 static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
980 struct uid_sid_cache *pc;
982 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
983 if (sid_compare(&pc->sid, psid) == 0) {
985 DEBUG(3,("fetch uid from cache %u -> %s\n",
986 (unsigned int)*puid, sid_string_static(psid)));
987 DLIST_PROMOTE(uid_sid_cache_head, pc);
994 /*****************************************************************
995 Store uid to SID mapping in cache.
996 *****************************************************************/
998 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
1000 struct uid_sid_cache *pc;
1002 if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
1003 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
1004 struct uid_sid_cache *pc_next;
1007 for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
1009 for(; pc; pc = pc_next) {
1011 DLIST_REMOVE(uid_sid_cache_head,pc);
1017 pc = SMB_MALLOC_P(struct uid_sid_cache);
1021 sid_copy(&pc->sid, psid);
1022 DLIST_ADD(uid_sid_cache_head, pc);
1026 /*****************************************************************
1027 Find a SID given a gid.
1028 *****************************************************************/
1030 static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1032 struct gid_sid_cache *pc;
1034 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
1035 if (pc->gid == gid) {
1037 DEBUG(3,("fetch sid from gid cache %u -> %s\n",
1038 (unsigned int)gid, sid_string_static(psid)));
1039 DLIST_PROMOTE(gid_sid_cache_head, pc);
1046 /*****************************************************************
1047 Find a gid given a SID.
1048 *****************************************************************/
1050 static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1052 struct gid_sid_cache *pc;
1054 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
1055 if (sid_compare(&pc->sid, psid) == 0) {
1057 DEBUG(3,("fetch gid from cache %u -> %s\n",
1058 (unsigned int)*pgid, sid_string_static(psid)));
1059 DLIST_PROMOTE(gid_sid_cache_head, pc);
1066 /*****************************************************************
1067 Store gid to SID mapping in cache.
1068 *****************************************************************/
1070 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1072 struct gid_sid_cache *pc;
1074 if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
1075 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
1076 struct gid_sid_cache *pc_next;
1079 for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
1081 for(; pc; pc = pc_next) {
1083 DLIST_REMOVE(gid_sid_cache_head,pc);
1089 pc = SMB_MALLOC_P(struct gid_sid_cache);
1093 sid_copy(&pc->sid, psid);
1094 DLIST_ADD(gid_sid_cache_head, pc);
1096 DEBUG(3,("store_gid_sid_cache: gid %u in cache -> %s\n", (unsigned int)gid,
1097 sid_string_static(psid)));
1102 /*****************************************************************
1103 *THE CANONICAL* convert uid_t to SID function.
1104 *****************************************************************/
1106 void uid_to_sid(DOM_SID *psid, uid_t uid)
1113 if (fetch_sid_from_uid_cache(psid, uid))
1116 if (lp_idmap_uid(&low, &high) && (uid >= low) && (uid <= high) &&
1117 winbind_uid_to_sid(psid, uid)) {
1119 DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
1120 (unsigned int)uid, sid_string_static(psid)));
1124 if (pdb_uid_to_rid(uid, &rid)) {
1125 /* This is a mapped user */
1126 sid_copy(psid, get_global_sam_sid());
1127 sid_append_rid(psid, rid);
1131 /* This is an unmapped user */
1133 uid_to_unix_users_sid(uid, psid);
1136 DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid,
1137 sid_string_static(psid)));
1139 store_uid_sid_cache(psid, uid);
1143 /*****************************************************************
1144 *THE CANONICAL* convert gid_t to SID function.
1145 *****************************************************************/
1147 void gid_to_sid(DOM_SID *psid, gid_t gid)
1153 if (fetch_sid_from_gid_cache(psid, gid))
1156 if (lp_idmap_gid(&low, &high) && (gid >= low) && (gid <= high) &&
1157 winbind_gid_to_sid(psid, gid)) {
1159 DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
1160 (unsigned int)gid, sid_string_static(psid)));
1164 if (pdb_gid_to_sid(gid, psid)) {
1165 /* This is a mapped group */
1169 /* This is an unmapped group */
1171 gid_to_unix_groups_sid(gid, psid);
1174 DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid,
1175 sid_string_static(psid)));
1177 store_gid_sid_cache(psid, gid);
1181 /*****************************************************************
1182 *THE CANONICAL* convert SID to uid function.
1183 *****************************************************************/
1185 BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
1187 enum SID_NAME_USE type;
1191 if (fetch_uid_from_cache(puid, psid))
1194 if (fetch_gid_from_cache(&gid, psid)) {
1198 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1204 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1207 if (pdb_sid_to_id(psid, &id, &type)) {
1208 if (type != SID_NAME_USER) {
1209 DEBUG(5, ("sid %s is a %s, expected a user\n",
1210 sid_string_static(psid),
1211 sid_type_lookup(type)));
1218 /* This was ours, but it was not mapped. Fail */
1223 if (winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
1225 if (type != SID_NAME_USER) {
1226 DEBUG(10, ("sid_to_uid: sid %s is a %s\n",
1227 sid_string_static(psid),
1228 sid_type_lookup(type)));
1232 if (!winbind_sid_to_uid(puid, psid)) {
1233 DEBUG(5, ("sid_to_uid: winbind failed to allocate a "
1234 "new uid for sid %s\n",
1235 sid_string_static(psid)));
1241 /* TODO: Here would be the place to allocate both a gid and a uid for
1242 * the SID in question */
1247 DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid),
1248 (unsigned int)*puid ));
1250 store_uid_sid_cache(psid, *puid);
1254 /*****************************************************************
1255 *THE CANONICAL* convert SID to gid function.
1256 Group mapping is used for gids that maps to Wellknown SIDs
1257 *****************************************************************/
1259 BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1264 enum SID_NAME_USE type;
1267 if (fetch_gid_from_cache(pgid, psid))
1270 if (fetch_uid_from_cache(&uid, psid))
1273 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1279 if ((sid_check_is_in_builtin(psid) ||
1280 sid_check_is_in_wellknown_domain(psid))) {
1281 if (pdb_getgrsid(&map, *psid)) {
1288 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1289 if (pdb_sid_to_id(psid, &id, &type)) {
1290 if ((type != SID_NAME_DOM_GRP) &&
1291 (type != SID_NAME_ALIAS)) {
1292 DEBUG(5, ("sid %s is a %s, expected a group\n",
1293 sid_string_static(psid),
1294 sid_type_lookup(type)));
1301 /* This was ours, but it was not mapped. Fail */
1306 if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
1307 DEBUG(11,("sid_to_gid: no one knows the SID %s (tried local, "
1308 "then winbind)\n", sid_string_static(psid)));
1313 /* winbindd knows it; Ensure this is a group sid */
1315 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
1316 (type != SID_NAME_WKN_GRP)) {
1317 DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is "
1318 "a %s\n", sid_type_lookup(type)));
1322 /* winbindd knows it and it is a type of group; sid_to_gid must succeed
1323 or we are dead in the water */
1325 if ( !winbind_sid_to_gid(pgid, psid) ) {
1326 DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid "
1327 "for sid %s\n", sid_string_static(psid)));
1332 DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid),
1333 (unsigned int)*pgid ));
1335 store_gid_sid_cache(psid, *pgid);