s3-winbind: Implemented samr backend function common_lockout_policy.
[idra/samba.git] / source3 / winbindd / winbindd_samr.c
1 /*
2  * Unix SMB/CIFS implementation.
3  *
4  * Winbind rpc backend functions
5  *
6  * Copyright (c) 2000-2003 Tim Potter
7  * Copyright (c) 2001      Andrew Tridgell
8  * Copyright (c) 2005      Volker Lendecke
9  * Copyright (c) 2008      Guenther Deschner (pidl conversion)
10  * Copyright (c) 2010      Andreas Schneider <asn@samba.org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24  */
25
26 #include "includes.h"
27 #include "winbindd.h"
28 #include "../librpc/gen_ndr/cli_samr.h"
29 #include "rpc_client/cli_samr.h"
30 #include "../librpc/gen_ndr/srv_samr.h"
31 #include "../librpc/gen_ndr/cli_lsa.h"
32 #include "rpc_client/cli_lsarpc.h"
33 #include "../librpc/gen_ndr/srv_lsa.h"
34
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_WINBIND
37
38 static NTSTATUS open_internal_samr_pipe(TALLOC_CTX *mem_ctx,
39                                         struct rpc_pipe_client **samr_pipe)
40 {
41         static struct rpc_pipe_client *cli = NULL;
42         struct auth_serversupplied_info *server_info = NULL;
43         NTSTATUS status;
44
45         if (cli != NULL) {
46                 goto done;
47         }
48
49         if (server_info == NULL) {
50                 status = make_server_info_system(mem_ctx, &server_info);
51                 if (!NT_STATUS_IS_OK(status)) {
52                         DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n",
53                                   nt_errstr(status)));
54                         return status;
55                 }
56         }
57
58         /* create a samr connection */
59         status = rpc_pipe_open_internal(talloc_autofree_context(),
60                                         &ndr_table_samr.syntax_id,
61                                         rpc_samr_dispatch,
62                                         server_info,
63                                         &cli);
64         if (!NT_STATUS_IS_OK(status)) {
65                 DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n",
66                           nt_errstr(status)));
67                 return status;
68         }
69
70 done:
71         if (samr_pipe) {
72                 *samr_pipe = cli;
73         }
74
75         return NT_STATUS_OK;
76 }
77
78 static NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
79                                         struct winbindd_domain *domain,
80                                         struct rpc_pipe_client **samr_pipe,
81                                         struct policy_handle *samr_domain_hnd)
82 {
83         NTSTATUS status;
84         struct policy_handle samr_connect_hnd;
85
86         status = open_internal_samr_pipe(mem_ctx, samr_pipe);
87         if (!NT_STATUS_IS_OK(status)) {
88                 return status;
89         }
90
91         status = rpccli_samr_Connect2((*samr_pipe),
92                                       mem_ctx,
93                                       (*samr_pipe)->desthost,
94                                       SEC_FLAG_MAXIMUM_ALLOWED,
95                                       &samr_connect_hnd);
96         if (!NT_STATUS_IS_OK(status)) {
97                 return status;
98         }
99
100         status = rpccli_samr_OpenDomain((*samr_pipe),
101                                         mem_ctx,
102                                         &samr_connect_hnd,
103                                         SEC_FLAG_MAXIMUM_ALLOWED,
104                                         &domain->sid,
105                                         samr_domain_hnd);
106
107         return status;
108 }
109
110 static NTSTATUS open_internal_lsa_pipe(TALLOC_CTX *mem_ctx,
111                                        struct rpc_pipe_client **lsa_pipe)
112 {
113         static struct rpc_pipe_client *cli = NULL;
114         struct auth_serversupplied_info *server_info = NULL;
115         NTSTATUS status;
116
117         if (cli != NULL) {
118                 goto done;
119         }
120
121         if (server_info == NULL) {
122                 status = make_server_info_system(mem_ctx, &server_info);
123                 if (!NT_STATUS_IS_OK(status)) {
124                         DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n",
125                                   nt_errstr(status)));
126                         return status;
127                 }
128         }
129
130         /* create a samr connection */
131         status = rpc_pipe_open_internal(talloc_autofree_context(),
132                                         &ndr_table_lsarpc.syntax_id,
133                                         rpc_lsarpc_dispatch,
134                                         server_info,
135                                         &cli);
136         if (!NT_STATUS_IS_OK(status)) {
137                 DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n",
138                           nt_errstr(status)));
139                 return status;
140         }
141
142 done:
143         if (lsa_pipe) {
144                 *lsa_pipe = cli;
145         }
146
147         return NT_STATUS_OK;
148 }
149
150 static NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
151                                        struct rpc_pipe_client **lsa_pipe,
152                                        struct policy_handle *lsa_hnd)
153 {
154         NTSTATUS status;
155
156         status = open_internal_lsa_pipe(mem_ctx, lsa_pipe);
157         if (!NT_STATUS_IS_OK(status)) {
158                 return status;
159         }
160
161         status = rpccli_lsa_open_policy((*lsa_pipe),
162                                         mem_ctx,
163                                         true,
164                                         SEC_FLAG_MAXIMUM_ALLOWED,
165                                         lsa_hnd);
166
167         return status;
168 }
169
170 /*********************************************************************
171  SAM specific functions.
172 *********************************************************************/
173
174 /* List all domain groups */
175 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
176                                     TALLOC_CTX *mem_ctx,
177                                     uint32_t *pnum_info,
178                                     struct acct_info **pinfo)
179 {
180         struct rpc_pipe_client *samr_pipe;
181         struct policy_handle dom_pol;
182         struct acct_info *info = NULL;
183         TALLOC_CTX *tmp_ctx;
184         uint32_t start = 0;
185         uint32_t num_info = 0;
186         NTSTATUS status;
187
188         DEBUG(3,("samr: query_user_list\n"));
189
190         if (pnum_info) {
191                 *pnum_info = 0;
192         }
193
194         tmp_ctx = talloc_stackframe();
195         if (tmp_ctx == NULL) {
196                 return NT_STATUS_NO_MEMORY;
197         }
198
199         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
200         if (!NT_STATUS_IS_OK(status)) {
201                 goto error;
202         }
203
204         do {
205                 struct samr_SamArray *sam_array = NULL;
206                 uint32_t count = 0;
207                 uint32_t g;
208
209                 /* start is updated by this call. */
210                 status = rpccli_samr_EnumDomainGroups(samr_pipe,
211                                                       tmp_ctx,
212                                                       &dom_pol,
213                                                       &start,
214                                                       &sam_array,
215                                                       0xFFFF, /* buffer size? */
216                                                       &count);
217                 if (!NT_STATUS_IS_OK(status)) {
218                         if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
219                                 DEBUG(2,("query_user_list: failed to enum domain groups: %s\n",
220                                          nt_errstr(status)));
221                                 goto error;
222                         }
223                 }
224
225                 info = TALLOC_REALLOC_ARRAY(tmp_ctx,
226                                             info,
227                                             struct acct_info,
228                                             num_info + count);
229                 if (info == NULL) {
230                         status = NT_STATUS_NO_MEMORY;
231                         goto error;
232                 }
233
234                 for (g = 0; g < count; g++) {
235                         fstrcpy(info[num_info + g].acct_name,
236                                 sam_array->entries[g].name.string);
237
238                         info[num_info + g].rid = sam_array->entries[g].idx;
239                 }
240
241                 num_info += count;
242         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
243
244         if (pnum_info) {
245                 *pnum_info = num_info;
246         }
247
248         if (pinfo) {
249                 *pinfo = talloc_move(mem_ctx, &info);
250         }
251
252 error:
253         TALLOC_FREE(tmp_ctx);
254         return status;
255 }
256
257 /* Query display info for a domain */
258 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
259                                     TALLOC_CTX *mem_ctx,
260                                     uint32_t *pnum_info,
261                                     struct wbint_userinfo **pinfo)
262 {
263         struct rpc_pipe_client *samr_pipe = NULL;
264         struct wbint_userinfo *info = NULL;
265         struct policy_handle dom_pol;
266         uint32_t num_info = 0;
267         uint32_t loop_count = 0;
268         uint32_t start_idx = 0;
269         uint32_t i = 0;
270         TALLOC_CTX *tmp_ctx;
271         NTSTATUS status;
272
273         DEBUG(3,("samr: query_user_list\n"));
274
275         if (pnum_info) {
276                 *pnum_info = 0;
277         }
278
279         tmp_ctx = talloc_stackframe();
280         if (tmp_ctx == NULL) {
281                 return NT_STATUS_NO_MEMORY;
282         }
283
284         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
285         if (!NT_STATUS_IS_OK(status)) {
286                 goto error;
287         }
288
289         do {
290                 uint32_t j;
291                 uint32_t num_dom_users;
292                 uint32_t max_entries, max_size;
293                 uint32_t total_size, returned_size;
294                 union samr_DispInfo disp_info;
295
296                 get_query_dispinfo_params(loop_count,
297                                           &max_entries,
298                                           &max_size);
299
300                 status = rpccli_samr_QueryDisplayInfo(samr_pipe,
301                                                       tmp_ctx,
302                                                       &dom_pol,
303                                                       1, /* level */
304                                                       start_idx,
305                                                       max_entries,
306                                                       max_size,
307                                                       &total_size,
308                                                       &returned_size,
309                                                       &disp_info);
310                 if (!NT_STATUS_IS_OK(status)) {
311                         if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
312                                 goto error;
313                         }
314                 }
315
316                 /* increment required start query values */
317                 start_idx += disp_info.info1.count;
318                 loop_count++;
319                 num_dom_users = disp_info.info1.count;
320
321                 num_info += num_dom_users;
322
323                 info = TALLOC_REALLOC_ARRAY(tmp_ctx,
324                                             info,
325                                             struct wbint_userinfo,
326                                             num_info);
327                 if (info == NULL) {
328                         status = NT_STATUS_NO_MEMORY;
329                         goto error;
330                 }
331
332                 for (j = 0; j < num_dom_users; i++, j++) {
333                         uint32_t rid = disp_info.info1.entries[j].rid;
334                         struct samr_DispEntryGeneral *src;
335                         struct wbint_userinfo *dst;
336
337                         src = &(disp_info.info1.entries[j]);
338                         dst = &(info[i]);
339
340                         dst->acct_name = talloc_strdup(info,
341                                                        src->account_name.string);
342                         if (dst->acct_name == NULL) {
343                                 status = NT_STATUS_NO_MEMORY;
344                                 goto error;
345                         }
346
347                         dst->full_name = talloc_strdup(info, src->full_name.string);
348                         if (dst->full_name == NULL) {
349                                 status = NT_STATUS_NO_MEMORY;
350                                 goto error;
351                         }
352
353                         dst->homedir = NULL;
354                         dst->shell = NULL;
355
356                         sid_compose(&dst->user_sid, &domain->sid, rid);
357
358                         /* For the moment we set the primary group for
359                            every user to be the Domain Users group.
360                            There are serious problems with determining
361                            the actual primary group for large domains.
362                            This should really be made into a 'winbind
363                            force group' smb.conf parameter or
364                            something like that. */
365                         sid_compose(&dst->group_sid, &domain->sid,
366                                     DOMAIN_RID_USERS);
367                 }
368         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
369
370         if (pnum_info) {
371                 *pnum_info = num_info;
372         }
373
374         if (pinfo) {
375                 *pinfo = talloc_move(mem_ctx, &info);
376         }
377
378 error:
379         TALLOC_FREE(tmp_ctx);
380         return status;
381 }
382
383 /* Lookup user information from a rid or username. */
384 static NTSTATUS sam_query_user(struct winbindd_domain *domain,
385                                TALLOC_CTX *mem_ctx,
386                                const struct dom_sid *user_sid,
387                                struct wbint_userinfo *user_info)
388 {
389         struct rpc_pipe_client *samr_pipe;
390         struct policy_handle dom_pol, user_pol;
391         union samr_UserInfo *info = NULL;
392         TALLOC_CTX *tmp_ctx;
393         uint32_t user_rid;
394         NTSTATUS status;
395
396         DEBUG(3,("samr: query_user\n"));
397
398         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
399                 return NT_STATUS_UNSUCCESSFUL;
400         }
401
402         if (user_info) {
403                 user_info->homedir = NULL;
404                 user_info->shell = NULL;
405                 user_info->primary_gid = (gid_t) -1;
406         }
407
408         tmp_ctx = talloc_stackframe();
409         if (tmp_ctx == NULL) {
410                 return NT_STATUS_NO_MEMORY;
411         }
412
413         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
414         if (!NT_STATUS_IS_OK(status)) {
415                 goto error;
416         }
417
418         /* Get user handle */
419         status = rpccli_samr_OpenUser(samr_pipe,
420                                       tmp_ctx,
421                                       &dom_pol,
422                                       SEC_FLAG_MAXIMUM_ALLOWED,
423                                       user_rid,
424                                       &user_pol);
425         if (!NT_STATUS_IS_OK(status)) {
426                 goto error;
427         }
428
429         /* Get user info */
430         status = rpccli_samr_QueryUserInfo(samr_pipe,
431                                            tmp_ctx,
432                                            &user_pol,
433                                            0x15,
434                                            &info);
435
436         rpccli_samr_Close(samr_pipe, tmp_ctx, &user_pol);
437
438         if (!NT_STATUS_IS_OK(status)) {
439                 goto error;
440         }
441
442         sid_compose(&user_info->user_sid, &domain->sid, user_rid);
443         sid_compose(&user_info->group_sid, &domain->sid,
444                     info->info21.primary_gid);
445
446         if (user_info) {
447                 user_info->acct_name = talloc_strdup(mem_ctx,
448                                                      info->info21.account_name.string);
449                 if (user_info->acct_name == NULL) {
450                         status = NT_STATUS_NO_MEMORY;
451                         goto error;
452                 }
453
454                 user_info->full_name = talloc_strdup(mem_ctx,
455                                                      info->info21.full_name.string);
456                 if (user_info->acct_name == NULL) {
457                         status = NT_STATUS_NO_MEMORY;
458                         goto error;
459                 }
460
461                 user_info->homedir = NULL;
462                 user_info->shell = NULL;
463                 user_info->primary_gid = (gid_t)-1;
464         }
465
466         status = NT_STATUS_OK;
467 error:
468         TALLOC_FREE(tmp_ctx);
469         return status;
470 }
471
472 /* get a list of trusted domains - builtin domain */
473 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
474                                     TALLOC_CTX *mem_ctx,
475                                     struct netr_DomainTrustList *trusts)
476 {
477         struct rpc_pipe_client *lsa_pipe;
478         struct netr_DomainTrust *array = NULL;
479         struct policy_handle lsa_policy;
480         uint32_t enum_ctx = 0;
481         uint32_t count = 0;
482         TALLOC_CTX *tmp_ctx;
483         NTSTATUS status;
484
485         DEBUG(3,("samr: trusted domains\n"));
486
487         tmp_ctx = talloc_stackframe();
488         if (tmp_ctx == NULL) {
489                 return NT_STATUS_NO_MEMORY;
490         }
491
492         status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
493         if (!NT_STATUS_IS_OK(status)) {
494                 goto error;
495         }
496
497         do {
498                 struct lsa_DomainList dom_list;
499                 uint32_t start_idx;
500                 uint32_t i;
501
502                 /*
503                  * We don't run into deadlocks here, cause winbind_off() is
504                  * called in the main function.
505                  */
506                 status = rpccli_lsa_EnumTrustDom(lsa_pipe,
507                                                  tmp_ctx,
508                                                  &lsa_policy,
509                                                  &enum_ctx,
510                                                  &dom_list,
511                                                  (uint32_t) -1);
512                 if (!NT_STATUS_IS_OK(status)) {
513                         if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
514                                 goto error;
515                         }
516                 }
517
518                 start_idx = trusts->count;
519                 count += dom_list.count;
520
521                 array = talloc_realloc(tmp_ctx,
522                                        array,
523                                        struct netr_DomainTrust,
524                                        count);
525                 if (array == NULL) {
526                         status = NT_STATUS_NO_MEMORY;
527                         goto error;
528                 }
529
530                 for (i = 0; i < dom_list.count; i++) {
531                         struct netr_DomainTrust *trust = &array[i];
532                         struct dom_sid *sid;
533
534                         ZERO_STRUCTP(trust);
535
536                         trust->netbios_name = talloc_move(array,
537                                                           &dom_list.domains[i].name.string);
538                         trust->dns_name = NULL;
539
540                         sid = talloc(array, struct dom_sid);
541                         if (sid == NULL) {
542                                 status = NT_STATUS_NO_MEMORY;
543                                 goto error;
544                         }
545                         sid_copy(sid, dom_list.domains[i].sid);
546                         trust->sid = sid;
547                 }
548         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
549
550         if (trusts) {
551                 trusts->count = count;
552                 trusts->array = talloc_move(mem_ctx, &array);
553         }
554
555 error:
556         TALLOC_FREE(tmp_ctx);
557         return status;
558 }
559
560 /* Lookup group membership given a rid.   */
561 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
562                                     TALLOC_CTX *mem_ctx,
563                                     const struct dom_sid *group_sid,
564                                     enum lsa_SidType type,
565                                     uint32_t *pnum_names,
566                                     struct dom_sid **psid_mem,
567                                     char ***pnames,
568                                     uint32_t **pname_types)
569 {
570         struct rpc_pipe_client *samr_pipe;
571         struct policy_handle dom_pol, group_pol;
572         uint32_t samr_access = SEC_FLAG_MAXIMUM_ALLOWED;
573         struct samr_RidTypeArray *rids = NULL;
574         uint32_t group_rid;
575         uint32_t *rid_mem = NULL;
576
577         uint32_t num_names = 0;
578         uint32_t total_names = 0;
579         struct dom_sid *sid_mem = NULL;
580         char **names = NULL;
581         uint32_t *name_types = NULL;
582
583         struct lsa_Strings tmp_names;
584         struct samr_Ids tmp_types;
585
586         uint32_t j, r;
587         TALLOC_CTX *tmp_ctx;
588         NTSTATUS status;
589
590         DEBUG(3,("samr: lookup groupmem\n"));
591
592         if (pnum_names) {
593                 pnum_names = 0;
594         }
595
596         if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) {
597                 return NT_STATUS_UNSUCCESSFUL;
598         }
599
600         tmp_ctx = talloc_stackframe();
601         if (tmp_ctx == NULL) {
602                 return NT_STATUS_NO_MEMORY;
603         }
604
605         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
606         if (!NT_STATUS_IS_OK(status)) {
607                 goto error;
608         }
609
610         status = rpccli_samr_OpenGroup(samr_pipe,
611                                        tmp_ctx,
612                                        &dom_pol,
613                                        samr_access,
614                                        group_rid,
615                                        &group_pol);
616         if (!NT_STATUS_IS_OK(status)) {
617                 goto error;
618         }
619
620         /*
621          * Step #1: Get a list of user rids that are the members of the group.
622          */
623         status = rpccli_samr_QueryGroupMember(samr_pipe,
624                                               tmp_ctx,
625                                               &group_pol,
626                                               &rids);
627
628         rpccli_samr_Close(samr_pipe, tmp_ctx, &group_pol);
629
630         if (!NT_STATUS_IS_OK(status)) {
631                 goto error;
632         }
633
634         if (rids == NULL || rids->count == 0) {
635                 pnum_names = 0;
636                 pnames = NULL;
637                 pname_types = NULL;
638                 psid_mem = NULL;
639
640                 status = NT_STATUS_OK;
641                 goto error;
642         }
643
644         num_names = rids->count;
645         rid_mem = rids->rids;
646
647         /*
648          * Step #2: Convert list of rids into list of usernames.
649          */
650 #define MAX_LOOKUP_RIDS 900
651
652         if (num_names > 0) {
653                 names = TALLOC_ZERO_ARRAY(tmp_ctx, char *, num_names);
654                 name_types = TALLOC_ZERO_ARRAY(tmp_ctx, uint32_t, num_names);
655                 sid_mem = TALLOC_ZERO_ARRAY(tmp_ctx, struct dom_sid, num_names);
656                 if (names == NULL || name_types == NULL || sid_mem == NULL) {
657                         status = NT_STATUS_NO_MEMORY;
658                         goto error;
659                 }
660         }
661
662         for (j = 0; j < num_names; j++) {
663                 sid_compose(&sid_mem[j], &domain->sid, rid_mem[j]);
664         }
665
666         status = rpccli_samr_LookupRids(samr_pipe,
667                                         tmp_ctx,
668                                         &dom_pol,
669                                         num_names,
670                                         rid_mem,
671                                         &tmp_names,
672                                         &tmp_types);
673         if (!NT_STATUS_IS_OK(status)) {
674                 if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
675                         goto error;
676                 }
677         }
678
679         /* Copy result into array.  The talloc system will take
680            care of freeing the temporary arrays later on. */
681         if (tmp_names.count != tmp_types.count) {
682                 status = NT_STATUS_UNSUCCESSFUL;
683                 goto error;
684         }
685
686         for (r = 0; r < tmp_names.count; r++) {
687                 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
688                         continue;
689                 }
690                 names[total_names] = fill_domain_username_talloc(names,
691                                                                  domain->name,
692                                                                  tmp_names.names[r].string,
693                                                                  true);
694                 name_types[total_names] = tmp_types.ids[r];
695                 total_names++;
696         }
697
698         if (pnum_names) {
699                 *pnum_names = total_names;
700         }
701
702         if (pnames) {
703                 *pnames = talloc_move(mem_ctx, &names);
704         }
705
706         if (pname_types) {
707                 *pname_types = talloc_move(mem_ctx, &name_types);
708         }
709
710         if (psid_mem) {
711                 *psid_mem = talloc_move(mem_ctx, &sid_mem);
712         }
713
714 error:
715         TALLOC_FREE(tmp_ctx);
716         return status;
717 }
718
719 /*********************************************************************
720  BUILTIN specific functions.
721 *********************************************************************/
722
723 /* List all domain groups */
724 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
725                                 TALLOC_CTX *mem_ctx,
726                                 uint32 *num_entries,
727                                 struct acct_info **info)
728 {
729         /* BUILTIN doesn't have domain groups */
730         *num_entries = 0;
731         *info = NULL;
732         return NT_STATUS_OK;
733 }
734
735 /* Query display info for a domain */
736 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
737                                 TALLOC_CTX *mem_ctx,
738                                 uint32 *num_entries,
739                                 struct wbint_userinfo **info)
740 {
741         /* We don't have users */
742         *num_entries = 0;
743         *info = NULL;
744         return NT_STATUS_OK;
745 }
746
747 /* Lookup user information from a rid or username. */
748 static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
749                                 TALLOC_CTX *mem_ctx,
750                                 const struct dom_sid *user_sid,
751                                 struct wbint_userinfo *user_info)
752 {
753         return NT_STATUS_NO_SUCH_USER;
754 }
755
756 /* get a list of trusted domains - builtin domain */
757 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
758                                         TALLOC_CTX *mem_ctx,
759                                         struct netr_DomainTrustList *trusts)
760 {
761         ZERO_STRUCTP(trusts);
762         return NT_STATUS_OK;
763 }
764
765 /*********************************************************************
766  COMMON functions.
767 *********************************************************************/
768
769 /* List all local groups (aliases) */
770 static NTSTATUS common_enum_local_groups(struct winbindd_domain *domain,
771                                          TALLOC_CTX *mem_ctx,
772                                          uint32_t *pnum_info,
773                                          struct acct_info **pinfo)
774 {
775         struct rpc_pipe_client *samr_pipe;
776         struct policy_handle dom_pol;
777         struct acct_info *info = NULL;
778         uint32_t num_info = 0;
779         TALLOC_CTX *tmp_ctx;
780         NTSTATUS status;
781
782         DEBUG(3,("samr: enum local groups\n"));
783
784         if (pnum_info) {
785                 *pnum_info = 0;
786         }
787
788         tmp_ctx = talloc_stackframe();
789         if (tmp_ctx == NULL) {
790                 return NT_STATUS_NO_MEMORY;
791         }
792
793         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
794         if (!NT_STATUS_IS_OK(status)) {
795                 goto error;
796         }
797
798         do {
799                 struct samr_SamArray *sam_array = NULL;
800                 uint32_t count = 0;
801                 uint32_t start = num_info;
802                 uint32_t g;
803
804                 status = rpccli_samr_EnumDomainAliases(samr_pipe,
805                                                        tmp_ctx,
806                                                        &dom_pol,
807                                                        &start,
808                                                        &sam_array,
809                                                        0xFFFF, /* buffer size? */
810                                                        &count);
811                 if (!NT_STATUS_IS_OK(status)) {
812                         if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
813                                 goto error;
814                         }
815                 }
816
817                 info = TALLOC_REALLOC_ARRAY(tmp_ctx,
818                                             info,
819                                             struct acct_info,
820                                             num_info + count);
821                 if (info == NULL) {
822                         status = NT_STATUS_NO_MEMORY;
823                         goto error;
824                 }
825
826                 for (g = 0; g < count; g++) {
827                         fstrcpy(info[num_info + g].acct_name,
828                                 sam_array->entries[g].name.string);
829                         info[num_info + g].rid = sam_array->entries[g].idx;
830                 }
831
832                 num_info += count;
833         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
834
835         if (pnum_info) {
836                 *pnum_info = num_info;
837         }
838
839         if (pinfo) {
840                 *pinfo = talloc_move(mem_ctx, &info);
841         }
842
843 error:
844         TALLOC_FREE(tmp_ctx);
845         return status;
846 }
847
848 /* convert a single name to a sid in a domain */
849 static NTSTATUS common_name_to_sid(struct winbindd_domain *domain,
850                                    TALLOC_CTX *mem_ctx,
851                                    const char *domain_name,
852                                    const char *name,
853                                    uint32_t flags,
854                                    struct dom_sid *sid,
855                                    enum lsa_SidType *type)
856 {
857         struct rpc_pipe_client *lsa_pipe;
858         struct policy_handle lsa_policy;
859         enum lsa_SidType *types = NULL;
860         struct dom_sid *sids = NULL;
861         char *full_name = NULL;
862         char *mapped_name = NULL;
863         TALLOC_CTX *tmp_ctx;
864         NTSTATUS status;
865
866         DEBUG(3,("samr: name to sid\n"));
867
868         tmp_ctx = talloc_stackframe();
869         if (tmp_ctx == NULL) {
870                 return NT_STATUS_NO_MEMORY;
871         }
872
873         status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
874         if (!NT_STATUS_IS_OK(status)) {
875                 goto error;
876         }
877
878         if (name == NULL || name[0] == '\0') {
879                 full_name = talloc_asprintf(tmp_ctx, "%s", domain_name);
880         } else if (domain_name == NULL || domain_name[0] == '\0') {
881                 full_name = talloc_asprintf(tmp_ctx, "%s", name);
882         } else {
883                 full_name = talloc_asprintf(tmp_ctx, "%s\\%s", domain_name, name);
884         }
885
886         if (full_name == NULL) {
887                 status = NT_STATUS_NO_MEMORY;
888         }
889
890         status = normalize_name_unmap(tmp_ctx, full_name, &mapped_name);
891         /* Reset the full_name pointer if we mapped anything */
892         if (NT_STATUS_IS_OK(status) ||
893             NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
894                 full_name = mapped_name;
895         }
896
897         DEBUG(3,("name_to_sid: %s for domain %s\n",
898                  full_name ? full_name : "", domain_name ));
899
900         /*
901          * We don't run into deadlocks here, cause winbind_off() is
902          * called in the main function.
903          */
904         status = rpccli_lsa_lookup_names(lsa_pipe,
905                                          tmp_ctx,
906                                          &lsa_policy,
907                                          1, /* num_names */
908                                          (const char **) &full_name,
909                                          NULL, /* domains */
910                                          1, /* level */
911                                          &sids,
912                                          &types);
913         if (!NT_STATUS_IS_OK(status)) {
914                 DEBUG(2,("name_to_sid: failed to lookup name: %s\n",
915                         nt_errstr(status)));
916                 goto error;
917         }
918
919         if (sid) {
920                 sid_copy(sid, &sids[0]);
921         }
922         if (type) {
923                 *type = types[0];
924         }
925
926 error:
927         TALLOC_FREE(tmp_ctx);
928         return status;
929 }
930
931 /* convert a domain SID to a user or group name */
932 static NTSTATUS common_sid_to_name(struct winbindd_domain *domain,
933                                    TALLOC_CTX *mem_ctx,
934                                    const struct dom_sid *sid,
935                                    char **domain_name,
936                                    char **name,
937                                    enum lsa_SidType *type)
938 {
939         struct rpc_pipe_client *lsa_pipe;
940         struct policy_handle lsa_policy;
941         char *mapped_name = NULL;
942         char **domains = NULL;
943         char **names = NULL;
944         enum lsa_SidType *types = NULL;
945         TALLOC_CTX *tmp_ctx;
946         NTSTATUS map_status;
947         NTSTATUS status;
948
949         DEBUG(3,("samr: sid to name\n"));
950
951         tmp_ctx = talloc_stackframe();
952         if (tmp_ctx == NULL) {
953                 return NT_STATUS_NO_MEMORY;
954         }
955
956         status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
957         if (!NT_STATUS_IS_OK(status)) {
958                 goto error;
959         }
960
961         /*
962          * We don't run into deadlocks here, cause winbind_off() is called in
963          * the main function.
964          */
965         status = rpccli_lsa_lookup_sids(lsa_pipe,
966                                         tmp_ctx,
967                                         &lsa_policy,
968                                         1, /* num_sids */
969                                         sid,
970                                         &domains,
971                                         &names,
972                                         &types);
973         if (!NT_STATUS_IS_OK(status)) {
974                 DEBUG(2,("sid_to_name: failed to lookup sids: %s\n",
975                         nt_errstr(status)));
976                 goto error;
977         }
978
979         if (type) {
980                 *type = (enum lsa_SidType) types[0];
981         }
982
983         if (name) {
984                 map_status = normalize_name_map(tmp_ctx,
985                                                 domain,
986                                                 *name,
987                                                 &mapped_name);
988                 if (NT_STATUS_IS_OK(map_status) ||
989                     NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
990                         *name = talloc_strdup(mem_ctx, mapped_name);
991                         DEBUG(5,("returning mapped name -- %s\n", *name));
992                 } else {
993                         *name = talloc_strdup(mem_ctx, names[0]);
994                 }
995                 if (*name == NULL) {
996                         status = NT_STATUS_NO_MEMORY;
997                         goto error;
998                 }
999         }
1000
1001         if (domain_name) {
1002                 *domain_name = talloc_strdup(mem_ctx, domains[0]);
1003                 if (*domain_name == NULL) {
1004                         status = NT_STATUS_NO_MEMORY;
1005                         goto error;
1006                 }
1007         }
1008
1009 error:
1010         TALLOC_FREE(tmp_ctx);
1011         return status;
1012 }
1013
1014 static NTSTATUS common_rids_to_names(struct winbindd_domain *domain,
1015                                      TALLOC_CTX *mem_ctx,
1016                                      const struct dom_sid *sid,
1017                                      uint32 *rids,
1018                                      size_t num_rids,
1019                                      char **pdomain_name,
1020                                      char ***pnames,
1021                                      enum lsa_SidType **ptypes)
1022 {
1023         struct rpc_pipe_client *lsa_pipe;
1024         struct policy_handle lsa_policy;
1025         enum lsa_SidType *types = NULL;
1026         char *domain_name = NULL;
1027         char **domains = NULL;
1028         char **names = NULL;
1029         struct dom_sid *sids;
1030         size_t i;
1031         TALLOC_CTX *tmp_ctx;
1032         NTSTATUS status;
1033
1034         DEBUG(3,("samr: rids to names for domain %s\n", domain->name));
1035
1036         tmp_ctx = talloc_stackframe();
1037         if (tmp_ctx == NULL) {
1038                 return NT_STATUS_NO_MEMORY;
1039         }
1040
1041         status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
1042         if (!NT_STATUS_IS_OK(status)) {
1043                 goto error;
1044         }
1045
1046         if (num_rids) {
1047                 sids = TALLOC_ARRAY(tmp_ctx, struct dom_sid, num_rids);
1048                 if (sids == NULL) {
1049                         status = NT_STATUS_NO_MEMORY;
1050                         goto error;
1051                 }
1052         } else {
1053                 sids = NULL;
1054         }
1055
1056         for (i = 0; i < num_rids; i++) {
1057                 if (!sid_compose(&sids[i], sid, rids[i])) {
1058                         status = NT_STATUS_INTERNAL_ERROR;
1059                         goto error;
1060                 }
1061         }
1062
1063         /*
1064          * We don't run into deadlocks here, cause winbind_off() is called in
1065          * the main function.
1066          */
1067         status = rpccli_lsa_lookup_sids(lsa_pipe,
1068                                         tmp_ctx,
1069                                         &lsa_policy,
1070                                         num_rids,
1071                                         sids,
1072                                         &domains,
1073                                         &names,
1074                                         &types);
1075         if (!NT_STATUS_IS_OK(status) &&
1076             !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
1077                 DEBUG(2,("rids_to_names: failed to lookup sids: %s\n",
1078                         nt_errstr(status)));
1079                 goto error;
1080         }
1081
1082         for (i = 0; i < num_rids; i++) {
1083                 char *mapped_name = NULL;
1084                 NTSTATUS map_status;
1085
1086                 if (types[i] != SID_NAME_UNKNOWN) {
1087                         map_status = normalize_name_map(tmp_ctx,
1088                                                         domain,
1089                                                         names[i],
1090                                                         &mapped_name);
1091                         if (NT_STATUS_IS_OK(map_status) ||
1092                             NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
1093                                 TALLOC_FREE(names[i]);
1094                                 names[i] = talloc_strdup(names, mapped_name);
1095                                 if (names[i] == NULL) {
1096                                         status = NT_STATUS_NO_MEMORY;
1097                                         goto error;
1098                                 }
1099                         }
1100
1101                         domain_name = domains[i];
1102                 }
1103         }
1104
1105         if (pdomain_name) {
1106                 *pdomain_name = talloc_strdup(mem_ctx, domain_name);
1107                 if (*pdomain_name == NULL) {
1108                         status = NT_STATUS_NO_MEMORY;
1109                         goto error;
1110                 }
1111         }
1112
1113         if (ptypes) {
1114                 *ptypes = talloc_move(mem_ctx, &types);
1115         }
1116
1117         if (pnames) {
1118                 *pnames = talloc_move(mem_ctx, &names);
1119         }
1120
1121 error:
1122         TALLOC_FREE(tmp_ctx);
1123         return status;
1124 }
1125
1126 static NTSTATUS common_lockout_policy(struct winbindd_domain *domain,
1127                                       TALLOC_CTX *mem_ctx,
1128                                       struct samr_DomInfo12 *lockout_policy)
1129 {
1130         struct rpc_pipe_client *samr_pipe;
1131         struct policy_handle dom_pol;
1132         union samr_DomainInfo *info = NULL;
1133         TALLOC_CTX *tmp_ctx;
1134         NTSTATUS status;
1135
1136         DEBUG(3,("samr: lockout policy\n"));
1137
1138         tmp_ctx = talloc_stackframe();
1139         if (tmp_ctx == NULL) {
1140                 return NT_STATUS_NO_MEMORY;
1141         }
1142
1143         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
1144         if (!NT_STATUS_IS_OK(status)) {
1145                 goto error;
1146         }
1147
1148         status = rpccli_samr_QueryDomainInfo(samr_pipe,
1149                                              mem_ctx,
1150                                              &dom_pol,
1151                                              12,
1152                                              &info);
1153         if (!NT_STATUS_IS_OK(status)) {
1154                 goto error;
1155         }
1156
1157         *lockout_policy = info->info12;
1158
1159 error:
1160         TALLOC_FREE(tmp_ctx);
1161         return status;
1162 }
1163
1164 static NTSTATUS common_password_policy(struct winbindd_domain *domain,
1165                                        TALLOC_CTX *mem_ctx,
1166                                        struct samr_DomInfo1 *policy)
1167 {
1168         /* TODO FIXME */
1169         return NT_STATUS_NOT_IMPLEMENTED;
1170 }
1171
1172 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
1173 static NTSTATUS common_lookup_usergroups(struct winbindd_domain *domain,
1174                                          TALLOC_CTX *mem_ctx,
1175                                          const struct dom_sid *user_sid,
1176                                          uint32_t *num_groups,
1177                                          struct dom_sid **user_gids)
1178 {
1179         /* TODO FIXME */
1180         return NT_STATUS_NOT_IMPLEMENTED;
1181 }
1182
1183 static NTSTATUS common_lookup_useraliases(struct winbindd_domain *domain,
1184                                           TALLOC_CTX *mem_ctx,
1185                                           uint32_t num_sids,
1186                                           const struct dom_sid *sids,
1187                                           uint32_t *p_num_aliases,
1188                                           uint32_t **rids)
1189 {
1190         /* TODO FIXME */
1191         return NT_STATUS_NOT_IMPLEMENTED;
1192 }
1193
1194 /* find the sequence number for a domain */
1195 static NTSTATUS common_sequence_number(struct winbindd_domain *domain,
1196                                        uint32_t *seq)
1197 {
1198         /* TODO FIXME */
1199         return NT_STATUS_NOT_IMPLEMENTED;
1200 }
1201
1202 #if 0
1203 /* the rpc backend methods are exposed via this structure */
1204 struct winbindd_methods builtin_passdb_methods = {
1205         .consistent            = false,
1206
1207         .query_user_list       = builtin_query_user_list,
1208         .enum_dom_groups       = builtin_enum_dom_groups,
1209         .enum_local_groups     = common_enum_local_groups,
1210         .name_to_sid           = common_name_to_sid,
1211         .sid_to_name           = common_sid_to_name,
1212         .rids_to_names         = common_rids_to_names,
1213         .query_user            = builtin_query_user,
1214         .lookup_usergroups     = common_lookup_usergroups,
1215         .lookup_useraliases    = common_lookup_useraliases,
1216         .lookup_groupmem       = sam_lookup_groupmem,
1217         .sequence_number       = common_sequence_number,
1218         .lockout_policy        = common_lockout_policy,
1219         .password_policy       = common_password_policy,
1220         .trusted_domains       = builtin_trusted_domains
1221 };
1222
1223 /* the rpc backend methods are exposed via this structure */
1224 struct winbindd_methods sam_passdb_methods = {
1225         .consistent            = false,
1226
1227         .query_user_list       = sam_query_user_list,
1228         .enum_dom_groups       = sam_enum_dom_groups,
1229         .enum_local_groups     = common_enum_local_groups,
1230         .name_to_sid           = common_name_to_sid,
1231         .sid_to_name           = common_sid_to_name,
1232         .rids_to_names         = common_rids_to_names,
1233         .query_user            = sam_query_user,
1234         .lookup_usergroups     = common_lookup_usergroups,
1235         .lookup_useraliases    = common_lookup_useraliases,
1236         .lookup_groupmem       = sam_lookup_groupmem,
1237         .sequence_number       = common_sequence_number,
1238         .lockout_policy        = common_lockout_policy,
1239         .password_policy       = common_password_policy,
1240         .trusted_domains       = sam_trusted_domains
1241 };
1242 #endif