libcli: Remove an unused variable
[Samba.git] / source3 / winbindd / winbindd_rpc.c
blob85b3d5c08e532651990974f8d826bc3b09e28602
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 *pnum_info,
42 struct wbint_userinfo **pinfo)
44 struct wbint_userinfo *info = NULL;
45 uint32_t num_info = 0;
46 uint32_t loop_count = 0;
47 uint32_t start_idx = 0;
48 uint32_t i = 0;
49 NTSTATUS status, result;
50 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
52 *pnum_info = 0;
54 do {
55 uint32_t j;
56 uint32_t num_dom_users;
57 uint32_t max_entries, max_size;
58 uint32_t total_size, returned_size;
59 union samr_DispInfo disp_info;
61 dcerpc_get_query_dispinfo_params(loop_count,
62 &max_entries,
63 &max_size);
65 status = dcerpc_samr_QueryDisplayInfo(b,
66 mem_ctx,
67 samr_policy,
68 1, /* level */
69 start_idx,
70 max_entries,
71 max_size,
72 &total_size,
73 &returned_size,
74 &disp_info,
75 &result);
76 if (!NT_STATUS_IS_OK(status)) {
77 return status;
79 if (!NT_STATUS_IS_OK(result)) {
80 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
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_info += num_dom_users;
92 info = talloc_realloc(mem_ctx,
93 info,
94 struct wbint_userinfo,
95 num_info);
96 if (info == NULL) {
97 return NT_STATUS_NO_MEMORY;
100 for (j = 0; j < num_dom_users; i++, j++) {
101 uint32_t rid = disp_info.info1.entries[j].rid;
102 struct samr_DispEntryGeneral *src;
103 struct wbint_userinfo *dst;
105 src = &(disp_info.info1.entries[j]);
106 dst = &(info[i]);
108 dst->acct_name = talloc_strdup(info,
109 src->account_name.string);
110 if (dst->acct_name == NULL) {
111 return NT_STATUS_NO_MEMORY;
114 dst->full_name = talloc_strdup(info, src->full_name.string);
115 if ((src->full_name.string != NULL) &&
116 (dst->full_name == NULL))
118 return NT_STATUS_NO_MEMORY;
121 dst->homedir = NULL;
122 dst->shell = NULL;
124 sid_compose(&dst->user_sid, domain_sid, rid);
126 /* For the moment we set the primary group for
127 every user to be the Domain Users group.
128 There are serious problems with determining
129 the actual primary group for large domains.
130 This should really be made into a 'winbind
131 force group' smb.conf parameter or
132 something like that. */
133 sid_compose(&dst->group_sid, domain_sid,
134 DOMAIN_RID_USERS);
136 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
138 *pnum_info = num_info;
139 *pinfo = info;
141 return NT_STATUS_OK;
144 /* List all domain groups */
145 NTSTATUS rpc_enum_dom_groups(TALLOC_CTX *mem_ctx,
146 struct rpc_pipe_client *samr_pipe,
147 struct policy_handle *samr_policy,
148 uint32_t *pnum_info,
149 struct wb_acct_info **pinfo)
151 struct wb_acct_info *info = NULL;
152 uint32_t start = 0;
153 uint32_t num_info = 0;
154 NTSTATUS status, result;
155 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
157 *pnum_info = 0;
159 do {
160 struct samr_SamArray *sam_array = NULL;
161 uint32_t count = 0;
162 uint32_t g;
164 /* start is updated by this call. */
165 status = dcerpc_samr_EnumDomainGroups(b,
166 mem_ctx,
167 samr_policy,
168 &start,
169 &sam_array,
170 0xFFFF, /* buffer size? */
171 &count,
172 &result);
173 if (!NT_STATUS_IS_OK(status)) {
174 return status;
176 if (!NT_STATUS_IS_OK(result)) {
177 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
178 DEBUG(2,("query_user_list: failed to enum domain groups: %s\n",
179 nt_errstr(result)));
180 return result;
184 info = talloc_realloc(mem_ctx,
185 info,
186 struct wb_acct_info,
187 num_info + count);
188 if (info == NULL) {
189 return NT_STATUS_NO_MEMORY;
192 for (g = 0; g < count; g++) {
193 fstrcpy(info[num_info + g].acct_name,
194 sam_array->entries[g].name.string);
196 info[num_info + g].rid = sam_array->entries[g].idx;
199 num_info += count;
200 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
202 *pnum_info = num_info;
203 *pinfo = info;
205 return NT_STATUS_OK;
208 NTSTATUS rpc_enum_local_groups(TALLOC_CTX *mem_ctx,
209 struct rpc_pipe_client *samr_pipe,
210 struct policy_handle *samr_policy,
211 uint32_t *pnum_info,
212 struct wb_acct_info **pinfo)
214 struct wb_acct_info *info = NULL;
215 uint32_t num_info = 0;
216 NTSTATUS status, result;
217 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
219 *pnum_info = 0;
221 do {
222 struct samr_SamArray *sam_array = NULL;
223 uint32_t count = 0;
224 uint32_t start = num_info;
225 uint32_t g;
227 status = dcerpc_samr_EnumDomainAliases(b,
228 mem_ctx,
229 samr_policy,
230 &start,
231 &sam_array,
232 0xFFFF, /* buffer size? */
233 &count,
234 &result);
235 if (!NT_STATUS_IS_OK(status)) {
236 return status;
238 if (!NT_STATUS_IS_OK(result)) {
239 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
240 return result;
244 info = talloc_realloc(mem_ctx,
245 info,
246 struct wb_acct_info,
247 num_info + count);
248 if (info == NULL) {
249 return NT_STATUS_NO_MEMORY;
252 for (g = 0; g < count; g++) {
253 fstrcpy(info[num_info + g].acct_name,
254 sam_array->entries[g].name.string);
255 info[num_info + g].rid = sam_array->entries[g].idx;
258 num_info += count;
259 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
261 *pnum_info = num_info;
262 *pinfo = info;
264 return NT_STATUS_OK;
267 /* convert a single name to a sid in a domain */
268 NTSTATUS rpc_name_to_sid(TALLOC_CTX *mem_ctx,
269 struct rpc_pipe_client *lsa_pipe,
270 struct policy_handle *lsa_policy,
271 const char *domain_name,
272 const char *name,
273 uint32_t flags,
274 struct dom_sid *sid,
275 enum lsa_SidType *type)
277 enum lsa_SidType *types = NULL;
278 struct dom_sid *sids = NULL;
279 char *full_name = NULL;
280 char *mapped_name = NULL;
281 NTSTATUS status;
283 if (name == NULL || name[0] == '\0') {
284 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
285 } else if (domain_name == NULL || domain_name[0] == '\0') {
286 full_name = talloc_asprintf(mem_ctx, "%s", name);
287 } else {
288 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
291 if (full_name == NULL) {
292 return NT_STATUS_NO_MEMORY;
295 status = normalize_name_unmap(mem_ctx, full_name, &mapped_name);
296 /* Reset the full_name pointer if we mapped anything */
297 if (NT_STATUS_IS_OK(status) ||
298 NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
299 full_name = mapped_name;
302 DEBUG(3,("name_to_sid: %s for domain %s\n",
303 full_name ? full_name : "", domain_name ));
306 * We don't run into deadlocks here, cause winbind_off() is
307 * called in the main function.
309 status = rpccli_lsa_lookup_names(lsa_pipe,
310 mem_ctx,
311 lsa_policy,
312 1, /* num_names */
313 (const char **) &full_name,
314 NULL, /* domains */
315 1, /* level */
316 &sids,
317 &types);
318 if (!NT_STATUS_IS_OK(status)) {
319 DEBUG(2,("name_to_sid: failed to lookup name: %s\n",
320 nt_errstr(status)));
321 return status;
324 sid_copy(sid, &sids[0]);
325 *type = types[0];
327 return NT_STATUS_OK;
330 /* Convert a domain SID to a user or group name */
331 NTSTATUS rpc_sid_to_name(TALLOC_CTX *mem_ctx,
332 struct rpc_pipe_client *lsa_pipe,
333 struct policy_handle *lsa_policy,
334 struct winbindd_domain *domain,
335 const struct dom_sid *sid,
336 char **pdomain_name,
337 char **pname,
338 enum lsa_SidType *ptype)
340 char *mapped_name = NULL;
341 char **domains = NULL;
342 char **names = NULL;
343 enum lsa_SidType *types = NULL;
344 NTSTATUS map_status;
345 NTSTATUS status;
347 status = rpccli_lsa_lookup_sids(lsa_pipe,
348 mem_ctx,
349 lsa_policy,
350 1, /* num_sids */
351 sid,
352 &domains,
353 &names,
354 &types);
355 if (!NT_STATUS_IS_OK(status)) {
356 DEBUG(2,("sid_to_name: failed to lookup sids: %s\n",
357 nt_errstr(status)));
358 return status;
361 *ptype = (enum lsa_SidType) types[0];
363 map_status = normalize_name_map(mem_ctx,
364 domain,
365 names[0],
366 &mapped_name);
367 if (NT_STATUS_IS_OK(map_status) ||
368 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
369 *pname = talloc_strdup(mem_ctx, mapped_name);
370 DEBUG(5,("returning mapped name -- %s\n", *pname));
371 } else {
372 *pname = talloc_strdup(mem_ctx, names[0]);
374 if ((names[0] != NULL) && (*pname == NULL)) {
375 return NT_STATUS_NO_MEMORY;
378 *pdomain_name = talloc_strdup(mem_ctx, domains[0]);
379 if (*pdomain_name == NULL) {
380 return NT_STATUS_NO_MEMORY;
383 return NT_STATUS_OK;
386 /* Convert a bunch of rids to user or group names */
387 NTSTATUS rpc_rids_to_names(TALLOC_CTX *mem_ctx,
388 struct rpc_pipe_client *lsa_pipe,
389 struct policy_handle *lsa_policy,
390 struct winbindd_domain *domain,
391 const struct dom_sid *sid,
392 uint32_t *rids,
393 size_t num_rids,
394 char **pdomain_name,
395 char ***pnames,
396 enum lsa_SidType **ptypes)
398 enum lsa_SidType *types = NULL;
399 char *domain_name = NULL;
400 char **domains = NULL;
401 char **names = NULL;
402 struct dom_sid *sids;
403 size_t i;
404 NTSTATUS status;
406 if (num_rids > 0) {
407 sids = talloc_array(mem_ctx, struct dom_sid, num_rids);
408 if (sids == NULL) {
409 return NT_STATUS_NO_MEMORY;
411 } else {
412 sids = NULL;
415 for (i = 0; i < num_rids; i++) {
416 if (!sid_compose(&sids[i], sid, rids[i])) {
417 return NT_STATUS_INTERNAL_ERROR;
421 status = rpccli_lsa_lookup_sids(lsa_pipe,
422 mem_ctx,
423 lsa_policy,
424 num_rids,
425 sids,
426 &domains,
427 &names,
428 &types);
429 if (!NT_STATUS_IS_OK(status) &&
430 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
431 DEBUG(2,("rids_to_names: failed to lookup sids: %s\n",
432 nt_errstr(status)));
433 return status;
436 for (i = 0; i < num_rids; i++) {
437 char *mapped_name = NULL;
438 NTSTATUS map_status;
440 if (types[i] != SID_NAME_UNKNOWN) {
441 map_status = normalize_name_map(mem_ctx,
442 domain,
443 names[i],
444 &mapped_name);
445 if (NT_STATUS_IS_OK(map_status) ||
446 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
447 TALLOC_FREE(names[i]);
448 names[i] = talloc_strdup(names, mapped_name);
449 if (names[i] == NULL) {
450 return NT_STATUS_NO_MEMORY;
454 domain_name = domains[i];
458 *pdomain_name = domain_name;
459 *ptypes = types;
460 *pnames = names;
462 return NT_STATUS_OK;
465 /* Lookup user information from a rid or username. */
466 NTSTATUS rpc_query_user(TALLOC_CTX *mem_ctx,
467 struct rpc_pipe_client *samr_pipe,
468 struct policy_handle *samr_policy,
469 const struct dom_sid *domain_sid,
470 const struct dom_sid *user_sid,
471 struct wbint_userinfo *user_info)
473 struct policy_handle user_policy;
474 union samr_UserInfo *info = NULL;
475 uint32_t user_rid;
476 NTSTATUS status, result;
477 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
479 if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
480 return NT_STATUS_UNSUCCESSFUL;
483 /* Get user handle */
484 status = dcerpc_samr_OpenUser(b,
485 mem_ctx,
486 samr_policy,
487 SEC_FLAG_MAXIMUM_ALLOWED,
488 user_rid,
489 &user_policy,
490 &result);
491 if (!NT_STATUS_IS_OK(status)) {
492 return status;
494 if (!NT_STATUS_IS_OK(result)) {
495 return result;
498 /* Get user info */
499 status = dcerpc_samr_QueryUserInfo(b,
500 mem_ctx,
501 &user_policy,
502 0x15,
503 &info,
504 &result);
506 NTSTATUS _result;
507 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
509 if (!NT_STATUS_IS_OK(status)) {
510 return status;
512 if (!NT_STATUS_IS_OK(result)) {
513 return result;
516 sid_compose(&user_info->user_sid, domain_sid, user_rid);
517 sid_compose(&user_info->group_sid, domain_sid,
518 info->info21.primary_gid);
520 user_info->acct_name = talloc_strdup(user_info,
521 info->info21.account_name.string);
522 if (user_info->acct_name == NULL) {
523 return NT_STATUS_NO_MEMORY;
526 user_info->full_name = talloc_strdup(user_info,
527 info->info21.full_name.string);
528 if ((info->info21.full_name.string != NULL) &&
529 (user_info->full_name == NULL))
531 return NT_STATUS_NO_MEMORY;
534 user_info->homedir = NULL;
535 user_info->shell = NULL;
536 user_info->primary_gid = (gid_t)-1;
538 return NT_STATUS_OK;
541 /* Lookup groups a user is a member of. */
542 NTSTATUS rpc_lookup_usergroups(TALLOC_CTX *mem_ctx,
543 struct rpc_pipe_client *samr_pipe,
544 struct policy_handle *samr_policy,
545 const struct dom_sid *domain_sid,
546 const struct dom_sid *user_sid,
547 uint32_t *pnum_groups,
548 struct dom_sid **puser_grpsids)
550 struct policy_handle user_policy;
551 struct samr_RidWithAttributeArray *rid_array = NULL;
552 struct dom_sid *user_grpsids = NULL;
553 uint32_t num_groups = 0, i;
554 uint32_t user_rid;
555 NTSTATUS status, result;
556 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
558 if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
559 return NT_STATUS_UNSUCCESSFUL;
562 /* Get user handle */
563 status = dcerpc_samr_OpenUser(b,
564 mem_ctx,
565 samr_policy,
566 SEC_FLAG_MAXIMUM_ALLOWED,
567 user_rid,
568 &user_policy,
569 &result);
570 if (!NT_STATUS_IS_OK(status)) {
571 return status;
573 if (!NT_STATUS_IS_OK(result)) {
574 return result;
577 /* Query user rids */
578 status = dcerpc_samr_GetGroupsForUser(b,
579 mem_ctx,
580 &user_policy,
581 &rid_array,
582 &result);
584 NTSTATUS _result;
585 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
588 if (!NT_STATUS_IS_OK(status)) {
589 return status;
591 if (!NT_STATUS_IS_OK(result)) {
592 return result;
595 num_groups = rid_array->count;
597 user_grpsids = talloc_array(mem_ctx, struct dom_sid, num_groups);
598 if (user_grpsids == NULL) {
599 status = NT_STATUS_NO_MEMORY;
600 return status;
603 for (i = 0; i < num_groups; i++) {
604 sid_compose(&(user_grpsids[i]), domain_sid,
605 rid_array->rids[i].rid);
608 *pnum_groups = num_groups;
610 *puser_grpsids = user_grpsids;
612 return NT_STATUS_OK;
615 NTSTATUS rpc_lookup_useraliases(TALLOC_CTX *mem_ctx,
616 struct rpc_pipe_client *samr_pipe,
617 struct policy_handle *samr_policy,
618 uint32_t num_sids,
619 const struct dom_sid *sids,
620 uint32_t *pnum_aliases,
621 uint32_t **palias_rids)
623 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
624 uint32_t num_query_sids = 0;
625 uint32_t num_queries = 1;
626 uint32_t num_aliases = 0;
627 uint32_t total_sids = 0;
628 uint32_t *alias_rids = NULL;
629 uint32_t rangesize = MAX_SAM_ENTRIES_W2K;
630 uint32_t i;
631 struct samr_Ids alias_rids_query;
632 NTSTATUS status, result;
633 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
635 do {
636 /* prepare query */
637 struct lsa_SidArray sid_array;
639 ZERO_STRUCT(sid_array);
641 num_query_sids = MIN(num_sids - total_sids, rangesize);
643 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
644 num_queries, num_query_sids));
646 if (num_query_sids) {
647 sid_array.sids = talloc_zero_array(mem_ctx, struct lsa_SidPtr, num_query_sids);
648 if (sid_array.sids == NULL) {
649 return NT_STATUS_NO_MEMORY;
651 } else {
652 sid_array.sids = NULL;
655 for (i = 0; i < num_query_sids; i++) {
656 sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[total_sids++]);
657 if (sid_array.sids[i].sid == NULL) {
658 return NT_STATUS_NO_MEMORY;
661 sid_array.num_sids = num_query_sids;
663 /* do request */
664 status = dcerpc_samr_GetAliasMembership(b,
665 mem_ctx,
666 samr_policy,
667 &sid_array,
668 &alias_rids_query,
669 &result);
670 if (!NT_STATUS_IS_OK(status)) {
671 return status;
673 if (!NT_STATUS_IS_OK(result)) {
674 return result;
677 /* process output */
678 for (i = 0; i < alias_rids_query.count; i++) {
679 size_t na = num_aliases;
681 if (!add_rid_to_array_unique(mem_ctx,
682 alias_rids_query.ids[i],
683 &alias_rids,
684 &na)) {
685 return NT_STATUS_NO_MEMORY;
687 num_aliases = na;
690 num_queries++;
692 } while (total_sids < num_sids);
694 DEBUG(10,("rpc: rpc_lookup_useraliases: got %d aliases in %d queries "
695 "(rangesize: %d)\n", num_aliases, num_queries, rangesize));
697 *pnum_aliases = num_aliases;
698 *palias_rids = alias_rids;
700 return NT_STATUS_OK;
701 #undef MAX_SAM_ENTRIES_W2K
704 /* Lookup group membership given a rid. */
705 NTSTATUS rpc_lookup_groupmem(TALLOC_CTX *mem_ctx,
706 struct rpc_pipe_client *samr_pipe,
707 struct policy_handle *samr_policy,
708 const char *domain_name,
709 const struct dom_sid *domain_sid,
710 const struct dom_sid *group_sid,
711 enum lsa_SidType type,
712 uint32_t *pnum_names,
713 struct dom_sid **psid_mem,
714 char ***pnames,
715 uint32_t **pname_types)
717 struct policy_handle group_policy;
718 uint32_t group_rid;
719 uint32_t *rid_mem = NULL;
721 uint32_t num_names = 0;
722 uint32_t total_names = 0;
723 struct dom_sid *sid_mem = NULL;
724 char **names = NULL;
725 uint32_t *name_types = NULL;
727 struct lsa_Strings tmp_names;
728 struct samr_Ids tmp_types;
730 uint32_t j, r;
731 NTSTATUS status, result;
732 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
734 if (!sid_peek_check_rid(domain_sid, group_sid, &group_rid)) {
735 return NT_STATUS_UNSUCCESSFUL;
738 switch(type) {
739 case SID_NAME_DOM_GRP:
741 struct samr_RidAttrArray *rids = NULL;
743 status = dcerpc_samr_OpenGroup(b,
744 mem_ctx,
745 samr_policy,
746 SEC_FLAG_MAXIMUM_ALLOWED,
747 group_rid,
748 &group_policy,
749 &result);
750 if (!NT_STATUS_IS_OK(status)) {
751 return status;
753 if (!NT_STATUS_IS_OK(result)) {
754 return result;
758 * Step #1: Get a list of user rids that are the members of the group.
760 status = dcerpc_samr_QueryGroupMember(b,
761 mem_ctx,
762 &group_policy,
763 &rids,
764 &result);
766 NTSTATUS _result;
767 dcerpc_samr_Close(b, mem_ctx, &group_policy, &_result);
770 if (!NT_STATUS_IS_OK(status)) {
771 return status;
773 if (!NT_STATUS_IS_OK(result)) {
774 return result;
778 if (rids == NULL || rids->count == 0) {
779 pnum_names = 0;
780 pnames = NULL;
781 pname_types = NULL;
782 psid_mem = NULL;
784 return NT_STATUS_OK;
787 num_names = rids->count;
788 rid_mem = rids->rids;
790 break;
792 case SID_NAME_WKN_GRP:
793 case SID_NAME_ALIAS:
795 struct lsa_SidArray sid_array;
796 struct lsa_SidPtr sid_ptr;
797 struct samr_Ids rids_query;
799 sid_ptr.sid = dom_sid_dup(mem_ctx, group_sid);
800 if (sid_ptr.sid == NULL) {
801 return NT_STATUS_NO_MEMORY;
804 sid_array.num_sids = 1;
805 sid_array.sids = &sid_ptr;
807 status = dcerpc_samr_GetAliasMembership(b,
808 mem_ctx,
809 samr_policy,
810 &sid_array,
811 &rids_query,
812 &result);
813 if (!NT_STATUS_IS_OK(status)) {
814 return status;
816 if (!NT_STATUS_IS_OK(result)) {
817 return result;
820 if (rids_query.count == 0) {
821 pnum_names = 0;
822 pnames = NULL;
823 pname_types = NULL;
824 psid_mem = NULL;
826 return NT_STATUS_OK;
829 num_names = rids_query.count;
830 rid_mem = rids_query.ids;
832 break;
834 default:
835 return NT_STATUS_UNSUCCESSFUL;
839 * Step #2: Convert list of rids into list of usernames.
841 if (num_names > 0) {
842 names = talloc_zero_array(mem_ctx, char *, num_names);
843 name_types = talloc_zero_array(mem_ctx, uint32_t, num_names);
844 sid_mem = talloc_zero_array(mem_ctx, struct dom_sid, num_names);
845 if (names == NULL || name_types == NULL || sid_mem == NULL) {
846 return NT_STATUS_NO_MEMORY;
850 for (j = 0; j < num_names; j++) {
851 sid_compose(&sid_mem[j], domain_sid, rid_mem[j]);
854 status = dcerpc_samr_LookupRids(b,
855 mem_ctx,
856 samr_policy,
857 num_names,
858 rid_mem,
859 &tmp_names,
860 &tmp_types,
861 &result);
862 if (!NT_STATUS_IS_OK(status)) {
863 return status;
866 if (!NT_STATUS_IS_OK(result)) {
867 if (!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
868 return result;
872 /* Copy result into array. The talloc system will take
873 care of freeing the temporary arrays later on. */
874 if (tmp_names.count != num_names) {
875 return NT_STATUS_INVALID_NETWORK_RESPONSE;
877 if (tmp_types.count != num_names) {
878 return NT_STATUS_INVALID_NETWORK_RESPONSE;
881 for (r = 0; r < tmp_names.count; r++) {
882 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
883 continue;
885 if (total_names >= num_names) {
886 break;
888 names[total_names] = fill_domain_username_talloc(names,
889 domain_name,
890 tmp_names.names[r].string,
891 true);
892 if (names[total_names] == NULL) {
893 return NT_STATUS_NO_MEMORY;
895 name_types[total_names] = tmp_types.ids[r];
896 total_names++;
899 *pnum_names = total_names;
900 *pnames = names;
901 *pname_types = name_types;
902 *psid_mem = sid_mem;
904 return NT_STATUS_OK;
907 /* Find the sequence number for a domain */
908 NTSTATUS rpc_sequence_number(TALLOC_CTX *mem_ctx,
909 struct rpc_pipe_client *samr_pipe,
910 struct policy_handle *samr_policy,
911 const char *domain_name,
912 uint32_t *pseq)
914 union samr_DomainInfo *info = NULL;
915 bool got_seq_num = false;
916 NTSTATUS status, result;
917 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
919 /* query domain info */
920 status = dcerpc_samr_QueryDomainInfo(b,
921 mem_ctx,
922 samr_policy,
924 &info,
925 &result);
926 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
927 *pseq = info->info8.sequence_num;
928 got_seq_num = true;
929 goto seq_num;
932 /* retry with info-level 2 in case the dc does not support info-level 8
933 * (like all older samba2 and samba3 dc's) - Guenther */
934 status = dcerpc_samr_QueryDomainInfo(b,
935 mem_ctx,
936 samr_policy,
938 &info,
939 &result);
940 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
941 *pseq = info->general.sequence_num;
942 got_seq_num = true;
943 goto seq_num;
946 if (!NT_STATUS_IS_OK(status)) {
947 goto seq_num;
950 status = result;
952 seq_num:
953 if (got_seq_num) {
954 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
955 domain_name, (unsigned) *pseq));
956 } else {
957 DEBUG(10,("domain_sequence_number: failed to get sequence "
958 "number (%u) for domain %s\n",
959 (unsigned) *pseq, domain_name ));
960 status = NT_STATUS_OK;
963 return status;
966 /* Get a list of trusted domains */
967 NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
968 struct rpc_pipe_client *lsa_pipe,
969 struct policy_handle *lsa_policy,
970 uint32_t *pnum_trusts,
971 struct netr_DomainTrust **ptrusts)
973 struct netr_DomainTrust *array = NULL;
974 uint32_t enum_ctx = 0;
975 uint32_t count = 0;
976 NTSTATUS status, result;
977 struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
979 do {
980 struct lsa_DomainList dom_list;
981 struct lsa_DomainListEx dom_list_ex;
982 bool has_ex = false;
983 uint32_t i;
986 * We don't run into deadlocks here, cause winbind_off() is
987 * called in the main function.
989 status = dcerpc_lsa_EnumTrustedDomainsEx(b,
990 mem_ctx,
991 lsa_policy,
992 &enum_ctx,
993 &dom_list_ex,
994 (uint32_t) -1,
995 &result);
996 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_ERR(result) &&
997 dom_list_ex.count > 0) {
998 count += dom_list_ex.count;
999 has_ex = true;
1000 } else {
1001 status = dcerpc_lsa_EnumTrustDom(b,
1002 mem_ctx,
1003 lsa_policy,
1004 &enum_ctx,
1005 &dom_list,
1006 (uint32_t) -1,
1007 &result);
1008 if (!NT_STATUS_IS_OK(status)) {
1009 return status;
1011 if (!NT_STATUS_IS_OK(result)) {
1012 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1013 return result;
1017 count += dom_list.count;
1020 array = talloc_realloc(mem_ctx,
1021 array,
1022 struct netr_DomainTrust,
1023 count);
1024 if (array == NULL) {
1025 return NT_STATUS_NO_MEMORY;
1028 for (i = 0; i < count; i++) {
1029 struct netr_DomainTrust *trust = &array[i];
1030 struct dom_sid *sid;
1032 ZERO_STRUCTP(trust);
1034 sid = talloc(array, struct dom_sid);
1035 if (sid == NULL) {
1036 return NT_STATUS_NO_MEMORY;
1039 if (has_ex) {
1040 trust->netbios_name = talloc_move(array,
1041 &dom_list_ex.domains[i].netbios_name.string);
1042 trust->dns_name = talloc_move(array,
1043 &dom_list_ex.domains[i].domain_name.string);
1045 sid_copy(sid, dom_list_ex.domains[i].sid);
1046 } else {
1047 trust->netbios_name = talloc_move(array,
1048 &dom_list.domains[i].name.string);
1049 trust->dns_name = NULL;
1051 sid_copy(sid, dom_list.domains[i].sid);
1054 trust->sid = sid;
1056 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1058 *pnum_trusts = count;
1059 *ptrusts = array;
1061 return NT_STATUS_OK;
1064 static NTSTATUS rpc_try_lookup_sids3(TALLOC_CTX *mem_ctx,
1065 struct winbindd_domain *domain,
1066 struct rpc_pipe_client *cli,
1067 struct lsa_SidArray *sids,
1068 struct lsa_RefDomainList **pdomains,
1069 struct lsa_TransNameArray **pnames)
1071 struct lsa_TransNameArray2 lsa_names2;
1072 struct lsa_TransNameArray *names = *pnames;
1073 uint32_t i, count;
1074 NTSTATUS status, result;
1076 ZERO_STRUCT(lsa_names2);
1077 status = dcerpc_lsa_LookupSids3(cli->binding_handle,
1078 mem_ctx,
1079 sids,
1080 pdomains,
1081 &lsa_names2,
1082 LSA_LOOKUP_NAMES_ALL,
1083 &count,
1084 LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
1085 LSA_CLIENT_REVISION_2,
1086 &result);
1087 if (!NT_STATUS_IS_OK(status)) {
1088 return status;
1090 if (NT_STATUS_IS_ERR(result)) {
1091 return result;
1093 if (sids->num_sids != lsa_names2.count) {
1094 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1097 names->count = lsa_names2.count;
1098 names->names = talloc_array(names, struct lsa_TranslatedName,
1099 names->count);
1100 if (names->names == NULL) {
1101 return NT_STATUS_NO_MEMORY;
1103 for (i=0; i<names->count; i++) {
1104 names->names[i].sid_type = lsa_names2.names[i].sid_type;
1105 names->names[i].name.string = talloc_move(
1106 names->names, &lsa_names2.names[i].name.string);
1107 names->names[i].sid_index = lsa_names2.names[i].sid_index;
1109 if (names->names[i].sid_index == UINT32_MAX) {
1110 continue;
1112 if ((*pdomains) == NULL) {
1113 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1115 if (names->names[i].sid_index >= (*pdomains)->count) {
1116 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1119 return result;
1122 NTSTATUS rpc_lookup_sids(TALLOC_CTX *mem_ctx,
1123 struct winbindd_domain *domain,
1124 struct lsa_SidArray *sids,
1125 struct lsa_RefDomainList **pdomains,
1126 struct lsa_TransNameArray **pnames)
1128 struct lsa_TransNameArray *names = *pnames;
1129 struct rpc_pipe_client *cli = NULL;
1130 struct policy_handle lsa_policy;
1131 uint32_t count;
1132 uint32_t i;
1133 NTSTATUS status, result;
1135 status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
1136 if (!NT_STATUS_IS_OK(status)) {
1137 return status;
1140 if (cli->transport->transport == NCACN_IP_TCP) {
1141 return rpc_try_lookup_sids3(mem_ctx, domain, cli, sids,
1142 pdomains, pnames);
1145 status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
1146 &lsa_policy, sids, pdomains,
1147 names, LSA_LOOKUP_NAMES_ALL,
1148 &count, &result);
1149 if (!NT_STATUS_IS_OK(status)) {
1150 return status;
1152 if (NT_STATUS_IS_ERR(result)) {
1153 return result;
1156 if (sids->num_sids != names->count) {
1157 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1160 for (i=0; i < names->count; i++) {
1161 if (names->names[i].sid_index == UINT32_MAX) {
1162 continue;
1164 if ((*pdomains) == NULL) {
1165 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1167 if (names->names[i].sid_index >= (*pdomains)->count) {
1168 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1172 return result;