r20824: Send access to the trusted domain passwords through the pdb backend, so that
[jra/samba/.git] / source / nsswitch / winbindd_passdb.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind rpc backend functions
5
6    Copyright (C) Tim Potter 2000-2001,2003
7    Copyright (C) Simo Sorce 2003
8    Copyright (C) Volker Lendecke 2004
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "winbindd.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_WINBIND
30
31 static void add_member(const char *domain, const char *user,
32            char **pp_members, size_t *p_num_members)
33 {
34         fstring name;
35
36         fill_domain_username(name, domain, user, True);
37         safe_strcat(name, ",", sizeof(name)-1);
38         string_append(pp_members, name);
39         *p_num_members += 1;
40 }
41
42 /**********************************************************************
43  Add member users resulting from sid. Expand if it is a domain group.
44 **********************************************************************/
45
46 static void add_expanded_sid(const DOM_SID *sid, char **pp_members, size_t *p_num_members)
47 {
48         DOM_SID dom_sid;
49         uint32 rid;
50         struct winbindd_domain *domain;
51         size_t i;
52
53         char *domain_name = NULL;
54         char *name = NULL;
55         enum lsa_SidType type;
56
57         uint32 num_names;
58         DOM_SID *sid_mem;
59         char **names;
60         uint32 *types;
61
62         NTSTATUS result;
63
64         TALLOC_CTX *mem_ctx = talloc_init("add_expanded_sid");
65
66         if (mem_ctx == NULL) {
67                 DEBUG(1, ("talloc_init failed\n"));
68                 return;
69         }
70
71         sid_copy(&dom_sid, sid);
72         sid_split_rid(&dom_sid, &rid);
73
74         domain = find_lookup_domain_from_sid(sid);
75
76         if (domain == NULL) {
77                 DEBUG(3, ("Could not find domain for sid %s\n",
78                           sid_string_static(sid)));
79                 goto done;
80         }
81
82         result = domain->methods->sid_to_name(domain, mem_ctx, sid,
83                                               &domain_name, &name, &type);
84
85         if (!NT_STATUS_IS_OK(result)) {
86                 DEBUG(3, ("sid_to_name failed for sid %s\n",
87                           sid_string_static(sid)));
88                 goto done;
89         }
90
91         DEBUG(10, ("Found name %s, type %d\n", name, type));
92
93         if (type == SID_NAME_USER) {
94                 add_member(domain_name, name, pp_members, p_num_members);
95                 goto done;
96         }
97
98         if (type != SID_NAME_DOM_GRP) {
99                 DEBUG(10, ("Alias member %s neither user nor group, ignore\n",
100                            name));
101                 goto done;
102         }
103
104         /* Expand the domain group, this must be done via the target domain */
105
106         domain = find_domain_from_sid(sid);
107
108         if (domain == NULL) {
109                 DEBUG(3, ("Could not find domain from SID %s\n",
110                           sid_string_static(sid)));
111                 goto done;
112         }
113
114         result = domain->methods->lookup_groupmem(domain, mem_ctx,
115                                                   sid, &num_names,
116                                                   &sid_mem, &names,
117                                                   &types);
118
119         if (!NT_STATUS_IS_OK(result)) {
120                 DEBUG(10, ("Could not lookup group members for %s: %s\n",
121                            name, nt_errstr(result)));
122                 goto done;
123         }
124
125         for (i=0; i<num_names; i++) {
126                 DEBUG(10, ("Adding group member SID %s\n",
127                            sid_string_static(&sid_mem[i])));
128
129                 if (types[i] != SID_NAME_USER) {
130                         DEBUG(1, ("Hmmm. Member %s of group %s is no user. "
131                                   "Ignoring.\n", names[i], name));
132                         continue;
133                 }
134
135                 add_member(domain->name, names[i], pp_members, p_num_members);
136         }
137
138  done:
139         talloc_destroy(mem_ctx);
140         return;
141 }
142
143 BOOL fill_passdb_alias_grmem(struct winbindd_domain *domain,
144                              DOM_SID *group_sid, 
145                              size_t *num_gr_mem, char **gr_mem, size_t *gr_mem_len)
146 {
147         DOM_SID *members;
148         size_t i, num_members;
149
150         *num_gr_mem = 0;
151         *gr_mem = NULL;
152         *gr_mem_len = 0;
153
154         if (!NT_STATUS_IS_OK(pdb_enum_aliasmem(group_sid, &members,
155                                                &num_members)))
156                 return True;
157
158         for (i=0; i<num_members; i++) {
159                 add_expanded_sid(&members[i], gr_mem, num_gr_mem);
160         }
161
162         SAFE_FREE(members);
163
164         if (*gr_mem != NULL) {
165                 size_t len;
166
167                 /* We have at least one member, strip off the last "," */
168                 len = strlen(*gr_mem);
169                 (*gr_mem)[len-1] = '\0';
170                 *gr_mem_len = len;
171         }
172
173         return True;
174 }
175
176 /* Query display info for a domain.  This returns enough information plus a
177    bit extra to give an overview of domain users for the User Manager
178    application. */
179 static NTSTATUS query_user_list(struct winbindd_domain *domain,
180                                TALLOC_CTX *mem_ctx,
181                                uint32 *num_entries, 
182                                WINBIND_USERINFO **info)
183 {
184         /* We don't have users */
185         *num_entries = 0;
186         *info = NULL;
187         return NT_STATUS_OK;
188 }
189
190 /* list all domain groups */
191 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
192                                 TALLOC_CTX *mem_ctx,
193                                 uint32 *num_entries, 
194                                 struct acct_info **info)
195 {
196         /* We don't have domain groups */
197         *num_entries = 0;
198         *info = NULL;
199         return NT_STATUS_OK;
200 }
201
202 /* List all domain groups */
203
204 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
205                                 TALLOC_CTX *mem_ctx,
206                                 uint32 *num_entries, 
207                                 struct acct_info **info)
208 {
209         struct pdb_search *search;
210         struct samr_displayentry *aliases;
211         int i;
212         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
213
214         search = pdb_search_aliases(&domain->sid);
215         if (search == NULL) goto done;
216
217         *num_entries = pdb_search_entries(search, 0, 0xffffffff, &aliases);
218         if (*num_entries == 0) goto done;
219
220         *info = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
221         if (*info == NULL) {
222                 result = NT_STATUS_NO_MEMORY;
223                 goto done;
224         }
225
226         for (i=0; i<*num_entries; i++) {
227                 fstrcpy((*info)[i].acct_name, aliases[i].account_name);
228                 fstrcpy((*info)[i].acct_desc, aliases[i].description);
229                 (*info)[i].rid = aliases[i].rid;
230         }
231
232         result = NT_STATUS_OK;
233  done:
234         pdb_search_destroy(search);
235         return result;
236 }
237
238 /* convert a single name to a sid in a domain */
239 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
240                             TALLOC_CTX *mem_ctx,
241                             const char *domain_name,
242                             const char *name,
243                             DOM_SID *sid,
244                             enum lsa_SidType *type)
245 {
246         DEBUG(10, ("Finding name %s\n", name));
247
248         if ( !lookup_name( mem_ctx, name, LOOKUP_NAME_ALL, 
249                 NULL, NULL, sid, type ) )
250         {
251                 return NT_STATUS_NONE_MAPPED;
252         }
253
254         return NT_STATUS_OK;
255 }
256
257 /*
258   convert a domain SID to a user or group name
259 */
260 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
261                             TALLOC_CTX *mem_ctx,
262                             const DOM_SID *sid,
263                             char **domain_name,
264                             char **name,
265                             enum lsa_SidType *type)
266 {
267         const char *dom, *nam;
268
269         DEBUG(10, ("Converting SID %s\n", sid_string_static(sid)));
270
271         /* Paranoia check */
272         if (!sid_check_is_in_builtin(sid) &&
273             !sid_check_is_in_our_domain(sid)) {
274                 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
275                           "passdb backend\n", sid_string_static(sid)));
276                 return NT_STATUS_NONE_MAPPED;
277         }
278
279         if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) {
280                 return NT_STATUS_NONE_MAPPED;
281         }
282
283         *domain_name = talloc_strdup(mem_ctx, dom);
284         *name = talloc_strdup(mem_ctx, nam);
285
286         return NT_STATUS_OK;
287 }
288
289 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
290                               TALLOC_CTX *mem_ctx,
291                               const DOM_SID *sid,
292                               uint32 *rids,
293                               size_t num_rids,
294                               char **domain_name,
295                               char ***names,
296                               enum lsa_SidType **types)
297 {
298         return NT_STATUS_UNSUCCESSFUL;
299 }
300
301 /* Lookup user information from a rid or username. */
302 static NTSTATUS query_user(struct winbindd_domain *domain, 
303                            TALLOC_CTX *mem_ctx, 
304                            const DOM_SID *user_sid,
305                            WINBIND_USERINFO *user_info)
306 {
307         return NT_STATUS_NO_SUCH_USER;
308 }
309
310 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
311 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
312                                   TALLOC_CTX *mem_ctx,
313                                   const DOM_SID *user_sid,
314                                   uint32 *num_groups, DOM_SID **user_gids)
315 {
316         NTSTATUS result;
317         DOM_SID *groups = NULL;
318         gid_t *gids = NULL;
319         size_t ngroups = 0;
320         struct samu *user;
321
322         if ( (user = samu_new(mem_ctx)) == NULL ) {
323                 return NT_STATUS_NO_MEMORY;
324         }
325
326         if ( !pdb_getsampwsid( user, user_sid ) ) {
327                 return NT_STATUS_NO_SUCH_USER;
328         }
329
330         result = pdb_enum_group_memberships( mem_ctx, user, &groups, &gids, &ngroups );
331
332         TALLOC_FREE( user );
333
334         *num_groups = (uint32)ngroups;
335         *user_gids = groups;
336
337         return result;
338 }
339
340 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
341                                    TALLOC_CTX *mem_ctx,
342                                    uint32 num_sids, const DOM_SID *sids,
343                                    uint32 *p_num_aliases, uint32 **rids)
344 {
345         NTSTATUS result;
346         size_t num_aliases = 0;
347
348         result = pdb_enum_alias_memberships(mem_ctx, &domain->sid,
349                                             sids, num_sids, rids, &num_aliases);
350
351         *p_num_aliases = num_aliases;
352         return result;
353 }
354
355 /* Lookup group membership given a rid.   */
356 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
357                                 TALLOC_CTX *mem_ctx,
358                                 const DOM_SID *group_sid, uint32 *num_names, 
359                                 DOM_SID **sid_mem, char ***names, 
360                                 uint32 **name_types)
361 {
362         size_t i, num_members, num_mapped;
363         uint32 *rids;
364         NTSTATUS result;
365         const DOM_SID **sids;
366         struct lsa_dom_info *lsa_domains;
367         struct lsa_name_info *lsa_names;
368         TALLOC_CTX *tmp_ctx;
369
370         if (!sid_check_is_in_our_domain(group_sid)) {
371                 /* There's no groups, only aliases in BUILTIN */
372                 return NT_STATUS_NO_SUCH_GROUP;
373         }
374
375         if (!(tmp_ctx = talloc_init("lookup_groupmem"))) {
376                 return NT_STATUS_NO_MEMORY;
377         }
378
379         result = pdb_enum_group_members(tmp_ctx, group_sid, &rids,
380                                         &num_members);
381         if (!NT_STATUS_IS_OK(result)) {
382                 TALLOC_FREE(tmp_ctx);
383                 return result;
384         }
385
386         if (num_members == 0) {
387                 *num_names = 0;
388                 *sid_mem = NULL;
389                 *names = NULL;
390                 *name_types = NULL;
391                 TALLOC_FREE(tmp_ctx);
392                 return NT_STATUS_OK;
393         }
394
395         *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members);
396         *names = TALLOC_ARRAY(mem_ctx, char *, num_members);
397         *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members);
398         sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members);
399
400         if (((*sid_mem) == NULL) || ((*names) == NULL) ||
401             ((*name_types) == NULL) || (sids == NULL)) {
402                 TALLOC_FREE(tmp_ctx);
403                 return NT_STATUS_NO_MEMORY;
404         }
405
406         /*
407          * Prepare an array of sid pointers for the lookup_sids calling
408          * convention.
409          */
410
411         for (i=0; i<num_members; i++) {
412                 DOM_SID *sid = &((*sid_mem)[i]);
413                 if (!sid_compose(sid, &domain->sid, rids[i])) {
414                         TALLOC_FREE(tmp_ctx);
415                         return NT_STATUS_INTERNAL_ERROR;
416                 }
417                 sids[i] = sid;
418         }
419
420         result = lookup_sids(tmp_ctx, num_members, sids, 1,
421                              &lsa_domains, &lsa_names);
422         if (!NT_STATUS_IS_OK(result)) {
423                 TALLOC_FREE(tmp_ctx);
424                 return result;
425         }
426
427         num_mapped = 0;
428         for (i=0; i<num_members; i++) {
429                 if (lsa_names[i].type != SID_NAME_USER) {
430                         DEBUG(2, ("Got %s as group member -- ignoring\n",
431                                   sid_type_lookup(lsa_names[i].type)));
432                         continue;
433                 }
434                 if (!((*names)[i] = talloc_strdup((*names),
435                                                   lsa_names[i].name))) {
436                         TALLOC_FREE(tmp_ctx);
437                         return NT_STATUS_NO_MEMORY;
438                 }
439
440                 (*name_types)[i] = lsa_names[i].type;
441
442                 num_mapped += 1;
443         }
444
445         *num_names = num_mapped;
446
447         TALLOC_FREE(tmp_ctx);
448         return NT_STATUS_OK;
449 }
450
451 /* find the sequence number for a domain */
452 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
453 {
454         BOOL result;
455         time_t seq_num;
456
457         result = pdb_get_seq_num(&seq_num);
458         if (!result) {
459                 *seq = 1;
460         }
461
462         *seq = (int) seq_num;
463         /* *seq = 1; */
464         return NT_STATUS_OK;
465 }
466
467 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
468                                TALLOC_CTX *mem_ctx,
469                                SAM_UNK_INFO_12 *policy)
470 {
471         /* actually we have that */
472         return NT_STATUS_NOT_IMPLEMENTED;
473 }
474
475 static NTSTATUS password_policy(struct winbindd_domain *domain,
476                                 TALLOC_CTX *mem_ctx,
477                                 SAM_UNK_INFO_1 *policy)
478 {
479         uint32 min_pass_len,pass_hist,password_properties;
480         time_t u_expire, u_min_age;
481         NTTIME nt_expire, nt_min_age;
482         uint32 account_policy_temp;
483
484         if ((policy = TALLOC_ZERO_P(mem_ctx, SAM_UNK_INFO_1)) == NULL) {
485                 return NT_STATUS_NO_MEMORY;
486         }
487
488         if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp)) {
489                 return NT_STATUS_ACCESS_DENIED;
490         }
491         min_pass_len = account_policy_temp;
492
493         if (!pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp)) {
494                 return NT_STATUS_ACCESS_DENIED;
495         }
496         pass_hist = account_policy_temp;
497
498         if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp)) {
499                 return NT_STATUS_ACCESS_DENIED;
500         }
501         password_properties = account_policy_temp;
502         
503         if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp)) {
504                 return NT_STATUS_ACCESS_DENIED;
505         }
506         u_expire = account_policy_temp;
507
508         if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp)) {
509                 return NT_STATUS_ACCESS_DENIED;
510         }
511         u_min_age = account_policy_temp;
512
513         unix_to_nt_time_abs(&nt_expire, u_expire);
514         unix_to_nt_time_abs(&nt_min_age, u_min_age);
515
516         init_unk_info1(policy, (uint16)min_pass_len, (uint16)pass_hist, 
517                        password_properties, nt_expire, nt_min_age);
518
519         return NT_STATUS_OK;
520 }
521
522 /* get a list of trusted domains */
523 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
524                                 TALLOC_CTX *mem_ctx,
525                                 uint32 *num_domains,
526                                 char ***names,
527                                 char ***alt_names,
528                                 DOM_SID **dom_sids)
529 {
530         NTSTATUS nt_status;
531         struct trustdom_info **domains;
532         int i;
533         TALLOC_CTX *tmp_ctx;
534
535         *num_domains = 0;
536         *names = NULL;
537         *alt_names = NULL;
538         *dom_sids = NULL;
539
540         if (!(tmp_ctx = talloc_init("trusted_domains"))) {
541                 return NT_STATUS_NO_MEMORY;
542         }
543
544         nt_status = pdb_enum_trusteddoms(tmp_ctx, num_domains, &domains);
545         if (!NT_STATUS_IS_OK(nt_status)) {
546                 TALLOC_FREE(tmp_ctx);
547                 return nt_status;
548         }
549
550         *names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
551         *alt_names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
552         *dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
553
554         if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) {
555                 TALLOC_FREE(tmp_ctx);
556                 return NT_STATUS_NO_MEMORY;
557         }
558
559         for (i=0; i<*num_domains; i++) {
560                 (*alt_names)[i] = NULL;
561                 if (!((*names)[i] = talloc_strdup((*names),
562                                                   domains[i]->name))) {
563                         TALLOC_FREE(tmp_ctx);
564                         return NT_STATUS_NO_MEMORY;
565                 }
566                 sid_copy(&(*dom_sids)[i], &domains[i]->sid);
567         }
568
569         TALLOC_FREE(tmp_ctx);
570         return NT_STATUS_OK;
571 }
572
573 /* the rpc backend methods are exposed via this structure */
574 struct winbindd_methods passdb_methods = {
575         False,
576         query_user_list,
577         enum_dom_groups,
578         enum_local_groups,
579         name_to_sid,
580         sid_to_name,
581         rids_to_names,
582         query_user,
583         lookup_usergroups,
584         lookup_useraliases,
585         lookup_groupmem,
586         sequence_number,
587         lockout_policy,
588         password_policy,
589         trusted_domains,
590 };