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 if ((domain == NULL) || (name == NULL)) {
64 DEBUG(0, ("talloc failed\n"));
68 if (strequal(domain, get_global_sam_name())) {
70 /* It's our own domain, lookup the name in passdb */
71 if (lookup_global_sam_name(name, flags, &rid, &type)) {
72 sid_copy(&sid, get_global_sam_sid());
73 sid_append_rid(&sid, rid);
79 if (strequal(domain, builtin_domain_name())) {
81 /* Explicit request for a name in BUILTIN */
82 if (lookup_builtin_name(name, &rid)) {
83 sid_copy(&sid, &global_sid_Builtin);
84 sid_append_rid(&sid, rid);
85 type = SID_NAME_ALIAS;
91 /* Try the explicit winbind lookup first, don't let it guess the
92 * domain yet at this point yet. This comes later. */
94 if ((domain[0] != '\0') &&
95 (winbind_lookup_name(domain, name, &sid, &type))) {
99 if (strequal(domain, unix_users_domain_name())) {
100 if (lookup_unix_user_name(name, &sid)) {
101 type = SID_NAME_USER;
107 if (strequal(domain, unix_groups_domain_name())) {
108 if (lookup_unix_group_name(name, &sid)) {
109 type = SID_NAME_DOM_GRP;
115 if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
120 * Nasty hack necessary for too common scenarios:
122 * For 'valid users = +users' we know "users" is most probably not
123 * BUILTIN\users but the unix group users. This hack requires the
124 * admin to explicitly qualify BUILTIN if BUILTIN\users is meant.
126 * Please note that LOOKUP_NAME_GROUP can not be requested via for
127 * example lsa_lookupnames, it only comes into this routine via
128 * the expansion of group names coming in from smb.conf
131 if (flags & LOOKUP_NAME_GROUP) {
134 /* If we are using the smbpasswd backend, we need to use the
135 * algorithmic mapping for the unix group we find. This is
136 * necessary because when creating the NT token from the unix
137 * gid list we got from initgroups() we use gid_to_sid() that
138 * uses algorithmic mapping if pdb_rid_algorithm() is true. */
140 if (pdb_rid_algorithm() && ((grp = getgrnam(name)) != NULL) &&
141 (grp->gr_gid < max_algorithmic_gid())) {
142 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
143 sid_compose(&sid, get_global_sam_sid(),
144 pdb_gid_to_group_rid(grp->gr_gid));
145 type = SID_NAME_DOM_GRP;
149 if (lookup_unix_group_name(name, &sid)) {
150 domain = talloc_strdup(tmp_ctx,
151 unix_groups_domain_name());
152 type = SID_NAME_DOM_GRP;
157 /* Now the guesswork begins, we haven't been given an explicit
158 * domain. Try the sequence as documented on
159 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
160 * November 27, 2005 */
162 /* 1. well-known names */
164 if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) {
165 type = SID_NAME_WKN_GRP;
169 /* 2. Builtin domain as such */
171 if (strequal(name, builtin_domain_name())) {
172 /* Swap domain and name */
173 tmp = name; name = domain; domain = tmp;
174 sid_copy(&sid, &global_sid_Builtin);
175 type = SID_NAME_DOMAIN;
179 /* 3. Account domain */
181 if (strequal(name, get_global_sam_name())) {
182 if (!secrets_fetch_domain_sid(name, &sid)) {
183 DEBUG(3, ("Could not fetch my SID\n"));
186 /* Swap domain and name */
187 tmp = name; name = domain; domain = tmp;
188 type = SID_NAME_DOMAIN;
192 /* 4. Primary domain */
194 if (!IS_DC && strequal(name, lp_workgroup())) {
195 if (!secrets_fetch_domain_sid(name, &sid)) {
196 DEBUG(3, ("Could not fetch the domain SID\n"));
199 /* Swap domain and name */
200 tmp = name; name = domain; domain = tmp;
201 type = SID_NAME_DOMAIN;
205 /* 5. Trusted domains as such, to me it looks as if members don't do
206 this, tested an XP workstation in a NT domain -- vl */
208 if (IS_DC && (secrets_fetch_trusted_domain_password(name, NULL,
210 /* Swap domain and name */
211 tmp = name; name = domain; domain = tmp;
212 type = SID_NAME_DOMAIN;
216 /* 6. Builtin aliases */
218 if (lookup_builtin_name(name, &rid)) {
219 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
220 sid_copy(&sid, &global_sid_Builtin);
221 sid_append_rid(&sid, rid);
222 type = SID_NAME_ALIAS;
226 /* 7. Local systems' SAM (DCs don't have a local SAM) */
227 /* 8. Primary SAM (On members, this is the domain) */
229 /* Both cases are done by looking at our passdb */
231 if (lookup_global_sam_name(name, flags, &rid, &type)) {
232 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
233 sid_copy(&sid, get_global_sam_sid());
234 sid_append_rid(&sid, rid);
238 /* Now our local possibilities are exhausted. */
240 if (!(flags & LOOKUP_NAME_REMOTE)) {
244 /* If we are not a DC, we have to ask in our primary domain. Let
245 * winbind do that. */
248 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
249 domain = talloc_strdup(tmp_ctx, lp_workgroup());
253 /* 9. Trusted domains */
255 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
256 * that (yet), but give it a chance. */
258 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
261 enum SID_NAME_USE domain_type;
263 if (type == SID_NAME_DOMAIN) {
264 /* Swap name and type */
265 tmp = name; name = domain; domain = tmp;
269 /* Here we have to cope with a little deficiency in the
270 * winbind API: We have to ask it again for the name of the
271 * domain it figured out itself. Maybe fix that later... */
273 sid_copy(&dom_sid, &sid);
274 sid_split_rid(&dom_sid, &tmp_rid);
276 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
278 (domain_type != SID_NAME_DOMAIN)) {
279 DEBUG(2, ("winbind could not find the domain's name "
280 "it just looked up for us\n"));
286 /* 10. Don't translate */
288 /* 11. Ok, windows would end here. Samba has two more options:
289 Unmapped users and unmapped groups */
291 if (lookup_unix_user_name(name, &sid)) {
292 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
293 type = SID_NAME_USER;
297 if (lookup_unix_group_name(name, &sid)) {
298 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
299 type = SID_NAME_DOM_GRP;
304 TALLOC_FREE(tmp_ctx);
308 if ((domain == NULL) || (name == NULL)) {
309 DEBUG(0, ("talloc failed\n"));
310 TALLOC_FREE(tmp_ctx);
314 if (ret_name != NULL) {
315 *ret_name = talloc_steal(mem_ctx, name);
318 if (ret_domain != NULL) {
319 char *tmp_dom = talloc_strdup(tmp_ctx, domain);
321 *ret_domain = talloc_steal(mem_ctx, tmp_dom);
324 if (ret_sid != NULL) {
325 sid_copy(ret_sid, &sid);
328 if (ret_type != NULL) {
332 TALLOC_FREE(tmp_ctx);
336 static BOOL winbind_lookup_rids(TALLOC_CTX *mem_ctx,
337 const DOM_SID *domain_sid,
338 int num_rids, uint32 *rids,
339 const char **domain_name,
340 const char **names, uint32 *types)
342 /* Unless the winbind interface is upgraded, fall back to ask for
343 * individual sids. I imagine introducing a lookuprids operation that
344 * directly proxies to lsa_lookupsids to the correct DC. -- vl */
347 for (i=0; i<num_rids; i++) {
350 sid_copy(&sid, domain_sid);
351 sid_append_rid(&sid, rids[i]);
353 if (winbind_lookup_sid(mem_ctx, &sid,
354 *domain_name == NULL ?
356 &names[i], &types[i])) {
357 if ((names[i] == NULL) || ((*domain_name) == NULL)) {
361 types[i] = SID_NAME_UNKNOWN;
367 static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
368 int num_rids, uint32_t *rids,
369 const char **domain_name,
370 const char ***names, enum SID_NAME_USE **types)
374 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
375 *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids);
377 if ((*names == NULL) || (*types == NULL)) {
381 if (sid_check_is_domain(domain_sid)) {
384 if (*domain_name == NULL) {
385 *domain_name = talloc_strdup(
386 mem_ctx, get_global_sam_name());
389 if (*domain_name == NULL) {
394 result = pdb_lookup_rids(domain_sid, num_rids, rids,
398 return (NT_STATUS_IS_OK(result) ||
399 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
400 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
403 if (sid_check_is_builtin(domain_sid)) {
405 if (*domain_name == NULL) {
406 *domain_name = talloc_strdup(
407 mem_ctx, builtin_domain_name());
410 if (*domain_name == NULL) {
414 for (i=0; i<num_rids; i++) {
415 if (lookup_builtin_rid(*names, rids[i],
417 if ((*names)[i] == NULL) {
420 (*types)[i] = SID_NAME_ALIAS;
422 (*types)[i] = SID_NAME_UNKNOWN;
428 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
429 for (i=0; i<num_rids; i++) {
431 sid_copy(&sid, domain_sid);
432 sid_append_rid(&sid, rids[i]);
433 if (lookup_wellknown_sid(mem_ctx, &sid,
434 domain_name, &(*names)[i])) {
435 if ((*names)[i] == NULL) {
438 (*types)[i] = SID_NAME_WKN_GRP;
440 (*types)[i] = SID_NAME_UNKNOWN;
446 if (sid_check_is_unix_users(domain_sid)) {
447 if (*domain_name == NULL) {
448 *domain_name = talloc_strdup(
449 mem_ctx, unix_users_domain_name());
451 for (i=0; i<num_rids; i++) {
452 (*names)[i] = talloc_strdup(
453 (*names), uidtoname(rids[i]));
454 (*types)[i] = SID_NAME_USER;
459 if (sid_check_is_unix_groups(domain_sid)) {
460 if (*domain_name == NULL) {
461 *domain_name = talloc_strdup(
462 mem_ctx, unix_groups_domain_name());
464 for (i=0; i<num_rids; i++) {
465 (*names)[i] = talloc_strdup(
466 (*names), gidtoname(rids[i]));
467 (*types)[i] = SID_NAME_DOM_GRP;
472 return winbind_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
473 domain_name, *names, *types);
477 * Is the SID a domain as such? If yes, lookup its name.
480 static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
484 enum SID_NAME_USE type;
486 if (sid_check_is_domain(sid)) {
487 *name = talloc_strdup(mem_ctx, get_global_sam_name());
491 if (sid_check_is_builtin(sid)) {
492 *name = talloc_strdup(mem_ctx, builtin_domain_name());
496 if (sid_check_is_wellknown_domain(sid, &tmp)) {
497 *name = talloc_strdup(mem_ctx, tmp);
501 if (sid->num_auths != 4) {
502 /* This can't be a domain */
507 uint32 i, num_domains;
508 struct trustdom_info **domains;
510 /* This is relatively expensive, but it happens only on DCs
511 * and for SIDs that have 4 sub-authorities and thus look like
514 if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx,
520 for (i=0; i<num_domains; i++) {
521 if (sid_equal(sid, &domains[i]->sid)) {
522 *name = talloc_strdup(mem_ctx,
530 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
531 (type == SID_NAME_DOMAIN)) {
540 * This tries to implement the rather weird rules for the lsa_lookup level
543 * This is as close as we can get to what W2k3 does. With this we survive the
544 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
545 * different, but I assume that's just being too liberal. For example, W2k3
546 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
547 * whereas NT4 does the same as level 1 (I think). I did not fully test that
548 * with NT4, this is what w2k3 does.
550 * Level 1: Ask everywhere
551 * Level 2: Ask domain and trusted domains, no builtin and wkn
552 * Level 3: Only ask domain
553 * Level 4: W2k3ad: Only ask AD trusts
554 * Level 5: Don't lookup anything
558 static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
567 ret = (!sid_check_is_builtin(sid) &&
568 !sid_check_is_wellknown_domain(sid, NULL));
573 ret = sid_check_is_domain(sid);
580 DEBUG(10, ("%s SID %s in level %d\n",
581 ret ? "Accepting" : "Rejecting",
582 sid_string_static(sid), level));
587 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
588 * references to domains, it is explicitly made for this.
590 * This attempts to be as efficient as possible: It collects all SIDs
591 * belonging to a domain and hands them in bulk to the appropriate lookup
592 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
593 * *hugely* from this. Winbind is going to be extended with a lookup_rids
594 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
598 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
599 const DOM_SID **sids, int level,
600 struct lsa_dom_info **ret_domains,
601 struct lsa_name_info **ret_names)
604 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
605 struct lsa_name_info *name_infos;
606 struct lsa_dom_info *dom_infos;
610 tmp_ctx = talloc_new(mem_ctx);
611 if (tmp_ctx == NULL) {
612 DEBUG(0, ("talloc_new failed\n"));
613 return NT_STATUS_NO_MEMORY;
616 name_infos = TALLOC_ARRAY(tmp_ctx, struct lsa_name_info, num_sids);
617 dom_infos = TALLOC_ZERO_ARRAY(tmp_ctx, struct lsa_dom_info,
619 if ((name_infos == NULL) || (dom_infos == NULL)) {
620 result = NT_STATUS_NO_MEMORY;
624 /* First build up the data structures:
626 * dom_infos is a list of domains referenced in the list of
627 * SIDs. Later we will walk the list of domains and look up the RIDs
630 * name_infos is a shadow-copy of the SIDs array to collect the real
633 * dom_info->idxs is an index into the name_infos array. The
634 * difficulty we have here is that we need to keep the SIDs the client
635 * asked for in the same order for the reply
638 for (i=0; i<num_sids; i++) {
641 const char *domain_name = NULL;
643 sid_copy(&sid, sids[i]);
644 name_infos[i].type = SID_NAME_USE_NONE;
646 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
647 /* We can't push that through the normal lookup
648 * process, as this would reference illegal
651 * For example S-1-5-32 would end up referencing
652 * domain S-1-5- with RID 32 which is clearly wrong.
654 if (domain_name == NULL) {
655 result = NT_STATUS_NO_MEMORY;
659 name_infos[i].rid = 0;
660 name_infos[i].type = SID_NAME_DOMAIN;
661 name_infos[i].name = NULL;
663 if (sid_check_is_builtin(&sid)) {
664 /* Yes, W2k3 returns "BUILTIN" both as domain
666 name_infos[i].name = talloc_strdup(
667 name_infos, builtin_domain_name());
668 if (name_infos[i].name == NULL) {
669 result = NT_STATUS_NO_MEMORY;
674 /* This is a normal SID with rid component */
675 if (!sid_split_rid(&sid, &rid)) {
676 result = NT_STATUS_INVALID_PARAMETER;
681 if (!check_dom_sid_to_level(&sid, level)) {
682 name_infos[i].rid = 0;
683 name_infos[i].type = SID_NAME_UNKNOWN;
684 name_infos[i].name = NULL;
688 for (j=0; j<MAX_REF_DOMAINS; j++) {
689 if (!dom_infos[j].valid) {
692 if (sid_equal(&sid, &dom_infos[j].sid)) {
697 if (j == MAX_REF_DOMAINS) {
698 /* TODO: What's the right error message here? */
699 result = NT_STATUS_NONE_MAPPED;
703 if (!dom_infos[j].valid) {
704 /* We found a domain not yet referenced, create a new
706 dom_infos[j].valid = True;
707 sid_copy(&dom_infos[j].sid, &sid);
709 if (domain_name != NULL) {
710 /* This name was being found above in the case
711 * when we found a domain SID */
713 talloc_steal(dom_infos, domain_name);
715 /* lookup_rids will take care of this */
716 dom_infos[j].name = NULL;
720 name_infos[i].dom_idx = j;
722 if (name_infos[i].type == SID_NAME_USE_NONE) {
723 name_infos[i].rid = rid;
725 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
726 &dom_infos[j].num_idxs);
728 if (dom_infos[j].idxs == NULL) {
729 result = NT_STATUS_NO_MEMORY;
735 /* Iterate over the domains found */
737 for (i=0; i<MAX_REF_DOMAINS; i++) {
740 enum SID_NAME_USE *types;
741 struct lsa_dom_info *dom = &dom_infos[i];
744 /* No domains left, we're done */
748 rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs);
751 result = NT_STATUS_NO_MEMORY;
755 for (j=0; j<dom->num_idxs; j++) {
756 rids[j] = name_infos[dom->idxs[j]].rid;
759 if (!lookup_rids(tmp_ctx, &dom->sid,
760 dom->num_idxs, rids, &dom->name,
762 result = NT_STATUS_NO_MEMORY;
766 talloc_steal(dom_infos, dom->name);
768 for (j=0; j<dom->num_idxs; j++) {
769 int idx = dom->idxs[j];
770 name_infos[idx].type = types[j];
771 if (types[j] != SID_NAME_UNKNOWN) {
772 name_infos[idx].name =
773 talloc_steal(name_infos, names[j]);
775 name_infos[idx].name = NULL;
780 *ret_domains = talloc_steal(mem_ctx, dom_infos);
781 *ret_names = talloc_steal(mem_ctx, name_infos);
782 result = NT_STATUS_OK;
785 TALLOC_FREE(tmp_ctx);
789 /*****************************************************************
790 *THE CANONICAL* convert SID to name function.
791 *****************************************************************/
793 BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
794 const char **ret_domain, const char **ret_name,
795 enum SID_NAME_USE *ret_type)
797 struct lsa_dom_info *domain;
798 struct lsa_name_info *name;
802 tmp_ctx = talloc_new(mem_ctx);
804 if (tmp_ctx == NULL) {
805 DEBUG(0, ("talloc_new failed\n"));
809 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
814 if (name->type == SID_NAME_UNKNOWN) {
818 if (ret_domain != NULL) {
819 *ret_domain = talloc_steal(mem_ctx, domain->name);
822 if (ret_name != NULL) {
823 *ret_name = talloc_steal(mem_ctx, name->name);
826 if (ret_type != NULL) {
827 *ret_type = name->type;
834 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
835 sid_string_static(sid), domain->name,
836 name->name, name->type));
838 DEBUG(10, ("failed to lookup sid %s\n",
839 sid_string_static(sid)));
841 TALLOC_FREE(tmp_ctx);
845 /*****************************************************************
846 Id mapping cache. This is to avoid Winbind mappings already
847 seen by smbd to be queried too frequently, keeping winbindd
848 busy, and blocking smbd while winbindd is busy with other
849 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
850 modified to use linked lists by jra.
851 *****************************************************************/
853 #define MAX_UID_SID_CACHE_SIZE 100
854 #define TURNOVER_UID_SID_CACHE_SIZE 10
855 #define MAX_GID_SID_CACHE_SIZE 100
856 #define TURNOVER_GID_SID_CACHE_SIZE 10
858 static size_t n_uid_sid_cache = 0;
859 static size_t n_gid_sid_cache = 0;
861 static struct uid_sid_cache {
862 struct uid_sid_cache *next, *prev;
865 enum SID_NAME_USE sidtype;
866 } *uid_sid_cache_head;
868 static struct gid_sid_cache {
869 struct gid_sid_cache *next, *prev;
872 enum SID_NAME_USE sidtype;
873 } *gid_sid_cache_head;
875 /*****************************************************************
876 Find a SID given a uid.
877 *****************************************************************/
879 static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
881 struct uid_sid_cache *pc;
883 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
884 if (pc->uid == uid) {
886 DEBUG(3,("fetch sid from uid cache %u -> %s\n",
887 (unsigned int)uid, sid_string_static(psid)));
888 DLIST_PROMOTE(uid_sid_cache_head, pc);
895 /*****************************************************************
896 Find a uid given a SID.
897 *****************************************************************/
899 static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
901 struct uid_sid_cache *pc;
903 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
904 if (sid_compare(&pc->sid, psid) == 0) {
906 DEBUG(3,("fetch uid from cache %u -> %s\n",
907 (unsigned int)*puid, sid_string_static(psid)));
908 DLIST_PROMOTE(uid_sid_cache_head, pc);
915 /*****************************************************************
916 Store uid to SID mapping in cache.
917 *****************************************************************/
919 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
921 struct uid_sid_cache *pc;
923 if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
924 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
925 struct uid_sid_cache *pc_next;
928 for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
930 for(; pc; pc = pc_next) {
932 DLIST_REMOVE(uid_sid_cache_head,pc);
938 pc = SMB_MALLOC_P(struct uid_sid_cache);
942 sid_copy(&pc->sid, psid);
943 DLIST_ADD(uid_sid_cache_head, pc);
947 /*****************************************************************
948 Find a SID given a gid.
949 *****************************************************************/
951 static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
953 struct gid_sid_cache *pc;
955 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
956 if (pc->gid == gid) {
958 DEBUG(3,("fetch sid from gid cache %u -> %s\n",
959 (unsigned int)gid, sid_string_static(psid)));
960 DLIST_PROMOTE(gid_sid_cache_head, pc);
967 /*****************************************************************
968 Find a gid given a SID.
969 *****************************************************************/
971 static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
973 struct gid_sid_cache *pc;
975 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
976 if (sid_compare(&pc->sid, psid) == 0) {
978 DEBUG(3,("fetch gid from cache %u -> %s\n",
979 (unsigned int)*pgid, sid_string_static(psid)));
980 DLIST_PROMOTE(gid_sid_cache_head, pc);
987 /*****************************************************************
988 Store gid to SID mapping in cache.
989 *****************************************************************/
991 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
993 struct gid_sid_cache *pc;
995 if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
996 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
997 struct gid_sid_cache *pc_next;
1000 for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
1002 for(; pc; pc = pc_next) {
1004 DLIST_REMOVE(gid_sid_cache_head,pc);
1010 pc = SMB_MALLOC_P(struct gid_sid_cache);
1014 sid_copy(&pc->sid, psid);
1015 DLIST_ADD(gid_sid_cache_head, pc);
1017 DEBUG(3,("store_gid_sid_cache: gid %u in cache -> %s\n", (unsigned int)gid,
1018 sid_string_static(psid)));
1023 /*****************************************************************
1024 *THE CANONICAL* convert uid_t to SID function.
1025 *****************************************************************/
1027 void uid_to_sid(DOM_SID *psid, uid_t uid)
1034 if (fetch_sid_from_uid_cache(psid, uid))
1037 if (lp_idmap_uid(&low, &high) && (uid >= low) && (uid <= high) &&
1038 winbind_uid_to_sid(psid, uid)) {
1040 DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
1041 (unsigned int)uid, sid_string_static(psid)));
1045 if (pdb_uid_to_rid(uid, &rid)) {
1046 /* This is a mapped user */
1047 sid_copy(psid, get_global_sam_sid());
1048 sid_append_rid(psid, rid);
1052 if (pdb_rid_algorithm() && (uid < max_algorithmic_uid())) {
1053 sid_copy(psid, get_global_sam_sid());
1054 sid_append_rid(psid, algorithmic_pdb_uid_to_user_rid(uid));
1057 sid_copy(psid, &global_sid_Unix_Users);
1058 sid_append_rid(psid, uid);
1063 DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid,
1064 sid_string_static(psid)));
1066 store_uid_sid_cache(psid, uid);
1070 /*****************************************************************
1071 *THE CANONICAL* convert gid_t to SID function.
1072 *****************************************************************/
1074 void gid_to_sid(DOM_SID *psid, gid_t gid)
1080 if (fetch_sid_from_gid_cache(psid, gid))
1083 if (lp_idmap_gid(&low, &high) && (gid >= low) && (gid <= high) &&
1084 winbind_gid_to_sid(psid, gid)) {
1086 DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
1087 (unsigned int)gid, sid_string_static(psid)));
1091 if (pdb_gid_to_sid(gid, psid)) {
1092 /* This is a mapped group */
1096 if (pdb_rid_algorithm() && (gid < max_algorithmic_gid())) {
1097 sid_copy(psid, get_global_sam_sid());
1098 sid_append_rid(psid, pdb_gid_to_group_rid(gid));
1101 sid_copy(psid, &global_sid_Unix_Groups);
1102 sid_append_rid(psid, gid);
1107 DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid,
1108 sid_string_static(psid)));
1110 store_gid_sid_cache(psid, gid);
1114 /*****************************************************************
1115 *THE CANONICAL* convert SID to uid function.
1116 *****************************************************************/
1118 BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
1120 enum SID_NAME_USE type;
1124 if (fetch_uid_from_cache(puid, psid))
1127 if (fetch_gid_from_cache(&gid, psid)) {
1131 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1137 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1140 if (pdb_sid_to_id(psid, &id, &type)) {
1141 if (type != SID_NAME_USER) {
1142 DEBUG(5, ("sid %s is a %s, expected a user\n",
1143 sid_string_static(psid),
1144 sid_type_lookup(type)));
1150 if (pdb_rid_algorithm() &&
1151 algorithmic_pdb_rid_is_user(rid)) {
1152 *puid = algorithmic_pdb_user_rid_to_uid(rid);
1156 /* This was ours, but it was neither mapped nor
1157 * algorithmic. Fail */
1161 if (winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
1163 if (type != SID_NAME_USER) {
1164 DEBUG(10, ("sid_to_uid: sid %s is a %s\n",
1165 sid_string_static(psid),
1166 sid_type_lookup(type)));
1170 if (!winbind_sid_to_uid(puid, psid)) {
1171 DEBUG(5, ("sid_to_uid: winbind failed to allocate a "
1172 "new uid for sid %s\n",
1173 sid_string_static(psid)));
1179 /* TODO: Here would be the place to allocate both a gid and a uid for
1180 * the SID in question */
1185 DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid),
1186 (unsigned int)*puid ));
1188 store_uid_sid_cache(psid, *puid);
1192 /*****************************************************************
1193 *THE CANONICAL* convert SID to gid function.
1194 Group mapping is used for gids that maps to Wellknown SIDs
1195 *****************************************************************/
1197 BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1202 enum SID_NAME_USE type;
1205 if (fetch_gid_from_cache(pgid, psid))
1208 if (fetch_uid_from_cache(&uid, psid))
1211 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1217 if ((sid_check_is_in_builtin(psid) ||
1218 sid_check_is_in_wellknown_domain(psid))) {
1219 if (pdb_getgrsid(&map, *psid)) {
1226 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1227 if (pdb_sid_to_id(psid, &id, &type)) {
1228 if ((type != SID_NAME_DOM_GRP) &&
1229 (type != SID_NAME_ALIAS)) {
1230 DEBUG(5, ("sid %s is a %s, expected a group\n",
1231 sid_string_static(psid),
1232 sid_type_lookup(type)));
1238 if (pdb_rid_algorithm() &&
1239 !algorithmic_pdb_rid_is_user(rid)) {
1240 /* This must be a group, presented as alias */
1241 *pgid = pdb_group_rid_to_gid(rid);
1244 /* This was ours, but it was neither mapped nor
1245 * algorithmic. Fail. */
1249 if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
1250 DEBUG(11,("sid_to_gid: no one knows the SID %s (tried local, "
1251 "then winbind)\n", sid_string_static(psid)));
1256 /* winbindd knows it; Ensure this is a group sid */
1258 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
1259 (type != SID_NAME_WKN_GRP)) {
1260 DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is "
1261 "a %s\n", sid_type_lookup(type)));
1265 /* winbindd knows it and it is a type of group; sid_to_gid must succeed
1266 or we are dead in the water */
1268 if ( !winbind_sid_to_gid(pgid, psid) ) {
1269 DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid "
1270 "for sid %s\n", sid_string_static(psid)));
1275 DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid),
1276 (unsigned int)*pgid ));
1278 store_gid_sid_cache(psid, *pgid);