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/>.
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
,
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;
51 NTSTATUS status
, result
;
52 struct dcerpc_binding_handle
*b
= samr_pipe
->binding_handle
;
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
,
67 status
= dcerpc_samr_QueryDisplayInfo(b
,
78 if (!NT_STATUS_IS_OK(status
)) {
81 if (!NT_STATUS_IS_OK(result
)) {
82 if (!NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
)) {
87 /* increment required start query values */
88 start_idx
+= disp_info
.info1
.count
;
90 num_dom_users
= disp_info
.info1
.count
;
92 num_info
+= num_dom_users
;
94 info
= TALLOC_REALLOC_ARRAY(mem_ctx
,
96 struct wbint_userinfo
,
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
]);
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
;
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
,
138 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
140 *pnum_info
= num_info
;
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
,
151 struct acct_info
**pinfo
)
153 struct acct_info
*info
= NULL
;
155 uint32_t num_info
= 0;
156 NTSTATUS status
, result
;
157 struct dcerpc_binding_handle
*b
= samr_pipe
->binding_handle
;
162 struct samr_SamArray
*sam_array
= NULL
;
166 /* start is updated by this call. */
167 status
= dcerpc_samr_EnumDomainGroups(b
,
172 0xFFFF, /* buffer size? */
175 if (!NT_STATUS_IS_OK(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",
186 info
= TALLOC_REALLOC_ARRAY(mem_ctx
,
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
;
202 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
204 *pnum_info
= num_info
;
210 NTSTATUS
rpc_enum_local_groups(TALLOC_CTX
*mem_ctx
,
211 struct rpc_pipe_client
*samr_pipe
,
212 struct policy_handle
*samr_policy
,
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
;
224 struct samr_SamArray
*sam_array
= NULL
;
226 uint32_t start
= num_info
;
229 status
= dcerpc_samr_EnumDomainAliases(b
,
234 0xFFFF, /* buffer size? */
237 if (!NT_STATUS_IS_OK(status
)) {
240 if (!NT_STATUS_IS_OK(result
)) {
241 if (!NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
)) {
246 info
= TALLOC_REALLOC_ARRAY(mem_ctx
,
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
;
261 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
263 *pnum_info
= num_info
;
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
,
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
;
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
);
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
,
315 (const char **) &full_name
,
320 if (!NT_STATUS_IS_OK(status
)) {
321 DEBUG(2,("name_to_sid: failed to lookup name: %s\n",
326 sid_copy(sid
, &sids
[0]);
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
,
340 enum lsa_SidType
*ptype
)
342 char *mapped_name
= NULL
;
343 char **domains
= NULL
;
345 enum lsa_SidType
*types
= NULL
;
349 status
= rpccli_lsa_lookup_sids(lsa_pipe
,
357 if (!NT_STATUS_IS_OK(status
)) {
358 DEBUG(2,("sid_to_name: failed to lookup sids: %s\n",
363 *ptype
= (enum lsa_SidType
) types
[0];
365 map_status
= normalize_name_map(mem_ctx
,
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
));
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
;
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
,
398 enum lsa_SidType
**ptypes
)
400 enum lsa_SidType
*types
= NULL
;
401 char *domain_name
= NULL
;
402 char **domains
= NULL
;
404 struct dom_sid
*sids
;
409 sids
= TALLOC_ARRAY(mem_ctx
, struct dom_sid
, num_rids
);
411 return NT_STATUS_NO_MEMORY
;
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
,
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",
438 for (i
= 0; i
< num_rids
; i
++) {
439 char *mapped_name
= NULL
;
442 if (types
[i
] != SID_NAME_UNKNOWN
) {
443 map_status
= normalize_name_map(mem_ctx
,
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
;
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
;
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
,
489 SEC_FLAG_MAXIMUM_ALLOWED
,
493 if (!NT_STATUS_IS_OK(status
)) {
496 if (!NT_STATUS_IS_OK(result
)) {
501 status
= dcerpc_samr_QueryUserInfo(b
,
509 dcerpc_samr_Close(b
, mem_ctx
, &user_policy
, &_result
);
511 if (!NT_STATUS_IS_OK(status
)) {
514 if (!NT_STATUS_IS_OK(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;
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
;
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
,
568 SEC_FLAG_MAXIMUM_ALLOWED
,
572 if (!NT_STATUS_IS_OK(status
)) {
575 if (!NT_STATUS_IS_OK(result
)) {
579 /* Query user rids */
580 status
= dcerpc_samr_GetGroupsForUser(b
,
585 num_groups
= rid_array
->count
;
589 dcerpc_samr_Close(b
, mem_ctx
, &user_policy
, &_result
);
592 if (!NT_STATUS_IS_OK(status
)) {
595 if (!NT_STATUS_IS_OK(result
) || num_groups
== 0) {
599 user_grpsids
= TALLOC_ARRAY(mem_ctx
, struct dom_sid
, num_groups
);
600 if (user_grpsids
== NULL
) {
601 status
= NT_STATUS_NO_MEMORY
;
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
;
617 NTSTATUS
rpc_lookup_useraliases(TALLOC_CTX
*mem_ctx
,
618 struct rpc_pipe_client
*samr_pipe
,
619 struct policy_handle
*samr_policy
,
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
;
633 struct samr_Ids alias_rids_query
;
634 NTSTATUS status
, result
;
635 struct dcerpc_binding_handle
*b
= samr_pipe
->binding_handle
;
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
;
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
;
666 status
= dcerpc_samr_GetAliasMembership(b
,
672 if (!NT_STATUS_IS_OK(status
)) {
675 if (!NT_STATUS_IS_OK(result
)) {
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
],
687 return NT_STATUS_NO_MEMORY
;
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
;
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
,
717 uint32_t **pname_types
)
719 struct policy_handle group_policy
;
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
;
727 uint32_t *name_types
= NULL
;
729 struct lsa_Strings tmp_names
;
730 struct samr_Ids tmp_types
;
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
;
741 case SID_NAME_DOM_GRP
:
743 struct samr_RidAttrArray
*rids
= NULL
;
745 status
= dcerpc_samr_OpenGroup(b
,
748 SEC_FLAG_MAXIMUM_ALLOWED
,
752 if (!NT_STATUS_IS_OK(status
)) {
755 if (!NT_STATUS_IS_OK(result
)) {
760 * Step #1: Get a list of user rids that are the members of the group.
762 status
= dcerpc_samr_QueryGroupMember(b
,
769 dcerpc_samr_Close(b
, mem_ctx
, &group_policy
, &_result
);
772 if (!NT_STATUS_IS_OK(status
)) {
775 if (!NT_STATUS_IS_OK(result
)) {
780 if (rids
== NULL
|| rids
->count
== 0) {
789 num_names
= rids
->count
;
790 rid_mem
= rids
->rids
;
794 case SID_NAME_WKN_GRP
:
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
,
815 if (!NT_STATUS_IS_OK(status
)) {
818 if (!NT_STATUS_IS_OK(result
)) {
822 if (rids_query
.count
== 0) {
831 num_names
= rids_query
.count
;
832 rid_mem
= rids_query
.ids
;
837 return NT_STATUS_UNSUCCESSFUL
;
841 * Step #2: Convert list of rids into list of usernames.
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
,
864 if (!NT_STATUS_IS_OK(status
)) {
868 if (!NT_STATUS_IS_OK(result
)) {
869 if (!NT_STATUS_EQUAL(result
, STATUS_SOME_UNMAPPED
)) {
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
) {
884 names
[total_names
] = fill_domain_username_talloc(names
,
886 tmp_names
.names
[r
].string
,
888 if (names
[total_names
] == NULL
) {
889 return NT_STATUS_NO_MEMORY
;
891 name_types
[total_names
] = tmp_types
.ids
[r
];
895 *pnum_names
= total_names
;
897 *pname_types
= name_types
;
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
,
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
,
922 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
923 *pseq
= info
->info8
.sequence_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
,
936 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
937 *pseq
= info
->general
.sequence_num
;
942 if (!NT_STATUS_IS_OK(status
)) {
950 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
951 domain_name
, (unsigned) *pseq
));
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
;
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;
972 NTSTATUS status
, result
;
973 struct dcerpc_binding_handle
*b
= lsa_pipe
->binding_handle
;
976 struct lsa_DomainList dom_list
;
981 * We don't run into deadlocks here, cause winbind_off() is
982 * called in the main function.
984 status
= dcerpc_lsa_EnumTrustDom(b
,
991 if (!NT_STATUS_IS_OK(status
)) {
994 if (!NT_STATUS_IS_OK(result
)) {
995 if (!NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
)) {
1001 count
+= dom_list
.count
;
1003 array
= talloc_realloc(mem_ctx
,
1005 struct netr_DomainTrust
,
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
);
1023 return NT_STATUS_NO_MEMORY
;
1025 sid_copy(sid
, dom_list
.domains
[i
].sid
);
1028 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
1030 *pnum_trusts
= count
;
1033 return NT_STATUS_OK
;