2 Unix SMB/CIFS implementation.
4 Winbind rpc backend functions
6 Copyright (C) Tim Potter 2000-2001,2003
7 Copyright (C) Simo Sorce 2003
8 Copyright (C) Volker Lendecke 2004
9 Copyright (C) Jeremy Allison 2008
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 #define DBGC_CLASS DBGC_WINBIND
31 static NTSTATUS
enum_groups_internal(struct winbindd_domain
*domain
,
34 struct acct_info
**info
,
35 enum lsa_SidType sidtype
)
37 struct pdb_search
*search
;
38 struct samr_displayentry
*entries
;
40 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
42 if (sidtype
== SID_NAME_ALIAS
) {
43 search
= pdb_search_aliases(talloc_tos(), &domain
->sid
);
45 search
= pdb_search_groups(talloc_tos());
48 if (search
== NULL
) goto done
;
50 *num_entries
= pdb_search_entries(search
, 0, 0xffffffff, &entries
);
51 if (*num_entries
== 0) {
52 /* Zero entries isn't an error */
53 result
= NT_STATUS_OK
;
57 *info
= TALLOC_ARRAY(mem_ctx
, struct acct_info
, *num_entries
);
59 result
= NT_STATUS_NO_MEMORY
;
63 for (i
=0; i
<*num_entries
; i
++) {
64 fstrcpy((*info
)[i
].acct_name
, entries
[i
].account_name
);
65 fstrcpy((*info
)[i
].acct_desc
, entries
[i
].description
);
66 (*info
)[i
].rid
= entries
[i
].rid
;
69 result
= NT_STATUS_OK
;
75 /* List all local groups (aliases) */
76 static NTSTATUS
enum_local_groups(struct winbindd_domain
*domain
,
79 struct acct_info
**info
)
81 return enum_groups_internal(domain
,
88 /* convert a single name to a sid in a domain */
89 static NTSTATUS
name_to_sid(struct winbindd_domain
*domain
,
91 enum winbindd_cmd original_cmd
,
92 const char *domain_name
,
95 enum lsa_SidType
*type
)
98 uint32 flags
= LOOKUP_NAME_ALL
;
100 switch ( original_cmd
) {
101 case WINBINDD_LOOKUPNAME
:
102 /* This call is ok */
105 /* Avoid any NSS calls in the lookup_name by default */
106 flags
|= LOOKUP_NAME_EXPLICIT
;
107 DEBUG(10,("winbindd_passdb: limiting name_to_sid() to explicit mappings\n"));
111 if (domain_name
&& domain_name
[0] && strchr_m(name
, '\\') == NULL
) {
112 fullname
= talloc_asprintf(mem_ctx
, "%s\\%s",
114 if (fullname
== NULL
) {
115 return NT_STATUS_NO_MEMORY
;
121 DEBUG(10, ("Finding fullname %s\n", fullname
));
123 if ( !lookup_name( mem_ctx
, fullname
, flags
, NULL
, NULL
, sid
, type
) ) {
124 return NT_STATUS_NONE_MAPPED
;
127 DEBUG(10, ("name_to_sid for %s returned %s (%s)\n",
130 sid_type_lookup((uint32
)*type
)));
136 convert a domain SID to a user or group name
138 static NTSTATUS
sid_to_name(struct winbindd_domain
*domain
,
143 enum lsa_SidType
*type
)
145 const char *dom
, *nam
;
147 DEBUG(10, ("Converting SID %s\n", sid_string_dbg(sid
)));
150 if (!sid_check_is_in_builtin(sid
) &&
151 !sid_check_is_in_our_domain(sid
) &&
152 !sid_check_is_in_unix_users(sid
) &&
153 !sid_check_is_unix_users(sid
) &&
154 !sid_check_is_in_unix_groups(sid
) &&
155 !sid_check_is_unix_groups(sid
) &&
156 !sid_check_is_in_wellknown_domain(sid
))
158 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
159 "passdb backend\n", sid_string_dbg(sid
)));
160 return NT_STATUS_NONE_MAPPED
;
163 if (!lookup_sid(mem_ctx
, sid
, &dom
, &nam
, type
)) {
164 return NT_STATUS_NONE_MAPPED
;
167 *domain_name
= talloc_strdup(mem_ctx
, dom
);
168 *name
= talloc_strdup(mem_ctx
, nam
);
173 static NTSTATUS
rids_to_names(struct winbindd_domain
*domain
,
180 enum lsa_SidType
**types
)
195 if (!sid_check_is_in_builtin(sid
) &&
196 !sid_check_is_in_our_domain(sid
) &&
197 !sid_check_is_in_unix_users(sid
) &&
198 !sid_check_is_unix_users(sid
) &&
199 !sid_check_is_in_unix_groups(sid
) &&
200 !sid_check_is_unix_groups(sid
) &&
201 !sid_check_is_in_wellknown_domain(sid
))
203 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
204 "passdb backend\n", sid_string_dbg(sid
)));
205 return NT_STATUS_NONE_MAPPED
;
208 *names
= TALLOC_ARRAY(mem_ctx
, char *, num_rids
);
209 *types
= TALLOC_ARRAY(mem_ctx
, enum lsa_SidType
, num_rids
);
211 if ((*names
== NULL
) || (*types
== NULL
)) {
212 return NT_STATUS_NO_MEMORY
;
215 have_mapped
= have_unmapped
= false;
217 for (i
=0; i
<num_rids
; i
++) {
219 const char *dom
= NULL
, *nam
= NULL
;
220 enum lsa_SidType type
= SID_NAME_UNKNOWN
;
222 if (!sid_compose(&lsid
, sid
, rids
[i
])) {
223 return NT_STATUS_INTERNAL_ERROR
;
226 if (!lookup_sid(mem_ctx
, &lsid
, &dom
, &nam
, &type
)) {
227 have_unmapped
= true;
228 (*types
)[i
] = SID_NAME_UNKNOWN
;
229 (*names
)[i
] = talloc_strdup(mem_ctx
, "");
233 (*names
)[i
] = CONST_DISCARD(char *, nam
);
236 if (*domain_name
== NULL
) {
237 *domain_name
= CONST_DISCARD(char *, dom
);
239 char *dname
= CONST_DISCARD(char *, dom
);
245 return NT_STATUS_NONE_MAPPED
;
247 if (!have_unmapped
) {
250 return STATUS_SOME_UNMAPPED
;
253 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
254 static NTSTATUS
lookup_usergroups(struct winbindd_domain
*domain
,
256 const DOM_SID
*user_sid
,
257 uint32
*num_groups
, DOM_SID
**user_gids
)
260 DOM_SID
*groups
= NULL
;
265 if ( (user
= samu_new(mem_ctx
)) == NULL
) {
266 return NT_STATUS_NO_MEMORY
;
269 if ( !pdb_getsampwsid( user
, user_sid
) ) {
271 return NT_STATUS_NO_SUCH_USER
;
274 result
= pdb_enum_group_memberships( mem_ctx
, user
, &groups
, &gids
, &ngroups
);
278 *num_groups
= (uint32
)ngroups
;
284 static NTSTATUS
lookup_useraliases(struct winbindd_domain
*domain
,
286 uint32 num_sids
, const DOM_SID
*sids
,
287 uint32
*p_num_aliases
, uint32
**rids
)
290 size_t num_aliases
= 0;
292 result
= pdb_enum_alias_memberships(mem_ctx
, &domain
->sid
,
293 sids
, num_sids
, rids
, &num_aliases
);
295 *p_num_aliases
= num_aliases
;
299 /* find the sequence number for a domain */
300 static NTSTATUS
sequence_number(struct winbindd_domain
*domain
, uint32
*seq
)
305 result
= pdb_get_seq_num(&seq_num
);
310 *seq
= (int) seq_num
;
315 static NTSTATUS
lockout_policy(struct winbindd_domain
*domain
,
317 struct samr_DomInfo12
*policy
)
319 /* actually we have that */
320 return NT_STATUS_NOT_IMPLEMENTED
;
323 static NTSTATUS
password_policy(struct winbindd_domain
*domain
,
325 struct samr_DomInfo1
*policy
)
327 struct samr_DomInfo1
*p
;
328 time_t u_expire
, u_min_age
;
329 uint32 account_policy_temp
;
331 if ((p
= TALLOC_ZERO_P(mem_ctx
, struct samr_DomInfo1
)) == NULL
) {
332 return NT_STATUS_NO_MEMORY
;
335 if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN
,
336 &account_policy_temp
)) {
337 return NT_STATUS_ACCESS_DENIED
;
339 p
->min_password_length
= account_policy_temp
;
341 if (!pdb_get_account_policy(AP_PASSWORD_HISTORY
,
342 &account_policy_temp
)) {
343 return NT_STATUS_ACCESS_DENIED
;
345 p
->password_history_length
= account_policy_temp
;
347 if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS
,
348 &p
->password_properties
)) {
349 return NT_STATUS_ACCESS_DENIED
;
352 if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE
, &account_policy_temp
)) {
353 return NT_STATUS_ACCESS_DENIED
;
355 u_expire
= account_policy_temp
;
357 if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE
, &account_policy_temp
)) {
358 return NT_STATUS_ACCESS_DENIED
;
360 u_min_age
= account_policy_temp
;
362 unix_to_nt_time_abs((NTTIME
*)&p
->max_password_age
, u_expire
);
363 unix_to_nt_time_abs((NTTIME
*)&p
->min_password_age
, u_min_age
);
370 /*********************************************************************
371 BUILTIN specific functions.
372 *********************************************************************/
374 /* list all domain groups */
375 static NTSTATUS
builtin_enum_dom_groups(struct winbindd_domain
*domain
,
378 struct acct_info
**info
)
380 /* BUILTIN doesn't have domain groups */
386 /* Query display info for a domain. This returns enough information plus a
387 bit extra to give an overview of domain users for the User Manager
389 static NTSTATUS
builtin_query_user_list(struct winbindd_domain
*domain
,
392 WINBIND_USERINFO
**info
)
394 /* We don't have users */
400 /* Lookup user information from a rid or username. */
401 static NTSTATUS
builtin_query_user(struct winbindd_domain
*domain
,
403 const DOM_SID
*user_sid
,
404 WINBIND_USERINFO
*user_info
)
406 return NT_STATUS_NO_SUCH_USER
;
409 static NTSTATUS
builtin_lookup_groupmem(struct winbindd_domain
*domain
,
411 const DOM_SID
*group_sid
, uint32
*num_names
,
412 DOM_SID
**sid_mem
, char ***names
,
419 return NT_STATUS_NO_SUCH_GROUP
;
422 /* get a list of trusted domains - builtin domain */
423 static NTSTATUS
builtin_trusted_domains(struct winbindd_domain
*domain
,
437 /*********************************************************************
438 SAM specific functions.
439 *********************************************************************/
441 /* list all domain groups */
442 static NTSTATUS
sam_enum_dom_groups(struct winbindd_domain
*domain
,
445 struct acct_info
**info
)
447 return enum_groups_internal(domain
,
454 static NTSTATUS
sam_query_user_list(struct winbindd_domain
*domain
,
457 WINBIND_USERINFO
**info
)
459 struct pdb_search
*ps
= pdb_search_users(talloc_tos(), ACB_NORMAL
);
460 struct samr_displayentry
*entries
= NULL
;
467 return NT_STATUS_NO_MEMORY
;
470 *num_entries
= pdb_search_entries(ps
,
474 *info
= TALLOC_ZERO_ARRAY(mem_ctx
, WINBIND_USERINFO
, *num_entries
);
477 return NT_STATUS_NO_MEMORY
;
480 for (i
= 0; i
< *num_entries
; i
++) {
481 struct samr_displayentry
*e
= &entries
[i
];
483 (*info
)[i
].acct_name
= talloc_strdup(mem_ctx
, e
->account_name
);
484 (*info
)[i
].full_name
= talloc_strdup(mem_ctx
, e
->fullname
);
485 (*info
)[i
].homedir
= NULL
;
486 (*info
)[i
].shell
= NULL
;
487 sid_compose(&(*info
)[i
].user_sid
, &domain
->sid
, e
->rid
);
489 /* For the moment we set the primary group for
490 every user to be the Domain Users group.
491 There are serious problems with determining
492 the actual primary group for large domains.
493 This should really be made into a 'winbind
494 force group' smb.conf parameter or
495 something like that. */
497 sid_compose(&(*info
)[i
].group_sid
, &domain
->sid
,
498 DOMAIN_GROUP_RID_USERS
);
505 /* Lookup user information from a rid or username. */
506 static NTSTATUS
sam_query_user(struct winbindd_domain
*domain
,
508 const DOM_SID
*user_sid
,
509 WINBIND_USERINFO
*user_info
)
511 struct samu
*sampass
= NULL
;
513 ZERO_STRUCTP(user_info
);
515 if (!sid_check_is_in_our_domain(user_sid
)) {
516 return NT_STATUS_NO_SUCH_USER
;
519 DEBUG(10,("sam_query_user: getting samu info for sid %s\n",
520 sid_string_dbg(user_sid
) ));
522 if (!(sampass
= samu_new(mem_ctx
))) {
523 return NT_STATUS_NO_MEMORY
;
526 if (!pdb_getsampwsid(sampass
, user_sid
)) {
527 TALLOC_FREE(sampass
);
528 return NT_STATUS_NO_SUCH_USER
;
531 if (pdb_get_group_sid(sampass
) == NULL
) {
532 TALLOC_FREE(sampass
);
533 return NT_STATUS_NO_SUCH_GROUP
;
536 DEBUG(10,("sam_query_user: group sid %s\n",
537 sid_string_dbg(sampass
->group_sid
) ));
539 sid_copy(&user_info
->user_sid
, user_sid
);
540 sid_copy(&user_info
->group_sid
, sampass
->group_sid
);
542 user_info
->acct_name
= talloc_strdup(mem_ctx
, sampass
->username
?
543 sampass
->username
: "");
544 user_info
->full_name
= talloc_strdup(mem_ctx
, sampass
->full_name
?
545 sampass
->full_name
: "");
546 user_info
->homedir
= talloc_strdup(mem_ctx
, sampass
->home_dir
?
547 sampass
->home_dir
: "");
548 if (sampass
->unix_pw
&& sampass
->unix_pw
->pw_shell
) {
549 user_info
->shell
= talloc_strdup(mem_ctx
, sampass
->unix_pw
->pw_shell
);
551 user_info
->shell
= talloc_strdup(mem_ctx
, "");
553 user_info
->primary_gid
= sampass
->unix_pw
? sampass
->unix_pw
->pw_gid
: (gid_t
)-1;
555 TALLOC_FREE(sampass
);
559 /* Lookup group membership given a rid. */
560 static NTSTATUS
sam_lookup_groupmem(struct winbindd_domain
*domain
,
562 const DOM_SID
*group_sid
, uint32
*num_names
,
563 DOM_SID
**sid_mem
, char ***names
,
566 size_t i
, num_members
, num_mapped
;
569 const DOM_SID
**sids
;
570 struct lsa_dom_info
*lsa_domains
;
571 struct lsa_name_info
*lsa_names
;
574 if (!sid_check_is_in_our_domain(group_sid
)) {
575 /* There's no groups, only aliases in BUILTIN */
576 return NT_STATUS_NO_SUCH_GROUP
;
579 if (!(tmp_ctx
= talloc_init("lookup_groupmem"))) {
580 return NT_STATUS_NO_MEMORY
;
583 result
= pdb_enum_group_members(tmp_ctx
, group_sid
, &rids
,
585 if (!NT_STATUS_IS_OK(result
)) {
586 TALLOC_FREE(tmp_ctx
);
590 if (num_members
== 0) {
595 TALLOC_FREE(tmp_ctx
);
599 *sid_mem
= TALLOC_ARRAY(mem_ctx
, DOM_SID
, num_members
);
600 *names
= TALLOC_ARRAY(mem_ctx
, char *, num_members
);
601 *name_types
= TALLOC_ARRAY(mem_ctx
, uint32
, num_members
);
602 sids
= TALLOC_ARRAY(tmp_ctx
, const DOM_SID
*, num_members
);
604 if (((*sid_mem
) == NULL
) || ((*names
) == NULL
) ||
605 ((*name_types
) == NULL
) || (sids
== NULL
)) {
606 TALLOC_FREE(tmp_ctx
);
607 return NT_STATUS_NO_MEMORY
;
611 * Prepare an array of sid pointers for the lookup_sids calling
615 for (i
=0; i
<num_members
; i
++) {
616 DOM_SID
*sid
= &((*sid_mem
)[i
]);
617 if (!sid_compose(sid
, &domain
->sid
, rids
[i
])) {
618 TALLOC_FREE(tmp_ctx
);
619 return NT_STATUS_INTERNAL_ERROR
;
624 result
= lookup_sids(tmp_ctx
, num_members
, sids
, 1,
625 &lsa_domains
, &lsa_names
);
626 if (!NT_STATUS_IS_OK(result
)) {
627 TALLOC_FREE(tmp_ctx
);
632 for (i
=0; i
<num_members
; i
++) {
633 if (lsa_names
[i
].type
!= SID_NAME_USER
) {
634 DEBUG(2, ("Got %s as group member -- ignoring\n",
635 sid_type_lookup(lsa_names
[i
].type
)));
638 if (!((*names
)[num_mapped
] = talloc_strdup((*names
),
639 lsa_names
[i
].name
))) {
640 TALLOC_FREE(tmp_ctx
);
641 return NT_STATUS_NO_MEMORY
;
644 (*name_types
)[num_mapped
] = lsa_names
[i
].type
;
649 *num_names
= num_mapped
;
651 TALLOC_FREE(tmp_ctx
);
655 /* get a list of trusted domains */
656 static NTSTATUS
sam_trusted_domains(struct winbindd_domain
*domain
,
664 struct trustdom_info
**domains
;
673 if (!(tmp_ctx
= talloc_init("trusted_domains"))) {
674 return NT_STATUS_NO_MEMORY
;
677 nt_status
= pdb_enum_trusteddoms(tmp_ctx
, num_domains
, &domains
);
678 if (!NT_STATUS_IS_OK(nt_status
)) {
679 TALLOC_FREE(tmp_ctx
);
684 *names
= TALLOC_ARRAY(mem_ctx
, char *, *num_domains
);
685 *alt_names
= TALLOC_ARRAY(mem_ctx
, char *, *num_domains
);
686 *dom_sids
= TALLOC_ARRAY(mem_ctx
, DOM_SID
, *num_domains
);
688 if ((*alt_names
== NULL
) || (*names
== NULL
) || (*dom_sids
== NULL
)) {
689 TALLOC_FREE(tmp_ctx
);
690 return NT_STATUS_NO_MEMORY
;
698 for (i
=0; i
<*num_domains
; i
++) {
699 (*alt_names
)[i
] = NULL
;
700 if (!((*names
)[i
] = talloc_strdup((*names
),
701 domains
[i
]->name
))) {
702 TALLOC_FREE(tmp_ctx
);
703 return NT_STATUS_NO_MEMORY
;
705 sid_copy(&(*dom_sids
)[i
], &domains
[i
]->sid
);
708 TALLOC_FREE(tmp_ctx
);
712 /* the rpc backend methods are exposed via this structure */
713 struct winbindd_methods builtin_passdb_methods
= {
715 builtin_query_user_list
,
716 builtin_enum_dom_groups
,
724 builtin_lookup_groupmem
,
728 builtin_trusted_domains
,
731 /* the rpc backend methods are exposed via this structure */
732 struct winbindd_methods sam_passdb_methods
= {