tevent: Add lib/tevent as include directory.
[Samba.git] / source3 / winbindd / winbindd_rpc.c
blob5efd57e21955ac1ac413562bbba79bda5b6490b5
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"
30 #include "librpc/gen_ndr/ndr_samr_c.h"
31 #include "librpc/gen_ndr/srv_samr.h"
32 #include "librpc/gen_ndr/ndr_lsa_c.h"
33 #include "librpc/gen_ndr/srv_lsa.h"
34 #include "rpc_client/cli_samr.h"
35 #include "rpc_client/cli_lsarpc.h"
36 #include "../libcli/security/security.h"
38 /* Query display info for a domain */
39 NTSTATUS rpc_query_user_list(TALLOC_CTX *mem_ctx,
40 struct rpc_pipe_client *samr_pipe,
41 struct policy_handle *samr_policy,
42 const struct dom_sid *domain_sid,
43 uint32_t *pnum_info,
44 struct wbint_userinfo **pinfo)
46 struct wbint_userinfo *info = NULL;
47 uint32_t num_info = 0;
48 uint32_t loop_count = 0;
49 uint32_t start_idx = 0;
50 uint32_t i = 0;
51 NTSTATUS status, result;
52 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
54 *pnum_info = 0;
56 do {
57 uint32_t j;
58 uint32_t num_dom_users;
59 uint32_t max_entries, max_size;
60 uint32_t total_size, returned_size;
61 union samr_DispInfo disp_info;
63 dcerpc_get_query_dispinfo_params(loop_count,
64 &max_entries,
65 &max_size);
67 status = dcerpc_samr_QueryDisplayInfo(b,
68 mem_ctx,
69 samr_policy,
70 1, /* level */
71 start_idx,
72 max_entries,
73 max_size,
74 &total_size,
75 &returned_size,
76 &disp_info,
77 &result);
78 if (!NT_STATUS_IS_OK(status)) {
79 return status;
81 if (!NT_STATUS_IS_OK(result)) {
82 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
83 return result;
87 /* increment required start query values */
88 start_idx += disp_info.info1.count;
89 loop_count++;
90 num_dom_users = disp_info.info1.count;
92 num_info += num_dom_users;
94 info = TALLOC_REALLOC_ARRAY(mem_ctx,
95 info,
96 struct wbint_userinfo,
97 num_info);
98 if (info == NULL) {
99 return NT_STATUS_NO_MEMORY;
102 for (j = 0; j < num_dom_users; i++, j++) {
103 uint32_t rid = disp_info.info1.entries[j].rid;
104 struct samr_DispEntryGeneral *src;
105 struct wbint_userinfo *dst;
107 src = &(disp_info.info1.entries[j]);
108 dst = &(info[i]);
110 dst->acct_name = talloc_strdup(info,
111 src->account_name.string);
112 if (dst->acct_name == NULL) {
113 return NT_STATUS_NO_MEMORY;
116 dst->full_name = talloc_strdup(info, src->full_name.string);
117 if ((src->full_name.string != NULL) &&
118 (dst->full_name == NULL))
120 return NT_STATUS_NO_MEMORY;
123 dst->homedir = NULL;
124 dst->shell = NULL;
126 sid_compose(&dst->user_sid, domain_sid, rid);
128 /* For the moment we set the primary group for
129 every user to be the Domain Users group.
130 There are serious problems with determining
131 the actual primary group for large domains.
132 This should really be made into a 'winbind
133 force group' smb.conf parameter or
134 something like that. */
135 sid_compose(&dst->group_sid, domain_sid,
136 DOMAIN_RID_USERS);
138 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
140 *pnum_info = num_info;
141 *pinfo = info;
143 return NT_STATUS_OK;
146 /* List all domain groups */
147 NTSTATUS rpc_enum_dom_groups(TALLOC_CTX *mem_ctx,
148 struct rpc_pipe_client *samr_pipe,
149 struct policy_handle *samr_policy,
150 uint32_t *pnum_info,
151 struct acct_info **pinfo)
153 struct acct_info *info = NULL;
154 uint32_t start = 0;
155 uint32_t num_info = 0;
156 NTSTATUS status, result;
157 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
159 *pnum_info = 0;
161 do {
162 struct samr_SamArray *sam_array = NULL;
163 uint32_t count = 0;
164 uint32_t g;
166 /* start is updated by this call. */
167 status = dcerpc_samr_EnumDomainGroups(b,
168 mem_ctx,
169 samr_policy,
170 &start,
171 &sam_array,
172 0xFFFF, /* buffer size? */
173 &count,
174 &result);
175 if (!NT_STATUS_IS_OK(status)) {
176 return status;
178 if (!NT_STATUS_IS_OK(result)) {
179 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
180 DEBUG(2,("query_user_list: failed to enum domain groups: %s\n",
181 nt_errstr(result)));
182 return result;
186 info = TALLOC_REALLOC_ARRAY(mem_ctx,
187 info,
188 struct acct_info,
189 num_info + count);
190 if (info == NULL) {
191 return NT_STATUS_NO_MEMORY;
194 for (g = 0; g < count; g++) {
195 fstrcpy(info[num_info + g].acct_name,
196 sam_array->entries[g].name.string);
198 info[num_info + g].rid = sam_array->entries[g].idx;
201 num_info += count;
202 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
204 *pnum_info = num_info;
205 *pinfo = info;
207 return NT_STATUS_OK;
210 NTSTATUS rpc_enum_local_groups(TALLOC_CTX *mem_ctx,
211 struct rpc_pipe_client *samr_pipe,
212 struct policy_handle *samr_policy,
213 uint32_t *pnum_info,
214 struct acct_info **pinfo)
216 struct acct_info *info = NULL;
217 uint32_t num_info = 0;
218 NTSTATUS status, result;
219 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
221 *pnum_info = 0;
223 do {
224 struct samr_SamArray *sam_array = NULL;
225 uint32_t count = 0;
226 uint32_t start = num_info;
227 uint32_t g;
229 status = dcerpc_samr_EnumDomainAliases(b,
230 mem_ctx,
231 samr_policy,
232 &start,
233 &sam_array,
234 0xFFFF, /* buffer size? */
235 &count,
236 &result);
237 if (!NT_STATUS_IS_OK(status)) {
238 return status;
240 if (!NT_STATUS_IS_OK(result)) {
241 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
242 return result;
246 info = TALLOC_REALLOC_ARRAY(mem_ctx,
247 info,
248 struct acct_info,
249 num_info + count);
250 if (info == NULL) {
251 return NT_STATUS_NO_MEMORY;
254 for (g = 0; g < count; g++) {
255 fstrcpy(info[num_info + g].acct_name,
256 sam_array->entries[g].name.string);
257 info[num_info + g].rid = sam_array->entries[g].idx;
260 num_info += count;
261 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
263 *pnum_info = num_info;
264 *pinfo = info;
266 return NT_STATUS_OK;
269 /* convert a single name to a sid in a domain */
270 NTSTATUS rpc_name_to_sid(TALLOC_CTX *mem_ctx,
271 struct rpc_pipe_client *lsa_pipe,
272 struct policy_handle *lsa_policy,
273 const char *domain_name,
274 const char *name,
275 uint32_t flags,
276 struct dom_sid *sid,
277 enum lsa_SidType *type)
279 enum lsa_SidType *types = NULL;
280 struct dom_sid *sids = NULL;
281 char *full_name = NULL;
282 char *mapped_name = NULL;
283 NTSTATUS status;
285 if (name == NULL || name[0] == '\0') {
286 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
287 } else if (domain_name == NULL || domain_name[0] == '\0') {
288 full_name = talloc_asprintf(mem_ctx, "%s", name);
289 } else {
290 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
293 if (full_name == NULL) {
294 return NT_STATUS_NO_MEMORY;
297 status = normalize_name_unmap(mem_ctx, full_name, &mapped_name);
298 /* Reset the full_name pointer if we mapped anything */
299 if (NT_STATUS_IS_OK(status) ||
300 NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
301 full_name = mapped_name;
304 DEBUG(3,("name_to_sid: %s for domain %s\n",
305 full_name ? full_name : "", domain_name ));
308 * We don't run into deadlocks here, cause winbind_off() is
309 * called in the main function.
311 status = rpccli_lsa_lookup_names(lsa_pipe,
312 mem_ctx,
313 lsa_policy,
314 1, /* num_names */
315 (const char **) &full_name,
316 NULL, /* domains */
317 1, /* level */
318 &sids,
319 &types);
320 if (!NT_STATUS_IS_OK(status)) {
321 DEBUG(2,("name_to_sid: failed to lookup name: %s\n",
322 nt_errstr(status)));
323 return status;
326 sid_copy(sid, &sids[0]);
327 *type = types[0];
329 return NT_STATUS_OK;
332 /* Convert a domain SID to a user or group name */
333 NTSTATUS rpc_sid_to_name(TALLOC_CTX *mem_ctx,
334 struct rpc_pipe_client *lsa_pipe,
335 struct policy_handle *lsa_policy,
336 struct winbindd_domain *domain,
337 const struct dom_sid *sid,
338 char **pdomain_name,
339 char **pname,
340 enum lsa_SidType *ptype)
342 char *mapped_name = NULL;
343 char **domains = NULL;
344 char **names = NULL;
345 enum lsa_SidType *types = NULL;
346 NTSTATUS map_status;
347 NTSTATUS status;
349 status = rpccli_lsa_lookup_sids(lsa_pipe,
350 mem_ctx,
351 lsa_policy,
352 1, /* num_sids */
353 sid,
354 &domains,
355 &names,
356 &types);
357 if (!NT_STATUS_IS_OK(status)) {
358 DEBUG(2,("sid_to_name: failed to lookup sids: %s\n",
359 nt_errstr(status)));
360 return status;
363 *ptype = (enum lsa_SidType) types[0];
365 map_status = normalize_name_map(mem_ctx,
366 domain,
367 *pname,
368 &mapped_name);
369 if (NT_STATUS_IS_OK(map_status) ||
370 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
371 *pname = talloc_strdup(mem_ctx, mapped_name);
372 DEBUG(5,("returning mapped name -- %s\n", *pname));
373 } else {
374 *pname = talloc_strdup(mem_ctx, names[0]);
376 if (*pname == NULL) {
377 return NT_STATUS_NO_MEMORY;
380 *pdomain_name = talloc_strdup(mem_ctx, domains[0]);
381 if (*pdomain_name == NULL) {
382 return NT_STATUS_NO_MEMORY;
385 return NT_STATUS_OK;
388 /* Convert a bunch of rids to user or group names */
389 NTSTATUS rpc_rids_to_names(TALLOC_CTX *mem_ctx,
390 struct rpc_pipe_client *lsa_pipe,
391 struct policy_handle *lsa_policy,
392 struct winbindd_domain *domain,
393 const struct dom_sid *sid,
394 uint32_t *rids,
395 size_t num_rids,
396 char **pdomain_name,
397 char ***pnames,
398 enum lsa_SidType **ptypes)
400 enum lsa_SidType *types = NULL;
401 char *domain_name = NULL;
402 char **domains = NULL;
403 char **names = NULL;
404 struct dom_sid *sids;
405 size_t i;
406 NTSTATUS status;
408 if (num_rids > 0) {
409 sids = TALLOC_ARRAY(mem_ctx, struct dom_sid, num_rids);
410 if (sids == NULL) {
411 return NT_STATUS_NO_MEMORY;
413 } else {
414 sids = NULL;
417 for (i = 0; i < num_rids; i++) {
418 if (!sid_compose(&sids[i], sid, rids[i])) {
419 return NT_STATUS_INTERNAL_ERROR;
423 status = rpccli_lsa_lookup_sids(lsa_pipe,
424 mem_ctx,
425 lsa_policy,
426 num_rids,
427 sids,
428 &domains,
429 &names,
430 &types);
431 if (!NT_STATUS_IS_OK(status) &&
432 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
433 DEBUG(2,("rids_to_names: failed to lookup sids: %s\n",
434 nt_errstr(status)));
435 return status;
438 for (i = 0; i < num_rids; i++) {
439 char *mapped_name = NULL;
440 NTSTATUS map_status;
442 if (types[i] != SID_NAME_UNKNOWN) {
443 map_status = normalize_name_map(mem_ctx,
444 domain,
445 names[i],
446 &mapped_name);
447 if (NT_STATUS_IS_OK(map_status) ||
448 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
449 TALLOC_FREE(names[i]);
450 names[i] = talloc_strdup(names, mapped_name);
451 if (names[i] == NULL) {
452 return NT_STATUS_NO_MEMORY;
456 domain_name = domains[i];
460 *pdomain_name = domain_name;
461 *ptypes = types;
462 *pnames = names;
464 return NT_STATUS_OK;
467 /* Lookup user information from a rid or username. */
468 NTSTATUS rpc_query_user(TALLOC_CTX *mem_ctx,
469 struct rpc_pipe_client *samr_pipe,
470 struct policy_handle *samr_policy,
471 const struct dom_sid *domain_sid,
472 const struct dom_sid *user_sid,
473 struct wbint_userinfo *user_info)
475 struct policy_handle user_policy;
476 union samr_UserInfo *info = NULL;
477 uint32_t user_rid;
478 NTSTATUS status, result;
479 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
481 if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
482 return NT_STATUS_UNSUCCESSFUL;
485 /* Get user handle */
486 status = dcerpc_samr_OpenUser(b,
487 mem_ctx,
488 samr_policy,
489 SEC_FLAG_MAXIMUM_ALLOWED,
490 user_rid,
491 &user_policy,
492 &result);
493 if (!NT_STATUS_IS_OK(status)) {
494 return status;
496 if (!NT_STATUS_IS_OK(result)) {
497 return result;
500 /* Get user info */
501 status = dcerpc_samr_QueryUserInfo(b,
502 mem_ctx,
503 &user_policy,
504 0x15,
505 &info,
506 &result);
508 NTSTATUS _result;
509 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
511 if (!NT_STATUS_IS_OK(status)) {
512 return status;
514 if (!NT_STATUS_IS_OK(result)) {
515 return result;
518 sid_compose(&user_info->user_sid, domain_sid, user_rid);
519 sid_compose(&user_info->group_sid, domain_sid,
520 info->info21.primary_gid);
522 user_info->acct_name = talloc_strdup(user_info,
523 info->info21.account_name.string);
524 if (user_info->acct_name == NULL) {
525 return NT_STATUS_NO_MEMORY;
528 user_info->full_name = talloc_strdup(user_info,
529 info->info21.full_name.string);
530 if ((info->info21.full_name.string != NULL) &&
531 (user_info->acct_name == NULL))
533 return NT_STATUS_NO_MEMORY;
536 user_info->homedir = NULL;
537 user_info->shell = NULL;
538 user_info->primary_gid = (gid_t)-1;
540 return NT_STATUS_OK;
543 /* Lookup groups a user is a member of. */
544 NTSTATUS rpc_lookup_usergroups(TALLOC_CTX *mem_ctx,
545 struct rpc_pipe_client *samr_pipe,
546 struct policy_handle *samr_policy,
547 const struct dom_sid *domain_sid,
548 const struct dom_sid *user_sid,
549 uint32_t *pnum_groups,
550 struct dom_sid **puser_grpsids)
552 struct policy_handle user_policy;
553 struct samr_RidWithAttributeArray *rid_array = NULL;
554 struct dom_sid *user_grpsids = NULL;
555 uint32_t num_groups = 0, i;
556 uint32_t user_rid;
557 NTSTATUS status, result;
558 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
560 if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
561 return NT_STATUS_UNSUCCESSFUL;
564 /* Get user handle */
565 status = dcerpc_samr_OpenUser(b,
566 mem_ctx,
567 samr_policy,
568 SEC_FLAG_MAXIMUM_ALLOWED,
569 user_rid,
570 &user_policy,
571 &result);
572 if (!NT_STATUS_IS_OK(status)) {
573 return status;
575 if (!NT_STATUS_IS_OK(result)) {
576 return result;
579 /* Query user rids */
580 status = dcerpc_samr_GetGroupsForUser(b,
581 mem_ctx,
582 &user_policy,
583 &rid_array,
584 &result);
585 num_groups = rid_array->count;
588 NTSTATUS _result;
589 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
592 if (!NT_STATUS_IS_OK(status)) {
593 return status;
595 if (!NT_STATUS_IS_OK(result) || num_groups == 0) {
596 return result;
599 user_grpsids = TALLOC_ARRAY(mem_ctx, struct dom_sid, num_groups);
600 if (user_grpsids == NULL) {
601 status = NT_STATUS_NO_MEMORY;
602 return status;
605 for (i = 0; i < num_groups; i++) {
606 sid_compose(&(user_grpsids[i]), domain_sid,
607 rid_array->rids[i].rid);
610 *pnum_groups = num_groups;
612 *puser_grpsids = user_grpsids;
614 return NT_STATUS_OK;
617 NTSTATUS rpc_lookup_useraliases(TALLOC_CTX *mem_ctx,
618 struct rpc_pipe_client *samr_pipe,
619 struct policy_handle *samr_policy,
620 uint32_t num_sids,
621 const struct dom_sid *sids,
622 uint32_t *pnum_aliases,
623 uint32_t **palias_rids)
625 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
626 uint32_t num_query_sids = 0;
627 uint32_t num_queries = 1;
628 uint32_t num_aliases = 0;
629 uint32_t total_sids = 0;
630 uint32_t *alias_rids = NULL;
631 uint32_t rangesize = MAX_SAM_ENTRIES_W2K;
632 uint32_t i;
633 struct samr_Ids alias_rids_query;
634 NTSTATUS status, result;
635 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
637 do {
638 /* prepare query */
639 struct lsa_SidArray sid_array;
641 ZERO_STRUCT(sid_array);
643 num_query_sids = MIN(num_sids - total_sids, rangesize);
645 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
646 num_queries, num_query_sids));
648 if (num_query_sids) {
649 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
650 if (sid_array.sids == NULL) {
651 return NT_STATUS_NO_MEMORY;
653 } else {
654 sid_array.sids = NULL;
657 for (i = 0; i < num_query_sids; i++) {
658 sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[total_sids++]);
659 if (sid_array.sids[i].sid == NULL) {
660 return NT_STATUS_NO_MEMORY;
663 sid_array.num_sids = num_query_sids;
665 /* do request */
666 status = dcerpc_samr_GetAliasMembership(b,
667 mem_ctx,
668 samr_policy,
669 &sid_array,
670 &alias_rids_query,
671 &result);
672 if (!NT_STATUS_IS_OK(status)) {
673 return status;
675 if (!NT_STATUS_IS_OK(result)) {
676 return result;
679 /* process output */
680 for (i = 0; i < alias_rids_query.count; i++) {
681 size_t na = num_aliases;
683 if (!add_rid_to_array_unique(mem_ctx,
684 alias_rids_query.ids[i],
685 &alias_rids,
686 &na)) {
687 return NT_STATUS_NO_MEMORY;
689 num_aliases = na;
692 num_queries++;
694 } while (total_sids < num_sids);
696 DEBUG(10,("rpc: rpc_lookup_useraliases: got %d aliases in %d queries "
697 "(rangesize: %d)\n", num_aliases, num_queries, rangesize));
699 *pnum_aliases = num_aliases;
700 *palias_rids = alias_rids;
702 return NT_STATUS_OK;
703 #undef MAX_SAM_ENTRIES_W2K
706 /* Lookup group membership given a rid. */
707 NTSTATUS rpc_lookup_groupmem(TALLOC_CTX *mem_ctx,
708 struct rpc_pipe_client *samr_pipe,
709 struct policy_handle *samr_policy,
710 const char *domain_name,
711 const struct dom_sid *domain_sid,
712 const struct dom_sid *group_sid,
713 enum lsa_SidType type,
714 uint32_t *pnum_names,
715 struct dom_sid **psid_mem,
716 char ***pnames,
717 uint32_t **pname_types)
719 struct policy_handle group_policy;
720 uint32_t group_rid;
721 uint32_t *rid_mem = NULL;
723 uint32_t num_names = 0;
724 uint32_t total_names = 0;
725 struct dom_sid *sid_mem = NULL;
726 char **names = NULL;
727 uint32_t *name_types = NULL;
729 struct lsa_Strings tmp_names;
730 struct samr_Ids tmp_types;
732 uint32_t j, r;
733 NTSTATUS status, result;
734 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
736 if (!sid_peek_check_rid(domain_sid, group_sid, &group_rid)) {
737 return NT_STATUS_UNSUCCESSFUL;
740 switch(type) {
741 case SID_NAME_DOM_GRP:
743 struct samr_RidAttrArray *rids = NULL;
745 status = dcerpc_samr_OpenGroup(b,
746 mem_ctx,
747 samr_policy,
748 SEC_FLAG_MAXIMUM_ALLOWED,
749 group_rid,
750 &group_policy,
751 &result);
752 if (!NT_STATUS_IS_OK(status)) {
753 return status;
755 if (!NT_STATUS_IS_OK(result)) {
756 return result;
760 * Step #1: Get a list of user rids that are the members of the group.
762 status = dcerpc_samr_QueryGroupMember(b,
763 mem_ctx,
764 &group_policy,
765 &rids,
766 &result);
768 NTSTATUS _result;
769 dcerpc_samr_Close(b, mem_ctx, &group_policy, &_result);
772 if (!NT_STATUS_IS_OK(status)) {
773 return status;
775 if (!NT_STATUS_IS_OK(result)) {
776 return result;
780 if (rids == NULL || rids->count == 0) {
781 pnum_names = 0;
782 pnames = NULL;
783 pname_types = NULL;
784 psid_mem = NULL;
786 return NT_STATUS_OK;
789 num_names = rids->count;
790 rid_mem = rids->rids;
792 break;
794 case SID_NAME_WKN_GRP:
795 case SID_NAME_ALIAS:
797 struct lsa_SidArray sid_array;
798 struct lsa_SidPtr sid_ptr;
799 struct samr_Ids rids_query;
801 sid_ptr.sid = dom_sid_dup(mem_ctx, group_sid);
802 if (sid_ptr.sid == NULL) {
803 return NT_STATUS_NO_MEMORY;
806 sid_array.num_sids = 1;
807 sid_array.sids = &sid_ptr;
809 status = dcerpc_samr_GetAliasMembership(b,
810 mem_ctx,
811 samr_policy,
812 &sid_array,
813 &rids_query,
814 &result);
815 if (!NT_STATUS_IS_OK(status)) {
816 return status;
818 if (!NT_STATUS_IS_OK(result)) {
819 return result;
822 if (rids_query.count == 0) {
823 pnum_names = 0;
824 pnames = NULL;
825 pname_types = NULL;
826 psid_mem = NULL;
828 return NT_STATUS_OK;
831 num_names = rids_query.count;
832 rid_mem = rids_query.ids;
834 break;
836 default:
837 return NT_STATUS_UNSUCCESSFUL;
841 * Step #2: Convert list of rids into list of usernames.
843 if (num_names > 0) {
844 names = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_names);
845 name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32_t, num_names);
846 sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, num_names);
847 if (names == NULL || name_types == NULL || sid_mem == NULL) {
848 return NT_STATUS_NO_MEMORY;
852 for (j = 0; j < num_names; j++) {
853 sid_compose(&sid_mem[j], domain_sid, rid_mem[j]);
856 status = dcerpc_samr_LookupRids(b,
857 mem_ctx,
858 samr_policy,
859 num_names,
860 rid_mem,
861 &tmp_names,
862 &tmp_types,
863 &result);
864 if (!NT_STATUS_IS_OK(status)) {
865 return status;
868 if (!NT_STATUS_IS_OK(result)) {
869 if (!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
870 return result;
874 /* Copy result into array. The talloc system will take
875 care of freeing the temporary arrays later on. */
876 if (tmp_names.count != tmp_types.count) {
877 return NT_STATUS_UNSUCCESSFUL;
880 for (r = 0; r < tmp_names.count; r++) {
881 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
882 continue;
884 names[total_names] = fill_domain_username_talloc(names,
885 domain_name,
886 tmp_names.names[r].string,
887 true);
888 if (names[total_names] == NULL) {
889 return NT_STATUS_NO_MEMORY;
891 name_types[total_names] = tmp_types.ids[r];
892 total_names++;
895 *pnum_names = total_names;
896 *pnames = names;
897 *pname_types = name_types;
898 *psid_mem = sid_mem;
900 return NT_STATUS_OK;
903 /* Find the sequence number for a domain */
904 NTSTATUS rpc_sequence_number(TALLOC_CTX *mem_ctx,
905 struct rpc_pipe_client *samr_pipe,
906 struct policy_handle *samr_policy,
907 const char *domain_name,
908 uint32_t *pseq)
910 union samr_DomainInfo *info = NULL;
911 bool got_seq_num = false;
912 NTSTATUS status, result;
913 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
915 /* query domain info */
916 status = dcerpc_samr_QueryDomainInfo(b,
917 mem_ctx,
918 samr_policy,
920 &info,
921 &result);
922 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
923 *pseq = info->info8.sequence_num;
924 got_seq_num = true;
925 goto seq_num;
928 /* retry with info-level 2 in case the dc does not support info-level 8
929 * (like all older samba2 and samba3 dc's) - Guenther */
930 status = dcerpc_samr_QueryDomainInfo(b,
931 mem_ctx,
932 samr_policy,
934 &info,
935 &result);
936 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
937 *pseq = info->general.sequence_num;
938 got_seq_num = true;
939 goto seq_num;
942 if (!NT_STATUS_IS_OK(status)) {
943 goto seq_num;
946 status = result;
948 seq_num:
949 if (got_seq_num) {
950 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
951 domain_name, (unsigned) *pseq));
952 } else {
953 DEBUG(10,("domain_sequence_number: failed to get sequence "
954 "number (%u) for domain %s\n",
955 (unsigned) *pseq, domain_name ));
956 status = NT_STATUS_OK;
959 return status;
962 /* Get a list of trusted domains */
963 NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
964 struct rpc_pipe_client *lsa_pipe,
965 struct policy_handle *lsa_policy,
966 uint32_t *pnum_trusts,
967 struct netr_DomainTrust **ptrusts)
969 struct netr_DomainTrust *array = NULL;
970 uint32_t enum_ctx = 0;
971 uint32_t count = 0;
972 NTSTATUS status, result;
973 struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
975 do {
976 struct lsa_DomainList dom_list;
977 uint32_t start_idx;
978 uint32_t i;
981 * We don't run into deadlocks here, cause winbind_off() is
982 * called in the main function.
984 status = dcerpc_lsa_EnumTrustDom(b,
985 mem_ctx,
986 lsa_policy,
987 &enum_ctx,
988 &dom_list,
989 (uint32_t) -1,
990 &result);
991 if (!NT_STATUS_IS_OK(status)) {
992 return status;
994 if (!NT_STATUS_IS_OK(result)) {
995 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
996 return result;
1000 start_idx = count;
1001 count += dom_list.count;
1003 array = talloc_realloc(mem_ctx,
1004 array,
1005 struct netr_DomainTrust,
1006 count);
1007 if (array == NULL) {
1008 return NT_STATUS_NO_MEMORY;
1011 for (i = 0; i < dom_list.count; i++) {
1012 struct netr_DomainTrust *trust = &array[i];
1013 struct dom_sid *sid;
1015 ZERO_STRUCTP(trust);
1017 trust->netbios_name = talloc_move(array,
1018 &dom_list.domains[i].name.string);
1019 trust->dns_name = NULL;
1021 sid = talloc(array, struct dom_sid);
1022 if (sid == NULL) {
1023 return NT_STATUS_NO_MEMORY;
1025 sid_copy(sid, dom_list.domains[i].sid);
1026 trust->sid = sid;
1028 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1030 *pnum_trusts = count;
1031 *ptrusts = array;
1033 return NT_STATUS_OK;