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