s3:winbind: Add lookup_aliasmem to winbindd_methods and implement it in all backends
[samba4-gss.git] / source3 / winbindd / winbindd_rpc.c
blob6a0f2b2e7aa277b959743a7f3c913e8de560cf53
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 case SID_NAME_WKN_GRP:
495 case SID_NAME_ALIAS:
497 struct lsa_SidArray sid_array;
498 struct lsa_SidPtr sid_ptr;
499 struct samr_Ids rids_query;
501 sid_ptr.sid = dom_sid_dup(mem_ctx, group_sid);
502 if (sid_ptr.sid == NULL) {
503 return NT_STATUS_NO_MEMORY;
506 sid_array.num_sids = 1;
507 sid_array.sids = &sid_ptr;
509 status = dcerpc_samr_GetAliasMembership(b,
510 mem_ctx,
511 samr_policy,
512 &sid_array,
513 &rids_query,
514 &result);
515 if (!NT_STATUS_IS_OK(status)) {
516 return status;
518 if (!NT_STATUS_IS_OK(result)) {
519 return result;
522 if (rids_query.count == 0) {
523 pnum_names = 0;
524 pnames = NULL;
525 pname_types = NULL;
526 psid_mem = NULL;
528 return NT_STATUS_OK;
531 num_names = rids_query.count;
532 rid_mem = rids_query.ids;
534 break;
536 default:
537 return NT_STATUS_UNSUCCESSFUL;
541 * Step #2: Convert list of rids into list of usernames.
543 if (num_names > 0) {
544 names = talloc_zero_array(mem_ctx, char *, num_names);
545 name_types = talloc_zero_array(mem_ctx, uint32_t, num_names);
546 sid_mem = talloc_zero_array(mem_ctx, struct dom_sid, num_names);
547 if (names == NULL || name_types == NULL || sid_mem == NULL) {
548 return NT_STATUS_NO_MEMORY;
552 for (j = 0; j < num_names; j++) {
553 sid_compose(&sid_mem[j], domain_sid, rid_mem[j]);
556 status = dcerpc_samr_LookupRids(b,
557 mem_ctx,
558 samr_policy,
559 num_names,
560 rid_mem,
561 &tmp_names,
562 &tmp_types,
563 &result);
564 if (!NT_STATUS_IS_OK(status)) {
565 return status;
568 if (!NT_STATUS_IS_OK(result)) {
569 if (!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
570 return result;
574 /* Copy result into array. The talloc system will take
575 care of freeing the temporary arrays later on. */
576 if (tmp_names.count != num_names) {
577 return NT_STATUS_INVALID_NETWORK_RESPONSE;
579 if (tmp_types.count != num_names) {
580 return NT_STATUS_INVALID_NETWORK_RESPONSE;
583 for (r = 0; r < tmp_names.count; r++) {
584 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
585 continue;
587 if (total_names >= num_names) {
588 break;
590 names[total_names] = fill_domain_username_talloc(names,
591 domain_name,
592 tmp_names.names[r].string,
593 true);
594 if (names[total_names] == NULL) {
595 return NT_STATUS_NO_MEMORY;
597 name_types[total_names] = tmp_types.ids[r];
598 total_names++;
601 *pnum_names = total_names;
602 *pnames = names;
603 *pname_types = name_types;
604 *psid_mem = sid_mem;
606 return NT_STATUS_OK;
609 /* Lookup alias membership using a rid taken from alias_sid. */
610 NTSTATUS rpc_lookup_aliasmem(TALLOC_CTX *mem_ctx,
611 struct rpc_pipe_client *samr_pipe,
612 struct policy_handle *samr_policy,
613 const struct dom_sid *domain_sid,
614 const struct dom_sid *alias_sid,
615 enum lsa_SidType type,
616 uint32_t *pnum_sids,
617 struct dom_sid **psids)
619 uint32_t alias_rid;
620 struct dom_sid *sid_mem = NULL;
621 struct lsa_SidArray sid_array;
622 uint32_t i;
623 NTSTATUS status, result;
624 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
626 if (!sid_peek_check_rid(domain_sid, alias_sid, &alias_rid)) {
627 return NT_STATUS_UNSUCCESSFUL;
630 switch (type) {
631 case SID_NAME_ALIAS: {
632 struct policy_handle alias_policy;
634 status = dcerpc_samr_OpenAlias(b,
635 mem_ctx,
636 samr_policy,
637 SEC_FLAG_MAXIMUM_ALLOWED,
638 alias_rid,
639 &alias_policy,
640 &result);
641 if (any_nt_status_not_ok(status, result, &status)) {
642 return status;
645 status = dcerpc_samr_GetMembersInAlias(b,
646 mem_ctx,
647 &alias_policy,
648 &sid_array,
649 &result);
651 NTSTATUS _result;
652 dcerpc_samr_Close(b, mem_ctx, &alias_policy, &_result);
654 if (any_nt_status_not_ok(status, result, &status)) {
655 return status;
658 sid_mem = talloc_zero_array(mem_ctx,
659 struct dom_sid,
660 sid_array.num_sids);
661 if (sid_mem == NULL) {
662 return NT_STATUS_NO_MEMORY;
666 * We cannot just simply assign '*psids = sid_array.sids;'
667 * we need to copy every sid since these are incompatible types:
668 * 'struct dom_sid *' vs 'struct lsa_SidPtr *'
670 for (i = 0; i < sid_array.num_sids; i++) {
671 sid_copy(&sid_mem[i], sid_array.sids[i].sid);
674 *pnum_sids = sid_array.num_sids;
675 *psids = sid_mem;
677 return NT_STATUS_OK;
679 default:
680 return NT_STATUS_UNSUCCESSFUL;
684 /* Get a list of trusted domains */
685 NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
686 struct rpc_pipe_client *lsa_pipe,
687 struct policy_handle *lsa_policy,
688 uint32_t *pnum_trusts,
689 struct netr_DomainTrust **ptrusts)
691 struct netr_DomainTrust *array = NULL;
692 uint32_t enum_ctx = 0;
693 uint32_t count = 0;
694 NTSTATUS status, result;
695 struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
697 do {
698 struct lsa_DomainList dom_list;
699 struct lsa_DomainListEx dom_list_ex;
700 bool has_ex = false;
701 uint32_t i;
704 * We don't run into deadlocks here, cause winbind_off() is
705 * called in the main function.
707 status = dcerpc_lsa_EnumTrustedDomainsEx(b,
708 mem_ctx,
709 lsa_policy,
710 &enum_ctx,
711 &dom_list_ex,
712 (uint32_t) -1,
713 &result);
714 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_ERR(result) &&
715 dom_list_ex.count > 0) {
716 count += dom_list_ex.count;
717 has_ex = true;
718 } else {
719 status = dcerpc_lsa_EnumTrustDom(b,
720 mem_ctx,
721 lsa_policy,
722 &enum_ctx,
723 &dom_list,
724 (uint32_t) -1,
725 &result);
726 if (!NT_STATUS_IS_OK(status)) {
727 return status;
729 if (!NT_STATUS_IS_OK(result)) {
730 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
731 return result;
735 count += dom_list.count;
738 array = talloc_realloc(mem_ctx,
739 array,
740 struct netr_DomainTrust,
741 count);
742 if (array == NULL) {
743 return NT_STATUS_NO_MEMORY;
746 for (i = 0; i < count; i++) {
747 struct netr_DomainTrust *trust = &array[i];
748 struct dom_sid *sid;
750 ZERO_STRUCTP(trust);
752 sid = talloc(array, struct dom_sid);
753 if (sid == NULL) {
754 return NT_STATUS_NO_MEMORY;
757 if (dom_list_ex.domains[i].sid == NULL) {
758 DBG_ERR("Trusted domain %s has no SID, "
759 "skipping!\n",
760 trust->dns_name);
761 continue;
764 if (has_ex) {
765 trust->netbios_name = talloc_move(array,
766 &dom_list_ex.domains[i].netbios_name.string);
767 trust->dns_name = talloc_move(array,
768 &dom_list_ex.domains[i].domain_name.string);
769 sid_copy(sid, dom_list_ex.domains[i].sid);
770 } else {
771 trust->netbios_name = talloc_move(array,
772 &dom_list.domains[i].name.string);
773 trust->dns_name = NULL;
775 sid_copy(sid, dom_list.domains[i].sid);
778 trust->sid = sid;
780 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
782 *pnum_trusts = count;
783 *ptrusts = array;
785 return NT_STATUS_OK;
788 static NTSTATUS rpc_try_lookup_sids3(TALLOC_CTX *mem_ctx,
789 struct winbindd_domain *domain,
790 struct rpc_pipe_client *cli,
791 struct lsa_SidArray *sids,
792 struct lsa_RefDomainList **pdomains,
793 struct lsa_TransNameArray **pnames)
795 struct lsa_TransNameArray2 lsa_names2;
796 struct lsa_TransNameArray *names = *pnames;
797 uint32_t i, count = 0;
798 NTSTATUS status, result;
800 ZERO_STRUCT(lsa_names2);
801 status = dcerpc_lsa_LookupSids3(cli->binding_handle,
802 mem_ctx,
803 sids,
804 pdomains,
805 &lsa_names2,
806 LSA_LOOKUP_NAMES_ALL,
807 &count,
808 LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
809 LSA_CLIENT_REVISION_2,
810 &result);
811 if (!NT_STATUS_IS_OK(status)) {
812 return status;
814 if (NT_STATUS_LOOKUP_ERR(result)) {
815 return result;
817 if (sids->num_sids != lsa_names2.count) {
818 return NT_STATUS_INVALID_NETWORK_RESPONSE;
821 names->count = lsa_names2.count;
822 names->names = talloc_array(names, struct lsa_TranslatedName,
823 names->count);
824 if (names->names == NULL) {
825 return NT_STATUS_NO_MEMORY;
827 for (i=0; i<names->count; i++) {
828 names->names[i].sid_type = lsa_names2.names[i].sid_type;
829 names->names[i].name.string = talloc_move(
830 names->names, &lsa_names2.names[i].name.string);
831 names->names[i].sid_index = lsa_names2.names[i].sid_index;
833 if (names->names[i].sid_index == UINT32_MAX) {
834 continue;
836 if ((*pdomains) == NULL) {
837 return NT_STATUS_INVALID_NETWORK_RESPONSE;
839 if (names->names[i].sid_index >= (*pdomains)->count) {
840 return NT_STATUS_INVALID_NETWORK_RESPONSE;
843 return NT_STATUS_OK;
846 NTSTATUS rpc_lookup_sids(TALLOC_CTX *mem_ctx,
847 struct winbindd_domain *domain,
848 struct lsa_SidArray *sids,
849 struct lsa_RefDomainList **pdomains,
850 struct lsa_TransNameArray **pnames)
852 struct lsa_TransNameArray *names = *pnames;
853 struct rpc_pipe_client *cli = NULL;
854 struct policy_handle lsa_policy;
855 uint32_t count;
856 uint32_t i;
857 NTSTATUS status, result;
859 status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
860 if (!NT_STATUS_IS_OK(status)) {
861 return status;
864 if (cli->transport->transport == NCACN_IP_TCP) {
865 return rpc_try_lookup_sids3(mem_ctx, domain, cli, sids,
866 pdomains, pnames);
869 status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
870 &lsa_policy, sids, pdomains,
871 names, LSA_LOOKUP_NAMES_ALL,
872 &count, &result);
873 if (!NT_STATUS_IS_OK(status)) {
874 return status;
876 if (NT_STATUS_LOOKUP_ERR(result)) {
877 return result;
880 if (sids->num_sids != names->count) {
881 return NT_STATUS_INVALID_NETWORK_RESPONSE;
884 for (i=0; i < names->count; i++) {
885 if (names->names[i].sid_index == UINT32_MAX) {
886 continue;
888 if ((*pdomains) == NULL) {
889 return NT_STATUS_INVALID_NETWORK_RESPONSE;
891 if (names->names[i].sid_index >= (*pdomains)->count) {
892 return NT_STATUS_INVALID_NETWORK_RESPONSE;
896 return NT_STATUS_OK;