negoex.idl: use DATA_BLOB for negoex_BYTE_VECTOR
[Samba.git] / source3 / winbindd / winbindd_rpc.c
blob386396a1e19174e7ee30bc46282507ff6b58ef95
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;
123 dst->primary_gid = (gid_t)-1;
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 struct wb_acct_info *i = &info[num_info + g];
195 fstrcpy(i->acct_name,
196 sam_array->entries[g].name.string);
197 fstrcpy(i->acct_desc, "");
198 i->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 wb_acct_info **pinfo)
216 struct wb_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(mem_ctx,
247 info,
248 struct wb_acct_info,
249 num_info + count);
250 if (info == NULL) {
251 return NT_STATUS_NO_MEMORY;
254 for (g = 0; g < count; g++) {
255 struct wb_acct_info *i = &info[num_info + g];
257 fstrcpy(i->acct_name,
258 sam_array->entries[g].name.string);
259 fstrcpy(i->acct_desc, "");
260 i->rid = sam_array->entries[g].idx;
263 num_info += count;
264 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
266 *pnum_info = num_info;
267 *pinfo = info;
269 return NT_STATUS_OK;
272 /* convert a single name to a sid in a domain */
273 NTSTATUS rpc_name_to_sid(TALLOC_CTX *mem_ctx,
274 struct rpc_pipe_client *lsa_pipe,
275 struct policy_handle *lsa_policy,
276 const char *domain_name,
277 const char *name,
278 uint32_t flags,
279 struct dom_sid *sid,
280 enum lsa_SidType *type)
282 enum lsa_SidType *types = NULL;
283 struct dom_sid *sids = NULL;
284 char *full_name = NULL;
285 const char *names[1];
286 char *mapped_name = NULL;
287 NTSTATUS status;
289 if (name == NULL || name[0] == '\0') {
290 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
291 } else if (domain_name == NULL || domain_name[0] == '\0') {
292 full_name = talloc_asprintf(mem_ctx, "%s", name);
293 } else {
294 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
297 if (full_name == NULL) {
298 return NT_STATUS_NO_MEMORY;
301 status = normalize_name_unmap(mem_ctx, full_name, &mapped_name);
302 /* Reset the full_name pointer if we mapped anything */
303 if (NT_STATUS_IS_OK(status) ||
304 NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
305 full_name = mapped_name;
308 DEBUG(3,("name_to_sid: %s for domain %s\n",
309 full_name ? full_name : "", domain_name ));
311 names[0] = full_name;
314 * We don't run into deadlocks here, cause winbind_off() is
315 * called in the main function.
317 status = rpccli_lsa_lookup_names(lsa_pipe,
318 mem_ctx,
319 lsa_policy,
320 1, /* num_names */
321 names,
322 NULL, /* domains */
323 1, /* level */
324 &sids,
325 &types);
326 if (!NT_STATUS_IS_OK(status)) {
327 DEBUG(2,("name_to_sid: failed to lookup name: %s\n",
328 nt_errstr(status)));
329 return status;
332 sid_copy(sid, &sids[0]);
333 *type = types[0];
335 return NT_STATUS_OK;
338 /* Convert a domain SID to a user or group name */
339 NTSTATUS rpc_sid_to_name(TALLOC_CTX *mem_ctx,
340 struct rpc_pipe_client *lsa_pipe,
341 struct policy_handle *lsa_policy,
342 struct winbindd_domain *domain,
343 const struct dom_sid *sid,
344 char **pdomain_name,
345 char **pname,
346 enum lsa_SidType *ptype)
348 char *mapped_name = NULL;
349 char **domains = NULL;
350 char **names = NULL;
351 enum lsa_SidType *types = NULL;
352 NTSTATUS map_status;
353 NTSTATUS status;
355 status = rpccli_lsa_lookup_sids(lsa_pipe,
356 mem_ctx,
357 lsa_policy,
358 1, /* num_sids */
359 sid,
360 &domains,
361 &names,
362 &types);
363 if (!NT_STATUS_IS_OK(status)) {
364 DEBUG(2,("sid_to_name: failed to lookup sids: %s\n",
365 nt_errstr(status)));
366 return status;
369 *ptype = (enum lsa_SidType) types[0];
371 map_status = normalize_name_map(mem_ctx,
372 domain,
373 names[0],
374 &mapped_name);
375 if (NT_STATUS_IS_OK(map_status) ||
376 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
377 *pname = talloc_strdup(mem_ctx, mapped_name);
378 DEBUG(5,("returning mapped name -- %s\n", *pname));
379 } else {
380 *pname = talloc_strdup(mem_ctx, names[0]);
382 if ((names[0] != NULL) && (*pname == NULL)) {
383 return NT_STATUS_NO_MEMORY;
386 *pdomain_name = talloc_strdup(mem_ctx, domains[0]);
387 if (*pdomain_name == NULL) {
388 return NT_STATUS_NO_MEMORY;
391 return NT_STATUS_OK;
394 /* Convert a bunch of rids to user or group names */
395 NTSTATUS rpc_rids_to_names(TALLOC_CTX *mem_ctx,
396 struct rpc_pipe_client *lsa_pipe,
397 struct policy_handle *lsa_policy,
398 struct winbindd_domain *domain,
399 const struct dom_sid *sid,
400 uint32_t *rids,
401 size_t num_rids,
402 char **pdomain_name,
403 char ***pnames,
404 enum lsa_SidType **ptypes)
406 enum lsa_SidType *types = NULL;
407 char *domain_name = NULL;
408 char **domains = NULL;
409 char **names = NULL;
410 struct dom_sid *sids;
411 size_t i;
412 NTSTATUS status;
414 if (num_rids > 0) {
415 sids = talloc_array(mem_ctx, struct dom_sid, num_rids);
416 if (sids == NULL) {
417 return NT_STATUS_NO_MEMORY;
419 } else {
420 sids = NULL;
423 for (i = 0; i < num_rids; i++) {
424 if (!sid_compose(&sids[i], sid, rids[i])) {
425 return NT_STATUS_INTERNAL_ERROR;
429 status = rpccli_lsa_lookup_sids(lsa_pipe,
430 mem_ctx,
431 lsa_policy,
432 num_rids,
433 sids,
434 &domains,
435 &names,
436 &types);
437 if (!NT_STATUS_IS_OK(status) &&
438 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
439 DEBUG(2,("rids_to_names: failed to lookup sids: %s\n",
440 nt_errstr(status)));
441 return status;
444 for (i = 0; i < num_rids; i++) {
445 char *mapped_name = NULL;
446 NTSTATUS map_status;
448 if (types[i] != SID_NAME_UNKNOWN) {
449 map_status = normalize_name_map(mem_ctx,
450 domain,
451 names[i],
452 &mapped_name);
453 if (NT_STATUS_IS_OK(map_status) ||
454 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
455 TALLOC_FREE(names[i]);
456 names[i] = talloc_strdup(names, mapped_name);
457 if (names[i] == NULL) {
458 return NT_STATUS_NO_MEMORY;
462 domain_name = domains[i];
466 *pdomain_name = domain_name;
467 *ptypes = types;
468 *pnames = names;
470 return NT_STATUS_OK;
473 /* Lookup user information from a rid or username. */
474 NTSTATUS rpc_query_user(TALLOC_CTX *mem_ctx,
475 struct rpc_pipe_client *samr_pipe,
476 struct policy_handle *samr_policy,
477 const struct dom_sid *domain_sid,
478 const struct dom_sid *user_sid,
479 struct wbint_userinfo *user_info)
481 struct policy_handle user_policy;
482 union samr_UserInfo *info = NULL;
483 uint32_t user_rid;
484 NTSTATUS status, result;
485 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
487 if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
488 return NT_STATUS_UNSUCCESSFUL;
491 /* Get user handle */
492 status = dcerpc_samr_OpenUser(b,
493 mem_ctx,
494 samr_policy,
495 SEC_FLAG_MAXIMUM_ALLOWED,
496 user_rid,
497 &user_policy,
498 &result);
499 if (!NT_STATUS_IS_OK(status)) {
500 return status;
502 if (!NT_STATUS_IS_OK(result)) {
503 return result;
506 /* Get user info */
507 status = dcerpc_samr_QueryUserInfo(b,
508 mem_ctx,
509 &user_policy,
510 0x15,
511 &info,
512 &result);
514 NTSTATUS _result;
515 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
517 if (!NT_STATUS_IS_OK(status)) {
518 return status;
520 if (!NT_STATUS_IS_OK(result)) {
521 return result;
524 sid_compose(&user_info->user_sid, domain_sid, user_rid);
525 sid_compose(&user_info->group_sid, domain_sid,
526 info->info21.primary_gid);
528 user_info->acct_name = talloc_strdup(user_info,
529 info->info21.account_name.string);
530 if (user_info->acct_name == NULL) {
531 return NT_STATUS_NO_MEMORY;
534 user_info->full_name = talloc_strdup(user_info,
535 info->info21.full_name.string);
536 if ((info->info21.full_name.string != NULL) &&
537 (user_info->full_name == NULL))
539 return NT_STATUS_NO_MEMORY;
542 user_info->homedir = NULL;
543 user_info->shell = NULL;
544 user_info->primary_gid = (gid_t)-1;
546 return NT_STATUS_OK;
549 /* Lookup groups a user is a member of. */
550 NTSTATUS rpc_lookup_usergroups(TALLOC_CTX *mem_ctx,
551 struct rpc_pipe_client *samr_pipe,
552 struct policy_handle *samr_policy,
553 const struct dom_sid *domain_sid,
554 const struct dom_sid *user_sid,
555 uint32_t *pnum_groups,
556 struct dom_sid **puser_grpsids)
558 struct policy_handle user_policy;
559 struct samr_RidWithAttributeArray *rid_array = NULL;
560 struct dom_sid *user_grpsids = NULL;
561 uint32_t num_groups = 0, i;
562 uint32_t user_rid;
563 NTSTATUS status, result;
564 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
566 if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
567 return NT_STATUS_UNSUCCESSFUL;
570 /* Get user handle */
571 status = dcerpc_samr_OpenUser(b,
572 mem_ctx,
573 samr_policy,
574 SEC_FLAG_MAXIMUM_ALLOWED,
575 user_rid,
576 &user_policy,
577 &result);
578 if (!NT_STATUS_IS_OK(status)) {
579 return status;
581 if (!NT_STATUS_IS_OK(result)) {
582 return result;
585 /* Query user rids */
586 status = dcerpc_samr_GetGroupsForUser(b,
587 mem_ctx,
588 &user_policy,
589 &rid_array,
590 &result);
592 NTSTATUS _result;
593 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
596 if (!NT_STATUS_IS_OK(status)) {
597 return status;
599 if (!NT_STATUS_IS_OK(result)) {
600 return result;
603 num_groups = rid_array->count;
605 user_grpsids = talloc_array(mem_ctx, struct dom_sid, num_groups);
606 if (user_grpsids == NULL) {
607 status = NT_STATUS_NO_MEMORY;
608 return status;
611 for (i = 0; i < num_groups; i++) {
612 sid_compose(&(user_grpsids[i]), domain_sid,
613 rid_array->rids[i].rid);
616 *pnum_groups = num_groups;
618 *puser_grpsids = user_grpsids;
620 return NT_STATUS_OK;
623 NTSTATUS rpc_lookup_useraliases(TALLOC_CTX *mem_ctx,
624 struct rpc_pipe_client *samr_pipe,
625 struct policy_handle *samr_policy,
626 uint32_t num_sids,
627 const struct dom_sid *sids,
628 uint32_t *pnum_aliases,
629 uint32_t **palias_rids)
631 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
632 uint32_t num_query_sids = 0;
633 uint32_t num_queries = 1;
634 uint32_t num_aliases = 0;
635 uint32_t total_sids = 0;
636 uint32_t *alias_rids = NULL;
637 uint32_t rangesize = MAX_SAM_ENTRIES_W2K;
638 uint32_t i;
639 struct samr_Ids alias_rids_query;
640 NTSTATUS status, result;
641 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
643 do {
644 /* prepare query */
645 struct lsa_SidArray sid_array;
647 ZERO_STRUCT(sid_array);
649 num_query_sids = MIN(num_sids - total_sids, rangesize);
651 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
652 num_queries, num_query_sids));
654 if (num_query_sids) {
655 sid_array.sids = talloc_zero_array(mem_ctx, struct lsa_SidPtr, num_query_sids);
656 if (sid_array.sids == NULL) {
657 return NT_STATUS_NO_MEMORY;
659 } else {
660 sid_array.sids = NULL;
663 for (i = 0; i < num_query_sids; i++) {
664 sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[total_sids++]);
665 if (sid_array.sids[i].sid == NULL) {
666 return NT_STATUS_NO_MEMORY;
669 sid_array.num_sids = num_query_sids;
671 /* do request */
672 status = dcerpc_samr_GetAliasMembership(b,
673 mem_ctx,
674 samr_policy,
675 &sid_array,
676 &alias_rids_query,
677 &result);
678 if (!NT_STATUS_IS_OK(status)) {
679 return status;
681 if (!NT_STATUS_IS_OK(result)) {
682 return result;
685 /* process output */
686 for (i = 0; i < alias_rids_query.count; i++) {
687 size_t na = num_aliases;
689 if (!add_rid_to_array_unique(mem_ctx,
690 alias_rids_query.ids[i],
691 &alias_rids,
692 &na)) {
693 return NT_STATUS_NO_MEMORY;
695 num_aliases = na;
698 num_queries++;
700 } while (total_sids < num_sids);
702 DEBUG(10,("rpc: rpc_lookup_useraliases: got %d aliases in %d queries "
703 "(rangesize: %d)\n", num_aliases, num_queries, rangesize));
705 *pnum_aliases = num_aliases;
706 *palias_rids = alias_rids;
708 return NT_STATUS_OK;
709 #undef MAX_SAM_ENTRIES_W2K
712 /* Lookup group membership given a rid. */
713 NTSTATUS rpc_lookup_groupmem(TALLOC_CTX *mem_ctx,
714 struct rpc_pipe_client *samr_pipe,
715 struct policy_handle *samr_policy,
716 const char *domain_name,
717 const struct dom_sid *domain_sid,
718 const struct dom_sid *group_sid,
719 enum lsa_SidType type,
720 uint32_t *pnum_names,
721 struct dom_sid **psid_mem,
722 char ***pnames,
723 uint32_t **pname_types)
725 struct policy_handle group_policy;
726 uint32_t group_rid;
727 uint32_t *rid_mem = NULL;
729 uint32_t num_names = 0;
730 uint32_t total_names = 0;
731 struct dom_sid *sid_mem = NULL;
732 char **names = NULL;
733 uint32_t *name_types = NULL;
735 struct lsa_Strings tmp_names;
736 struct samr_Ids tmp_types;
738 uint32_t j, r;
739 NTSTATUS status, result;
740 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
742 if (!sid_peek_check_rid(domain_sid, group_sid, &group_rid)) {
743 return NT_STATUS_UNSUCCESSFUL;
746 switch(type) {
747 case SID_NAME_DOM_GRP:
749 struct samr_RidAttrArray *rids = NULL;
751 status = dcerpc_samr_OpenGroup(b,
752 mem_ctx,
753 samr_policy,
754 SEC_FLAG_MAXIMUM_ALLOWED,
755 group_rid,
756 &group_policy,
757 &result);
758 if (!NT_STATUS_IS_OK(status)) {
759 return status;
761 if (!NT_STATUS_IS_OK(result)) {
762 return result;
766 * Step #1: Get a list of user rids that are the members of the group.
768 status = dcerpc_samr_QueryGroupMember(b,
769 mem_ctx,
770 &group_policy,
771 &rids,
772 &result);
774 NTSTATUS _result;
775 dcerpc_samr_Close(b, mem_ctx, &group_policy, &_result);
778 if (!NT_STATUS_IS_OK(status)) {
779 return status;
781 if (!NT_STATUS_IS_OK(result)) {
782 return result;
786 if (rids == NULL || rids->count == 0) {
787 pnum_names = 0;
788 pnames = NULL;
789 pname_types = NULL;
790 psid_mem = NULL;
792 return NT_STATUS_OK;
795 num_names = rids->count;
796 rid_mem = rids->rids;
798 break;
800 case SID_NAME_WKN_GRP:
801 case SID_NAME_ALIAS:
803 struct lsa_SidArray sid_array;
804 struct lsa_SidPtr sid_ptr;
805 struct samr_Ids rids_query;
807 sid_ptr.sid = dom_sid_dup(mem_ctx, group_sid);
808 if (sid_ptr.sid == NULL) {
809 return NT_STATUS_NO_MEMORY;
812 sid_array.num_sids = 1;
813 sid_array.sids = &sid_ptr;
815 status = dcerpc_samr_GetAliasMembership(b,
816 mem_ctx,
817 samr_policy,
818 &sid_array,
819 &rids_query,
820 &result);
821 if (!NT_STATUS_IS_OK(status)) {
822 return status;
824 if (!NT_STATUS_IS_OK(result)) {
825 return result;
828 if (rids_query.count == 0) {
829 pnum_names = 0;
830 pnames = NULL;
831 pname_types = NULL;
832 psid_mem = NULL;
834 return NT_STATUS_OK;
837 num_names = rids_query.count;
838 rid_mem = rids_query.ids;
840 break;
842 default:
843 return NT_STATUS_UNSUCCESSFUL;
847 * Step #2: Convert list of rids into list of usernames.
849 if (num_names > 0) {
850 names = talloc_zero_array(mem_ctx, char *, num_names);
851 name_types = talloc_zero_array(mem_ctx, uint32_t, num_names);
852 sid_mem = talloc_zero_array(mem_ctx, struct dom_sid, num_names);
853 if (names == NULL || name_types == NULL || sid_mem == NULL) {
854 return NT_STATUS_NO_MEMORY;
858 for (j = 0; j < num_names; j++) {
859 sid_compose(&sid_mem[j], domain_sid, rid_mem[j]);
862 status = dcerpc_samr_LookupRids(b,
863 mem_ctx,
864 samr_policy,
865 num_names,
866 rid_mem,
867 &tmp_names,
868 &tmp_types,
869 &result);
870 if (!NT_STATUS_IS_OK(status)) {
871 return status;
874 if (!NT_STATUS_IS_OK(result)) {
875 if (!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
876 return result;
880 /* Copy result into array. The talloc system will take
881 care of freeing the temporary arrays later on. */
882 if (tmp_names.count != num_names) {
883 return NT_STATUS_INVALID_NETWORK_RESPONSE;
885 if (tmp_types.count != num_names) {
886 return NT_STATUS_INVALID_NETWORK_RESPONSE;
889 for (r = 0; r < tmp_names.count; r++) {
890 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
891 continue;
893 if (total_names >= num_names) {
894 break;
896 names[total_names] = fill_domain_username_talloc(names,
897 domain_name,
898 tmp_names.names[r].string,
899 true);
900 if (names[total_names] == NULL) {
901 return NT_STATUS_NO_MEMORY;
903 name_types[total_names] = tmp_types.ids[r];
904 total_names++;
907 *pnum_names = total_names;
908 *pnames = names;
909 *pname_types = name_types;
910 *psid_mem = sid_mem;
912 return NT_STATUS_OK;
915 /* Find the sequence number for a domain */
916 NTSTATUS rpc_sequence_number(TALLOC_CTX *mem_ctx,
917 struct rpc_pipe_client *samr_pipe,
918 struct policy_handle *samr_policy,
919 const char *domain_name,
920 uint32_t *pseq)
922 union samr_DomainInfo *info = NULL;
923 bool got_seq_num = false;
924 NTSTATUS status, result;
925 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
927 /* query domain info */
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->info8.sequence_num;
936 got_seq_num = true;
937 goto seq_num;
940 /* retry with info-level 2 in case the dc does not support info-level 8
941 * (like all older samba2 and samba3 dc's) - Guenther */
942 status = dcerpc_samr_QueryDomainInfo(b,
943 mem_ctx,
944 samr_policy,
946 &info,
947 &result);
948 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
949 *pseq = info->general.sequence_num;
950 got_seq_num = true;
951 goto seq_num;
954 if (!NT_STATUS_IS_OK(status)) {
955 goto seq_num;
958 status = result;
960 seq_num:
961 if (got_seq_num) {
962 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
963 domain_name, (unsigned) *pseq));
964 } else {
965 DEBUG(10,("domain_sequence_number: failed to get sequence "
966 "number (%u) for domain %s\n",
967 (unsigned) *pseq, domain_name ));
968 status = NT_STATUS_OK;
971 return status;
974 /* Get a list of trusted domains */
975 NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
976 struct rpc_pipe_client *lsa_pipe,
977 struct policy_handle *lsa_policy,
978 uint32_t *pnum_trusts,
979 struct netr_DomainTrust **ptrusts)
981 struct netr_DomainTrust *array = NULL;
982 uint32_t enum_ctx = 0;
983 uint32_t count = 0;
984 NTSTATUS status, result;
985 struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
987 do {
988 struct lsa_DomainList dom_list;
989 struct lsa_DomainListEx dom_list_ex;
990 bool has_ex = false;
991 uint32_t i;
994 * We don't run into deadlocks here, cause winbind_off() is
995 * called in the main function.
997 status = dcerpc_lsa_EnumTrustedDomainsEx(b,
998 mem_ctx,
999 lsa_policy,
1000 &enum_ctx,
1001 &dom_list_ex,
1002 (uint32_t) -1,
1003 &result);
1004 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_ERR(result) &&
1005 dom_list_ex.count > 0) {
1006 count += dom_list_ex.count;
1007 has_ex = true;
1008 } else {
1009 status = dcerpc_lsa_EnumTrustDom(b,
1010 mem_ctx,
1011 lsa_policy,
1012 &enum_ctx,
1013 &dom_list,
1014 (uint32_t) -1,
1015 &result);
1016 if (!NT_STATUS_IS_OK(status)) {
1017 return status;
1019 if (!NT_STATUS_IS_OK(result)) {
1020 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1021 return result;
1025 count += dom_list.count;
1028 array = talloc_realloc(mem_ctx,
1029 array,
1030 struct netr_DomainTrust,
1031 count);
1032 if (array == NULL) {
1033 return NT_STATUS_NO_MEMORY;
1036 for (i = 0; i < count; i++) {
1037 struct netr_DomainTrust *trust = &array[i];
1038 struct dom_sid *sid;
1040 ZERO_STRUCTP(trust);
1042 sid = talloc(array, struct dom_sid);
1043 if (sid == NULL) {
1044 return NT_STATUS_NO_MEMORY;
1047 if (has_ex) {
1048 trust->netbios_name = talloc_move(array,
1049 &dom_list_ex.domains[i].netbios_name.string);
1050 trust->dns_name = talloc_move(array,
1051 &dom_list_ex.domains[i].domain_name.string);
1052 if (dom_list_ex.domains[i].sid == NULL) {
1053 DEBUG(0, ("Trusted Domain %s has no SID, aborting!\n", trust->dns_name));
1054 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1056 sid_copy(sid, dom_list_ex.domains[i].sid);
1057 } else {
1058 trust->netbios_name = talloc_move(array,
1059 &dom_list.domains[i].name.string);
1060 trust->dns_name = NULL;
1062 if (dom_list.domains[i].sid == NULL) {
1063 DEBUG(0, ("Trusted Domain %s has no SID, aborting!\n", trust->netbios_name));
1064 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1067 sid_copy(sid, dom_list.domains[i].sid);
1070 trust->sid = sid;
1072 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1074 *pnum_trusts = count;
1075 *ptrusts = array;
1077 return NT_STATUS_OK;
1080 static NTSTATUS rpc_try_lookup_sids3(TALLOC_CTX *mem_ctx,
1081 struct winbindd_domain *domain,
1082 struct rpc_pipe_client *cli,
1083 struct lsa_SidArray *sids,
1084 struct lsa_RefDomainList **pdomains,
1085 struct lsa_TransNameArray **pnames)
1087 struct lsa_TransNameArray2 lsa_names2;
1088 struct lsa_TransNameArray *names = *pnames;
1089 uint32_t i, count = 0;
1090 NTSTATUS status, result;
1092 ZERO_STRUCT(lsa_names2);
1093 status = dcerpc_lsa_LookupSids3(cli->binding_handle,
1094 mem_ctx,
1095 sids,
1096 pdomains,
1097 &lsa_names2,
1098 LSA_LOOKUP_NAMES_ALL,
1099 &count,
1100 LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
1101 LSA_CLIENT_REVISION_2,
1102 &result);
1103 if (!NT_STATUS_IS_OK(status)) {
1104 return status;
1106 if (NT_STATUS_IS_ERR(result)) {
1107 return result;
1109 if (sids->num_sids != lsa_names2.count) {
1110 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1113 names->count = lsa_names2.count;
1114 names->names = talloc_array(names, struct lsa_TranslatedName,
1115 names->count);
1116 if (names->names == NULL) {
1117 return NT_STATUS_NO_MEMORY;
1119 for (i=0; i<names->count; i++) {
1120 names->names[i].sid_type = lsa_names2.names[i].sid_type;
1121 names->names[i].name.string = talloc_move(
1122 names->names, &lsa_names2.names[i].name.string);
1123 names->names[i].sid_index = lsa_names2.names[i].sid_index;
1125 if (names->names[i].sid_index == UINT32_MAX) {
1126 continue;
1128 if ((*pdomains) == NULL) {
1129 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1131 if (names->names[i].sid_index >= (*pdomains)->count) {
1132 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1135 return result;
1138 NTSTATUS rpc_lookup_sids(TALLOC_CTX *mem_ctx,
1139 struct winbindd_domain *domain,
1140 struct lsa_SidArray *sids,
1141 struct lsa_RefDomainList **pdomains,
1142 struct lsa_TransNameArray **pnames)
1144 struct lsa_TransNameArray *names = *pnames;
1145 struct rpc_pipe_client *cli = NULL;
1146 struct policy_handle lsa_policy;
1147 uint32_t count;
1148 uint32_t i;
1149 NTSTATUS status, result;
1151 status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
1152 if (!NT_STATUS_IS_OK(status)) {
1153 return status;
1156 if (cli->transport->transport == NCACN_IP_TCP) {
1157 return rpc_try_lookup_sids3(mem_ctx, domain, cli, sids,
1158 pdomains, pnames);
1161 status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
1162 &lsa_policy, sids, pdomains,
1163 names, LSA_LOOKUP_NAMES_ALL,
1164 &count, &result);
1165 if (!NT_STATUS_IS_OK(status)) {
1166 return status;
1168 if (NT_STATUS_IS_ERR(result)) {
1169 return result;
1172 if (sids->num_sids != names->count) {
1173 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1176 for (i=0; i < names->count; i++) {
1177 if (names->names[i].sid_index == UINT32_MAX) {
1178 continue;
1180 if ((*pdomains) == NULL) {
1181 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1183 if (names->names[i].sid_index >= (*pdomains)->count) {
1184 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1188 return result;