selftest: fix domain name of nt4_dc_smb1 environment
[Samba.git] / source3 / winbindd / winbindd_rpc.c
blob2b4a47e223dac30ddbed5510bfcb7a0038b0b9f1
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"
35 #include "lsa.h"
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)
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;
53 *prids = NULL;
55 tmp_ctx = talloc_stackframe();
56 if (tmp_ctx == NULL) {
57 return NT_STATUS_NO_MEMORY;
60 do {
61 struct samr_SamArray *sam_array = NULL;
62 uint32_t count = 0;
63 uint32_t *tmp;
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;
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;
80 if (num_rids + count < num_rids) {
81 status = NT_STATUS_INTEGER_OVERFLOW;
82 goto done;
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;
90 rids = tmp;
92 for (i=0; i<count; i++) {
93 rids[num_rids++] = sam_array->entries[i].idx;
96 TALLOC_FREE(sam_array);
97 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
99 *prids = talloc_steal(mem_ctx, rids);
100 status = NT_STATUS_OK;
102 done:
103 TALLOC_FREE(tmp_ctx);
104 return status;
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)
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;
120 *pnum_info = 0;
122 do {
123 struct samr_SamArray *sam_array = NULL;
124 uint32_t count = 0;
125 uint32_t g;
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;
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;
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;
155 for (g = 0; g < count; g++) {
156 struct wb_acct_info *i = &info[num_info + g];
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;
164 i->acct_desc = NULL;
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 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;
230 i->acct_desc = NULL;
231 i->rid = sam_array->entries[g].idx;
234 num_info += count;
235 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
237 *pnum_info = num_info;
238 *pinfo = info;
240 return NT_STATUS_OK;
243 /* Lookup groups a user is a member of. */
244 NTSTATUS rpc_lookup_usergroups(TALLOC_CTX *mem_ctx,
245 struct rpc_pipe_client *samr_pipe,
246 struct policy_handle *samr_policy,
247 const struct dom_sid *domain_sid,
248 const struct dom_sid *user_sid,
249 uint32_t *pnum_groups,
250 struct dom_sid **puser_grpsids)
252 struct policy_handle user_policy;
253 struct samr_RidWithAttributeArray *rid_array = NULL;
254 struct dom_sid *user_grpsids = NULL;
255 uint32_t num_groups = 0, i;
256 uint32_t user_rid;
257 NTSTATUS status, result;
258 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
260 if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
261 return NT_STATUS_UNSUCCESSFUL;
264 /* Get user handle */
265 status = dcerpc_samr_OpenUser(b,
266 mem_ctx,
267 samr_policy,
268 SEC_FLAG_MAXIMUM_ALLOWED,
269 user_rid,
270 &user_policy,
271 &result);
272 if (!NT_STATUS_IS_OK(status)) {
273 return status;
275 if (!NT_STATUS_IS_OK(result)) {
276 return result;
279 /* Query user rids */
280 status = dcerpc_samr_GetGroupsForUser(b,
281 mem_ctx,
282 &user_policy,
283 &rid_array,
284 &result);
286 NTSTATUS _result;
287 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
290 if (!NT_STATUS_IS_OK(status)) {
291 return status;
293 if (!NT_STATUS_IS_OK(result)) {
294 return result;
297 num_groups = rid_array->count;
299 user_grpsids = talloc_array(mem_ctx, struct dom_sid, num_groups);
300 if (user_grpsids == NULL) {
301 status = NT_STATUS_NO_MEMORY;
302 return status;
305 for (i = 0; i < num_groups; i++) {
306 sid_compose(&(user_grpsids[i]), domain_sid,
307 rid_array->rids[i].rid);
310 *pnum_groups = num_groups;
312 *puser_grpsids = user_grpsids;
314 return NT_STATUS_OK;
317 NTSTATUS rpc_lookup_useraliases(TALLOC_CTX *mem_ctx,
318 struct rpc_pipe_client *samr_pipe,
319 struct policy_handle *samr_policy,
320 uint32_t num_sids,
321 const struct dom_sid *sids,
322 uint32_t *pnum_aliases,
323 uint32_t **palias_rids)
325 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
326 uint32_t num_query_sids = 0;
327 uint32_t num_queries = 1;
328 uint32_t num_aliases = 0;
329 uint32_t total_sids = 0;
330 uint32_t *alias_rids = NULL;
331 uint32_t rangesize = MAX_SAM_ENTRIES_W2K;
332 uint32_t i;
333 struct samr_Ids alias_rids_query;
334 NTSTATUS status, result;
335 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
337 do {
338 /* prepare query */
339 struct lsa_SidArray sid_array;
341 ZERO_STRUCT(sid_array);
343 num_query_sids = MIN(num_sids - total_sids, rangesize);
345 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
346 num_queries, num_query_sids));
348 if (num_query_sids) {
349 sid_array.sids = talloc_zero_array(mem_ctx, struct lsa_SidPtr, num_query_sids);
350 if (sid_array.sids == NULL) {
351 return NT_STATUS_NO_MEMORY;
353 } else {
354 sid_array.sids = NULL;
357 for (i = 0; i < num_query_sids; i++) {
358 sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[total_sids++]);
359 if (sid_array.sids[i].sid == NULL) {
360 return NT_STATUS_NO_MEMORY;
363 sid_array.num_sids = num_query_sids;
365 /* do request */
366 status = dcerpc_samr_GetAliasMembership(b,
367 mem_ctx,
368 samr_policy,
369 &sid_array,
370 &alias_rids_query,
371 &result);
372 if (!NT_STATUS_IS_OK(status)) {
373 return status;
375 if (!NT_STATUS_IS_OK(result)) {
376 return result;
379 /* process output */
380 for (i = 0; i < alias_rids_query.count; i++) {
381 size_t na = num_aliases;
383 if (!add_rid_to_array_unique(mem_ctx,
384 alias_rids_query.ids[i],
385 &alias_rids,
386 &na)) {
387 return NT_STATUS_NO_MEMORY;
389 num_aliases = na;
392 num_queries++;
394 } while (total_sids < num_sids);
396 DEBUG(10,("rpc: rpc_lookup_useraliases: got %d aliases in %d queries "
397 "(rangesize: %d)\n", num_aliases, num_queries, rangesize));
399 *pnum_aliases = num_aliases;
400 *palias_rids = alias_rids;
402 return NT_STATUS_OK;
403 #undef MAX_SAM_ENTRIES_W2K
406 /* Lookup group membership given a rid. */
407 NTSTATUS rpc_lookup_groupmem(TALLOC_CTX *mem_ctx,
408 struct rpc_pipe_client *samr_pipe,
409 struct policy_handle *samr_policy,
410 const char *domain_name,
411 const struct dom_sid *domain_sid,
412 const struct dom_sid *group_sid,
413 enum lsa_SidType type,
414 uint32_t *pnum_names,
415 struct dom_sid **psid_mem,
416 char ***pnames,
417 uint32_t **pname_types)
419 struct policy_handle group_policy;
420 uint32_t group_rid;
421 uint32_t *rid_mem = NULL;
423 uint32_t num_names = 0;
424 uint32_t total_names = 0;
425 struct dom_sid *sid_mem = NULL;
426 char **names = NULL;
427 uint32_t *name_types = NULL;
429 struct lsa_Strings tmp_names;
430 struct samr_Ids tmp_types;
432 uint32_t j, r;
433 NTSTATUS status, result;
434 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
436 if (!sid_peek_check_rid(domain_sid, group_sid, &group_rid)) {
437 return NT_STATUS_UNSUCCESSFUL;
440 switch(type) {
441 case SID_NAME_DOM_GRP:
443 struct samr_RidAttrArray *rids = NULL;
445 status = dcerpc_samr_OpenGroup(b,
446 mem_ctx,
447 samr_policy,
448 SEC_FLAG_MAXIMUM_ALLOWED,
449 group_rid,
450 &group_policy,
451 &result);
452 if (!NT_STATUS_IS_OK(status)) {
453 return status;
455 if (!NT_STATUS_IS_OK(result)) {
456 return result;
460 * Step #1: Get a list of user rids that are the members of the group.
462 status = dcerpc_samr_QueryGroupMember(b,
463 mem_ctx,
464 &group_policy,
465 &rids,
466 &result);
468 NTSTATUS _result;
469 dcerpc_samr_Close(b, mem_ctx, &group_policy, &_result);
472 if (!NT_STATUS_IS_OK(status)) {
473 return status;
475 if (!NT_STATUS_IS_OK(result)) {
476 return result;
480 if (rids == NULL || rids->count == 0) {
481 pnum_names = 0;
482 pnames = NULL;
483 pname_types = NULL;
484 psid_mem = NULL;
486 return NT_STATUS_OK;
489 num_names = rids->count;
490 rid_mem = rids->rids;
492 break;
494 default:
495 return NT_STATUS_UNSUCCESSFUL;
499 * Step #2: Convert list of rids into list of usernames.
501 if (num_names > 0) {
502 names = talloc_zero_array(mem_ctx, char *, num_names);
503 name_types = talloc_zero_array(mem_ctx, uint32_t, num_names);
504 sid_mem = talloc_zero_array(mem_ctx, struct dom_sid, num_names);
505 if (names == NULL || name_types == NULL || sid_mem == NULL) {
506 return NT_STATUS_NO_MEMORY;
510 for (j = 0; j < num_names; j++) {
511 sid_compose(&sid_mem[j], domain_sid, rid_mem[j]);
514 status = dcerpc_samr_LookupRids(b,
515 mem_ctx,
516 samr_policy,
517 num_names,
518 rid_mem,
519 &tmp_names,
520 &tmp_types,
521 &result);
522 if (!NT_STATUS_IS_OK(status)) {
523 return status;
526 if (!NT_STATUS_IS_OK(result)) {
527 if (!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
528 return result;
532 /* Copy result into array. The talloc system will take
533 care of freeing the temporary arrays later on. */
534 if (tmp_names.count != num_names) {
535 return NT_STATUS_INVALID_NETWORK_RESPONSE;
537 if (tmp_types.count != num_names) {
538 return NT_STATUS_INVALID_NETWORK_RESPONSE;
541 for (r = 0; r < tmp_names.count; r++) {
542 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
543 continue;
545 if (total_names >= num_names) {
546 break;
548 names[total_names] = fill_domain_username_talloc(names,
549 domain_name,
550 tmp_names.names[r].string,
551 true);
552 if (names[total_names] == NULL) {
553 return NT_STATUS_NO_MEMORY;
555 name_types[total_names] = tmp_types.ids[r];
556 total_names++;
559 *pnum_names = total_names;
560 *pnames = names;
561 *pname_types = name_types;
562 *psid_mem = sid_mem;
564 return NT_STATUS_OK;
567 /* Lookup alias membership using a rid taken from alias_sid. */
568 NTSTATUS rpc_lookup_aliasmem(TALLOC_CTX *mem_ctx,
569 struct rpc_pipe_client *samr_pipe,
570 struct policy_handle *samr_policy,
571 const struct dom_sid *domain_sid,
572 const struct dom_sid *alias_sid,
573 enum lsa_SidType type,
574 uint32_t *pnum_sids,
575 struct dom_sid **psids)
577 uint32_t alias_rid;
578 struct dom_sid *sid_mem = NULL;
579 struct lsa_SidArray sid_array;
580 uint32_t i;
581 NTSTATUS status, result;
582 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
584 if (!sid_peek_check_rid(domain_sid, alias_sid, &alias_rid)) {
585 return NT_STATUS_UNSUCCESSFUL;
588 switch (type) {
589 case SID_NAME_ALIAS: {
590 struct policy_handle alias_policy;
592 status = dcerpc_samr_OpenAlias(b,
593 mem_ctx,
594 samr_policy,
595 SEC_FLAG_MAXIMUM_ALLOWED,
596 alias_rid,
597 &alias_policy,
598 &result);
599 if (any_nt_status_not_ok(status, result, &status)) {
600 return status;
603 status = dcerpc_samr_GetMembersInAlias(b,
604 mem_ctx,
605 &alias_policy,
606 &sid_array,
607 &result);
609 NTSTATUS _result;
610 dcerpc_samr_Close(b, mem_ctx, &alias_policy, &_result);
612 if (any_nt_status_not_ok(status, result, &status)) {
613 return status;
616 sid_mem = talloc_zero_array(mem_ctx,
617 struct dom_sid,
618 sid_array.num_sids);
619 if (sid_mem == NULL) {
620 return NT_STATUS_NO_MEMORY;
624 * We cannot just simply assign '*psids = sid_array.sids;'
625 * we need to copy every sid since these are incompatible types:
626 * 'struct dom_sid *' vs 'struct lsa_SidPtr *'
628 for (i = 0; i < sid_array.num_sids; i++) {
629 sid_copy(&sid_mem[i], sid_array.sids[i].sid);
632 *pnum_sids = sid_array.num_sids;
633 *psids = sid_mem;
635 return NT_STATUS_OK;
637 default:
638 return NT_STATUS_UNSUCCESSFUL;
642 /* Get a list of trusted domains */
643 NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
644 struct rpc_pipe_client *lsa_pipe,
645 struct policy_handle *lsa_policy,
646 uint32_t *pnum_trusts,
647 struct netr_DomainTrust **ptrusts)
649 struct netr_DomainTrust *array = NULL;
650 uint32_t enum_ctx = 0;
651 uint32_t count = 0;
652 NTSTATUS status, result;
653 struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
655 do {
656 struct lsa_DomainList dom_list;
657 struct lsa_DomainListEx dom_list_ex;
658 bool has_ex = false;
659 uint32_t i;
662 * We don't run into deadlocks here, cause winbind_off() is
663 * called in the main function.
665 status = dcerpc_lsa_EnumTrustedDomainsEx(b,
666 mem_ctx,
667 lsa_policy,
668 &enum_ctx,
669 &dom_list_ex,
670 (uint32_t) -1,
671 &result);
672 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_ERR(result) &&
673 dom_list_ex.count > 0) {
674 count += dom_list_ex.count;
675 has_ex = true;
676 } else {
677 status = dcerpc_lsa_EnumTrustDom(b,
678 mem_ctx,
679 lsa_policy,
680 &enum_ctx,
681 &dom_list,
682 (uint32_t) -1,
683 &result);
684 if (!NT_STATUS_IS_OK(status)) {
685 return status;
687 if (!NT_STATUS_IS_OK(result)) {
688 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
689 return result;
693 count += dom_list.count;
696 array = talloc_realloc(mem_ctx,
697 array,
698 struct netr_DomainTrust,
699 count);
700 if (array == NULL) {
701 return NT_STATUS_NO_MEMORY;
704 for (i = 0; i < count; i++) {
705 struct netr_DomainTrust *trust = &array[i];
706 struct dom_sid *sid;
708 ZERO_STRUCTP(trust);
710 sid = talloc(array, struct dom_sid);
711 if (sid == NULL) {
712 return NT_STATUS_NO_MEMORY;
715 if (dom_list_ex.domains[i].sid == NULL) {
716 DBG_ERR("Trusted domain %s has no SID, "
717 "skipping!\n",
718 trust->dns_name);
719 continue;
722 if (has_ex) {
723 trust->netbios_name = talloc_move(array,
724 &dom_list_ex.domains[i].netbios_name.string);
725 trust->dns_name = talloc_move(array,
726 &dom_list_ex.domains[i].domain_name.string);
727 sid_copy(sid, dom_list_ex.domains[i].sid);
728 } else {
729 trust->netbios_name = talloc_move(array,
730 &dom_list.domains[i].name.string);
731 trust->dns_name = NULL;
733 sid_copy(sid, dom_list.domains[i].sid);
736 trust->sid = sid;
738 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
740 *pnum_trusts = count;
741 *ptrusts = array;
743 return NT_STATUS_OK;
746 static NTSTATUS rpc_try_lookup_sids3(TALLOC_CTX *mem_ctx,
747 struct winbindd_domain *domain,
748 struct rpc_pipe_client *cli,
749 struct lsa_SidArray *sids,
750 struct lsa_RefDomainList **pdomains,
751 struct lsa_TransNameArray **pnames)
753 struct lsa_TransNameArray2 lsa_names2;
754 struct lsa_TransNameArray *names = *pnames;
755 uint32_t i, count = 0;
756 NTSTATUS status, result;
758 ZERO_STRUCT(lsa_names2);
759 status = dcerpc_lsa_LookupSids3(cli->binding_handle,
760 mem_ctx,
761 sids,
762 pdomains,
763 &lsa_names2,
764 LSA_LOOKUP_NAMES_ALL,
765 &count,
766 LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
767 LSA_CLIENT_REVISION_2,
768 &result);
769 if (!NT_STATUS_IS_OK(status)) {
770 return status;
772 if (NT_STATUS_LOOKUP_ERR(result)) {
773 return result;
775 if (sids->num_sids != lsa_names2.count) {
776 return NT_STATUS_INVALID_NETWORK_RESPONSE;
779 names->count = lsa_names2.count;
780 names->names = talloc_array(names, struct lsa_TranslatedName,
781 names->count);
782 if (names->names == NULL) {
783 return NT_STATUS_NO_MEMORY;
785 for (i=0; i<names->count; i++) {
786 names->names[i].sid_type = lsa_names2.names[i].sid_type;
787 names->names[i].name.string = talloc_move(
788 names->names, &lsa_names2.names[i].name.string);
789 names->names[i].sid_index = lsa_names2.names[i].sid_index;
791 if (names->names[i].sid_index == UINT32_MAX) {
792 continue;
794 if ((*pdomains) == NULL) {
795 return NT_STATUS_INVALID_NETWORK_RESPONSE;
797 if (names->names[i].sid_index >= (*pdomains)->count) {
798 return NT_STATUS_INVALID_NETWORK_RESPONSE;
801 return NT_STATUS_OK;
804 NTSTATUS rpc_lookup_sids(TALLOC_CTX *mem_ctx,
805 struct winbindd_domain *domain,
806 struct lsa_SidArray *sids,
807 struct lsa_RefDomainList **pdomains,
808 struct lsa_TransNameArray **pnames)
810 struct lsa_TransNameArray *names = *pnames;
811 struct rpc_pipe_client *cli = NULL;
812 struct policy_handle lsa_policy;
813 uint32_t count;
814 uint32_t i;
815 NTSTATUS status, result;
817 status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
818 if (!NT_STATUS_IS_OK(status)) {
819 return status;
822 if (cli->transport->transport == NCACN_IP_TCP) {
823 return rpc_try_lookup_sids3(mem_ctx, domain, cli, sids,
824 pdomains, pnames);
827 status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
828 &lsa_policy, sids, pdomains,
829 names, LSA_LOOKUP_NAMES_ALL,
830 &count, &result);
831 if (!NT_STATUS_IS_OK(status)) {
832 return status;
834 if (NT_STATUS_LOOKUP_ERR(result)) {
835 return result;
838 if (sids->num_sids != names->count) {
839 return NT_STATUS_INVALID_NETWORK_RESPONSE;
842 for (i=0; i < names->count; i++) {
843 if (names->names[i].sid_index == UINT32_MAX) {
844 continue;
846 if ((*pdomains) == NULL) {
847 return NT_STATUS_INVALID_NETWORK_RESPONSE;
849 if (names->names[i].sid_index >= (*pdomains)->count) {
850 return NT_STATUS_INVALID_NETWORK_RESPONSE;
854 return NT_STATUS_OK;