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", name
?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
;
478 struct rpc_pipe_client
*cli
;
483 DEBUG(3,("rpc: lookup_useraliases\n"));
485 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
486 if (!NT_STATUS_IS_OK(result
))
489 sid2
= TALLOC_ARRAY(mem_ctx
, DOM_SID2
, num_sids
);
492 return NT_STATUS_NO_MEMORY
;
494 for (i
=0; i
<num_sids
; i
++) {
495 sid_copy(&sid2
[i
].sid
, &sids
[i
]);
496 sid2
[i
].num_auths
= sid2
[i
].sid
.num_auths
;
499 result
= rpccli_samr_query_useraliases(cli
, mem_ctx
, &dom_pol
,
501 num_aliases
, alias_rids
);
507 /* Lookup group membership given a rid. */
508 static NTSTATUS
lookup_groupmem(struct winbindd_domain
*domain
,
510 const DOM_SID
*group_sid
, uint32
*num_names
,
511 DOM_SID
**sid_mem
, char ***names
,
514 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
515 uint32 i
, total_names
= 0;
516 POLICY_HND dom_pol
, group_pol
;
517 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
518 uint32
*rid_mem
= NULL
;
522 struct rpc_pipe_client
*cli
;
524 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain
->name
,
525 sid_to_string(sid_string
, group_sid
)));
527 if (!sid_peek_check_rid(&domain
->sid
, group_sid
, &group_rid
))
528 return NT_STATUS_UNSUCCESSFUL
;
532 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
533 if (!NT_STATUS_IS_OK(result
))
536 result
= rpccli_samr_open_group(cli
, mem_ctx
, &dom_pol
,
537 des_access
, group_rid
, &group_pol
);
539 if (!NT_STATUS_IS_OK(result
))
542 /* Step #1: Get a list of user rids that are the members of the
545 result
= rpccli_samr_query_groupmem(cli
, mem_ctx
,
546 &group_pol
, num_names
, &rid_mem
,
549 rpccli_samr_close(cli
, mem_ctx
, &group_pol
);
551 if (!NT_STATUS_IS_OK(result
))
561 /* Step #2: Convert list of rids into list of usernames. Do this
562 in bunches of ~1000 to avoid crashing NT4. It looks like there
563 is a buffer overflow or something like that lurking around
566 #define MAX_LOOKUP_RIDS 900
568 *names
= TALLOC_ZERO_ARRAY(mem_ctx
, char *, *num_names
);
569 *name_types
= TALLOC_ZERO_ARRAY(mem_ctx
, uint32
, *num_names
);
570 *sid_mem
= TALLOC_ZERO_ARRAY(mem_ctx
, DOM_SID
, *num_names
);
572 for (j
=0;j
<(*num_names
);j
++)
573 sid_compose(&(*sid_mem
)[j
], &domain
->sid
, rid_mem
[j
]);
575 if (*num_names
>0 && (!*names
|| !*name_types
))
576 return NT_STATUS_NO_MEMORY
;
578 for (i
= 0; i
< *num_names
; i
+= MAX_LOOKUP_RIDS
) {
579 int num_lookup_rids
= MIN(*num_names
- i
, MAX_LOOKUP_RIDS
);
580 uint32 tmp_num_names
= 0;
581 char **tmp_names
= NULL
;
582 uint32
*tmp_types
= NULL
;
584 /* Lookup a chunk of rids */
586 result
= rpccli_samr_lookup_rids(cli
, mem_ctx
,
591 &tmp_names
, &tmp_types
);
593 /* see if we have a real error (and yes the
594 STATUS_SOME_UNMAPPED is the one returned from 2k) */
596 if (!NT_STATUS_IS_OK(result
) &&
597 !NT_STATUS_EQUAL(result
, STATUS_SOME_UNMAPPED
))
600 /* Copy result into array. The talloc system will take
601 care of freeing the temporary arrays later on. */
603 memcpy(&(*names
)[i
], tmp_names
, sizeof(char *) *
606 memcpy(&(*name_types
)[i
], tmp_types
, sizeof(uint32
) *
609 total_names
+= tmp_num_names
;
612 *num_names
= total_names
;
621 static int get_ldap_seq(const char *server
, int port
, uint32
*seq
)
625 const char *attrs
[] = {"highestCommittedUSN", NULL
};
626 LDAPMessage
*res
= NULL
;
627 char **values
= NULL
;
630 *seq
= DOM_SEQUENCE_NONE
;
633 * Parameterised (5) second timeout on open. This is needed as the
634 * search timeout doesn't seem to apply to doing an open as well. JRA.
637 ldp
= ldap_open_with_timeout(server
, port
, lp_ldap_timeout());
641 /* Timeout if no response within 20 seconds. */
645 if (ldap_search_st(ldp
, "", LDAP_SCOPE_BASE
, "(objectclass=*)",
646 CONST_DISCARD(char **, attrs
), 0, &to
, &res
))
649 if (ldap_count_entries(ldp
, res
) != 1)
652 values
= ldap_get_values(ldp
, res
, "highestCommittedUSN");
653 if (!values
|| !values
[0])
656 *seq
= atoi(values
[0]);
662 ldap_value_free(values
);
670 /**********************************************************************
671 Get the sequence number for a Windows AD native mode domain using
673 **********************************************************************/
675 static int get_ldap_sequence_number( const char* domain
, uint32
*seq
)
678 int i
, port
= LDAP_PORT
;
679 struct ip_service
*ip_list
= NULL
;
682 if ( !get_sorted_dc_list(domain
, &ip_list
, &count
, False
) ) {
683 DEBUG(3, ("Could not look up dc's for domain %s\n", domain
));
687 /* Finally return first DC that we can contact */
689 for (i
= 0; i
< count
; i
++) {
692 /* since the is an LDAP lookup, default to the LDAP_PORT is
694 port
= (ip_list
[i
].port
!= PORT_NONE
) ?
695 ip_list
[i
].port
: LDAP_PORT
;
697 fstrcpy( ipstr
, inet_ntoa(ip_list
[i
].ip
) );
699 if (is_zero_ip(ip_list
[i
].ip
))
702 if ( (ret
= get_ldap_seq( ipstr
, port
, seq
)) == 0 )
705 /* add to failed connection cache */
706 add_failed_connection_entry( domain
, ipstr
,
707 NT_STATUS_UNSUCCESSFUL
);
712 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
713 "number for Domain (%s) from DC (%s:%d)\n",
714 domain
, inet_ntoa(ip_list
[i
].ip
), port
));
722 #endif /* HAVE_LDAP */
724 /* find the sequence number for a domain */
725 static NTSTATUS
sequence_number(struct winbindd_domain
*domain
, uint32
*seq
)
731 BOOL got_seq_num
= False
;
733 struct rpc_pipe_client
*cli
;
735 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain
->name
));
737 *seq
= DOM_SEQUENCE_NONE
;
739 if (!(mem_ctx
= talloc_init("sequence_number[rpc]")))
740 return NT_STATUS_NO_MEMORY
;
745 if ( domain
->native_mode
)
749 DEBUG(8,("using get_ldap_seq() to retrieve the "
750 "sequence number\n"));
752 res
= get_ldap_sequence_number( domain
->name
, seq
);
755 result
= NT_STATUS_OK
;
756 DEBUG(10,("domain_sequence_number: LDAP for "
758 domain
->name
, *seq
));
762 DEBUG(10,("domain_sequence_number: failed to get LDAP "
763 "sequence number for domain %s\n",
766 #endif /* HAVE_LDAP */
768 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
769 if (!NT_STATUS_IS_OK(result
)) {
773 /* Query domain info */
775 result
= rpccli_samr_query_dom_info(cli
, mem_ctx
, &dom_pol
, 8, &ctr
);
777 if (NT_STATUS_IS_OK(result
)) {
778 *seq
= ctr
.info
.inf8
.seq_num
.low
;
783 /* retry with info-level 2 in case the dc does not support info-level 8
784 * (like all older samba2 and samba3 dc's - Guenther */
786 result
= rpccli_samr_query_dom_info(cli
, mem_ctx
, &dom_pol
, 2, &ctr
);
788 if (NT_STATUS_IS_OK(result
)) {
789 *seq
= ctr
.info
.inf2
.seq_num
.low
;
795 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
796 domain
->name
, (unsigned)*seq
));
798 DEBUG(10,("domain_sequence_number: failed to get sequence "
799 "number (%u) for domain %s\n",
800 (unsigned)*seq
, domain
->name
));
805 talloc_destroy(mem_ctx
);
810 /* get a list of trusted domains */
811 static NTSTATUS
trusted_domains(struct winbindd_domain
*domain
,
818 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
820 struct rpc_pipe_client
*cli
;
821 POLICY_HND lsa_policy
;
823 DEBUG(3,("rpc: trusted_domains\n"));
830 result
= cm_connect_lsa(domain
, mem_ctx
, &cli
, &lsa_policy
);
831 if (!NT_STATUS_IS_OK(result
))
834 result
= STATUS_MORE_ENTRIES
;
836 while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
)) {
837 uint32 start_idx
, num
;
842 result
= rpccli_lsa_enum_trust_dom(cli
, mem_ctx
,
843 &lsa_policy
, &enum_ctx
,
847 if (!NT_STATUS_IS_OK(result
) &&
848 !NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
))
851 start_idx
= *num_domains
;
853 *names
= TALLOC_REALLOC_ARRAY(mem_ctx
, *names
,
854 char *, *num_domains
);
855 *dom_sids
= TALLOC_REALLOC_ARRAY(mem_ctx
, *dom_sids
,
856 DOM_SID
, *num_domains
);
857 *alt_names
= TALLOC_REALLOC_ARRAY(mem_ctx
, *alt_names
,
858 char *, *num_domains
);
859 if ((*names
== NULL
) || (*dom_sids
== NULL
) ||
860 (*alt_names
== NULL
))
861 return NT_STATUS_NO_MEMORY
;
863 for (i
=0; i
<num
; i
++) {
864 (*names
)[start_idx
+i
] = tmp_names
[i
];
865 (*dom_sids
)[start_idx
+i
] = tmp_sids
[i
];
866 (*alt_names
)[start_idx
+i
] = talloc_strdup(mem_ctx
, "");
872 /* find the lockout policy for a domain */
873 NTSTATUS
msrpc_lockout_policy(struct winbindd_domain
*domain
,
875 SAM_UNK_INFO_12
*lockout_policy
)
878 struct rpc_pipe_client
*cli
;
882 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain
->name
));
884 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
885 if (!NT_STATUS_IS_OK(result
)) {
889 result
= rpccli_samr_query_dom_info(cli
, mem_ctx
, &dom_pol
, 12, &ctr
);
890 if (!NT_STATUS_IS_OK(result
)) {
894 *lockout_policy
= ctr
.info
.inf12
;
896 DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n",
897 ctr
.info
.inf12
.bad_attempt_lockout
));
904 /* find the password policy for a domain */
905 NTSTATUS
msrpc_password_policy(struct winbindd_domain
*domain
,
907 SAM_UNK_INFO_1
*password_policy
)
910 struct rpc_pipe_client
*cli
;
914 DEBUG(10,("rpc: fetch password policy for %s\n", domain
->name
));
916 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
917 if (!NT_STATUS_IS_OK(result
)) {
921 result
= rpccli_samr_query_dom_info(cli
, mem_ctx
, &dom_pol
, 1, &ctr
);
922 if (!NT_STATUS_IS_OK(result
)) {
926 *password_policy
= ctr
.info
.inf1
;
928 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
929 ctr
.info
.inf1
.min_length_password
));
937 /* the rpc backend methods are exposed via this structure */
938 struct winbindd_methods msrpc_methods
= {
947 msrpc_lookup_useraliases
,
950 msrpc_lockout_policy
,
951 msrpc_password_policy
,