2 Unix SMB/CIFS implementation.
4 Winbind rpc backend functions
6 Copyright (C) Tim Potter 2000-2001,2003
7 Copyright (C) Andrew Tridgell 2001
8 Copyright (C) Volker Lendecke 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #define DBGC_CLASS DBGC_WINBIND
32 /* Query display info for a domain. This returns enough information plus a
33 bit extra to give an overview of domain users for the User Manager
35 static NTSTATUS
query_user_list(struct winbindd_domain
*domain
,
38 WINBIND_USERINFO
**info
)
42 unsigned int i
, start_idx
;
44 struct rpc_pipe_client
*cli
;
46 DEBUG(3,("rpc: query_user_list\n"));
51 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
52 if (!NT_STATUS_IS_OK(result
))
60 uint32 num_dom_users
, j
;
61 uint32 max_entries
, max_size
;
67 ctr
.sam
.info1
= &info1
;
69 if (!(ctx2
= talloc_init("winbindd enum_users")))
70 return NT_STATUS_NO_MEMORY
;
72 /* this next bit is copied from net_user_list_internal() */
74 get_query_dispinfo_params(loop_count
, &max_entries
,
77 result
= rpccli_samr_query_dispinfo(cli
, mem_ctx
, &dom_pol
,
80 max_entries
, max_size
,
85 *num_entries
+= num_dom_users
;
87 *info
= TALLOC_REALLOC_ARRAY(mem_ctx
, *info
, WINBIND_USERINFO
,
92 return NT_STATUS_NO_MEMORY
;
95 for (j
= 0; j
< num_dom_users
; i
++, j
++) {
96 fstring username
, fullname
;
97 uint32 rid
= ctr
.sam
.info1
->sam
[j
].rid_user
;
99 unistr2_to_ascii( username
, &(&ctr
.sam
.info1
->str
[j
])->uni_acct_name
, sizeof(username
)-1);
100 unistr2_to_ascii( fullname
, &(&ctr
.sam
.info1
->str
[j
])->uni_full_name
, sizeof(fullname
)-1);
102 (*info
)[i
].acct_name
= talloc_strdup(mem_ctx
, username
);
103 (*info
)[i
].full_name
= talloc_strdup(mem_ctx
, fullname
);
104 (*info
)[i
].homedir
= NULL
;
105 (*info
)[i
].shell
= NULL
;
106 sid_compose(&(*info
)[i
].user_sid
, &domain
->sid
, rid
);
108 /* For the moment we set the primary group for
109 every user to be the Domain Users group.
110 There are serious problems with determining
111 the actual primary group for large domains.
112 This should really be made into a 'winbind
113 force group' smb.conf parameter or
114 something like that. */
116 sid_compose(&(*info
)[i
].group_sid
, &domain
->sid
,
117 DOMAIN_GROUP_RID_USERS
);
120 talloc_destroy(ctx2
);
122 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
127 /* list all domain groups */
128 static NTSTATUS
enum_dom_groups(struct winbindd_domain
*domain
,
131 struct acct_info
**info
)
136 struct rpc_pipe_client
*cli
;
141 DEBUG(3,("rpc: enum_dom_groups\n"));
143 status
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
144 if (!NT_STATUS_IS_OK(status
))
148 struct acct_info
*info2
= NULL
;
150 TALLOC_CTX
*mem_ctx2
;
152 mem_ctx2
= talloc_init("enum_dom_groups[rpc]");
154 /* start is updated by this call. */
155 status
= rpccli_samr_enum_dom_groups(cli
, mem_ctx2
, &dom_pol
,
157 0xFFFF, /* buffer size? */
160 if (!NT_STATUS_IS_OK(status
) &&
161 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
162 talloc_destroy(mem_ctx2
);
166 (*info
) = TALLOC_REALLOC_ARRAY(mem_ctx
, *info
,
168 (*num_entries
) + count
);
170 talloc_destroy(mem_ctx2
);
171 status
= NT_STATUS_NO_MEMORY
;
175 memcpy(&(*info
)[*num_entries
], info2
, count
*sizeof(*info2
));
176 (*num_entries
) += count
;
177 talloc_destroy(mem_ctx2
);
178 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
183 /* List all domain groups */
185 static NTSTATUS
enum_local_groups(struct winbindd_domain
*domain
,
188 struct acct_info
**info
)
192 struct rpc_pipe_client
*cli
;
197 DEBUG(3,("rpc: enum_local_groups\n"));
199 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
200 if (!NT_STATUS_IS_OK(result
))
204 struct acct_info
*info2
= NULL
;
205 uint32 count
= 0, start
= *num_entries
;
206 TALLOC_CTX
*mem_ctx2
;
208 mem_ctx2
= talloc_init("enum_dom_local_groups[rpc]");
210 result
= rpccli_samr_enum_als_groups( cli
, mem_ctx2
, &dom_pol
,
211 &start
, 0xFFFF, &info2
,
214 if (!NT_STATUS_IS_OK(result
) &&
215 !NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
) )
217 talloc_destroy(mem_ctx2
);
221 (*info
) = TALLOC_REALLOC_ARRAY(mem_ctx
, *info
,
223 (*num_entries
) + count
);
225 talloc_destroy(mem_ctx2
);
226 return NT_STATUS_NO_MEMORY
;
229 memcpy(&(*info
)[*num_entries
], info2
, count
*sizeof(*info2
));
230 (*num_entries
) += count
;
231 talloc_destroy(mem_ctx2
);
233 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
238 /* convert a single name to a sid in a domain */
239 NTSTATUS
msrpc_name_to_sid(struct winbindd_domain
*domain
,
241 const char *domain_name
,
244 enum SID_NAME_USE
*type
)
247 DOM_SID
*sids
= NULL
;
248 uint32
*types
= NULL
;
249 const char *full_name
;
250 struct rpc_pipe_client
*cli
;
251 POLICY_HND lsa_policy
;
253 if(name
== NULL
|| *name
=='\0') {
254 DEBUG(3,("rpc: name_to_sid name=%s\n", domain_name
));
255 full_name
= talloc_asprintf(mem_ctx
, "%s", domain_name
);
257 DEBUG(3,("rpc: name_to_sid name=%s\\%s\n", domain_name
, name
));
258 full_name
= talloc_asprintf(mem_ctx
, "%s\\%s", domain_name
, name
);
261 DEBUG(0, ("talloc_asprintf failed!\n"));
262 return NT_STATUS_NO_MEMORY
;
265 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name
?full_name
:"", domain_name
));
267 result
= cm_connect_lsa(domain
, mem_ctx
, &cli
, &lsa_policy
);
268 if (!NT_STATUS_IS_OK(result
))
271 result
= rpccli_lsa_lookup_names(cli
, mem_ctx
, &lsa_policy
, 1,
272 &full_name
, NULL
, &sids
, &types
);
274 if (!NT_STATUS_IS_OK(result
))
277 /* Return rid and type if lookup successful */
279 sid_copy(sid
, &sids
[0]);
280 *type
= (enum SID_NAME_USE
)types
[0];
286 convert a domain SID to a user or group name
288 NTSTATUS
msrpc_sid_to_name(struct winbindd_domain
*domain
,
293 enum SID_NAME_USE
*type
)
299 struct rpc_pipe_client
*cli
;
300 POLICY_HND lsa_policy
;
302 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid
),
305 result
= cm_connect_lsa(domain
, mem_ctx
, &cli
, &lsa_policy
);
306 if (!NT_STATUS_IS_OK(result
))
309 result
= rpccli_lsa_lookup_sids(cli
, mem_ctx
, &lsa_policy
,
310 1, sid
, &domains
, &names
, &types
);
311 if (!NT_STATUS_IS_OK(result
))
314 *type
= (enum SID_NAME_USE
)types
[0];
315 *domain_name
= domains
[0];
317 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains
[0], *name
));
321 /* Lookup user information from a rid or username. */
322 static NTSTATUS
query_user(struct winbindd_domain
*domain
,
324 const DOM_SID
*user_sid
,
325 WINBIND_USERINFO
*user_info
)
327 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
328 POLICY_HND dom_pol
, user_pol
;
329 SAM_USERINFO_CTR
*ctr
;
332 NET_USER_INFO_3
*user
;
333 struct rpc_pipe_client
*cli
;
335 DEBUG(3,("rpc: query_user rid=%s\n",
336 sid_to_string(sid_string
, user_sid
)));
338 if (!sid_peek_check_rid(&domain
->sid
, user_sid
, &user_rid
))
339 return NT_STATUS_UNSUCCESSFUL
;
341 /* try netsamlogon cache first */
343 if ( (user
= netsamlogon_cache_get( mem_ctx
, user_sid
)) != NULL
)
346 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
347 sid_string_static(user_sid
)));
349 sid_compose(&user_info
->user_sid
, &domain
->sid
, user_rid
);
350 sid_compose(&user_info
->group_sid
, &domain
->sid
,
353 user_info
->acct_name
= unistr2_tdup(mem_ctx
,
354 &user
->uni_user_name
);
355 user_info
->full_name
= unistr2_tdup(mem_ctx
,
356 &user
->uni_full_name
);
358 user_info
->homedir
= NULL
;
359 user_info
->shell
= NULL
;
366 /* no cache; hit the wire */
368 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
369 if (!NT_STATUS_IS_OK(result
))
372 /* Get user handle */
373 result
= rpccli_samr_open_user(cli
, mem_ctx
, &dom_pol
,
374 SEC_RIGHTS_MAXIMUM_ALLOWED
, user_rid
,
377 if (!NT_STATUS_IS_OK(result
))
381 result
= rpccli_samr_query_userinfo(cli
, mem_ctx
, &user_pol
,
384 rpccli_samr_close(cli
, mem_ctx
, &user_pol
);
386 if (!NT_STATUS_IS_OK(result
))
389 sid_compose(&user_info
->user_sid
, &domain
->sid
, user_rid
);
390 sid_compose(&user_info
->group_sid
, &domain
->sid
,
391 ctr
->info
.id21
->group_rid
);
392 user_info
->acct_name
= unistr2_tdup(mem_ctx
,
393 &ctr
->info
.id21
->uni_user_name
);
394 user_info
->full_name
= unistr2_tdup(mem_ctx
,
395 &ctr
->info
.id21
->uni_full_name
);
396 user_info
->homedir
= NULL
;
397 user_info
->shell
= NULL
;
402 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
403 static NTSTATUS
lookup_usergroups(struct winbindd_domain
*domain
,
405 const DOM_SID
*user_sid
,
406 uint32
*num_groups
, DOM_SID
**user_grpsids
)
408 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
409 POLICY_HND dom_pol
, user_pol
;
410 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
411 DOM_GID
*user_groups
;
415 struct rpc_pipe_client
*cli
;
417 DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
418 sid_to_string(sid_string
, user_sid
)));
420 if (!sid_peek_check_rid(&domain
->sid
, user_sid
, &user_rid
))
421 return NT_STATUS_UNSUCCESSFUL
;
424 *user_grpsids
= NULL
;
426 /* so lets see if we have a cached user_info_3 */
427 result
= lookup_usergroups_cached(domain
, mem_ctx
, user_sid
,
428 num_groups
, user_grpsids
);
430 if (NT_STATUS_IS_OK(result
)) {
434 /* no cache; hit the wire */
436 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
437 if (!NT_STATUS_IS_OK(result
))
440 /* Get user handle */
441 result
= rpccli_samr_open_user(cli
, mem_ctx
, &dom_pol
,
442 des_access
, user_rid
, &user_pol
);
444 if (!NT_STATUS_IS_OK(result
))
447 /* Query user rids */
448 result
= rpccli_samr_query_usergroups(cli
, mem_ctx
, &user_pol
,
449 num_groups
, &user_groups
);
451 rpccli_samr_close(cli
, mem_ctx
, &user_pol
);
453 if (!NT_STATUS_IS_OK(result
) || (*num_groups
) == 0)
456 (*user_grpsids
) = TALLOC_ARRAY(mem_ctx
, DOM_SID
, *num_groups
);
457 if (!(*user_grpsids
))
458 return NT_STATUS_NO_MEMORY
;
460 for (i
=0;i
<(*num_groups
);i
++) {
461 sid_copy(&((*user_grpsids
)[i
]), &domain
->sid
);
462 sid_append_rid(&((*user_grpsids
)[i
]),
463 user_groups
[i
].g_rid
);
469 NTSTATUS
msrpc_lookup_useraliases(struct winbindd_domain
*domain
,
471 uint32 num_sids
, const DOM_SID
*sids
,
472 uint32
*num_aliases
, uint32
**alias_rids
)
474 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
476 DOM_SID2
*query_sids
;
477 uint32 num_query_sids
= 0;
479 struct rpc_pipe_client
*cli
;
480 uint32
*alias_rids_query
, num_aliases_query
;
481 int rangesize
= MAX_SAM_ENTRIES_W2K
;
482 uint32 total_sids
= 0;
488 DEBUG(3,("rpc: lookup_useraliases\n"));
490 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
491 if (!NT_STATUS_IS_OK(result
))
497 num_query_sids
= MIN(num_sids
- total_sids
, rangesize
);
499 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
500 num_queries
, num_query_sids
));
503 query_sids
= TALLOC_ARRAY(mem_ctx
, DOM_SID2
, num_query_sids
);
504 if (query_sids
== NULL
) {
505 return NT_STATUS_NO_MEMORY
;
508 for (i
=0; i
<num_query_sids
; i
++) {
509 sid_copy(&query_sids
[i
].sid
, &sids
[total_sids
++]);
510 query_sids
[i
].num_auths
= query_sids
[i
].sid
.num_auths
;
515 result
= rpccli_samr_query_useraliases(cli
, mem_ctx
, &dom_pol
,
516 num_query_sids
, query_sids
,
520 if (!NT_STATUS_IS_OK(result
)) {
523 TALLOC_FREE(query_sids
);
529 for (i
=0; i
<num_aliases_query
; i
++) {
530 size_t na
= *num_aliases
;
531 add_rid_to_array_unique(mem_ctx
, alias_rids_query
[i
],
536 TALLOC_FREE(query_sids
);
540 } while (total_sids
< num_sids
);
543 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
544 "(rangesize: %d)\n", *num_aliases
, num_queries
, rangesize
));
550 /* Lookup group membership given a rid. */
551 static NTSTATUS
lookup_groupmem(struct winbindd_domain
*domain
,
553 const DOM_SID
*group_sid
, uint32
*num_names
,
554 DOM_SID
**sid_mem
, char ***names
,
557 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
558 uint32 i
, total_names
= 0;
559 POLICY_HND dom_pol
, group_pol
;
560 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
561 uint32
*rid_mem
= NULL
;
565 struct rpc_pipe_client
*cli
;
567 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain
->name
,
568 sid_to_string(sid_string
, group_sid
)));
570 if (!sid_peek_check_rid(&domain
->sid
, group_sid
, &group_rid
))
571 return NT_STATUS_UNSUCCESSFUL
;
575 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
576 if (!NT_STATUS_IS_OK(result
))
579 result
= rpccli_samr_open_group(cli
, mem_ctx
, &dom_pol
,
580 des_access
, group_rid
, &group_pol
);
582 if (!NT_STATUS_IS_OK(result
))
585 /* Step #1: Get a list of user rids that are the members of the
588 result
= rpccli_samr_query_groupmem(cli
, mem_ctx
,
589 &group_pol
, num_names
, &rid_mem
,
592 rpccli_samr_close(cli
, mem_ctx
, &group_pol
);
594 if (!NT_STATUS_IS_OK(result
))
604 /* Step #2: Convert list of rids into list of usernames. Do this
605 in bunches of ~1000 to avoid crashing NT4. It looks like there
606 is a buffer overflow or something like that lurking around
609 #define MAX_LOOKUP_RIDS 900
611 *names
= TALLOC_ZERO_ARRAY(mem_ctx
, char *, *num_names
);
612 *name_types
= TALLOC_ZERO_ARRAY(mem_ctx
, uint32
, *num_names
);
613 *sid_mem
= TALLOC_ZERO_ARRAY(mem_ctx
, DOM_SID
, *num_names
);
615 for (j
=0;j
<(*num_names
);j
++)
616 sid_compose(&(*sid_mem
)[j
], &domain
->sid
, rid_mem
[j
]);
618 if (*num_names
>0 && (!*names
|| !*name_types
))
619 return NT_STATUS_NO_MEMORY
;
621 for (i
= 0; i
< *num_names
; i
+= MAX_LOOKUP_RIDS
) {
622 int num_lookup_rids
= MIN(*num_names
- i
, MAX_LOOKUP_RIDS
);
623 uint32 tmp_num_names
= 0;
624 char **tmp_names
= NULL
;
625 uint32
*tmp_types
= NULL
;
627 /* Lookup a chunk of rids */
629 result
= rpccli_samr_lookup_rids(cli
, mem_ctx
,
634 &tmp_names
, &tmp_types
);
636 /* see if we have a real error (and yes the
637 STATUS_SOME_UNMAPPED is the one returned from 2k) */
639 if (!NT_STATUS_IS_OK(result
) &&
640 !NT_STATUS_EQUAL(result
, STATUS_SOME_UNMAPPED
))
643 /* Copy result into array. The talloc system will take
644 care of freeing the temporary arrays later on. */
646 memcpy(&(*names
)[i
], tmp_names
, sizeof(char *) *
649 memcpy(&(*name_types
)[i
], tmp_types
, sizeof(uint32
) *
652 total_names
+= tmp_num_names
;
655 *num_names
= total_names
;
664 static int get_ldap_seq(const char *server
, int port
, uint32
*seq
)
668 const char *attrs
[] = {"highestCommittedUSN", NULL
};
669 LDAPMessage
*res
= NULL
;
670 char **values
= NULL
;
673 *seq
= DOM_SEQUENCE_NONE
;
676 * Parameterised (5) second timeout on open. This is needed as the
677 * search timeout doesn't seem to apply to doing an open as well. JRA.
680 ldp
= ldap_open_with_timeout(server
, port
, lp_ldap_timeout());
684 /* Timeout if no response within 20 seconds. */
688 if (ldap_search_st(ldp
, "", LDAP_SCOPE_BASE
, "(objectclass=*)",
689 CONST_DISCARD(char **, attrs
), 0, &to
, &res
))
692 if (ldap_count_entries(ldp
, res
) != 1)
695 values
= ldap_get_values(ldp
, res
, "highestCommittedUSN");
696 if (!values
|| !values
[0])
699 *seq
= atoi(values
[0]);
705 ldap_value_free(values
);
713 /**********************************************************************
714 Get the sequence number for a Windows AD native mode domain using
716 **********************************************************************/
718 static int get_ldap_sequence_number( const char* domain
, uint32
*seq
)
721 int i
, port
= LDAP_PORT
;
722 struct ip_service
*ip_list
= NULL
;
725 if ( !get_sorted_dc_list(domain
, &ip_list
, &count
, False
) ) {
726 DEBUG(3, ("Could not look up dc's for domain %s\n", domain
));
730 /* Finally return first DC that we can contact */
732 for (i
= 0; i
< count
; i
++) {
735 /* since the is an LDAP lookup, default to the LDAP_PORT is
737 port
= (ip_list
[i
].port
!= PORT_NONE
) ?
738 ip_list
[i
].port
: LDAP_PORT
;
740 fstrcpy( ipstr
, inet_ntoa(ip_list
[i
].ip
) );
742 if (is_zero_ip(ip_list
[i
].ip
))
745 if ( (ret
= get_ldap_seq( ipstr
, port
, seq
)) == 0 )
748 /* add to failed connection cache */
749 add_failed_connection_entry( domain
, ipstr
,
750 NT_STATUS_UNSUCCESSFUL
);
755 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
756 "number for Domain (%s) from DC (%s:%d)\n",
757 domain
, inet_ntoa(ip_list
[i
].ip
), port
));
765 #endif /* HAVE_LDAP */
767 /* find the sequence number for a domain */
768 static NTSTATUS
sequence_number(struct winbindd_domain
*domain
, uint32
*seq
)
774 BOOL got_seq_num
= False
;
776 struct rpc_pipe_client
*cli
;
778 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain
->name
));
780 *seq
= DOM_SEQUENCE_NONE
;
782 if (!(mem_ctx
= talloc_init("sequence_number[rpc]")))
783 return NT_STATUS_NO_MEMORY
;
788 if ( domain
->native_mode
)
792 DEBUG(8,("using get_ldap_seq() to retrieve the "
793 "sequence number\n"));
795 res
= get_ldap_sequence_number( domain
->name
, seq
);
798 result
= NT_STATUS_OK
;
799 DEBUG(10,("domain_sequence_number: LDAP for "
801 domain
->name
, *seq
));
805 DEBUG(10,("domain_sequence_number: failed to get LDAP "
806 "sequence number for domain %s\n",
809 #endif /* HAVE_LDAP */
811 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
812 if (!NT_STATUS_IS_OK(result
)) {
816 /* Query domain info */
818 result
= rpccli_samr_query_dom_info(cli
, mem_ctx
, &dom_pol
, 8, &ctr
);
820 if (NT_STATUS_IS_OK(result
)) {
821 *seq
= ctr
.info
.inf8
.seq_num
.low
;
826 /* retry with info-level 2 in case the dc does not support info-level 8
827 * (like all older samba2 and samba3 dc's - Guenther */
829 result
= rpccli_samr_query_dom_info(cli
, mem_ctx
, &dom_pol
, 2, &ctr
);
831 if (NT_STATUS_IS_OK(result
)) {
832 *seq
= ctr
.info
.inf2
.seq_num
.low
;
838 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
839 domain
->name
, (unsigned)*seq
));
841 DEBUG(10,("domain_sequence_number: failed to get sequence "
842 "number (%u) for domain %s\n",
843 (unsigned)*seq
, domain
->name
));
848 talloc_destroy(mem_ctx
);
853 /* get a list of trusted domains */
854 static NTSTATUS
trusted_domains(struct winbindd_domain
*domain
,
861 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
863 struct rpc_pipe_client
*cli
;
864 POLICY_HND lsa_policy
;
866 DEBUG(3,("rpc: trusted_domains\n"));
873 result
= cm_connect_lsa(domain
, mem_ctx
, &cli
, &lsa_policy
);
874 if (!NT_STATUS_IS_OK(result
))
877 result
= STATUS_MORE_ENTRIES
;
879 while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
)) {
880 uint32 start_idx
, num
;
885 result
= rpccli_lsa_enum_trust_dom(cli
, mem_ctx
,
886 &lsa_policy
, &enum_ctx
,
890 if (!NT_STATUS_IS_OK(result
) &&
891 !NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
))
894 start_idx
= *num_domains
;
896 *names
= TALLOC_REALLOC_ARRAY(mem_ctx
, *names
,
897 char *, *num_domains
);
898 *dom_sids
= TALLOC_REALLOC_ARRAY(mem_ctx
, *dom_sids
,
899 DOM_SID
, *num_domains
);
900 *alt_names
= TALLOC_REALLOC_ARRAY(mem_ctx
, *alt_names
,
901 char *, *num_domains
);
902 if ((*names
== NULL
) || (*dom_sids
== NULL
) ||
903 (*alt_names
== NULL
))
904 return NT_STATUS_NO_MEMORY
;
906 for (i
=0; i
<num
; i
++) {
907 (*names
)[start_idx
+i
] = tmp_names
[i
];
908 (*dom_sids
)[start_idx
+i
] = tmp_sids
[i
];
909 (*alt_names
)[start_idx
+i
] = talloc_strdup(mem_ctx
, "");
915 /* find the lockout policy for a domain */
916 NTSTATUS
msrpc_lockout_policy(struct winbindd_domain
*domain
,
918 SAM_UNK_INFO_12
*lockout_policy
)
921 struct rpc_pipe_client
*cli
;
925 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain
->name
));
927 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
928 if (!NT_STATUS_IS_OK(result
)) {
932 result
= rpccli_samr_query_dom_info(cli
, mem_ctx
, &dom_pol
, 12, &ctr
);
933 if (!NT_STATUS_IS_OK(result
)) {
937 *lockout_policy
= ctr
.info
.inf12
;
939 DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n",
940 ctr
.info
.inf12
.bad_attempt_lockout
));
947 /* find the password policy for a domain */
948 NTSTATUS
msrpc_password_policy(struct winbindd_domain
*domain
,
950 SAM_UNK_INFO_1
*password_policy
)
953 struct rpc_pipe_client
*cli
;
957 DEBUG(10,("rpc: fetch password policy for %s\n", domain
->name
));
959 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
960 if (!NT_STATUS_IS_OK(result
)) {
964 result
= rpccli_samr_query_dom_info(cli
, mem_ctx
, &dom_pol
, 1, &ctr
);
965 if (!NT_STATUS_IS_OK(result
)) {
969 *password_policy
= ctr
.info
.inf1
;
971 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
972 ctr
.info
.inf1
.min_length_password
));
980 /* the rpc backend methods are exposed via this structure */
981 struct winbindd_methods msrpc_methods
= {
990 msrpc_lookup_useraliases
,
993 msrpc_lockout_policy
,
994 msrpc_password_policy
,