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