s3: Rename server_messaging_context() to global_messaging_context()
[metze/samba-autobuild/.git] / source3 / winbindd / winbindd_rpc.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 "rpc_client/rpc_client.h"
30 #include "librpc/gen_ndr/ndr_samr_c.h"
31 #include "librpc/gen_ndr/ndr_lsa_c.h"
32 #include "rpc_client/cli_samr.h"
33 #include "rpc_client/cli_lsarpc.h"
34 #include "../libcli/security/security.h"
35 #include "lsa.h"
36
37 /* Query display info for a domain */
38 NTSTATUS rpc_query_user_list(TALLOC_CTX *mem_ctx,
39                              struct rpc_pipe_client *samr_pipe,
40                              struct policy_handle *samr_policy,
41                              const struct dom_sid *domain_sid,
42                              uint32_t **prids)
43 {
44         struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
45         uint32_t *rids = NULL;
46         uint32_t num_rids = 0;
47         uint32_t i = 0;
48         uint32_t resume_handle = 0;
49         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
50         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
51         TALLOC_CTX *tmp_ctx;
52
53         *prids = NULL;
54
55         tmp_ctx = talloc_stackframe();
56         if (tmp_ctx == NULL) {
57                 return NT_STATUS_NO_MEMORY;
58         }
59
60         do {
61                 struct samr_SamArray *sam_array = NULL;
62                 uint32_t count = 0;
63                 uint32_t *tmp;
64
65                 status = dcerpc_samr_EnumDomainUsers(
66                         b, tmp_ctx, samr_policy, &resume_handle,
67                         ACB_NORMAL, &sam_array, 0xffff, &count, &result);
68                 if (!NT_STATUS_IS_OK(status)) {
69                         goto done;
70                 }
71                 if (!NT_STATUS_IS_OK(result)) {
72                         if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
73                                 DBG_WARNING("EnumDomainUsers failed: %s\n",
74                                             nt_errstr(result));
75                                 status = result;
76                                 goto done;
77                         }
78                 }
79
80                 if (num_rids + count < num_rids) {
81                         status = NT_STATUS_INTEGER_OVERFLOW;
82                         goto done;
83                 }
84
85                 tmp = talloc_realloc(tmp_ctx, rids, uint32_t, num_rids+count);
86                 if (tmp == NULL) {
87                         status = NT_STATUS_NO_MEMORY;
88                         goto done;
89                 }
90                 rids = tmp;
91
92                 for (i=0; i<count; i++) {
93                         rids[num_rids++] = sam_array->entries[i].idx;
94                 }
95
96                 TALLOC_FREE(sam_array);
97         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
98
99         *prids = talloc_steal(mem_ctx, rids);
100         status = NT_STATUS_OK;
101
102 done:
103         TALLOC_FREE(tmp_ctx);
104         return status;
105 }
106
107 /* List all domain groups */
108 NTSTATUS rpc_enum_dom_groups(TALLOC_CTX *mem_ctx,
109                              struct rpc_pipe_client *samr_pipe,
110                              struct policy_handle *samr_policy,
111                              uint32_t *pnum_info,
112                              struct wb_acct_info **pinfo)
113 {
114         struct wb_acct_info *info = NULL;
115         uint32_t start = 0;
116         uint32_t num_info = 0;
117         NTSTATUS status, result;
118         struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
119
120         *pnum_info = 0;
121
122         do {
123                 struct samr_SamArray *sam_array = NULL;
124                 uint32_t count = 0;
125                 uint32_t g;
126
127                 /* start is updated by this call. */
128                 status = dcerpc_samr_EnumDomainGroups(b,
129                                                       mem_ctx,
130                                                       samr_policy,
131                                                       &start,
132                                                       &sam_array,
133                                                       0xFFFF, /* buffer size? */
134                                                       &count,
135                                                       &result);
136                 if (!NT_STATUS_IS_OK(status)) {
137                         return status;
138                 }
139                 if (!NT_STATUS_IS_OK(result)) {
140                         if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
141                                 DEBUG(2,("query_user_list: failed to enum domain groups: %s\n",
142                                          nt_errstr(result)));
143                                 return result;
144                         }
145                 }
146
147                 info = talloc_realloc(mem_ctx,
148                                             info,
149                                             struct wb_acct_info,
150                                             num_info + count);
151                 if (info == NULL) {
152                         return NT_STATUS_NO_MEMORY;
153                 }
154
155                 for (g = 0; g < count; g++) {
156                         struct wb_acct_info *i = &info[num_info + g];
157
158                         fstrcpy(i->acct_name,
159                                 sam_array->entries[g].name.string);
160                         fstrcpy(i->acct_desc, "");
161                         i->rid = sam_array->entries[g].idx;
162                 }
163
164                 num_info += count;
165         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
166
167         *pnum_info = num_info;
168         *pinfo = info;
169
170         return NT_STATUS_OK;
171 }
172
173 NTSTATUS rpc_enum_local_groups(TALLOC_CTX *mem_ctx,
174                                struct rpc_pipe_client *samr_pipe,
175                                struct policy_handle *samr_policy,
176                                uint32_t *pnum_info,
177                                struct wb_acct_info **pinfo)
178 {
179         struct wb_acct_info *info = NULL;
180         uint32_t num_info = 0;
181         NTSTATUS status, result;
182         struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
183
184         *pnum_info = 0;
185
186         do {
187                 struct samr_SamArray *sam_array = NULL;
188                 uint32_t count = 0;
189                 uint32_t start = num_info;
190                 uint32_t g;
191
192                 status = dcerpc_samr_EnumDomainAliases(b,
193                                                        mem_ctx,
194                                                        samr_policy,
195                                                        &start,
196                                                        &sam_array,
197                                                        0xFFFF, /* buffer size? */
198                                                        &count,
199                                                        &result);
200                 if (!NT_STATUS_IS_OK(status)) {
201                         return status;
202                 }
203                 if (!NT_STATUS_IS_OK(result)) {
204                         if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
205                                 return result;
206                         }
207                 }
208
209                 info = talloc_realloc(mem_ctx,
210                                             info,
211                                             struct wb_acct_info,
212                                             num_info + count);
213                 if (info == NULL) {
214                         return  NT_STATUS_NO_MEMORY;
215                 }
216
217                 for (g = 0; g < count; g++) {
218                         struct wb_acct_info *i = &info[num_info + g];
219
220                         fstrcpy(i->acct_name,
221                                 sam_array->entries[g].name.string);
222                         fstrcpy(i->acct_desc, "");
223                         i->rid = sam_array->entries[g].idx;
224                 }
225
226                 num_info += count;
227         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
228
229         *pnum_info = num_info;
230         *pinfo = info;
231
232         return NT_STATUS_OK;
233 }
234
235 /* convert a single name to a sid in a domain */
236 NTSTATUS rpc_name_to_sid(TALLOC_CTX *mem_ctx,
237                          struct rpc_pipe_client *lsa_pipe,
238                          struct policy_handle *lsa_policy,
239                          const char *domain_name,
240                          const char *name,
241                          uint32_t flags,
242                          struct dom_sid *sid,
243                          enum lsa_SidType *type)
244 {
245         enum lsa_SidType *types = NULL;
246         struct dom_sid *sids = NULL;
247         char *full_name = NULL;
248         const char *names[1];
249         char *mapped_name = NULL;
250         NTSTATUS status;
251
252         if (name == NULL || name[0] == '\0') {
253                 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
254         } else if (domain_name == NULL || domain_name[0] == '\0') {
255                 full_name = talloc_asprintf(mem_ctx, "%s", name);
256         } else {
257                 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
258         }
259
260         if (full_name == NULL) {
261                 return NT_STATUS_NO_MEMORY;
262         }
263
264         status = normalize_name_unmap(mem_ctx, full_name, &mapped_name);
265         /* Reset the full_name pointer if we mapped anything */
266         if (NT_STATUS_IS_OK(status) ||
267             NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
268                 full_name = mapped_name;
269         }
270
271         DEBUG(3,("name_to_sid: %s for domain %s\n",
272                  full_name ? full_name : "", domain_name ));
273
274         names[0] = full_name;
275
276         /*
277          * We don't run into deadlocks here, cause winbind_off() is
278          * called in the main function.
279          */
280         status = rpccli_lsa_lookup_names(lsa_pipe,
281                                          mem_ctx,
282                                          lsa_policy,
283                                          1, /* num_names */
284                                          names,
285                                          NULL, /* domains */
286                                          1, /* level */
287                                          &sids,
288                                          &types);
289         if (!NT_STATUS_IS_OK(status)) {
290                 DEBUG(2,("name_to_sid: failed to lookup name: %s\n",
291                         nt_errstr(status)));
292                 return status;
293         }
294
295         sid_copy(sid, &sids[0]);
296         *type = types[0];
297
298         return NT_STATUS_OK;
299 }
300
301 /* Convert a domain SID to a user or group name */
302 NTSTATUS rpc_sid_to_name(TALLOC_CTX *mem_ctx,
303                          struct rpc_pipe_client *lsa_pipe,
304                          struct policy_handle *lsa_policy,
305                          struct winbindd_domain *domain,
306                          const struct dom_sid *sid,
307                          char **pdomain_name,
308                          char **pname,
309                          enum lsa_SidType *ptype)
310 {
311         char *mapped_name = NULL;
312         char **domains = NULL;
313         char **names = NULL;
314         enum lsa_SidType *types = NULL;
315         NTSTATUS map_status;
316         NTSTATUS status;
317
318         status = rpccli_lsa_lookup_sids(lsa_pipe,
319                                         mem_ctx,
320                                         lsa_policy,
321                                         1, /* num_sids */
322                                         sid,
323                                         &domains,
324                                         &names,
325                                         &types);
326         if (!NT_STATUS_IS_OK(status)) {
327                 DEBUG(2,("sid_to_name: failed to lookup sids: %s\n",
328                         nt_errstr(status)));
329                 return status;
330         }
331
332         *ptype = (enum lsa_SidType) types[0];
333
334         map_status = normalize_name_map(mem_ctx,
335                                         domain->name,
336                                         names[0],
337                                         &mapped_name);
338         if (NT_STATUS_IS_OK(map_status) ||
339             NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
340                 *pname = talloc_strdup(mem_ctx, mapped_name);
341                 DEBUG(5,("returning mapped name -- %s\n", *pname));
342         } else {
343                 *pname = talloc_strdup(mem_ctx, names[0]);
344         }
345         if ((names[0] != NULL) && (*pname == NULL)) {
346                 return NT_STATUS_NO_MEMORY;
347         }
348
349         *pdomain_name = talloc_strdup(mem_ctx, domains[0]);
350         if (*pdomain_name == NULL) {
351                 return NT_STATUS_NO_MEMORY;
352         }
353
354         return NT_STATUS_OK;
355 }
356
357 /* Convert a bunch of rids to user or group names */
358 NTSTATUS rpc_rids_to_names(TALLOC_CTX *mem_ctx,
359                            struct rpc_pipe_client *lsa_pipe,
360                            struct policy_handle *lsa_policy,
361                            struct winbindd_domain *domain,
362                            const struct dom_sid *sid,
363                            uint32_t *rids,
364                            size_t num_rids,
365                            char **pdomain_name,
366                            char ***pnames,
367                            enum lsa_SidType **ptypes)
368 {
369         enum lsa_SidType *types = NULL;
370         char *domain_name = NULL;
371         char **domains = NULL;
372         char **names = NULL;
373         struct dom_sid *sids;
374         size_t i;
375         NTSTATUS status;
376
377         if (num_rids > 0) {
378                 sids = talloc_array(mem_ctx, struct dom_sid, num_rids);
379                 if (sids == NULL) {
380                         return NT_STATUS_NO_MEMORY;
381                 }
382         } else {
383                 sids = NULL;
384         }
385
386         for (i = 0; i < num_rids; i++) {
387                 if (!sid_compose(&sids[i], sid, rids[i])) {
388                         return NT_STATUS_INTERNAL_ERROR;
389                 }
390         }
391
392         status = rpccli_lsa_lookup_sids(lsa_pipe,
393                                         mem_ctx,
394                                         lsa_policy,
395                                         num_rids,
396                                         sids,
397                                         &domains,
398                                         &names,
399                                         &types);
400         if (!NT_STATUS_IS_OK(status) &&
401             !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
402                 DEBUG(2,("rids_to_names: failed to lookup sids: %s\n",
403                         nt_errstr(status)));
404                 return status;
405         }
406
407         for (i = 0; i < num_rids; i++) {
408                 char *mapped_name = NULL;
409                 NTSTATUS map_status;
410
411                 if (types[i] != SID_NAME_UNKNOWN) {
412                         map_status = normalize_name_map(mem_ctx,
413                                                         domain->name,
414                                                         names[i],
415                                                         &mapped_name);
416                         if (NT_STATUS_IS_OK(map_status) ||
417                             NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
418                                 TALLOC_FREE(names[i]);
419                                 names[i] = talloc_strdup(names, mapped_name);
420                                 if (names[i] == NULL) {
421                                         return NT_STATUS_NO_MEMORY;
422                                 }
423                         }
424
425                         domain_name = domains[i];
426                 }
427         }
428
429         *pdomain_name = domain_name;
430         *ptypes = types;
431         *pnames = names;
432
433         return NT_STATUS_OK;
434 }
435
436 /* Lookup groups a user is a member of. */
437 NTSTATUS rpc_lookup_usergroups(TALLOC_CTX *mem_ctx,
438                                struct rpc_pipe_client *samr_pipe,
439                                struct policy_handle *samr_policy,
440                                const struct dom_sid *domain_sid,
441                                const struct dom_sid *user_sid,
442                                uint32_t *pnum_groups,
443                                struct dom_sid **puser_grpsids)
444 {
445         struct policy_handle user_policy;
446         struct samr_RidWithAttributeArray *rid_array = NULL;
447         struct dom_sid *user_grpsids = NULL;
448         uint32_t num_groups = 0, i;
449         uint32_t user_rid;
450         NTSTATUS status, result;
451         struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
452
453         if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
454                 return NT_STATUS_UNSUCCESSFUL;
455         }
456
457         /* Get user handle */
458         status = dcerpc_samr_OpenUser(b,
459                                       mem_ctx,
460                                       samr_policy,
461                                       SEC_FLAG_MAXIMUM_ALLOWED,
462                                       user_rid,
463                                       &user_policy,
464                                       &result);
465         if (!NT_STATUS_IS_OK(status)) {
466                 return status;
467         }
468         if (!NT_STATUS_IS_OK(result)) {
469                 return result;
470         }
471
472         /* Query user rids */
473         status = dcerpc_samr_GetGroupsForUser(b,
474                                               mem_ctx,
475                                               &user_policy,
476                                               &rid_array,
477                                               &result);
478         {
479                 NTSTATUS _result;
480                 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
481         }
482
483         if (!NT_STATUS_IS_OK(status)) {
484                 return status;
485         }
486         if (!NT_STATUS_IS_OK(result)) {
487                 return result;
488         }
489
490         num_groups = rid_array->count;
491
492         user_grpsids = talloc_array(mem_ctx, struct dom_sid, num_groups);
493         if (user_grpsids == NULL) {
494                 status = NT_STATUS_NO_MEMORY;
495                 return status;
496         }
497
498         for (i = 0; i < num_groups; i++) {
499                 sid_compose(&(user_grpsids[i]), domain_sid,
500                             rid_array->rids[i].rid);
501         }
502
503         *pnum_groups = num_groups;
504
505         *puser_grpsids = user_grpsids;
506
507         return NT_STATUS_OK;
508 }
509
510 NTSTATUS rpc_lookup_useraliases(TALLOC_CTX *mem_ctx,
511                                 struct rpc_pipe_client *samr_pipe,
512                                 struct policy_handle *samr_policy,
513                                 uint32_t num_sids,
514                                 const struct dom_sid *sids,
515                                 uint32_t *pnum_aliases,
516                                 uint32_t **palias_rids)
517 {
518 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
519         uint32_t num_query_sids = 0;
520         uint32_t num_queries = 1;
521         uint32_t num_aliases = 0;
522         uint32_t total_sids = 0;
523         uint32_t *alias_rids = NULL;
524         uint32_t rangesize = MAX_SAM_ENTRIES_W2K;
525         uint32_t i;
526         struct samr_Ids alias_rids_query;
527         NTSTATUS status, result;
528         struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
529
530         do {
531                 /* prepare query */
532                 struct lsa_SidArray sid_array;
533
534                 ZERO_STRUCT(sid_array);
535
536                 num_query_sids = MIN(num_sids - total_sids, rangesize);
537
538                 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
539                         num_queries, num_query_sids));
540
541                 if (num_query_sids) {
542                         sid_array.sids = talloc_zero_array(mem_ctx, struct lsa_SidPtr, num_query_sids);
543                         if (sid_array.sids == NULL) {
544                                 return NT_STATUS_NO_MEMORY;
545                         }
546                 } else {
547                         sid_array.sids = NULL;
548                 }
549
550                 for (i = 0; i < num_query_sids; i++) {
551                         sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[total_sids++]);
552                         if (sid_array.sids[i].sid == NULL) {
553                                 return NT_STATUS_NO_MEMORY;
554                         }
555                 }
556                 sid_array.num_sids = num_query_sids;
557
558                 /* do request */
559                 status = dcerpc_samr_GetAliasMembership(b,
560                                                         mem_ctx,
561                                                         samr_policy,
562                                                         &sid_array,
563                                                         &alias_rids_query,
564                                                         &result);
565                 if (!NT_STATUS_IS_OK(status)) {
566                         return status;
567                 }
568                 if (!NT_STATUS_IS_OK(result)) {
569                         return result;
570                 }
571
572                 /* process output */
573                 for (i = 0; i < alias_rids_query.count; i++) {
574                         size_t na = num_aliases;
575
576                         if (!add_rid_to_array_unique(mem_ctx,
577                                                      alias_rids_query.ids[i],
578                                                      &alias_rids,
579                                                      &na)) {
580                                         return NT_STATUS_NO_MEMORY;
581                                 }
582                                 num_aliases = na;
583                 }
584
585                 num_queries++;
586
587         } while (total_sids < num_sids);
588
589         DEBUG(10,("rpc: rpc_lookup_useraliases: got %d aliases in %d queries "
590                   "(rangesize: %d)\n", num_aliases, num_queries, rangesize));
591
592         *pnum_aliases = num_aliases;
593         *palias_rids = alias_rids;
594
595         return NT_STATUS_OK;
596 #undef MAX_SAM_ENTRIES_W2K
597 }
598
599 /* Lookup group membership given a rid.   */
600 NTSTATUS rpc_lookup_groupmem(TALLOC_CTX *mem_ctx,
601                              struct rpc_pipe_client *samr_pipe,
602                              struct policy_handle *samr_policy,
603                              const char *domain_name,
604                              const struct dom_sid *domain_sid,
605                              const struct dom_sid *group_sid,
606                              enum lsa_SidType type,
607                              uint32_t *pnum_names,
608                              struct dom_sid **psid_mem,
609                              char ***pnames,
610                              uint32_t **pname_types)
611 {
612         struct policy_handle group_policy;
613         uint32_t group_rid;
614         uint32_t *rid_mem = NULL;
615
616         uint32_t num_names = 0;
617         uint32_t total_names = 0;
618         struct dom_sid *sid_mem = NULL;
619         char **names = NULL;
620         uint32_t *name_types = NULL;
621
622         struct lsa_Strings tmp_names;
623         struct samr_Ids tmp_types;
624
625         uint32_t j, r;
626         NTSTATUS status, result;
627         struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
628
629         if (!sid_peek_check_rid(domain_sid, group_sid, &group_rid)) {
630                 return NT_STATUS_UNSUCCESSFUL;
631         }
632
633         switch(type) {
634         case SID_NAME_DOM_GRP:
635         {
636                 struct samr_RidAttrArray *rids = NULL;
637
638                 status = dcerpc_samr_OpenGroup(b,
639                                                mem_ctx,
640                                                samr_policy,
641                                                SEC_FLAG_MAXIMUM_ALLOWED,
642                                                group_rid,
643                                                &group_policy,
644                                                &result);
645                 if (!NT_STATUS_IS_OK(status)) {
646                         return status;
647                 }
648                 if (!NT_STATUS_IS_OK(result)) {
649                         return result;
650                 }
651
652                 /*
653                  * Step #1: Get a list of user rids that are the members of the group.
654                  */
655                 status = dcerpc_samr_QueryGroupMember(b,
656                                                       mem_ctx,
657                                                       &group_policy,
658                                                       &rids,
659                                                       &result);
660                 {
661                         NTSTATUS _result;
662                         dcerpc_samr_Close(b, mem_ctx, &group_policy, &_result);
663                 }
664
665                 if (!NT_STATUS_IS_OK(status)) {
666                         return status;
667                 }
668                 if (!NT_STATUS_IS_OK(result)) {
669                         return result;
670                 }
671
672
673                 if (rids == NULL || rids->count == 0) {
674                         pnum_names = 0;
675                         pnames = NULL;
676                         pname_types = NULL;
677                         psid_mem = NULL;
678
679                         return NT_STATUS_OK;
680                 }
681
682                 num_names = rids->count;
683                 rid_mem = rids->rids;
684
685                 break;
686         }
687         case SID_NAME_WKN_GRP:
688         case SID_NAME_ALIAS:
689         {
690                 struct lsa_SidArray sid_array;
691                 struct lsa_SidPtr sid_ptr;
692                 struct samr_Ids rids_query;
693
694                 sid_ptr.sid = dom_sid_dup(mem_ctx, group_sid);
695                 if (sid_ptr.sid == NULL) {
696                         return NT_STATUS_NO_MEMORY;
697                 }
698
699                 sid_array.num_sids = 1;
700                 sid_array.sids = &sid_ptr;
701
702                 status = dcerpc_samr_GetAliasMembership(b,
703                                                         mem_ctx,
704                                                         samr_policy,
705                                                         &sid_array,
706                                                         &rids_query,
707                                                         &result);
708                 if (!NT_STATUS_IS_OK(status)) {
709                         return status;
710                 }
711                 if (!NT_STATUS_IS_OK(result)) {
712                         return result;
713                 }
714
715                 if (rids_query.count == 0) {
716                         pnum_names = 0;
717                         pnames = NULL;
718                         pname_types = NULL;
719                         psid_mem = NULL;
720
721                         return NT_STATUS_OK;
722                 }
723
724                 num_names = rids_query.count;
725                 rid_mem = rids_query.ids;
726
727                 break;
728         }
729         default:
730                 return NT_STATUS_UNSUCCESSFUL;
731         }
732
733         /*
734          * Step #2: Convert list of rids into list of usernames.
735          */
736         if (num_names > 0) {
737                 names = talloc_zero_array(mem_ctx, char *, num_names);
738                 name_types = talloc_zero_array(mem_ctx, uint32_t, num_names);
739                 sid_mem = talloc_zero_array(mem_ctx, struct dom_sid, num_names);
740                 if (names == NULL || name_types == NULL || sid_mem == NULL) {
741                         return NT_STATUS_NO_MEMORY;
742                 }
743         }
744
745         for (j = 0; j < num_names; j++) {
746                 sid_compose(&sid_mem[j], domain_sid, rid_mem[j]);
747         }
748
749         status = dcerpc_samr_LookupRids(b,
750                                         mem_ctx,
751                                         samr_policy,
752                                         num_names,
753                                         rid_mem,
754                                         &tmp_names,
755                                         &tmp_types,
756                                         &result);
757         if (!NT_STATUS_IS_OK(status)) {
758                 return status;
759         }
760
761         if (!NT_STATUS_IS_OK(result)) {
762                 if (!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
763                         return result;
764                 }
765         }
766
767         /* Copy result into array.  The talloc system will take
768            care of freeing the temporary arrays later on. */
769         if (tmp_names.count != num_names) {
770                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
771         }
772         if (tmp_types.count != num_names) {
773                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
774         }
775
776         for (r = 0; r < tmp_names.count; r++) {
777                 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
778                         continue;
779                 }
780                 if (total_names >= num_names) {
781                         break;
782                 }
783                 names[total_names] = fill_domain_username_talloc(names,
784                                                                  domain_name,
785                                                                  tmp_names.names[r].string,
786                                                                  true);
787                 if (names[total_names] == NULL) {
788                         return NT_STATUS_NO_MEMORY;
789                 }
790                 name_types[total_names] = tmp_types.ids[r];
791                 total_names++;
792         }
793
794         *pnum_names = total_names;
795         *pnames = names;
796         *pname_types = name_types;
797         *psid_mem = sid_mem;
798
799         return NT_STATUS_OK;
800 }
801
802 /* Find the sequence number for a domain */
803 NTSTATUS rpc_sequence_number(TALLOC_CTX *mem_ctx,
804                              struct rpc_pipe_client *samr_pipe,
805                              struct policy_handle *samr_policy,
806                              const char *domain_name,
807                              uint32_t *pseq)
808 {
809         union samr_DomainInfo *info = NULL;
810         bool got_seq_num = false;
811         NTSTATUS status, result;
812         struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
813
814         /* query domain info */
815         status = dcerpc_samr_QueryDomainInfo(b,
816                                              mem_ctx,
817                                              samr_policy,
818                                              8,
819                                              &info,
820                                              &result);
821         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
822                 *pseq = info->info8.sequence_num;
823                 got_seq_num = true;
824                 goto seq_num;
825         }
826
827         /* retry with info-level 2 in case the dc does not support info-level 8
828          * (like all older samba2 and samba3 dc's) - Guenther */
829         status = dcerpc_samr_QueryDomainInfo(b,
830                                              mem_ctx,
831                                              samr_policy,
832                                              2,
833                                              &info,
834                                              &result);
835         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
836                 *pseq = info->general.sequence_num;
837                 got_seq_num = true;
838                 goto seq_num;
839         }
840
841         if (!NT_STATUS_IS_OK(status)) {
842                 goto seq_num;
843         }
844
845         status = result;
846
847 seq_num:
848         if (got_seq_num) {
849                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
850                           domain_name, (unsigned) *pseq));
851         } else {
852                 DEBUG(10,("domain_sequence_number: failed to get sequence "
853                           "number (%u) for domain %s\n",
854                           (unsigned) *pseq, domain_name ));
855                 status = NT_STATUS_OK;
856         }
857
858         return status;
859 }
860
861 /* Get a list of trusted domains */
862 NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
863                              struct rpc_pipe_client *lsa_pipe,
864                              struct policy_handle *lsa_policy,
865                              uint32_t *pnum_trusts,
866                              struct netr_DomainTrust **ptrusts)
867 {
868         struct netr_DomainTrust *array = NULL;
869         uint32_t enum_ctx = 0;
870         uint32_t count = 0;
871         NTSTATUS status, result;
872         struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
873
874         do {
875                 struct lsa_DomainList dom_list;
876                 struct lsa_DomainListEx dom_list_ex;
877                 bool has_ex = false;
878                 uint32_t i;
879
880                 /*
881                  * We don't run into deadlocks here, cause winbind_off() is
882                  * called in the main function.
883                  */
884                 status = dcerpc_lsa_EnumTrustedDomainsEx(b,
885                                                          mem_ctx,
886                                                          lsa_policy,
887                                                          &enum_ctx,
888                                                          &dom_list_ex,
889                                                          (uint32_t) -1,
890                                                          &result);
891                 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_ERR(result) &&
892                     dom_list_ex.count > 0) {
893                         count += dom_list_ex.count;
894                         has_ex = true;
895                 } else {
896                         status = dcerpc_lsa_EnumTrustDom(b,
897                                                          mem_ctx,
898                                                          lsa_policy,
899                                                          &enum_ctx,
900                                                          &dom_list,
901                                                          (uint32_t) -1,
902                                                          &result);
903                         if (!NT_STATUS_IS_OK(status)) {
904                                 return status;
905                         }
906                         if (!NT_STATUS_IS_OK(result)) {
907                                 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
908                                         return result;
909                                 }
910                         }
911
912                         count += dom_list.count;
913                 }
914
915                 array = talloc_realloc(mem_ctx,
916                                        array,
917                                        struct netr_DomainTrust,
918                                        count);
919                 if (array == NULL) {
920                         return NT_STATUS_NO_MEMORY;
921                 }
922
923                 for (i = 0; i < count; i++) {
924                         struct netr_DomainTrust *trust = &array[i];
925                         struct dom_sid *sid;
926
927                         ZERO_STRUCTP(trust);
928
929                         sid = talloc(array, struct dom_sid);
930                         if (sid == NULL) {
931                                 return NT_STATUS_NO_MEMORY;
932                         }
933
934                         if (has_ex) {
935                                 trust->netbios_name = talloc_move(array,
936                                                                   &dom_list_ex.domains[i].netbios_name.string);
937                                 trust->dns_name = talloc_move(array,
938                                                               &dom_list_ex.domains[i].domain_name.string);
939                                 if (dom_list_ex.domains[i].sid == NULL) {
940                                         DEBUG(0, ("Trusted Domain %s has no SID, aborting!\n", trust->dns_name));
941                                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
942                                 }
943                                 sid_copy(sid, dom_list_ex.domains[i].sid);
944                         } else {
945                                 trust->netbios_name = talloc_move(array,
946                                                                   &dom_list.domains[i].name.string);
947                                 trust->dns_name = NULL;
948
949                                 if (dom_list.domains[i].sid == NULL) {
950                                         DEBUG(0, ("Trusted Domain %s has no SID, aborting!\n", trust->netbios_name));
951                                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
952                                 }
953
954                                 sid_copy(sid, dom_list.domains[i].sid);
955                         }
956
957                         trust->sid = sid;
958                 }
959         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
960
961         *pnum_trusts = count;
962         *ptrusts = array;
963
964         return NT_STATUS_OK;
965 }
966
967 static NTSTATUS rpc_try_lookup_sids3(TALLOC_CTX *mem_ctx,
968                                      struct winbindd_domain *domain,
969                                      struct rpc_pipe_client *cli,
970                                      struct lsa_SidArray *sids,
971                                      struct lsa_RefDomainList **pdomains,
972                                      struct lsa_TransNameArray **pnames)
973 {
974         struct lsa_TransNameArray2 lsa_names2;
975         struct lsa_TransNameArray *names = *pnames;
976         uint32_t i, count = 0;
977         NTSTATUS status, result;
978
979         ZERO_STRUCT(lsa_names2);
980         status = dcerpc_lsa_LookupSids3(cli->binding_handle,
981                                         mem_ctx,
982                                         sids,
983                                         pdomains,
984                                         &lsa_names2,
985                                         LSA_LOOKUP_NAMES_ALL,
986                                         &count,
987                                         LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
988                                         LSA_CLIENT_REVISION_2,
989                                         &result);
990         if (!NT_STATUS_IS_OK(status)) {
991                 return status;
992         }
993         if (NT_STATUS_LOOKUP_ERR(result)) {
994                 return result;
995         }
996         if (sids->num_sids != lsa_names2.count) {
997                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
998         }
999
1000         names->count = lsa_names2.count;
1001         names->names = talloc_array(names, struct lsa_TranslatedName,
1002                                     names->count);
1003         if (names->names == NULL) {
1004                 return NT_STATUS_NO_MEMORY;
1005         }
1006         for (i=0; i<names->count; i++) {
1007                 names->names[i].sid_type = lsa_names2.names[i].sid_type;
1008                 names->names[i].name.string = talloc_move(
1009                         names->names, &lsa_names2.names[i].name.string);
1010                 names->names[i].sid_index = lsa_names2.names[i].sid_index;
1011
1012                 if (names->names[i].sid_index == UINT32_MAX) {
1013                         continue;
1014                 }
1015                 if ((*pdomains) == NULL) {
1016                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
1017                 }
1018                 if (names->names[i].sid_index >= (*pdomains)->count) {
1019                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
1020                 }
1021         }
1022         return NT_STATUS_OK;
1023 }
1024
1025 NTSTATUS rpc_lookup_sids(TALLOC_CTX *mem_ctx,
1026                          struct winbindd_domain *domain,
1027                          struct lsa_SidArray *sids,
1028                          struct lsa_RefDomainList **pdomains,
1029                          struct lsa_TransNameArray **pnames)
1030 {
1031         struct lsa_TransNameArray *names = *pnames;
1032         struct rpc_pipe_client *cli = NULL;
1033         struct policy_handle lsa_policy;
1034         uint32_t count;
1035         uint32_t i;
1036         NTSTATUS status, result;
1037
1038         status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
1039         if (!NT_STATUS_IS_OK(status)) {
1040                 return status;
1041         }
1042
1043         if (cli->transport->transport == NCACN_IP_TCP) {
1044                 return rpc_try_lookup_sids3(mem_ctx, domain, cli, sids,
1045                                             pdomains, pnames);
1046         }
1047
1048         status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
1049                                        &lsa_policy, sids, pdomains,
1050                                        names, LSA_LOOKUP_NAMES_ALL,
1051                                        &count, &result);
1052         if (!NT_STATUS_IS_OK(status)) {
1053                 return status;
1054         }
1055         if (NT_STATUS_LOOKUP_ERR(result)) {
1056                 return result;
1057         }
1058
1059         if (sids->num_sids != names->count) {
1060                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1061         }
1062
1063         for (i=0; i < names->count; i++) {
1064                 if (names->names[i].sid_index == UINT32_MAX) {
1065                         continue;
1066                 }
1067                 if ((*pdomains) == NULL) {
1068                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
1069                 }
1070                 if (names->names[i].sid_index >= (*pdomains)->count) {
1071                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
1072                 }
1073         }
1074
1075         return NT_STATUS_OK;
1076 }