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 lsa_SidType *type)
247 DOM_SID *sids = NULL;
248 enum lsa_SidType *types = NULL;
249 char *full_name = NULL;
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 ws_name_return( full_name, WB_REPLACE_CHAR );
267 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
269 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
270 if (!NT_STATUS_IS_OK(result))
273 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
274 (const char**) &full_name, NULL, &sids, &types);
276 if (!NT_STATUS_IS_OK(result))
279 /* Return rid and type if lookup successful */
281 sid_copy(sid, &sids[0]);
288 convert a domain SID to a user or group name
290 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
295 enum lsa_SidType *type)
299 enum lsa_SidType *types;
301 struct rpc_pipe_client *cli;
302 POLICY_HND lsa_policy;
304 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
307 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
308 if (!NT_STATUS_IS_OK(result))
311 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
312 1, sid, &domains, &names, &types);
313 if (!NT_STATUS_IS_OK(result))
316 *type = (enum lsa_SidType)types[0];
317 *domain_name = domains[0];
320 ws_name_replace( *name, WB_REPLACE_CHAR );
322 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
326 NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
333 enum lsa_SidType **types)
337 struct rpc_pipe_client *cli;
338 POLICY_HND lsa_policy;
343 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
346 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
348 return NT_STATUS_NO_MEMORY;
354 for (i=0; i<num_rids; i++) {
355 if (!sid_compose(&sids[i], sid, rids[i])) {
356 return NT_STATUS_INTERNAL_ERROR;
360 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
361 if (!NT_STATUS_IS_OK(result)) {
365 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
366 num_rids, sids, &domains,
368 if (!NT_STATUS_IS_OK(result) &&
369 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
374 for (i=0; i<num_rids; i++) {
375 if ((*types)[i] != SID_NAME_UNKNOWN) {
376 ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
377 *domain_name = domains[i];
384 /* Lookup user information from a rid or username. */
385 static NTSTATUS query_user(struct winbindd_domain *domain,
387 const DOM_SID *user_sid,
388 WINBIND_USERINFO *user_info)
390 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
391 POLICY_HND dom_pol, user_pol;
392 SAM_USERINFO_CTR *ctr;
395 NET_USER_INFO_3 *user;
396 struct rpc_pipe_client *cli;
398 DEBUG(3,("rpc: query_user sid=%s\n",
399 sid_to_string(sid_string, user_sid)));
401 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
402 return NT_STATUS_UNSUCCESSFUL;
404 /* try netsamlogon cache first */
406 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
409 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
410 sid_string_static(user_sid)));
412 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
413 sid_compose(&user_info->group_sid, &domain->sid,
416 user_info->acct_name = unistr2_tdup(mem_ctx,
417 &user->uni_user_name);
418 user_info->full_name = unistr2_tdup(mem_ctx,
419 &user->uni_full_name);
421 user_info->homedir = NULL;
422 user_info->shell = NULL;
423 user_info->primary_gid = (gid_t)-1;
430 /* no cache; hit the wire */
432 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
433 if (!NT_STATUS_IS_OK(result))
436 /* Get user handle */
437 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
438 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
441 if (!NT_STATUS_IS_OK(result))
445 result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
448 rpccli_samr_close(cli, mem_ctx, &user_pol);
450 if (!NT_STATUS_IS_OK(result))
453 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
454 sid_compose(&user_info->group_sid, &domain->sid,
455 ctr->info.id21->group_rid);
456 user_info->acct_name = unistr2_tdup(mem_ctx,
457 &ctr->info.id21->uni_user_name);
458 user_info->full_name = unistr2_tdup(mem_ctx,
459 &ctr->info.id21->uni_full_name);
460 user_info->homedir = NULL;
461 user_info->shell = NULL;
462 user_info->primary_gid = (gid_t)-1;
467 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
468 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
470 const DOM_SID *user_sid,
471 uint32 *num_groups, DOM_SID **user_grpsids)
473 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
474 POLICY_HND dom_pol, user_pol;
475 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
476 DOM_GID *user_groups;
480 struct rpc_pipe_client *cli;
482 DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
483 sid_to_string(sid_string, user_sid)));
485 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
486 return NT_STATUS_UNSUCCESSFUL;
489 *user_grpsids = NULL;
491 /* so lets see if we have a cached user_info_3 */
492 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
493 num_groups, user_grpsids);
495 if (NT_STATUS_IS_OK(result)) {
499 /* no cache; hit the wire */
501 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
502 if (!NT_STATUS_IS_OK(result))
505 /* Get user handle */
506 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
507 des_access, user_rid, &user_pol);
509 if (!NT_STATUS_IS_OK(result))
512 /* Query user rids */
513 result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
514 num_groups, &user_groups);
516 rpccli_samr_close(cli, mem_ctx, &user_pol);
518 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
521 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
522 if (!(*user_grpsids))
523 return NT_STATUS_NO_MEMORY;
525 for (i=0;i<(*num_groups);i++) {
526 sid_copy(&((*user_grpsids)[i]), &domain->sid);
527 sid_append_rid(&((*user_grpsids)[i]),
528 user_groups[i].g_rid);
534 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
536 uint32 num_sids, const DOM_SID *sids,
537 uint32 *num_aliases, uint32 **alias_rids)
539 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
541 DOM_SID2 *query_sids;
542 uint32 num_query_sids = 0;
544 struct rpc_pipe_client *cli;
545 uint32 *alias_rids_query, num_aliases_query;
546 int rangesize = MAX_SAM_ENTRIES_W2K;
547 uint32 total_sids = 0;
553 DEBUG(3,("rpc: lookup_useraliases\n"));
555 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
556 if (!NT_STATUS_IS_OK(result))
562 num_query_sids = MIN(num_sids - total_sids, rangesize);
564 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
565 num_queries, num_query_sids));
567 if (num_query_sids) {
568 query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids);
569 if (query_sids == NULL) {
570 return NT_STATUS_NO_MEMORY;
576 for (i=0; i<num_query_sids; i++) {
577 sid_copy(&query_sids[i].sid, &sids[total_sids++]);
578 query_sids[i].num_auths = query_sids[i].sid.num_auths;
583 result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
584 num_query_sids, query_sids,
588 if (!NT_STATUS_IS_OK(result)) {
591 TALLOC_FREE(query_sids);
597 for (i=0; i<num_aliases_query; i++) {
598 size_t na = *num_aliases;
599 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query[i],
601 return NT_STATUS_NO_MEMORY;
606 TALLOC_FREE(query_sids);
610 } while (total_sids < num_sids);
613 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
614 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
620 /* Lookup group membership given a rid. */
621 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
623 const DOM_SID *group_sid, uint32 *num_names,
624 DOM_SID **sid_mem, char ***names,
627 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
628 uint32 i, total_names = 0;
629 POLICY_HND dom_pol, group_pol;
630 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
631 uint32 *rid_mem = NULL;
635 struct rpc_pipe_client *cli;
636 unsigned int orig_timeout;
638 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
639 sid_to_string(sid_string, group_sid)));
641 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
642 return NT_STATUS_UNSUCCESSFUL;
646 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
647 if (!NT_STATUS_IS_OK(result))
650 result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
651 des_access, group_rid, &group_pol);
653 if (!NT_STATUS_IS_OK(result))
656 /* Step #1: Get a list of user rids that are the members of the
659 /* This call can take a long time - allow the server to time out.
660 35 seconds should do it. */
662 orig_timeout = cli_set_timeout(cli->cli, 35000);
664 result = rpccli_samr_query_groupmem(cli, mem_ctx,
665 &group_pol, num_names, &rid_mem,
668 /* And restore our original timeout. */
669 cli_set_timeout(cli->cli, orig_timeout);
671 rpccli_samr_close(cli, mem_ctx, &group_pol);
673 if (!NT_STATUS_IS_OK(result))
683 /* Step #2: Convert list of rids into list of usernames. Do this
684 in bunches of ~1000 to avoid crashing NT4. It looks like there
685 is a buffer overflow or something like that lurking around
688 #define MAX_LOOKUP_RIDS 900
690 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
691 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
692 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
694 for (j=0;j<(*num_names);j++)
695 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
697 if (*num_names>0 && (!*names || !*name_types))
698 return NT_STATUS_NO_MEMORY;
700 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
701 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
702 uint32 tmp_num_names = 0;
703 char **tmp_names = NULL;
704 uint32 *tmp_types = NULL;
706 /* Lookup a chunk of rids */
708 result = rpccli_samr_lookup_rids(cli, mem_ctx,
713 &tmp_names, &tmp_types);
715 /* see if we have a real error (and yes the
716 STATUS_SOME_UNMAPPED is the one returned from 2k) */
718 if (!NT_STATUS_IS_OK(result) &&
719 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
722 /* Copy result into array. The talloc system will take
723 care of freeing the temporary arrays later on. */
725 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
728 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
731 total_names += tmp_num_names;
734 *num_names = total_names;
743 static int get_ldap_seq(const char *server, int port, uint32 *seq)
747 const char *attrs[] = {"highestCommittedUSN", NULL};
748 LDAPMessage *res = NULL;
749 char **values = NULL;
752 *seq = DOM_SEQUENCE_NONE;
755 * Parameterised (5) second timeout on open. This is needed as the
756 * search timeout doesn't seem to apply to doing an open as well. JRA.
759 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
763 /* Timeout if no response within 20 seconds. */
767 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
768 CONST_DISCARD(char **, attrs), 0, &to, &res))
771 if (ldap_count_entries(ldp, res) != 1)
774 values = ldap_get_values(ldp, res, "highestCommittedUSN");
775 if (!values || !values[0])
778 *seq = atoi(values[0]);
784 ldap_value_free(values);
792 /**********************************************************************
793 Get the sequence number for a Windows AD native mode domain using
795 **********************************************************************/
797 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
802 fstrcpy( ipstr, inet_ntoa(domain->dcaddr.sin_addr));
803 if ((ret = get_ldap_seq( ipstr, LDAP_PORT, seq)) == 0) {
804 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
805 "number for Domain (%s) from DC (%s)\n",
806 domain->name, ipstr));
811 #endif /* HAVE_LDAP */
813 /* find the sequence number for a domain */
814 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
820 BOOL got_seq_num = False;
821 struct rpc_pipe_client *cli;
823 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
825 *seq = DOM_SEQUENCE_NONE;
827 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
828 return NT_STATUS_NO_MEMORY;
831 if ( domain->native_mode )
835 DEBUG(8,("using get_ldap_seq() to retrieve the "
836 "sequence number\n"));
838 res = get_ldap_sequence_number( domain, seq );
841 result = NT_STATUS_OK;
842 DEBUG(10,("domain_sequence_number: LDAP for "
844 domain->name, *seq));
848 DEBUG(10,("domain_sequence_number: failed to get LDAP "
849 "sequence number for domain %s\n",
852 #endif /* HAVE_LDAP */
854 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
855 if (!NT_STATUS_IS_OK(result)) {
859 /* Query domain info */
861 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
863 if (NT_STATUS_IS_OK(result)) {
864 *seq = ctr.info.inf8.seq_num;
869 /* retry with info-level 2 in case the dc does not support info-level 8
870 * (like all older samba2 and samba3 dc's - Guenther */
872 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
874 if (NT_STATUS_IS_OK(result)) {
875 *seq = ctr.info.inf2.seq_num;
881 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
882 domain->name, (unsigned)*seq));
884 DEBUG(10,("domain_sequence_number: failed to get sequence "
885 "number (%u) for domain %s\n",
886 (unsigned)*seq, domain->name ));
891 talloc_destroy(mem_ctx);
896 /* get a list of trusted domains */
897 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
904 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
906 struct rpc_pipe_client *cli;
907 POLICY_HND lsa_policy;
909 DEBUG(3,("rpc: trusted_domains\n"));
916 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
917 if (!NT_STATUS_IS_OK(result))
920 result = STATUS_MORE_ENTRIES;
922 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
923 uint32 start_idx, num;
928 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
929 &lsa_policy, &enum_ctx,
933 if (!NT_STATUS_IS_OK(result) &&
934 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
937 start_idx = *num_domains;
939 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
940 char *, *num_domains);
941 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
942 DOM_SID, *num_domains);
943 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
944 char *, *num_domains);
945 if ((*names == NULL) || (*dom_sids == NULL) ||
946 (*alt_names == NULL))
947 return NT_STATUS_NO_MEMORY;
949 for (i=0; i<num; i++) {
950 (*names)[start_idx+i] = tmp_names[i];
951 (*dom_sids)[start_idx+i] = tmp_sids[i];
952 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
958 /* find the lockout policy for a domain */
959 NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
961 SAM_UNK_INFO_12 *lockout_policy)
964 struct rpc_pipe_client *cli;
968 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
970 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
971 if (!NT_STATUS_IS_OK(result)) {
975 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
976 if (!NT_STATUS_IS_OK(result)) {
980 *lockout_policy = ctr.info.inf12;
982 DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n",
983 ctr.info.inf12.bad_attempt_lockout));
990 /* find the password policy for a domain */
991 NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
993 SAM_UNK_INFO_1 *password_policy)
996 struct rpc_pipe_client *cli;
1000 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1002 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1003 if (!NT_STATUS_IS_OK(result)) {
1007 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
1008 if (!NT_STATUS_IS_OK(result)) {
1012 *password_policy = ctr.info.inf1;
1014 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1015 ctr.info.inf1.min_length_password));
1023 /* the rpc backend methods are exposed via this structure */
1024 struct winbindd_methods msrpc_methods = {
1031 msrpc_rids_to_names,
1034 msrpc_lookup_useraliases,
1037 msrpc_lockout_policy,
1038 msrpc_password_policy,