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 DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
65 full_name, domain, name));
67 if ((domain == NULL) || (name == NULL)) {
68 DEBUG(0, ("talloc failed\n"));
73 if (strequal(domain, get_global_sam_name())) {
75 /* It's our own domain, lookup the name in passdb */
76 if (lookup_global_sam_name(name, flags, &rid, &type)) {
77 sid_copy(&sid, get_global_sam_sid());
78 sid_append_rid(&sid, rid);
85 if (strequal(domain, builtin_domain_name())) {
87 /* Explicit request for a name in BUILTIN */
88 if (lookup_builtin_name(name, &rid)) {
89 sid_copy(&sid, &global_sid_Builtin);
90 sid_append_rid(&sid, rid);
91 type = SID_NAME_ALIAS;
98 /* Try the explicit winbind lookup first, don't let it guess the
99 * domain yet at this point yet. This comes later. */
101 if ((domain[0] != '\0') &&
102 (winbind_lookup_name(domain, name, &sid, &type))) {
106 if (strequal(domain, unix_users_domain_name())) {
107 if (lookup_unix_user_name(name, &sid)) {
108 type = SID_NAME_USER;
111 TALLOC_FREE(tmp_ctx);
115 if (strequal(domain, unix_groups_domain_name())) {
116 if (lookup_unix_group_name(name, &sid)) {
117 type = SID_NAME_DOM_GRP;
120 TALLOC_FREE(tmp_ctx);
124 if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
125 TALLOC_FREE(tmp_ctx);
130 * Nasty hack necessary for too common scenarios:
132 * For 'valid users = +users' we know "users" is most probably not
133 * BUILTIN\users but the unix group users. This hack requires the
134 * admin to explicitly qualify BUILTIN if BUILTIN\users is meant.
136 * Please note that LOOKUP_NAME_GROUP can not be requested via for
137 * example lsa_lookupnames, it only comes into this routine via
138 * the expansion of group names coming in from smb.conf
141 if ((flags & LOOKUP_NAME_GROUP) && ((grp = getgrnam(name)) != NULL)) {
145 if (pdb_getgrgid(&map, grp->gr_gid)) {
146 /* The hack gets worse. Handle the case where we have
147 * 'force group = +unixgroup' but "unixgroup" has a
150 if (sid_check_is_in_builtin(&map.sid)) {
151 domain = talloc_strdup(
152 tmp_ctx, builtin_domain_name());
154 domain = talloc_strdup(
155 tmp_ctx, get_global_sam_name());
158 sid_copy(&sid, &map.sid);
159 type = map.sid_name_use;
163 /* If we are using the smbpasswd backend, we need to use the
164 * algorithmic mapping for the unix group we find. This is
165 * necessary because when creating the NT token from the unix
166 * gid list we got from initgroups() we use gid_to_sid() that
167 * uses algorithmic mapping if pdb_rid_algorithm() is true. */
169 if (pdb_rid_algorithm() &&
170 (grp->gr_gid < max_algorithmic_gid())) {
171 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
172 sid_compose(&sid, get_global_sam_sid(),
173 pdb_gid_to_group_rid(grp->gr_gid));
174 type = SID_NAME_DOM_GRP;
178 if (lookup_unix_group_name(name, &sid)) {
179 domain = talloc_strdup(tmp_ctx,
180 unix_groups_domain_name());
181 type = SID_NAME_DOM_GRP;
186 /* Now the guesswork begins, we haven't been given an explicit
187 * domain. Try the sequence as documented on
188 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
189 * November 27, 2005 */
191 /* 1. well-known names */
193 if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) {
194 type = SID_NAME_WKN_GRP;
198 /* 2. Builtin domain as such */
200 if (strequal(name, builtin_domain_name())) {
201 /* Swap domain and name */
202 tmp = name; name = domain; domain = tmp;
203 sid_copy(&sid, &global_sid_Builtin);
204 type = SID_NAME_DOMAIN;
208 /* 3. Account domain */
210 if (strequal(name, get_global_sam_name())) {
211 if (!secrets_fetch_domain_sid(name, &sid)) {
212 DEBUG(3, ("Could not fetch my SID\n"));
213 TALLOC_FREE(tmp_ctx);
216 /* Swap domain and name */
217 tmp = name; name = domain; domain = tmp;
218 type = SID_NAME_DOMAIN;
222 /* 4. Primary domain */
224 if (!IS_DC && strequal(name, lp_workgroup())) {
225 if (!secrets_fetch_domain_sid(name, &sid)) {
226 DEBUG(3, ("Could not fetch the domain SID\n"));
227 TALLOC_FREE(tmp_ctx);
230 /* Swap domain and name */
231 tmp = name; name = domain; domain = tmp;
232 type = SID_NAME_DOMAIN;
236 /* 5. Trusted domains as such, to me it looks as if members don't do
237 this, tested an XP workstation in a NT domain -- vl */
239 if (IS_DC && (secrets_fetch_trusted_domain_password(name, NULL,
241 /* Swap domain and name */
242 tmp = name; name = domain; domain = tmp;
243 type = SID_NAME_DOMAIN;
247 /* 6. Builtin aliases */
249 if (lookup_builtin_name(name, &rid)) {
250 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
251 sid_copy(&sid, &global_sid_Builtin);
252 sid_append_rid(&sid, rid);
253 type = SID_NAME_ALIAS;
257 /* 7. Local systems' SAM (DCs don't have a local SAM) */
258 /* 8. Primary SAM (On members, this is the domain) */
260 /* Both cases are done by looking at our passdb */
262 if (lookup_global_sam_name(name, flags, &rid, &type)) {
263 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
264 sid_copy(&sid, get_global_sam_sid());
265 sid_append_rid(&sid, rid);
269 /* Now our local possibilities are exhausted. */
271 if (!(flags & LOOKUP_NAME_REMOTE)) {
272 TALLOC_FREE(tmp_ctx);
276 /* If we are not a DC, we have to ask in our primary domain. Let
277 * winbind do that. */
280 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
281 domain = talloc_strdup(tmp_ctx, lp_workgroup());
285 /* 9. Trusted domains */
287 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
288 * that (yet), but give it a chance. */
290 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
293 enum SID_NAME_USE domain_type;
295 if (type == SID_NAME_DOMAIN) {
296 /* Swap name and type */
297 tmp = name; name = domain; domain = tmp;
301 /* Here we have to cope with a little deficiency in the
302 * winbind API: We have to ask it again for the name of the
303 * domain it figured out itself. Maybe fix that later... */
305 sid_copy(&dom_sid, &sid);
306 sid_split_rid(&dom_sid, &tmp_rid);
308 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
310 (domain_type != SID_NAME_DOMAIN)) {
311 DEBUG(2, ("winbind could not find the domain's name "
312 "it just looked up for us\n"));
313 TALLOC_FREE(tmp_ctx);
319 /* 10. Don't translate */
321 /* 11. Ok, windows would end here. Samba has two more options:
322 Unmapped users and unmapped groups */
324 if (lookup_unix_user_name(name, &sid)) {
325 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
326 type = SID_NAME_USER;
330 if (lookup_unix_group_name(name, &sid)) {
331 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
332 type = SID_NAME_DOM_GRP;
337 * Ok, all possibilities tried. Fail.
340 TALLOC_FREE(tmp_ctx);
344 if ((domain == NULL) || (name == NULL)) {
345 DEBUG(0, ("talloc failed\n"));
346 TALLOC_FREE(tmp_ctx);
351 * Hand over the results to the talloc context we've been given.
354 if ((ret_name != NULL) &&
355 !(*ret_name = talloc_strdup(mem_ctx, name))) {
356 DEBUG(0, ("talloc failed\n"));
357 TALLOC_FREE(tmp_ctx);
361 if (ret_domain != NULL) {
363 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
364 DEBUG(0, ("talloc failed\n"));
365 TALLOC_FREE(tmp_ctx);
369 *ret_domain = tmp_dom;
372 if (ret_sid != NULL) {
373 sid_copy(ret_sid, &sid);
376 if (ret_type != NULL) {
380 TALLOC_FREE(tmp_ctx);
384 /************************************************************************
385 Names from smb.conf can be unqualified. eg. valid users = foo
386 These names should never map to a remote name. Try global_sam_name()\foo,
387 and then "Unix Users"\foo (or "Unix Groups"\foo).
388 ************************************************************************/
390 BOOL lookup_name_smbconf(TALLOC_CTX *mem_ctx,
391 const char *full_name, int flags,
392 const char **ret_domain, const char **ret_name,
393 DOM_SID *ret_sid, enum SID_NAME_USE *ret_type)
395 char *qualified_name;
398 /* NB. No winbindd_separator here as lookup_name needs \\' */
399 if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
401 /* The name is already qualified with a domain. */
403 if (*lp_winbind_separator() != '\\') {
406 /* lookup_name() needs '\\' as a separator */
408 tmp = talloc_strdup(mem_ctx, full_name);
412 tmp[p - full_name] = '\\';
416 return lookup_name(mem_ctx, full_name, flags,
417 ret_domain, ret_name,
421 /* Try with our own SAM name. */
422 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
423 get_global_sam_name(),
425 if (!qualified_name) {
429 if (lookup_name(mem_ctx, qualified_name, flags,
430 ret_domain, ret_name,
431 ret_sid, ret_type)) {
435 /* Finally try with "Unix Users" or "Unix Group" */
436 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
437 flags & LOOKUP_NAME_GROUP ?
438 unix_groups_domain_name() :
439 unix_users_domain_name(),
441 if (!qualified_name) {
445 return lookup_name(mem_ctx, qualified_name, flags,
446 ret_domain, ret_name,
450 static BOOL wb_lookup_rids(TALLOC_CTX *mem_ctx,
451 const DOM_SID *domain_sid,
452 int num_rids, uint32 *rids,
453 const char **domain_name,
454 const char **names, enum SID_NAME_USE *types)
457 const char **my_names;
458 enum SID_NAME_USE *my_types;
461 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
465 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
466 domain_name, &my_names, &my_types)) {
467 for (i=0; i<num_rids; i++) {
468 types[i] = SID_NAME_UNKNOWN;
474 * winbind_lookup_rids allocates its own array. We've been given the
475 * array, so copy it over
478 for (i=0; i<num_rids; i++) {
479 if (my_names[i] == NULL) {
480 TALLOC_FREE(tmp_ctx);
483 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
484 TALLOC_FREE(tmp_ctx);
487 types[i] = my_types[i];
489 TALLOC_FREE(tmp_ctx);
493 static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
494 int num_rids, uint32_t *rids,
495 const char **domain_name,
496 const char ***names, enum SID_NAME_USE **types)
500 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
501 *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids);
503 if ((*names == NULL) || (*types == NULL)) {
507 if (sid_check_is_domain(domain_sid)) {
510 if (*domain_name == NULL) {
511 *domain_name = talloc_strdup(
512 mem_ctx, get_global_sam_name());
515 if (*domain_name == NULL) {
520 result = pdb_lookup_rids(domain_sid, num_rids, rids,
524 return (NT_STATUS_IS_OK(result) ||
525 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
526 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
529 if (sid_check_is_builtin(domain_sid)) {
531 if (*domain_name == NULL) {
532 *domain_name = talloc_strdup(
533 mem_ctx, builtin_domain_name());
536 if (*domain_name == NULL) {
540 for (i=0; i<num_rids; i++) {
541 if (lookup_builtin_rid(*names, rids[i],
543 if ((*names)[i] == NULL) {
546 (*types)[i] = SID_NAME_ALIAS;
548 (*types)[i] = SID_NAME_UNKNOWN;
554 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
555 for (i=0; i<num_rids; i++) {
557 sid_copy(&sid, domain_sid);
558 sid_append_rid(&sid, rids[i]);
559 if (lookup_wellknown_sid(mem_ctx, &sid,
560 domain_name, &(*names)[i])) {
561 if ((*names)[i] == NULL) {
564 (*types)[i] = SID_NAME_WKN_GRP;
566 (*types)[i] = SID_NAME_UNKNOWN;
572 if (sid_check_is_unix_users(domain_sid)) {
573 if (*domain_name == NULL) {
574 *domain_name = talloc_strdup(
575 mem_ctx, unix_users_domain_name());
577 for (i=0; i<num_rids; i++) {
578 (*names)[i] = talloc_strdup(
579 (*names), uidtoname(rids[i]));
580 (*types)[i] = SID_NAME_USER;
585 if (sid_check_is_unix_groups(domain_sid)) {
586 if (*domain_name == NULL) {
587 *domain_name = talloc_strdup(
588 mem_ctx, unix_groups_domain_name());
590 for (i=0; i<num_rids; i++) {
591 (*names)[i] = talloc_strdup(
592 (*names), gidtoname(rids[i]));
593 (*types)[i] = SID_NAME_DOM_GRP;
598 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
599 domain_name, *names, *types);
603 * Is the SID a domain as such? If yes, lookup its name.
606 static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
610 enum SID_NAME_USE type;
612 if (sid_check_is_domain(sid)) {
613 *name = talloc_strdup(mem_ctx, get_global_sam_name());
617 if (sid_check_is_builtin(sid)) {
618 *name = talloc_strdup(mem_ctx, builtin_domain_name());
622 if (sid_check_is_wellknown_domain(sid, &tmp)) {
623 *name = talloc_strdup(mem_ctx, tmp);
627 if (sid->num_auths != 4) {
628 /* This can't be a domain */
633 uint32 i, num_domains;
634 struct trustdom_info **domains;
636 /* This is relatively expensive, but it happens only on DCs
637 * and for SIDs that have 4 sub-authorities and thus look like
640 if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx,
646 for (i=0; i<num_domains; i++) {
647 if (sid_equal(sid, &domains[i]->sid)) {
648 *name = talloc_strdup(mem_ctx,
656 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
657 (type == SID_NAME_DOMAIN)) {
666 * This tries to implement the rather weird rules for the lsa_lookup level
669 * This is as close as we can get to what W2k3 does. With this we survive the
670 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
671 * different, but I assume that's just being too liberal. For example, W2k3
672 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
673 * whereas NT4 does the same as level 1 (I think). I did not fully test that
674 * with NT4, this is what w2k3 does.
676 * Level 1: Ask everywhere
677 * Level 2: Ask domain and trusted domains, no builtin and wkn
678 * Level 3: Only ask domain
679 * Level 4: W2k3ad: Only ask AD trusts
680 * Level 5: Don't lookup anything
684 static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
693 ret = (!sid_check_is_builtin(sid) &&
694 !sid_check_is_wellknown_domain(sid, NULL));
699 ret = sid_check_is_domain(sid);
706 DEBUG(10, ("%s SID %s in level %d\n",
707 ret ? "Accepting" : "Rejecting",
708 sid_string_static(sid), level));
713 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
714 * references to domains, it is explicitly made for this.
716 * This attempts to be as efficient as possible: It collects all SIDs
717 * belonging to a domain and hands them in bulk to the appropriate lookup
718 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
719 * *hugely* from this. Winbind is going to be extended with a lookup_rids
720 * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
724 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
725 const DOM_SID **sids, int level,
726 struct lsa_dom_info **ret_domains,
727 struct lsa_name_info **ret_names)
730 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
731 struct lsa_name_info *name_infos;
732 struct lsa_dom_info *dom_infos;
736 if (!(tmp_ctx = talloc_new(mem_ctx))) {
737 DEBUG(0, ("talloc_new failed\n"));
738 return NT_STATUS_NO_MEMORY;
741 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
742 dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
744 if ((name_infos == NULL) || (dom_infos == NULL)) {
745 result = NT_STATUS_NO_MEMORY;
749 /* First build up the data structures:
751 * dom_infos is a list of domains referenced in the list of
752 * SIDs. Later we will walk the list of domains and look up the RIDs
755 * name_infos is a shadow-copy of the SIDs array to collect the real
758 * dom_info->idxs is an index into the name_infos array. The
759 * difficulty we have here is that we need to keep the SIDs the client
760 * asked for in the same order for the reply
763 for (i=0; i<num_sids; i++) {
766 const char *domain_name = NULL;
768 sid_copy(&sid, sids[i]);
769 name_infos[i].type = SID_NAME_USE_NONE;
771 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
772 /* We can't push that through the normal lookup
773 * process, as this would reference illegal
776 * For example S-1-5-32 would end up referencing
777 * domain S-1-5- with RID 32 which is clearly wrong.
779 if (domain_name == NULL) {
780 result = NT_STATUS_NO_MEMORY;
784 name_infos[i].rid = 0;
785 name_infos[i].type = SID_NAME_DOMAIN;
786 name_infos[i].name = NULL;
788 if (sid_check_is_builtin(&sid)) {
789 /* Yes, W2k3 returns "BUILTIN" both as domain
791 name_infos[i].name = talloc_strdup(
792 name_infos, builtin_domain_name());
793 if (name_infos[i].name == NULL) {
794 result = NT_STATUS_NO_MEMORY;
799 /* This is a normal SID with rid component */
800 if (!sid_split_rid(&sid, &rid)) {
801 result = NT_STATUS_INVALID_PARAMETER;
806 if (!check_dom_sid_to_level(&sid, level)) {
807 name_infos[i].rid = 0;
808 name_infos[i].type = SID_NAME_UNKNOWN;
809 name_infos[i].name = NULL;
813 for (j=0; j<MAX_REF_DOMAINS; j++) {
814 if (!dom_infos[j].valid) {
817 if (sid_equal(&sid, &dom_infos[j].sid)) {
822 if (j == MAX_REF_DOMAINS) {
823 /* TODO: What's the right error message here? */
824 result = NT_STATUS_NONE_MAPPED;
828 if (!dom_infos[j].valid) {
829 /* We found a domain not yet referenced, create a new
831 dom_infos[j].valid = True;
832 sid_copy(&dom_infos[j].sid, &sid);
834 if (domain_name != NULL) {
835 /* This name was being found above in the case
836 * when we found a domain SID */
838 talloc_strdup(dom_infos, domain_name);
839 if (dom_infos[j].name == NULL) {
840 result = NT_STATUS_NO_MEMORY;
844 /* lookup_rids will take care of this */
845 dom_infos[j].name = NULL;
849 name_infos[i].dom_idx = j;
851 if (name_infos[i].type == SID_NAME_USE_NONE) {
852 name_infos[i].rid = rid;
854 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
855 &dom_infos[j].num_idxs);
857 if (dom_infos[j].idxs == NULL) {
858 result = NT_STATUS_NO_MEMORY;
864 /* Iterate over the domains found */
866 for (i=0; i<MAX_REF_DOMAINS; i++) {
868 const char *domain_name = NULL;
870 enum SID_NAME_USE *types;
871 struct lsa_dom_info *dom = &dom_infos[i];
874 /* No domains left, we're done */
878 if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
879 result = NT_STATUS_NO_MEMORY;
883 for (j=0; j<dom->num_idxs; j++) {
884 rids[j] = name_infos[dom->idxs[j]].rid;
887 if (!lookup_rids(tmp_ctx, &dom->sid,
888 dom->num_idxs, rids, &domain_name,
890 result = NT_STATUS_NO_MEMORY;
894 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
895 result = NT_STATUS_NO_MEMORY;
899 for (j=0; j<dom->num_idxs; j++) {
900 int idx = dom->idxs[j];
901 name_infos[idx].type = types[j];
902 if (types[j] != SID_NAME_UNKNOWN) {
903 name_infos[idx].name =
904 talloc_strdup(name_infos, names[j]);
905 if (name_infos[idx].name == NULL) {
906 result = NT_STATUS_NO_MEMORY;
910 name_infos[idx].name = NULL;
915 *ret_domains = dom_infos;
916 *ret_names = name_infos;
920 TALLOC_FREE(dom_infos);
921 TALLOC_FREE(name_infos);
922 TALLOC_FREE(tmp_ctx);
926 /*****************************************************************
927 *THE CANONICAL* convert SID to name function.
928 *****************************************************************/
930 BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
931 const char **ret_domain, const char **ret_name,
932 enum SID_NAME_USE *ret_type)
934 struct lsa_dom_info *domain;
935 struct lsa_name_info *name;
939 if (!(tmp_ctx = talloc_new(mem_ctx))) {
940 DEBUG(0, ("talloc_new failed\n"));
944 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
949 if (name->type == SID_NAME_UNKNOWN) {
953 if ((ret_domain != NULL) &&
954 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
958 if ((ret_name != NULL) &&
959 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
963 if (ret_type != NULL) {
964 *ret_type = name->type;
971 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
972 sid_string_static(sid), domain->name,
973 name->name, name->type));
975 DEBUG(10, ("failed to lookup sid %s\n",
976 sid_string_static(sid)));
978 TALLOC_FREE(tmp_ctx);
982 /*****************************************************************
983 Id mapping cache. This is to avoid Winbind mappings already
984 seen by smbd to be queried too frequently, keeping winbindd
985 busy, and blocking smbd while winbindd is busy with other
986 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
987 modified to use linked lists by jra.
988 *****************************************************************/
990 #define MAX_UID_SID_CACHE_SIZE 100
991 #define TURNOVER_UID_SID_CACHE_SIZE 10
992 #define MAX_GID_SID_CACHE_SIZE 100
993 #define TURNOVER_GID_SID_CACHE_SIZE 10
995 static size_t n_uid_sid_cache = 0;
996 static size_t n_gid_sid_cache = 0;
998 static struct uid_sid_cache {
999 struct uid_sid_cache *next, *prev;
1002 enum SID_NAME_USE sidtype;
1003 } *uid_sid_cache_head;
1005 static struct gid_sid_cache {
1006 struct gid_sid_cache *next, *prev;
1009 enum SID_NAME_USE sidtype;
1010 } *gid_sid_cache_head;
1012 /*****************************************************************
1013 Find a SID given a uid.
1014 *****************************************************************/
1016 static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
1018 struct uid_sid_cache *pc;
1020 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
1021 if (pc->uid == uid) {
1023 DEBUG(3,("fetch sid from uid cache %u -> %s\n",
1024 (unsigned int)uid, sid_string_static(psid)));
1025 DLIST_PROMOTE(uid_sid_cache_head, pc);
1032 /*****************************************************************
1033 Find a uid given a SID.
1034 *****************************************************************/
1036 static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
1038 struct uid_sid_cache *pc;
1040 for (pc = uid_sid_cache_head; pc; pc = pc->next) {
1041 if (sid_compare(&pc->sid, psid) == 0) {
1043 DEBUG(3,("fetch uid from cache %u -> %s\n",
1044 (unsigned int)*puid, sid_string_static(psid)));
1045 DLIST_PROMOTE(uid_sid_cache_head, pc);
1052 /*****************************************************************
1053 Store uid to SID mapping in cache.
1054 *****************************************************************/
1056 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
1058 struct uid_sid_cache *pc;
1060 if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
1061 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
1062 struct uid_sid_cache *pc_next;
1065 for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
1067 for(; pc; pc = pc_next) {
1069 DLIST_REMOVE(uid_sid_cache_head,pc);
1075 pc = SMB_MALLOC_P(struct uid_sid_cache);
1079 sid_copy(&pc->sid, psid);
1080 DLIST_ADD(uid_sid_cache_head, pc);
1084 /*****************************************************************
1085 Find a SID given a gid.
1086 *****************************************************************/
1088 static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
1090 struct gid_sid_cache *pc;
1092 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
1093 if (pc->gid == gid) {
1095 DEBUG(3,("fetch sid from gid cache %u -> %s\n",
1096 (unsigned int)gid, sid_string_static(psid)));
1097 DLIST_PROMOTE(gid_sid_cache_head, pc);
1104 /*****************************************************************
1105 Find a gid given a SID.
1106 *****************************************************************/
1108 static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
1110 struct gid_sid_cache *pc;
1112 for (pc = gid_sid_cache_head; pc; pc = pc->next) {
1113 if (sid_compare(&pc->sid, psid) == 0) {
1115 DEBUG(3,("fetch gid from cache %u -> %s\n",
1116 (unsigned int)*pgid, sid_string_static(psid)));
1117 DLIST_PROMOTE(gid_sid_cache_head, pc);
1124 /*****************************************************************
1125 Store gid to SID mapping in cache.
1126 *****************************************************************/
1128 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
1130 struct gid_sid_cache *pc;
1132 if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
1133 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
1134 struct gid_sid_cache *pc_next;
1137 for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
1139 for(; pc; pc = pc_next) {
1141 DLIST_REMOVE(gid_sid_cache_head,pc);
1147 pc = SMB_MALLOC_P(struct gid_sid_cache);
1151 sid_copy(&pc->sid, psid);
1152 DLIST_ADD(gid_sid_cache_head, pc);
1154 DEBUG(3,("store_gid_sid_cache: gid %u in cache -> %s\n", (unsigned int)gid,
1155 sid_string_static(psid)));
1160 /*****************************************************************
1161 *THE CANONICAL* convert uid_t to SID function.
1162 *****************************************************************/
1164 void uid_to_sid(DOM_SID *psid, uid_t uid)
1171 if (fetch_sid_from_uid_cache(psid, uid))
1174 if (lp_idmap_uid(&low, &high) && (uid >= low) && (uid <= high) &&
1175 winbind_uid_to_sid(psid, uid)) {
1177 DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
1178 (unsigned int)uid, sid_string_static(psid)));
1182 if (pdb_uid_to_rid(uid, &rid)) {
1183 /* This is a mapped user */
1184 sid_copy(psid, get_global_sam_sid());
1185 sid_append_rid(psid, rid);
1189 if (pdb_rid_algorithm() && (uid < max_algorithmic_uid())) {
1190 sid_copy(psid, get_global_sam_sid());
1191 sid_append_rid(psid, algorithmic_pdb_uid_to_user_rid(uid));
1194 uid_to_unix_users_sid(uid, psid);
1199 DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid,
1200 sid_string_static(psid)));
1202 store_uid_sid_cache(psid, uid);
1206 /*****************************************************************
1207 *THE CANONICAL* convert gid_t to SID function.
1208 *****************************************************************/
1210 void gid_to_sid(DOM_SID *psid, gid_t gid)
1216 if (fetch_sid_from_gid_cache(psid, gid))
1219 if (lp_idmap_gid(&low, &high) && (gid >= low) && (gid <= high) &&
1220 winbind_gid_to_sid(psid, gid)) {
1222 DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
1223 (unsigned int)gid, sid_string_static(psid)));
1227 if (pdb_gid_to_sid(gid, psid)) {
1228 /* This is a mapped group */
1232 if (pdb_rid_algorithm() && (gid < max_algorithmic_gid())) {
1233 sid_copy(psid, get_global_sam_sid());
1234 sid_append_rid(psid, pdb_gid_to_group_rid(gid));
1237 sid_copy(psid, &global_sid_Unix_Groups);
1238 sid_append_rid(psid, gid);
1243 DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid,
1244 sid_string_static(psid)));
1246 store_gid_sid_cache(psid, gid);
1250 /*****************************************************************
1251 *THE CANONICAL* convert SID to uid function.
1252 *****************************************************************/
1254 BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
1256 enum SID_NAME_USE type;
1260 if (fetch_uid_from_cache(puid, psid))
1263 if (fetch_gid_from_cache(&gid, psid)) {
1267 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1273 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1276 if (pdb_sid_to_id(psid, &id, &type)) {
1277 if (type != SID_NAME_USER) {
1278 DEBUG(5, ("sid %s is a %s, expected a user\n",
1279 sid_string_static(psid),
1280 sid_type_lookup(type)));
1286 if (pdb_rid_algorithm() &&
1287 algorithmic_pdb_rid_is_user(rid)) {
1288 *puid = algorithmic_pdb_user_rid_to_uid(rid);
1292 /* This was ours, but it was neither mapped nor
1293 * algorithmic. Fail */
1297 if (winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
1299 if (type != SID_NAME_USER) {
1300 DEBUG(10, ("sid_to_uid: sid %s is a %s\n",
1301 sid_string_static(psid),
1302 sid_type_lookup(type)));
1306 if (!winbind_sid_to_uid(puid, psid)) {
1307 DEBUG(5, ("sid_to_uid: winbind failed to allocate a "
1308 "new uid for sid %s\n",
1309 sid_string_static(psid)));
1315 /* TODO: Here would be the place to allocate both a gid and a uid for
1316 * the SID in question */
1321 DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid),
1322 (unsigned int)*puid ));
1324 store_uid_sid_cache(psid, *puid);
1328 /*****************************************************************
1329 *THE CANONICAL* convert SID to gid function.
1330 Group mapping is used for gids that maps to Wellknown SIDs
1331 *****************************************************************/
1333 BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
1338 enum SID_NAME_USE type;
1341 if (fetch_gid_from_cache(pgid, psid))
1344 if (fetch_uid_from_cache(&uid, psid))
1347 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1353 if ((sid_check_is_in_builtin(psid) ||
1354 sid_check_is_in_wellknown_domain(psid))) {
1355 if (pdb_getgrsid(&map, *psid)) {
1362 if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1363 if (pdb_sid_to_id(psid, &id, &type)) {
1364 if ((type != SID_NAME_DOM_GRP) &&
1365 (type != SID_NAME_ALIAS)) {
1366 DEBUG(5, ("sid %s is a %s, expected a group\n",
1367 sid_string_static(psid),
1368 sid_type_lookup(type)));
1374 if (pdb_rid_algorithm() &&
1375 !algorithmic_pdb_rid_is_user(rid)) {
1376 /* This must be a group, presented as alias */
1377 *pgid = pdb_group_rid_to_gid(rid);
1380 /* This was ours, but it was neither mapped nor
1381 * algorithmic. Fail. */
1385 if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
1386 DEBUG(11,("sid_to_gid: no one knows the SID %s (tried local, "
1387 "then winbind)\n", sid_string_static(psid)));
1392 /* winbindd knows it; Ensure this is a group sid */
1394 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
1395 (type != SID_NAME_WKN_GRP)) {
1396 DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is "
1397 "a %s\n", sid_type_lookup(type)));
1401 /* winbindd knows it and it is a type of group; sid_to_gid must succeed
1402 or we are dead in the water */
1404 if ( !winbind_sid_to_gid(pgid, psid) ) {
1405 DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid "
1406 "for sid %s\n", sid_string_static(psid)));
1411 DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid),
1412 (unsigned int)*pgid ));
1414 store_gid_sid_cache(psid, *pgid);