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