s3: Make winbindd_register_handlers static
[Samba.git] / source3 / winbindd / winbindd_rpc.c
bloba3faf422fceca071bab14585da5aba72afdc3729
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 *pname,
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 (*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->acct_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);
583 num_groups = rid_array->count;
586 NTSTATUS _result;
587 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
590 if (!NT_STATUS_IS_OK(status)) {
591 return status;
593 if (!NT_STATUS_IS_OK(result) || num_groups == 0) {
594 return result;
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 != tmp_types.count) {
875 return NT_STATUS_UNSUCCESSFUL;
878 for (r = 0; r < tmp_names.count; r++) {
879 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
880 continue;
882 names[total_names] = fill_domain_username_talloc(names,
883 domain_name,
884 tmp_names.names[r].string,
885 true);
886 if (names[total_names] == NULL) {
887 return NT_STATUS_NO_MEMORY;
889 name_types[total_names] = tmp_types.ids[r];
890 total_names++;
893 *pnum_names = total_names;
894 *pnames = names;
895 *pname_types = name_types;
896 *psid_mem = sid_mem;
898 return NT_STATUS_OK;
901 /* Find the sequence number for a domain */
902 NTSTATUS rpc_sequence_number(TALLOC_CTX *mem_ctx,
903 struct rpc_pipe_client *samr_pipe,
904 struct policy_handle *samr_policy,
905 const char *domain_name,
906 uint32_t *pseq)
908 union samr_DomainInfo *info = NULL;
909 bool got_seq_num = false;
910 NTSTATUS status, result;
911 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
913 /* query domain info */
914 status = dcerpc_samr_QueryDomainInfo(b,
915 mem_ctx,
916 samr_policy,
918 &info,
919 &result);
920 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
921 *pseq = info->info8.sequence_num;
922 got_seq_num = true;
923 goto seq_num;
926 /* retry with info-level 2 in case the dc does not support info-level 8
927 * (like all older samba2 and samba3 dc's) - Guenther */
928 status = dcerpc_samr_QueryDomainInfo(b,
929 mem_ctx,
930 samr_policy,
932 &info,
933 &result);
934 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
935 *pseq = info->general.sequence_num;
936 got_seq_num = true;
937 goto seq_num;
940 if (!NT_STATUS_IS_OK(status)) {
941 goto seq_num;
944 status = result;
946 seq_num:
947 if (got_seq_num) {
948 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
949 domain_name, (unsigned) *pseq));
950 } else {
951 DEBUG(10,("domain_sequence_number: failed to get sequence "
952 "number (%u) for domain %s\n",
953 (unsigned) *pseq, domain_name ));
954 status = NT_STATUS_OK;
957 return status;
960 /* Get a list of trusted domains */
961 NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
962 struct rpc_pipe_client *lsa_pipe,
963 struct policy_handle *lsa_policy,
964 uint32_t *pnum_trusts,
965 struct netr_DomainTrust **ptrusts)
967 struct netr_DomainTrust *array = NULL;
968 uint32_t enum_ctx = 0;
969 uint32_t count = 0;
970 NTSTATUS status, result;
971 struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
973 do {
974 struct lsa_DomainList dom_list;
975 struct lsa_DomainListEx dom_list_ex;
976 bool has_ex = false;
977 uint32_t i;
980 * We don't run into deadlocks here, cause winbind_off() is
981 * called in the main function.
983 status = dcerpc_lsa_EnumTrustedDomainsEx(b,
984 mem_ctx,
985 lsa_policy,
986 &enum_ctx,
987 &dom_list_ex,
988 (uint32_t) -1,
989 &result);
990 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_ERR(result) &&
991 dom_list_ex.count > 0) {
992 count += dom_list_ex.count;
993 has_ex = true;
994 } else {
995 status = dcerpc_lsa_EnumTrustDom(b,
996 mem_ctx,
997 lsa_policy,
998 &enum_ctx,
999 &dom_list,
1000 (uint32_t) -1,
1001 &result);
1002 if (!NT_STATUS_IS_OK(status)) {
1003 return status;
1005 if (!NT_STATUS_IS_OK(result)) {
1006 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1007 return result;
1011 count += dom_list.count;
1014 array = talloc_realloc(mem_ctx,
1015 array,
1016 struct netr_DomainTrust,
1017 count);
1018 if (array == NULL) {
1019 return NT_STATUS_NO_MEMORY;
1022 for (i = 0; i < count; i++) {
1023 struct netr_DomainTrust *trust = &array[i];
1024 struct dom_sid *sid;
1026 ZERO_STRUCTP(trust);
1028 sid = talloc(array, struct dom_sid);
1029 if (sid == NULL) {
1030 return NT_STATUS_NO_MEMORY;
1033 if (has_ex) {
1034 trust->netbios_name = talloc_move(array,
1035 &dom_list_ex.domains[i].netbios_name.string);
1036 trust->dns_name = talloc_move(array,
1037 &dom_list_ex.domains[i].domain_name.string);
1039 sid_copy(sid, dom_list_ex.domains[i].sid);
1040 } else {
1041 trust->netbios_name = talloc_move(array,
1042 &dom_list.domains[i].name.string);
1043 trust->dns_name = NULL;
1045 sid_copy(sid, dom_list.domains[i].sid);
1048 trust->sid = sid;
1050 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1052 *pnum_trusts = count;
1053 *ptrusts = array;
1055 return NT_STATUS_OK;
1058 static NTSTATUS rpc_try_lookup_sids3(TALLOC_CTX *mem_ctx,
1059 struct winbindd_domain *domain,
1060 struct lsa_SidArray *sids,
1061 struct lsa_RefDomainList **pdomains,
1062 struct lsa_TransNameArray **pnames)
1064 struct lsa_TransNameArray2 lsa_names2;
1065 struct lsa_TransNameArray *names;
1066 uint32_t i, count;
1067 struct rpc_pipe_client *cli;
1068 NTSTATUS status, result;
1070 status = cm_connect_lsa_tcp(domain, talloc_tos(), &cli);
1071 if (!NT_STATUS_IS_OK(status)) {
1072 domain->can_do_ncacn_ip_tcp = false;
1073 return status;
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 names = talloc_zero(mem_ctx, struct lsa_TransNameArray);
1094 if (names == NULL) {
1095 return NT_STATUS_NO_MEMORY;
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 *pnames = names;
1110 return result;
1113 NTSTATUS rpc_lookup_sids(TALLOC_CTX *mem_ctx,
1114 struct winbindd_domain *domain,
1115 struct lsa_SidArray *sids,
1116 struct lsa_RefDomainList **pdomains,
1117 struct lsa_TransNameArray **pnames)
1119 struct lsa_TransNameArray *names;
1120 struct rpc_pipe_client *cli = NULL;
1121 struct policy_handle lsa_policy;
1122 uint32_t count;
1123 NTSTATUS status, result;
1125 if (domain->can_do_ncacn_ip_tcp) {
1126 status = rpc_try_lookup_sids3(mem_ctx, domain, sids,
1127 pdomains, pnames);
1128 if (!NT_STATUS_IS_ERR(status)) {
1129 return status;
1133 status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1134 if (!NT_STATUS_IS_OK(status)) {
1135 return status;
1138 names = talloc_zero(mem_ctx, struct lsa_TransNameArray);
1139 if (names == NULL) {
1140 return NT_STATUS_NO_MEMORY;
1142 status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
1143 &lsa_policy, sids, pdomains,
1144 names, LSA_LOOKUP_NAMES_ALL,
1145 &count, &result);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 return status;
1149 if (NT_STATUS_IS_ERR(result)) {
1150 return result;
1152 *pnames = names;
1153 return result;