Attempt to fix Coverity ID 596
[Samba.git] / source / winbindd / winbindd_passdb.c
blob8387565a74c0b0345de497b0c2bc35923fae75e4
1 /*
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/>.
25 #include "includes.h"
26 #include "winbindd.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_WINBIND
31 static NTSTATUS enum_groups_internal(struct winbindd_domain *domain,
32 TALLOC_CTX *mem_ctx,
33 uint32 *num_entries,
34 struct acct_info **info,
35 enum lsa_SidType sidtype)
37 struct pdb_search *search;
38 struct samr_displayentry *entries;
39 int i;
40 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
42 if (sidtype == SID_NAME_ALIAS) {
43 search = pdb_search_aliases(&domain->sid);
44 } else {
45 search = pdb_search_groups();
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;
54 goto done;
57 *info = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
58 if (*info == NULL) {
59 result = NT_STATUS_NO_MEMORY;
60 goto done;
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;
70 done:
71 pdb_search_destroy(search);
72 return result;
75 /* List all local groups (aliases) */
76 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
77 TALLOC_CTX *mem_ctx,
78 uint32 *num_entries,
79 struct acct_info **info)
81 return enum_groups_internal(domain,
82 mem_ctx,
83 num_entries,
84 info,
85 SID_NAME_ALIAS);
88 /* convert a single name to a sid in a domain */
89 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
90 TALLOC_CTX *mem_ctx,
91 enum winbindd_cmd original_cmd,
92 const char *domain_name,
93 const char *name,
94 DOM_SID *sid,
95 enum lsa_SidType *type)
97 uint32 flags = LOOKUP_NAME_ALL;
99 switch ( original_cmd ) {
100 case WINBINDD_LOOKUPNAME:
101 /* This call is ok */
102 break;
103 default:
104 /* Avoid any NSS calls in the lookup_name by default */
105 flags |= LOOKUP_NAME_EXPLICIT;
106 DEBUG(10,("winbindd_passdb: limiting name_to_sid() to explicit mappings\n"));
107 break;
110 DEBUG(10, ("Finding name %s\n", name));
112 if ( !lookup_name( mem_ctx, name, flags, NULL, NULL, sid, type ) ) {
113 return NT_STATUS_NONE_MAPPED;
116 return NT_STATUS_OK;
120 convert a domain SID to a user or group name
122 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
123 TALLOC_CTX *mem_ctx,
124 const DOM_SID *sid,
125 char **domain_name,
126 char **name,
127 enum lsa_SidType *type)
129 const char *dom, *nam;
131 DEBUG(10, ("Converting SID %s\n", sid_string_dbg(sid)));
133 /* Paranoia check */
134 if (!sid_check_is_in_builtin(sid) &&
135 !sid_check_is_in_our_domain(sid) &&
136 !sid_check_is_in_unix_users(sid) &&
137 !sid_check_is_unix_users(sid) &&
138 !sid_check_is_in_unix_groups(sid) &&
139 !sid_check_is_unix_groups(sid) &&
140 !sid_check_is_in_wellknown_domain(sid))
142 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
143 "passdb backend\n", sid_string_dbg(sid)));
144 return NT_STATUS_NONE_MAPPED;
147 if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) {
148 return NT_STATUS_NONE_MAPPED;
151 *domain_name = talloc_strdup(mem_ctx, dom);
152 *name = talloc_strdup(mem_ctx, nam);
154 return NT_STATUS_OK;
157 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
158 TALLOC_CTX *mem_ctx,
159 const DOM_SID *sid,
160 uint32 *rids,
161 size_t num_rids,
162 char **domain_name,
163 char ***names,
164 enum lsa_SidType **types)
166 size_t i;
167 bool have_mapped;
168 bool have_unmapped;
170 *domain_name = NULL;
171 *names = NULL;
172 *types = NULL;
174 if (!num_rids) {
175 return NT_STATUS_OK;
178 /* Paranoia check */
179 if (!sid_check_is_in_builtin(sid) &&
180 !sid_check_is_in_our_domain(sid) &&
181 !sid_check_is_in_unix_users(sid) &&
182 !sid_check_is_unix_users(sid) &&
183 !sid_check_is_in_unix_groups(sid) &&
184 !sid_check_is_unix_groups(sid) &&
185 !sid_check_is_in_wellknown_domain(sid))
187 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
188 "passdb backend\n", sid_string_dbg(sid)));
189 return NT_STATUS_NONE_MAPPED;
192 *names = TALLOC_ARRAY(mem_ctx, char *, num_rids);
193 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
195 if ((*names == NULL) || (*types == NULL)) {
196 return NT_STATUS_NO_MEMORY;
199 have_mapped = have_unmapped = false;
201 for (i=0; i<num_rids; i++) {
202 DOM_SID lsid;
203 const char *dom = NULL, *nam = NULL;
204 enum lsa_SidType type = SID_NAME_UNKNOWN;
206 if (!sid_compose(&lsid, sid, rids[i])) {
207 return NT_STATUS_INTERNAL_ERROR;
210 if (!lookup_sid(mem_ctx, &lsid, &dom, &nam, &type)) {
211 have_unmapped = true;
212 (*types)[i] = SID_NAME_UNKNOWN;
213 (*names)[i] = talloc_strdup(mem_ctx, "");
214 } else {
215 have_mapped = true;
216 (*types)[i] = type;
217 (*names)[i] = CONST_DISCARD(char *, nam);
220 if (*domain_name == NULL) {
221 *domain_name = CONST_DISCARD(char *, dom);
222 } else {
223 char *dname = CONST_DISCARD(char *, dom);
224 TALLOC_FREE(dname);
228 if (!have_mapped) {
229 return NT_STATUS_NONE_MAPPED;
231 if (!have_unmapped) {
232 return NT_STATUS_OK;
234 return STATUS_SOME_UNMAPPED;
237 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
238 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
239 TALLOC_CTX *mem_ctx,
240 const DOM_SID *user_sid,
241 uint32 *num_groups, DOM_SID **user_gids)
243 NTSTATUS result;
244 DOM_SID *groups = NULL;
245 gid_t *gids = NULL;
246 size_t ngroups = 0;
247 struct samu *user;
249 if ( (user = samu_new(mem_ctx)) == NULL ) {
250 return NT_STATUS_NO_MEMORY;
253 if ( !pdb_getsampwsid( user, user_sid ) ) {
254 return NT_STATUS_NO_SUCH_USER;
257 result = pdb_enum_group_memberships( mem_ctx, user, &groups, &gids, &ngroups );
259 TALLOC_FREE( user );
261 *num_groups = (uint32)ngroups;
262 *user_gids = groups;
264 return result;
267 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
268 TALLOC_CTX *mem_ctx,
269 uint32 num_sids, const DOM_SID *sids,
270 uint32 *p_num_aliases, uint32 **rids)
272 NTSTATUS result;
273 size_t num_aliases = 0;
275 result = pdb_enum_alias_memberships(mem_ctx, &domain->sid,
276 sids, num_sids, rids, &num_aliases);
278 *p_num_aliases = num_aliases;
279 return result;
282 /* find the sequence number for a domain */
283 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
285 bool result;
286 time_t seq_num;
288 result = pdb_get_seq_num(&seq_num);
289 if (!result) {
290 *seq = 1;
293 *seq = (int) seq_num;
294 /* *seq = 1; */
295 return NT_STATUS_OK;
298 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
299 TALLOC_CTX *mem_ctx,
300 struct samr_DomInfo12 *policy)
302 /* actually we have that */
303 return NT_STATUS_NOT_IMPLEMENTED;
306 static NTSTATUS password_policy(struct winbindd_domain *domain,
307 TALLOC_CTX *mem_ctx,
308 struct samr_DomInfo1 *policy)
310 uint32 min_pass_len,pass_hist,password_properties;
311 time_t u_expire, u_min_age;
312 NTTIME nt_expire, nt_min_age;
313 uint32 account_policy_temp;
315 if ((policy = TALLOC_ZERO_P(mem_ctx, struct samr_DomInfo1)) == NULL) {
316 return NT_STATUS_NO_MEMORY;
319 if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp)) {
320 return NT_STATUS_ACCESS_DENIED;
322 min_pass_len = account_policy_temp;
324 if (!pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp)) {
325 return NT_STATUS_ACCESS_DENIED;
327 pass_hist = account_policy_temp;
329 if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp)) {
330 return NT_STATUS_ACCESS_DENIED;
332 password_properties = account_policy_temp;
334 if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp)) {
335 return NT_STATUS_ACCESS_DENIED;
337 u_expire = account_policy_temp;
339 if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp)) {
340 return NT_STATUS_ACCESS_DENIED;
342 u_min_age = account_policy_temp;
344 unix_to_nt_time_abs(&nt_expire, u_expire);
345 unix_to_nt_time_abs(&nt_min_age, u_min_age);
347 init_samr_DomInfo1(policy,
348 (uint16)min_pass_len,
349 (uint16)pass_hist,
350 password_properties,
351 nt_expire,
352 nt_min_age);
354 return NT_STATUS_OK;
357 /*********************************************************************
358 BUILTIN specific functions.
359 *********************************************************************/
361 /* list all domain groups */
362 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
363 TALLOC_CTX *mem_ctx,
364 uint32 *num_entries,
365 struct acct_info **info)
367 /* BUILTIN doesn't have domain groups */
368 *num_entries = 0;
369 *info = NULL;
370 return NT_STATUS_OK;
373 /* Query display info for a domain. This returns enough information plus a
374 bit extra to give an overview of domain users for the User Manager
375 application. */
376 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
377 TALLOC_CTX *mem_ctx,
378 uint32 *num_entries,
379 WINBIND_USERINFO **info)
381 /* We don't have users */
382 *num_entries = 0;
383 *info = NULL;
384 return NT_STATUS_OK;
387 /* Lookup user information from a rid or username. */
388 static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
389 TALLOC_CTX *mem_ctx,
390 const DOM_SID *user_sid,
391 WINBIND_USERINFO *user_info)
393 return NT_STATUS_NO_SUCH_USER;
396 static NTSTATUS builtin_lookup_groupmem(struct winbindd_domain *domain,
397 TALLOC_CTX *mem_ctx,
398 const DOM_SID *group_sid, uint32 *num_names,
399 DOM_SID **sid_mem, char ***names,
400 uint32 **name_types)
402 *num_names = 0;
403 *sid_mem = NULL;
404 *names = NULL;
405 *name_types = 0;
406 return NT_STATUS_NO_SUCH_GROUP;
409 /* get a list of trusted domains - builtin domain */
410 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
411 TALLOC_CTX *mem_ctx,
412 uint32 *num_domains,
413 char ***names,
414 char ***alt_names,
415 DOM_SID **dom_sids)
417 *num_domains = 0;
418 *names = NULL;
419 *alt_names = NULL;
420 *dom_sids = NULL;
421 return NT_STATUS_OK;
424 /*********************************************************************
425 SAM specific functions.
426 *********************************************************************/
428 /* list all domain groups */
429 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
430 TALLOC_CTX *mem_ctx,
431 uint32 *num_entries,
432 struct acct_info **info)
434 return enum_groups_internal(domain,
435 mem_ctx,
436 num_entries,
437 info,
438 SID_NAME_DOM_GRP);
441 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
442 TALLOC_CTX *mem_ctx,
443 uint32 *num_entries,
444 WINBIND_USERINFO **info)
446 struct pdb_search *ps = pdb_search_users(ACB_NORMAL);
447 struct samr_displayentry *entries = NULL;
448 uint32 i;
450 *num_entries = 0;
451 *info = NULL;
453 if (!ps) {
454 return NT_STATUS_NO_MEMORY;
457 *num_entries = pdb_search_entries(ps,
458 1, 0xffffffff,
459 &entries);
461 *info = TALLOC_ZERO_ARRAY(mem_ctx, WINBIND_USERINFO, *num_entries);
462 if (!(*info)) {
463 pdb_search_destroy(ps);
464 return NT_STATUS_NO_MEMORY;
467 for (i = 0; i < *num_entries; i++) {
468 struct samr_displayentry *e = &entries[i];
470 (*info)[i].acct_name = talloc_strdup(mem_ctx, e->account_name );
471 (*info)[i].full_name = talloc_strdup(mem_ctx, e->fullname );
472 (*info)[i].homedir = NULL;
473 (*info)[i].shell = NULL;
474 sid_compose(&(*info)[i].user_sid, &domain->sid, e->rid);
476 /* For the moment we set the primary group for
477 every user to be the Domain Users group.
478 There are serious problems with determining
479 the actual primary group for large domains.
480 This should really be made into a 'winbind
481 force group' smb.conf parameter or
482 something like that. */
484 sid_compose(&(*info)[i].group_sid, &domain->sid,
485 DOMAIN_GROUP_RID_USERS);
488 pdb_search_destroy(ps);
489 return NT_STATUS_OK;
492 /* Lookup user information from a rid or username. */
493 static NTSTATUS sam_query_user(struct winbindd_domain *domain,
494 TALLOC_CTX *mem_ctx,
495 const DOM_SID *user_sid,
496 WINBIND_USERINFO *user_info)
498 struct samu *sampass = NULL;
500 ZERO_STRUCTP(user_info);
502 if (!sid_check_is_in_our_domain(user_sid)) {
503 return NT_STATUS_NO_SUCH_USER;
506 DEBUG(10,("sam_query_user: getting samu info for sid %s\n",
507 sid_string_dbg(user_sid) ));
509 if (!(sampass = samu_new(mem_ctx))) {
510 return NT_STATUS_NO_MEMORY;
513 if (!pdb_getsampwsid(sampass, user_sid)) {
514 TALLOC_FREE(sampass);
515 return NT_STATUS_NO_SUCH_USER;
518 if (pdb_get_group_sid(sampass) == NULL) {
519 TALLOC_FREE(sampass);
520 return NT_STATUS_NO_SUCH_GROUP;
523 DEBUG(10,("sam_query_user: group sid %s\n",
524 sid_string_dbg(sampass->group_sid) ));
526 sid_copy(&user_info->user_sid, user_sid);
527 sid_copy(&user_info->group_sid, sampass->group_sid);
529 user_info->acct_name = talloc_strdup(mem_ctx, sampass->username ?
530 sampass->username : "");
531 user_info->full_name = talloc_strdup(mem_ctx, sampass->full_name ?
532 sampass->full_name : "");
533 user_info->homedir = talloc_strdup(mem_ctx, sampass->home_dir ?
534 sampass->home_dir : "");
535 if (sampass->unix_pw && sampass->unix_pw->pw_shell) {
536 user_info->shell = talloc_strdup(mem_ctx, sampass->unix_pw->pw_shell);
537 } else {
538 user_info->shell = talloc_strdup(mem_ctx, "");
540 user_info->primary_gid = sampass->unix_pw ? sampass->unix_pw->pw_gid : (gid_t)-1;
542 TALLOC_FREE(sampass);
543 return NT_STATUS_OK;
546 /* Lookup group membership given a rid. */
547 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
548 TALLOC_CTX *mem_ctx,
549 const DOM_SID *group_sid, uint32 *num_names,
550 DOM_SID **sid_mem, char ***names,
551 uint32 **name_types)
553 size_t i, num_members, num_mapped;
554 uint32 *rids;
555 NTSTATUS result;
556 const DOM_SID **sids;
557 struct lsa_dom_info *lsa_domains;
558 struct lsa_name_info *lsa_names;
559 TALLOC_CTX *tmp_ctx;
561 if (!sid_check_is_in_our_domain(group_sid)) {
562 /* There's no groups, only aliases in BUILTIN */
563 return NT_STATUS_NO_SUCH_GROUP;
566 if (!(tmp_ctx = talloc_init("lookup_groupmem"))) {
567 return NT_STATUS_NO_MEMORY;
570 result = pdb_enum_group_members(tmp_ctx, group_sid, &rids,
571 &num_members);
572 if (!NT_STATUS_IS_OK(result)) {
573 TALLOC_FREE(tmp_ctx);
574 return result;
577 if (num_members == 0) {
578 *num_names = 0;
579 *sid_mem = NULL;
580 *names = NULL;
581 *name_types = NULL;
582 TALLOC_FREE(tmp_ctx);
583 return NT_STATUS_OK;
586 *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members);
587 *names = TALLOC_ARRAY(mem_ctx, char *, num_members);
588 *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members);
589 sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members);
591 if (((*sid_mem) == NULL) || ((*names) == NULL) ||
592 ((*name_types) == NULL) || (sids == NULL)) {
593 TALLOC_FREE(tmp_ctx);
594 return NT_STATUS_NO_MEMORY;
598 * Prepare an array of sid pointers for the lookup_sids calling
599 * convention.
602 for (i=0; i<num_members; i++) {
603 DOM_SID *sid = &((*sid_mem)[i]);
604 if (!sid_compose(sid, &domain->sid, rids[i])) {
605 TALLOC_FREE(tmp_ctx);
606 return NT_STATUS_INTERNAL_ERROR;
608 sids[i] = sid;
611 result = lookup_sids(tmp_ctx, num_members, sids, 1,
612 &lsa_domains, &lsa_names);
613 if (!NT_STATUS_IS_OK(result)) {
614 TALLOC_FREE(tmp_ctx);
615 return result;
618 num_mapped = 0;
619 for (i=0; i<num_members; i++) {
620 if (lsa_names[i].type != SID_NAME_USER) {
621 DEBUG(2, ("Got %s as group member -- ignoring\n",
622 sid_type_lookup(lsa_names[i].type)));
623 continue;
625 if (!((*names)[i] = talloc_strdup((*names),
626 lsa_names[i].name))) {
627 TALLOC_FREE(tmp_ctx);
628 return NT_STATUS_NO_MEMORY;
631 (*name_types)[i] = lsa_names[i].type;
633 num_mapped += 1;
636 *num_names = num_mapped;
638 TALLOC_FREE(tmp_ctx);
639 return NT_STATUS_OK;
642 /* get a list of trusted domains */
643 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
644 TALLOC_CTX *mem_ctx,
645 uint32 *num_domains,
646 char ***names,
647 char ***alt_names,
648 DOM_SID **dom_sids)
650 NTSTATUS nt_status;
651 struct trustdom_info **domains;
652 int i;
653 TALLOC_CTX *tmp_ctx;
655 *num_domains = 0;
656 *names = NULL;
657 *alt_names = NULL;
658 *dom_sids = NULL;
660 if (!(tmp_ctx = talloc_init("trusted_domains"))) {
661 return NT_STATUS_NO_MEMORY;
664 nt_status = pdb_enum_trusteddoms(tmp_ctx, num_domains, &domains);
665 if (!NT_STATUS_IS_OK(nt_status)) {
666 TALLOC_FREE(tmp_ctx);
667 return nt_status;
670 if (*num_domains) {
671 *names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
672 *alt_names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
673 *dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
675 if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) {
676 TALLOC_FREE(tmp_ctx);
677 return NT_STATUS_NO_MEMORY;
679 } else {
680 *names = NULL;
681 *alt_names = NULL;
682 *dom_sids = NULL;
685 for (i=0; i<*num_domains; i++) {
686 (*alt_names)[i] = NULL;
687 if (!((*names)[i] = talloc_strdup((*names),
688 domains[i]->name))) {
689 TALLOC_FREE(tmp_ctx);
690 return NT_STATUS_NO_MEMORY;
692 sid_copy(&(*dom_sids)[i], &domains[i]->sid);
695 TALLOC_FREE(tmp_ctx);
696 return NT_STATUS_OK;
699 /* the rpc backend methods are exposed via this structure */
700 struct winbindd_methods builtin_passdb_methods = {
701 false,
702 builtin_query_user_list,
703 builtin_enum_dom_groups,
704 enum_local_groups,
705 name_to_sid,
706 sid_to_name,
707 rids_to_names,
708 builtin_query_user,
709 lookup_usergroups,
710 lookup_useraliases,
711 builtin_lookup_groupmem,
712 sequence_number,
713 lockout_policy,
714 password_policy,
715 builtin_trusted_domains,
718 /* the rpc backend methods are exposed via this structure */
719 struct winbindd_methods sam_passdb_methods = {
720 false,
721 sam_query_user_list,
722 sam_enum_dom_groups,
723 enum_local_groups,
724 name_to_sid,
725 sid_to_name,
726 rids_to_names,
727 sam_query_user,
728 lookup_usergroups,
729 lookup_useraliases,
730 sam_lookup_groupmem,
731 sequence_number,
732 lockout_policy,
733 password_policy,
734 sam_trusted_domains,