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 */
127 if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) {
128 type = SID_NAME_WKN_GRP;
133 /* 2. Builtin domain as such */
135 if (strequal(name, builtin_domain_name())) {
136 /* Swap domain and name */
137 tmp = name; name = domain; domain = tmp;
138 sid_copy(&sid, &global_sid_Builtin);
139 type = SID_NAME_DOMAIN;
143 /* 3. Account domain */
145 if (strequal(name, get_global_sam_name())) {
146 if (!secrets_fetch_domain_sid(name, &sid)) {
147 DEBUG(3, ("Could not fetch my SID\n"));
150 /* Swap domain and name */
151 tmp = name; name = domain; domain = tmp;
152 type = SID_NAME_DOMAIN;
156 /* 4. Primary domain */
158 if (!IS_DC && strequal(name, lp_workgroup())) {
159 if (!secrets_fetch_domain_sid(name, &sid)) {
160 DEBUG(3, ("Could not fetch the domain SID\n"));
163 /* Swap domain and name */
164 tmp = name; name = domain; domain = tmp;
165 type = SID_NAME_DOMAIN;
169 /* 5. Trusted domains as such, to me it looks as if members don't do
170 this, tested an XP workstation in a NT domain -- vl */
172 if (IS_DC && (secrets_fetch_trusted_domain_password(name, NULL,
174 /* Swap domain and name */
175 tmp = name; name = domain; domain = tmp;
176 type = SID_NAME_DOMAIN;
180 /* 6. Builtin aliases */
182 if (lookup_builtin_name(name, &rid)) {
183 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
184 sid_copy(&sid, &global_sid_Builtin);
185 sid_append_rid(&sid, rid);
186 type = SID_NAME_ALIAS;
190 /* 7. Local systems' SAM (DCs don't have a local SAM) */
191 /* 8. Primary SAM (On members, this is the domain) */
193 /* Both cases are done by looking at our passdb */
195 if (lookup_global_sam_name(name, flags, &rid, &type)) {
196 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
197 sid_copy(&sid, get_global_sam_sid());
198 sid_append_rid(&sid, rid);
202 /* Now our local possibilities are exhausted. */
204 if (!(flags & LOOKUP_NAME_REMOTE)) {
208 /* If we are not a DC, we have to ask in our primary domain. Let
209 * winbind do that. */
212 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
213 domain = talloc_strdup(tmp_ctx, lp_workgroup());
217 /* 9. Trusted domains */
219 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
220 * that (yet), but give it a chance. */
222 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
225 enum SID_NAME_USE domain_type;
227 if (type == SID_NAME_DOMAIN) {
228 /* Swap name and type */
229 tmp = name; name = domain; domain = tmp;
233 /* Here we have to cope with a little deficiency in the
234 * winbind API: We have to ask it again for the name of the
235 * domain it figured out itself. Maybe fix that later... */
237 sid_copy(&dom_sid, &sid);
238 sid_split_rid(&dom_sid, &tmp_rid);
240 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
242 (domain_type != SID_NAME_DOMAIN)) {
243 DEBUG(2, ("winbind could not find the domain's name "
244 "it just looked up for us\n"));
250 /* 10. Don't translate */
252 /* 11. Ok, windows would end here. Samba has two more options:
253 Unmapped users and unmapped groups */
255 if (lookup_unix_user_name(name, &sid)) {
256 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
257 type = SID_NAME_USER;
261 if (lookup_unix_group_name(name, &sid)) {
262 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
263 type = SID_NAME_DOM_GRP;
268 TALLOC_FREE(tmp_ctx);
272 if ((domain == NULL) || (name == NULL)) {
273 DEBUG(0, ("talloc failed\n"));
274 TALLOC_FREE(tmp_ctx);
278 if (ret_name != NULL) {
279 *ret_name = talloc_steal(mem_ctx, name);
282 if (ret_domain != NULL) {
283 char *tmp_dom = talloc_strdup(tmp_ctx, domain);
285 *ret_domain = talloc_steal(mem_ctx, tmp_dom);
288 if (ret_sid != NULL) {
289 sid_copy(ret_sid, &sid);
292 if (ret_type != NULL) {
296 TALLOC_FREE(tmp_ctx);
300 static BOOL winbind_lookup_rids(TALLOC_CTX *mem_ctx,
301 const DOM_SID *domain_sid,
302 int num_rids, uint32 *rids,
303 const char **domain_name,
304 const char **names, uint32 *types)
306 /* Unless the winbind interface is upgraded, fall back to ask for
307 * individual sids. I imagine introducing a lookuprids operation that
308 * directly proxies to lsa_lookupsids to the correct DC. -- vl */
311 for (i=0; i<num_rids; i++) {
314 sid_copy(&sid, domain_sid);
315 sid_append_rid(&sid, rids[i]);
317 if (winbind_lookup_sid(mem_ctx, &sid,
318 *domain_name == NULL ?
320 &names[i], &types[i])) {
321 if ((names[i] == NULL) || ((*domain_name) == NULL)) {
325 types[i] = SID_NAME_UNKNOWN;
331 static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
332 int num_rids, uint32_t *rids,
333 const char **domain_name,
334 const char ***names, enum SID_NAME_USE **types)
338 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
339 *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids);
341 if ((*names == NULL) || (*types == NULL)) {
345 if (sid_check_is_domain(domain_sid)) {
348 if (*domain_name == NULL) {
349 *domain_name = talloc_strdup(
350 mem_ctx, get_global_sam_name());
353 if (*domain_name == NULL) {
358 result = pdb_lookup_rids(domain_sid, num_rids, rids,
362 return (NT_STATUS_IS_OK(result) ||
363 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
364 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
367 if (sid_check_is_builtin(domain_sid)) {
369 if (*domain_name == NULL) {
370 *domain_name = talloc_strdup(
371 mem_ctx, builtin_domain_name());
374 if (*domain_name == NULL) {
378 for (i=0; i<num_rids; i++) {
379 if (lookup_builtin_rid(*names, rids[i],
381 if ((*names)[i] == NULL) {
384 (*types)[i] = SID_NAME_ALIAS;
386 (*types)[i] = SID_NAME_UNKNOWN;
392 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
393 for (i=0; i<num_rids; i++) {
395 sid_copy(&sid, domain_sid);
396 sid_append_rid(&sid, rids[i]);
397 if (lookup_wellknown_sid(mem_ctx, &sid,
398 domain_name, &(*names)[i])) {
399 if ((*names)[i] == NULL) {
402 (*types)[i] = SID_NAME_WKN_GRP;
404 (*types)[i] = SID_NAME_UNKNOWN;
410 if (sid_check_is_unix_users(domain_sid)) {
411 if (*domain_name == NULL) {
412 *domain_name = talloc_strdup(
413 mem_ctx, unix_users_domain_name());
415 for (i=0; i<num_rids; i++) {
416 (*names)[i] = talloc_strdup(
417 (*names), uidtoname(rids[i]));
418 (*types)[i] = SID_NAME_USER;
423 if (sid_check_is_unix_groups(domain_sid)) {
424 if (*domain_name == NULL) {
425 *domain_name = talloc_strdup(
426 mem_ctx, unix_groups_domain_name());
428 for (i=0; i<num_rids; i++) {
429 (*names)[i] = talloc_strdup(
430 (*names), gidtoname(rids[i]));
431 (*types)[i] = SID_NAME_DOM_GRP;
436 return winbind_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
437 domain_name, *names, *types);
441 * Is the SID a domain as such? If yes, lookup its name.
444 static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
448 enum SID_NAME_USE type;
450 if (sid_check_is_domain(sid)) {
451 *name = talloc_strdup(mem_ctx, get_global_sam_name());
455 if (sid_check_is_builtin(sid)) {
456 *name = talloc_strdup(mem_ctx, builtin_domain_name());
460 if (sid_check_is_wellknown_domain(sid, &tmp)) {
461 *name = talloc_strdup(mem_ctx, tmp);
465 if (sid->num_auths != 4) {
466 /* This can't be a domain */
471 uint32 i, num_domains;
472 struct trustdom_info **domains;
474 /* This is relatively expensive, but it happens only on DCs
475 * and for SIDs that have 4 sub-authorities and thus look like
478 if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx,
484 for (i=0; i<num_domains; i++) {
485 if (sid_equal(sid, &domains[i]->sid)) {
486 *name = talloc_strdup(mem_ctx,
494 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
495 (type == SID_NAME_DOMAIN)) {
504 * This tries to implement the rather weird rules for the lsa_lookup level
507 * This is as close as we can get to what W2k3 does. With this we survive the
508 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
509 * different, but I assume that's just being too liberal. For example, W2k3
510 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
511 * whereas NT4 does the same as level 1 (I think). I did not fully test that
512 * with NT4, this is what w2k3 does.
514 * Level 1: Ask everywhere
515 * Level 2: Ask domain and trusted domains, no builtin and wkn
516 * Level 3: Only ask domain
517 * Level 4: W2k3ad: Only ask AD trusts
518 * Level 5: Don't lookup anything
522 static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
531 ret = (!sid_check_is_builtin(sid) &&
532 !sid_check_is_wellknown_domain(sid, NULL));
537 ret = sid_check_is_domain(sid);
544 DEBUG(10, ("%s SID %s in level %d\n",
545 ret ? "Accepting" : "Rejecting",
546 sid_string_static(sid), level));
551 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
552 * references to domains, it is explicitly made for this.
554 * This attempts to be as efficient as possible: It collects all SIDs
555 * belonging to a domain and hands them in bulk to the appropriate lookup
556 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
557 * *hugely* from this. Winbind is going to be extended with a lookup_rids
558 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
562 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
563 const DOM_SID **sids, int level,
564 struct lsa_dom_info **ret_domains,
565 struct lsa_name_info **ret_names)
568 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
569 struct lsa_name_info *name_infos;
570 struct lsa_dom_info *dom_infos;
574 tmp_ctx = talloc_new(mem_ctx);
575 if (tmp_ctx == NULL) {
576 DEBUG(0, ("talloc_new failed\n"));
577 return NT_STATUS_NO_MEMORY;
580 name_infos = TALLOC_ARRAY(tmp_ctx, struct lsa_name_info, num_sids);
581 dom_infos = TALLOC_ZERO_ARRAY(tmp_ctx, struct lsa_dom_info,
583 if ((name_infos == NULL) || (dom_infos == NULL)) {
584 result = NT_STATUS_NO_MEMORY;
588 /* First build up the data structures:
590 * dom_infos is a list of domains referenced in the list of
591 * SIDs. Later we will walk the list of domains and look up the RIDs
594 * name_infos is a shadow-copy of the SIDs array to collect the real
597 * dom_info->idxs is an index into the name_infos array. The
598 * difficulty we have here is that we need to keep the SIDs the client
599 * asked for in the same order for the reply
602 for (i=0; i<num_sids; i++) {
605 const char *domain_name = NULL;
607 sid_copy(&sid, sids[i]);
608 name_infos[i].type = SID_NAME_USE_NONE;
610 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
611 /* We can't push that through the normal lookup
612 * process, as this would reference illegal
615 * For example S-1-5-32 would end up referencing
616 * domain S-1-5- with RID 32 which is clearly wrong.
618 if (domain_name == NULL) {
619 result = NT_STATUS_NO_MEMORY;
623 name_infos[i].rid = 0;
624 name_infos[i].type = SID_NAME_DOMAIN;
625 name_infos[i].name = NULL;
627 if (sid_check_is_builtin(&sid)) {
628 /* Yes, W2k3 returns "BUILTIN" both as domain
630 name_infos[i].name = talloc_strdup(
631 name_infos, builtin_domain_name());
632 if (name_infos[i].name == NULL) {
633 result = NT_STATUS_NO_MEMORY;
638 /* This is a normal SID with rid component */
639 if (!sid_split_rid(&sid, &rid)) {
640 result = NT_STATUS_INVALID_PARAMETER;
645 if (!check_dom_sid_to_level(&sid, level)) {
646 name_infos[i].rid = 0;
647 name_infos[i].type = SID_NAME_UNKNOWN;
648 name_infos[i].name = NULL;
652 for (j=0; j<MAX_REF_DOMAINS; j++) {
653 if (!dom_infos[j].valid) {
656 if (sid_equal(&sid, &dom_infos[j].sid)) {
661 if (j == MAX_REF_DOMAINS) {
662 /* TODO: What's the right error message here? */
663 result = NT_STATUS_NONE_MAPPED;
667 if (!dom_infos[j].valid) {
668 /* We found a domain not yet referenced, create a new
670 dom_infos[j].valid = True;
671 sid_copy(&dom_infos[j].sid, &sid);
673 if (domain_name != NULL) {
674 /* This name was being found above in the case
675 * when we found a domain SID */
677 talloc_steal(dom_infos, domain_name);
679 /* lookup_rids will take care of this */
680 dom_infos[j].name = NULL;
684 name_infos[i].dom_idx = j;
686 if (name_infos[i].type == SID_NAME_USE_NONE) {
687 name_infos[i].rid = rid;
689 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
690 &dom_infos[j].num_idxs);
692 if (dom_infos[j].idxs == NULL) {
693 result = NT_STATUS_NO_MEMORY;
699 /* Iterate over the domains found */
701 for (i=0; i<MAX_REF_DOMAINS; i++) {
704 enum SID_NAME_USE *types;
705 struct lsa_dom_info *dom = &dom_infos[i];
708 /* No domains left, we're done */
712 rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs);
715 result = NT_STATUS_NO_MEMORY;
719 for (j=0; j<dom->num_idxs; j++) {
720 rids[j] = name_infos[dom->idxs[j]].rid;
723 if (!lookup_rids(tmp_ctx, &dom->sid,
724 dom->num_idxs, rids, &dom->name,
726 result = NT_STATUS_NO_MEMORY;
730 talloc_steal(dom_infos, dom->name);
732 for (j=0; j<dom->num_idxs; j++) {
733 int idx = dom->idxs[j];
734 name_infos[idx].type = types[j];
735 if (types[j] != SID_NAME_UNKNOWN) {
736 name_infos[idx].name =
737 talloc_steal(name_infos, names[j]);
739 name_infos[idx].name = NULL;
744 *ret_domains = talloc_steal(mem_ctx, dom_infos);
745 *ret_names = talloc_steal(mem_ctx, name_infos);
746 result = NT_STATUS_OK;
749 TALLOC_FREE(tmp_ctx);
753 /*****************************************************************
754 *THE CANONICAL* convert SID to name function.
755 *****************************************************************/
757 BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
758 const char **ret_domain, const char **ret_name,
759 enum SID_NAME_USE *ret_type)
761 struct lsa_dom_info *domain;
762 struct lsa_name_info *name;
766 tmp_ctx = talloc_new(mem_ctx);
768 if (tmp_ctx == NULL) {
769 DEBUG(0, ("talloc_new failed\n"));
773 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
778 if (name->type == SID_NAME_UNKNOWN) {
782 if (ret_domain != NULL) {
783 *ret_domain = talloc_steal(mem_ctx, domain->name);
786 if (ret_name != NULL) {
787 *ret_name = talloc_steal(mem_ctx, name->name);
790 if (ret_type != NULL) {
791 *ret_type = name->type;
798 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
799 sid_string_static(sid), domain->name,
800 name->name, name->type));
802 DEBUG(10, ("failed to lookup sid %s\n",
803 sid_string_static(sid)));
805 TALLOC_FREE(tmp_ctx);
809 /*****************************************************************
810 Id mapping cache. This is to avoid Winbind mappings already
811 seen by smbd to be queried too frequently, keeping winbindd
812 busy, and blocking smbd while winbindd is busy with other
813 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
814 modified to use linked lists by jra.
815 *****************************************************************/
817 #define MAX_UID_SID_CACHE_SIZE 100
818 #define TURNOVER_UID_SID_CACHE_SIZE 10
819 #define MAX_GID_SID_CACHE_SIZE 100
820 #define TURNOVER_GID_SID_CACHE_SIZE 10
822 static size_t n_uid_sid_cache = 0;
823 static size_t n_gid_sid_cache = 0;
825 static struct uid_sid_cache {
826 struct uid_sid_cache *next, *prev;
829 enum SID_NAME_USE sidtype;
830 } *uid_sid_cache_head;
832 static struct gid_sid_cache {
833 struct gid_sid_cache *next, *prev;
836 enum SID_NAME_USE sidtype;
837 } *gid_sid_cache_head;
839 /*****************************************************************
840 Find a SID given a uid.
841 *****************************************************************/
843 static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
845 struct uid_sid_cache *pc;
847 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
848 if (pc->uid == uid) {
850 DEBUG(3,("fetch sid from uid cache %u -> %s\n",
851 (unsigned int)uid, sid_string_static(psid)));
852 DLIST_PROMOTE(uid_sid_cache_head, pc);
859 /*****************************************************************
860 Find a uid given a SID.
861 *****************************************************************/
863 static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
865 struct uid_sid_cache *pc;
867 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
868 if (sid_compare(&pc->sid, psid) == 0) {
870 DEBUG(3,("fetch uid from cache %u -> %s\n",
871 (unsigned int)*puid, sid_string_static(psid)));
872 DLIST_PROMOTE(uid_sid_cache_head, pc);
879 /*****************************************************************
880 Store uid to SID mapping in cache.
881 *****************************************************************/
883 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
885 struct uid_sid_cache *pc;
887 if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
888 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
889 struct uid_sid_cache *pc_next;
892 for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
894 for(; pc; pc = pc_next) {
896 DLIST_REMOVE(uid_sid_cache_head,pc);
902 pc = SMB_MALLOC_P(struct uid_sid_cache);
906 sid_copy(&pc->sid, psid);
907 DLIST_ADD(uid_sid_cache_head, pc);
911 /*****************************************************************
912 Find a SID given a gid.
913 *****************************************************************/
915 static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
917 struct gid_sid_cache *pc;
919 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
920 if (pc->gid == gid) {
922 DEBUG(3,("fetch sid from gid cache %u -> %s\n",
923 (unsigned int)gid, sid_string_static(psid)));
924 DLIST_PROMOTE(gid_sid_cache_head, pc);
931 /*****************************************************************
932 Find a gid given a SID.
933 *****************************************************************/
935 static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
937 struct gid_sid_cache *pc;
939 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
940 if (sid_compare(&pc->sid, psid) == 0) {
942 DEBUG(3,("fetch gid from cache %u -> %s\n",
943 (unsigned int)*pgid, sid_string_static(psid)));
944 DLIST_PROMOTE(gid_sid_cache_head, pc);
951 /*****************************************************************
952 Store gid to SID mapping in cache.
953 *****************************************************************/
955 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
957 struct gid_sid_cache *pc;
959 if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
960 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
961 struct gid_sid_cache *pc_next;
964 for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
966 for(; pc; pc = pc_next) {
968 DLIST_REMOVE(gid_sid_cache_head,pc);
974 pc = SMB_MALLOC_P(struct gid_sid_cache);
978 sid_copy(&pc->sid, psid);
979 DLIST_ADD(gid_sid_cache_head, pc);
983 /*****************************************************************
984 *THE CANONICAL* convert uid_t to SID function.
985 *****************************************************************/
987 void uid_to_sid(DOM_SID *psid, uid_t uid)
994 if (fetch_sid_from_uid_cache(psid, uid))
997 if (lp_idmap_uid(&low, &high) && (uid >= low) && (uid <= high) &&
998 winbind_uid_to_sid(psid, uid)) {
1000 DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
1001 (unsigned int)uid, sid_string_static(psid)));
1005 if (pdb_uid_to_rid(uid, &rid)) {
1006 /* This is a mapped user */
1007 sid_copy(psid, get_global_sam_sid());
1008 sid_append_rid(psid, rid);
1012 if (pdb_rid_algorithm() && (uid < max_algorithmic_uid())) {
1013 sid_copy(psid, get_global_sam_sid());
1014 sid_append_rid(psid, algorithmic_pdb_uid_to_user_rid(uid));
1017 sid_copy(psid, &global_sid_Unix_Users);
1018 sid_append_rid(psid, uid);
1023 DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid,
1024 sid_string_static(psid)));
1026 store_uid_sid_cache(psid, uid);
1030 /*****************************************************************
1031 *THE CANONICAL* convert gid_t to SID function.
1032 *****************************************************************/
1034 void gid_to_sid(DOM_SID *psid, gid_t gid)
1040 if (fetch_sid_from_gid_cache(psid, gid))
1043 if (lp_idmap_gid(&low, &high) && (gid >= low) && (gid <= high) &&
1044 winbind_gid_to_sid(psid, gid)) {
1046 DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
1047 (unsigned int)gid, sid_string_static(psid)));
1051 if (pdb_gid_to_sid(gid, psid)) {
1052 /* This is a mapped group */
1056 if (pdb_rid_algorithm() && (gid < max_algorithmic_gid())) {
1057 sid_copy(psid, get_global_sam_sid());
1058 sid_append_rid(psid, pdb_gid_to_group_rid(gid));
1061 sid_copy(psid, &global_sid_Unix_Groups);
1062 sid_append_rid(psid, gid);
1067 DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid,
1068 sid_string_static(psid)));
1070 store_gid_sid_cache(psid, gid);
1074 /*****************************************************************
1075 *THE CANONICAL* convert SID to uid function.
1076 *****************************************************************/
1078 BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
1080 enum SID_NAME_USE type;
1084 if (fetch_uid_from_cache(puid, psid))
1087 if (fetch_gid_from_cache(&gid, psid)) {
1091 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1097 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1100 if (pdb_sid_to_id(psid, &id, &type)) {
1101 if (type != SID_NAME_USER) {
1102 DEBUG(5, ("sid %s is a %s, expected a user\n",
1103 sid_string_static(psid),
1104 sid_type_lookup(type)));
1110 if (pdb_rid_algorithm() &&
1111 algorithmic_pdb_rid_is_user(rid)) {
1112 *puid = algorithmic_pdb_user_rid_to_uid(rid);
1116 /* This was ours, but it was neither mapped nor
1117 * algorithmic. Fail */
1121 if (winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
1123 if (type != SID_NAME_USER) {
1124 DEBUG(10, ("sid_to_uid: sid %s is a %s\n",
1125 sid_string_static(psid),
1126 sid_type_lookup(type)));
1130 if (!winbind_sid_to_uid(puid, psid)) {
1131 DEBUG(5, ("sid_to_uid: winbind failed to allocate a "
1132 "new uid for sid %s\n",
1133 sid_string_static(psid)));
1139 /* TODO: Here would be the place to allocate both a gid and a uid for
1140 * the SID in question */
1145 DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid),
1146 (unsigned int)*puid ));
1148 store_uid_sid_cache(psid, *puid);
1152 /*****************************************************************
1153 *THE CANONICAL* convert SID to gid function.
1154 Group mapping is used for gids that maps to Wellknown SIDs
1155 *****************************************************************/
1157 BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1162 enum SID_NAME_USE type;
1165 if (fetch_gid_from_cache(pgid, psid))
1168 if (fetch_uid_from_cache(&uid, psid))
1171 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1177 if (sid_check_is_in_builtin(psid) && pdb_getgrsid(&map, *psid)) {
1182 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1183 if (pdb_sid_to_id(psid, &id, &type)) {
1184 if ((type != SID_NAME_DOM_GRP) &&
1185 (type != SID_NAME_ALIAS)) {
1186 DEBUG(5, ("sid %s is a %s, expected a group\n",
1187 sid_string_static(psid),
1188 sid_type_lookup(type)));
1194 if (pdb_rid_algorithm() &&
1195 !algorithmic_pdb_rid_is_user(rid)) {
1196 /* This must be a group, presented as alias */
1197 *pgid = pdb_group_rid_to_gid(rid);
1200 /* This was ours, but it was neither mapped nor
1201 * algorithmic. Fail. */
1205 if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
1206 DEBUG(11,("sid_to_gid: no one knows the SID %s (tried local, "
1207 "then winbind)\n", sid_string_static(psid)));
1212 /* winbindd knows it; Ensure this is a group sid */
1214 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
1215 (type != SID_NAME_WKN_GRP)) {
1216 DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is "
1217 "a %s\n", sid_type_lookup(type)));
1221 /* winbindd knows it and it is a type of group; sid_to_gid must succeed
1222 or we are dead in the water */
1224 if ( !winbind_sid_to_gid(pgid, psid) ) {
1225 DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid "
1226 "for sid %s\n", sid_string_static(psid)));
1231 DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid),
1232 (unsigned int)*pgid ));
1234 store_gid_sid_cache(psid, *pgid);