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 const char *domain_name,
95 enum lsa_SidType *type)
99 flags |= LOOKUP_NAME_ALL;
101 if (domain_name && domain_name[0] && strchr_m(name, '\\') == NULL) {
102 fullname = talloc_asprintf(mem_ctx, "%s\\%s",
104 if (fullname == NULL) {
105 return NT_STATUS_NO_MEMORY;
111 DEBUG(10, ("Finding fullname %s\n", fullname));
113 if ( !lookup_name( mem_ctx, fullname, flags, NULL, NULL, sid, type ) ) {
114 return NT_STATUS_NONE_MAPPED;
117 DEBUG(10, ("name_to_sid for %s returned %s (%s)\n",
120 sid_type_lookup((uint32)*type)));
126 convert a domain SID to a user or group name
128 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
133 enum lsa_SidType *type)
135 const char *dom, *nam;
137 DEBUG(10, ("Converting SID %s\n", sid_string_dbg(sid)));
140 if (!sid_check_is_in_builtin(sid) &&
141 !sid_check_is_in_our_domain(sid) &&
142 !sid_check_is_in_unix_users(sid) &&
143 !sid_check_is_unix_users(sid) &&
144 !sid_check_is_in_unix_groups(sid) &&
145 !sid_check_is_unix_groups(sid) &&
146 !sid_check_is_in_wellknown_domain(sid))
148 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
149 "passdb backend\n", sid_string_dbg(sid)));
150 return NT_STATUS_NONE_MAPPED;
153 if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) {
154 return NT_STATUS_NONE_MAPPED;
157 *domain_name = talloc_strdup(mem_ctx, dom);
158 *name = talloc_strdup(mem_ctx, nam);
163 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
170 enum lsa_SidType **types)
185 if (!sid_check_is_in_builtin(sid) &&
186 !sid_check_is_in_our_domain(sid) &&
187 !sid_check_is_in_unix_users(sid) &&
188 !sid_check_is_unix_users(sid) &&
189 !sid_check_is_in_unix_groups(sid) &&
190 !sid_check_is_unix_groups(sid) &&
191 !sid_check_is_in_wellknown_domain(sid))
193 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
194 "passdb backend\n", sid_string_dbg(sid)));
195 return NT_STATUS_NONE_MAPPED;
198 *names = TALLOC_ARRAY(mem_ctx, char *, num_rids);
199 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
201 if ((*names == NULL) || (*types == NULL)) {
202 return NT_STATUS_NO_MEMORY;
205 have_mapped = have_unmapped = false;
207 for (i=0; i<num_rids; i++) {
209 const char *dom = NULL, *nam = NULL;
210 enum lsa_SidType type = SID_NAME_UNKNOWN;
212 if (!sid_compose(&lsid, sid, rids[i])) {
213 return NT_STATUS_INTERNAL_ERROR;
216 if (!lookup_sid(mem_ctx, &lsid, &dom, &nam, &type)) {
217 have_unmapped = true;
218 (*types)[i] = SID_NAME_UNKNOWN;
219 (*names)[i] = talloc_strdup(mem_ctx, "");
223 (*names)[i] = CONST_DISCARD(char *, nam);
226 if (*domain_name == NULL) {
227 *domain_name = CONST_DISCARD(char *, dom);
229 char *dname = CONST_DISCARD(char *, dom);
235 return NT_STATUS_NONE_MAPPED;
237 if (!have_unmapped) {
240 return STATUS_SOME_UNMAPPED;
243 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
244 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
246 const DOM_SID *user_sid,
247 uint32 *num_groups, DOM_SID **user_gids)
250 DOM_SID *groups = NULL;
255 if ( (user = samu_new(mem_ctx)) == NULL ) {
256 return NT_STATUS_NO_MEMORY;
259 if ( !pdb_getsampwsid( user, user_sid ) ) {
261 return NT_STATUS_NO_SUCH_USER;
264 result = pdb_enum_group_memberships( mem_ctx, user, &groups, &gids, &ngroups );
268 *num_groups = (uint32)ngroups;
274 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
276 uint32 num_sids, const DOM_SID *sids,
277 uint32 *p_num_aliases, uint32 **rids)
280 size_t num_aliases = 0;
282 result = pdb_enum_alias_memberships(mem_ctx, &domain->sid,
283 sids, num_sids, rids, &num_aliases);
285 *p_num_aliases = num_aliases;
289 /* find the sequence number for a domain */
290 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
295 result = pdb_get_seq_num(&seq_num);
300 *seq = (int) seq_num;
305 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
307 struct samr_DomInfo12 *policy)
309 /* actually we have that */
310 return NT_STATUS_NOT_IMPLEMENTED;
313 static NTSTATUS password_policy(struct winbindd_domain *domain,
315 struct samr_DomInfo1 *policy)
317 struct samr_DomInfo1 *p;
318 time_t u_expire, u_min_age;
319 uint32 account_policy_temp;
321 if ((p = TALLOC_ZERO_P(mem_ctx, struct samr_DomInfo1)) == NULL) {
322 return NT_STATUS_NO_MEMORY;
325 if (!pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN,
326 &account_policy_temp)) {
327 return NT_STATUS_ACCESS_DENIED;
329 p->min_password_length = account_policy_temp;
331 if (!pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY,
332 &account_policy_temp)) {
333 return NT_STATUS_ACCESS_DENIED;
335 p->password_history_length = account_policy_temp;
337 if (!pdb_get_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS,
338 &p->password_properties)) {
339 return NT_STATUS_ACCESS_DENIED;
342 if (!pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &account_policy_temp)) {
343 return NT_STATUS_ACCESS_DENIED;
345 u_expire = account_policy_temp;
347 if (!pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, &account_policy_temp)) {
348 return NT_STATUS_ACCESS_DENIED;
350 u_min_age = account_policy_temp;
352 unix_to_nt_time_abs((NTTIME *)&p->max_password_age, u_expire);
353 unix_to_nt_time_abs((NTTIME *)&p->min_password_age, u_min_age);
360 /*********************************************************************
361 BUILTIN specific functions.
362 *********************************************************************/
364 /* list all domain groups */
365 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
368 struct acct_info **info)
370 /* BUILTIN doesn't have domain groups */
376 /* Query display info for a domain. This returns enough information plus a
377 bit extra to give an overview of domain users for the User Manager
379 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
382 struct wbint_userinfo **info)
384 /* We don't have users */
390 /* Lookup user information from a rid or username. */
391 static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
393 const DOM_SID *user_sid,
394 struct wbint_userinfo *user_info)
396 return NT_STATUS_NO_SUCH_USER;
399 static NTSTATUS builtin_lookup_groupmem(struct winbindd_domain *domain,
401 const DOM_SID *group_sid, uint32 *num_names,
402 DOM_SID **sid_mem, char ***names,
405 DEBUG(10,("passdb: lookup_groupmem (builtin) %s sid=%s\n", domain->name,
406 sid_string_dbg(group_sid)));
412 return NT_STATUS_NO_SUCH_GROUP;
415 /* get a list of trusted domains - builtin domain */
416 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
430 /*********************************************************************
431 SAM specific functions.
432 *********************************************************************/
434 /* list all domain groups */
435 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
438 struct acct_info **info)
440 return enum_groups_internal(domain,
447 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
450 struct wbint_userinfo **info)
452 struct pdb_search *ps = pdb_search_users(talloc_tos(), ACB_NORMAL);
453 struct samr_displayentry *entries = NULL;
460 return NT_STATUS_NO_MEMORY;
463 *num_entries = pdb_search_entries(ps,
467 *info = TALLOC_ZERO_ARRAY(mem_ctx, struct wbint_userinfo, *num_entries);
470 return NT_STATUS_NO_MEMORY;
473 for (i = 0; i < *num_entries; i++) {
474 struct samr_displayentry *e = &entries[i];
476 (*info)[i].acct_name = talloc_strdup(mem_ctx, e->account_name );
477 (*info)[i].full_name = talloc_strdup(mem_ctx, e->fullname );
478 (*info)[i].homedir = NULL;
479 (*info)[i].shell = NULL;
480 sid_compose(&(*info)[i].user_sid, &domain->sid, e->rid);
482 /* For the moment we set the primary group for
483 every user to be the Domain Users group.
484 There are serious problems with determining
485 the actual primary group for large domains.
486 This should really be made into a 'winbind
487 force group' smb.conf parameter or
488 something like that. */
490 sid_compose(&(*info)[i].group_sid, &domain->sid,
491 DOMAIN_GROUP_RID_USERS);
498 /* Lookup user information from a rid or username. */
499 static NTSTATUS sam_query_user(struct winbindd_domain *domain,
501 const DOM_SID *user_sid,
502 struct wbint_userinfo *user_info)
504 struct samu *sampass = NULL;
506 ZERO_STRUCTP(user_info);
508 if (!sid_check_is_in_our_domain(user_sid)) {
509 return NT_STATUS_NO_SUCH_USER;
512 DEBUG(10,("sam_query_user: getting samu info for sid %s\n",
513 sid_string_dbg(user_sid) ));
515 if (!(sampass = samu_new(mem_ctx))) {
516 return NT_STATUS_NO_MEMORY;
519 if (!pdb_getsampwsid(sampass, user_sid)) {
520 TALLOC_FREE(sampass);
521 return NT_STATUS_NO_SUCH_USER;
524 if (pdb_get_group_sid(sampass) == NULL) {
525 TALLOC_FREE(sampass);
526 return NT_STATUS_NO_SUCH_GROUP;
529 DEBUG(10,("sam_query_user: group sid %s\n",
530 sid_string_dbg(sampass->group_sid) ));
532 sid_copy(&user_info->user_sid, user_sid);
533 sid_copy(&user_info->group_sid, sampass->group_sid);
535 user_info->acct_name = talloc_strdup(mem_ctx, sampass->username ?
536 sampass->username : "");
537 user_info->full_name = talloc_strdup(mem_ctx, sampass->full_name ?
538 sampass->full_name : "");
539 user_info->homedir = talloc_strdup(mem_ctx, sampass->home_dir ?
540 sampass->home_dir : "");
541 if (sampass->unix_pw && sampass->unix_pw->pw_shell) {
542 user_info->shell = talloc_strdup(mem_ctx, sampass->unix_pw->pw_shell);
544 user_info->shell = talloc_strdup(mem_ctx, "");
546 user_info->primary_gid = sampass->unix_pw ? sampass->unix_pw->pw_gid : (gid_t)-1;
548 TALLOC_FREE(sampass);
552 /* Lookup group membership given a rid. */
553 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
555 const DOM_SID *group_sid, uint32 *num_names,
556 DOM_SID **sid_mem, char ***names,
559 size_t i, num_members, num_mapped;
562 const DOM_SID **sids;
563 struct lsa_dom_info *lsa_domains;
564 struct lsa_name_info *lsa_names;
567 DEBUG(10,("passdb: lookup_groupmem (sam) %s sid=%s\n", domain->name,
568 sid_string_dbg(group_sid)));
570 if (!sid_check_is_in_our_domain(group_sid)) {
571 /* There's no groups, only aliases in BUILTIN */
572 return NT_STATUS_NO_SUCH_GROUP;
575 if (!(tmp_ctx = talloc_init("lookup_groupmem"))) {
576 return NT_STATUS_NO_MEMORY;
579 result = pdb_enum_group_members(tmp_ctx, group_sid, &rids,
581 if (!NT_STATUS_IS_OK(result)) {
582 TALLOC_FREE(tmp_ctx);
586 if (num_members == 0) {
591 TALLOC_FREE(tmp_ctx);
595 *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members);
596 *names = TALLOC_ARRAY(mem_ctx, char *, num_members);
597 *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members);
598 sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members);
600 if (((*sid_mem) == NULL) || ((*names) == NULL) ||
601 ((*name_types) == NULL) || (sids == NULL)) {
602 TALLOC_FREE(tmp_ctx);
603 return NT_STATUS_NO_MEMORY;
607 * Prepare an array of sid pointers for the lookup_sids calling
611 for (i=0; i<num_members; i++) {
612 DOM_SID *sid = &((*sid_mem)[i]);
613 if (!sid_compose(sid, &domain->sid, rids[i])) {
614 TALLOC_FREE(tmp_ctx);
615 return NT_STATUS_INTERNAL_ERROR;
620 result = lookup_sids(tmp_ctx, num_members, sids, 1,
621 &lsa_domains, &lsa_names);
622 if (!NT_STATUS_IS_OK(result)) {
623 TALLOC_FREE(tmp_ctx);
628 for (i=0; i<num_members; i++) {
629 if (lsa_names[i].type != SID_NAME_USER) {
630 DEBUG(2, ("Got %s as group member -- ignoring\n",
631 sid_type_lookup(lsa_names[i].type)));
634 if (!((*names)[num_mapped] = talloc_strdup((*names),
635 lsa_names[i].name))) {
636 TALLOC_FREE(tmp_ctx);
637 return NT_STATUS_NO_MEMORY;
640 (*name_types)[num_mapped] = lsa_names[i].type;
645 *num_names = num_mapped;
647 TALLOC_FREE(tmp_ctx);
651 /* get a list of trusted domains */
652 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
660 struct trustdom_info **domains;
669 if (!(tmp_ctx = talloc_init("trusted_domains"))) {
670 return NT_STATUS_NO_MEMORY;
673 nt_status = pdb_enum_trusteddoms(tmp_ctx, num_domains, &domains);
674 if (!NT_STATUS_IS_OK(nt_status)) {
675 TALLOC_FREE(tmp_ctx);
680 *names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
681 *alt_names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
682 *dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
684 if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) {
685 TALLOC_FREE(tmp_ctx);
686 return NT_STATUS_NO_MEMORY;
694 for (i=0; i<*num_domains; i++) {
695 (*alt_names)[i] = NULL;
696 if (!((*names)[i] = talloc_strdup((*names),
697 domains[i]->name))) {
698 TALLOC_FREE(tmp_ctx);
699 return NT_STATUS_NO_MEMORY;
701 sid_copy(&(*dom_sids)[i], &domains[i]->sid);
704 TALLOC_FREE(tmp_ctx);
708 /* the rpc backend methods are exposed via this structure */
709 struct winbindd_methods builtin_passdb_methods = {
711 builtin_query_user_list,
712 builtin_enum_dom_groups,
720 builtin_lookup_groupmem,
724 builtin_trusted_domains,
727 /* the rpc backend methods are exposed via this structure */
728 struct winbindd_methods sam_passdb_methods = {