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))) {
119 /* Now the guesswork begins, we haven't been given an explicit
120 * domain. Try the sequence as documented on
121 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
122 * November 27, 2005 */
124 /* 1. well-known names */
126 if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) {
127 type = SID_NAME_WKN_GRP;
131 /* 2. Builtin domain as such */
133 if (strequal(name, builtin_domain_name())) {
134 /* Swap domain and name */
135 tmp = name; name = domain; domain = tmp;
136 sid_copy(&sid, &global_sid_Builtin);
137 type = SID_NAME_DOMAIN;
141 /* 3. Account domain */
143 if (strequal(name, get_global_sam_name())) {
144 if (!secrets_fetch_domain_sid(name, &sid)) {
145 DEBUG(3, ("Could not fetch my SID\n"));
148 /* Swap domain and name */
149 tmp = name; name = domain; domain = tmp;
150 type = SID_NAME_DOMAIN;
154 /* 4. Primary domain */
156 if (!IS_DC && strequal(name, lp_workgroup())) {
157 if (!secrets_fetch_domain_sid(name, &sid)) {
158 DEBUG(3, ("Could not fetch the domain SID\n"));
161 /* Swap domain and name */
162 tmp = name; name = domain; domain = tmp;
163 type = SID_NAME_DOMAIN;
167 /* 5. Trusted domains as such, to me it looks as if members don't do
168 this, tested an XP workstation in a NT domain -- vl */
170 if (IS_DC && (secrets_fetch_trusted_domain_password(name, NULL,
172 /* Swap domain and name */
173 tmp = name; name = domain; domain = tmp;
174 type = SID_NAME_DOMAIN;
178 /* 6. Builtin aliases */
180 if (lookup_builtin_name(name, &rid)) {
181 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
182 sid_copy(&sid, &global_sid_Builtin);
183 sid_append_rid(&sid, rid);
184 type = SID_NAME_ALIAS;
188 /* 7. Local systems' SAM (DCs don't have a local SAM) */
189 /* 8. Primary SAM (On members, this is the domain) */
191 /* Both cases are done by looking at our passdb */
193 if (lookup_global_sam_name(name, flags, &rid, &type)) {
194 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
195 sid_copy(&sid, get_global_sam_sid());
196 sid_append_rid(&sid, rid);
200 /* Now our local possibilities are exhausted. */
202 if (!(flags & LOOKUP_NAME_REMOTE)) {
206 /* If we are not a DC, we have to ask in our primary domain. Let
207 * winbind do that. */
210 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
211 domain = talloc_strdup(tmp_ctx, lp_workgroup());
215 /* 9. Trusted domains */
217 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
218 * that (yet), but give it a chance. */
220 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
223 enum SID_NAME_USE domain_type;
225 if (type == SID_NAME_DOMAIN) {
226 /* Swap name and type */
227 tmp = name; name = domain; domain = tmp;
231 /* Here we have to cope with a little deficiency in the
232 * winbind API: We have to ask it again for the name of the
233 * domain it figured out itself. Maybe fix that later... */
235 sid_copy(&dom_sid, &sid);
236 sid_split_rid(&dom_sid, &tmp_rid);
238 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
240 (domain_type != SID_NAME_DOMAIN)) {
241 DEBUG(2, ("winbind could not find the domain's name "
242 "it just looked up for us\n"));
248 /* 10. Don't translate */
250 /* 11. Ok, windows would end here. Samba has two more options:
251 Unmapped users and unmapped groups */
253 if (lookup_unix_user_name(name, &sid)) {
254 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
255 type = SID_NAME_USER;
259 if (lookup_unix_group_name(name, &sid)) {
260 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
261 type = SID_NAME_DOM_GRP;
266 TALLOC_FREE(tmp_ctx);
270 if ((domain == NULL) || (name == NULL)) {
271 DEBUG(0, ("talloc failed\n"));
272 TALLOC_FREE(tmp_ctx);
276 if (ret_name != NULL) {
277 *ret_name = talloc_steal(mem_ctx, name);
280 if (ret_domain != NULL) {
281 char *tmp_dom = talloc_strdup(tmp_ctx, domain);
283 *ret_domain = talloc_steal(mem_ctx, tmp_dom);
286 if (ret_sid != NULL) {
287 sid_copy(ret_sid, &sid);
290 if (ret_type != NULL) {
294 TALLOC_FREE(tmp_ctx);
298 static BOOL winbind_lookup_rids(TALLOC_CTX *mem_ctx,
299 const DOM_SID *domain_sid,
300 int num_rids, uint32 *rids,
301 const char **domain_name,
302 const char **names, uint32 *types)
304 /* Unless the winbind interface is upgraded, fall back to ask for
305 * individual sids. I imagine introducing a lookuprids operation that
306 * directly proxies to lsa_lookupsids to the correct DC. -- vl */
309 for (i=0; i<num_rids; i++) {
312 sid_copy(&sid, domain_sid);
313 sid_append_rid(&sid, rids[i]);
315 if (winbind_lookup_sid(mem_ctx, &sid,
316 *domain_name == NULL ?
318 &names[i], &types[i])) {
319 if ((names[i] == NULL) || ((*domain_name) == NULL)) {
323 types[i] = SID_NAME_UNKNOWN;
329 static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
330 int num_rids, uint32_t *rids,
331 const char **domain_name,
332 const char ***names, enum SID_NAME_USE **types)
336 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
337 *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids);
339 if ((*names == NULL) || (*types == NULL)) {
343 if (sid_check_is_domain(domain_sid)) {
346 if (*domain_name == NULL) {
347 *domain_name = talloc_strdup(
348 mem_ctx, get_global_sam_name());
351 if (*domain_name == NULL) {
356 result = pdb_lookup_rids(domain_sid, num_rids, rids,
360 return (NT_STATUS_IS_OK(result) ||
361 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
362 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
365 if (sid_check_is_builtin(domain_sid)) {
367 if (*domain_name == NULL) {
368 *domain_name = talloc_strdup(
369 mem_ctx, builtin_domain_name());
372 if (*domain_name == NULL) {
376 for (i=0; i<num_rids; i++) {
377 if (lookup_builtin_rid(*names, rids[i],
379 if ((*names)[i] == NULL) {
382 (*types)[i] = SID_NAME_ALIAS;
384 (*types)[i] = SID_NAME_UNKNOWN;
390 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
391 for (i=0; i<num_rids; i++) {
393 sid_copy(&sid, domain_sid);
394 sid_append_rid(&sid, rids[i]);
395 if (lookup_wellknown_sid(mem_ctx, &sid,
396 domain_name, &(*names)[i])) {
397 if ((*names)[i] == NULL) {
400 (*types)[i] = SID_NAME_WKN_GRP;
402 (*types)[i] = SID_NAME_UNKNOWN;
408 if (sid_check_is_unix_users(domain_sid)) {
409 if (*domain_name == NULL) {
410 *domain_name = talloc_strdup(
411 mem_ctx, unix_users_domain_name());
413 for (i=0; i<num_rids; i++) {
414 (*names)[i] = talloc_strdup(
415 (*names), uidtoname(rids[i]));
416 (*types)[i] = SID_NAME_USER;
421 if (sid_check_is_unix_groups(domain_sid)) {
422 if (*domain_name == NULL) {
423 *domain_name = talloc_strdup(
424 mem_ctx, unix_groups_domain_name());
426 for (i=0; i<num_rids; i++) {
427 (*names)[i] = talloc_strdup(
428 (*names), gidtoname(rids[i]));
429 (*types)[i] = SID_NAME_DOM_GRP;
434 return winbind_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
435 domain_name, *names, *types);
439 * Is the SID a domain as such? If yes, lookup its name.
442 static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
446 enum SID_NAME_USE type;
448 if (sid_check_is_domain(sid)) {
449 *name = talloc_strdup(mem_ctx, get_global_sam_name());
453 if (sid_check_is_builtin(sid)) {
454 *name = talloc_strdup(mem_ctx, builtin_domain_name());
458 if (sid_check_is_wellknown_domain(sid, &tmp)) {
459 *name = talloc_strdup(mem_ctx, tmp);
463 if (sid->num_auths != 4) {
464 /* This can't be a domain */
469 uint32 i, num_domains;
470 struct trustdom_info **domains;
472 /* This is relatively expensive, but it happens only on DCs
473 * and for SIDs that have 4 sub-authorities and thus look like
476 if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx,
482 for (i=0; i<num_domains; i++) {
483 if (sid_equal(sid, &domains[i]->sid)) {
484 *name = talloc_strdup(mem_ctx,
492 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
493 (type == SID_NAME_DOMAIN)) {
502 * This tries to implement the rather weird rules for the lsa_lookup level
505 * This is as close as we can get to what W2k3 does. With this we survive the
506 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
507 * different, but I assume that's just being too liberal. For example, W2k3
508 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
509 * whereas NT4 does the same as level 1 (I think). I did not fully test that
510 * with NT4, this is what w2k3 does.
512 * Level 1: Ask everywhere
513 * Level 2: Ask domain and trusted domains, no builtin and wkn
514 * Level 3: Only ask domain
515 * Level 4: W2k3ad: Only ask AD trusts
516 * Level 5: Don't lookup anything
520 static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
529 ret = (!sid_check_is_builtin(sid) &&
530 !sid_check_is_wellknown_domain(sid, NULL));
535 ret = sid_check_is_domain(sid);
542 DEBUG(10, ("%s SID %s in level %d\n",
543 ret ? "Accepting" : "Rejecting",
544 sid_string_static(sid), level));
549 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
550 * references to domains, it is explicitly made for this.
552 * This attempts to be as efficient as possible: It collects all SIDs
553 * belonging to a domain and hands them in bulk to the appropriate lookup
554 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
555 * *hugely* from this. Winbind is going to be extended with a lookup_rids
556 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
560 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
561 const DOM_SID **sids, int level,
562 struct lsa_dom_info **ret_domains,
563 struct lsa_name_info **ret_names)
566 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
567 struct lsa_name_info *name_infos;
568 struct lsa_dom_info *dom_infos;
572 tmp_ctx = talloc_new(mem_ctx);
573 if (tmp_ctx == NULL) {
574 DEBUG(0, ("talloc_new failed\n"));
575 return NT_STATUS_NO_MEMORY;
578 name_infos = TALLOC_ARRAY(tmp_ctx, struct lsa_name_info, num_sids);
579 dom_infos = TALLOC_ZERO_ARRAY(tmp_ctx, struct lsa_dom_info,
581 if ((name_infos == NULL) || (dom_infos == NULL)) {
582 result = NT_STATUS_NO_MEMORY;
586 /* First build up the data structures:
588 * dom_infos is a list of domains referenced in the list of
589 * SIDs. Later we will walk the list of domains and look up the RIDs
592 * name_infos is a shadow-copy of the SIDs array to collect the real
595 * dom_info->idxs is an index into the name_infos array. The
596 * difficulty we have here is that we need to keep the SIDs the client
597 * asked for in the same order for the reply
600 for (i=0; i<num_sids; i++) {
603 const char *domain_name = NULL;
605 sid_copy(&sid, sids[i]);
606 name_infos[i].type = SID_NAME_USE_NONE;
608 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
609 /* We can't push that through the normal lookup
610 * process, as this would reference illegal
613 * For example S-1-5-32 would end up referencing
614 * domain S-1-5- with RID 32 which is clearly wrong.
616 if (domain_name == NULL) {
617 result = NT_STATUS_NO_MEMORY;
621 name_infos[i].rid = 0;
622 name_infos[i].type = SID_NAME_DOMAIN;
623 name_infos[i].name = NULL;
625 if (sid_check_is_builtin(&sid)) {
626 /* Yes, W2k3 returns "BUILTIN" both as domain
628 name_infos[i].name = talloc_strdup(
629 name_infos, builtin_domain_name());
630 if (name_infos[i].name == NULL) {
631 result = NT_STATUS_NO_MEMORY;
636 /* This is a normal SID with rid component */
637 if (!sid_split_rid(&sid, &rid)) {
638 result = NT_STATUS_INVALID_PARAMETER;
643 if (!check_dom_sid_to_level(&sid, level)) {
644 name_infos[i].rid = 0;
645 name_infos[i].type = SID_NAME_UNKNOWN;
646 name_infos[i].name = NULL;
650 for (j=0; j<MAX_REF_DOMAINS; j++) {
651 if (!dom_infos[j].valid) {
654 if (sid_equal(&sid, &dom_infos[j].sid)) {
659 if (j == MAX_REF_DOMAINS) {
660 /* TODO: What's the right error message here? */
661 result = NT_STATUS_NONE_MAPPED;
665 if (!dom_infos[j].valid) {
666 /* We found a domain not yet referenced, create a new
668 dom_infos[j].valid = True;
669 sid_copy(&dom_infos[j].sid, &sid);
671 if (domain_name != NULL) {
672 /* This name was being found above in the case
673 * when we found a domain SID */
675 talloc_steal(dom_infos, domain_name);
677 /* lookup_rids will take care of this */
678 dom_infos[j].name = NULL;
682 name_infos[i].dom_idx = j;
684 if (name_infos[i].type == SID_NAME_USE_NONE) {
685 name_infos[i].rid = rid;
687 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
688 &dom_infos[j].num_idxs);
690 if (dom_infos[j].idxs == NULL) {
691 result = NT_STATUS_NO_MEMORY;
697 /* Iterate over the domains found */
699 for (i=0; i<MAX_REF_DOMAINS; i++) {
702 enum SID_NAME_USE *types;
703 struct lsa_dom_info *dom = &dom_infos[i];
706 /* No domains left, we're done */
710 rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs);
713 result = NT_STATUS_NO_MEMORY;
717 for (j=0; j<dom->num_idxs; j++) {
718 rids[j] = name_infos[dom->idxs[j]].rid;
721 if (!lookup_rids(tmp_ctx, &dom->sid,
722 dom->num_idxs, rids, &dom->name,
724 result = NT_STATUS_NO_MEMORY;
728 talloc_steal(dom_infos, dom->name);
730 for (j=0; j<dom->num_idxs; j++) {
731 int idx = dom->idxs[j];
732 name_infos[idx].type = types[j];
733 if (types[j] != SID_NAME_UNKNOWN) {
734 name_infos[idx].name =
735 talloc_steal(name_infos, names[j]);
737 name_infos[idx].name = NULL;
742 *ret_domains = talloc_steal(mem_ctx, dom_infos);
743 *ret_names = talloc_steal(mem_ctx, name_infos);
744 result = NT_STATUS_OK;
747 TALLOC_FREE(tmp_ctx);
751 /*****************************************************************
752 *THE CANONICAL* convert SID to name function.
753 *****************************************************************/
755 BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
756 const char **ret_domain, const char **ret_name,
757 enum SID_NAME_USE *ret_type)
759 struct lsa_dom_info *domain;
760 struct lsa_name_info *name;
764 tmp_ctx = talloc_new(mem_ctx);
766 if (tmp_ctx == NULL) {
767 DEBUG(0, ("talloc_new failed\n"));
771 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
776 if (name->type == SID_NAME_UNKNOWN) {
780 if (ret_domain != NULL) {
781 *ret_domain = talloc_steal(mem_ctx, domain->name);
784 if (ret_name != NULL) {
785 *ret_name = talloc_steal(mem_ctx, name->name);
788 if (ret_type != NULL) {
789 *ret_type = name->type;
796 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
797 sid_string_static(sid), domain->name,
798 name->name, name->type));
800 DEBUG(10, ("failed to lookup sid %s\n",
801 sid_string_static(sid)));
803 TALLOC_FREE(tmp_ctx);
807 /*****************************************************************
808 Id mapping cache. This is to avoid Winbind mappings already
809 seen by smbd to be queried too frequently, keeping winbindd
810 busy, and blocking smbd while winbindd is busy with other
811 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
812 modified to use linked lists by jra.
813 *****************************************************************/
815 #define MAX_UID_SID_CACHE_SIZE 100
816 #define TURNOVER_UID_SID_CACHE_SIZE 10
817 #define MAX_GID_SID_CACHE_SIZE 100
818 #define TURNOVER_GID_SID_CACHE_SIZE 10
820 static size_t n_uid_sid_cache = 0;
821 static size_t n_gid_sid_cache = 0;
823 static struct uid_sid_cache {
824 struct uid_sid_cache *next, *prev;
827 enum SID_NAME_USE sidtype;
828 } *uid_sid_cache_head;
830 static struct gid_sid_cache {
831 struct gid_sid_cache *next, *prev;
834 enum SID_NAME_USE sidtype;
835 } *gid_sid_cache_head;
837 /*****************************************************************
838 Find a SID given a uid.
839 *****************************************************************/
841 static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
843 struct uid_sid_cache *pc;
845 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
846 if (pc->uid == uid) {
848 DEBUG(3,("fetch sid from uid cache %u -> %s\n",
849 (unsigned int)uid, sid_string_static(psid)));
850 DLIST_PROMOTE(uid_sid_cache_head, pc);
857 /*****************************************************************
858 Find a uid given a SID.
859 *****************************************************************/
861 static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
863 struct uid_sid_cache *pc;
865 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
866 if (sid_compare(&pc->sid, psid) == 0) {
868 DEBUG(3,("fetch uid from cache %u -> %s\n",
869 (unsigned int)*puid, sid_string_static(psid)));
870 DLIST_PROMOTE(uid_sid_cache_head, pc);
877 /*****************************************************************
878 Store uid to SID mapping in cache.
879 *****************************************************************/
881 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
883 struct uid_sid_cache *pc;
885 if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
886 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
887 struct uid_sid_cache *pc_next;
890 for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
892 for(; pc; pc = pc_next) {
894 DLIST_REMOVE(uid_sid_cache_head,pc);
900 pc = SMB_MALLOC_P(struct uid_sid_cache);
904 sid_copy(&pc->sid, psid);
905 DLIST_ADD(uid_sid_cache_head, pc);
909 /*****************************************************************
910 Find a SID given a gid.
911 *****************************************************************/
913 static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
915 struct gid_sid_cache *pc;
917 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
918 if (pc->gid == gid) {
920 DEBUG(3,("fetch sid from gid cache %u -> %s\n",
921 (unsigned int)gid, sid_string_static(psid)));
922 DLIST_PROMOTE(gid_sid_cache_head, pc);
929 /*****************************************************************
930 Find a gid given a SID.
931 *****************************************************************/
933 static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
935 struct gid_sid_cache *pc;
937 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
938 if (sid_compare(&pc->sid, psid) == 0) {
940 DEBUG(3,("fetch gid from cache %u -> %s\n",
941 (unsigned int)*pgid, sid_string_static(psid)));
942 DLIST_PROMOTE(gid_sid_cache_head, pc);
949 /*****************************************************************
950 Store gid to SID mapping in cache.
951 *****************************************************************/
953 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
955 struct gid_sid_cache *pc;
957 if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
958 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
959 struct gid_sid_cache *pc_next;
962 for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
964 for(; pc; pc = pc_next) {
966 DLIST_REMOVE(gid_sid_cache_head,pc);
972 pc = SMB_MALLOC_P(struct gid_sid_cache);
976 sid_copy(&pc->sid, psid);
977 DLIST_ADD(gid_sid_cache_head, pc);
981 /*****************************************************************
982 *THE CANONICAL* convert uid_t to SID function.
983 *****************************************************************/
985 void uid_to_sid(DOM_SID *psid, uid_t uid)
992 if (fetch_sid_from_uid_cache(psid, uid))
995 if (lp_idmap_uid(&low, &high) && (uid >= low) && (uid <= high) &&
996 winbind_uid_to_sid(psid, uid)) {
998 DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
999 (unsigned int)uid, sid_string_static(psid)));
1003 if (pdb_uid_to_rid(uid, &rid)) {
1004 /* This is a mapped user */
1005 sid_copy(psid, get_global_sam_sid());
1006 sid_append_rid(psid, rid);
1010 if (pdb_rid_algorithm() && (uid < max_algorithmic_uid())) {
1011 sid_copy(psid, get_global_sam_sid());
1012 sid_append_rid(psid, algorithmic_pdb_uid_to_user_rid(uid));
1015 sid_copy(psid, &global_sid_Unix_Users);
1016 sid_append_rid(psid, uid);
1021 DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid,
1022 sid_string_static(psid)));
1024 store_uid_sid_cache(psid, uid);
1028 /*****************************************************************
1029 *THE CANONICAL* convert gid_t to SID function.
1030 *****************************************************************/
1032 void gid_to_sid(DOM_SID *psid, gid_t gid)
1038 if (fetch_sid_from_gid_cache(psid, gid))
1041 if (lp_idmap_gid(&low, &high) && (gid >= low) && (gid <= high) &&
1042 winbind_gid_to_sid(psid, gid)) {
1044 DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
1045 (unsigned int)gid, sid_string_static(psid)));
1049 if (pdb_gid_to_sid(gid, psid)) {
1050 /* This is a mapped group */
1054 if (pdb_rid_algorithm() && (gid < max_algorithmic_gid())) {
1055 sid_copy(psid, get_global_sam_sid());
1056 sid_append_rid(psid, pdb_gid_to_group_rid(gid));
1059 sid_copy(psid, &global_sid_Unix_Groups);
1060 sid_append_rid(psid, gid);
1065 DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid,
1066 sid_string_static(psid)));
1068 store_gid_sid_cache(psid, gid);
1072 /*****************************************************************
1073 *THE CANONICAL* convert SID to uid function.
1074 *****************************************************************/
1076 BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
1078 enum SID_NAME_USE type;
1082 if (fetch_uid_from_cache(puid, psid))
1085 if (fetch_gid_from_cache(&gid, psid)) {
1089 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1095 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1098 if (pdb_sid_to_id(psid, &id, &type)) {
1099 if (type != SID_NAME_USER) {
1100 DEBUG(5, ("sid %s is a %s, expected a user\n",
1101 sid_string_static(psid),
1102 sid_type_lookup(type)));
1108 if (pdb_rid_algorithm() &&
1109 algorithmic_pdb_rid_is_user(rid)) {
1110 *puid = algorithmic_pdb_user_rid_to_uid(rid);
1114 /* This was ours, but it was neither mapped nor
1115 * algorithmic. Fail */
1119 if (winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
1121 if (type != SID_NAME_USER) {
1122 DEBUG(10, ("sid_to_uid: sid %s is a %s\n",
1123 sid_string_static(psid),
1124 sid_type_lookup(type)));
1128 if (!winbind_sid_to_uid(puid, psid)) {
1129 DEBUG(5, ("sid_to_uid: winbind failed to allocate a "
1130 "new uid for sid %s\n",
1131 sid_string_static(psid)));
1137 /* TODO: Here would be the place to allocate both a gid and a uid for
1138 * the SID in question */
1143 DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid),
1144 (unsigned int)*puid ));
1146 store_uid_sid_cache(psid, *puid);
1150 /*****************************************************************
1151 *THE CANONICAL* convert SID to gid function.
1152 Group mapping is used for gids that maps to Wellknown SIDs
1153 *****************************************************************/
1155 BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1160 enum SID_NAME_USE type;
1163 if (fetch_gid_from_cache(pgid, psid))
1166 if (fetch_uid_from_cache(&uid, psid))
1169 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1175 if (sid_check_is_in_builtin(psid) && pdb_getgrsid(&map, *psid)) {
1180 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1181 if (pdb_sid_to_id(psid, &id, &type)) {
1182 if ((type != SID_NAME_DOM_GRP) &&
1183 (type != SID_NAME_ALIAS)) {
1184 DEBUG(5, ("sid %s is a %s, expected a group\n",
1185 sid_string_static(psid),
1186 sid_type_lookup(type)));
1192 if (pdb_rid_algorithm() &&
1193 !algorithmic_pdb_rid_is_user(rid)) {
1194 /* This must be a group, presented as alias */
1195 *pgid = pdb_group_rid_to_gid(rid);
1198 /* This was ours, but it was neither mapped nor
1199 * algorithmic. Fail. */
1203 if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
1204 DEBUG(11,("sid_to_gid: no one knows the SID %s (tried local, "
1205 "then winbind)\n", sid_string_static(psid)));
1210 /* winbindd knows it; Ensure this is a group sid */
1212 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
1213 (type != SID_NAME_WKN_GRP)) {
1214 DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is "
1215 "a %s\n", sid_type_lookup(type)));
1219 /* winbindd knows it and it is a type of group; sid_to_gid must succeed
1220 or we are dead in the water */
1222 if ( !winbind_sid_to_gid(pgid, psid) ) {
1223 DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid "
1224 "for sid %s\n", sid_string_static(psid)));
1229 DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid),
1230 (unsigned int)*pgid ));
1232 store_gid_sid_cache(psid, *pgid);