VERSION: Raise version number up to 3.0.36.
[Samba.git] / source / nsswitch / winbindd_passdb.c
blobe22a20723dc1be00b532fea3ba9d106cd5dc0866
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 2 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, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
27 #include "winbindd.h"
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_WINBIND
32 static NTSTATUS enum_groups_internal(struct winbindd_domain *domain,
33 TALLOC_CTX *mem_ctx,
34 uint32 *num_entries,
35 struct acct_info **info,
36 enum lsa_SidType sidtype)
38 struct pdb_search *search;
39 struct samr_displayentry *entries;
40 int i;
41 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
43 if (sidtype == SID_NAME_ALIAS) {
44 search = pdb_search_aliases(&domain->sid);
45 } else {
46 search = pdb_search_groups();
49 if (search == NULL) goto done;
51 *num_entries = pdb_search_entries(search, 0, 0xffffffff, &entries);
52 if (*num_entries == 0) {
53 /* Zero entries isn't an error */
54 result = NT_STATUS_OK;
55 goto done;
58 *info = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
59 if (*info == NULL) {
60 result = NT_STATUS_NO_MEMORY;
61 goto done;
64 for (i=0; i<*num_entries; i++) {
65 fstrcpy((*info)[i].acct_name, entries[i].account_name);
66 fstrcpy((*info)[i].acct_desc, entries[i].description);
67 (*info)[i].rid = entries[i].rid;
70 result = NT_STATUS_OK;
71 done:
72 pdb_search_destroy(search);
73 return result;
76 /* List all local groups (aliases) */
77 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
78 TALLOC_CTX *mem_ctx,
79 uint32 *num_entries,
80 struct acct_info **info)
82 return enum_groups_internal(domain,
83 mem_ctx,
84 num_entries,
85 info,
86 SID_NAME_ALIAS);
89 /* convert a single name to a sid in a domain */
90 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
91 TALLOC_CTX *mem_ctx,
92 const char *domain_name,
93 const char *name,
94 DOM_SID *sid,
95 enum lsa_SidType *type)
97 DEBUG(10, ("Finding name %s\n", name));
99 if ( !lookup_name( mem_ctx, name, LOOKUP_NAME_ALL,
100 NULL, NULL, sid, type ) )
102 return NT_STATUS_NONE_MAPPED;
105 return NT_STATUS_OK;
109 convert a domain SID to a user or group name
111 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
112 TALLOC_CTX *mem_ctx,
113 const DOM_SID *sid,
114 char **domain_name,
115 char **name,
116 enum lsa_SidType *type)
118 const char *dom, *nam;
120 DEBUG(10, ("Converting SID %s\n", sid_string_static(sid)));
122 /* Paranoia check */
123 if (!sid_check_is_in_builtin(sid) &&
124 !sid_check_is_in_our_domain(sid)) {
125 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
126 "passdb backend\n", sid_string_static(sid)));
127 return NT_STATUS_NONE_MAPPED;
130 if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) {
131 return NT_STATUS_NONE_MAPPED;
134 *domain_name = talloc_strdup(mem_ctx, dom);
135 *name = talloc_strdup(mem_ctx, nam);
137 return NT_STATUS_OK;
140 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
141 TALLOC_CTX *mem_ctx,
142 const DOM_SID *domain_sid,
143 uint32 *rids,
144 size_t num_rids,
145 char **domain_name,
146 char ***names,
147 enum lsa_SidType **types)
149 size_t i;
150 bool have_mapped;
151 bool have_unmapped;
153 *domain_name = NULL;
154 *names = NULL;
155 *types = NULL;
157 if (!num_rids) {
158 return NT_STATUS_OK;
161 *names = TALLOC_ARRAY(mem_ctx, char *, num_rids);
162 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
164 if ((*names == NULL) || (*types == NULL)) {
165 return NT_STATUS_NO_MEMORY;
168 have_mapped = have_unmapped = false;
170 for (i=0; i<num_rids; i++) {
171 DOM_SID sid;
172 const char *dom = NULL, *nam = NULL;
173 enum lsa_SidType type = SID_NAME_UNKNOWN;
175 if (!sid_compose(&sid, domain_sid, rids[i])) {
176 return NT_STATUS_INTERNAL_ERROR;
179 if (!lookup_sid(mem_ctx, &sid, &dom, &nam, &type)) {
180 have_unmapped = true;
181 (*types)[i] = SID_NAME_UNKNOWN;
182 (*names)[i] = talloc_strdup(mem_ctx, "");
183 } else {
184 have_mapped = true;
185 (*types)[i] = type;
186 (*names)[i] = CONST_DISCARD(char *, nam);
189 if (domain_name == NULL) {
190 *domain_name = CONST_DISCARD(char *, dom);
191 } else {
192 char *dname = CONST_DISCARD(char *, dom);
193 TALLOC_FREE(dname);
197 if (!have_mapped) {
198 return NT_STATUS_NONE_MAPPED;
200 if (!have_unmapped) {
201 return NT_STATUS_OK;
203 return STATUS_SOME_UNMAPPED;
206 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
207 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
208 TALLOC_CTX *mem_ctx,
209 const DOM_SID *user_sid,
210 uint32 *num_groups, DOM_SID **user_gids)
212 NTSTATUS result;
213 DOM_SID *groups = NULL;
214 gid_t *gids = NULL;
215 size_t ngroups = 0;
216 struct samu *user;
218 if ( (user = samu_new(mem_ctx)) == NULL ) {
219 return NT_STATUS_NO_MEMORY;
222 if (!pdb_getsampwsid(user, user_sid ) ) {
223 TALLOC_FREE( user );
224 return NT_STATUS_NO_SUCH_USER;
227 result = pdb_enum_group_memberships( mem_ctx, user, &groups, &gids, &ngroups );
229 TALLOC_FREE( user );
231 *num_groups = (uint32)ngroups;
232 *user_gids = groups;
234 return result;
237 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
238 TALLOC_CTX *mem_ctx,
239 uint32 num_sids, const DOM_SID *sids,
240 uint32 *p_num_aliases, uint32 **rids)
242 NTSTATUS result;
243 size_t num_aliases = 0;
245 result = pdb_enum_alias_memberships(mem_ctx, &domain->sid,
246 sids, num_sids, rids, &num_aliases);
248 *p_num_aliases = num_aliases;
249 return result;
252 /* find the sequence number for a domain */
253 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
255 BOOL result;
256 time_t seq_num;
258 result = pdb_get_seq_num(&seq_num);
259 if (!result) {
260 *seq = 1;
263 *seq = (int) seq_num;
264 /* *seq = 1; */
265 return NT_STATUS_OK;
268 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
269 TALLOC_CTX *mem_ctx,
270 SAM_UNK_INFO_12 *policy)
272 /* actually we have that */
273 return NT_STATUS_NOT_IMPLEMENTED;
276 static NTSTATUS password_policy(struct winbindd_domain *domain,
277 TALLOC_CTX *mem_ctx,
278 SAM_UNK_INFO_1 *policy)
280 uint32 min_pass_len,pass_hist,password_properties;
281 time_t u_expire, u_min_age;
282 NTTIME nt_expire, nt_min_age;
283 uint32 account_policy_temp;
285 if ((policy = TALLOC_ZERO_P(mem_ctx, SAM_UNK_INFO_1)) == NULL) {
286 return NT_STATUS_NO_MEMORY;
289 if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp)) {
290 return NT_STATUS_ACCESS_DENIED;
292 min_pass_len = account_policy_temp;
294 if (!pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp)) {
295 return NT_STATUS_ACCESS_DENIED;
297 pass_hist = account_policy_temp;
299 if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp)) {
300 return NT_STATUS_ACCESS_DENIED;
302 password_properties = account_policy_temp;
304 if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp)) {
305 return NT_STATUS_ACCESS_DENIED;
307 u_expire = account_policy_temp;
309 if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp)) {
310 return NT_STATUS_ACCESS_DENIED;
312 u_min_age = account_policy_temp;
314 unix_to_nt_time_abs(&nt_expire, u_expire);
315 unix_to_nt_time_abs(&nt_min_age, u_min_age);
317 init_unk_info1(policy, (uint16)min_pass_len, (uint16)pass_hist,
318 password_properties, nt_expire, nt_min_age);
320 return NT_STATUS_OK;
323 /*********************************************************************
324 BUILTIN specific functions.
325 *********************************************************************/
327 /* list all domain groups */
328 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
329 TALLOC_CTX *mem_ctx,
330 uint32 *num_entries,
331 struct acct_info **info)
333 /* BUILTIN doesn't have domain groups */
334 *num_entries = 0;
335 *info = NULL;
336 return NT_STATUS_OK;
339 /* Query display info for a domain. This returns enough information plus a
340 bit extra to give an overview of domain users for the User Manager
341 application. */
342 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
343 TALLOC_CTX *mem_ctx,
344 uint32 *num_entries,
345 WINBIND_USERINFO **info)
347 /* We don't have users */
348 *num_entries = 0;
349 *info = NULL;
350 return NT_STATUS_OK;
353 /* Lookup user information from a rid or username. */
354 static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
355 TALLOC_CTX *mem_ctx,
356 const DOM_SID *user_sid,
357 WINBIND_USERINFO *user_info)
359 return NT_STATUS_NO_SUCH_USER;
362 static NTSTATUS builtin_lookup_groupmem(struct winbindd_domain *domain,
363 TALLOC_CTX *mem_ctx,
364 const DOM_SID *group_sid, uint32 *num_names,
365 DOM_SID **sid_mem, char ***names,
366 uint32 **name_types)
368 *num_names = 0;
369 *sid_mem = NULL;
370 *names = NULL;
371 *name_types = 0;
372 return NT_STATUS_NO_SUCH_GROUP;
375 /* get a list of trusted domains - builtin domain */
376 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
377 TALLOC_CTX *mem_ctx,
378 uint32 *num_domains,
379 char ***names,
380 char ***alt_names,
381 DOM_SID **dom_sids)
383 *num_domains = 0;
384 *names = NULL;
385 *alt_names = NULL;
386 *dom_sids = NULL;
387 return NT_STATUS_OK;
390 /*********************************************************************
391 SAM specific functions.
392 *********************************************************************/
394 /* list all domain groups */
395 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
396 TALLOC_CTX *mem_ctx,
397 uint32 *num_entries,
398 struct acct_info **info)
400 return enum_groups_internal(domain,
401 mem_ctx,
402 num_entries,
403 info,
404 SID_NAME_DOM_GRP);
407 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
408 TALLOC_CTX *mem_ctx,
409 uint32 *num_entries,
410 WINBIND_USERINFO **info)
412 struct pdb_search *ps = pdb_search_users(ACB_NORMAL);
413 struct samr_displayentry *entries = NULL;
414 uint32 i;
416 *num_entries = 0;
417 *info = NULL;
419 if (!ps) {
420 return NT_STATUS_NO_MEMORY;
423 *num_entries = pdb_search_entries(ps,
424 1, 0xffffffff,
425 &entries);
427 *info = TALLOC_ZERO_ARRAY(mem_ctx, WINBIND_USERINFO, *num_entries);
428 if (!(*info)) {
429 pdb_search_destroy(ps);
430 return NT_STATUS_NO_MEMORY;
433 for (i = 0; i < *num_entries; i++) {
434 struct samr_displayentry *e = &entries[i];
436 (*info)[i].acct_name = talloc_strdup(mem_ctx, e->account_name );
437 (*info)[i].full_name = talloc_strdup(mem_ctx, e->fullname );
438 (*info)[i].homedir = NULL;
439 (*info)[i].shell = NULL;
440 sid_compose(&(*info)[i].user_sid, &domain->sid, e->rid);
442 /* For the moment we set the primary group for
443 every user to be the Domain Users group.
444 There are serious problems with determining
445 the actual primary group for large domains.
446 This should really be made into a 'winbind
447 force group' smb.conf parameter or
448 something like that. */
450 sid_compose(&(*info)[i].group_sid, &domain->sid,
451 DOMAIN_GROUP_RID_USERS);
454 pdb_search_destroy(ps);
455 return NT_STATUS_OK;
458 /* Lookup user information from a rid or username. */
459 static NTSTATUS sam_query_user(struct winbindd_domain *domain,
460 TALLOC_CTX *mem_ctx,
461 const DOM_SID *user_sid,
462 WINBIND_USERINFO *user_info)
464 struct samu *sampass = NULL;
465 fstring sidstr;
467 ZERO_STRUCTP(user_info);
469 if (!sid_check_is_in_our_domain(user_sid)) {
470 return NT_STATUS_NO_SUCH_USER;
473 sid_to_string(sidstr, user_sid);
474 DEBUG(10,("sam_query_user: getting samu info for sid %s\n",
475 sidstr ));
477 if (!(sampass = samu_new(mem_ctx))) {
478 return NT_STATUS_NO_MEMORY;
481 if (!pdb_getsampwsid(sampass, user_sid)) {
482 TALLOC_FREE(sampass);
483 return NT_STATUS_NO_SUCH_USER;
486 if (pdb_get_group_sid(sampass) == NULL) {
487 TALLOC_FREE(sampass);
488 return NT_STATUS_NO_SUCH_GROUP;
491 sid_to_string(sidstr, sampass->group_sid);
492 DEBUG(10,("sam_query_user: group sid %s\n", sidstr ));
494 sid_copy(&user_info->user_sid, user_sid);
495 sid_copy(&user_info->group_sid, sampass->group_sid);
497 user_info->acct_name = talloc_strdup(mem_ctx, sampass->username ?
498 sampass->username : "");
499 user_info->full_name = talloc_strdup(mem_ctx, sampass->full_name ?
500 sampass->full_name : "");
501 user_info->homedir = talloc_strdup(mem_ctx, sampass->home_dir ?
502 sampass->home_dir : "");
503 if (sampass->unix_pw && sampass->unix_pw->pw_shell) {
504 user_info->shell = talloc_strdup(mem_ctx, sampass->unix_pw->pw_shell);
505 } else {
506 user_info->shell = talloc_strdup(mem_ctx, "");
508 user_info->primary_gid = sampass->unix_pw ? sampass->unix_pw->pw_gid : (gid_t)-1;
510 TALLOC_FREE(sampass);
511 return NT_STATUS_OK;
514 /* Lookup group membership given a rid. */
515 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
516 TALLOC_CTX *mem_ctx,
517 const DOM_SID *group_sid, uint32 *num_names,
518 DOM_SID **sid_mem, char ***names,
519 uint32 **name_types)
521 size_t i, num_members, num_mapped;
522 uint32 *rids;
523 NTSTATUS result;
524 const DOM_SID **sids;
525 struct lsa_dom_info *lsa_domains;
526 struct lsa_name_info *lsa_names;
527 TALLOC_CTX *tmp_ctx;
529 if (!sid_check_is_in_our_domain(group_sid)) {
530 /* There's no groups, only aliases in BUILTIN */
531 return NT_STATUS_NO_SUCH_GROUP;
534 if (!(tmp_ctx = talloc_init("lookup_groupmem"))) {
535 return NT_STATUS_NO_MEMORY;
538 result = pdb_enum_group_members(tmp_ctx, group_sid, &rids,
539 &num_members);
540 if (!NT_STATUS_IS_OK(result)) {
541 TALLOC_FREE(tmp_ctx);
542 return result;
545 if (num_members == 0) {
546 *num_names = 0;
547 *sid_mem = NULL;
548 *names = NULL;
549 *name_types = NULL;
550 TALLOC_FREE(tmp_ctx);
551 return NT_STATUS_OK;
554 *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members);
555 *names = TALLOC_ARRAY(mem_ctx, char *, num_members);
556 *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members);
557 sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members);
559 if (((*sid_mem) == NULL) || ((*names) == NULL) ||
560 ((*name_types) == NULL) || (sids == NULL)) {
561 TALLOC_FREE(tmp_ctx);
562 return NT_STATUS_NO_MEMORY;
566 * Prepare an array of sid pointers for the lookup_sids calling
567 * convention.
570 for (i=0; i<num_members; i++) {
571 DOM_SID *sid = &((*sid_mem)[i]);
572 if (!sid_compose(sid, &domain->sid, rids[i])) {
573 TALLOC_FREE(tmp_ctx);
574 return NT_STATUS_INTERNAL_ERROR;
576 sids[i] = sid;
579 result = lookup_sids(tmp_ctx, num_members, sids, 1,
580 &lsa_domains, &lsa_names);
581 if (!NT_STATUS_IS_OK(result)) {
582 TALLOC_FREE(tmp_ctx);
583 return result;
586 num_mapped = 0;
587 for (i=0; i<num_members; i++) {
588 if (lsa_names[i].type != SID_NAME_USER) {
589 DEBUG(2, ("Got %s as group member -- ignoring\n",
590 sid_type_lookup(lsa_names[i].type)));
591 continue;
593 if (!((*names)[num_mapped] = talloc_strdup((*names),
594 lsa_names[i].name))) {
595 TALLOC_FREE(tmp_ctx);
596 return NT_STATUS_NO_MEMORY;
599 (*name_types)[num_mapped] = lsa_names[i].type;
601 num_mapped += 1;
604 *num_names = num_mapped;
606 TALLOC_FREE(tmp_ctx);
607 return NT_STATUS_OK;
610 /* get a list of trusted domains - sam */
611 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
612 TALLOC_CTX *mem_ctx,
613 uint32 *num_domains,
614 char ***names,
615 char ***alt_names,
616 DOM_SID **dom_sids)
618 NTSTATUS nt_status;
619 struct trustdom_info **domains;
620 int i;
621 TALLOC_CTX *tmp_ctx;
623 *num_domains = 0;
624 *names = NULL;
625 *alt_names = NULL;
626 *dom_sids = NULL;
628 if (!(tmp_ctx = talloc_init("trusted_domains"))) {
629 return NT_STATUS_NO_MEMORY;
632 nt_status = secrets_trusted_domains(tmp_ctx, num_domains,
633 &domains);
634 if (!NT_STATUS_IS_OK(nt_status)) {
635 TALLOC_FREE(tmp_ctx);
636 return nt_status;
639 if (*num_domains) {
640 *names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
641 *alt_names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
642 *dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
644 if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) {
645 TALLOC_FREE(tmp_ctx);
646 return NT_STATUS_NO_MEMORY;
648 } else {
649 *names = NULL;
650 *alt_names = NULL;
651 *dom_sids = NULL;
654 for (i=0; i<*num_domains; i++) {
655 (*alt_names)[i] = NULL;
656 if (!((*names)[i] = talloc_strdup((*names),
657 domains[i]->name))) {
658 TALLOC_FREE(tmp_ctx);
659 return NT_STATUS_NO_MEMORY;
661 sid_copy(&(*dom_sids)[i], &domains[i]->sid);
664 TALLOC_FREE(tmp_ctx);
665 return NT_STATUS_OK;
668 /* the rpc backend methods are exposed via this structure */
669 struct winbindd_methods builtin_passdb_methods = {
670 false,
671 builtin_query_user_list,
672 builtin_enum_dom_groups,
673 enum_local_groups,
674 name_to_sid,
675 sid_to_name,
676 rids_to_names,
677 builtin_query_user,
678 lookup_usergroups,
679 lookup_useraliases,
680 builtin_lookup_groupmem,
681 sequence_number,
682 lockout_policy,
683 password_policy,
684 builtin_trusted_domains,
687 /* the rpc backend methods are exposed via this structure */
688 struct winbindd_methods sam_passdb_methods = {
689 false,
690 sam_query_user_list,
691 sam_enum_dom_groups,
692 enum_local_groups,
693 name_to_sid,
694 sid_to_name,
695 rids_to_names,
696 sam_query_user,
697 lookup_usergroups,
698 lookup_useraliases,
699 sam_lookup_groupmem,
700 sequence_number,
701 lockout_policy,
702 password_policy,
703 sam_trusted_domains,