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);
48 if (tmp_ctx == NULL) {
49 DEBUG(0, ("talloc_new failed\n"));
53 p = strchr_m(full_name, '\\');
56 domain = talloc_strndup(tmp_ctx, full_name,
57 PTR_DIFF(p, full_name));
58 name = talloc_strdup(tmp_ctx, p+1);
60 domain = talloc_strdup(tmp_ctx, "");
61 name = talloc_strdup(tmp_ctx, full_name);
64 if ((domain == NULL) || (name == NULL)) {
65 DEBUG(0, ("talloc failed\n"));
70 if (strequal(domain, get_global_sam_name())) {
72 /* It's our own domain, lookup the name in passdb */
73 if (lookup_global_sam_name(name, flags, &rid, &type)) {
74 sid_copy(&sid, get_global_sam_sid());
75 sid_append_rid(&sid, rid);
82 if (strequal(domain, builtin_domain_name())) {
84 /* Explicit request for a name in BUILTIN */
85 if (lookup_builtin_name(name, &rid)) {
86 sid_copy(&sid, &global_sid_Builtin);
87 sid_append_rid(&sid, rid);
88 type = SID_NAME_ALIAS;
95 /* Try the explicit winbind lookup first, don't let it guess the
96 * domain yet at this point yet. This comes later. */
98 if ((domain[0] != '\0') &&
99 (winbind_lookup_name(domain, name, &sid, &type))) {
103 if (strequal(domain, unix_users_domain_name())) {
104 if (lookup_unix_user_name(name, &sid)) {
105 type = SID_NAME_USER;
108 TALLOC_FREE(tmp_ctx);
112 if (strequal(domain, unix_groups_domain_name())) {
113 if (lookup_unix_group_name(name, &sid)) {
114 type = SID_NAME_DOM_GRP;
117 TALLOC_FREE(tmp_ctx);
121 if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
122 TALLOC_FREE(tmp_ctx);
127 * Nasty hack necessary for too common scenarios:
129 * For 'valid users = +users' we know "users" is most probably not
130 * BUILTIN\users but the unix group users. This hack requires the
131 * admin to explicitly qualify BUILTIN if BUILTIN\users is meant.
133 * Please note that LOOKUP_NAME_GROUP can not be requested via for
134 * example lsa_lookupnames, it only comes into this routine via
135 * the expansion of group names coming in from smb.conf
138 if ((flags & LOOKUP_NAME_GROUP) && ((grp = getgrnam(name)) != NULL)) {
142 if (pdb_getgrgid(&map, grp->gr_gid)) {
143 /* The hack gets worse. Handle the case where we have
144 * 'force group = +unixgroup' but "unixgroup" has a
147 if (sid_check_is_in_builtin(&map.sid)) {
148 domain = talloc_strdup(
149 tmp_ctx, builtin_domain_name());
151 domain = talloc_strdup(
152 tmp_ctx, get_global_sam_name());
155 sid_copy(&sid, &map.sid);
156 type = map.sid_name_use;
160 /* If we are using the smbpasswd backend, we need to use the
161 * algorithmic mapping for the unix group we find. This is
162 * necessary because when creating the NT token from the unix
163 * gid list we got from initgroups() we use gid_to_sid() that
164 * uses algorithmic mapping if pdb_rid_algorithm() is true. */
166 if (pdb_rid_algorithm() &&
167 (grp->gr_gid < max_algorithmic_gid())) {
168 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
169 sid_compose(&sid, get_global_sam_sid(),
170 pdb_gid_to_group_rid(grp->gr_gid));
171 type = SID_NAME_DOM_GRP;
175 if (lookup_unix_group_name(name, &sid)) {
176 domain = talloc_strdup(tmp_ctx,
177 unix_groups_domain_name());
178 type = SID_NAME_DOM_GRP;
183 /* Now the guesswork begins, we haven't been given an explicit
184 * domain. Try the sequence as documented on
185 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
186 * November 27, 2005 */
188 /* 1. well-known names */
190 if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) {
191 type = SID_NAME_WKN_GRP;
195 /* 2. Builtin domain as such */
197 if (strequal(name, builtin_domain_name())) {
198 /* Swap domain and name */
199 tmp = name; name = domain; domain = tmp;
200 sid_copy(&sid, &global_sid_Builtin);
201 type = SID_NAME_DOMAIN;
205 /* 3. Account domain */
207 if (strequal(name, get_global_sam_name())) {
208 if (!secrets_fetch_domain_sid(name, &sid)) {
209 DEBUG(3, ("Could not fetch my SID\n"));
210 TALLOC_FREE(tmp_ctx);
213 /* Swap domain and name */
214 tmp = name; name = domain; domain = tmp;
215 type = SID_NAME_DOMAIN;
219 /* 4. Primary domain */
221 if (!IS_DC && strequal(name, lp_workgroup())) {
222 if (!secrets_fetch_domain_sid(name, &sid)) {
223 DEBUG(3, ("Could not fetch the domain SID\n"));
224 TALLOC_FREE(tmp_ctx);
227 /* Swap domain and name */
228 tmp = name; name = domain; domain = tmp;
229 type = SID_NAME_DOMAIN;
233 /* 5. Trusted domains as such, to me it looks as if members don't do
234 this, tested an XP workstation in a NT domain -- vl */
236 if (IS_DC && (secrets_fetch_trusted_domain_password(name, NULL,
238 /* Swap domain and name */
239 tmp = name; name = domain; domain = tmp;
240 type = SID_NAME_DOMAIN;
244 /* 6. Builtin aliases */
246 if (lookup_builtin_name(name, &rid)) {
247 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
248 sid_copy(&sid, &global_sid_Builtin);
249 sid_append_rid(&sid, rid);
250 type = SID_NAME_ALIAS;
254 /* 7. Local systems' SAM (DCs don't have a local SAM) */
255 /* 8. Primary SAM (On members, this is the domain) */
257 /* Both cases are done by looking at our passdb */
259 if (lookup_global_sam_name(name, flags, &rid, &type)) {
260 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
261 sid_copy(&sid, get_global_sam_sid());
262 sid_append_rid(&sid, rid);
266 /* Now our local possibilities are exhausted. */
268 if (!(flags & LOOKUP_NAME_REMOTE)) {
269 TALLOC_FREE(tmp_ctx);
273 /* If we are not a DC, we have to ask in our primary domain. Let
274 * winbind do that. */
277 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
278 domain = talloc_strdup(tmp_ctx, lp_workgroup());
282 /* 9. Trusted domains */
284 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
285 * that (yet), but give it a chance. */
287 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
290 enum SID_NAME_USE domain_type;
292 if (type == SID_NAME_DOMAIN) {
293 /* Swap name and type */
294 tmp = name; name = domain; domain = tmp;
298 /* Here we have to cope with a little deficiency in the
299 * winbind API: We have to ask it again for the name of the
300 * domain it figured out itself. Maybe fix that later... */
302 sid_copy(&dom_sid, &sid);
303 sid_split_rid(&dom_sid, &tmp_rid);
305 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
307 (domain_type != SID_NAME_DOMAIN)) {
308 DEBUG(2, ("winbind could not find the domain's name "
309 "it just looked up for us\n"));
310 TALLOC_FREE(tmp_ctx);
316 /* 10. Don't translate */
318 /* 11. Ok, windows would end here. Samba has two more options:
319 Unmapped users and unmapped groups */
321 if (lookup_unix_user_name(name, &sid)) {
322 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
323 type = SID_NAME_USER;
327 if (lookup_unix_group_name(name, &sid)) {
328 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
329 type = SID_NAME_DOM_GRP;
334 * Ok, all possibilities tried. Fail.
337 TALLOC_FREE(tmp_ctx);
341 if ((domain == NULL) || (name == NULL)) {
342 DEBUG(0, ("talloc failed\n"));
343 TALLOC_FREE(tmp_ctx);
348 * Hand over the results to the talloc context we've been given.
351 if ((ret_name != NULL) &&
352 !(*ret_name = talloc_strdup(mem_ctx, name))) {
353 DEBUG(0, ("talloc failed\n"));
354 TALLOC_FREE(tmp_ctx);
358 if (ret_domain != NULL) {
360 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
361 DEBUG(0, ("talloc failed\n"));
362 TALLOC_FREE(tmp_ctx);
366 *ret_domain = tmp_dom;
369 if (ret_sid != NULL) {
370 sid_copy(ret_sid, &sid);
373 if (ret_type != NULL) {
377 TALLOC_FREE(tmp_ctx);
381 static BOOL wb_lookup_rids(TALLOC_CTX *mem_ctx,
382 const DOM_SID *domain_sid,
383 int num_rids, uint32 *rids,
384 const char **domain_name,
385 const char **names, enum SID_NAME_USE *types)
388 const char **my_names;
389 enum SID_NAME_USE *my_types;
392 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
396 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
397 domain_name, &my_names, &my_types)) {
398 for (i=0; i<num_rids; i++) {
399 types[i] = SID_NAME_UNKNOWN;
405 * winbind_lookup_rids allocates its own array. We've been given the
406 * array, so copy it over
409 for (i=0; i<num_rids; i++) {
410 if (my_names[i] == NULL) {
411 TALLOC_FREE(tmp_ctx);
414 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
415 TALLOC_FREE(tmp_ctx);
418 types[i] = my_types[i];
420 TALLOC_FREE(tmp_ctx);
424 static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
425 int num_rids, uint32_t *rids,
426 const char **domain_name,
427 const char ***names, enum SID_NAME_USE **types)
431 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
432 *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids);
434 if ((*names == NULL) || (*types == NULL)) {
438 if (sid_check_is_domain(domain_sid)) {
441 if (*domain_name == NULL) {
442 *domain_name = talloc_strdup(
443 mem_ctx, get_global_sam_name());
446 if (*domain_name == NULL) {
451 result = pdb_lookup_rids(domain_sid, num_rids, rids,
455 return (NT_STATUS_IS_OK(result) ||
456 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
457 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
460 if (sid_check_is_builtin(domain_sid)) {
462 if (*domain_name == NULL) {
463 *domain_name = talloc_strdup(
464 mem_ctx, builtin_domain_name());
467 if (*domain_name == NULL) {
471 for (i=0; i<num_rids; i++) {
472 if (lookup_builtin_rid(*names, rids[i],
474 if ((*names)[i] == NULL) {
477 (*types)[i] = SID_NAME_ALIAS;
479 (*types)[i] = SID_NAME_UNKNOWN;
485 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
486 for (i=0; i<num_rids; i++) {
488 sid_copy(&sid, domain_sid);
489 sid_append_rid(&sid, rids[i]);
490 if (lookup_wellknown_sid(mem_ctx, &sid,
491 domain_name, &(*names)[i])) {
492 if ((*names)[i] == NULL) {
495 (*types)[i] = SID_NAME_WKN_GRP;
497 (*types)[i] = SID_NAME_UNKNOWN;
503 if (sid_check_is_unix_users(domain_sid)) {
504 if (*domain_name == NULL) {
505 *domain_name = talloc_strdup(
506 mem_ctx, unix_users_domain_name());
508 for (i=0; i<num_rids; i++) {
509 (*names)[i] = talloc_strdup(
510 (*names), uidtoname(rids[i]));
511 (*types)[i] = SID_NAME_USER;
516 if (sid_check_is_unix_groups(domain_sid)) {
517 if (*domain_name == NULL) {
518 *domain_name = talloc_strdup(
519 mem_ctx, unix_groups_domain_name());
521 for (i=0; i<num_rids; i++) {
522 (*names)[i] = talloc_strdup(
523 (*names), gidtoname(rids[i]));
524 (*types)[i] = SID_NAME_DOM_GRP;
529 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
530 domain_name, *names, *types);
534 * Is the SID a domain as such? If yes, lookup its name.
537 static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
541 enum SID_NAME_USE type;
543 if (sid_check_is_domain(sid)) {
544 *name = talloc_strdup(mem_ctx, get_global_sam_name());
548 if (sid_check_is_builtin(sid)) {
549 *name = talloc_strdup(mem_ctx, builtin_domain_name());
553 if (sid_check_is_wellknown_domain(sid, &tmp)) {
554 *name = talloc_strdup(mem_ctx, tmp);
558 if (sid->num_auths != 4) {
559 /* This can't be a domain */
564 uint32 i, num_domains;
565 struct trustdom_info **domains;
567 /* This is relatively expensive, but it happens only on DCs
568 * and for SIDs that have 4 sub-authorities and thus look like
571 if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx,
577 for (i=0; i<num_domains; i++) {
578 if (sid_equal(sid, &domains[i]->sid)) {
579 *name = talloc_strdup(mem_ctx,
587 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
588 (type == SID_NAME_DOMAIN)) {
597 * This tries to implement the rather weird rules for the lsa_lookup level
600 * This is as close as we can get to what W2k3 does. With this we survive the
601 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
602 * different, but I assume that's just being too liberal. For example, W2k3
603 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
604 * whereas NT4 does the same as level 1 (I think). I did not fully test that
605 * with NT4, this is what w2k3 does.
607 * Level 1: Ask everywhere
608 * Level 2: Ask domain and trusted domains, no builtin and wkn
609 * Level 3: Only ask domain
610 * Level 4: W2k3ad: Only ask AD trusts
611 * Level 5: Don't lookup anything
615 static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
624 ret = (!sid_check_is_builtin(sid) &&
625 !sid_check_is_wellknown_domain(sid, NULL));
630 ret = sid_check_is_domain(sid);
637 DEBUG(10, ("%s SID %s in level %d\n",
638 ret ? "Accepting" : "Rejecting",
639 sid_string_static(sid), level));
644 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
645 * references to domains, it is explicitly made for this.
647 * This attempts to be as efficient as possible: It collects all SIDs
648 * belonging to a domain and hands them in bulk to the appropriate lookup
649 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
650 * *hugely* from this. Winbind is going to be extended with a lookup_rids
651 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
655 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
656 const DOM_SID **sids, int level,
657 struct lsa_dom_info **ret_domains,
658 struct lsa_name_info **ret_names)
661 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
662 struct lsa_name_info *name_infos;
663 struct lsa_dom_info *dom_infos;
667 if (!(tmp_ctx = talloc_new(mem_ctx))) {
668 DEBUG(0, ("talloc_new failed\n"));
669 return NT_STATUS_NO_MEMORY;
672 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
673 dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
675 if ((name_infos == NULL) || (dom_infos == NULL)) {
676 result = NT_STATUS_NO_MEMORY;
680 /* First build up the data structures:
682 * dom_infos is a list of domains referenced in the list of
683 * SIDs. Later we will walk the list of domains and look up the RIDs
686 * name_infos is a shadow-copy of the SIDs array to collect the real
689 * dom_info->idxs is an index into the name_infos array. The
690 * difficulty we have here is that we need to keep the SIDs the client
691 * asked for in the same order for the reply
694 for (i=0; i<num_sids; i++) {
697 const char *domain_name = NULL;
699 sid_copy(&sid, sids[i]);
700 name_infos[i].type = SID_NAME_USE_NONE;
702 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
703 /* We can't push that through the normal lookup
704 * process, as this would reference illegal
707 * For example S-1-5-32 would end up referencing
708 * domain S-1-5- with RID 32 which is clearly wrong.
710 if (domain_name == NULL) {
711 result = NT_STATUS_NO_MEMORY;
715 name_infos[i].rid = 0;
716 name_infos[i].type = SID_NAME_DOMAIN;
717 name_infos[i].name = NULL;
719 if (sid_check_is_builtin(&sid)) {
720 /* Yes, W2k3 returns "BUILTIN" both as domain
722 name_infos[i].name = talloc_strdup(
723 name_infos, builtin_domain_name());
724 if (name_infos[i].name == NULL) {
725 result = NT_STATUS_NO_MEMORY;
730 /* This is a normal SID with rid component */
731 if (!sid_split_rid(&sid, &rid)) {
732 result = NT_STATUS_INVALID_PARAMETER;
737 if (!check_dom_sid_to_level(&sid, level)) {
738 name_infos[i].rid = 0;
739 name_infos[i].type = SID_NAME_UNKNOWN;
740 name_infos[i].name = NULL;
744 for (j=0; j<MAX_REF_DOMAINS; j++) {
745 if (!dom_infos[j].valid) {
748 if (sid_equal(&sid, &dom_infos[j].sid)) {
753 if (j == MAX_REF_DOMAINS) {
754 /* TODO: What's the right error message here? */
755 result = NT_STATUS_NONE_MAPPED;
759 if (!dom_infos[j].valid) {
760 /* We found a domain not yet referenced, create a new
762 dom_infos[j].valid = True;
763 sid_copy(&dom_infos[j].sid, &sid);
765 if (domain_name != NULL) {
766 /* This name was being found above in the case
767 * when we found a domain SID */
769 talloc_strdup(dom_infos, domain_name);
770 if (dom_infos[j].name == NULL) {
771 result = NT_STATUS_NO_MEMORY;
775 /* lookup_rids will take care of this */
776 dom_infos[j].name = NULL;
780 name_infos[i].dom_idx = j;
782 if (name_infos[i].type == SID_NAME_USE_NONE) {
783 name_infos[i].rid = rid;
785 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
786 &dom_infos[j].num_idxs);
788 if (dom_infos[j].idxs == NULL) {
789 result = NT_STATUS_NO_MEMORY;
795 /* Iterate over the domains found */
797 for (i=0; i<MAX_REF_DOMAINS; i++) {
799 const char *domain_name = NULL;
801 enum SID_NAME_USE *types;
802 struct lsa_dom_info *dom = &dom_infos[i];
805 /* No domains left, we're done */
809 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
810 result = NT_STATUS_NO_MEMORY;
814 for (j=0; j<dom->num_idxs; j++) {
815 rids[j] = name_infos[dom->idxs[j]].rid;
818 if (!lookup_rids(tmp_ctx, &dom->sid,
819 dom->num_idxs, rids, &domain_name,
821 result = NT_STATUS_NO_MEMORY;
825 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
826 result = NT_STATUS_NO_MEMORY;
830 for (j=0; j<dom->num_idxs; j++) {
831 int idx = dom->idxs[j];
832 name_infos[idx].type = types[j];
833 if (types[j] != SID_NAME_UNKNOWN) {
834 name_infos[idx].name =
835 talloc_strdup(name_infos, names[j]);
836 if (name_infos[idx].name == NULL) {
837 result = NT_STATUS_NO_MEMORY;
841 name_infos[idx].name = NULL;
846 *ret_domains = dom_infos;
847 *ret_names = name_infos;
851 TALLOC_FREE(dom_infos);
852 TALLOC_FREE(name_infos);
853 TALLOC_FREE(tmp_ctx);
857 /*****************************************************************
858 *THE CANONICAL* convert SID to name function.
859 *****************************************************************/
861 BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
862 const char **ret_domain, const char **ret_name,
863 enum SID_NAME_USE *ret_type)
865 struct lsa_dom_info *domain;
866 struct lsa_name_info *name;
870 if (!(tmp_ctx = talloc_new(mem_ctx))) {
871 DEBUG(0, ("talloc_new failed\n"));
875 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
880 if (name->type == SID_NAME_UNKNOWN) {
884 if ((ret_domain != NULL) &&
885 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
889 if ((ret_name != NULL) &&
890 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
894 if (ret_type != NULL) {
895 *ret_type = name->type;
902 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
903 sid_string_static(sid), domain->name,
904 name->name, name->type));
906 DEBUG(10, ("failed to lookup sid %s\n",
907 sid_string_static(sid)));
909 TALLOC_FREE(tmp_ctx);
913 /*****************************************************************
914 Id mapping cache. This is to avoid Winbind mappings already
915 seen by smbd to be queried too frequently, keeping winbindd
916 busy, and blocking smbd while winbindd is busy with other
917 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
918 modified to use linked lists by jra.
919 *****************************************************************/
921 #define MAX_UID_SID_CACHE_SIZE 100
922 #define TURNOVER_UID_SID_CACHE_SIZE 10
923 #define MAX_GID_SID_CACHE_SIZE 100
924 #define TURNOVER_GID_SID_CACHE_SIZE 10
926 static size_t n_uid_sid_cache = 0;
927 static size_t n_gid_sid_cache = 0;
929 static struct uid_sid_cache {
930 struct uid_sid_cache *next, *prev;
933 enum SID_NAME_USE sidtype;
934 } *uid_sid_cache_head;
936 static struct gid_sid_cache {
937 struct gid_sid_cache *next, *prev;
940 enum SID_NAME_USE sidtype;
941 } *gid_sid_cache_head;
943 /*****************************************************************
944 Find a SID given a uid.
945 *****************************************************************/
947 static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
949 struct uid_sid_cache *pc;
951 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
952 if (pc->uid == uid) {
954 DEBUG(3,("fetch sid from uid cache %u -> %s\n",
955 (unsigned int)uid, sid_string_static(psid)));
956 DLIST_PROMOTE(uid_sid_cache_head, pc);
963 /*****************************************************************
964 Find a uid given a SID.
965 *****************************************************************/
967 static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
969 struct uid_sid_cache *pc;
971 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
972 if (sid_compare(&pc->sid, psid) == 0) {
974 DEBUG(3,("fetch uid from cache %u -> %s\n",
975 (unsigned int)*puid, sid_string_static(psid)));
976 DLIST_PROMOTE(uid_sid_cache_head, pc);
983 /*****************************************************************
984 Store uid to SID mapping in cache.
985 *****************************************************************/
987 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
989 struct uid_sid_cache *pc;
991 if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
992 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
993 struct uid_sid_cache *pc_next;
996 for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
998 for(; pc; pc = pc_next) {
1000 DLIST_REMOVE(uid_sid_cache_head,pc);
1006 pc = SMB_MALLOC_P(struct uid_sid_cache);
1010 sid_copy(&pc->sid, psid);
1011 DLIST_ADD(uid_sid_cache_head, pc);
1015 /*****************************************************************
1016 Find a SID given a gid.
1017 *****************************************************************/
1019 static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1021 struct gid_sid_cache *pc;
1023 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
1024 if (pc->gid == gid) {
1026 DEBUG(3,("fetch sid from gid cache %u -> %s\n",
1027 (unsigned int)gid, sid_string_static(psid)));
1028 DLIST_PROMOTE(gid_sid_cache_head, pc);
1035 /*****************************************************************
1036 Find a gid given a SID.
1037 *****************************************************************/
1039 static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1041 struct gid_sid_cache *pc;
1043 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
1044 if (sid_compare(&pc->sid, psid) == 0) {
1046 DEBUG(3,("fetch gid from cache %u -> %s\n",
1047 (unsigned int)*pgid, sid_string_static(psid)));
1048 DLIST_PROMOTE(gid_sid_cache_head, pc);
1055 /*****************************************************************
1056 Store gid to SID mapping in cache.
1057 *****************************************************************/
1059 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1061 struct gid_sid_cache *pc;
1063 if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
1064 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
1065 struct gid_sid_cache *pc_next;
1068 for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
1070 for(; pc; pc = pc_next) {
1072 DLIST_REMOVE(gid_sid_cache_head,pc);
1078 pc = SMB_MALLOC_P(struct gid_sid_cache);
1082 sid_copy(&pc->sid, psid);
1083 DLIST_ADD(gid_sid_cache_head, pc);
1085 DEBUG(3,("store_gid_sid_cache: gid %u in cache -> %s\n", (unsigned int)gid,
1086 sid_string_static(psid)));
1091 /*****************************************************************
1092 *THE CANONICAL* convert uid_t to SID function.
1093 *****************************************************************/
1095 void uid_to_sid(DOM_SID *psid, uid_t uid)
1102 if (fetch_sid_from_uid_cache(psid, uid))
1105 if (lp_idmap_uid(&low, &high) && (uid >= low) && (uid <= high) &&
1106 winbind_uid_to_sid(psid, uid)) {
1108 DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
1109 (unsigned int)uid, sid_string_static(psid)));
1113 if (pdb_uid_to_rid(uid, &rid)) {
1114 /* This is a mapped user */
1115 sid_copy(psid, get_global_sam_sid());
1116 sid_append_rid(psid, rid);
1120 if (pdb_rid_algorithm() && (uid < max_algorithmic_uid())) {
1121 sid_copy(psid, get_global_sam_sid());
1122 sid_append_rid(psid, algorithmic_pdb_uid_to_user_rid(uid));
1125 uid_to_unix_users_sid(uid, psid);
1130 DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid,
1131 sid_string_static(psid)));
1133 store_uid_sid_cache(psid, uid);
1137 /*****************************************************************
1138 *THE CANONICAL* convert gid_t to SID function.
1139 *****************************************************************/
1141 void gid_to_sid(DOM_SID *psid, gid_t gid)
1147 if (fetch_sid_from_gid_cache(psid, gid))
1150 if (lp_idmap_gid(&low, &high) && (gid >= low) && (gid <= high) &&
1151 winbind_gid_to_sid(psid, gid)) {
1153 DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
1154 (unsigned int)gid, sid_string_static(psid)));
1158 if (pdb_gid_to_sid(gid, psid)) {
1159 /* This is a mapped group */
1163 if (pdb_rid_algorithm() && (gid < max_algorithmic_gid())) {
1164 sid_copy(psid, get_global_sam_sid());
1165 sid_append_rid(psid, pdb_gid_to_group_rid(gid));
1168 sid_copy(psid, &global_sid_Unix_Groups);
1169 sid_append_rid(psid, gid);
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)));
1217 if (pdb_rid_algorithm() &&
1218 algorithmic_pdb_rid_is_user(rid)) {
1219 *puid = algorithmic_pdb_user_rid_to_uid(rid);
1223 /* This was ours, but it was neither mapped nor
1224 * algorithmic. Fail */
1228 if (winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
1230 if (type != SID_NAME_USER) {
1231 DEBUG(10, ("sid_to_uid: sid %s is a %s\n",
1232 sid_string_static(psid),
1233 sid_type_lookup(type)));
1237 if (!winbind_sid_to_uid(puid, psid)) {
1238 DEBUG(5, ("sid_to_uid: winbind failed to allocate a "
1239 "new uid for sid %s\n",
1240 sid_string_static(psid)));
1246 /* TODO: Here would be the place to allocate both a gid and a uid for
1247 * the SID in question */
1252 DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid),
1253 (unsigned int)*puid ));
1255 store_uid_sid_cache(psid, *puid);
1259 /*****************************************************************
1260 *THE CANONICAL* convert SID to gid function.
1261 Group mapping is used for gids that maps to Wellknown SIDs
1262 *****************************************************************/
1264 BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1269 enum SID_NAME_USE type;
1272 if (fetch_gid_from_cache(pgid, psid))
1275 if (fetch_uid_from_cache(&uid, psid))
1278 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1284 if ((sid_check_is_in_builtin(psid) ||
1285 sid_check_is_in_wellknown_domain(psid))) {
1286 if (pdb_getgrsid(&map, *psid)) {
1293 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1294 if (pdb_sid_to_id(psid, &id, &type)) {
1295 if ((type != SID_NAME_DOM_GRP) &&
1296 (type != SID_NAME_ALIAS)) {
1297 DEBUG(5, ("sid %s is a %s, expected a group\n",
1298 sid_string_static(psid),
1299 sid_type_lookup(type)));
1305 if (pdb_rid_algorithm() &&
1306 !algorithmic_pdb_rid_is_user(rid)) {
1307 /* This must be a group, presented as alias */
1308 *pgid = pdb_group_rid_to_gid(rid);
1311 /* This was ours, but it was neither mapped nor
1312 * algorithmic. Fail. */
1316 if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
1317 DEBUG(11,("sid_to_gid: no one knows the SID %s (tried local, "
1318 "then winbind)\n", sid_string_static(psid)));
1323 /* winbindd knows it; Ensure this is a group sid */
1325 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
1326 (type != SID_NAME_WKN_GRP)) {
1327 DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is "
1328 "a %s\n", sid_type_lookup(type)));
1332 /* winbindd knows it and it is a type of group; sid_to_gid must succeed
1333 or we are dead in the water */
1335 if ( !winbind_sid_to_gid(pgid, psid) ) {
1336 DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid "
1337 "for sid %s\n", sid_string_static(psid)));
1342 DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid),
1343 (unsigned int)*pgid ));
1345 store_gid_sid_cache(psid, *pgid);