winbind: Avoid a few talloc_tos() in winbindd_cache.c
[Samba.git] / source3 / winbindd / winbindd_rpc.c
blob03bc9b577fcb28fd5f5f6062b38efc6c4a5110a7
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 const char *names[1];
281 char *mapped_name = NULL;
282 NTSTATUS status;
284 if (name == NULL || name[0] == '\0') {
285 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
286 } else if (domain_name == NULL || domain_name[0] == '\0') {
287 full_name = talloc_asprintf(mem_ctx, "%s", name);
288 } else {
289 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
292 if (full_name == NULL) {
293 return NT_STATUS_NO_MEMORY;
296 status = normalize_name_unmap(mem_ctx, full_name, &mapped_name);
297 /* Reset the full_name pointer if we mapped anything */
298 if (NT_STATUS_IS_OK(status) ||
299 NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
300 full_name = mapped_name;
303 DEBUG(3,("name_to_sid: %s for domain %s\n",
304 full_name ? full_name : "", domain_name ));
306 names[0] = full_name;
309 * We don't run into deadlocks here, cause winbind_off() is
310 * called in the main function.
312 status = rpccli_lsa_lookup_names(lsa_pipe,
313 mem_ctx,
314 lsa_policy,
315 1, /* num_names */
316 names,
317 NULL, /* domains */
318 1, /* level */
319 &sids,
320 &types);
321 if (!NT_STATUS_IS_OK(status)) {
322 DEBUG(2,("name_to_sid: failed to lookup name: %s\n",
323 nt_errstr(status)));
324 return status;
327 sid_copy(sid, &sids[0]);
328 *type = types[0];
330 return NT_STATUS_OK;
333 /* Convert a domain SID to a user or group name */
334 NTSTATUS rpc_sid_to_name(TALLOC_CTX *mem_ctx,
335 struct rpc_pipe_client *lsa_pipe,
336 struct policy_handle *lsa_policy,
337 struct winbindd_domain *domain,
338 const struct dom_sid *sid,
339 char **pdomain_name,
340 char **pname,
341 enum lsa_SidType *ptype)
343 char *mapped_name = NULL;
344 char **domains = NULL;
345 char **names = NULL;
346 enum lsa_SidType *types = NULL;
347 NTSTATUS map_status;
348 NTSTATUS status;
350 status = rpccli_lsa_lookup_sids(lsa_pipe,
351 mem_ctx,
352 lsa_policy,
353 1, /* num_sids */
354 sid,
355 &domains,
356 &names,
357 &types);
358 if (!NT_STATUS_IS_OK(status)) {
359 DEBUG(2,("sid_to_name: failed to lookup sids: %s\n",
360 nt_errstr(status)));
361 return status;
364 *ptype = (enum lsa_SidType) types[0];
366 map_status = normalize_name_map(mem_ctx,
367 domain,
368 names[0],
369 &mapped_name);
370 if (NT_STATUS_IS_OK(map_status) ||
371 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
372 *pname = talloc_strdup(mem_ctx, mapped_name);
373 DEBUG(5,("returning mapped name -- %s\n", *pname));
374 } else {
375 *pname = talloc_strdup(mem_ctx, names[0]);
377 if ((names[0] != NULL) && (*pname == NULL)) {
378 return NT_STATUS_NO_MEMORY;
381 *pdomain_name = talloc_strdup(mem_ctx, domains[0]);
382 if (*pdomain_name == NULL) {
383 return NT_STATUS_NO_MEMORY;
386 return NT_STATUS_OK;
389 /* Convert a bunch of rids to user or group names */
390 NTSTATUS rpc_rids_to_names(TALLOC_CTX *mem_ctx,
391 struct rpc_pipe_client *lsa_pipe,
392 struct policy_handle *lsa_policy,
393 struct winbindd_domain *domain,
394 const struct dom_sid *sid,
395 uint32_t *rids,
396 size_t num_rids,
397 char **pdomain_name,
398 char ***pnames,
399 enum lsa_SidType **ptypes)
401 enum lsa_SidType *types = NULL;
402 char *domain_name = NULL;
403 char **domains = NULL;
404 char **names = NULL;
405 struct dom_sid *sids;
406 size_t i;
407 NTSTATUS status;
409 if (num_rids > 0) {
410 sids = talloc_array(mem_ctx, struct dom_sid, num_rids);
411 if (sids == NULL) {
412 return NT_STATUS_NO_MEMORY;
414 } else {
415 sids = NULL;
418 for (i = 0; i < num_rids; i++) {
419 if (!sid_compose(&sids[i], sid, rids[i])) {
420 return NT_STATUS_INTERNAL_ERROR;
424 status = rpccli_lsa_lookup_sids(lsa_pipe,
425 mem_ctx,
426 lsa_policy,
427 num_rids,
428 sids,
429 &domains,
430 &names,
431 &types);
432 if (!NT_STATUS_IS_OK(status) &&
433 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
434 DEBUG(2,("rids_to_names: failed to lookup sids: %s\n",
435 nt_errstr(status)));
436 return status;
439 for (i = 0; i < num_rids; i++) {
440 char *mapped_name = NULL;
441 NTSTATUS map_status;
443 if (types[i] != SID_NAME_UNKNOWN) {
444 map_status = normalize_name_map(mem_ctx,
445 domain,
446 names[i],
447 &mapped_name);
448 if (NT_STATUS_IS_OK(map_status) ||
449 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
450 TALLOC_FREE(names[i]);
451 names[i] = talloc_strdup(names, mapped_name);
452 if (names[i] == NULL) {
453 return NT_STATUS_NO_MEMORY;
457 domain_name = domains[i];
461 *pdomain_name = domain_name;
462 *ptypes = types;
463 *pnames = names;
465 return NT_STATUS_OK;
468 /* Lookup user information from a rid or username. */
469 NTSTATUS rpc_query_user(TALLOC_CTX *mem_ctx,
470 struct rpc_pipe_client *samr_pipe,
471 struct policy_handle *samr_policy,
472 const struct dom_sid *domain_sid,
473 const struct dom_sid *user_sid,
474 struct wbint_userinfo *user_info)
476 struct policy_handle user_policy;
477 union samr_UserInfo *info = NULL;
478 uint32_t user_rid;
479 NTSTATUS status, result;
480 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
482 if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
483 return NT_STATUS_UNSUCCESSFUL;
486 /* Get user handle */
487 status = dcerpc_samr_OpenUser(b,
488 mem_ctx,
489 samr_policy,
490 SEC_FLAG_MAXIMUM_ALLOWED,
491 user_rid,
492 &user_policy,
493 &result);
494 if (!NT_STATUS_IS_OK(status)) {
495 return status;
497 if (!NT_STATUS_IS_OK(result)) {
498 return result;
501 /* Get user info */
502 status = dcerpc_samr_QueryUserInfo(b,
503 mem_ctx,
504 &user_policy,
505 0x15,
506 &info,
507 &result);
509 NTSTATUS _result;
510 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
512 if (!NT_STATUS_IS_OK(status)) {
513 return status;
515 if (!NT_STATUS_IS_OK(result)) {
516 return result;
519 sid_compose(&user_info->user_sid, domain_sid, user_rid);
520 sid_compose(&user_info->group_sid, domain_sid,
521 info->info21.primary_gid);
523 user_info->acct_name = talloc_strdup(user_info,
524 info->info21.account_name.string);
525 if (user_info->acct_name == NULL) {
526 return NT_STATUS_NO_MEMORY;
529 user_info->full_name = talloc_strdup(user_info,
530 info->info21.full_name.string);
531 if ((info->info21.full_name.string != NULL) &&
532 (user_info->full_name == NULL))
534 return NT_STATUS_NO_MEMORY;
537 user_info->homedir = NULL;
538 user_info->shell = NULL;
539 user_info->primary_gid = (gid_t)-1;
541 return NT_STATUS_OK;
544 /* Lookup groups a user is a member of. */
545 NTSTATUS rpc_lookup_usergroups(TALLOC_CTX *mem_ctx,
546 struct rpc_pipe_client *samr_pipe,
547 struct policy_handle *samr_policy,
548 const struct dom_sid *domain_sid,
549 const struct dom_sid *user_sid,
550 uint32_t *pnum_groups,
551 struct dom_sid **puser_grpsids)
553 struct policy_handle user_policy;
554 struct samr_RidWithAttributeArray *rid_array = NULL;
555 struct dom_sid *user_grpsids = NULL;
556 uint32_t num_groups = 0, i;
557 uint32_t user_rid;
558 NTSTATUS status, result;
559 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
561 if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
562 return NT_STATUS_UNSUCCESSFUL;
565 /* Get user handle */
566 status = dcerpc_samr_OpenUser(b,
567 mem_ctx,
568 samr_policy,
569 SEC_FLAG_MAXIMUM_ALLOWED,
570 user_rid,
571 &user_policy,
572 &result);
573 if (!NT_STATUS_IS_OK(status)) {
574 return status;
576 if (!NT_STATUS_IS_OK(result)) {
577 return result;
580 /* Query user rids */
581 status = dcerpc_samr_GetGroupsForUser(b,
582 mem_ctx,
583 &user_policy,
584 &rid_array,
585 &result);
587 NTSTATUS _result;
588 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
591 if (!NT_STATUS_IS_OK(status)) {
592 return status;
594 if (!NT_STATUS_IS_OK(result)) {
595 return result;
598 num_groups = rid_array->count;
600 user_grpsids = talloc_array(mem_ctx, struct dom_sid, num_groups);
601 if (user_grpsids == NULL) {
602 status = NT_STATUS_NO_MEMORY;
603 return status;
606 for (i = 0; i < num_groups; i++) {
607 sid_compose(&(user_grpsids[i]), domain_sid,
608 rid_array->rids[i].rid);
611 *pnum_groups = num_groups;
613 *puser_grpsids = user_grpsids;
615 return NT_STATUS_OK;
618 NTSTATUS rpc_lookup_useraliases(TALLOC_CTX *mem_ctx,
619 struct rpc_pipe_client *samr_pipe,
620 struct policy_handle *samr_policy,
621 uint32_t num_sids,
622 const struct dom_sid *sids,
623 uint32_t *pnum_aliases,
624 uint32_t **palias_rids)
626 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
627 uint32_t num_query_sids = 0;
628 uint32_t num_queries = 1;
629 uint32_t num_aliases = 0;
630 uint32_t total_sids = 0;
631 uint32_t *alias_rids = NULL;
632 uint32_t rangesize = MAX_SAM_ENTRIES_W2K;
633 uint32_t i;
634 struct samr_Ids alias_rids_query;
635 NTSTATUS status, result;
636 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
638 do {
639 /* prepare query */
640 struct lsa_SidArray sid_array;
642 ZERO_STRUCT(sid_array);
644 num_query_sids = MIN(num_sids - total_sids, rangesize);
646 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
647 num_queries, num_query_sids));
649 if (num_query_sids) {
650 sid_array.sids = talloc_zero_array(mem_ctx, struct lsa_SidPtr, num_query_sids);
651 if (sid_array.sids == NULL) {
652 return NT_STATUS_NO_MEMORY;
654 } else {
655 sid_array.sids = NULL;
658 for (i = 0; i < num_query_sids; i++) {
659 sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[total_sids++]);
660 if (sid_array.sids[i].sid == NULL) {
661 return NT_STATUS_NO_MEMORY;
664 sid_array.num_sids = num_query_sids;
666 /* do request */
667 status = dcerpc_samr_GetAliasMembership(b,
668 mem_ctx,
669 samr_policy,
670 &sid_array,
671 &alias_rids_query,
672 &result);
673 if (!NT_STATUS_IS_OK(status)) {
674 return status;
676 if (!NT_STATUS_IS_OK(result)) {
677 return result;
680 /* process output */
681 for (i = 0; i < alias_rids_query.count; i++) {
682 size_t na = num_aliases;
684 if (!add_rid_to_array_unique(mem_ctx,
685 alias_rids_query.ids[i],
686 &alias_rids,
687 &na)) {
688 return NT_STATUS_NO_MEMORY;
690 num_aliases = na;
693 num_queries++;
695 } while (total_sids < num_sids);
697 DEBUG(10,("rpc: rpc_lookup_useraliases: got %d aliases in %d queries "
698 "(rangesize: %d)\n", num_aliases, num_queries, rangesize));
700 *pnum_aliases = num_aliases;
701 *palias_rids = alias_rids;
703 return NT_STATUS_OK;
704 #undef MAX_SAM_ENTRIES_W2K
707 /* Lookup group membership given a rid. */
708 NTSTATUS rpc_lookup_groupmem(TALLOC_CTX *mem_ctx,
709 struct rpc_pipe_client *samr_pipe,
710 struct policy_handle *samr_policy,
711 const char *domain_name,
712 const struct dom_sid *domain_sid,
713 const struct dom_sid *group_sid,
714 enum lsa_SidType type,
715 uint32_t *pnum_names,
716 struct dom_sid **psid_mem,
717 char ***pnames,
718 uint32_t **pname_types)
720 struct policy_handle group_policy;
721 uint32_t group_rid;
722 uint32_t *rid_mem = NULL;
724 uint32_t num_names = 0;
725 uint32_t total_names = 0;
726 struct dom_sid *sid_mem = NULL;
727 char **names = NULL;
728 uint32_t *name_types = NULL;
730 struct lsa_Strings tmp_names;
731 struct samr_Ids tmp_types;
733 uint32_t j, r;
734 NTSTATUS status, result;
735 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
737 if (!sid_peek_check_rid(domain_sid, group_sid, &group_rid)) {
738 return NT_STATUS_UNSUCCESSFUL;
741 switch(type) {
742 case SID_NAME_DOM_GRP:
744 struct samr_RidAttrArray *rids = NULL;
746 status = dcerpc_samr_OpenGroup(b,
747 mem_ctx,
748 samr_policy,
749 SEC_FLAG_MAXIMUM_ALLOWED,
750 group_rid,
751 &group_policy,
752 &result);
753 if (!NT_STATUS_IS_OK(status)) {
754 return status;
756 if (!NT_STATUS_IS_OK(result)) {
757 return result;
761 * Step #1: Get a list of user rids that are the members of the group.
763 status = dcerpc_samr_QueryGroupMember(b,
764 mem_ctx,
765 &group_policy,
766 &rids,
767 &result);
769 NTSTATUS _result;
770 dcerpc_samr_Close(b, mem_ctx, &group_policy, &_result);
773 if (!NT_STATUS_IS_OK(status)) {
774 return status;
776 if (!NT_STATUS_IS_OK(result)) {
777 return result;
781 if (rids == NULL || rids->count == 0) {
782 pnum_names = 0;
783 pnames = NULL;
784 pname_types = NULL;
785 psid_mem = NULL;
787 return NT_STATUS_OK;
790 num_names = rids->count;
791 rid_mem = rids->rids;
793 break;
795 case SID_NAME_WKN_GRP:
796 case SID_NAME_ALIAS:
798 struct lsa_SidArray sid_array;
799 struct lsa_SidPtr sid_ptr;
800 struct samr_Ids rids_query;
802 sid_ptr.sid = dom_sid_dup(mem_ctx, group_sid);
803 if (sid_ptr.sid == NULL) {
804 return NT_STATUS_NO_MEMORY;
807 sid_array.num_sids = 1;
808 sid_array.sids = &sid_ptr;
810 status = dcerpc_samr_GetAliasMembership(b,
811 mem_ctx,
812 samr_policy,
813 &sid_array,
814 &rids_query,
815 &result);
816 if (!NT_STATUS_IS_OK(status)) {
817 return status;
819 if (!NT_STATUS_IS_OK(result)) {
820 return result;
823 if (rids_query.count == 0) {
824 pnum_names = 0;
825 pnames = NULL;
826 pname_types = NULL;
827 psid_mem = NULL;
829 return NT_STATUS_OK;
832 num_names = rids_query.count;
833 rid_mem = rids_query.ids;
835 break;
837 default:
838 return NT_STATUS_UNSUCCESSFUL;
842 * Step #2: Convert list of rids into list of usernames.
844 if (num_names > 0) {
845 names = talloc_zero_array(mem_ctx, char *, num_names);
846 name_types = talloc_zero_array(mem_ctx, uint32_t, num_names);
847 sid_mem = talloc_zero_array(mem_ctx, struct dom_sid, num_names);
848 if (names == NULL || name_types == NULL || sid_mem == NULL) {
849 return NT_STATUS_NO_MEMORY;
853 for (j = 0; j < num_names; j++) {
854 sid_compose(&sid_mem[j], domain_sid, rid_mem[j]);
857 status = dcerpc_samr_LookupRids(b,
858 mem_ctx,
859 samr_policy,
860 num_names,
861 rid_mem,
862 &tmp_names,
863 &tmp_types,
864 &result);
865 if (!NT_STATUS_IS_OK(status)) {
866 return status;
869 if (!NT_STATUS_IS_OK(result)) {
870 if (!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
871 return result;
875 /* Copy result into array. The talloc system will take
876 care of freeing the temporary arrays later on. */
877 if (tmp_names.count != num_names) {
878 return NT_STATUS_INVALID_NETWORK_RESPONSE;
880 if (tmp_types.count != num_names) {
881 return NT_STATUS_INVALID_NETWORK_RESPONSE;
884 for (r = 0; r < tmp_names.count; r++) {
885 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
886 continue;
888 if (total_names >= num_names) {
889 break;
891 names[total_names] = fill_domain_username_talloc(names,
892 domain_name,
893 tmp_names.names[r].string,
894 true);
895 if (names[total_names] == NULL) {
896 return NT_STATUS_NO_MEMORY;
898 name_types[total_names] = tmp_types.ids[r];
899 total_names++;
902 *pnum_names = total_names;
903 *pnames = names;
904 *pname_types = name_types;
905 *psid_mem = sid_mem;
907 return NT_STATUS_OK;
910 /* Find the sequence number for a domain */
911 NTSTATUS rpc_sequence_number(TALLOC_CTX *mem_ctx,
912 struct rpc_pipe_client *samr_pipe,
913 struct policy_handle *samr_policy,
914 const char *domain_name,
915 uint32_t *pseq)
917 union samr_DomainInfo *info = NULL;
918 bool got_seq_num = false;
919 NTSTATUS status, result;
920 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
922 /* query domain info */
923 status = dcerpc_samr_QueryDomainInfo(b,
924 mem_ctx,
925 samr_policy,
927 &info,
928 &result);
929 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
930 *pseq = info->info8.sequence_num;
931 got_seq_num = true;
932 goto seq_num;
935 /* retry with info-level 2 in case the dc does not support info-level 8
936 * (like all older samba2 and samba3 dc's) - Guenther */
937 status = dcerpc_samr_QueryDomainInfo(b,
938 mem_ctx,
939 samr_policy,
941 &info,
942 &result);
943 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
944 *pseq = info->general.sequence_num;
945 got_seq_num = true;
946 goto seq_num;
949 if (!NT_STATUS_IS_OK(status)) {
950 goto seq_num;
953 status = result;
955 seq_num:
956 if (got_seq_num) {
957 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
958 domain_name, (unsigned) *pseq));
959 } else {
960 DEBUG(10,("domain_sequence_number: failed to get sequence "
961 "number (%u) for domain %s\n",
962 (unsigned) *pseq, domain_name ));
963 status = NT_STATUS_OK;
966 return status;
969 /* Get a list of trusted domains */
970 NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
971 struct rpc_pipe_client *lsa_pipe,
972 struct policy_handle *lsa_policy,
973 uint32_t *pnum_trusts,
974 struct netr_DomainTrust **ptrusts)
976 struct netr_DomainTrust *array = NULL;
977 uint32_t enum_ctx = 0;
978 uint32_t count = 0;
979 NTSTATUS status, result;
980 struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
982 do {
983 struct lsa_DomainList dom_list;
984 struct lsa_DomainListEx dom_list_ex;
985 bool has_ex = false;
986 uint32_t i;
989 * We don't run into deadlocks here, cause winbind_off() is
990 * called in the main function.
992 status = dcerpc_lsa_EnumTrustedDomainsEx(b,
993 mem_ctx,
994 lsa_policy,
995 &enum_ctx,
996 &dom_list_ex,
997 (uint32_t) -1,
998 &result);
999 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_ERR(result) &&
1000 dom_list_ex.count > 0) {
1001 count += dom_list_ex.count;
1002 has_ex = true;
1003 } else {
1004 status = dcerpc_lsa_EnumTrustDom(b,
1005 mem_ctx,
1006 lsa_policy,
1007 &enum_ctx,
1008 &dom_list,
1009 (uint32_t) -1,
1010 &result);
1011 if (!NT_STATUS_IS_OK(status)) {
1012 return status;
1014 if (!NT_STATUS_IS_OK(result)) {
1015 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1016 return result;
1020 count += dom_list.count;
1023 array = talloc_realloc(mem_ctx,
1024 array,
1025 struct netr_DomainTrust,
1026 count);
1027 if (array == NULL) {
1028 return NT_STATUS_NO_MEMORY;
1031 for (i = 0; i < count; i++) {
1032 struct netr_DomainTrust *trust = &array[i];
1033 struct dom_sid *sid;
1035 ZERO_STRUCTP(trust);
1037 sid = talloc(array, struct dom_sid);
1038 if (sid == NULL) {
1039 return NT_STATUS_NO_MEMORY;
1042 if (has_ex) {
1043 trust->netbios_name = talloc_move(array,
1044 &dom_list_ex.domains[i].netbios_name.string);
1045 trust->dns_name = talloc_move(array,
1046 &dom_list_ex.domains[i].domain_name.string);
1047 if (dom_list_ex.domains[i].sid == NULL) {
1048 DEBUG(0, ("Trusted Domain %s has no SID, aborting!\n", trust->dns_name));
1049 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1051 sid_copy(sid, dom_list_ex.domains[i].sid);
1052 } else {
1053 trust->netbios_name = talloc_move(array,
1054 &dom_list.domains[i].name.string);
1055 trust->dns_name = NULL;
1057 if (dom_list.domains[i].sid == NULL) {
1058 DEBUG(0, ("Trusted Domain %s has no SID, aborting!\n", trust->netbios_name));
1059 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1062 sid_copy(sid, dom_list.domains[i].sid);
1065 trust->sid = sid;
1067 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1069 *pnum_trusts = count;
1070 *ptrusts = array;
1072 return NT_STATUS_OK;
1075 static NTSTATUS rpc_try_lookup_sids3(TALLOC_CTX *mem_ctx,
1076 struct winbindd_domain *domain,
1077 struct rpc_pipe_client *cli,
1078 struct lsa_SidArray *sids,
1079 struct lsa_RefDomainList **pdomains,
1080 struct lsa_TransNameArray **pnames)
1082 struct lsa_TransNameArray2 lsa_names2;
1083 struct lsa_TransNameArray *names = *pnames;
1084 uint32_t i, count;
1085 NTSTATUS status, result;
1087 ZERO_STRUCT(lsa_names2);
1088 status = dcerpc_lsa_LookupSids3(cli->binding_handle,
1089 mem_ctx,
1090 sids,
1091 pdomains,
1092 &lsa_names2,
1093 LSA_LOOKUP_NAMES_ALL,
1094 &count,
1095 LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
1096 LSA_CLIENT_REVISION_2,
1097 &result);
1098 if (!NT_STATUS_IS_OK(status)) {
1099 return status;
1101 if (NT_STATUS_IS_ERR(result)) {
1102 return result;
1104 if (sids->num_sids != lsa_names2.count) {
1105 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1108 names->count = lsa_names2.count;
1109 names->names = talloc_array(names, struct lsa_TranslatedName,
1110 names->count);
1111 if (names->names == NULL) {
1112 return NT_STATUS_NO_MEMORY;
1114 for (i=0; i<names->count; i++) {
1115 names->names[i].sid_type = lsa_names2.names[i].sid_type;
1116 names->names[i].name.string = talloc_move(
1117 names->names, &lsa_names2.names[i].name.string);
1118 names->names[i].sid_index = lsa_names2.names[i].sid_index;
1120 if (names->names[i].sid_index == UINT32_MAX) {
1121 continue;
1123 if ((*pdomains) == NULL) {
1124 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1126 if (names->names[i].sid_index >= (*pdomains)->count) {
1127 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1130 return result;
1133 NTSTATUS rpc_lookup_sids(TALLOC_CTX *mem_ctx,
1134 struct winbindd_domain *domain,
1135 struct lsa_SidArray *sids,
1136 struct lsa_RefDomainList **pdomains,
1137 struct lsa_TransNameArray **pnames)
1139 struct lsa_TransNameArray *names = *pnames;
1140 struct rpc_pipe_client *cli = NULL;
1141 struct policy_handle lsa_policy;
1142 uint32_t count;
1143 uint32_t i;
1144 NTSTATUS status, result;
1146 status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
1147 if (!NT_STATUS_IS_OK(status)) {
1148 return status;
1151 if (cli->transport->transport == NCACN_IP_TCP) {
1152 return rpc_try_lookup_sids3(mem_ctx, domain, cli, sids,
1153 pdomains, pnames);
1156 status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
1157 &lsa_policy, sids, pdomains,
1158 names, LSA_LOOKUP_NAMES_ALL,
1159 &count, &result);
1160 if (!NT_STATUS_IS_OK(status)) {
1161 return status;
1163 if (NT_STATUS_IS_ERR(result)) {
1164 return result;
1167 if (sids->num_sids != names->count) {
1168 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1171 for (i=0; i < names->count; i++) {
1172 if (names->names[i].sid_index == UINT32_MAX) {
1173 continue;
1175 if ((*pdomains) == NULL) {
1176 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1178 if (names->names[i].sid_index >= (*pdomains)->count) {
1179 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1183 return result;