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