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 3 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, see <http://www.gnu.org/licenses/>.
24 #include "../librpc/gen_ndr/ndr_security.h"
26 #include "../lib/util/memcache.h"
27 #include "idmap_cache.h"
28 #include "../libcli/security/security.h"
29 #include "lib/winbind_util.h"
30 #include "../librpc/gen_ndr/idmap.h"
32 /*****************************************************************
33 Dissect a user-provided name into domain, name, sid and type.
35 If an explicit domain name was given in the form domain\user, it
36 has to try that. If no explicit domain name was given, we have
38 *****************************************************************/
40 bool lookup_name(TALLOC_CTX
*mem_ctx
,
41 const char *full_name
, int flags
,
42 const char **ret_domain
, const char **ret_name
,
43 struct dom_sid
*ret_sid
, enum lsa_SidType
*ret_type
)
47 const char *domain
= NULL
;
48 const char *name
= NULL
;
51 enum lsa_SidType type
;
52 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
54 if (tmp_ctx
== NULL
) {
55 DEBUG(0, ("talloc_new failed\n"));
59 p
= strchr_m(full_name
, '\\');
62 domain
= talloc_strndup(tmp_ctx
, full_name
,
63 PTR_DIFF(p
, full_name
));
64 name
= talloc_strdup(tmp_ctx
, p
+1);
66 domain
= talloc_strdup(tmp_ctx
, "");
67 name
= talloc_strdup(tmp_ctx
, full_name
);
70 if ((domain
== NULL
) || (name
== NULL
)) {
71 DEBUG(0, ("talloc failed\n"));
76 DEBUG(10,("lookup_name: %s => domain=[%s], name=[%s]\n",
77 full_name
, domain
, name
));
78 DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags
));
80 if ((flags
& LOOKUP_NAME_DOMAIN
) &&
81 strequal(domain
, get_global_sam_name()))
84 /* It's our own domain, lookup the name in passdb */
85 if (lookup_global_sam_name(name
, flags
, &rid
, &type
)) {
86 sid_compose(&sid
, get_global_sam_sid(), rid
);
93 if ((flags
& LOOKUP_NAME_BUILTIN
) &&
94 strequal(domain
, builtin_domain_name()))
96 if (strlen(name
) == 0) {
97 /* Swap domain and name */
98 tmp
= name
; name
= domain
; domain
= tmp
;
99 sid_copy(&sid
, &global_sid_Builtin
);
100 type
= SID_NAME_DOMAIN
;
104 /* Explicit request for a name in BUILTIN */
105 if (lookup_builtin_name(name
, &rid
)) {
106 sid_compose(&sid
, &global_sid_Builtin
, rid
);
107 type
= SID_NAME_ALIAS
;
110 TALLOC_FREE(tmp_ctx
);
114 /* Try the explicit winbind lookup first, don't let it guess the
115 * domain yet at this point yet. This comes later. */
117 if ((domain
[0] != '\0') &&
118 (flags
& ~(LOOKUP_NAME_DOMAIN
|LOOKUP_NAME_ISOLATED
)) &&
119 (winbind_lookup_name(domain
, name
, &sid
, &type
))) {
123 if (((flags
& LOOKUP_NAME_NO_NSS
) == 0)
124 && strequal(domain
, unix_users_domain_name())) {
125 if (lookup_unix_user_name(name
, &sid
)) {
126 type
= SID_NAME_USER
;
129 TALLOC_FREE(tmp_ctx
);
133 if (((flags
& LOOKUP_NAME_NO_NSS
) == 0)
134 && strequal(domain
, unix_groups_domain_name())) {
135 if (lookup_unix_group_name(name
, &sid
)) {
136 type
= SID_NAME_DOM_GRP
;
139 TALLOC_FREE(tmp_ctx
);
143 if ((domain
[0] == '\0') && (!(flags
& LOOKUP_NAME_ISOLATED
))) {
144 TALLOC_FREE(tmp_ctx
);
148 /* Now the guesswork begins, we haven't been given an explicit
149 * domain. Try the sequence as documented on
150 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
151 * November 27, 2005 */
153 /* 1. well-known names */
155 if ((flags
& LOOKUP_NAME_WKN
) &&
156 lookup_wellknown_name(tmp_ctx
, name
, &sid
, &domain
))
158 type
= SID_NAME_WKN_GRP
;
162 /* 2. Builtin domain as such */
164 if ((flags
& (LOOKUP_NAME_BUILTIN
|LOOKUP_NAME_REMOTE
)) &&
165 strequal(name
, builtin_domain_name()))
167 /* Swap domain and name */
168 tmp
= name
; name
= domain
; domain
= tmp
;
169 sid_copy(&sid
, &global_sid_Builtin
);
170 type
= SID_NAME_DOMAIN
;
174 /* 3. Account domain */
176 if ((flags
& LOOKUP_NAME_DOMAIN
) &&
177 strequal(name
, get_global_sam_name()))
179 if (!secrets_fetch_domain_sid(name
, &sid
)) {
180 DEBUG(3, ("Could not fetch my SID\n"));
181 TALLOC_FREE(tmp_ctx
);
184 /* Swap domain and name */
185 tmp
= name
; name
= domain
; domain
= tmp
;
186 type
= SID_NAME_DOMAIN
;
190 /* 4. Primary domain */
192 if ((flags
& LOOKUP_NAME_DOMAIN
) && !IS_DC
&&
193 strequal(name
, lp_workgroup()))
195 if (!secrets_fetch_domain_sid(name
, &sid
)) {
196 DEBUG(3, ("Could not fetch the domain SID\n"));
197 TALLOC_FREE(tmp_ctx
);
200 /* Swap domain and name */
201 tmp
= name
; name
= domain
; domain
= tmp
;
202 type
= SID_NAME_DOMAIN
;
206 /* 5. Trusted domains as such, to me it looks as if members don't do
207 this, tested an XP workstation in a NT domain -- vl */
209 if ((flags
& LOOKUP_NAME_REMOTE
) && IS_DC
&&
210 (pdb_get_trusteddom_pw(name
, NULL
, &sid
, NULL
)))
212 /* Swap domain and name */
213 tmp
= name
; name
= domain
; domain
= tmp
;
214 type
= SID_NAME_DOMAIN
;
218 /* 6. Builtin aliases */
220 if ((flags
& LOOKUP_NAME_BUILTIN
) &&
221 lookup_builtin_name(name
, &rid
))
223 domain
= talloc_strdup(tmp_ctx
, builtin_domain_name());
224 sid_compose(&sid
, &global_sid_Builtin
, rid
);
225 type
= SID_NAME_ALIAS
;
229 /* 7. Local systems' SAM (DCs don't have a local SAM) */
230 /* 8. Primary SAM (On members, this is the domain) */
232 /* Both cases are done by looking at our passdb */
234 if ((flags
& LOOKUP_NAME_DOMAIN
) &&
235 lookup_global_sam_name(name
, flags
, &rid
, &type
))
237 domain
= talloc_strdup(tmp_ctx
, get_global_sam_name());
238 sid_compose(&sid
, get_global_sam_sid(), rid
);
242 /* Now our local possibilities are exhausted. */
244 if (!(flags
& LOOKUP_NAME_REMOTE
)) {
245 TALLOC_FREE(tmp_ctx
);
249 /* If we are not a DC, we have to ask in our primary domain. Let
250 * winbind do that. */
253 (winbind_lookup_name(lp_workgroup(), name
, &sid
, &type
))) {
254 domain
= talloc_strdup(tmp_ctx
, lp_workgroup());
258 /* 9. Trusted domains */
260 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
261 * that (yet), but give it a chance. */
263 if (IS_DC
&& winbind_lookup_name("", name
, &sid
, &type
)) {
264 struct dom_sid dom_sid
;
265 enum lsa_SidType domain_type
;
267 if (type
== SID_NAME_DOMAIN
) {
268 /* Swap name and type */
269 tmp
= name
; name
= domain
; domain
= tmp
;
273 /* Here we have to cope with a little deficiency in the
274 * winbind API: We have to ask it again for the name of the
275 * domain it figured out itself. Maybe fix that later... */
277 sid_copy(&dom_sid
, &sid
);
278 sid_split_rid(&dom_sid
, NULL
);
280 if (!winbind_lookup_sid(tmp_ctx
, &dom_sid
, &domain
, NULL
,
282 (domain_type
!= SID_NAME_DOMAIN
)) {
283 DEBUG(2, ("winbind could not find the domain's name "
284 "it just looked up for us\n"));
285 TALLOC_FREE(tmp_ctx
);
291 /* 10. Don't translate */
293 /* 11. Ok, windows would end here. Samba has two more options:
294 Unmapped users and unmapped groups */
296 if (((flags
& LOOKUP_NAME_NO_NSS
) == 0)
297 && lookup_unix_user_name(name
, &sid
)) {
298 domain
= talloc_strdup(tmp_ctx
, unix_users_domain_name());
299 type
= SID_NAME_USER
;
303 if (((flags
& LOOKUP_NAME_NO_NSS
) == 0)
304 && lookup_unix_group_name(name
, &sid
)) {
305 domain
= talloc_strdup(tmp_ctx
, unix_groups_domain_name());
306 type
= SID_NAME_DOM_GRP
;
311 * Ok, all possibilities tried. Fail.
314 TALLOC_FREE(tmp_ctx
);
318 if ((domain
== NULL
) || (name
== NULL
)) {
319 DEBUG(0, ("talloc failed\n"));
320 TALLOC_FREE(tmp_ctx
);
325 * Hand over the results to the talloc context we've been given.
328 if ((ret_name
!= NULL
) &&
329 !(*ret_name
= talloc_strdup(mem_ctx
, name
))) {
330 DEBUG(0, ("talloc failed\n"));
331 TALLOC_FREE(tmp_ctx
);
335 if (ret_domain
!= NULL
) {
337 if (!(tmp_dom
= talloc_strdup(mem_ctx
, domain
))) {
338 DEBUG(0, ("talloc failed\n"));
339 TALLOC_FREE(tmp_ctx
);
342 if (!strupper_m(tmp_dom
)) {
343 TALLOC_FREE(tmp_ctx
);
346 *ret_domain
= tmp_dom
;
349 if (ret_sid
!= NULL
) {
350 sid_copy(ret_sid
, &sid
);
353 if (ret_type
!= NULL
) {
357 TALLOC_FREE(tmp_ctx
);
361 /************************************************************************
362 Names from smb.conf can be unqualified. eg. valid users = foo
363 These names should never map to a remote name. Try global_sam_name()\foo,
364 and then "Unix Users"\foo (or "Unix Groups"\foo).
365 ************************************************************************/
367 bool lookup_name_smbconf(TALLOC_CTX
*mem_ctx
,
368 const char *full_name
, int flags
,
369 const char **ret_domain
, const char **ret_name
,
370 struct dom_sid
*ret_sid
, enum lsa_SidType
*ret_type
)
372 char *qualified_name
;
375 /* NB. No winbindd_separator here as lookup_name needs \\' */
376 if ((p
= strchr_m(full_name
, *lp_winbind_separator())) != NULL
) {
378 /* The name is already qualified with a domain. */
380 if (*lp_winbind_separator() != '\\') {
383 /* lookup_name() needs '\\' as a separator */
385 tmp
= talloc_strdup(mem_ctx
, full_name
);
389 tmp
[p
- full_name
] = '\\';
393 return lookup_name(mem_ctx
, full_name
, flags
,
394 ret_domain
, ret_name
,
398 /* Try with winbind default domain name. */
399 if (lp_winbind_use_default_domain()) {
402 qualified_name
= talloc_asprintf(mem_ctx
,
406 if (qualified_name
== NULL
) {
410 ok
= lookup_name(mem_ctx
,
422 /* Try with our own SAM name. */
423 qualified_name
= talloc_asprintf(mem_ctx
, "%s\\%s",
424 get_global_sam_name(),
426 if (!qualified_name
) {
430 if (lookup_name(mem_ctx
, qualified_name
, flags
,
431 ret_domain
, ret_name
,
432 ret_sid
, ret_type
)) {
436 /* Finally try with "Unix Users" or "Unix Group" */
437 qualified_name
= talloc_asprintf(mem_ctx
, "%s\\%s",
438 flags
& LOOKUP_NAME_GROUP
?
439 unix_groups_domain_name() :
440 unix_users_domain_name(),
442 if (!qualified_name
) {
446 return lookup_name(mem_ctx
, qualified_name
, flags
,
447 ret_domain
, ret_name
,
451 static bool wb_lookup_rids(TALLOC_CTX
*mem_ctx
,
452 const struct dom_sid
*domain_sid
,
453 int num_rids
, uint32
*rids
,
454 const char **domain_name
,
455 const char **names
, enum lsa_SidType
*types
)
458 const char **my_names
;
459 enum lsa_SidType
*my_types
;
462 if (!(tmp_ctx
= talloc_init("wb_lookup_rids"))) {
466 if (!winbind_lookup_rids(tmp_ctx
, domain_sid
, num_rids
, rids
,
467 domain_name
, &my_names
, &my_types
)) {
469 for (i
=0; i
<num_rids
; i
++) {
471 types
[i
] = SID_NAME_UNKNOWN
;
473 TALLOC_FREE(tmp_ctx
);
477 if (!(*domain_name
= talloc_strdup(mem_ctx
, *domain_name
))) {
478 TALLOC_FREE(tmp_ctx
);
483 * winbind_lookup_rids allocates its own array. We've been given the
484 * array, so copy it over
487 for (i
=0; i
<num_rids
; i
++) {
488 if (my_names
[i
] == NULL
) {
489 TALLOC_FREE(tmp_ctx
);
492 if (!(names
[i
] = talloc_strdup(names
, my_names
[i
]))) {
493 TALLOC_FREE(tmp_ctx
);
496 types
[i
] = my_types
[i
];
498 TALLOC_FREE(tmp_ctx
);
502 static bool lookup_rids(TALLOC_CTX
*mem_ctx
, const struct dom_sid
*domain_sid
,
503 int num_rids
, uint32_t *rids
,
504 const char **domain_name
,
505 const char ***names
, enum lsa_SidType
**types
)
509 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
510 sid_string_dbg(domain_sid
)));
513 *names
= talloc_zero_array(mem_ctx
, const char *, num_rids
);
514 *types
= talloc_array(mem_ctx
, enum lsa_SidType
, num_rids
);
516 if ((*names
== NULL
) || (*types
== NULL
)) {
520 for (i
= 0; i
< num_rids
; i
++)
521 (*types
)[i
] = SID_NAME_UNKNOWN
;
527 if (sid_check_is_our_sam(domain_sid
)) {
530 if (*domain_name
== NULL
) {
531 *domain_name
= talloc_strdup(
532 mem_ctx
, get_global_sam_name());
535 if (*domain_name
== NULL
) {
540 result
= pdb_lookup_rids(domain_sid
, num_rids
, rids
,
544 return (NT_STATUS_IS_OK(result
) ||
545 NT_STATUS_EQUAL(result
, NT_STATUS_NONE_MAPPED
) ||
546 NT_STATUS_EQUAL(result
, STATUS_SOME_UNMAPPED
));
549 if (sid_check_is_builtin(domain_sid
)) {
551 if (*domain_name
== NULL
) {
552 *domain_name
= talloc_strdup(
553 mem_ctx
, builtin_domain_name());
556 if (*domain_name
== NULL
) {
560 for (i
=0; i
<num_rids
; i
++) {
561 if (lookup_builtin_rid(*names
, rids
[i
],
563 if ((*names
)[i
] == NULL
) {
566 (*types
)[i
] = SID_NAME_ALIAS
;
568 (*types
)[i
] = SID_NAME_UNKNOWN
;
574 if (sid_check_is_wellknown_domain(domain_sid
, NULL
)) {
575 for (i
=0; i
<num_rids
; i
++) {
577 sid_compose(&sid
, domain_sid
, rids
[i
]);
578 if (lookup_wellknown_sid(mem_ctx
, &sid
,
579 domain_name
, &(*names
)[i
])) {
580 if ((*names
)[i
] == NULL
) {
583 (*types
)[i
] = SID_NAME_WKN_GRP
;
585 (*types
)[i
] = SID_NAME_UNKNOWN
;
591 if (sid_check_is_unix_users(domain_sid
)) {
592 if (*domain_name
== NULL
) {
593 *domain_name
= talloc_strdup(
594 mem_ctx
, unix_users_domain_name());
595 if (*domain_name
== NULL
) {
599 for (i
=0; i
<num_rids
; i
++) {
600 (*names
)[i
] = talloc_strdup(
601 (*names
), uidtoname(rids
[i
]));
602 if ((*names
)[i
] == NULL
) {
605 (*types
)[i
] = SID_NAME_USER
;
610 if (sid_check_is_unix_groups(domain_sid
)) {
611 if (*domain_name
== NULL
) {
612 *domain_name
= talloc_strdup(
613 mem_ctx
, unix_groups_domain_name());
614 if (*domain_name
== NULL
) {
618 for (i
=0; i
<num_rids
; i
++) {
619 (*names
)[i
] = talloc_strdup(
620 (*names
), gidtoname(rids
[i
]));
621 if ((*names
)[i
] == NULL
) {
624 (*types
)[i
] = SID_NAME_DOM_GRP
;
629 return wb_lookup_rids(mem_ctx
, domain_sid
, num_rids
, rids
,
630 domain_name
, *names
, *types
);
634 * Is the SID a domain as such? If yes, lookup its name.
637 static bool lookup_as_domain(const struct dom_sid
*sid
, TALLOC_CTX
*mem_ctx
,
641 enum lsa_SidType type
;
643 if (sid_check_is_our_sam(sid
)) {
644 *name
= talloc_strdup(mem_ctx
, get_global_sam_name());
648 if (sid_check_is_builtin(sid
)) {
649 *name
= talloc_strdup(mem_ctx
, builtin_domain_name());
653 if (sid_check_is_wellknown_domain(sid
, &tmp
)) {
654 *name
= talloc_strdup(mem_ctx
, tmp
);
658 if (sid_check_is_unix_users(sid
)) {
659 *name
= talloc_strdup(mem_ctx
, unix_users_domain_name());
663 if (sid_check_is_unix_groups(sid
)) {
664 *name
= talloc_strdup(mem_ctx
, unix_groups_domain_name());
668 if (sid
->num_auths
!= 4) {
669 /* This can't be a domain */
674 uint32 i
, num_domains
;
675 struct trustdom_info
**domains
;
677 /* This is relatively expensive, but it happens only on DCs
678 * and for SIDs that have 4 sub-authorities and thus look like
681 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx
,
687 for (i
=0; i
<num_domains
; i
++) {
688 if (dom_sid_equal(sid
, &domains
[i
]->sid
)) {
689 *name
= talloc_strdup(mem_ctx
,
697 if (winbind_lookup_sid(mem_ctx
, sid
, &tmp
, NULL
, &type
) &&
698 (type
== SID_NAME_DOMAIN
)) {
707 * This tries to implement the rather weird rules for the lsa_lookup level
710 * This is as close as we can get to what W2k3 does. With this we survive the
711 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
712 * different, but I assume that's just being too liberal. For example, W2k3
713 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
714 * whereas NT4 does the same as level 1 (I think). I did not fully test that
715 * with NT4, this is what w2k3 does.
717 * Level 1: Ask everywhere
718 * Level 2: Ask domain and trusted domains, no builtin and wkn
719 * Level 3: Only ask domain
720 * Level 4: W2k3ad: Only ask AD trusts
721 * Level 5: Only ask transitive forest trusts
725 static bool check_dom_sid_to_level(const struct dom_sid
*sid
, int level
)
734 ret
= (!sid_check_is_builtin(sid
) &&
735 !sid_check_is_wellknown_domain(sid
, NULL
));
740 ret
= sid_check_is_our_sam(sid
);
747 DEBUG(10, ("%s SID %s in level %d\n",
748 ret
? "Accepting" : "Rejecting",
749 sid_string_dbg(sid
), level
));
754 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
755 * references to domains, it is explicitly made for this.
757 * This attempts to be as efficient as possible: It collects all SIDs
758 * belonging to a domain and hands them in bulk to the appropriate lookup
759 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
760 * *hugely* from this.
763 NTSTATUS
lookup_sids(TALLOC_CTX
*mem_ctx
, int num_sids
,
764 const struct dom_sid
**sids
, int level
,
765 struct lsa_dom_info
**ret_domains
,
766 struct lsa_name_info
**ret_names
)
769 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
770 struct lsa_name_info
*name_infos
;
771 struct lsa_dom_info
*dom_infos
= NULL
;
775 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
776 DEBUG(0, ("talloc_new failed\n"));
777 return NT_STATUS_NO_MEMORY
;
781 name_infos
= talloc_array(mem_ctx
, struct lsa_name_info
, num_sids
);
782 if (name_infos
== NULL
) {
783 result
= NT_STATUS_NO_MEMORY
;
790 dom_infos
= talloc_zero_array(mem_ctx
, struct lsa_dom_info
,
791 LSA_REF_DOMAIN_LIST_MULTIPLIER
);
792 if (dom_infos
== NULL
) {
793 result
= NT_STATUS_NO_MEMORY
;
797 /* First build up the data structures:
799 * dom_infos is a list of domains referenced in the list of
800 * SIDs. Later we will walk the list of domains and look up the RIDs
803 * name_infos is a shadow-copy of the SIDs array to collect the real
806 * dom_info->idxs is an index into the name_infos array. The
807 * difficulty we have here is that we need to keep the SIDs the client
808 * asked for in the same order for the reply
811 for (i
=0; i
<num_sids
; i
++) {
814 const char *domain_name
= NULL
;
816 sid_copy(&sid
, sids
[i
]);
817 name_infos
[i
].type
= SID_NAME_USE_NONE
;
819 if (lookup_as_domain(&sid
, name_infos
, &domain_name
)) {
820 /* We can't push that through the normal lookup
821 * process, as this would reference illegal
824 * For example S-1-5-32 would end up referencing
825 * domain S-1-5- with RID 32 which is clearly wrong.
827 if (domain_name
== NULL
) {
828 result
= NT_STATUS_NO_MEMORY
;
832 name_infos
[i
].rid
= 0;
833 name_infos
[i
].type
= SID_NAME_DOMAIN
;
834 name_infos
[i
].name
= NULL
;
836 if (sid_check_is_builtin(&sid
)) {
837 /* Yes, W2k3 returns "BUILTIN" both as domain
839 name_infos
[i
].name
= talloc_strdup(
840 name_infos
, builtin_domain_name());
841 if (name_infos
[i
].name
== NULL
) {
842 result
= NT_STATUS_NO_MEMORY
;
847 /* This is a normal SID with rid component */
848 if (!sid_split_rid(&sid
, &rid
)) {
849 result
= NT_STATUS_INVALID_SID
;
854 if (!check_dom_sid_to_level(&sid
, level
)) {
855 name_infos
[i
].rid
= 0;
856 name_infos
[i
].type
= SID_NAME_UNKNOWN
;
857 name_infos
[i
].name
= NULL
;
861 for (j
=0; j
<LSA_REF_DOMAIN_LIST_MULTIPLIER
; j
++) {
862 if (!dom_infos
[j
].valid
) {
865 if (dom_sid_equal(&sid
, &dom_infos
[j
].sid
)) {
870 if (j
== LSA_REF_DOMAIN_LIST_MULTIPLIER
) {
871 /* TODO: What's the right error message here? */
872 result
= NT_STATUS_NONE_MAPPED
;
876 if (!dom_infos
[j
].valid
) {
877 /* We found a domain not yet referenced, create a new
879 dom_infos
[j
].valid
= true;
880 sid_copy(&dom_infos
[j
].sid
, &sid
);
882 if (domain_name
!= NULL
) {
883 /* This name was being found above in the case
884 * when we found a domain SID */
886 talloc_strdup(dom_infos
, domain_name
);
887 if (dom_infos
[j
].name
== NULL
) {
888 result
= NT_STATUS_NO_MEMORY
;
892 /* lookup_rids will take care of this */
893 dom_infos
[j
].name
= NULL
;
897 name_infos
[i
].dom_idx
= j
;
899 if (name_infos
[i
].type
== SID_NAME_USE_NONE
) {
900 name_infos
[i
].rid
= rid
;
902 ADD_TO_ARRAY(dom_infos
, int, i
, &dom_infos
[j
].idxs
,
903 &dom_infos
[j
].num_idxs
);
905 if (dom_infos
[j
].idxs
== NULL
) {
906 result
= NT_STATUS_NO_MEMORY
;
912 /* Iterate over the domains found */
914 for (i
=0; i
<LSA_REF_DOMAIN_LIST_MULTIPLIER
; i
++) {
916 const char *domain_name
= NULL
;
918 enum lsa_SidType
*types
;
919 struct lsa_dom_info
*dom
= &dom_infos
[i
];
922 /* No domains left, we're done */
927 if (!(rids
= talloc_array(tmp_ctx
, uint32
, dom
->num_idxs
))) {
928 result
= NT_STATUS_NO_MEMORY
;
935 for (j
=0; j
<dom
->num_idxs
; j
++) {
936 rids
[j
] = name_infos
[dom
->idxs
[j
]].rid
;
939 if (!lookup_rids(tmp_ctx
, &dom
->sid
,
940 dom
->num_idxs
, rids
, &domain_name
,
942 result
= NT_STATUS_NO_MEMORY
;
946 if (!(dom
->name
= talloc_strdup(dom_infos
, domain_name
))) {
947 result
= NT_STATUS_NO_MEMORY
;
951 for (j
=0; j
<dom
->num_idxs
; j
++) {
952 int idx
= dom
->idxs
[j
];
953 name_infos
[idx
].type
= types
[j
];
954 if (types
[j
] != SID_NAME_UNKNOWN
) {
955 name_infos
[idx
].name
=
956 talloc_strdup(name_infos
, names
[j
]);
957 if (name_infos
[idx
].name
== NULL
) {
958 result
= NT_STATUS_NO_MEMORY
;
962 name_infos
[idx
].name
= NULL
;
967 *ret_domains
= dom_infos
;
968 *ret_names
= name_infos
;
969 TALLOC_FREE(tmp_ctx
);
973 TALLOC_FREE(dom_infos
);
974 TALLOC_FREE(name_infos
);
975 TALLOC_FREE(tmp_ctx
);
979 /*****************************************************************
980 *THE CANONICAL* convert SID to name function.
981 *****************************************************************/
983 bool lookup_sid(TALLOC_CTX
*mem_ctx
, const struct dom_sid
*sid
,
984 const char **ret_domain
, const char **ret_name
,
985 enum lsa_SidType
*ret_type
)
987 struct lsa_dom_info
*domain
;
988 struct lsa_name_info
*name
;
992 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid
)));
994 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
995 DEBUG(0, ("talloc_new failed\n"));
999 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx
, 1, &sid
, 1,
1004 if (name
->type
== SID_NAME_UNKNOWN
) {
1008 if ((ret_domain
!= NULL
) &&
1009 !(*ret_domain
= talloc_strdup(mem_ctx
, domain
->name
))) {
1013 if ((ret_name
!= NULL
) &&
1014 !(*ret_name
= talloc_strdup(mem_ctx
, name
->name
))) {
1018 if (ret_type
!= NULL
) {
1019 *ret_type
= name
->type
;
1026 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid
),
1027 domain
->name
, name
->name
, name
->type
));
1029 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid
)));
1031 TALLOC_FREE(tmp_ctx
);
1035 /*****************************************************************
1036 Id mapping cache. This is to avoid Winbind mappings already
1037 seen by smbd to be queried too frequently, keeping winbindd
1038 busy, and blocking smbd while winbindd is busy with other
1039 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1040 modified to use linked lists by jra.
1041 *****************************************************************/
1044 /*****************************************************************
1045 *THE LEGACY* convert uid_t to SID function.
1046 *****************************************************************/
1048 static void legacy_uid_to_sid(struct dom_sid
*psid
, uid_t uid
)
1055 ret
= pdb_uid_to_sid(uid
, psid
);
1059 /* This is a mapped user */
1063 /* This is an unmapped user */
1065 uid_to_unix_users_sid(uid
, psid
);
1068 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid
,
1069 sid_string_dbg(psid
)));
1074 /*****************************************************************
1075 *THE LEGACY* convert gid_t to SID function.
1076 *****************************************************************/
1078 static void legacy_gid_to_sid(struct dom_sid
*psid
, gid_t gid
)
1085 ret
= pdb_gid_to_sid(gid
, psid
);
1089 /* This is a mapped group */
1093 /* This is an unmapped group */
1095 gid_to_unix_groups_sid(gid
, psid
);
1098 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid
,
1099 sid_string_dbg(psid
)));
1104 /*****************************************************************
1105 *THE LEGACY* convert SID to id function.
1106 *****************************************************************/
1108 static bool legacy_sid_to_unixid(const struct dom_sid
*psid
, struct unixid
*id
)
1113 ret
= pdb_sid_to_id(psid
, id
);
1117 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1118 sid_string_dbg(psid
)));
1125 static bool legacy_sid_to_gid(const struct dom_sid
*psid
, gid_t
*pgid
)
1128 if (!legacy_sid_to_unixid(psid
, &id
)) {
1131 if (id
.type
== ID_TYPE_GID
|| id
.type
== ID_TYPE_BOTH
) {
1138 static bool legacy_sid_to_uid(const struct dom_sid
*psid
, uid_t
*puid
)
1141 if (!legacy_sid_to_unixid(psid
, &id
)) {
1144 if (id
.type
== ID_TYPE_UID
|| id
.type
== ID_TYPE_BOTH
) {
1151 /*****************************************************************
1152 *THE CANONICAL* convert uid_t to SID function.
1153 *****************************************************************/
1155 void uid_to_sid(struct dom_sid
*psid
, uid_t uid
)
1157 bool expired
= true;
1161 /* Check the winbindd cache directly. */
1162 ret
= idmap_cache_find_uid2sid(uid
, psid
, &expired
);
1164 if (ret
&& !expired
&& is_null_sid(psid
)) {
1166 * Negative cache entry, we already asked.
1169 legacy_uid_to_sid(psid
, uid
);
1173 if (!ret
|| expired
) {
1174 /* Not in cache. Ask winbindd. */
1175 if (!winbind_uid_to_sid(psid
, uid
)) {
1177 * We shouldn't return the NULL SID
1178 * here if winbind was running and
1179 * couldn't map, as winbind will have
1180 * added a negative entry that will
1181 * cause us to go though the
1182 * legacy_uid_to_sid()
1183 * function anyway in the case above
1184 * the next time we ask.
1186 DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1187 "for uid %u\n", (unsigned int)uid
));
1189 legacy_uid_to_sid(psid
, uid
);
1194 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid
,
1195 sid_string_dbg(psid
)));
1200 /*****************************************************************
1201 *THE CANONICAL* convert gid_t to SID function.
1202 *****************************************************************/
1204 void gid_to_sid(struct dom_sid
*psid
, gid_t gid
)
1206 bool expired
= true;
1210 /* Check the winbindd cache directly. */
1211 ret
= idmap_cache_find_gid2sid(gid
, psid
, &expired
);
1213 if (ret
&& !expired
&& is_null_sid(psid
)) {
1215 * Negative cache entry, we already asked.
1218 legacy_gid_to_sid(psid
, gid
);
1222 if (!ret
|| expired
) {
1223 /* Not in cache. Ask winbindd. */
1224 if (!winbind_gid_to_sid(psid
, gid
)) {
1226 * We shouldn't return the NULL SID
1227 * here if winbind was running and
1228 * couldn't map, as winbind will have
1229 * added a negative entry that will
1230 * cause us to go though the
1231 * legacy_gid_to_sid()
1232 * function anyway in the case above
1233 * the next time we ask.
1235 DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1236 "for gid %u\n", (unsigned int)gid
));
1238 legacy_gid_to_sid(psid
, gid
);
1243 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid
,
1244 sid_string_dbg(psid
)));
1249 bool sids_to_unixids(const struct dom_sid
*sids
, uint32_t num_sids
,
1252 struct wbcDomainSid
*wbc_sids
= NULL
;
1253 struct wbcUnixId
*wbc_ids
= NULL
;
1254 uint32_t i
, num_not_cached
;
1258 wbc_sids
= talloc_array(talloc_tos(), struct wbcDomainSid
, num_sids
);
1259 if (wbc_sids
== NULL
) {
1265 for (i
=0; i
<num_sids
; i
++) {
1269 if (sid_peek_check_rid(&global_sid_Unix_Users
,
1271 ids
[i
].type
= ID_TYPE_UID
;
1275 if (sid_peek_check_rid(&global_sid_Unix_Groups
,
1277 ids
[i
].type
= ID_TYPE_GID
;
1281 if (idmap_cache_find_sid2unixid(&sids
[i
], &ids
[i
], &expired
)
1286 ids
[i
].type
= ID_TYPE_NOT_SPECIFIED
;
1287 memcpy(&wbc_sids
[num_not_cached
], &sids
[i
],
1288 ndr_size_dom_sid(&sids
[i
], 0));
1289 num_not_cached
+= 1;
1291 if (num_not_cached
== 0) {
1294 wbc_ids
= talloc_array(talloc_tos(), struct wbcUnixId
, num_not_cached
);
1295 if (wbc_ids
== NULL
) {
1298 for (i
=0; i
<num_not_cached
; i
++) {
1299 wbc_ids
[i
].type
= WBC_ID_TYPE_NOT_SPECIFIED
;
1301 err
= wbcSidsToUnixIds(wbc_sids
, num_not_cached
, wbc_ids
);
1302 if (!WBC_ERROR_IS_OK(err
)) {
1303 DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
1304 wbcErrorString(err
)));
1309 for (i
=0; i
<num_sids
; i
++) {
1310 if (ids
[i
].type
== ID_TYPE_NOT_SPECIFIED
) {
1311 switch (wbc_ids
[num_not_cached
].type
) {
1312 case WBC_ID_TYPE_UID
:
1313 ids
[i
].type
= ID_TYPE_UID
;
1314 ids
[i
].id
= wbc_ids
[num_not_cached
].id
.uid
;
1316 case WBC_ID_TYPE_GID
:
1317 ids
[i
].type
= ID_TYPE_GID
;
1318 ids
[i
].id
= wbc_ids
[num_not_cached
].id
.gid
;
1321 /* The types match, and wbcUnixId -> id is a union anyway */
1322 ids
[i
].type
= (enum id_type
)wbc_ids
[num_not_cached
].type
;
1323 ids
[i
].id
= wbc_ids
[num_not_cached
].id
.gid
;
1326 num_not_cached
+= 1;
1330 for (i
=0; i
<num_sids
; i
++) {
1331 if (ids
[i
].type
!= ID_TYPE_NOT_SPECIFIED
) {
1334 if (legacy_sid_to_gid(&sids
[i
], &ids
[i
].id
)) {
1335 ids
[i
].type
= ID_TYPE_GID
;
1338 if (legacy_sid_to_uid(&sids
[i
], &ids
[i
].id
)) {
1339 ids
[i
].type
= ID_TYPE_UID
;
1344 for (i
=0; i
<num_sids
; i
++) {
1345 switch(ids
[i
].type
) {
1346 case WBC_ID_TYPE_GID
:
1347 case WBC_ID_TYPE_UID
:
1348 case WBC_ID_TYPE_BOTH
:
1349 if (ids
[i
].id
== -1) {
1350 ids
[i
].type
= ID_TYPE_NOT_SPECIFIED
;
1353 case WBC_ID_TYPE_NOT_SPECIFIED
:
1360 TALLOC_FREE(wbc_ids
);
1361 TALLOC_FREE(wbc_sids
);
1365 /*****************************************************************
1366 *THE CANONICAL* convert SID to uid function.
1367 *****************************************************************/
1369 bool sid_to_uid(const struct dom_sid
*psid
, uid_t
*puid
)
1371 bool expired
= true;
1375 /* Optimize for the Unix Users Domain
1376 * as the conversion is straightforward */
1377 if (sid_peek_check_rid(&global_sid_Unix_Users
, psid
, &rid
)) {
1381 /* return here, don't cache */
1382 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid
),
1383 (unsigned int)*puid
));
1387 /* Check the winbindd cache directly. */
1388 ret
= idmap_cache_find_sid2uid(psid
, puid
, &expired
);
1390 if (ret
&& !expired
&& (*puid
== (uid_t
)-1)) {
1392 * Negative cache entry, we already asked.
1395 return legacy_sid_to_uid(psid
, puid
);
1398 if (!ret
|| expired
) {
1399 /* Not in cache. Ask winbindd. */
1400 if (!winbind_sid_to_uid(puid
, psid
)) {
1401 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1402 sid_string_dbg(psid
)));
1403 /* winbind failed. do legacy */
1404 return legacy_sid_to_uid(psid
, puid
);
1408 /* TODO: Here would be the place to allocate both a gid and a uid for
1409 * the SID in question */
1411 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid
),
1412 (unsigned int)*puid
));
1417 /*****************************************************************
1418 *THE CANONICAL* convert SID to gid function.
1419 Group mapping is used for gids that maps to Wellknown SIDs
1420 *****************************************************************/
1422 bool sid_to_gid(const struct dom_sid
*psid
, gid_t
*pgid
)
1424 bool expired
= true;
1428 /* Optimize for the Unix Groups Domain
1429 * as the conversion is straightforward */
1430 if (sid_peek_check_rid(&global_sid_Unix_Groups
, psid
, &rid
)) {
1434 /* return here, don't cache */
1435 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid
),
1436 (unsigned int)*pgid
));
1440 /* Check the winbindd cache directly. */
1441 ret
= idmap_cache_find_sid2gid(psid
, pgid
, &expired
);
1443 if (ret
&& !expired
&& (*pgid
== (gid_t
)-1)) {
1445 * Negative cache entry, we already asked.
1448 return legacy_sid_to_gid(psid
, pgid
);
1451 if (!ret
|| expired
) {
1452 /* Not in cache or negative. Ask winbindd. */
1453 /* Ask winbindd if it can map this sid to a gid.
1454 * (Idmap will check it is a valid SID and of the right type) */
1456 if ( !winbind_sid_to_gid(pgid
, psid
) ) {
1458 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1459 sid_string_dbg(psid
)));
1460 /* winbind failed. do legacy */
1461 return legacy_sid_to_gid(psid
, pgid
);
1465 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid
),
1466 (unsigned int)*pgid
));
1472 * @brief This function gets the primary group SID mapping the primary
1473 * GID of the user as obtained by an actual getpwnam() call.
1474 * This is necessary to avoid issues with arbitrary group SIDs
1475 * stored in passdb. We try as hard as we can to get the SID
1476 * corresponding to the GID, including trying group mapping.
1477 * If nothing else works, we will force "Domain Users" as the
1479 * This is needed because we must always be able to lookup the
1480 * primary group SID, so we cannot settle for an arbitrary SID.
1482 * This call can be expensive. Use with moderation.
1483 * If you have a "samu" struct around use pdb_get_group_sid()
1484 * instead as it does properly cache results.
1486 * @param mem_ctx[in] The memory context iused to allocate the result.
1487 * @param username[in] The user's name
1488 * @param _pwd[in|out] If available, pass in user's passwd struct.
1489 * It will contain a tallocated passwd if NULL was
1491 * @param _group_sid[out] The user's Primary Group SID
1493 * @return NTSTATUS error code.
1495 NTSTATUS
get_primary_group_sid(TALLOC_CTX
*mem_ctx
,
1496 const char *username
,
1497 struct passwd
**_pwd
,
1498 struct dom_sid
**_group_sid
)
1500 TALLOC_CTX
*tmp_ctx
;
1501 bool need_lookup_sid
= false;
1502 struct dom_sid
*group_sid
;
1503 struct passwd
*pwd
= *_pwd
;
1505 tmp_ctx
= talloc_new(mem_ctx
);
1507 return NT_STATUS_NO_MEMORY
;
1511 pwd
= Get_Pwnam_alloc(mem_ctx
, username
);
1513 DEBUG(0, ("Failed to find a Unix account for %s",
1515 TALLOC_FREE(tmp_ctx
);
1516 return NT_STATUS_NO_SUCH_USER
;
1520 group_sid
= talloc_zero(mem_ctx
, struct dom_sid
);
1522 TALLOC_FREE(tmp_ctx
);
1523 return NT_STATUS_NO_MEMORY
;
1526 gid_to_sid(group_sid
, pwd
->pw_gid
);
1527 if (!is_null_sid(group_sid
)) {
1528 struct dom_sid domain_sid
;
1531 /* We need a sid within our domain */
1532 sid_copy(&domain_sid
, group_sid
);
1533 sid_split_rid(&domain_sid
, &rid
);
1534 if (dom_sid_equal(&domain_sid
, get_global_sam_sid())) {
1536 * As shortcut for the expensive lookup_sid call
1537 * compare the domain sid part
1540 case DOMAIN_RID_ADMINS
:
1541 case DOMAIN_RID_USERS
:
1544 need_lookup_sid
= true;
1548 /* Try group mapping */
1549 ZERO_STRUCTP(group_sid
);
1550 if (pdb_gid_to_sid(pwd
->pw_gid
, group_sid
)) {
1551 need_lookup_sid
= true;
1556 /* We must verify that this is a valid SID that resolves to a
1557 * group of the correct type */
1558 if (need_lookup_sid
) {
1559 enum lsa_SidType type
= SID_NAME_UNKNOWN
;
1562 DEBUG(10, ("do lookup_sid(%s) for group of user %s\n",
1563 sid_string_dbg(group_sid
), username
));
1565 /* Now check that it's actually a domain group and
1566 * not something else */
1567 lookup_ret
= lookup_sid(tmp_ctx
, group_sid
,
1570 if (lookup_ret
&& (type
== SID_NAME_DOM_GRP
)) {
1574 DEBUG(3, ("Primary group %s for user %s is"
1575 " a %s and not a domain group\n",
1576 sid_string_dbg(group_sid
), username
,
1577 sid_type_lookup(type
)));
1580 /* Everything else, failed.
1581 * Just set it to the 'Domain Users' RID of 513 which will
1582 always resolve to a name */
1583 DEBUG(3, ("Forcing Primary Group to 'Domain Users' for %s\n",
1586 sid_compose(group_sid
, get_global_sam_sid(), DOMAIN_RID_USERS
);
1589 *_pwd
= talloc_move(mem_ctx
, &pwd
);
1590 *_group_sid
= talloc_move(mem_ctx
, &group_sid
);
1591 TALLOC_FREE(tmp_ctx
);
1592 return NT_STATUS_OK
;