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