winbind: Simplify query_user_list to only return rids
[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 "winbindd_rpc.h"
29 #include "lib/util_unixsids.h"
30 #include "rpc_client/rpc_client.h"
31 #include "../librpc/gen_ndr/ndr_samr_c.h"
32 #include "rpc_client/cli_samr.h"
33 #include "../librpc/gen_ndr/ndr_lsa_c.h"
34 #include "rpc_client/cli_lsarpc.h"
35 #include "rpc_server/rpc_ncacn_np.h"
36 #include "../libcli/security/security.h"
37 #include "passdb/machine_sid.h"
38 #include "auth.h"
39
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_WINBIND
42
43 NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
44                                  struct winbindd_domain *domain,
45                                  struct rpc_pipe_client **samr_pipe,
46                                  struct policy_handle *samr_domain_hnd)
47 {
48         NTSTATUS status, result;
49         struct policy_handle samr_connect_hnd;
50         struct dcerpc_binding_handle *b;
51
52         status = wb_open_internal_pipe(mem_ctx, &ndr_table_samr, samr_pipe);
53         if (!NT_STATUS_IS_OK(status)) {
54                 return status;
55         }
56
57         b = (*samr_pipe)->binding_handle;
58
59         status = dcerpc_samr_Connect2(b, mem_ctx,
60                                       (*samr_pipe)->desthost,
61                                       SEC_FLAG_MAXIMUM_ALLOWED,
62                                       &samr_connect_hnd,
63                                       &result);
64         if (!NT_STATUS_IS_OK(status)) {
65                 return status;
66         }
67         if (!NT_STATUS_IS_OK(result)) {
68                 return result;
69         }
70
71         status = dcerpc_samr_OpenDomain(b, mem_ctx,
72                                         &samr_connect_hnd,
73                                         SEC_FLAG_MAXIMUM_ALLOWED,
74                                         &domain->sid,
75                                         samr_domain_hnd,
76                                         &result);
77         if (!NT_STATUS_IS_OK(status)) {
78                 return status;
79         }
80
81         return result;
82 }
83
84 NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
85                                 struct rpc_pipe_client **lsa_pipe,
86                                 struct policy_handle *lsa_hnd)
87 {
88         NTSTATUS status;
89
90         status = wb_open_internal_pipe(mem_ctx, &ndr_table_lsarpc, lsa_pipe);
91         if (!NT_STATUS_IS_OK(status)) {
92                 return status;
93         }
94
95         status = rpccli_lsa_open_policy((*lsa_pipe),
96                                         mem_ctx,
97                                         true,
98                                         SEC_FLAG_MAXIMUM_ALLOWED,
99                                         lsa_hnd);
100
101         return status;
102 }
103
104 /*********************************************************************
105  SAM specific functions.
106 *********************************************************************/
107
108 /* List all domain groups */
109 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
110                                     TALLOC_CTX *mem_ctx,
111                                     uint32_t *pnum_info,
112                                     struct wb_acct_info **pinfo)
113 {
114         struct rpc_pipe_client *samr_pipe;
115         struct policy_handle dom_pol;
116         struct wb_acct_info *info = NULL;
117         uint32_t num_info = 0;
118         TALLOC_CTX *tmp_ctx;
119         NTSTATUS status, result;
120         struct dcerpc_binding_handle *b = NULL;
121
122         DEBUG(3,("sam_enum_dom_groups\n"));
123
124         ZERO_STRUCT(dom_pol);
125
126         if (pnum_info) {
127                 *pnum_info = 0;
128         }
129
130         tmp_ctx = talloc_stackframe();
131         if (tmp_ctx == NULL) {
132                 return NT_STATUS_NO_MEMORY;
133         }
134
135         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
136         if (!NT_STATUS_IS_OK(status)) {
137                 goto error;
138         }
139
140         b = samr_pipe->binding_handle;
141
142         status = rpc_enum_dom_groups(tmp_ctx,
143                                      samr_pipe,
144                                      &dom_pol,
145                                      &num_info,
146                                      &info);
147         if (!NT_STATUS_IS_OK(status)) {
148                 goto error;
149         }
150
151         if (pnum_info) {
152                 *pnum_info = num_info;
153         }
154
155         if (pinfo) {
156                 *pinfo = talloc_move(mem_ctx, &info);
157         }
158
159 error:
160         if (b && is_valid_policy_hnd(&dom_pol)) {
161                 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
162         }
163         TALLOC_FREE(tmp_ctx);
164         return status;
165 }
166
167 /* Query display info for a domain */
168 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
169                                     TALLOC_CTX *mem_ctx,
170                                     uint32_t **prids)
171 {
172         struct rpc_pipe_client *samr_pipe = NULL;
173         struct policy_handle dom_pol;
174         uint32_t *rids;
175         TALLOC_CTX *tmp_ctx;
176         NTSTATUS status, result;
177         struct dcerpc_binding_handle *b = NULL;
178
179         DEBUG(3,("samr_query_user_list\n"));
180
181         ZERO_STRUCT(dom_pol);
182
183         *prids = NULL;
184
185         tmp_ctx = talloc_stackframe();
186         if (tmp_ctx == NULL) {
187                 return NT_STATUS_NO_MEMORY;
188         }
189
190         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
191         if (!NT_STATUS_IS_OK(status)) {
192                 goto done;
193         }
194
195         b = samr_pipe->binding_handle;
196
197         status = rpc_query_user_list(tmp_ctx,
198                                      samr_pipe,
199                                      &dom_pol,
200                                      &domain->sid,
201                                      &rids);
202         if (!NT_STATUS_IS_OK(status)) {
203                 goto done;
204         }
205
206         if (prids) {
207                 *prids = talloc_move(mem_ctx, &rids);
208         }
209
210 done:
211         if (b && is_valid_policy_hnd(&dom_pol)) {
212                 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
213         }
214
215         TALLOC_FREE(tmp_ctx);
216         return status;
217 }
218
219 /* get a list of trusted domains - builtin domain */
220 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
221                                     TALLOC_CTX *mem_ctx,
222                                     struct netr_DomainTrustList *ptrust_list)
223 {
224         struct rpc_pipe_client *lsa_pipe;
225         struct policy_handle lsa_policy;
226         struct netr_DomainTrust *trusts = NULL;
227         uint32_t num_trusts = 0;
228         TALLOC_CTX *tmp_ctx;
229         NTSTATUS status, result;
230         struct dcerpc_binding_handle *b = NULL;
231
232         DEBUG(3,("samr: trusted domains\n"));
233
234         ZERO_STRUCT(lsa_policy);
235
236         if (ptrust_list) {
237                 ZERO_STRUCTP(ptrust_list);
238         }
239
240         tmp_ctx = talloc_stackframe();
241         if (tmp_ctx == NULL) {
242                 return NT_STATUS_NO_MEMORY;
243         }
244
245         status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
246         if (!NT_STATUS_IS_OK(status)) {
247                 goto done;
248         }
249
250         b = lsa_pipe->binding_handle;
251
252         status = rpc_trusted_domains(tmp_ctx,
253                                      lsa_pipe,
254                                      &lsa_policy,
255                                      &num_trusts,
256                                      &trusts);
257         if (!NT_STATUS_IS_OK(status)) {
258                 goto done;
259         }
260
261         if (ptrust_list) {
262                 ptrust_list->count = num_trusts;
263                 ptrust_list->array = talloc_move(mem_ctx, &trusts);
264         }
265
266 done:
267         if (b && is_valid_policy_hnd(&lsa_policy)) {
268                 dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
269         }
270
271         TALLOC_FREE(tmp_ctx);
272         return status;
273 }
274
275 /* Lookup group membership given a rid.   */
276 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
277                                     TALLOC_CTX *mem_ctx,
278                                     const struct dom_sid *group_sid,
279                                     enum lsa_SidType type,
280                                     uint32_t *pnum_names,
281                                     struct dom_sid **psid_mem,
282                                     char ***pnames,
283                                     uint32_t **pname_types)
284 {
285         struct rpc_pipe_client *samr_pipe;
286         struct policy_handle dom_pol;
287
288         uint32_t num_names = 0;
289         struct dom_sid *sid_mem = NULL;
290         char **names = NULL;
291         uint32_t *name_types = NULL;
292
293         TALLOC_CTX *tmp_ctx;
294         NTSTATUS status, result;
295         struct dcerpc_binding_handle *b = NULL;
296
297         DEBUG(3,("sam_lookup_groupmem\n"));
298
299         ZERO_STRUCT(dom_pol);
300
301         /* Paranoia check */
302         if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) {
303                 /* There's no groups, only aliases in BUILTIN */
304                 return NT_STATUS_NO_SUCH_GROUP;
305         }
306
307         if (pnum_names) {
308                 *pnum_names = 0;
309         }
310
311         tmp_ctx = talloc_stackframe();
312         if (tmp_ctx == NULL) {
313                 return NT_STATUS_NO_MEMORY;
314         }
315
316         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
317         if (!NT_STATUS_IS_OK(status)) {
318                 goto done;
319         }
320
321         b = samr_pipe->binding_handle;
322
323         status = rpc_lookup_groupmem(tmp_ctx,
324                                      samr_pipe,
325                                      &dom_pol,
326                                      domain->name,
327                                      &domain->sid,
328                                      group_sid,
329                                      type,
330                                      &num_names,
331                                      &sid_mem,
332                                      &names,
333                                      &name_types);
334
335         if (pnum_names) {
336                 *pnum_names = num_names;
337         }
338
339         if (pnames) {
340                 *pnames = talloc_move(mem_ctx, &names);
341         }
342
343         if (pname_types) {
344                 *pname_types = talloc_move(mem_ctx, &name_types);
345         }
346
347         if (psid_mem) {
348                 *psid_mem = talloc_move(mem_ctx, &sid_mem);
349         }
350
351 done:
352         if (b && is_valid_policy_hnd(&dom_pol)) {
353                 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
354         }
355
356         TALLOC_FREE(tmp_ctx);
357         return status;
358 }
359
360 /*********************************************************************
361  BUILTIN specific functions.
362 *********************************************************************/
363
364 /* List all domain groups */
365 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
366                                 TALLOC_CTX *mem_ctx,
367                                 uint32_t *num_entries,
368                                 struct wb_acct_info **info)
369 {
370         /* BUILTIN doesn't have domain groups */
371         *num_entries = 0;
372         *info = NULL;
373         return NT_STATUS_OK;
374 }
375
376 /* Query display info for a domain */
377 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
378                                 TALLOC_CTX *mem_ctx,
379                                 uint32_t **rids)
380 {
381         /* We don't have users */
382         *rids = NULL;
383         return NT_STATUS_OK;
384 }
385
386 /* get a list of trusted domains - builtin domain */
387 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
388                                         TALLOC_CTX *mem_ctx,
389                                         struct netr_DomainTrustList *trusts)
390 {
391         ZERO_STRUCTP(trusts);
392         return NT_STATUS_OK;
393 }
394
395 /*********************************************************************
396  COMMON functions.
397 *********************************************************************/
398
399 /* List all local groups (aliases) */
400 static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
401                                       TALLOC_CTX *mem_ctx,
402                                       uint32_t *pnum_info,
403                                       struct wb_acct_info **pinfo)
404 {
405         struct rpc_pipe_client *samr_pipe;
406         struct policy_handle dom_pol;
407         struct wb_acct_info *info = NULL;
408         uint32_t num_info = 0;
409         TALLOC_CTX *tmp_ctx;
410         NTSTATUS status, result;
411         struct dcerpc_binding_handle *b = NULL;
412
413         DEBUG(3,("samr: enum local groups\n"));
414
415         ZERO_STRUCT(dom_pol);
416
417         if (pnum_info) {
418                 *pnum_info = 0;
419         }
420
421         tmp_ctx = talloc_stackframe();
422         if (tmp_ctx == NULL) {
423                 return NT_STATUS_NO_MEMORY;
424         }
425
426         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
427         if (!NT_STATUS_IS_OK(status)) {
428                 goto done;
429         }
430
431         b = samr_pipe->binding_handle;
432
433         status = rpc_enum_local_groups(mem_ctx,
434                                        samr_pipe,
435                                        &dom_pol,
436                                        &num_info,
437                                        &info);
438         if (!NT_STATUS_IS_OK(status)) {
439                 goto done;
440         }
441
442         if (pnum_info) {
443                 *pnum_info = num_info;
444         }
445
446         if (pinfo) {
447                 *pinfo = talloc_move(mem_ctx, &info);
448         }
449
450 done:
451         if (b && is_valid_policy_hnd(&dom_pol)) {
452                 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
453         }
454
455         TALLOC_FREE(tmp_ctx);
456         return status;
457 }
458
459 /* convert a single name to a sid in a domain */
460 static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
461                                    TALLOC_CTX *mem_ctx,
462                                    const char *domain_name,
463                                    const char *name,
464                                    uint32_t flags,
465                                    struct dom_sid *psid,
466                                    enum lsa_SidType *ptype)
467 {
468         struct rpc_pipe_client *lsa_pipe;
469         struct policy_handle lsa_policy;
470         struct dom_sid sid;
471         enum lsa_SidType type;
472         TALLOC_CTX *tmp_ctx;
473         NTSTATUS status, result;
474         struct dcerpc_binding_handle *b = NULL;
475
476         DEBUG(3,("sam_name_to_sid\n"));
477
478         ZERO_STRUCT(lsa_policy);
479
480         tmp_ctx = talloc_stackframe();
481         if (tmp_ctx == NULL) {
482                 return NT_STATUS_NO_MEMORY;
483         }
484
485         status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
486         if (!NT_STATUS_IS_OK(status)) {
487                 goto done;
488         }
489
490         b = lsa_pipe->binding_handle;
491
492         status = rpc_name_to_sid(tmp_ctx,
493                                  lsa_pipe,
494                                  &lsa_policy,
495                                  domain_name,
496                                  name,
497                                  flags,
498                                  &sid,
499                                  &type);
500         if (!NT_STATUS_IS_OK(status)) {
501                 goto done;
502         }
503
504         if (psid) {
505                 sid_copy(psid, &sid);
506         }
507         if (ptype) {
508                 *ptype = type;
509         }
510
511 done:
512         if (b && is_valid_policy_hnd(&lsa_policy)) {
513                 dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
514         }
515
516         TALLOC_FREE(tmp_ctx);
517         return status;
518 }
519
520 /* convert a domain SID to a user or group name */
521 static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
522                                 TALLOC_CTX *mem_ctx,
523                                 const struct dom_sid *sid,
524                                 char **pdomain_name,
525                                 char **pname,
526                                 enum lsa_SidType *ptype)
527 {
528         struct rpc_pipe_client *lsa_pipe;
529         struct policy_handle lsa_policy;
530         char *domain_name = NULL;
531         char *name = NULL;
532         enum lsa_SidType type;
533         TALLOC_CTX *tmp_ctx;
534         NTSTATUS status, result;
535         struct dcerpc_binding_handle *b = NULL;
536
537         DEBUG(3,("sam_sid_to_name\n"));
538
539         ZERO_STRUCT(lsa_policy);
540
541         /* Paranoia check */
542         if (!sid_check_is_in_builtin(sid) &&
543             !sid_check_is_builtin(sid) &&
544             !sid_check_is_in_our_sam(sid) &&
545             !sid_check_is_our_sam(sid) &&
546             !sid_check_is_in_unix_users(sid) &&
547             !sid_check_is_unix_users(sid) &&
548             !sid_check_is_in_unix_groups(sid) &&
549             !sid_check_is_unix_groups(sid) &&
550             !sid_check_is_in_wellknown_domain(sid)) {
551                 DEBUG(0, ("sam_sid_to_name: possible deadlock - trying to "
552                           "lookup SID %s\n", sid_string_dbg(sid)));
553                 return NT_STATUS_NONE_MAPPED;
554         }
555
556         tmp_ctx = talloc_stackframe();
557         if (tmp_ctx == NULL) {
558                 return NT_STATUS_NO_MEMORY;
559         }
560
561         status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
562         if (!NT_STATUS_IS_OK(status)) {
563                 goto done;
564         }
565
566         b = lsa_pipe->binding_handle;
567
568         status = rpc_sid_to_name(tmp_ctx,
569                                  lsa_pipe,
570                                  &lsa_policy,
571                                  domain,
572                                  sid,
573                                  &domain_name,
574                                  &name,
575                                  &type);
576
577         if (ptype) {
578                 *ptype = type;
579         }
580
581         if (pname) {
582                 *pname = talloc_move(mem_ctx, &name);
583         }
584
585         if (pdomain_name) {
586                 *pdomain_name = talloc_move(mem_ctx, &domain_name);
587         }
588
589 done:
590         if (b && is_valid_policy_hnd(&lsa_policy)) {
591                 dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
592         }
593
594         TALLOC_FREE(tmp_ctx);
595         return status;
596 }
597
598 static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
599                                   TALLOC_CTX *mem_ctx,
600                                   const struct dom_sid *domain_sid,
601                                   uint32_t *rids,
602                                   size_t num_rids,
603                                   char **pdomain_name,
604                                   char ***pnames,
605                                   enum lsa_SidType **ptypes)
606 {
607         struct rpc_pipe_client *lsa_pipe;
608         struct policy_handle lsa_policy;
609         enum lsa_SidType *types = NULL;
610         char *domain_name = NULL;
611         char **names = NULL;
612         TALLOC_CTX *tmp_ctx;
613         NTSTATUS status, result;
614         struct dcerpc_binding_handle *b = NULL;
615
616         DEBUG(3,("sam_rids_to_names for %s\n", domain->name));
617
618         ZERO_STRUCT(lsa_policy);
619
620         /* Paranoia check */
621         if (!sid_check_is_builtin(domain_sid) &&
622             !sid_check_is_our_sam(domain_sid) &&
623             !sid_check_is_unix_users(domain_sid) &&
624             !sid_check_is_unix_groups(domain_sid) &&
625             !sid_check_is_in_wellknown_domain(domain_sid)) {
626                 DEBUG(0, ("sam_rids_to_names: possible deadlock - trying to "
627                           "lookup SID %s\n", sid_string_dbg(domain_sid)));
628                 return NT_STATUS_NONE_MAPPED;
629         }
630
631         tmp_ctx = talloc_stackframe();
632         if (tmp_ctx == NULL) {
633                 return NT_STATUS_NO_MEMORY;
634         }
635
636         status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
637         if (!NT_STATUS_IS_OK(status)) {
638                 goto done;
639         }
640
641         b = lsa_pipe->binding_handle;
642
643         status = rpc_rids_to_names(tmp_ctx,
644                                    lsa_pipe,
645                                    &lsa_policy,
646                                    domain,
647                                    domain_sid,
648                                    rids,
649                                    num_rids,
650                                    &domain_name,
651                                    &names,
652                                    &types);
653         if (!NT_STATUS_IS_OK(status)) {
654                 goto done;
655         }
656
657         if (pdomain_name) {
658                 *pdomain_name = talloc_move(mem_ctx, &domain_name);
659         }
660
661         if (ptypes) {
662                 *ptypes = talloc_move(mem_ctx, &types);
663         }
664
665         if (pnames) {
666                 *pnames = talloc_move(mem_ctx, &names);
667         }
668
669 done:
670         if (b && is_valid_policy_hnd(&lsa_policy)) {
671                 dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
672         }
673
674         TALLOC_FREE(tmp_ctx);
675         return status;
676 }
677
678 static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain,
679                                    TALLOC_CTX *mem_ctx,
680                                    struct samr_DomInfo12 *lockout_policy)
681 {
682         struct rpc_pipe_client *samr_pipe;
683         struct policy_handle dom_pol;
684         union samr_DomainInfo *info = NULL;
685         TALLOC_CTX *tmp_ctx;
686         NTSTATUS status, result;
687         struct dcerpc_binding_handle *b = NULL;
688
689         DEBUG(3,("sam_lockout_policy\n"));
690
691         ZERO_STRUCT(dom_pol);
692
693         tmp_ctx = talloc_stackframe();
694         if (tmp_ctx == NULL) {
695                 return NT_STATUS_NO_MEMORY;
696         }
697
698         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
699         if (!NT_STATUS_IS_OK(status)) {
700                 goto error;
701         }
702
703         b = samr_pipe->binding_handle;
704
705         status = dcerpc_samr_QueryDomainInfo(b,
706                                              mem_ctx,
707                                              &dom_pol,
708                                              DomainLockoutInformation,
709                                              &info,
710                                              &result);
711         if (!NT_STATUS_IS_OK(status)) {
712                 goto error;
713         }
714         if (!NT_STATUS_IS_OK(result)) {
715                 status = result;
716                 goto error;
717         }
718
719         *lockout_policy = info->info12;
720
721 error:
722         if (b && is_valid_policy_hnd(&dom_pol)) {
723                 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
724         }
725
726         TALLOC_FREE(tmp_ctx);
727         return status;
728 }
729
730 static NTSTATUS sam_password_policy(struct winbindd_domain *domain,
731                                     TALLOC_CTX *mem_ctx,
732                                     struct samr_DomInfo1 *passwd_policy)
733 {
734         struct rpc_pipe_client *samr_pipe;
735         struct policy_handle dom_pol;
736         union samr_DomainInfo *info = NULL;
737         TALLOC_CTX *tmp_ctx;
738         NTSTATUS status, result;
739         struct dcerpc_binding_handle *b = NULL;
740
741         DEBUG(3,("sam_password_policy\n"));
742
743         ZERO_STRUCT(dom_pol);
744
745         tmp_ctx = talloc_stackframe();
746         if (tmp_ctx == NULL) {
747                 return NT_STATUS_NO_MEMORY;
748         }
749
750         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
751         if (!NT_STATUS_IS_OK(status)) {
752                 goto error;
753         }
754
755         b = samr_pipe->binding_handle;
756
757         status = dcerpc_samr_QueryDomainInfo(b,
758                                              mem_ctx,
759                                              &dom_pol,
760                                              DomainPasswordInformation,
761                                              &info,
762                                              &result);
763         if (!NT_STATUS_IS_OK(status)) {
764                 goto error;
765         }
766         if (!NT_STATUS_IS_OK(result)) {
767                 status = result;
768                 goto error;
769         }
770
771         *passwd_policy = info->info1;
772
773 error:
774         if (b && is_valid_policy_hnd(&dom_pol)) {
775                 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
776         }
777
778         TALLOC_FREE(tmp_ctx);
779         return status;
780 }
781
782 static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
783                                        TALLOC_CTX *mem_ctx,
784                                        uint32_t num_sids,
785                                        const struct dom_sid *sids,
786                                        uint32_t *pnum_aliases,
787                                        uint32_t **palias_rids)
788 {
789         struct rpc_pipe_client *samr_pipe;
790         struct policy_handle dom_pol;
791         uint32_t num_aliases = 0;
792         uint32_t *alias_rids = NULL;
793         TALLOC_CTX *tmp_ctx;
794         NTSTATUS status, result;
795         struct dcerpc_binding_handle *b = NULL;
796
797         DEBUG(3,("sam_lookup_useraliases\n"));
798
799         ZERO_STRUCT(dom_pol);
800
801         if (pnum_aliases) {
802                 *pnum_aliases = 0;
803         }
804
805         tmp_ctx = talloc_stackframe();
806         if (tmp_ctx == NULL) {
807                 return NT_STATUS_NO_MEMORY;
808         }
809
810         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
811         if (!NT_STATUS_IS_OK(status)) {
812                 goto done;
813         }
814
815         b = samr_pipe->binding_handle;
816
817         status = rpc_lookup_useraliases(tmp_ctx,
818                                         samr_pipe,
819                                         &dom_pol,
820                                         num_sids,
821                                         sids,
822                                         &num_aliases,
823                                         &alias_rids);
824         if (!NT_STATUS_IS_OK(status)) {
825                 goto done;
826         }
827
828         if (pnum_aliases) {
829                 *pnum_aliases = num_aliases;
830         }
831
832         if (palias_rids) {
833                 *palias_rids = talloc_move(mem_ctx, &alias_rids);
834         }
835
836 done:
837         if (b && is_valid_policy_hnd(&dom_pol)) {
838                 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
839         }
840
841         TALLOC_FREE(tmp_ctx);
842         return status;
843 }
844
845 /* find the sequence number for a domain */
846 static NTSTATUS sam_sequence_number(struct winbindd_domain *domain,
847                                     uint32_t *pseq)
848 {
849         struct rpc_pipe_client *samr_pipe;
850         struct policy_handle dom_pol;
851         uint32_t seq = DOM_SEQUENCE_NONE;
852         TALLOC_CTX *tmp_ctx;
853         NTSTATUS status, result;
854         struct dcerpc_binding_handle *b = NULL;
855
856         DEBUG(3,("samr: sequence number\n"));
857
858         ZERO_STRUCT(dom_pol);
859
860         if (pseq) {
861                 *pseq = DOM_SEQUENCE_NONE;
862         }
863
864         tmp_ctx = talloc_stackframe();
865         if (tmp_ctx == NULL) {
866                 return NT_STATUS_NO_MEMORY;
867         }
868
869         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
870         if (!NT_STATUS_IS_OK(status)) {
871                 goto done;
872         }
873
874         b = samr_pipe->binding_handle;
875
876         status = rpc_sequence_number(tmp_ctx,
877                                      samr_pipe,
878                                      &dom_pol,
879                                      domain->name,
880                                      &seq);
881         if (!NT_STATUS_IS_OK(status)) {
882                 goto done;
883         }
884
885         if (pseq) {
886                 *pseq = seq;
887         }
888 done:
889         if (b && is_valid_policy_hnd(&dom_pol)) {
890                 dcerpc_samr_Close(b, tmp_ctx, &dom_pol, &result);
891         }
892
893         TALLOC_FREE(tmp_ctx);
894         return status;
895 }
896
897 /* the rpc backend methods are exposed via this structure */
898 struct winbindd_methods builtin_passdb_methods = {
899         .consistent            = false,
900
901         .query_user_list       = builtin_query_user_list,
902         .enum_dom_groups       = builtin_enum_dom_groups,
903         .enum_local_groups     = sam_enum_local_groups,
904         .name_to_sid           = sam_name_to_sid,
905         .sid_to_name           = sam_sid_to_name,
906         .rids_to_names         = sam_rids_to_names,
907         .lookup_useraliases    = sam_lookup_useraliases,
908         .lookup_groupmem       = sam_lookup_groupmem,
909         .sequence_number       = sam_sequence_number,
910         .lockout_policy        = sam_lockout_policy,
911         .password_policy       = sam_password_policy,
912         .trusted_domains       = builtin_trusted_domains
913 };
914
915 /* the rpc backend methods are exposed via this structure */
916 struct winbindd_methods sam_passdb_methods = {
917         .consistent            = false,
918
919         .query_user_list       = sam_query_user_list,
920         .enum_dom_groups       = sam_enum_dom_groups,
921         .enum_local_groups     = sam_enum_local_groups,
922         .name_to_sid           = sam_name_to_sid,
923         .sid_to_name           = sam_sid_to_name,
924         .rids_to_names         = sam_rids_to_names,
925         .lookup_useraliases    = sam_lookup_useraliases,
926         .lookup_groupmem       = sam_lookup_groupmem,
927         .sequence_number       = sam_sequence_number,
928         .lockout_policy        = sam_lockout_policy,
929         .password_policy       = sam_password_policy,
930         .trusted_domains       = sam_trusted_domains
931 };