libndr: Avoid assigning duplicate versions to symbols
[amitay/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 "rpc_client/cli_pipe.h"
32 #include "../librpc/gen_ndr/ndr_samr_c.h"
33 #include "rpc_client/cli_samr.h"
34 #include "../librpc/gen_ndr/ndr_lsa_c.h"
35 #include "rpc_client/cli_lsarpc.h"
36 #include "rpc_server/rpc_ncacn_np.h"
37 #include "../libcli/security/security.h"
38 #include "passdb/machine_sid.h"
39 #include "auth.h"
40
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_WINBIND
43
44 /*
45  * The other end of this won't go away easily, so we can trust it
46  *
47  * It is either a long-lived process with the same lifetime as
48  * winbindd or a part of this process
49  */
50 struct winbind_internal_pipes {
51         struct rpc_pipe_client *samr_pipe;
52         struct policy_handle samr_domain_hnd;
53         struct rpc_pipe_client *lsa_pipe;
54         struct policy_handle lsa_hnd;
55 };
56
57
58 NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
59                                  struct winbindd_domain *domain,
60                                  struct rpc_pipe_client **samr_pipe,
61                                  struct policy_handle *samr_domain_hnd)
62 {
63         NTSTATUS status, result;
64         struct policy_handle samr_connect_hnd;
65         struct dcerpc_binding_handle *b;
66
67         status = wb_open_internal_pipe(mem_ctx, &ndr_table_samr, samr_pipe);
68         if (!NT_STATUS_IS_OK(status)) {
69                 return status;
70         }
71
72         b = (*samr_pipe)->binding_handle;
73
74         status = dcerpc_samr_Connect2(b, mem_ctx,
75                                       (*samr_pipe)->desthost,
76                                       SEC_FLAG_MAXIMUM_ALLOWED,
77                                       &samr_connect_hnd,
78                                       &result);
79         if (!NT_STATUS_IS_OK(status)) {
80                 return status;
81         }
82         if (!NT_STATUS_IS_OK(result)) {
83                 return result;
84         }
85
86         status = dcerpc_samr_OpenDomain(b, mem_ctx,
87                                         &samr_connect_hnd,
88                                         SEC_FLAG_MAXIMUM_ALLOWED,
89                                         &domain->sid,
90                                         samr_domain_hnd,
91                                         &result);
92         if (!NT_STATUS_IS_OK(status)) {
93                 return status;
94         }
95
96         return result;
97 }
98
99 NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
100                                 struct rpc_pipe_client **lsa_pipe,
101                                 struct policy_handle *lsa_hnd)
102 {
103         NTSTATUS status;
104
105         status = wb_open_internal_pipe(mem_ctx, &ndr_table_lsarpc, lsa_pipe);
106         if (!NT_STATUS_IS_OK(status)) {
107                 return status;
108         }
109
110         status = rpccli_lsa_open_policy((*lsa_pipe),
111                                         mem_ctx,
112                                         true,
113                                         SEC_FLAG_MAXIMUM_ALLOWED,
114                                         lsa_hnd);
115
116         return status;
117 }
118
119
120 static NTSTATUS open_cached_internal_pipe_conn(
121         struct winbindd_domain *domain,
122         struct rpc_pipe_client **samr_pipe,
123         struct policy_handle *samr_domain_hnd,
124         struct rpc_pipe_client **lsa_pipe,
125         struct policy_handle *lsa_hnd)
126 {
127         struct winbind_internal_pipes *internal_pipes = NULL;
128
129         if (domain->private_data == NULL) {
130                 TALLOC_CTX *frame = talloc_stackframe();
131                 NTSTATUS status;
132
133                 internal_pipes = talloc_zero(frame,
134                                              struct winbind_internal_pipes);
135
136                 status = open_internal_samr_conn(
137                         internal_pipes,
138                         domain,
139                         &internal_pipes->samr_pipe,
140                         &internal_pipes->samr_domain_hnd);
141                 if (!NT_STATUS_IS_OK(status)) {
142                         TALLOC_FREE(frame);
143                         return status;
144                 }
145
146                 status = open_internal_lsa_conn(internal_pipes,
147                                                 &internal_pipes->lsa_pipe,
148                                                 &internal_pipes->lsa_hnd);
149
150                 if (!NT_STATUS_IS_OK(status)) {
151                         TALLOC_FREE(frame);
152                         return status;
153                 }
154
155                 domain->private_data = talloc_move(domain, &internal_pipes);
156
157                 TALLOC_FREE(frame);
158
159         }
160
161         internal_pipes = talloc_get_type_abort(
162                 domain->private_data, struct winbind_internal_pipes);
163
164         if (samr_domain_hnd) {
165                 *samr_domain_hnd = internal_pipes->samr_domain_hnd;
166         }
167
168         if (samr_pipe) {
169                 *samr_pipe = internal_pipes->samr_pipe;
170         }
171
172         if (lsa_hnd) {
173                 *lsa_hnd = internal_pipes->lsa_hnd;
174         }
175
176         if (lsa_pipe) {
177                 *lsa_pipe = internal_pipes->lsa_pipe;
178         }
179
180         return NT_STATUS_OK;
181 }
182
183 static bool reset_connection_on_error(struct winbindd_domain *domain,
184                                       struct rpc_pipe_client *p,
185                                       NTSTATUS status)
186 {
187         struct winbind_internal_pipes *internal_pipes = NULL;
188         struct dcerpc_binding_handle *b = p->binding_handle;
189
190         internal_pipes = talloc_get_type_abort(
191                 domain->private_data, struct winbind_internal_pipes);
192
193         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
194             NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR))
195         {
196                 TALLOC_FREE(internal_pipes);
197                 domain->private_data = NULL;
198                 return true;
199         }
200
201         if (!dcerpc_binding_handle_is_connected(b)) {
202                 TALLOC_FREE(internal_pipes);
203                 domain->private_data = NULL;
204                 return true;
205         }
206
207         return false;
208 }
209
210 /*********************************************************************
211  SAM specific functions.
212 *********************************************************************/
213
214 /* List all domain groups */
215 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
216                                     TALLOC_CTX *mem_ctx,
217                                     uint32_t *pnum_info,
218                                     struct wb_acct_info **pinfo)
219 {
220         struct rpc_pipe_client *samr_pipe;
221         struct policy_handle dom_pol = { 0 };
222         struct wb_acct_info *info = NULL;
223         uint32_t num_info = 0;
224         TALLOC_CTX *tmp_ctx;
225         NTSTATUS status;
226         bool retry = false;
227
228         DEBUG(3,("sam_enum_dom_groups\n"));
229
230         if (pnum_info) {
231                 *pnum_info = 0;
232         }
233
234         tmp_ctx = talloc_stackframe();
235         if (tmp_ctx == NULL) {
236                 return NT_STATUS_NO_MEMORY;
237         }
238
239 again:
240         status = open_cached_internal_pipe_conn(domain,
241                                                 &samr_pipe,
242                                                 &dom_pol,
243                                                 NULL,
244                                                 NULL);
245         if (!NT_STATUS_IS_OK(status)) {
246                 TALLOC_FREE(tmp_ctx);
247                 return status;
248         }
249
250         status = rpc_enum_dom_groups(tmp_ctx,
251                                      samr_pipe,
252                                      &dom_pol,
253                                      &num_info,
254                                      &info);
255
256         if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
257                 retry = true;
258                 goto again;
259         }
260
261         if (!NT_STATUS_IS_OK(status)) {
262                 TALLOC_FREE(tmp_ctx);
263                 return status;
264         }
265
266         if (pnum_info) {
267                 *pnum_info = num_info;
268         }
269
270         if (pinfo) {
271                 *pinfo = talloc_move(mem_ctx, &info);
272         }
273
274         TALLOC_FREE(tmp_ctx);
275         return status;
276 }
277
278 /* Query display info for a domain */
279 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
280                                     TALLOC_CTX *mem_ctx,
281                                     uint32_t **prids)
282 {
283         struct rpc_pipe_client *samr_pipe = NULL;
284         struct policy_handle dom_pol = { 0 };
285         uint32_t *rids = NULL;
286         TALLOC_CTX *tmp_ctx;
287         NTSTATUS status;
288         bool retry = false;
289
290         DEBUG(3,("samr_query_user_list\n"));
291
292         tmp_ctx = talloc_stackframe();
293         if (tmp_ctx == NULL) {
294                 return NT_STATUS_NO_MEMORY;
295         }
296
297 again:
298         status = open_cached_internal_pipe_conn(domain,
299                                                 &samr_pipe,
300                                                 &dom_pol,
301                                                 NULL,
302                                                 NULL);
303         if (!NT_STATUS_IS_OK(status)) {
304                 goto done;
305         }
306
307         status = rpc_query_user_list(tmp_ctx,
308                                      samr_pipe,
309                                      &dom_pol,
310                                      &domain->sid,
311                                      &rids);
312         if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
313                 retry = true;
314                 goto again;
315         }
316
317         if (!NT_STATUS_IS_OK(status)) {
318                 goto done;
319         }
320
321         if (prids != NULL) {
322                 *prids = talloc_move(mem_ctx, &rids);
323         }
324
325 done:
326         TALLOC_FREE(rids);
327         TALLOC_FREE(tmp_ctx);
328         return status;
329 }
330
331 /* get a list of trusted domains - builtin domain */
332 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
333                                     TALLOC_CTX *mem_ctx,
334                                     struct netr_DomainTrustList *ptrust_list)
335 {
336         struct rpc_pipe_client *lsa_pipe;
337         struct policy_handle lsa_policy = { 0 };
338         struct netr_DomainTrust *trusts = NULL;
339         uint32_t num_trusts = 0;
340         TALLOC_CTX *tmp_ctx;
341         NTSTATUS status;
342         bool retry = false;
343
344         DEBUG(3,("samr: trusted domains\n"));
345
346         if (ptrust_list) {
347                 ZERO_STRUCTP(ptrust_list);
348         }
349
350         tmp_ctx = talloc_stackframe();
351         if (tmp_ctx == NULL) {
352                 return NT_STATUS_NO_MEMORY;
353         }
354
355 again:
356         status = open_cached_internal_pipe_conn(domain,
357                                                 NULL,
358                                                 NULL,
359                                                 &lsa_pipe,
360                                                 &lsa_policy);
361         if (!NT_STATUS_IS_OK(status)) {
362                 goto done;
363         }
364
365         status = rpc_trusted_domains(tmp_ctx,
366                                      lsa_pipe,
367                                      &lsa_policy,
368                                      &num_trusts,
369                                      &trusts);
370
371         if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
372                 retry = true;
373                 goto again;
374         }
375
376         if (!NT_STATUS_IS_OK(status)) {
377                 goto done;
378         }
379
380         if (ptrust_list) {
381                 ptrust_list->count = num_trusts;
382                 ptrust_list->array = talloc_move(mem_ctx, &trusts);
383         }
384
385 done:
386         TALLOC_FREE(tmp_ctx);
387         return status;
388 }
389
390 /* Lookup group membership given a rid.   */
391 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
392                                     TALLOC_CTX *mem_ctx,
393                                     const struct dom_sid *group_sid,
394                                     enum lsa_SidType type,
395                                     uint32_t *pnum_names,
396                                     struct dom_sid **psid_mem,
397                                     char ***pnames,
398                                     uint32_t **pname_types)
399 {
400         struct rpc_pipe_client *samr_pipe;
401         struct policy_handle dom_pol = { 0 };
402
403         uint32_t num_names = 0;
404         struct dom_sid *sid_mem = NULL;
405         char **names = NULL;
406         uint32_t *name_types = NULL;
407
408         TALLOC_CTX *tmp_ctx;
409         NTSTATUS status;
410         bool retry = false;
411
412         DEBUG(3,("sam_lookup_groupmem\n"));
413
414         /* Paranoia check */
415         if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) {
416                 /* There's no groups, only aliases in BUILTIN */
417                 return NT_STATUS_NO_SUCH_GROUP;
418         }
419
420         if (pnum_names) {
421                 *pnum_names = 0;
422         }
423
424         tmp_ctx = talloc_stackframe();
425         if (tmp_ctx == NULL) {
426                 return NT_STATUS_NO_MEMORY;
427         }
428
429 again:
430         status = open_cached_internal_pipe_conn(domain,
431                                                 &samr_pipe,
432                                                 &dom_pol,
433                                                 NULL,
434                                                 NULL);
435         if (!NT_STATUS_IS_OK(status)) {
436                 goto done;
437         }
438
439         status = rpc_lookup_groupmem(tmp_ctx,
440                                      samr_pipe,
441                                      &dom_pol,
442                                      domain->name,
443                                      &domain->sid,
444                                      group_sid,
445                                      type,
446                                      &num_names,
447                                      &sid_mem,
448                                      &names,
449                                      &name_types);
450
451         if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
452                 retry = true;
453                 goto again;
454         }
455
456         if (pnum_names) {
457                 *pnum_names = num_names;
458         }
459
460         if (pnames) {
461                 *pnames = talloc_move(mem_ctx, &names);
462         }
463
464         if (pname_types) {
465                 *pname_types = talloc_move(mem_ctx, &name_types);
466         }
467
468         if (psid_mem) {
469                 *psid_mem = talloc_move(mem_ctx, &sid_mem);
470         }
471
472 done:
473         TALLOC_FREE(tmp_ctx);
474         return status;
475 }
476
477 /*********************************************************************
478  BUILTIN specific functions.
479 *********************************************************************/
480
481 /* List all domain groups */
482 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
483                                 TALLOC_CTX *mem_ctx,
484                                 uint32_t *num_entries,
485                                 struct wb_acct_info **info)
486 {
487         /* BUILTIN doesn't have domain groups */
488         *num_entries = 0;
489         *info = NULL;
490         return NT_STATUS_OK;
491 }
492
493 /* Query display info for a domain */
494 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
495                                 TALLOC_CTX *mem_ctx,
496                                 uint32_t **rids)
497 {
498         /* We don't have users */
499         *rids = NULL;
500         return NT_STATUS_OK;
501 }
502
503 /* get a list of trusted domains - builtin domain */
504 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
505                                         TALLOC_CTX *mem_ctx,
506                                         struct netr_DomainTrustList *trusts)
507 {
508         ZERO_STRUCTP(trusts);
509         return NT_STATUS_OK;
510 }
511
512 /*********************************************************************
513  COMMON functions.
514 *********************************************************************/
515
516 /* List all local groups (aliases) */
517 static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
518                                       TALLOC_CTX *mem_ctx,
519                                       uint32_t *pnum_info,
520                                       struct wb_acct_info **pinfo)
521 {
522         struct rpc_pipe_client *samr_pipe;
523         struct policy_handle dom_pol = { 0 };
524         struct wb_acct_info *info = NULL;
525         uint32_t num_info = 0;
526         TALLOC_CTX *tmp_ctx;
527         NTSTATUS status;
528         bool retry = false;
529
530         DEBUG(3,("samr: enum local groups\n"));
531
532         if (pnum_info) {
533                 *pnum_info = 0;
534         }
535
536         tmp_ctx = talloc_stackframe();
537         if (tmp_ctx == NULL) {
538                 return NT_STATUS_NO_MEMORY;
539         }
540
541 again:
542         status = open_cached_internal_pipe_conn(domain,
543                                                 &samr_pipe,
544                                                 &dom_pol,
545                                                 NULL,
546                                                 NULL);
547         if (!NT_STATUS_IS_OK(status)) {
548                 goto done;
549         }
550
551         status = rpc_enum_local_groups(mem_ctx,
552                                        samr_pipe,
553                                        &dom_pol,
554                                        &num_info,
555
556                                        &info);
557         if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
558                 retry = true;
559                 goto again;
560         }
561
562         if (!NT_STATUS_IS_OK(status)) {
563                 goto done;
564         }
565
566         if (pnum_info) {
567                 *pnum_info = num_info;
568         }
569
570         if (pinfo) {
571                 *pinfo = talloc_move(mem_ctx, &info);
572         }
573
574 done:
575         TALLOC_FREE(tmp_ctx);
576         return status;
577 }
578
579 /* convert a single name to a sid in a domain */
580 static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
581                                    TALLOC_CTX *mem_ctx,
582                                    const char *domain_name,
583                                    const char *name,
584                                    uint32_t flags,
585                                    const char **pdom_name,
586                                    struct dom_sid *psid,
587                                    enum lsa_SidType *ptype)
588 {
589         struct rpc_pipe_client *lsa_pipe;
590         struct policy_handle lsa_policy = { 0 };
591         struct dom_sid sid;
592         const char *dom_name;
593         enum lsa_SidType type;
594         TALLOC_CTX *tmp_ctx;
595         NTSTATUS status;
596         bool retry = false;
597
598         DEBUG(3,("sam_name_to_sid\n"));
599
600         tmp_ctx = talloc_stackframe();
601         if (tmp_ctx == NULL) {
602                 return NT_STATUS_NO_MEMORY;
603         }
604
605 again:
606         status = open_cached_internal_pipe_conn(domain,
607                                                 NULL,
608                                                 NULL,
609                                                 &lsa_pipe,
610                                                 &lsa_policy);
611         if (!NT_STATUS_IS_OK(status)) {
612                 goto done;
613         }
614
615         status = rpc_name_to_sid(tmp_ctx,
616                                  lsa_pipe,
617                                  &lsa_policy,
618                                  domain_name,
619                                  name,
620                                  flags,
621                                  &dom_name,
622                                  &sid,
623                                  &type);
624
625         if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
626                 retry = true;
627                 goto again;
628         }
629
630         if (!NT_STATUS_IS_OK(status)) {
631                 goto done;
632         }
633
634         if (pdom_name != NULL) {
635                 *pdom_name = talloc_strdup(mem_ctx, dom_name);
636                 if (*pdom_name == NULL) {
637                         status = NT_STATUS_NO_MEMORY;
638                         goto done;
639                 }
640         }
641
642         if (psid) {
643                 sid_copy(psid, &sid);
644         }
645         if (ptype) {
646                 *ptype = type;
647         }
648
649 done:
650         TALLOC_FREE(tmp_ctx);
651         return status;
652 }
653
654 /* convert a domain SID to a user or group name */
655 static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
656                                 TALLOC_CTX *mem_ctx,
657                                 const struct dom_sid *sid,
658                                 char **pdomain_name,
659                                 char **pname,
660                                 enum lsa_SidType *ptype)
661 {
662         struct rpc_pipe_client *lsa_pipe;
663         struct policy_handle lsa_policy = { 0 };
664         char *domain_name = NULL;
665         char *name = NULL;
666         enum lsa_SidType type;
667         TALLOC_CTX *tmp_ctx;
668         NTSTATUS status;
669         bool retry = false;
670
671         DEBUG(3,("sam_sid_to_name\n"));
672
673         /* Paranoia check */
674         if (!sid_check_is_in_builtin(sid) &&
675             !sid_check_is_builtin(sid) &&
676             !sid_check_is_in_our_sam(sid) &&
677             !sid_check_is_our_sam(sid) &&
678             !sid_check_is_in_unix_users(sid) &&
679             !sid_check_is_unix_users(sid) &&
680             !sid_check_is_in_unix_groups(sid) &&
681             !sid_check_is_unix_groups(sid) &&
682             !sid_check_is_in_wellknown_domain(sid)) {
683                 struct dom_sid_buf buf;
684                 DEBUG(0, ("sam_sid_to_name: possible deadlock - trying to "
685                           "lookup SID %s\n",
686                           dom_sid_str_buf(sid, &buf)));
687                 return NT_STATUS_NONE_MAPPED;
688         }
689
690         tmp_ctx = talloc_stackframe();
691         if (tmp_ctx == NULL) {
692                 return NT_STATUS_NO_MEMORY;
693         }
694
695 again:
696         status = open_cached_internal_pipe_conn(domain,
697                                                 NULL,
698                                                 NULL,
699                                                 &lsa_pipe,
700                                                 &lsa_policy);
701         if (!NT_STATUS_IS_OK(status)) {
702                 goto done;
703         }
704
705         status = rpc_sid_to_name(tmp_ctx,
706                                  lsa_pipe,
707                                  &lsa_policy,
708                                  domain,
709                                  sid,
710                                  &domain_name,
711                                  &name,
712                                  &type);
713
714         if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
715                 retry = true;
716                 goto again;
717         }
718
719         if (ptype) {
720                 *ptype = type;
721         }
722
723         if (pname) {
724                 *pname = talloc_move(mem_ctx, &name);
725         }
726
727         if (pdomain_name) {
728                 *pdomain_name = talloc_move(mem_ctx, &domain_name);
729         }
730
731 done:
732
733         TALLOC_FREE(tmp_ctx);
734         return status;
735 }
736
737 static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
738                                   TALLOC_CTX *mem_ctx,
739                                   const struct dom_sid *domain_sid,
740                                   uint32_t *rids,
741                                   size_t num_rids,
742                                   char **pdomain_name,
743                                   char ***pnames,
744                                   enum lsa_SidType **ptypes)
745 {
746         struct rpc_pipe_client *lsa_pipe;
747         struct policy_handle lsa_policy = { 0 };
748         enum lsa_SidType *types = NULL;
749         char *domain_name = NULL;
750         char **names = NULL;
751         TALLOC_CTX *tmp_ctx;
752         NTSTATUS status;
753         bool retry = false;
754
755         DEBUG(3,("sam_rids_to_names for %s\n", domain->name));
756
757         /* Paranoia check */
758         if (!sid_check_is_builtin(domain_sid) &&
759             !sid_check_is_our_sam(domain_sid) &&
760             !sid_check_is_unix_users(domain_sid) &&
761             !sid_check_is_unix_groups(domain_sid) &&
762             !sid_check_is_in_wellknown_domain(domain_sid)) {
763                 struct dom_sid_buf buf;
764                 DEBUG(0, ("sam_rids_to_names: possible deadlock - trying to "
765                           "lookup SID %s\n",
766                           dom_sid_str_buf(domain_sid, &buf)));
767                 return NT_STATUS_NONE_MAPPED;
768         }
769
770         tmp_ctx = talloc_stackframe();
771         if (tmp_ctx == NULL) {
772                 return NT_STATUS_NO_MEMORY;
773         }
774
775 again:
776         status = open_cached_internal_pipe_conn(domain,
777                                                 NULL,
778                                                 NULL,
779                                                 &lsa_pipe,
780                                                 &lsa_policy);
781         if (!NT_STATUS_IS_OK(status)) {
782                 goto done;
783         }
784
785         status = rpc_rids_to_names(tmp_ctx,
786                                    lsa_pipe,
787                                    &lsa_policy,
788                                    domain,
789                                    domain_sid,
790                                    rids,
791                                    num_rids,
792                                    &domain_name,
793                                    &names,
794                                    &types);
795
796         if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
797                 retry = true;
798                 goto again;
799         }
800
801         if (!NT_STATUS_IS_OK(status)) {
802                 goto done;
803         }
804
805         if (pdomain_name) {
806                 *pdomain_name = talloc_move(mem_ctx, &domain_name);
807         }
808
809         if (ptypes) {
810                 *ptypes = talloc_move(mem_ctx, &types);
811         }
812
813         if (pnames) {
814                 *pnames = talloc_move(mem_ctx, &names);
815         }
816
817 done:
818         TALLOC_FREE(tmp_ctx);
819         return status;
820 }
821
822 static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain,
823                                    TALLOC_CTX *mem_ctx,
824                                    struct samr_DomInfo12 *lockout_policy)
825 {
826         struct rpc_pipe_client *samr_pipe;
827         struct policy_handle dom_pol = { 0 };
828         union samr_DomainInfo *info = NULL;
829         TALLOC_CTX *tmp_ctx;
830         NTSTATUS status, result;
831         struct dcerpc_binding_handle *b = NULL;
832         bool retry = false;
833
834         DEBUG(3,("sam_lockout_policy\n"));
835
836         tmp_ctx = talloc_stackframe();
837         if (tmp_ctx == NULL) {
838                 return NT_STATUS_NO_MEMORY;
839         }
840
841 again:
842         status = open_cached_internal_pipe_conn(domain,
843                                                 &samr_pipe,
844                                                 &dom_pol,
845                                                 NULL,
846                                                 NULL);
847         if (!NT_STATUS_IS_OK(status)) {
848                 goto error;
849         }
850
851         b = samr_pipe->binding_handle;
852
853         status = dcerpc_samr_QueryDomainInfo(b,
854                                              mem_ctx,
855                                              &dom_pol,
856                                              DomainLockoutInformation,
857                                              &info,
858                                              &result);
859
860         if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
861                 retry = true;
862                 goto again;
863         }
864
865         if (!NT_STATUS_IS_OK(status)) {
866                 goto error;
867         }
868         if (!NT_STATUS_IS_OK(result)) {
869                 status = result;
870                 goto error;
871         }
872
873         *lockout_policy = info->info12;
874
875 error:
876         TALLOC_FREE(tmp_ctx);
877         return status;
878 }
879
880 static NTSTATUS sam_password_policy(struct winbindd_domain *domain,
881                                     TALLOC_CTX *mem_ctx,
882                                     struct samr_DomInfo1 *passwd_policy)
883 {
884         struct rpc_pipe_client *samr_pipe;
885         struct policy_handle dom_pol = { 0 };
886         union samr_DomainInfo *info = NULL;
887         TALLOC_CTX *tmp_ctx;
888         NTSTATUS status, result;
889         struct dcerpc_binding_handle *b = NULL;
890         bool retry = false;
891
892         DEBUG(3,("sam_password_policy\n"));
893
894         tmp_ctx = talloc_stackframe();
895         if (tmp_ctx == NULL) {
896                 return NT_STATUS_NO_MEMORY;
897         }
898
899 again:
900         status = open_cached_internal_pipe_conn(domain,
901                                                 &samr_pipe,
902                                                 &dom_pol,
903                                                 NULL,
904                                                 NULL);
905         if (!NT_STATUS_IS_OK(status)) {
906                 goto error;
907         }
908
909         b = samr_pipe->binding_handle;
910
911         status = dcerpc_samr_QueryDomainInfo(b,
912                                              mem_ctx,
913                                              &dom_pol,
914                                              DomainPasswordInformation,
915                                              &info,
916                                              &result);
917
918         if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
919                 retry = true;
920                 goto again;
921         }
922
923         if (!NT_STATUS_IS_OK(status)) {
924                 goto error;
925         }
926         if (!NT_STATUS_IS_OK(result)) {
927                 status = result;
928                 goto error;
929         }
930
931         *passwd_policy = info->info1;
932
933 error:
934         TALLOC_FREE(tmp_ctx);
935         return status;
936 }
937
938 /* Lookup groups a user is a member of. */
939 static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
940                                       TALLOC_CTX *mem_ctx,
941                                       const struct dom_sid *user_sid,
942                                       uint32_t *pnum_groups,
943                                       struct dom_sid **puser_grpsids)
944 {
945         struct rpc_pipe_client *samr_pipe;
946         struct policy_handle dom_pol;
947         struct dom_sid *user_grpsids = NULL;
948         uint32_t num_groups = 0;
949         TALLOC_CTX *tmp_ctx;
950         NTSTATUS status;
951         bool retry = false;
952
953         DEBUG(3,("sam_lookup_usergroups\n"));
954
955         ZERO_STRUCT(dom_pol);
956
957         if (pnum_groups) {
958                 *pnum_groups = 0;
959         }
960
961         tmp_ctx = talloc_stackframe();
962         if (tmp_ctx == NULL) {
963                 return NT_STATUS_NO_MEMORY;
964         }
965
966 again:
967         status = open_cached_internal_pipe_conn(domain,
968                                                 &samr_pipe,
969                                                 &dom_pol,
970                                                 NULL,
971                                                 NULL);
972         if (!NT_STATUS_IS_OK(status)) {
973                 goto done;
974         }
975
976         status = rpc_lookup_usergroups(tmp_ctx,
977                                        samr_pipe,
978                                        &dom_pol,
979                                        &domain->sid,
980                                        user_sid,
981                                        &num_groups,
982                                        &user_grpsids);
983
984         if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
985                 retry = true;
986                 goto again;
987         }
988
989         if (!NT_STATUS_IS_OK(status)) {
990                 goto done;
991         }
992
993         if (pnum_groups) {
994                 *pnum_groups = num_groups;
995         }
996
997         if (puser_grpsids) {
998                 *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
999         }
1000
1001 done:
1002
1003         TALLOC_FREE(tmp_ctx);
1004         return status;
1005 }
1006
1007 static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
1008                                        TALLOC_CTX *mem_ctx,
1009                                        uint32_t num_sids,
1010                                        const struct dom_sid *sids,
1011                                        uint32_t *pnum_aliases,
1012                                        uint32_t **palias_rids)
1013 {
1014         struct rpc_pipe_client *samr_pipe;
1015         struct policy_handle dom_pol = { 0 };
1016         uint32_t num_aliases = 0;
1017         uint32_t *alias_rids = NULL;
1018         TALLOC_CTX *tmp_ctx;
1019         NTSTATUS status;
1020         bool retry = false;
1021
1022         DEBUG(3,("sam_lookup_useraliases\n"));
1023
1024         if (pnum_aliases) {
1025                 *pnum_aliases = 0;
1026         }
1027
1028         tmp_ctx = talloc_stackframe();
1029         if (tmp_ctx == NULL) {
1030                 return NT_STATUS_NO_MEMORY;
1031         }
1032
1033 again:
1034         status = open_cached_internal_pipe_conn(domain,
1035                                                 &samr_pipe,
1036                                                 &dom_pol,
1037                                                 NULL,
1038                                                 NULL);
1039         if (!NT_STATUS_IS_OK(status)) {
1040                 goto done;
1041         }
1042
1043         status = rpc_lookup_useraliases(tmp_ctx,
1044                                         samr_pipe,
1045                                         &dom_pol,
1046                                         num_sids,
1047                                         sids,
1048                                         &num_aliases,
1049                                         &alias_rids);
1050
1051         if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1052                 retry = true;
1053                 goto again;
1054         }
1055
1056         if (!NT_STATUS_IS_OK(status)) {
1057                 goto done;
1058         }
1059
1060         if (pnum_aliases) {
1061                 *pnum_aliases = num_aliases;
1062         }
1063
1064         if (palias_rids) {
1065                 *palias_rids = talloc_move(mem_ctx, &alias_rids);
1066         }
1067
1068 done:
1069
1070         TALLOC_FREE(tmp_ctx);
1071         return status;
1072 }
1073
1074 /* find the sequence number for a domain */
1075 static NTSTATUS sam_sequence_number(struct winbindd_domain *domain,
1076                                     uint32_t *pseq)
1077 {
1078         struct rpc_pipe_client *samr_pipe;
1079         struct policy_handle dom_pol = { 0 };
1080         uint32_t seq = DOM_SEQUENCE_NONE;
1081         TALLOC_CTX *tmp_ctx;
1082         NTSTATUS status;
1083         bool retry = false;
1084
1085         DEBUG(3,("samr: sequence number\n"));
1086
1087         if (pseq) {
1088                 *pseq = DOM_SEQUENCE_NONE;
1089         }
1090
1091         tmp_ctx = talloc_stackframe();
1092         if (tmp_ctx == NULL) {
1093                 return NT_STATUS_NO_MEMORY;
1094         }
1095
1096 again:
1097         status = open_cached_internal_pipe_conn(domain,
1098                                                 &samr_pipe,
1099                                                 &dom_pol,
1100                                                 NULL,
1101                                                 NULL);
1102         if (!NT_STATUS_IS_OK(status)) {
1103                 goto done;
1104         }
1105
1106         status = rpc_sequence_number(tmp_ctx,
1107                                      samr_pipe,
1108                                      &dom_pol,
1109                                      domain->name,
1110                                      &seq);
1111
1112         if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1113                 retry = true;
1114                 goto again;
1115         }
1116
1117         if (!NT_STATUS_IS_OK(status)) {
1118                 goto done;
1119         }
1120
1121         if (pseq) {
1122                 *pseq = seq;
1123         }
1124
1125 done:
1126         TALLOC_FREE(tmp_ctx);
1127         return status;
1128 }
1129
1130 /* the rpc backend methods are exposed via this structure */
1131 struct winbindd_methods builtin_passdb_methods = {
1132         .consistent            = false,
1133
1134         .query_user_list       = builtin_query_user_list,
1135         .enum_dom_groups       = builtin_enum_dom_groups,
1136         .enum_local_groups     = sam_enum_local_groups,
1137         .name_to_sid           = sam_name_to_sid,
1138         .sid_to_name           = sam_sid_to_name,
1139         .rids_to_names         = sam_rids_to_names,
1140         .lookup_usergroups     = sam_lookup_usergroups,
1141         .lookup_useraliases    = sam_lookup_useraliases,
1142         .lookup_groupmem       = sam_lookup_groupmem,
1143         .sequence_number       = sam_sequence_number,
1144         .lockout_policy        = sam_lockout_policy,
1145         .password_policy       = sam_password_policy,
1146         .trusted_domains       = builtin_trusted_domains
1147 };
1148
1149 /* the rpc backend methods are exposed via this structure */
1150 struct winbindd_methods sam_passdb_methods = {
1151         .consistent            = false,
1152
1153         .query_user_list       = sam_query_user_list,
1154         .enum_dom_groups       = sam_enum_dom_groups,
1155         .enum_local_groups     = sam_enum_local_groups,
1156         .name_to_sid           = sam_name_to_sid,
1157         .sid_to_name           = sam_sid_to_name,
1158         .rids_to_names         = sam_rids_to_names,
1159         .lookup_usergroups     = sam_lookup_usergroups,
1160         .lookup_useraliases    = sam_lookup_useraliases,
1161         .lookup_groupmem       = sam_lookup_groupmem,
1162         .sequence_number       = sam_sequence_number,
1163         .lockout_policy        = sam_lockout_policy,
1164         .password_policy       = sam_password_policy,
1165         .trusted_domains       = sam_trusted_domains
1166 };