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