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 "lib/util_unixsids.h"
25 #include "../librpc/gen_ndr/ndr_security.h"
27 #include "../lib/util/memcache.h"
28 #include "idmap_cache.h"
29 #include "../libcli/security/security.h"
30 #include "lib/winbind_util.h"
31 #include "../librpc/gen_ndr/idmap.h"
32 #include "lib/util/bitmap.h"
34 static bool lookup_unix_user_name(const char *name
, struct dom_sid
*sid
)
39 pwd
= Get_Pwnam_alloc(talloc_tos(), name
);
45 * For 64-bit uid's we have enough space in the whole SID,
46 * should they become necessary
48 ret
= sid_compose(sid
, &global_sid_Unix_Users
, pwd
->pw_uid
);
53 static bool lookup_unix_group_name(const char *name
, struct dom_sid
*sid
)
63 * For 64-bit gid's we have enough space in the whole SID,
64 * should they become necessary
66 return sid_compose(sid
, &global_sid_Unix_Groups
, grp
->gr_gid
);
69 /*****************************************************************
70 Dissect a user-provided name into domain, name, sid and type.
72 If an explicit domain name was given in the form domain\user, it
73 has to try that. If no explicit domain name was given, we have
75 *****************************************************************/
77 static NTSTATUS
lookup_name_internal(TALLOC_CTX
*mem_ctx
,
78 const char *full_name
,
80 const char **ret_domain
,
81 const char **ret_name
,
82 struct dom_sid
*ret_sid
,
83 enum lsa_SidType
*ret_type
)
87 const char *domain
= NULL
;
88 const char *name
= NULL
;
91 enum lsa_SidType type
;
92 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
95 if (tmp_ctx
== NULL
) {
96 DEBUG(0, ("talloc_new failed\n"));
97 return NT_STATUS_NO_MEMORY
;
100 p
= strchr_m(full_name
, '\\');
103 domain
= talloc_strndup(tmp_ctx
, full_name
,
104 PTR_DIFF(p
, full_name
));
105 name
= talloc_strdup(tmp_ctx
, p
+1);
107 char *q
= strchr_m(full_name
, '@');
109 /* Set the domain for UPNs */
111 name
= talloc_strndup(tmp_ctx
,
113 PTR_DIFF(q
, full_name
));
114 domain
= talloc_strdup(tmp_ctx
, q
+ 1);
116 domain
= talloc_strdup(tmp_ctx
, "");
117 name
= talloc_strdup(tmp_ctx
, full_name
);
121 if ((domain
== NULL
) || (name
== NULL
)) {
122 DEBUG(0, ("talloc failed\n"));
123 TALLOC_FREE(tmp_ctx
);
124 return NT_STATUS_NO_MEMORY
;
127 DEBUG(10,("lookup_name: %s => domain=[%s], name=[%s]\n",
128 full_name
, domain
, name
));
129 DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags
));
131 if ((flags
& LOOKUP_NAME_DOMAIN
) || (flags
== 0)) {
132 bool check_global_sam
= false;
134 check_global_sam
= strequal(domain
, get_global_sam_name());
136 /* If we are running on a DC that has PASSDB module with domain
137 * information, check if DNS forest name is matching the domain
138 * name. This is the case of IPA domain controller when
139 * trusted AD DC looks up users found in a Global Catalog of
140 * the forest root domain. */
141 if (!check_global_sam
&& (IS_DC
)) {
142 struct pdb_domain_info
*dom_info
= NULL
;
143 dom_info
= pdb_get_domain_info(tmp_ctx
);
145 if ((dom_info
!= NULL
) && (dom_info
->dns_forest
!= NULL
)) {
146 check_global_sam
= strequal(domain
, dom_info
->dns_forest
);
149 TALLOC_FREE(dom_info
);
152 if (check_global_sam
) {
153 /* It's our own domain, lookup the name in passdb */
154 if (lookup_global_sam_name(name
, flags
, &rid
, &type
)) {
155 sid_compose(&sid
, get_global_sam_sid(), rid
);
158 TALLOC_FREE(tmp_ctx
);
159 *ret_type
= SID_NAME_UNKNOWN
;
164 if ((flags
& LOOKUP_NAME_BUILTIN
) &&
165 strequal(domain
, builtin_domain_name()))
167 if (strlen(name
) == 0) {
168 /* Swap domain and name */
169 tmp
= name
; name
= domain
; domain
= tmp
;
170 sid_copy(&sid
, &global_sid_Builtin
);
171 type
= SID_NAME_DOMAIN
;
175 /* Explicit request for a name in BUILTIN */
176 if (lookup_builtin_name(name
, &rid
)) {
177 sid_compose(&sid
, &global_sid_Builtin
, rid
);
178 type
= SID_NAME_ALIAS
;
181 TALLOC_FREE(tmp_ctx
);
182 *ret_type
= SID_NAME_UNKNOWN
;
186 /* Try the explicit winbind lookup first, don't let it guess the
187 * domain yet at this point yet. This comes later. */
189 if ((domain
[0] != '\0') &&
190 (flags
& ~(LOOKUP_NAME_DOMAIN
|LOOKUP_NAME_ISOLATED
)))
192 status
= winbind_lookup_name_ex(domain
, name
, &sid
, &type
);
193 if (!NT_STATUS_IS_OK(status
)) {
196 if (type
!= SID_NAME_UNKNOWN
) {
201 if (((flags
& (LOOKUP_NAME_NO_NSS
|LOOKUP_NAME_GROUP
)) == 0)
202 && strequal(domain
, unix_users_domain_name())) {
203 if (lookup_unix_user_name(name
, &sid
)) {
204 type
= SID_NAME_USER
;
207 TALLOC_FREE(tmp_ctx
);
208 *ret_type
= SID_NAME_UNKNOWN
;
212 if (((flags
& LOOKUP_NAME_NO_NSS
) == 0)
213 && strequal(domain
, unix_groups_domain_name())) {
214 if (lookup_unix_group_name(name
, &sid
)) {
215 type
= SID_NAME_DOM_GRP
;
218 TALLOC_FREE(tmp_ctx
);
219 *ret_type
= SID_NAME_UNKNOWN
;
224 * Finally check for a well known domain name ("NT Authority"),
225 * this is being taken care of in lookup_wellknown_name().
227 if ((domain
[0] != '\0') &&
228 (flags
& LOOKUP_NAME_WKN
) &&
229 lookup_wellknown_name(tmp_ctx
, name
, &sid
, &domain
))
231 type
= SID_NAME_WKN_GRP
;
236 * If we're told not to look up 'isolated' names then we're
239 if (!(flags
& LOOKUP_NAME_ISOLATED
)) {
240 TALLOC_FREE(tmp_ctx
);
241 *ret_type
= SID_NAME_UNKNOWN
;
246 * No domain names beyond this point
248 if (domain
[0] != '\0') {
249 TALLOC_FREE(tmp_ctx
);
250 *ret_type
= SID_NAME_UNKNOWN
;
254 /* Now the guesswork begins, we haven't been given an explicit
255 * domain. Try the sequence as documented on
256 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
257 * November 27, 2005 */
259 /* 1. well-known names */
262 * Check for well known names without a domain name.
263 * e.g. \Creator Owner.
266 if ((flags
& LOOKUP_NAME_WKN
) &&
267 lookup_wellknown_name(tmp_ctx
, name
, &sid
, &domain
))
269 type
= SID_NAME_WKN_GRP
;
273 /* 2. Builtin domain as such */
275 if ((flags
& (LOOKUP_NAME_BUILTIN
|LOOKUP_NAME_REMOTE
)) &&
276 strequal(name
, builtin_domain_name()))
278 /* Swap domain and name */
279 tmp
= name
; name
= domain
; domain
= tmp
;
280 sid_copy(&sid
, &global_sid_Builtin
);
281 type
= SID_NAME_DOMAIN
;
285 /* 3. Account domain */
287 if ((flags
& LOOKUP_NAME_DOMAIN
) &&
288 strequal(name
, get_global_sam_name()))
290 if (!secrets_fetch_domain_sid(name
, &sid
)) {
291 DEBUG(3, ("Could not fetch my SID\n"));
292 TALLOC_FREE(tmp_ctx
);
293 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
295 /* Swap domain and name */
296 tmp
= name
; name
= domain
; domain
= tmp
;
297 type
= SID_NAME_DOMAIN
;
301 /* 4. Primary domain */
303 if ((flags
& LOOKUP_NAME_DOMAIN
) && !IS_DC
&&
304 strequal(name
, lp_workgroup()))
306 if (!secrets_fetch_domain_sid(name
, &sid
)) {
307 DEBUG(3, ("Could not fetch the domain SID\n"));
308 TALLOC_FREE(tmp_ctx
);
309 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
311 /* Swap domain and name */
312 tmp
= name
; name
= domain
; domain
= tmp
;
313 type
= SID_NAME_DOMAIN
;
317 /* 5. Trusted domains as such, to me it looks as if members don't do
318 this, tested an XP workstation in a NT domain -- vl */
320 if ((flags
& LOOKUP_NAME_REMOTE
) && IS_DC
&&
321 (pdb_get_trusteddom_pw(name
, NULL
, &sid
, NULL
)))
323 /* Swap domain and name */
324 tmp
= name
; name
= domain
; domain
= tmp
;
325 type
= SID_NAME_DOMAIN
;
329 /* 6. Builtin aliases */
331 if ((flags
& LOOKUP_NAME_BUILTIN
) &&
332 lookup_builtin_name(name
, &rid
))
334 domain
= talloc_strdup(tmp_ctx
, builtin_domain_name());
335 sid_compose(&sid
, &global_sid_Builtin
, rid
);
336 type
= SID_NAME_ALIAS
;
340 /* 7. Local systems' SAM (DCs don't have a local SAM) */
341 /* 8. Primary SAM (On members, this is the domain) */
343 /* Both cases are done by looking at our passdb */
345 if ((flags
& LOOKUP_NAME_DOMAIN
) &&
346 lookup_global_sam_name(name
, flags
, &rid
, &type
))
348 domain
= talloc_strdup(tmp_ctx
, get_global_sam_name());
349 sid_compose(&sid
, get_global_sam_sid(), rid
);
353 /* Now our local possibilities are exhausted. */
355 if (!(flags
& LOOKUP_NAME_REMOTE
)) {
356 TALLOC_FREE(tmp_ctx
);
357 *ret_type
= SID_NAME_UNKNOWN
;
361 /* If we are not a DC, we have to ask in our primary domain. Let
362 * winbind do that. */
365 status
= winbind_lookup_name_ex(lp_workgroup(), name
, &sid
, &type
);
366 if (!NT_STATUS_IS_OK(status
)) {
369 if (type
!= SID_NAME_UNKNOWN
) {
374 /* 9. Trusted domains */
376 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
377 * that (yet), but give it a chance. */
380 struct dom_sid dom_sid
;
381 enum lsa_SidType domain_type
;
383 status
= winbind_lookup_name_ex("", name
, &sid
, &type
);
384 if (!NT_STATUS_IS_OK(status
)) {
387 if (type
!= SID_NAME_UNKNOWN
) {
388 if (type
== SID_NAME_DOMAIN
) {
389 /* Swap name and type */
390 tmp
= name
; name
= domain
; domain
= tmp
;
394 /* Here we have to cope with a little deficiency
395 * in the winbind API: We have to ask it again
396 * for the name of the domain it figured out
397 * itself. Maybe fix that later... */
399 sid_copy(&dom_sid
, &sid
);
400 sid_split_rid(&dom_sid
, NULL
);
402 if (!winbind_lookup_sid(tmp_ctx
, &dom_sid
,
405 (domain_type
!= SID_NAME_DOMAIN
))
407 DBG_INFO("winbind could not find the "
408 "domain's name it just looked "
410 TALLOC_FREE(tmp_ctx
);
411 *ret_type
= SID_NAME_UNKNOWN
;
418 /* 10. Don't translate */
420 /* 11. Ok, windows would end here. Samba has two more options:
421 Unmapped users and unmapped groups */
423 if (((flags
& (LOOKUP_NAME_NO_NSS
|LOOKUP_NAME_GROUP
)) == 0)
424 && lookup_unix_user_name(name
, &sid
)) {
425 domain
= talloc_strdup(tmp_ctx
, unix_users_domain_name());
426 type
= SID_NAME_USER
;
430 if (((flags
& LOOKUP_NAME_NO_NSS
) == 0)
431 && lookup_unix_group_name(name
, &sid
)) {
432 domain
= talloc_strdup(tmp_ctx
, unix_groups_domain_name());
433 type
= SID_NAME_DOM_GRP
;
438 * Ok, all possibilities tried. Fail.
441 TALLOC_FREE(tmp_ctx
);
442 *ret_type
= SID_NAME_UNKNOWN
;
446 if ((domain
== NULL
) || (name
== NULL
)) {
447 DEBUG(0, ("talloc failed\n"));
448 TALLOC_FREE(tmp_ctx
);
449 return NT_STATUS_NO_MEMORY
;
453 * Hand over the results to the talloc context we've been given.
456 if ((ret_name
!= NULL
) &&
457 !(*ret_name
= talloc_strdup(mem_ctx
, name
))) {
458 DEBUG(0, ("talloc failed\n"));
459 TALLOC_FREE(tmp_ctx
);
460 return NT_STATUS_NO_MEMORY
;
463 if (ret_domain
!= NULL
) {
465 if (!(tmp_dom
= talloc_strdup(mem_ctx
, domain
))) {
466 DEBUG(0, ("talloc failed\n"));
467 TALLOC_FREE(tmp_ctx
);
468 return NT_STATUS_NO_MEMORY
;
470 if (!strupper_m(tmp_dom
)) {
471 TALLOC_FREE(tmp_ctx
);
472 return NT_STATUS_INTERNAL_ERROR
;
474 *ret_domain
= tmp_dom
;
477 if (ret_sid
!= NULL
) {
478 sid_copy(ret_sid
, &sid
);
483 TALLOC_FREE(tmp_ctx
);
487 bool lookup_name(TALLOC_CTX
*mem_ctx
,
488 const char *full_name
,
490 const char **ret_domain
,
491 const char **ret_name
,
492 struct dom_sid
*ret_sid
,
493 enum lsa_SidType
*ret_type
)
495 enum lsa_SidType type
;
498 status
= lookup_name_internal(mem_ctx
,
505 if (!NT_STATUS_IS_OK(status
)) {
508 if (ret_type
!= NULL
) {
511 if (type
== SID_NAME_UNKNOWN
) {
517 /************************************************************************
518 Names from smb.conf can be unqualified. eg. valid users = foo
519 These names should never map to a remote name. Try global_sam_name()\foo,
520 and then "Unix Users"\foo (or "Unix Groups"\foo).
521 ************************************************************************/
523 NTSTATUS
lookup_name_smbconf_ex(TALLOC_CTX
*mem_ctx
,
524 const char *full_name
,
526 const char **ret_domain
,
527 const char **ret_name
,
528 struct dom_sid
*ret_sid
,
529 enum lsa_SidType
*ret_type
)
531 char *qualified_name
= NULL
;
532 const char *p
= strchr_m(full_name
, *lp_winbind_separator());
533 bool is_qualified
= p
!= NULL
|| strchr_m(full_name
, '@') != NULL
;
536 /* For DOMAIN\user or user@REALM directly call lookup_name(). */
539 /* The name is already qualified with a domain. */
541 if (p
!= NULL
&& *lp_winbind_separator() != '\\') {
542 /* lookup_name() needs '\\' as a separator */
544 qualified_name
= talloc_strdup(mem_ctx
, full_name
);
545 if (qualified_name
== NULL
) {
546 return NT_STATUS_NO_MEMORY
;
548 qualified_name
[p
- full_name
] = '\\';
549 full_name
= qualified_name
;
552 return lookup_name_internal(mem_ctx
,
561 /* Try with winbind default domain name. */
562 if (lp_winbind_use_default_domain()) {
563 qualified_name
= talloc_asprintf(mem_ctx
,
567 if (qualified_name
== NULL
) {
568 return NT_STATUS_NO_MEMORY
;
571 status
= lookup_name_internal(mem_ctx
,
578 if (NT_STATUS_IS_OK(status
) &&
579 *ret_type
!= SID_NAME_UNKNOWN
)
585 /* Try with our own SAM name. */
586 qualified_name
= talloc_asprintf(mem_ctx
, "%s\\%s",
587 get_global_sam_name(),
589 if (!qualified_name
) {
590 return NT_STATUS_NO_MEMORY
;
593 status
= lookup_name_internal(mem_ctx
,
600 if (NT_STATUS_IS_OK(status
) &&
601 *ret_type
!= SID_NAME_UNKNOWN
)
606 /* Finally try with "Unix Users" or "Unix Group" */
607 qualified_name
= talloc_asprintf(mem_ctx
, "%s\\%s",
608 flags
& LOOKUP_NAME_GROUP
?
609 unix_groups_domain_name() :
610 unix_users_domain_name(),
612 if (!qualified_name
) {
613 return NT_STATUS_NO_MEMORY
;
616 return lookup_name_internal(mem_ctx
,
625 bool lookup_name_smbconf(TALLOC_CTX
*mem_ctx
,
626 const char *full_name
, int flags
,
627 const char **ret_domain
, const char **ret_name
,
628 struct dom_sid
*ret_sid
, enum lsa_SidType
*ret_type
)
630 enum lsa_SidType type
;
633 status
= lookup_name_smbconf_ex(mem_ctx
,
640 if (!NT_STATUS_IS_OK(status
)) {
643 if (ret_type
!= NULL
) {
646 if (type
== SID_NAME_UNKNOWN
) {
652 static bool wb_lookup_rids(TALLOC_CTX
*mem_ctx
,
653 const struct dom_sid
*domain_sid
,
654 int num_rids
, uint32_t *rids
,
655 const char **domain_name
,
656 const char **names
, enum lsa_SidType
*types
)
659 const char **my_names
;
660 enum lsa_SidType
*my_types
;
663 if (!(tmp_ctx
= talloc_init("wb_lookup_rids"))) {
667 if (!winbind_lookup_rids(tmp_ctx
, domain_sid
, num_rids
, rids
,
668 domain_name
, &my_names
, &my_types
)) {
670 for (i
=0; i
<num_rids
; i
++) {
672 types
[i
] = SID_NAME_UNKNOWN
;
674 TALLOC_FREE(tmp_ctx
);
678 if (!(*domain_name
= talloc_strdup(mem_ctx
, *domain_name
))) {
679 TALLOC_FREE(tmp_ctx
);
684 * winbind_lookup_rids allocates its own array. We've been given the
685 * array, so copy it over
688 for (i
=0; i
<num_rids
; i
++) {
689 if (my_names
[i
] == NULL
) {
690 TALLOC_FREE(tmp_ctx
);
693 if (!(names
[i
] = talloc_strdup(names
, my_names
[i
]))) {
694 TALLOC_FREE(tmp_ctx
);
697 types
[i
] = my_types
[i
];
699 TALLOC_FREE(tmp_ctx
);
703 static bool lookup_rids(TALLOC_CTX
*mem_ctx
, const struct dom_sid
*domain_sid
,
704 int num_rids
, uint32_t *rids
,
705 const char **domain_name
,
706 const char ***names
, enum lsa_SidType
**types
)
709 struct dom_sid_buf buf
;
711 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
712 dom_sid_str_buf(domain_sid
, &buf
)));
715 *names
= talloc_zero_array(mem_ctx
, const char *, num_rids
);
716 *types
= talloc_array(mem_ctx
, enum lsa_SidType
, num_rids
);
718 if ((*names
== NULL
) || (*types
== NULL
)) {
722 for (i
= 0; i
< num_rids
; i
++)
723 (*types
)[i
] = SID_NAME_UNKNOWN
;
729 if (sid_check_is_our_sam(domain_sid
)) {
732 if (*domain_name
== NULL
) {
733 *domain_name
= talloc_strdup(
734 mem_ctx
, get_global_sam_name());
737 if (*domain_name
== NULL
) {
742 result
= pdb_lookup_rids(domain_sid
, num_rids
, rids
,
746 return (NT_STATUS_IS_OK(result
) ||
747 NT_STATUS_EQUAL(result
, NT_STATUS_NONE_MAPPED
) ||
748 NT_STATUS_EQUAL(result
, STATUS_SOME_UNMAPPED
));
751 if (sid_check_is_builtin(domain_sid
)) {
753 if (*domain_name
== NULL
) {
754 *domain_name
= talloc_strdup(
755 mem_ctx
, builtin_domain_name());
758 if (*domain_name
== NULL
) {
762 for (i
=0; i
<num_rids
; i
++) {
763 if (lookup_builtin_rid(*names
, rids
[i
],
765 if ((*names
)[i
] == NULL
) {
768 (*types
)[i
] = SID_NAME_ALIAS
;
770 (*types
)[i
] = SID_NAME_UNKNOWN
;
776 if (sid_check_is_wellknown_domain(domain_sid
, NULL
)) {
777 for (i
=0; i
<num_rids
; i
++) {
779 sid_compose(&sid
, domain_sid
, rids
[i
]);
780 if (lookup_wellknown_sid(mem_ctx
, &sid
,
781 domain_name
, &(*names
)[i
])) {
782 if ((*names
)[i
] == NULL
) {
785 (*types
)[i
] = SID_NAME_WKN_GRP
;
787 (*types
)[i
] = SID_NAME_UNKNOWN
;
793 if (sid_check_is_unix_users(domain_sid
)) {
794 if (*domain_name
== NULL
) {
795 *domain_name
= talloc_strdup(
796 mem_ctx
, unix_users_domain_name());
797 if (*domain_name
== NULL
) {
801 for (i
=0; i
<num_rids
; i
++) {
802 (*names
)[i
] = talloc_strdup(
803 (*names
), uidtoname(rids
[i
]));
804 if ((*names
)[i
] == NULL
) {
807 (*types
)[i
] = SID_NAME_USER
;
812 if (sid_check_is_unix_groups(domain_sid
)) {
813 if (*domain_name
== NULL
) {
814 *domain_name
= talloc_strdup(
815 mem_ctx
, unix_groups_domain_name());
816 if (*domain_name
== NULL
) {
820 for (i
=0; i
<num_rids
; i
++) {
821 (*names
)[i
] = talloc_strdup(
822 (*names
), gidtoname(rids
[i
]));
823 if ((*names
)[i
] == NULL
) {
826 (*types
)[i
] = SID_NAME_DOM_GRP
;
831 return wb_lookup_rids(mem_ctx
, domain_sid
, num_rids
, rids
,
832 domain_name
, *names
, *types
);
836 * Is the SID a domain as such? If yes, lookup its name.
839 static bool lookup_as_domain(const struct dom_sid
*sid
, TALLOC_CTX
*mem_ctx
,
843 enum lsa_SidType type
;
845 if (sid_check_is_our_sam(sid
)) {
846 *name
= talloc_strdup(mem_ctx
, get_global_sam_name());
850 if (sid_check_is_builtin(sid
)) {
851 *name
= talloc_strdup(mem_ctx
, builtin_domain_name());
855 if (sid_check_is_wellknown_domain(sid
, &tmp
)) {
856 *name
= talloc_strdup(mem_ctx
, tmp
);
860 if (sid_check_is_unix_users(sid
)) {
861 *name
= talloc_strdup(mem_ctx
, unix_users_domain_name());
865 if (sid_check_is_unix_groups(sid
)) {
866 *name
= talloc_strdup(mem_ctx
, unix_groups_domain_name());
870 if (sid
->num_auths
!= 4) {
871 /* This can't be a domain */
876 uint32_t i
, num_domains
;
877 struct trustdom_info
**domains
;
879 /* This is relatively expensive, but it happens only on DCs
880 * and for SIDs that have 4 sub-authorities and thus look like
883 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx
,
889 for (i
=0; i
<num_domains
; i
++) {
890 if (dom_sid_equal(sid
, &domains
[i
]->sid
)) {
891 *name
= talloc_strdup(mem_ctx
,
899 if (winbind_lookup_sid(mem_ctx
, sid
, &tmp
, NULL
, &type
) &&
900 (type
== SID_NAME_DOMAIN
)) {
909 * This tries to implement the rather weird rules for the lsa_lookup level
912 * This is as close as we can get to what W2k3 does. With this we survive the
913 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
914 * different, but I assume that's just being too liberal. For example, W2k3
915 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
916 * whereas NT4 does the same as level 1 (I think). I did not fully test that
917 * with NT4, this is what w2k3 does.
919 * Level 1: Ask everywhere
920 * Level 2: Ask domain and trusted domains, no builtin and wkn
921 * Level 3: Only ask domain
922 * Level 4: W2k3ad: Only ask AD trusts
923 * Level 5: Only ask transitive forest trusts
927 static bool check_dom_sid_to_level(const struct dom_sid
*sid
, int level
)
929 struct dom_sid_buf buf
;
937 ret
= (!sid_check_is_builtin(sid
) &&
938 !sid_check_is_wellknown_domain(sid
, NULL
));
943 ret
= sid_check_is_our_sam(sid
);
950 DEBUG(10, ("%s SID %s in level %d\n",
951 ret
? "Accepting" : "Rejecting",
952 dom_sid_str_buf(sid
, &buf
),
958 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
959 * references to domains, it is explicitly made for this.
961 * This attempts to be as efficient as possible: It collects all SIDs
962 * belonging to a domain and hands them in bulk to the appropriate lookup
963 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
964 * *hugely* from this.
967 NTSTATUS
lookup_sids(TALLOC_CTX
*mem_ctx
, int num_sids
,
968 const struct dom_sid
**sids
, int level
,
969 struct lsa_dom_info
**ret_domains
,
970 struct lsa_name_info
**ret_names
)
974 struct lsa_name_info
*name_infos
;
975 struct lsa_dom_info
*dom_infos
= NULL
;
979 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
980 DEBUG(0, ("talloc_new failed\n"));
981 return NT_STATUS_NO_MEMORY
;
985 name_infos
= talloc_array(mem_ctx
, struct lsa_name_info
, num_sids
);
986 if (name_infos
== NULL
) {
987 result
= NT_STATUS_NO_MEMORY
;
994 dom_infos
= talloc_zero_array(mem_ctx
, struct lsa_dom_info
,
995 LSA_REF_DOMAIN_LIST_MULTIPLIER
);
996 if (dom_infos
== NULL
) {
997 result
= NT_STATUS_NO_MEMORY
;
1001 /* First build up the data structures:
1003 * dom_infos is a list of domains referenced in the list of
1004 * SIDs. Later we will walk the list of domains and look up the RIDs
1007 * name_infos is a shadow-copy of the SIDs array to collect the real
1010 * dom_info->idxs is an index into the name_infos array. The
1011 * difficulty we have here is that we need to keep the SIDs the client
1012 * asked for in the same order for the reply
1015 for (i
=0; i
<num_sids
; i
++) {
1018 const char *domain_name
= NULL
;
1020 sid_copy(&sid
, sids
[i
]);
1021 name_infos
[i
].type
= SID_NAME_USE_NONE
;
1023 if (lookup_as_domain(&sid
, name_infos
, &domain_name
)) {
1024 /* We can't push that through the normal lookup
1025 * process, as this would reference illegal
1028 * For example S-1-5-32 would end up referencing
1029 * domain S-1-5- with RID 32 which is clearly wrong.
1031 if (domain_name
== NULL
) {
1032 result
= NT_STATUS_NO_MEMORY
;
1036 name_infos
[i
].rid
= 0;
1037 name_infos
[i
].type
= SID_NAME_DOMAIN
;
1038 name_infos
[i
].name
= NULL
;
1040 if (sid_check_is_builtin(&sid
)) {
1041 /* Yes, W2k3 returns "BUILTIN" both as domain
1043 name_infos
[i
].name
= talloc_strdup(
1044 name_infos
, builtin_domain_name());
1045 if (name_infos
[i
].name
== NULL
) {
1046 result
= NT_STATUS_NO_MEMORY
;
1051 /* This is a normal SID with rid component */
1052 if (!sid_split_rid(&sid
, &rid
)) {
1053 result
= NT_STATUS_INVALID_SID
;
1058 if (!check_dom_sid_to_level(&sid
, level
)) {
1059 name_infos
[i
].rid
= 0;
1060 name_infos
[i
].type
= SID_NAME_UNKNOWN
;
1061 name_infos
[i
].name
= NULL
;
1065 for (j
=0; j
<LSA_REF_DOMAIN_LIST_MULTIPLIER
; j
++) {
1066 if (!dom_infos
[j
].valid
) {
1069 if (dom_sid_equal(&sid
, &dom_infos
[j
].sid
)) {
1074 if (j
== LSA_REF_DOMAIN_LIST_MULTIPLIER
) {
1075 /* TODO: What's the right error message here? */
1076 result
= NT_STATUS_NONE_MAPPED
;
1080 if (!dom_infos
[j
].valid
) {
1081 /* We found a domain not yet referenced, create a new
1083 dom_infos
[j
].valid
= true;
1084 sid_copy(&dom_infos
[j
].sid
, &sid
);
1086 if (domain_name
!= NULL
) {
1087 /* This name was being found above in the case
1088 * when we found a domain SID */
1090 talloc_strdup(dom_infos
, domain_name
);
1091 if (dom_infos
[j
].name
== NULL
) {
1092 result
= NT_STATUS_NO_MEMORY
;
1096 /* lookup_rids will take care of this */
1097 dom_infos
[j
].name
= NULL
;
1101 name_infos
[i
].dom_idx
= j
;
1103 if (name_infos
[i
].type
== SID_NAME_USE_NONE
) {
1104 name_infos
[i
].rid
= rid
;
1106 ADD_TO_ARRAY(dom_infos
, int, i
, &dom_infos
[j
].idxs
,
1107 &dom_infos
[j
].num_idxs
);
1109 if (dom_infos
[j
].idxs
== NULL
) {
1110 result
= NT_STATUS_NO_MEMORY
;
1116 /* Iterate over the domains found */
1118 for (i
=0; i
<LSA_REF_DOMAIN_LIST_MULTIPLIER
; i
++) {
1120 const char *domain_name
= NULL
;
1122 enum lsa_SidType
*types
;
1123 struct lsa_dom_info
*dom
= &dom_infos
[i
];
1126 /* No domains left, we're done */
1130 if (dom
->num_idxs
== 0) {
1132 * This happens only if the only sid related to
1133 * this domain is the domain sid itself, which
1134 * is mapped to SID_NAME_DOMAIN above.
1139 if (!(rids
= talloc_array(tmp_ctx
, uint32_t, dom
->num_idxs
))) {
1140 result
= NT_STATUS_NO_MEMORY
;
1144 for (j
=0; j
<dom
->num_idxs
; j
++) {
1145 rids
[j
] = name_infos
[dom
->idxs
[j
]].rid
;
1148 if (!lookup_rids(tmp_ctx
, &dom
->sid
,
1149 dom
->num_idxs
, rids
, &domain_name
,
1151 result
= NT_STATUS_NO_MEMORY
;
1155 if (!(dom
->name
= talloc_strdup(dom_infos
, domain_name
))) {
1156 result
= NT_STATUS_NO_MEMORY
;
1160 for (j
=0; j
<dom
->num_idxs
; j
++) {
1161 int idx
= dom
->idxs
[j
];
1162 name_infos
[idx
].type
= types
[j
];
1163 if (types
[j
] != SID_NAME_UNKNOWN
) {
1164 name_infos
[idx
].name
=
1165 talloc_strdup(name_infos
, names
[j
]);
1166 if (name_infos
[idx
].name
== NULL
) {
1167 result
= NT_STATUS_NO_MEMORY
;
1171 name_infos
[idx
].name
= NULL
;
1176 *ret_domains
= dom_infos
;
1177 *ret_names
= name_infos
;
1178 TALLOC_FREE(tmp_ctx
);
1179 return NT_STATUS_OK
;
1182 TALLOC_FREE(dom_infos
);
1183 TALLOC_FREE(name_infos
);
1184 TALLOC_FREE(tmp_ctx
);
1188 /*****************************************************************
1189 *THE CANONICAL* convert SID to name function.
1190 *****************************************************************/
1192 bool lookup_sid(TALLOC_CTX
*mem_ctx
, const struct dom_sid
*sid
,
1193 const char **ret_domain
, const char **ret_name
,
1194 enum lsa_SidType
*ret_type
)
1196 struct lsa_dom_info
*domain
;
1197 struct lsa_name_info
*name
;
1198 struct dom_sid_buf buf
;
1199 TALLOC_CTX
*tmp_ctx
;
1202 DEBUG(10, ("lookup_sid called for SID '%s'\n",
1203 dom_sid_str_buf(sid
, &buf
)));
1205 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
1206 DEBUG(0, ("talloc_new failed\n"));
1210 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx
, 1, &sid
, 1,
1215 if (name
->type
== SID_NAME_UNKNOWN
) {
1219 if ((ret_domain
!= NULL
) &&
1220 !(*ret_domain
= talloc_strdup(mem_ctx
, domain
->name
))) {
1224 if ((ret_name
!= NULL
) &&
1225 !(*ret_name
= talloc_strdup(mem_ctx
, name
->name
))) {
1229 if (ret_type
!= NULL
) {
1230 *ret_type
= name
->type
;
1237 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
1238 dom_sid_str_buf(sid
, &buf
),
1239 domain
->name
, name
->name
, name
->type
));
1241 DEBUG(10, ("failed to lookup sid %s\n",
1242 dom_sid_str_buf(sid
, &buf
)));
1244 TALLOC_FREE(tmp_ctx
);
1248 /*****************************************************************
1249 *THE LEGACY* convert SID to id function.
1250 *****************************************************************/
1252 static bool legacy_sid_to_unixid(const struct dom_sid
*psid
, struct unixid
*id
)
1257 ret
= pdb_sid_to_id(psid
, id
);
1261 struct dom_sid_buf buf
;
1262 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1263 dom_sid_str_buf(psid
, &buf
)));
1270 static bool legacy_sid_to_gid(const struct dom_sid
*psid
, gid_t
*pgid
)
1273 if (!legacy_sid_to_unixid(psid
, &id
)) {
1276 if (id
.type
== ID_TYPE_GID
|| id
.type
== ID_TYPE_BOTH
) {
1283 static bool legacy_sid_to_uid(const struct dom_sid
*psid
, uid_t
*puid
)
1286 if (!legacy_sid_to_unixid(psid
, &id
)) {
1289 if (id
.type
== ID_TYPE_UID
|| id
.type
== ID_TYPE_BOTH
) {
1296 void xid_to_sid(struct dom_sid
*psid
, const struct unixid
*xid
)
1298 bool expired
= true;
1300 struct dom_sid_buf buf
;
1302 SMB_ASSERT(xid
->type
== ID_TYPE_UID
|| xid
->type
== ID_TYPE_GID
);
1304 *psid
= (struct dom_sid
) {0};
1306 ret
= idmap_cache_find_xid2sid(xid
, psid
, &expired
);
1307 if (ret
&& !expired
) {
1308 DBG_DEBUG("%cID %"PRIu32
" -> %s from cache\n",
1309 xid
->type
== ID_TYPE_UID
? 'U' : 'G',
1311 dom_sid_str_buf(psid
, &buf
));
1315 ret
= winbind_xid_to_sid(psid
, xid
);
1318 * winbind can return an explicit negative mapping
1319 * here. It's up to winbind to prime the cache either
1320 * positively or negatively, don't mess with the cache
1323 DBG_DEBUG("%cID %"PRIu32
" -> %s from cache\n",
1324 xid
->type
== ID_TYPE_UID
? 'U' : 'G',
1326 dom_sid_str_buf(psid
, &buf
));
1332 * Make a copy, pdb_id_to_sid might want to turn
1333 * xid->type into ID_TYPE_BOTH, which we ignore here.
1335 struct unixid rw_xid
= *xid
;
1338 ret
= pdb_id_to_sid(&rw_xid
, psid
);
1343 DBG_DEBUG("%cID %"PRIu32
" -> %s from passdb\n",
1344 xid
->type
== ID_TYPE_UID
? 'U' : 'G',
1346 dom_sid_str_buf(psid
, &buf
));
1351 if (is_null_sid(psid
)) {
1353 * Nobody found anything: Return S-1-22-xx-yy. Don't
1354 * store that in caches, this is up to the layers
1357 if (xid
->type
== ID_TYPE_UID
) {
1358 uid_to_unix_users_sid(xid
->id
, psid
);
1360 gid_to_unix_groups_sid(xid
->id
, psid
);
1363 DBG_DEBUG("%cID %"PRIu32
" -> %s fallback\n",
1364 xid
->type
== ID_TYPE_UID
? 'U' : 'G',
1366 dom_sid_str_buf(psid
, &buf
));
1370 void uid_to_sid(struct dom_sid
*psid
, uid_t uid
)
1372 struct unixid xid
= { .type
= ID_TYPE_UID
, .id
= uid
};
1373 xid_to_sid(psid
, &xid
);
1376 void gid_to_sid(struct dom_sid
*psid
, gid_t gid
)
1378 struct unixid xid
= { .type
= ID_TYPE_GID
, .id
= gid
};
1379 xid_to_sid(psid
, &xid
);
1382 bool sids_to_unixids(const struct dom_sid
*sids
, uint32_t num_sids
,
1385 struct wbcDomainSid
*wbc_sids
= NULL
;
1386 struct wbcUnixId
*wbc_ids
= NULL
;
1387 struct bitmap
*found
= NULL
;
1388 uint32_t i
, num_not_cached
;
1389 uint32_t wbc_ids_size
= 0;
1393 wbc_sids
= talloc_array(talloc_tos(), struct wbcDomainSid
, num_sids
);
1394 if (wbc_sids
== NULL
) {
1397 found
= bitmap_talloc(wbc_sids
, num_sids
);
1398 if (found
== NULL
) {
1403 * We go through the requested SID array three times.
1404 * First time to look for global_sid_Unix_Users
1405 * and global_sid_Unix_Groups SIDS, and to look
1406 * for mappings cached in the idmap_cache.
1408 * Use bitmap_set() to mark an ids[] array entry as
1414 for (i
=0; i
<num_sids
; i
++) {
1418 if (sid_peek_check_rid(&global_sid_Unix_Users
,
1420 ids
[i
].type
= ID_TYPE_UID
;
1422 bitmap_set(found
, i
);
1425 if (sid_peek_check_rid(&global_sid_Unix_Groups
,
1427 ids
[i
].type
= ID_TYPE_GID
;
1429 bitmap_set(found
, i
);
1432 if (idmap_cache_find_sid2unixid(&sids
[i
], &ids
[i
], &expired
)
1435 bitmap_set(found
, i
);
1438 ids
[i
].type
= ID_TYPE_NOT_SPECIFIED
;
1439 memcpy(&wbc_sids
[num_not_cached
], &sids
[i
],
1440 ndr_size_dom_sid(&sids
[i
], 0));
1441 num_not_cached
+= 1;
1443 if (num_not_cached
== 0) {
1448 * For the ones that we couldn't map in the loop above, query winbindd
1449 * via wbcSidsToUnixIds().
1452 wbc_ids_size
= num_not_cached
;
1453 wbc_ids
= talloc_array(talloc_tos(), struct wbcUnixId
, wbc_ids_size
);
1454 if (wbc_ids
== NULL
) {
1457 for (i
=0; i
<wbc_ids_size
; i
++) {
1458 wbc_ids
[i
].type
= WBC_ID_TYPE_NOT_SPECIFIED
;
1459 wbc_ids
[i
].id
.gid
= (uint32_t)-1;
1461 err
= wbcSidsToUnixIds(wbc_sids
, wbc_ids_size
, wbc_ids
);
1462 if (!WBC_ERROR_IS_OK(err
)) {
1463 DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
1464 wbcErrorString(err
)));
1468 * Second time through the SID array, replace
1469 * the ids[] entries that wbcSidsToUnixIds() was able to
1472 * Use bitmap_set() to mark an ids[] array entry as
1478 for (i
=0; i
<num_sids
; i
++) {
1479 if (bitmap_query(found
, i
)) {
1483 SMB_ASSERT(num_not_cached
< wbc_ids_size
);
1485 switch (wbc_ids
[num_not_cached
].type
) {
1486 case WBC_ID_TYPE_UID
:
1487 ids
[i
].type
= ID_TYPE_UID
;
1488 ids
[i
].id
= wbc_ids
[num_not_cached
].id
.uid
;
1489 bitmap_set(found
, i
);
1491 case WBC_ID_TYPE_GID
:
1492 ids
[i
].type
= ID_TYPE_GID
;
1493 ids
[i
].id
= wbc_ids
[num_not_cached
].id
.gid
;
1494 bitmap_set(found
, i
);
1496 case WBC_ID_TYPE_BOTH
:
1497 ids
[i
].type
= ID_TYPE_BOTH
;
1498 ids
[i
].id
= wbc_ids
[num_not_cached
].id
.uid
;
1499 bitmap_set(found
, i
);
1501 case WBC_ID_TYPE_NOT_SPECIFIED
:
1503 * wbcSidsToUnixIds() wasn't able to map this
1504 * so we still need to check legacy_sid_to_XXX()
1505 * below. Don't mark the bitmap entry
1506 * as being found so the final loop knows
1507 * to try and map this entry.
1509 ids
[i
].type
= ID_TYPE_NOT_SPECIFIED
;
1510 ids
[i
].id
= (uint32_t)-1;
1514 * A successful return from wbcSidsToUnixIds()
1515 * cannot return anything other than the values
1516 * checked for above. Ensure this is so.
1518 smb_panic(__location__
);
1521 num_not_cached
+= 1;
1525 * Third and final time through the SID array,
1526 * try legacy_sid_to_gid()/legacy_sid_to_uid()
1527 * for entries we haven't already been able to
1530 * Use bitmap_set() to mark an ids[] array entry as
1534 for (i
=0; i
<num_sids
; i
++) {
1535 if (bitmap_query(found
, i
)) {
1538 if (legacy_sid_to_gid(&sids
[i
], &ids
[i
].id
)) {
1539 ids
[i
].type
= ID_TYPE_GID
;
1540 bitmap_set(found
, i
);
1543 if (legacy_sid_to_uid(&sids
[i
], &ids
[i
].id
)) {
1544 ids
[i
].type
= ID_TYPE_UID
;
1545 bitmap_set(found
, i
);
1551 * Pass through the return array for consistency.
1552 * Any ids[].id mapped to (uint32_t)-1 must be returned
1553 * as ID_TYPE_NOT_SPECIFIED.
1555 for (i
=0; i
<num_sids
; i
++) {
1556 switch(ids
[i
].type
) {
1560 if (ids
[i
].id
== (uint32_t)-1) {
1561 ids
[i
].type
= ID_TYPE_NOT_SPECIFIED
;
1564 case ID_TYPE_NOT_SPECIFIED
:
1566 case ID_TYPE_WB_REQUIRE_TYPE
:
1568 * these are internal between winbindd
1571 smb_panic(__location__
);
1578 TALLOC_FREE(wbc_ids
);
1579 TALLOC_FREE(wbc_sids
);
1583 /*****************************************************************
1584 *THE CANONICAL* convert SID to uid function.
1585 *****************************************************************/
1587 bool sid_to_uid(const struct dom_sid
*psid
, uid_t
*puid
)
1589 bool expired
= true;
1592 struct dom_sid_buf buf
;
1594 /* Optimize for the Unix Users Domain
1595 * as the conversion is straightforward */
1596 if (sid_peek_check_rid(&global_sid_Unix_Users
, psid
, &rid
)) {
1600 /* return here, don't cache */
1601 DEBUG(10,("sid %s -> uid %u\n",
1602 dom_sid_str_buf(psid
, &buf
),
1603 (unsigned int)*puid
));
1607 if (sid_check_is_in_unix_groups(psid
)) {
1608 DBG_DEBUG("SID %s is a group, failing\n",
1609 dom_sid_str_buf(psid
, &buf
));
1613 /* Check the winbindd cache directly. */
1614 ret
= idmap_cache_find_sid2uid(psid
, puid
, &expired
);
1616 if (ret
&& !expired
&& (*puid
== (uid_t
)-1)) {
1618 * Negative cache entry, we already asked.
1621 return legacy_sid_to_uid(psid
, puid
);
1624 if (!ret
|| expired
) {
1625 /* Not in cache. Ask winbindd. */
1626 if (!winbind_sid_to_uid(puid
, psid
)) {
1627 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1628 dom_sid_str_buf(psid
, &buf
)));
1629 /* winbind failed. do legacy */
1630 return legacy_sid_to_uid(psid
, puid
);
1634 /* TODO: Here would be the place to allocate both a gid and a uid for
1635 * the SID in question */
1637 DEBUG(10,("sid %s -> uid %u\n",
1638 dom_sid_str_buf(psid
, &buf
),
1639 (unsigned int)*puid
));
1644 /*****************************************************************
1645 *THE CANONICAL* convert SID to gid function.
1646 Group mapping is used for gids that maps to Wellknown SIDs
1647 *****************************************************************/
1649 bool sid_to_gid(const struct dom_sid
*psid
, gid_t
*pgid
)
1651 bool expired
= true;
1654 struct dom_sid_buf buf
;
1656 /* Optimize for the Unix Groups Domain
1657 * as the conversion is straightforward */
1658 if (sid_peek_check_rid(&global_sid_Unix_Groups
, psid
, &rid
)) {
1662 /* return here, don't cache */
1663 DEBUG(10,("sid %s -> gid %u\n",
1664 dom_sid_str_buf(psid
, &buf
),
1665 (unsigned int)*pgid
));
1669 if (sid_check_is_in_unix_users(psid
)) {
1670 DBG_DEBUG("SID %s is a user, failing\n",
1671 dom_sid_str_buf(psid
, &buf
));
1675 /* Check the winbindd cache directly. */
1676 ret
= idmap_cache_find_sid2gid(psid
, pgid
, &expired
);
1678 if (ret
&& !expired
&& (*pgid
== (gid_t
)-1)) {
1680 * Negative cache entry, we already asked.
1683 return legacy_sid_to_gid(psid
, pgid
);
1686 if (!ret
|| expired
) {
1687 /* Not in cache or negative. Ask winbindd. */
1688 /* Ask winbindd if it can map this sid to a gid.
1689 * (Idmap will check it is a valid SID and of the right type) */
1691 if ( !winbind_sid_to_gid(pgid
, psid
) ) {
1693 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1694 dom_sid_str_buf(psid
, &buf
)));
1695 /* winbind failed. do legacy */
1696 return legacy_sid_to_gid(psid
, pgid
);
1700 DEBUG(10,("sid %s -> gid %u\n",
1701 dom_sid_str_buf(psid
, &buf
),
1702 (unsigned int)*pgid
));
1708 * @brief This function gets the primary group SID mapping the primary
1709 * GID of the user as obtained by an actual getpwnam() call.
1710 * This is necessary to avoid issues with arbitrary group SIDs
1711 * stored in passdb. We try as hard as we can to get the SID
1712 * corresponding to the GID, including trying group mapping.
1713 * If nothing else works, we will force "Domain Users" as the
1715 * This is needed because we must always be able to lookup the
1716 * primary group SID, so we cannot settle for an arbitrary SID.
1718 * This call can be expensive. Use with moderation.
1719 * If you have a "samu" struct around use pdb_get_group_sid()
1720 * instead as it does properly cache results.
1722 * @param mem_ctx[in] The memory context iused to allocate the result.
1723 * @param username[in] The user's name
1724 * @param _pwd[in|out] If available, pass in user's passwd struct.
1725 * It will contain a tallocated passwd if NULL was
1727 * @param _group_sid[out] The user's Primary Group SID
1729 * @return NTSTATUS error code.
1731 NTSTATUS
get_primary_group_sid(TALLOC_CTX
*mem_ctx
,
1732 const char *username
,
1733 struct passwd
**_pwd
,
1734 struct dom_sid
**_group_sid
)
1736 TALLOC_CTX
*tmp_ctx
;
1737 bool need_lookup_sid
= false;
1738 struct dom_sid
*group_sid
;
1739 struct passwd
*pwd
= *_pwd
;
1741 tmp_ctx
= talloc_new(mem_ctx
);
1743 return NT_STATUS_NO_MEMORY
;
1747 pwd
= Get_Pwnam_alloc(mem_ctx
, username
);
1749 DEBUG(0, ("Failed to find a Unix account for %s\n",
1751 TALLOC_FREE(tmp_ctx
);
1752 return NT_STATUS_NO_SUCH_USER
;
1756 group_sid
= talloc_zero(mem_ctx
, struct dom_sid
);
1758 TALLOC_FREE(tmp_ctx
);
1759 return NT_STATUS_NO_MEMORY
;
1762 gid_to_sid(group_sid
, pwd
->pw_gid
);
1763 if (!is_null_sid(group_sid
)) {
1764 struct dom_sid domain_sid
;
1767 /* We need a sid within our domain */
1768 sid_copy(&domain_sid
, group_sid
);
1769 sid_split_rid(&domain_sid
, &rid
);
1770 if (dom_sid_equal(&domain_sid
, get_global_sam_sid())) {
1772 * As shortcut for the expensive lookup_sid call
1773 * compare the domain sid part
1776 case DOMAIN_RID_ADMINS
:
1777 case DOMAIN_RID_USERS
:
1780 need_lookup_sid
= true;
1784 /* Try group mapping */
1787 id
.id
= pwd
->pw_gid
;
1788 id
.type
= ID_TYPE_GID
;
1790 ZERO_STRUCTP(group_sid
);
1791 if (pdb_id_to_sid(&id
, group_sid
)) {
1792 need_lookup_sid
= true;
1797 /* We must verify that this is a valid SID that resolves to a
1798 * group of the correct type */
1799 if (need_lookup_sid
) {
1800 enum lsa_SidType type
= SID_NAME_UNKNOWN
;
1802 struct dom_sid_buf buf
;
1804 DEBUG(10, ("do lookup_sid(%s) for group of user %s\n",
1805 dom_sid_str_buf(group_sid
, &buf
),
1808 /* Now check that it's actually a domain group and
1809 * not something else */
1810 lookup_ret
= lookup_sid(tmp_ctx
, group_sid
,
1813 if (lookup_ret
&& (type
== SID_NAME_DOM_GRP
)) {
1817 DEBUG(3, ("Primary group %s for user %s is"
1818 " a %s and not a domain group\n",
1819 dom_sid_str_buf(group_sid
, &buf
),
1821 sid_type_lookup(type
)));
1824 /* Everything else, failed.
1825 * Just set it to the 'Domain Users' RID of 513 which will
1826 always resolve to a name */
1827 DEBUG(3, ("Forcing Primary Group to 'Domain Users' for %s\n",
1830 sid_compose(group_sid
, get_global_sam_sid(), DOMAIN_RID_USERS
);
1833 *_pwd
= talloc_move(mem_ctx
, &pwd
);
1834 *_group_sid
= talloc_move(mem_ctx
, &group_sid
);
1835 TALLOC_FREE(tmp_ctx
);
1836 return NT_STATUS_OK
;