Added ability to remove id mappings in wbinfo and libwbclient.
[tprouty/samba.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    Copyright (C) Jeremy Allison 2008
10    
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.
15    
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.
20    
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/>.
23 */
24
25 #include "includes.h"
26 #include "winbindd.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_WINBIND
30
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)
36 {
37         struct pdb_search *search;
38         struct samr_displayentry *entries;
39         int i;
40         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
41
42         if (sidtype == SID_NAME_ALIAS) {
43                 search = pdb_search_aliases(&domain->sid);
44         } else {
45                 search = pdb_search_groups();
46         }
47
48         if (search == NULL) goto done;
49
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;
55         }
56
57         *info = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
58         if (*info == NULL) {
59                 result = NT_STATUS_NO_MEMORY;
60                 goto done;
61         }
62
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;
67         }
68
69         result = NT_STATUS_OK;
70  done:
71         pdb_search_destroy(search);
72         return result;
73 }
74
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)
80 {
81         return enum_groups_internal(domain,
82                                 mem_ctx,
83                                 num_entries,
84                                 info,
85                                 SID_NAME_ALIAS);
86 }
87
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)
96 {
97         const char *fullname;
98         uint32 flags = LOOKUP_NAME_ALL;
99
100         switch ( original_cmd ) {
101         case WINBINDD_LOOKUPNAME:
102                 /* This call is ok */
103                 break;
104         default:
105                 /* Avoid any NSS calls in the lookup_name by default */
106                 flags |= LOOKUP_NAME_EXPLICIT;
107                 DEBUG(10,("winbindd_passdb: limiting name_to_sid() to explicit mappings\n"));
108                 break;
109         }
110         
111         if (domain_name && domain_name[0] && strchr_m(name, '\\') == NULL) {
112                 fullname = talloc_asprintf(mem_ctx, "%s\\%s",
113                                 domain_name, name);
114                 if (fullname == NULL) {
115                         return NT_STATUS_NO_MEMORY;
116                 }
117         } else {
118                 fullname = name;
119         }
120
121         DEBUG(10, ("Finding fullname %s\n", fullname));
122
123         if ( !lookup_name( mem_ctx, fullname, flags, NULL, NULL, sid, type ) ) {
124                 return NT_STATUS_NONE_MAPPED;
125         }
126
127         DEBUG(10, ("name_to_sid for %s returned %s (%s)\n",
128                 fullname,
129                 sid_string_dbg(sid),
130                 sid_type_lookup((uint32)*type)));
131                 
132         return NT_STATUS_OK;
133 }
134
135 /*
136   convert a domain SID to a user or group name
137 */
138 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
139                             TALLOC_CTX *mem_ctx,
140                             const DOM_SID *sid,
141                             char **domain_name,
142                             char **name,
143                             enum lsa_SidType *type)
144 {
145         const char *dom, *nam;
146
147         DEBUG(10, ("Converting SID %s\n", sid_string_dbg(sid)));
148
149         /* Paranoia check */
150         if (!sid_check_is_in_builtin(sid) &&
151             !sid_check_is_in_our_domain(sid) &&
152             !sid_check_is_in_unix_users(sid) &&
153             !sid_check_is_unix_users(sid) &&
154             !sid_check_is_in_unix_groups(sid) &&
155             !sid_check_is_unix_groups(sid) &&
156             !sid_check_is_in_wellknown_domain(sid))
157         {
158                 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
159                           "passdb backend\n", sid_string_dbg(sid)));
160                 return NT_STATUS_NONE_MAPPED;
161         }
162
163         if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) {
164                 return NT_STATUS_NONE_MAPPED;
165         }
166
167         *domain_name = talloc_strdup(mem_ctx, dom);
168         *name = talloc_strdup(mem_ctx, nam);
169
170         return NT_STATUS_OK;
171 }
172
173 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
174                               TALLOC_CTX *mem_ctx,
175                               const DOM_SID *sid,
176                               uint32 *rids,
177                               size_t num_rids,
178                               char **domain_name,
179                               char ***names,
180                               enum lsa_SidType **types)
181 {
182         size_t i;
183         bool have_mapped;
184         bool have_unmapped;
185
186         *domain_name = NULL;
187         *names = NULL;
188         *types = NULL;
189
190         if (!num_rids) {
191                 return NT_STATUS_OK;
192         }
193
194         /* Paranoia check */
195         if (!sid_check_is_in_builtin(sid) &&
196             !sid_check_is_in_our_domain(sid) &&
197             !sid_check_is_in_unix_users(sid) &&
198             !sid_check_is_unix_users(sid) &&
199             !sid_check_is_in_unix_groups(sid) &&
200             !sid_check_is_unix_groups(sid) &&
201             !sid_check_is_in_wellknown_domain(sid))
202         {
203                 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
204                           "passdb backend\n", sid_string_dbg(sid)));
205                 return NT_STATUS_NONE_MAPPED;
206         }
207
208         *names = TALLOC_ARRAY(mem_ctx, char *, num_rids);
209         *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
210
211         if ((*names == NULL) || (*types == NULL)) {
212                 return NT_STATUS_NO_MEMORY;
213         }
214
215         have_mapped = have_unmapped = false;
216
217         for (i=0; i<num_rids; i++) {
218                 DOM_SID lsid;
219                 const char *dom = NULL, *nam = NULL;
220                 enum lsa_SidType type = SID_NAME_UNKNOWN;
221
222                 if (!sid_compose(&lsid, sid, rids[i])) {
223                         return NT_STATUS_INTERNAL_ERROR;
224                 }
225
226                 if (!lookup_sid(mem_ctx, &lsid, &dom, &nam, &type)) {
227                         have_unmapped = true;
228                         (*types)[i] = SID_NAME_UNKNOWN;
229                         (*names)[i] = talloc_strdup(mem_ctx, "");
230                 } else {
231                         have_mapped = true;
232                         (*types)[i] = type;
233                         (*names)[i] = CONST_DISCARD(char *, nam);
234                 }
235
236                 if (*domain_name == NULL) {
237                         *domain_name = CONST_DISCARD(char *, dom);
238                 } else {
239                         char *dname = CONST_DISCARD(char *, dom);
240                         TALLOC_FREE(dname);
241                 }
242         }
243
244         if (!have_mapped) {
245                 return NT_STATUS_NONE_MAPPED;
246         }
247         if (!have_unmapped) {
248                 return NT_STATUS_OK;
249         }
250         return STATUS_SOME_UNMAPPED;
251 }
252
253 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
254 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
255                                   TALLOC_CTX *mem_ctx,
256                                   const DOM_SID *user_sid,
257                                   uint32 *num_groups, DOM_SID **user_gids)
258 {
259         NTSTATUS result;
260         DOM_SID *groups = NULL;
261         gid_t *gids = NULL;
262         size_t ngroups = 0;
263         struct samu *user;
264
265         if ( (user = samu_new(mem_ctx)) == NULL ) {
266                 return NT_STATUS_NO_MEMORY;
267         }
268
269         if ( !pdb_getsampwsid( user, user_sid ) ) {
270                 TALLOC_FREE( user );
271                 return NT_STATUS_NO_SUCH_USER;
272         }
273
274         result = pdb_enum_group_memberships( mem_ctx, user, &groups, &gids, &ngroups );
275
276         TALLOC_FREE( user );
277
278         *num_groups = (uint32)ngroups;
279         *user_gids = groups;
280
281         return result;
282 }
283
284 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
285                                    TALLOC_CTX *mem_ctx,
286                                    uint32 num_sids, const DOM_SID *sids,
287                                    uint32 *p_num_aliases, uint32 **rids)
288 {
289         NTSTATUS result;
290         size_t num_aliases = 0;
291
292         result = pdb_enum_alias_memberships(mem_ctx, &domain->sid,
293                                             sids, num_sids, rids, &num_aliases);
294
295         *p_num_aliases = num_aliases;
296         return result;
297 }
298
299 /* find the sequence number for a domain */
300 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
301 {
302         bool result;
303         time_t seq_num;
304
305         result = pdb_get_seq_num(&seq_num);
306         if (!result) {
307                 *seq = 1;
308         }
309
310         *seq = (int) seq_num;
311         /* *seq = 1; */
312         return NT_STATUS_OK;
313 }
314
315 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
316                                TALLOC_CTX *mem_ctx,
317                                struct samr_DomInfo12 *policy)
318 {
319         /* actually we have that */
320         return NT_STATUS_NOT_IMPLEMENTED;
321 }
322
323 static NTSTATUS password_policy(struct winbindd_domain *domain,
324                                 TALLOC_CTX *mem_ctx,
325                                 struct samr_DomInfo1 *policy)
326 {
327         uint32 min_pass_len,pass_hist,password_properties;
328         time_t u_expire, u_min_age;
329         NTTIME nt_expire, nt_min_age;
330         uint32 account_policy_temp;
331
332         if ((policy = TALLOC_ZERO_P(mem_ctx, struct samr_DomInfo1)) == NULL) {
333                 return NT_STATUS_NO_MEMORY;
334         }
335
336         if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp)) {
337                 return NT_STATUS_ACCESS_DENIED;
338         }
339         min_pass_len = account_policy_temp;
340
341         if (!pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp)) {
342                 return NT_STATUS_ACCESS_DENIED;
343         }
344         pass_hist = account_policy_temp;
345
346         if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp)) {
347                 return NT_STATUS_ACCESS_DENIED;
348         }
349         password_properties = account_policy_temp;
350         
351         if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp)) {
352                 return NT_STATUS_ACCESS_DENIED;
353         }
354         u_expire = account_policy_temp;
355
356         if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp)) {
357                 return NT_STATUS_ACCESS_DENIED;
358         }
359         u_min_age = account_policy_temp;
360
361         unix_to_nt_time_abs(&nt_expire, u_expire);
362         unix_to_nt_time_abs(&nt_min_age, u_min_age);
363
364         init_samr_DomInfo1(policy,
365                            (uint16)min_pass_len,
366                            (uint16)pass_hist,
367                            password_properties,
368                            nt_expire,
369                            nt_min_age);
370
371         return NT_STATUS_OK;
372 }
373
374 /*********************************************************************
375  BUILTIN specific functions.
376 *********************************************************************/
377
378 /* list all domain groups */
379 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
380                                 TALLOC_CTX *mem_ctx,
381                                 uint32 *num_entries, 
382                                 struct acct_info **info)
383 {
384         /* BUILTIN doesn't have domain groups */
385         *num_entries = 0;
386         *info = NULL;
387         return NT_STATUS_OK;
388 }
389
390 /* Query display info for a domain.  This returns enough information plus a
391    bit extra to give an overview of domain users for the User Manager
392    application. */
393 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
394                                 TALLOC_CTX *mem_ctx,
395                                 uint32 *num_entries,
396                                 WINBIND_USERINFO **info)
397 {
398         /* We don't have users */
399         *num_entries = 0;
400         *info = NULL;
401         return NT_STATUS_OK;
402 }
403
404 /* Lookup user information from a rid or username. */
405 static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
406                                 TALLOC_CTX *mem_ctx,
407                                 const DOM_SID *user_sid,
408                                 WINBIND_USERINFO *user_info)
409 {
410         return NT_STATUS_NO_SUCH_USER;
411 }
412
413 static NTSTATUS builtin_lookup_groupmem(struct winbindd_domain *domain,
414                                 TALLOC_CTX *mem_ctx,
415                                 const DOM_SID *group_sid, uint32 *num_names,
416                                 DOM_SID **sid_mem, char ***names,
417                                 uint32 **name_types)
418 {
419         *num_names = 0;
420         *sid_mem = NULL;
421         *names = NULL;
422         *name_types = 0;
423         return NT_STATUS_NO_SUCH_GROUP;
424 }
425
426 /* get a list of trusted domains - builtin domain */
427 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
428                                 TALLOC_CTX *mem_ctx,
429                                 uint32 *num_domains,
430                                 char ***names,
431                                 char ***alt_names,
432                                 DOM_SID **dom_sids)
433 {
434         *num_domains = 0;
435         *names = NULL;
436         *alt_names = NULL;
437         *dom_sids = NULL;
438         return NT_STATUS_OK;
439 }
440
441 /*********************************************************************
442  SAM specific functions.
443 *********************************************************************/
444
445 /* list all domain groups */
446 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
447                                 TALLOC_CTX *mem_ctx,
448                                 uint32 *num_entries, 
449                                 struct acct_info **info)
450 {
451         return enum_groups_internal(domain,
452                                 mem_ctx,
453                                 num_entries,
454                                 info,
455                                 SID_NAME_DOM_GRP);
456 }
457
458 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
459                                 TALLOC_CTX *mem_ctx,
460                                 uint32 *num_entries,
461                                 WINBIND_USERINFO **info)
462 {
463         struct pdb_search *ps = pdb_search_users(ACB_NORMAL);
464         struct samr_displayentry *entries = NULL;
465         uint32 i;
466
467         *num_entries = 0;
468         *info = NULL;
469
470         if (!ps) {
471                 return NT_STATUS_NO_MEMORY;
472         }
473
474         *num_entries = pdb_search_entries(ps,
475                                         1, 0xffffffff,
476                                         &entries);
477
478         *info = TALLOC_ZERO_ARRAY(mem_ctx, WINBIND_USERINFO, *num_entries);
479         if (!(*info)) {
480                 pdb_search_destroy(ps);
481                 return NT_STATUS_NO_MEMORY;
482         }
483
484         for (i = 0; i < *num_entries; i++) {
485                 struct samr_displayentry *e = &entries[i];
486
487                 (*info)[i].acct_name = talloc_strdup(mem_ctx, e->account_name );
488                 (*info)[i].full_name = talloc_strdup(mem_ctx, e->fullname );
489                 (*info)[i].homedir = NULL;
490                 (*info)[i].shell = NULL;
491                 sid_compose(&(*info)[i].user_sid, &domain->sid, e->rid);
492
493                 /* For the moment we set the primary group for
494                    every user to be the Domain Users group.
495                    There are serious problems with determining
496                    the actual primary group for large domains.
497                    This should really be made into a 'winbind
498                    force group' smb.conf parameter or
499                    something like that. */
500
501                 sid_compose(&(*info)[i].group_sid, &domain->sid,
502                                 DOMAIN_GROUP_RID_USERS);
503         }
504
505         pdb_search_destroy(ps);
506         return NT_STATUS_OK;
507 }
508
509 /* Lookup user information from a rid or username. */
510 static NTSTATUS sam_query_user(struct winbindd_domain *domain,
511                            TALLOC_CTX *mem_ctx,
512                            const DOM_SID *user_sid,
513                            WINBIND_USERINFO *user_info)
514 {
515         struct samu *sampass = NULL;
516
517         ZERO_STRUCTP(user_info);
518
519         if (!sid_check_is_in_our_domain(user_sid)) {
520                 return NT_STATUS_NO_SUCH_USER;
521         }
522
523         DEBUG(10,("sam_query_user: getting samu info for sid %s\n",
524                 sid_string_dbg(user_sid) ));
525
526         if (!(sampass = samu_new(mem_ctx))) {
527                 return NT_STATUS_NO_MEMORY;
528         }
529
530         if (!pdb_getsampwsid(sampass, user_sid)) {
531                 TALLOC_FREE(sampass);
532                 return NT_STATUS_NO_SUCH_USER;
533         }
534
535         if (pdb_get_group_sid(sampass) == NULL) {
536                 TALLOC_FREE(sampass);
537                 return NT_STATUS_NO_SUCH_GROUP;
538         }
539
540         DEBUG(10,("sam_query_user: group sid %s\n",
541                 sid_string_dbg(sampass->group_sid) ));
542
543         sid_copy(&user_info->user_sid, user_sid);
544         sid_copy(&user_info->group_sid, sampass->group_sid);
545
546         user_info->acct_name = talloc_strdup(mem_ctx, sampass->username ?
547                                         sampass->username : "");
548         user_info->full_name = talloc_strdup(mem_ctx, sampass->full_name ?
549                                         sampass->full_name : "");
550         user_info->homedir = talloc_strdup(mem_ctx, sampass->home_dir ?
551                                         sampass->home_dir : "");
552         if (sampass->unix_pw && sampass->unix_pw->pw_shell) {
553                 user_info->shell = talloc_strdup(mem_ctx, sampass->unix_pw->pw_shell);
554         } else {
555                 user_info->shell = talloc_strdup(mem_ctx, "");
556         }
557         user_info->primary_gid = sampass->unix_pw ? sampass->unix_pw->pw_gid : (gid_t)-1;
558
559         TALLOC_FREE(sampass);
560         return NT_STATUS_OK;
561 }
562
563 /* Lookup group membership given a rid.   */
564 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
565                                 TALLOC_CTX *mem_ctx,
566                                 const DOM_SID *group_sid, uint32 *num_names, 
567                                 DOM_SID **sid_mem, char ***names, 
568                                 uint32 **name_types)
569 {
570         size_t i, num_members, num_mapped;
571         uint32 *rids;
572         NTSTATUS result;
573         const DOM_SID **sids;
574         struct lsa_dom_info *lsa_domains;
575         struct lsa_name_info *lsa_names;
576         TALLOC_CTX *tmp_ctx;
577
578         if (!sid_check_is_in_our_domain(group_sid)) {
579                 /* There's no groups, only aliases in BUILTIN */
580                 return NT_STATUS_NO_SUCH_GROUP;
581         }
582
583         if (!(tmp_ctx = talloc_init("lookup_groupmem"))) {
584                 return NT_STATUS_NO_MEMORY;
585         }
586
587         result = pdb_enum_group_members(tmp_ctx, group_sid, &rids,
588                                         &num_members);
589         if (!NT_STATUS_IS_OK(result)) {
590                 TALLOC_FREE(tmp_ctx);
591                 return result;
592         }
593
594         if (num_members == 0) {
595                 *num_names = 0;
596                 *sid_mem = NULL;
597                 *names = NULL;
598                 *name_types = NULL;
599                 TALLOC_FREE(tmp_ctx);
600                 return NT_STATUS_OK;
601         }
602
603         *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members);
604         *names = TALLOC_ARRAY(mem_ctx, char *, num_members);
605         *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members);
606         sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members);
607
608         if (((*sid_mem) == NULL) || ((*names) == NULL) ||
609             ((*name_types) == NULL) || (sids == NULL)) {
610                 TALLOC_FREE(tmp_ctx);
611                 return NT_STATUS_NO_MEMORY;
612         }
613
614         /*
615          * Prepare an array of sid pointers for the lookup_sids calling
616          * convention.
617          */
618
619         for (i=0; i<num_members; i++) {
620                 DOM_SID *sid = &((*sid_mem)[i]);
621                 if (!sid_compose(sid, &domain->sid, rids[i])) {
622                         TALLOC_FREE(tmp_ctx);
623                         return NT_STATUS_INTERNAL_ERROR;
624                 }
625                 sids[i] = sid;
626         }
627
628         result = lookup_sids(tmp_ctx, num_members, sids, 1,
629                              &lsa_domains, &lsa_names);
630         if (!NT_STATUS_IS_OK(result)) {
631                 TALLOC_FREE(tmp_ctx);
632                 return result;
633         }
634
635         num_mapped = 0;
636         for (i=0; i<num_members; i++) {
637                 if (lsa_names[i].type != SID_NAME_USER) {
638                         DEBUG(2, ("Got %s as group member -- ignoring\n",
639                                   sid_type_lookup(lsa_names[i].type)));
640                         continue;
641                 }
642                 if (!((*names)[num_mapped] = talloc_strdup((*names),
643                                                   lsa_names[i].name))) {
644                         TALLOC_FREE(tmp_ctx);
645                         return NT_STATUS_NO_MEMORY;
646                 }
647
648                 (*name_types)[num_mapped] = lsa_names[i].type;
649
650                 num_mapped += 1;
651         }
652
653         *num_names = num_mapped;
654
655         TALLOC_FREE(tmp_ctx);
656         return NT_STATUS_OK;
657 }
658
659 /* get a list of trusted domains */
660 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
661                                 TALLOC_CTX *mem_ctx,
662                                 uint32 *num_domains,
663                                 char ***names,
664                                 char ***alt_names,
665                                 DOM_SID **dom_sids)
666 {
667         NTSTATUS nt_status;
668         struct trustdom_info **domains;
669         int i;
670         TALLOC_CTX *tmp_ctx;
671
672         *num_domains = 0;
673         *names = NULL;
674         *alt_names = NULL;
675         *dom_sids = NULL;
676
677         if (!(tmp_ctx = talloc_init("trusted_domains"))) {
678                 return NT_STATUS_NO_MEMORY;
679         }
680
681         nt_status = pdb_enum_trusteddoms(tmp_ctx, num_domains, &domains);
682         if (!NT_STATUS_IS_OK(nt_status)) {
683                 TALLOC_FREE(tmp_ctx);
684                 return nt_status;
685         }
686
687         if (*num_domains) {
688                 *names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
689                 *alt_names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
690                 *dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
691
692                 if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) {
693                         TALLOC_FREE(tmp_ctx);
694                         return NT_STATUS_NO_MEMORY;
695                 }
696         } else {
697                 *names = NULL;
698                 *alt_names = NULL;
699                 *dom_sids = NULL;
700         }
701
702         for (i=0; i<*num_domains; i++) {
703                 (*alt_names)[i] = NULL;
704                 if (!((*names)[i] = talloc_strdup((*names),
705                                                   domains[i]->name))) {
706                         TALLOC_FREE(tmp_ctx);
707                         return NT_STATUS_NO_MEMORY;
708                 }
709                 sid_copy(&(*dom_sids)[i], &domains[i]->sid);
710         }
711
712         TALLOC_FREE(tmp_ctx);
713         return NT_STATUS_OK;
714 }
715
716 /* the rpc backend methods are exposed via this structure */
717 struct winbindd_methods builtin_passdb_methods = {
718         false,
719         builtin_query_user_list,
720         builtin_enum_dom_groups,
721         enum_local_groups,
722         name_to_sid,
723         sid_to_name,
724         rids_to_names,
725         builtin_query_user,
726         lookup_usergroups,
727         lookup_useraliases,
728         builtin_lookup_groupmem,
729         sequence_number,
730         lockout_policy,
731         password_policy,
732         builtin_trusted_domains,
733 };
734
735 /* the rpc backend methods are exposed via this structure */
736 struct winbindd_methods sam_passdb_methods = {
737         false,
738         sam_query_user_list,
739         sam_enum_dom_groups,
740         enum_local_groups,
741         name_to_sid,
742         sid_to_name,
743         rids_to_names,
744         sam_query_user,
745         lookup_usergroups,
746         lookup_useraliases,
747         sam_lookup_groupmem,
748         sequence_number,
749         lockout_policy,
750         password_policy,
751         sam_trusted_domains,
752 };