gensec: Cast data for MIT Kerberos correctly
[Samba.git] / source3 / winbindd / winbindd_rpc.c
blobfcc636620a48a2a8f7aad5199a60117b65b72da2
1 /*
2 * Unix SMB/CIFS implementation.
4 * Winbind rpc backend functions
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>
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.
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.
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/>.
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"
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)
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;
51 *prids = NULL;
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;
60 dcerpc_get_query_dispinfo_params(loop_count,
61 &max_entries,
62 &max_size);
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;
78 if (!NT_STATUS_IS_OK(result)) {
79 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
80 TALLOC_FREE(rids);
81 return result;
85 /* increment required start query values */
86 start_idx += disp_info.info1.count;
87 loop_count++;
88 num_dom_users = disp_info.info1.count;
90 num_rids += num_dom_users;
91 /* If there are no user to enumerate we're done */
92 if (num_rids == 0) {
93 return NT_STATUS_OK;
96 rids = talloc_realloc(mem_ctx, rids, uint32_t, num_rids);
97 if (rids == NULL) {
98 return NT_STATUS_NO_MEMORY;
101 for (j = 0; j < num_dom_users; j++) {
102 rids[i++] = disp_info.info1.entries[j].rid;
104 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
106 *prids = rids;
108 return NT_STATUS_OK;
111 /* List all domain groups */
112 NTSTATUS rpc_enum_dom_groups(TALLOC_CTX *mem_ctx,
113 struct rpc_pipe_client *samr_pipe,
114 struct policy_handle *samr_policy,
115 uint32_t *pnum_info,
116 struct wb_acct_info **pinfo)
118 struct wb_acct_info *info = NULL;
119 uint32_t start = 0;
120 uint32_t num_info = 0;
121 NTSTATUS status, result;
122 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
124 *pnum_info = 0;
126 do {
127 struct samr_SamArray *sam_array = NULL;
128 uint32_t count = 0;
129 uint32_t g;
131 /* start is updated by this call. */
132 status = dcerpc_samr_EnumDomainGroups(b,
133 mem_ctx,
134 samr_policy,
135 &start,
136 &sam_array,
137 0xFFFF, /* buffer size? */
138 &count,
139 &result);
140 if (!NT_STATUS_IS_OK(status)) {
141 return status;
143 if (!NT_STATUS_IS_OK(result)) {
144 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
145 DEBUG(2,("query_user_list: failed to enum domain groups: %s\n",
146 nt_errstr(result)));
147 return result;
151 info = talloc_realloc(mem_ctx,
152 info,
153 struct wb_acct_info,
154 num_info + count);
155 if (info == NULL) {
156 return NT_STATUS_NO_MEMORY;
159 for (g = 0; g < count; g++) {
160 struct wb_acct_info *i = &info[num_info + g];
162 fstrcpy(i->acct_name,
163 sam_array->entries[g].name.string);
164 fstrcpy(i->acct_desc, "");
165 i->rid = sam_array->entries[g].idx;
168 num_info += count;
169 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
171 *pnum_info = num_info;
172 *pinfo = info;
174 return NT_STATUS_OK;
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)
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;
188 *pnum_info = 0;
190 do {
191 struct samr_SamArray *sam_array = NULL;
192 uint32_t count = 0;
193 uint32_t start = num_info;
194 uint32_t g;
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;
207 if (!NT_STATUS_IS_OK(result)) {
208 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
209 return result;
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;
221 for (g = 0; g < count; g++) {
222 struct wb_acct_info *i = &info[num_info + g];
224 fstrcpy(i->acct_name,
225 sam_array->entries[g].name.string);
226 fstrcpy(i->acct_desc, "");
227 i->rid = sam_array->entries[g].idx;
230 num_info += count;
231 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
233 *pnum_info = num_info;
234 *pinfo = info;
236 return NT_STATUS_OK;
239 /* convert a single name to a sid in a domain */
240 NTSTATUS rpc_name_to_sid(TALLOC_CTX *mem_ctx,
241 struct rpc_pipe_client *lsa_pipe,
242 struct policy_handle *lsa_policy,
243 const char *domain_name,
244 const char *name,
245 uint32_t flags,
246 struct dom_sid *sid,
247 enum lsa_SidType *type)
249 enum lsa_SidType *types = NULL;
250 struct dom_sid *sids = NULL;
251 char *full_name = NULL;
252 const char *names[1];
253 char *mapped_name = NULL;
254 NTSTATUS status;
256 if (name == NULL || name[0] == '\0') {
257 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
258 } else if (domain_name == NULL || domain_name[0] == '\0') {
259 full_name = talloc_asprintf(mem_ctx, "%s", name);
260 } else {
261 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
264 if (full_name == NULL) {
265 return NT_STATUS_NO_MEMORY;
268 status = normalize_name_unmap(mem_ctx, full_name, &mapped_name);
269 /* Reset the full_name pointer if we mapped anything */
270 if (NT_STATUS_IS_OK(status) ||
271 NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
272 full_name = mapped_name;
275 DEBUG(3,("name_to_sid: %s for domain %s\n",
276 full_name ? full_name : "", domain_name ));
278 names[0] = full_name;
281 * We don't run into deadlocks here, cause winbind_off() is
282 * called in the main function.
284 status = rpccli_lsa_lookup_names(lsa_pipe,
285 mem_ctx,
286 lsa_policy,
287 1, /* num_names */
288 names,
289 NULL, /* domains */
290 1, /* level */
291 &sids,
292 &types);
293 if (!NT_STATUS_IS_OK(status)) {
294 DEBUG(2,("name_to_sid: failed to lookup name: %s\n",
295 nt_errstr(status)));
296 return status;
299 sid_copy(sid, &sids[0]);
300 *type = types[0];
302 return NT_STATUS_OK;
305 /* Convert a domain SID to a user or group name */
306 NTSTATUS rpc_sid_to_name(TALLOC_CTX *mem_ctx,
307 struct rpc_pipe_client *lsa_pipe,
308 struct policy_handle *lsa_policy,
309 struct winbindd_domain *domain,
310 const struct dom_sid *sid,
311 char **pdomain_name,
312 char **pname,
313 enum lsa_SidType *ptype)
315 char *mapped_name = NULL;
316 char **domains = NULL;
317 char **names = NULL;
318 enum lsa_SidType *types = NULL;
319 NTSTATUS map_status;
320 NTSTATUS status;
322 status = rpccli_lsa_lookup_sids(lsa_pipe,
323 mem_ctx,
324 lsa_policy,
325 1, /* num_sids */
326 sid,
327 &domains,
328 &names,
329 &types);
330 if (!NT_STATUS_IS_OK(status)) {
331 DEBUG(2,("sid_to_name: failed to lookup sids: %s\n",
332 nt_errstr(status)));
333 return status;
336 *ptype = (enum lsa_SidType) types[0];
338 map_status = normalize_name_map(mem_ctx,
339 domain,
340 names[0],
341 &mapped_name);
342 if (NT_STATUS_IS_OK(map_status) ||
343 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
344 *pname = talloc_strdup(mem_ctx, mapped_name);
345 DEBUG(5,("returning mapped name -- %s\n", *pname));
346 } else {
347 *pname = talloc_strdup(mem_ctx, names[0]);
349 if ((names[0] != NULL) && (*pname == NULL)) {
350 return NT_STATUS_NO_MEMORY;
353 *pdomain_name = talloc_strdup(mem_ctx, domains[0]);
354 if (*pdomain_name == NULL) {
355 return NT_STATUS_NO_MEMORY;
358 return NT_STATUS_OK;
361 /* Convert a bunch of rids to user or group names */
362 NTSTATUS rpc_rids_to_names(TALLOC_CTX *mem_ctx,
363 struct rpc_pipe_client *lsa_pipe,
364 struct policy_handle *lsa_policy,
365 struct winbindd_domain *domain,
366 const struct dom_sid *sid,
367 uint32_t *rids,
368 size_t num_rids,
369 char **pdomain_name,
370 char ***pnames,
371 enum lsa_SidType **ptypes)
373 enum lsa_SidType *types = NULL;
374 char *domain_name = NULL;
375 char **domains = NULL;
376 char **names = NULL;
377 struct dom_sid *sids;
378 size_t i;
379 NTSTATUS status;
381 if (num_rids > 0) {
382 sids = talloc_array(mem_ctx, struct dom_sid, num_rids);
383 if (sids == NULL) {
384 return NT_STATUS_NO_MEMORY;
386 } else {
387 sids = NULL;
390 for (i = 0; i < num_rids; i++) {
391 if (!sid_compose(&sids[i], sid, rids[i])) {
392 return NT_STATUS_INTERNAL_ERROR;
396 status = rpccli_lsa_lookup_sids(lsa_pipe,
397 mem_ctx,
398 lsa_policy,
399 num_rids,
400 sids,
401 &domains,
402 &names,
403 &types);
404 if (!NT_STATUS_IS_OK(status) &&
405 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
406 DEBUG(2,("rids_to_names: failed to lookup sids: %s\n",
407 nt_errstr(status)));
408 return status;
411 for (i = 0; i < num_rids; i++) {
412 char *mapped_name = NULL;
413 NTSTATUS map_status;
415 if (types[i] != SID_NAME_UNKNOWN) {
416 map_status = normalize_name_map(mem_ctx,
417 domain,
418 names[i],
419 &mapped_name);
420 if (NT_STATUS_IS_OK(map_status) ||
421 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
422 TALLOC_FREE(names[i]);
423 names[i] = talloc_strdup(names, mapped_name);
424 if (names[i] == NULL) {
425 return NT_STATUS_NO_MEMORY;
429 domain_name = domains[i];
433 *pdomain_name = domain_name;
434 *ptypes = types;
435 *pnames = names;
437 return NT_STATUS_OK;
440 NTSTATUS rpc_lookup_useraliases(TALLOC_CTX *mem_ctx,
441 struct rpc_pipe_client *samr_pipe,
442 struct policy_handle *samr_policy,
443 uint32_t num_sids,
444 const struct dom_sid *sids,
445 uint32_t *pnum_aliases,
446 uint32_t **palias_rids)
448 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
449 uint32_t num_query_sids = 0;
450 uint32_t num_queries = 1;
451 uint32_t num_aliases = 0;
452 uint32_t total_sids = 0;
453 uint32_t *alias_rids = NULL;
454 uint32_t rangesize = MAX_SAM_ENTRIES_W2K;
455 uint32_t i;
456 struct samr_Ids alias_rids_query;
457 NTSTATUS status, result;
458 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
460 do {
461 /* prepare query */
462 struct lsa_SidArray sid_array;
464 ZERO_STRUCT(sid_array);
466 num_query_sids = MIN(num_sids - total_sids, rangesize);
468 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
469 num_queries, num_query_sids));
471 if (num_query_sids) {
472 sid_array.sids = talloc_zero_array(mem_ctx, struct lsa_SidPtr, num_query_sids);
473 if (sid_array.sids == NULL) {
474 return NT_STATUS_NO_MEMORY;
476 } else {
477 sid_array.sids = NULL;
480 for (i = 0; i < num_query_sids; i++) {
481 sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[total_sids++]);
482 if (sid_array.sids[i].sid == NULL) {
483 return NT_STATUS_NO_MEMORY;
486 sid_array.num_sids = num_query_sids;
488 /* do request */
489 status = dcerpc_samr_GetAliasMembership(b,
490 mem_ctx,
491 samr_policy,
492 &sid_array,
493 &alias_rids_query,
494 &result);
495 if (!NT_STATUS_IS_OK(status)) {
496 return status;
498 if (!NT_STATUS_IS_OK(result)) {
499 return result;
502 /* process output */
503 for (i = 0; i < alias_rids_query.count; i++) {
504 size_t na = num_aliases;
506 if (!add_rid_to_array_unique(mem_ctx,
507 alias_rids_query.ids[i],
508 &alias_rids,
509 &na)) {
510 return NT_STATUS_NO_MEMORY;
512 num_aliases = na;
515 num_queries++;
517 } while (total_sids < num_sids);
519 DEBUG(10,("rpc: rpc_lookup_useraliases: got %d aliases in %d queries "
520 "(rangesize: %d)\n", num_aliases, num_queries, rangesize));
522 *pnum_aliases = num_aliases;
523 *palias_rids = alias_rids;
525 return NT_STATUS_OK;
526 #undef MAX_SAM_ENTRIES_W2K
529 /* Lookup group membership given a rid. */
530 NTSTATUS rpc_lookup_groupmem(TALLOC_CTX *mem_ctx,
531 struct rpc_pipe_client *samr_pipe,
532 struct policy_handle *samr_policy,
533 const char *domain_name,
534 const struct dom_sid *domain_sid,
535 const struct dom_sid *group_sid,
536 enum lsa_SidType type,
537 uint32_t *pnum_names,
538 struct dom_sid **psid_mem,
539 char ***pnames,
540 uint32_t **pname_types)
542 struct policy_handle group_policy;
543 uint32_t group_rid;
544 uint32_t *rid_mem = NULL;
546 uint32_t num_names = 0;
547 uint32_t total_names = 0;
548 struct dom_sid *sid_mem = NULL;
549 char **names = NULL;
550 uint32_t *name_types = NULL;
552 struct lsa_Strings tmp_names;
553 struct samr_Ids tmp_types;
555 uint32_t j, r;
556 NTSTATUS status, result;
557 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
559 if (!sid_peek_check_rid(domain_sid, group_sid, &group_rid)) {
560 return NT_STATUS_UNSUCCESSFUL;
563 switch(type) {
564 case SID_NAME_DOM_GRP:
566 struct samr_RidAttrArray *rids = NULL;
568 status = dcerpc_samr_OpenGroup(b,
569 mem_ctx,
570 samr_policy,
571 SEC_FLAG_MAXIMUM_ALLOWED,
572 group_rid,
573 &group_policy,
574 &result);
575 if (!NT_STATUS_IS_OK(status)) {
576 return status;
578 if (!NT_STATUS_IS_OK(result)) {
579 return result;
583 * Step #1: Get a list of user rids that are the members of the group.
585 status = dcerpc_samr_QueryGroupMember(b,
586 mem_ctx,
587 &group_policy,
588 &rids,
589 &result);
591 NTSTATUS _result;
592 dcerpc_samr_Close(b, mem_ctx, &group_policy, &_result);
595 if (!NT_STATUS_IS_OK(status)) {
596 return status;
598 if (!NT_STATUS_IS_OK(result)) {
599 return result;
603 if (rids == NULL || rids->count == 0) {
604 pnum_names = 0;
605 pnames = NULL;
606 pname_types = NULL;
607 psid_mem = NULL;
609 return NT_STATUS_OK;
612 num_names = rids->count;
613 rid_mem = rids->rids;
615 break;
617 case SID_NAME_WKN_GRP:
618 case SID_NAME_ALIAS:
620 struct lsa_SidArray sid_array;
621 struct lsa_SidPtr sid_ptr;
622 struct samr_Ids rids_query;
624 sid_ptr.sid = dom_sid_dup(mem_ctx, group_sid);
625 if (sid_ptr.sid == NULL) {
626 return NT_STATUS_NO_MEMORY;
629 sid_array.num_sids = 1;
630 sid_array.sids = &sid_ptr;
632 status = dcerpc_samr_GetAliasMembership(b,
633 mem_ctx,
634 samr_policy,
635 &sid_array,
636 &rids_query,
637 &result);
638 if (!NT_STATUS_IS_OK(status)) {
639 return status;
641 if (!NT_STATUS_IS_OK(result)) {
642 return result;
645 if (rids_query.count == 0) {
646 pnum_names = 0;
647 pnames = NULL;
648 pname_types = NULL;
649 psid_mem = NULL;
651 return NT_STATUS_OK;
654 num_names = rids_query.count;
655 rid_mem = rids_query.ids;
657 break;
659 default:
660 return NT_STATUS_UNSUCCESSFUL;
664 * Step #2: Convert list of rids into list of usernames.
666 if (num_names > 0) {
667 names = talloc_zero_array(mem_ctx, char *, num_names);
668 name_types = talloc_zero_array(mem_ctx, uint32_t, num_names);
669 sid_mem = talloc_zero_array(mem_ctx, struct dom_sid, num_names);
670 if (names == NULL || name_types == NULL || sid_mem == NULL) {
671 return NT_STATUS_NO_MEMORY;
675 for (j = 0; j < num_names; j++) {
676 sid_compose(&sid_mem[j], domain_sid, rid_mem[j]);
679 status = dcerpc_samr_LookupRids(b,
680 mem_ctx,
681 samr_policy,
682 num_names,
683 rid_mem,
684 &tmp_names,
685 &tmp_types,
686 &result);
687 if (!NT_STATUS_IS_OK(status)) {
688 return status;
691 if (!NT_STATUS_IS_OK(result)) {
692 if (!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
693 return result;
697 /* Copy result into array. The talloc system will take
698 care of freeing the temporary arrays later on. */
699 if (tmp_names.count != num_names) {
700 return NT_STATUS_INVALID_NETWORK_RESPONSE;
702 if (tmp_types.count != num_names) {
703 return NT_STATUS_INVALID_NETWORK_RESPONSE;
706 for (r = 0; r < tmp_names.count; r++) {
707 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
708 continue;
710 if (total_names >= num_names) {
711 break;
713 names[total_names] = fill_domain_username_talloc(names,
714 domain_name,
715 tmp_names.names[r].string,
716 true);
717 if (names[total_names] == NULL) {
718 return NT_STATUS_NO_MEMORY;
720 name_types[total_names] = tmp_types.ids[r];
721 total_names++;
724 *pnum_names = total_names;
725 *pnames = names;
726 *pname_types = name_types;
727 *psid_mem = sid_mem;
729 return NT_STATUS_OK;
732 /* Find the sequence number for a domain */
733 NTSTATUS rpc_sequence_number(TALLOC_CTX *mem_ctx,
734 struct rpc_pipe_client *samr_pipe,
735 struct policy_handle *samr_policy,
736 const char *domain_name,
737 uint32_t *pseq)
739 union samr_DomainInfo *info = NULL;
740 bool got_seq_num = false;
741 NTSTATUS status, result;
742 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
744 /* query domain info */
745 status = dcerpc_samr_QueryDomainInfo(b,
746 mem_ctx,
747 samr_policy,
749 &info,
750 &result);
751 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
752 *pseq = info->info8.sequence_num;
753 got_seq_num = true;
754 goto seq_num;
757 /* retry with info-level 2 in case the dc does not support info-level 8
758 * (like all older samba2 and samba3 dc's) - Guenther */
759 status = dcerpc_samr_QueryDomainInfo(b,
760 mem_ctx,
761 samr_policy,
763 &info,
764 &result);
765 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
766 *pseq = info->general.sequence_num;
767 got_seq_num = true;
768 goto seq_num;
771 if (!NT_STATUS_IS_OK(status)) {
772 goto seq_num;
775 status = result;
777 seq_num:
778 if (got_seq_num) {
779 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
780 domain_name, (unsigned) *pseq));
781 } else {
782 DEBUG(10,("domain_sequence_number: failed to get sequence "
783 "number (%u) for domain %s\n",
784 (unsigned) *pseq, domain_name ));
785 status = NT_STATUS_OK;
788 return status;
791 /* Get a list of trusted domains */
792 NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
793 struct rpc_pipe_client *lsa_pipe,
794 struct policy_handle *lsa_policy,
795 uint32_t *pnum_trusts,
796 struct netr_DomainTrust **ptrusts)
798 struct netr_DomainTrust *array = NULL;
799 uint32_t enum_ctx = 0;
800 uint32_t count = 0;
801 NTSTATUS status, result;
802 struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
804 do {
805 struct lsa_DomainList dom_list;
806 struct lsa_DomainListEx dom_list_ex;
807 bool has_ex = false;
808 uint32_t i;
811 * We don't run into deadlocks here, cause winbind_off() is
812 * called in the main function.
814 status = dcerpc_lsa_EnumTrustedDomainsEx(b,
815 mem_ctx,
816 lsa_policy,
817 &enum_ctx,
818 &dom_list_ex,
819 (uint32_t) -1,
820 &result);
821 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_ERR(result) &&
822 dom_list_ex.count > 0) {
823 count += dom_list_ex.count;
824 has_ex = true;
825 } else {
826 status = dcerpc_lsa_EnumTrustDom(b,
827 mem_ctx,
828 lsa_policy,
829 &enum_ctx,
830 &dom_list,
831 (uint32_t) -1,
832 &result);
833 if (!NT_STATUS_IS_OK(status)) {
834 return status;
836 if (!NT_STATUS_IS_OK(result)) {
837 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
838 return result;
842 count += dom_list.count;
845 array = talloc_realloc(mem_ctx,
846 array,
847 struct netr_DomainTrust,
848 count);
849 if (array == NULL) {
850 return NT_STATUS_NO_MEMORY;
853 for (i = 0; i < count; i++) {
854 struct netr_DomainTrust *trust = &array[i];
855 struct dom_sid *sid;
857 ZERO_STRUCTP(trust);
859 sid = talloc(array, struct dom_sid);
860 if (sid == NULL) {
861 return NT_STATUS_NO_MEMORY;
864 if (has_ex) {
865 trust->netbios_name = talloc_move(array,
866 &dom_list_ex.domains[i].netbios_name.string);
867 trust->dns_name = talloc_move(array,
868 &dom_list_ex.domains[i].domain_name.string);
869 if (dom_list_ex.domains[i].sid == NULL) {
870 DEBUG(0, ("Trusted Domain %s has no SID, aborting!\n", trust->dns_name));
871 return NT_STATUS_INVALID_NETWORK_RESPONSE;
873 sid_copy(sid, dom_list_ex.domains[i].sid);
874 } else {
875 trust->netbios_name = talloc_move(array,
876 &dom_list.domains[i].name.string);
877 trust->dns_name = NULL;
879 if (dom_list.domains[i].sid == NULL) {
880 DEBUG(0, ("Trusted Domain %s has no SID, aborting!\n", trust->netbios_name));
881 return NT_STATUS_INVALID_NETWORK_RESPONSE;
884 sid_copy(sid, dom_list.domains[i].sid);
887 trust->sid = sid;
889 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
891 *pnum_trusts = count;
892 *ptrusts = array;
894 return NT_STATUS_OK;
897 static NTSTATUS rpc_try_lookup_sids3(TALLOC_CTX *mem_ctx,
898 struct winbindd_domain *domain,
899 struct rpc_pipe_client *cli,
900 struct lsa_SidArray *sids,
901 struct lsa_RefDomainList **pdomains,
902 struct lsa_TransNameArray **pnames)
904 struct lsa_TransNameArray2 lsa_names2;
905 struct lsa_TransNameArray *names = *pnames;
906 uint32_t i, count = 0;
907 NTSTATUS status, result;
909 ZERO_STRUCT(lsa_names2);
910 status = dcerpc_lsa_LookupSids3(cli->binding_handle,
911 mem_ctx,
912 sids,
913 pdomains,
914 &lsa_names2,
915 LSA_LOOKUP_NAMES_ALL,
916 &count,
917 LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
918 LSA_CLIENT_REVISION_2,
919 &result);
920 if (!NT_STATUS_IS_OK(status)) {
921 return status;
923 if (NT_STATUS_IS_ERR(result)) {
924 return result;
926 if (sids->num_sids != lsa_names2.count) {
927 return NT_STATUS_INVALID_NETWORK_RESPONSE;
930 names->count = lsa_names2.count;
931 names->names = talloc_array(names, struct lsa_TranslatedName,
932 names->count);
933 if (names->names == NULL) {
934 return NT_STATUS_NO_MEMORY;
936 for (i=0; i<names->count; i++) {
937 names->names[i].sid_type = lsa_names2.names[i].sid_type;
938 names->names[i].name.string = talloc_move(
939 names->names, &lsa_names2.names[i].name.string);
940 names->names[i].sid_index = lsa_names2.names[i].sid_index;
942 if (names->names[i].sid_index == UINT32_MAX) {
943 continue;
945 if ((*pdomains) == NULL) {
946 return NT_STATUS_INVALID_NETWORK_RESPONSE;
948 if (names->names[i].sid_index >= (*pdomains)->count) {
949 return NT_STATUS_INVALID_NETWORK_RESPONSE;
952 return result;
955 NTSTATUS rpc_lookup_sids(TALLOC_CTX *mem_ctx,
956 struct winbindd_domain *domain,
957 struct lsa_SidArray *sids,
958 struct lsa_RefDomainList **pdomains,
959 struct lsa_TransNameArray **pnames)
961 struct lsa_TransNameArray *names = *pnames;
962 struct rpc_pipe_client *cli = NULL;
963 struct policy_handle lsa_policy;
964 uint32_t count;
965 uint32_t i;
966 NTSTATUS status, result;
968 status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
969 if (!NT_STATUS_IS_OK(status)) {
970 return status;
973 if (cli->transport->transport == NCACN_IP_TCP) {
974 return rpc_try_lookup_sids3(mem_ctx, domain, cli, sids,
975 pdomains, pnames);
978 status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
979 &lsa_policy, sids, pdomains,
980 names, LSA_LOOKUP_NAMES_ALL,
981 &count, &result);
982 if (!NT_STATUS_IS_OK(status)) {
983 return status;
985 if (NT_STATUS_IS_ERR(result)) {
986 return result;
989 if (sids->num_sids != names->count) {
990 return NT_STATUS_INVALID_NETWORK_RESPONSE;
993 for (i=0; i < names->count; i++) {
994 if (names->names[i].sid_index == UINT32_MAX) {
995 continue;
997 if ((*pdomains) == NULL) {
998 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1000 if (names->names[i].sid_index >= (*pdomains)->count) {
1001 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1005 return result;