r25154: move winbindd code into winbindd/
[nivanova/samba-autobuild/.git] / source3 / winbindd / 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 3 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, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "winbindd.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_WINBIND
29
30 /* Query display info for a domain.  This returns enough information plus a
31    bit extra to give an overview of domain users for the User Manager
32    application. */
33 static NTSTATUS query_user_list(struct winbindd_domain *domain,
34                                TALLOC_CTX *mem_ctx,
35                                uint32 *num_entries, 
36                                WINBIND_USERINFO **info)
37 {
38         /* We don't have users */
39         *num_entries = 0;
40         *info = NULL;
41         return NT_STATUS_OK;
42 }
43
44 /* list all domain groups */
45 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
46                                 TALLOC_CTX *mem_ctx,
47                                 uint32 *num_entries, 
48                                 struct acct_info **info)
49 {
50         /* We don't have domain groups */
51         *num_entries = 0;
52         *info = NULL;
53         return NT_STATUS_OK;
54 }
55
56 /* List all domain groups */
57
58 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
59                                 TALLOC_CTX *mem_ctx,
60                                 uint32 *num_entries, 
61                                 struct acct_info **info)
62 {
63         struct pdb_search *search;
64         struct samr_displayentry *aliases;
65         int i;
66         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
67
68         search = pdb_search_aliases(&domain->sid);
69         if (search == NULL) goto done;
70
71         *num_entries = pdb_search_entries(search, 0, 0xffffffff, &aliases);
72         if (*num_entries == 0) goto done;
73
74         *info = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
75         if (*info == NULL) {
76                 result = NT_STATUS_NO_MEMORY;
77                 goto done;
78         }
79
80         for (i=0; i<*num_entries; i++) {
81                 fstrcpy((*info)[i].acct_name, aliases[i].account_name);
82                 fstrcpy((*info)[i].acct_desc, aliases[i].description);
83                 (*info)[i].rid = aliases[i].rid;
84         }
85
86         result = NT_STATUS_OK;
87  done:
88         pdb_search_destroy(search);
89         return result;
90 }
91
92 /* convert a single name to a sid in a domain */
93 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
94                             TALLOC_CTX *mem_ctx,
95                             enum winbindd_cmd original_cmd,
96                             const char *domain_name,
97                             const char *name,
98                             DOM_SID *sid,
99                             enum lsa_SidType *type)
100 {
101         uint32 flags = LOOKUP_NAME_ALL;
102
103         switch ( original_cmd ) {
104         case WINBINDD_LOOKUPNAME:
105                 /* This call is ok */
106                 break;
107         default:
108                 /* Avoid any NSS calls in the lookup_name by default */
109                 flags |= LOOKUP_NAME_EXPLICIT;
110                 DEBUG(10,("winbindd_passdb: limiting name_to_sid() to explicit mappings\n"));
111                 break;
112         }
113         
114         DEBUG(10, ("Finding name %s\n", name));
115
116         if ( !lookup_name( mem_ctx, name, flags, NULL, NULL, sid, type ) ) {
117                 return NT_STATUS_NONE_MAPPED;
118         }
119
120         return NT_STATUS_OK;
121 }
122
123 /*
124   convert a domain SID to a user or group name
125 */
126 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
127                             TALLOC_CTX *mem_ctx,
128                             const DOM_SID *sid,
129                             char **domain_name,
130                             char **name,
131                             enum lsa_SidType *type)
132 {
133         const char *dom, *nam;
134
135         DEBUG(10, ("Converting SID %s\n", sid_string_static(sid)));
136
137         /* Paranoia check */
138         if (!sid_check_is_in_builtin(sid) &&
139             !sid_check_is_in_our_domain(sid) &&
140             !sid_check_is_in_unix_users(sid) &&
141             !sid_check_is_unix_users(sid) &&
142             !sid_check_is_in_unix_groups(sid) &&
143             !sid_check_is_unix_groups(sid) )
144         {
145                 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
146                           "passdb backend\n", sid_string_static(sid)));
147                 return NT_STATUS_NONE_MAPPED;
148         }
149
150         if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) {
151                 return NT_STATUS_NONE_MAPPED;
152         }
153
154         *domain_name = talloc_strdup(mem_ctx, dom);
155         *name = talloc_strdup(mem_ctx, nam);
156
157         return NT_STATUS_OK;
158 }
159
160 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
161                               TALLOC_CTX *mem_ctx,
162                               const DOM_SID *sid,
163                               uint32 *rids,
164                               size_t num_rids,
165                               char **domain_name,
166                               char ***names,
167                               enum lsa_SidType **types)
168 {
169         return NT_STATUS_UNSUCCESSFUL;
170 }
171
172 /* Lookup user information from a rid or username. */
173 static NTSTATUS query_user(struct winbindd_domain *domain, 
174                            TALLOC_CTX *mem_ctx, 
175                            const DOM_SID *user_sid,
176                            WINBIND_USERINFO *user_info)
177 {
178         return NT_STATUS_NO_SUCH_USER;
179 }
180
181 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
182 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
183                                   TALLOC_CTX *mem_ctx,
184                                   const DOM_SID *user_sid,
185                                   uint32 *num_groups, DOM_SID **user_gids)
186 {
187         NTSTATUS result;
188         DOM_SID *groups = NULL;
189         gid_t *gids = NULL;
190         size_t ngroups = 0;
191         struct samu *user;
192
193         if ( (user = samu_new(mem_ctx)) == NULL ) {
194                 return NT_STATUS_NO_MEMORY;
195         }
196
197         if ( !pdb_getsampwsid( user, user_sid ) ) {
198                 return NT_STATUS_NO_SUCH_USER;
199         }
200
201         result = pdb_enum_group_memberships( mem_ctx, user, &groups, &gids, &ngroups );
202
203         TALLOC_FREE( user );
204
205         *num_groups = (uint32)ngroups;
206         *user_gids = groups;
207
208         return result;
209 }
210
211 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
212                                    TALLOC_CTX *mem_ctx,
213                                    uint32 num_sids, const DOM_SID *sids,
214                                    uint32 *p_num_aliases, uint32 **rids)
215 {
216         NTSTATUS result;
217         size_t num_aliases = 0;
218
219         result = pdb_enum_alias_memberships(mem_ctx, &domain->sid,
220                                             sids, num_sids, rids, &num_aliases);
221
222         *p_num_aliases = num_aliases;
223         return result;
224 }
225
226 /* Lookup group membership given a rid.   */
227 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
228                                 TALLOC_CTX *mem_ctx,
229                                 const DOM_SID *group_sid, uint32 *num_names, 
230                                 DOM_SID **sid_mem, char ***names, 
231                                 uint32 **name_types)
232 {
233         size_t i, num_members, num_mapped;
234         uint32 *rids;
235         NTSTATUS result;
236         const DOM_SID **sids;
237         struct lsa_dom_info *lsa_domains;
238         struct lsa_name_info *lsa_names;
239         TALLOC_CTX *tmp_ctx;
240
241         if (!sid_check_is_in_our_domain(group_sid)) {
242                 /* There's no groups, only aliases in BUILTIN */
243                 return NT_STATUS_NO_SUCH_GROUP;
244         }
245
246         if (!(tmp_ctx = talloc_init("lookup_groupmem"))) {
247                 return NT_STATUS_NO_MEMORY;
248         }
249
250         result = pdb_enum_group_members(tmp_ctx, group_sid, &rids,
251                                         &num_members);
252         if (!NT_STATUS_IS_OK(result)) {
253                 TALLOC_FREE(tmp_ctx);
254                 return result;
255         }
256
257         if (num_members == 0) {
258                 *num_names = 0;
259                 *sid_mem = NULL;
260                 *names = NULL;
261                 *name_types = NULL;
262                 TALLOC_FREE(tmp_ctx);
263                 return NT_STATUS_OK;
264         }
265
266         *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members);
267         *names = TALLOC_ARRAY(mem_ctx, char *, num_members);
268         *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members);
269         sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members);
270
271         if (((*sid_mem) == NULL) || ((*names) == NULL) ||
272             ((*name_types) == NULL) || (sids == NULL)) {
273                 TALLOC_FREE(tmp_ctx);
274                 return NT_STATUS_NO_MEMORY;
275         }
276
277         /*
278          * Prepare an array of sid pointers for the lookup_sids calling
279          * convention.
280          */
281
282         for (i=0; i<num_members; i++) {
283                 DOM_SID *sid = &((*sid_mem)[i]);
284                 if (!sid_compose(sid, &domain->sid, rids[i])) {
285                         TALLOC_FREE(tmp_ctx);
286                         return NT_STATUS_INTERNAL_ERROR;
287                 }
288                 sids[i] = sid;
289         }
290
291         result = lookup_sids(tmp_ctx, num_members, sids, 1,
292                              &lsa_domains, &lsa_names);
293         if (!NT_STATUS_IS_OK(result)) {
294                 TALLOC_FREE(tmp_ctx);
295                 return result;
296         }
297
298         num_mapped = 0;
299         for (i=0; i<num_members; i++) {
300                 if (lsa_names[i].type != SID_NAME_USER) {
301                         DEBUG(2, ("Got %s as group member -- ignoring\n",
302                                   sid_type_lookup(lsa_names[i].type)));
303                         continue;
304                 }
305                 if (!((*names)[i] = talloc_strdup((*names),
306                                                   lsa_names[i].name))) {
307                         TALLOC_FREE(tmp_ctx);
308                         return NT_STATUS_NO_MEMORY;
309                 }
310
311                 (*name_types)[i] = lsa_names[i].type;
312
313                 num_mapped += 1;
314         }
315
316         *num_names = num_mapped;
317
318         TALLOC_FREE(tmp_ctx);
319         return NT_STATUS_OK;
320 }
321
322 /* find the sequence number for a domain */
323 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
324 {
325         BOOL result;
326         time_t seq_num;
327
328         result = pdb_get_seq_num(&seq_num);
329         if (!result) {
330                 *seq = 1;
331         }
332
333         *seq = (int) seq_num;
334         /* *seq = 1; */
335         return NT_STATUS_OK;
336 }
337
338 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
339                                TALLOC_CTX *mem_ctx,
340                                SAM_UNK_INFO_12 *policy)
341 {
342         /* actually we have that */
343         return NT_STATUS_NOT_IMPLEMENTED;
344 }
345
346 static NTSTATUS password_policy(struct winbindd_domain *domain,
347                                 TALLOC_CTX *mem_ctx,
348                                 SAM_UNK_INFO_1 *policy)
349 {
350         uint32 min_pass_len,pass_hist,password_properties;
351         time_t u_expire, u_min_age;
352         NTTIME nt_expire, nt_min_age;
353         uint32 account_policy_temp;
354
355         if ((policy = TALLOC_ZERO_P(mem_ctx, SAM_UNK_INFO_1)) == NULL) {
356                 return NT_STATUS_NO_MEMORY;
357         }
358
359         if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp)) {
360                 return NT_STATUS_ACCESS_DENIED;
361         }
362         min_pass_len = account_policy_temp;
363
364         if (!pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp)) {
365                 return NT_STATUS_ACCESS_DENIED;
366         }
367         pass_hist = account_policy_temp;
368
369         if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp)) {
370                 return NT_STATUS_ACCESS_DENIED;
371         }
372         password_properties = account_policy_temp;
373         
374         if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp)) {
375                 return NT_STATUS_ACCESS_DENIED;
376         }
377         u_expire = account_policy_temp;
378
379         if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp)) {
380                 return NT_STATUS_ACCESS_DENIED;
381         }
382         u_min_age = account_policy_temp;
383
384         unix_to_nt_time_abs(&nt_expire, u_expire);
385         unix_to_nt_time_abs(&nt_min_age, u_min_age);
386
387         init_unk_info1(policy, (uint16)min_pass_len, (uint16)pass_hist, 
388                        password_properties, nt_expire, nt_min_age);
389
390         return NT_STATUS_OK;
391 }
392
393 /* get a list of trusted domains */
394 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
395                                 TALLOC_CTX *mem_ctx,
396                                 uint32 *num_domains,
397                                 char ***names,
398                                 char ***alt_names,
399                                 DOM_SID **dom_sids)
400 {
401         NTSTATUS nt_status;
402         struct trustdom_info **domains;
403         int i;
404         TALLOC_CTX *tmp_ctx;
405
406         *num_domains = 0;
407         *names = NULL;
408         *alt_names = NULL;
409         *dom_sids = NULL;
410
411         if (!(tmp_ctx = talloc_init("trusted_domains"))) {
412                 return NT_STATUS_NO_MEMORY;
413         }
414
415         nt_status = pdb_enum_trusteddoms(tmp_ctx, num_domains, &domains);
416         if (!NT_STATUS_IS_OK(nt_status)) {
417                 TALLOC_FREE(tmp_ctx);
418                 return nt_status;
419         }
420
421         if (*num_domains) {
422                 *names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
423                 *alt_names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
424                 *dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
425
426                 if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) {
427                         TALLOC_FREE(tmp_ctx);
428                         return NT_STATUS_NO_MEMORY;
429                 }
430         } else {
431                 *names = NULL;
432                 *alt_names = NULL;
433                 *dom_sids = NULL;
434         }
435
436         for (i=0; i<*num_domains; i++) {
437                 (*alt_names)[i] = NULL;
438                 if (!((*names)[i] = talloc_strdup((*names),
439                                                   domains[i]->name))) {
440                         TALLOC_FREE(tmp_ctx);
441                         return NT_STATUS_NO_MEMORY;
442                 }
443                 sid_copy(&(*dom_sids)[i], &domains[i]->sid);
444         }
445
446         TALLOC_FREE(tmp_ctx);
447         return NT_STATUS_OK;
448 }
449
450 /* the rpc backend methods are exposed via this structure */
451 struct winbindd_methods passdb_methods = {
452         False,
453         query_user_list,
454         enum_dom_groups,
455         enum_local_groups,
456         name_to_sid,
457         sid_to_name,
458         rids_to_names,
459         query_user,
460         lookup_usergroups,
461         lookup_useraliases,
462         lookup_groupmem,
463         sequence_number,
464         lockout_policy,
465         password_policy,
466         trusted_domains,
467 };