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
enum SID_NAME_USE *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]);
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)
297
enum SID_NAME_USE *types;
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
NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
328
enum SID_NAME_USE **types)
332
struct rpc_pipe_client *cli;
333
POLICY_HND lsa_policy;
337
DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
339
sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
341
return NT_STATUS_NO_MEMORY;
344
for (i=0; i<num_rids; i++) {
345
if (!sid_compose(&sids[i], sid, rids[i])) {
346
return NT_STATUS_INTERNAL_ERROR;
350
result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
351
if (!NT_STATUS_IS_OK(result)) {
355
result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
356
num_rids, sids, &domains,
358
if (!NT_STATUS_IS_OK(result) &&
359
!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
363
for (i=0; i<num_rids; i++) {
364
if ((*types)[i] != SID_NAME_UNKNOWN) {
365
*domain_name = domains[i];
373
/* Lookup user information from a rid or username. */
374
static NTSTATUS query_user(struct winbindd_domain *domain,
376
const DOM_SID *user_sid,
377
WINBIND_USERINFO *user_info)
379
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
380
POLICY_HND dom_pol, user_pol;
381
SAM_USERINFO_CTR *ctr;
384
NET_USER_INFO_3 *user;
385
struct rpc_pipe_client *cli;
387
DEBUG(3,("rpc: query_user rid=%s\n",
388
sid_to_string(sid_string, user_sid)));
390
if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
391
return NT_STATUS_UNSUCCESSFUL;
393
/* try netsamlogon cache first */
395
if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
398
DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
399
sid_string_static(user_sid)));
401
sid_compose(&user_info->user_sid, &domain->sid, user_rid);
402
sid_compose(&user_info->group_sid, &domain->sid,
405
user_info->acct_name = unistr2_tdup(mem_ctx,
406
&user->uni_user_name);
407
user_info->full_name = unistr2_tdup(mem_ctx,
408
&user->uni_full_name);
410
user_info->homedir = NULL;
411
user_info->shell = NULL;
418
/* no cache; hit the wire */
420
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
421
if (!NT_STATUS_IS_OK(result))
424
/* Get user handle */
425
result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
426
SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
429
if (!NT_STATUS_IS_OK(result))
433
result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
436
rpccli_samr_close(cli, mem_ctx, &user_pol);
438
if (!NT_STATUS_IS_OK(result))
441
sid_compose(&user_info->user_sid, &domain->sid, user_rid);
442
sid_compose(&user_info->group_sid, &domain->sid,
443
ctr->info.id21->group_rid);
444
user_info->acct_name = unistr2_tdup(mem_ctx,
445
&ctr->info.id21->uni_user_name);
446
user_info->full_name = unistr2_tdup(mem_ctx,
447
&ctr->info.id21->uni_full_name);
448
user_info->homedir = NULL;
449
user_info->shell = NULL;
454
/* Lookup groups a user is a member of. I wish Unix had a call like this! */
455
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
457
const DOM_SID *user_sid,
458
uint32 *num_groups, DOM_SID **user_grpsids)
460
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
461
POLICY_HND dom_pol, user_pol;
462
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
463
DOM_GID *user_groups;
467
struct rpc_pipe_client *cli;
469
DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
470
sid_to_string(sid_string, user_sid)));
472
if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
473
return NT_STATUS_UNSUCCESSFUL;
476
*user_grpsids = NULL;
478
/* so lets see if we have a cached user_info_3 */
479
result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
480
num_groups, user_grpsids);
482
if (NT_STATUS_IS_OK(result)) {
486
/* no cache; hit the wire */
488
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
489
if (!NT_STATUS_IS_OK(result))
492
/* Get user handle */
493
result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
494
des_access, user_rid, &user_pol);
496
if (!NT_STATUS_IS_OK(result))
499
/* Query user rids */
500
result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
501
num_groups, &user_groups);
503
rpccli_samr_close(cli, mem_ctx, &user_pol);
505
if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
508
(*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
509
if (!(*user_grpsids))
510
return NT_STATUS_NO_MEMORY;
512
for (i=0;i<(*num_groups);i++) {
513
sid_copy(&((*user_grpsids)[i]), &domain->sid);
514
sid_append_rid(&((*user_grpsids)[i]),
515
user_groups[i].g_rid);
521
NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
523
uint32 num_sids, const DOM_SID *sids,
524
uint32 *num_aliases, uint32 **alias_rids)
526
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
528
DOM_SID2 *query_sids;
529
uint32 num_query_sids = 0;
531
struct rpc_pipe_client *cli;
532
uint32 *alias_rids_query, num_aliases_query;
533
int rangesize = MAX_SAM_ENTRIES_W2K;
534
uint32 total_sids = 0;
540
DEBUG(3,("rpc: lookup_useraliases\n"));
542
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
543
if (!NT_STATUS_IS_OK(result))
549
num_query_sids = MIN(num_sids - total_sids, rangesize);
551
DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
552
num_queries, num_query_sids));
555
query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids);
556
if (query_sids == NULL) {
557
return NT_STATUS_NO_MEMORY;
560
for (i=0; i<num_query_sids; i++) {
561
sid_copy(&query_sids[i].sid, &sids[total_sids++]);
562
query_sids[i].num_auths = query_sids[i].sid.num_auths;
567
result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
568
num_query_sids, query_sids,
572
if (!NT_STATUS_IS_OK(result)) {
575
TALLOC_FREE(query_sids);
581
for (i=0; i<num_aliases_query; i++) {
582
size_t na = *num_aliases;
583
add_rid_to_array_unique(mem_ctx, alias_rids_query[i],
588
TALLOC_FREE(query_sids);
592
} while (total_sids < num_sids);
595
DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
596
"(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
602
/* Lookup group membership given a rid. */
603
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
605
const DOM_SID *group_sid, uint32 *num_names,
606
DOM_SID **sid_mem, char ***names,
609
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
610
uint32 i, total_names = 0;
611
POLICY_HND dom_pol, group_pol;
612
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
613
uint32 *rid_mem = NULL;
617
struct rpc_pipe_client *cli;
619
DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
620
sid_to_string(sid_string, group_sid)));
622
if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
623
return NT_STATUS_UNSUCCESSFUL;
627
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
628
if (!NT_STATUS_IS_OK(result))
631
result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
632
des_access, group_rid, &group_pol);
634
if (!NT_STATUS_IS_OK(result))
637
/* Step #1: Get a list of user rids that are the members of the
640
result = rpccli_samr_query_groupmem(cli, mem_ctx,
641
&group_pol, num_names, &rid_mem,
644
rpccli_samr_close(cli, mem_ctx, &group_pol);
646
if (!NT_STATUS_IS_OK(result))
656
/* Step #2: Convert list of rids into list of usernames. Do this
657
in bunches of ~1000 to avoid crashing NT4. It looks like there
658
is a buffer overflow or something like that lurking around
661
#define MAX_LOOKUP_RIDS 900
663
*names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
664
*name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
665
*sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
667
for (j=0;j<(*num_names);j++)
668
sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
670
if (*num_names>0 && (!*names || !*name_types))
671
return NT_STATUS_NO_MEMORY;
673
for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
674
int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
675
uint32 tmp_num_names = 0;
676
char **tmp_names = NULL;
677
uint32 *tmp_types = NULL;
679
/* Lookup a chunk of rids */
681
result = rpccli_samr_lookup_rids(cli, mem_ctx,
686
&tmp_names, &tmp_types);
688
/* see if we have a real error (and yes the
689
STATUS_SOME_UNMAPPED is the one returned from 2k) */
691
if (!NT_STATUS_IS_OK(result) &&
692
!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
695
/* Copy result into array. The talloc system will take
696
care of freeing the temporary arrays later on. */
698
memcpy(&(*names)[i], tmp_names, sizeof(char *) *
701
memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
704
total_names += tmp_num_names;
707
*num_names = total_names;
716
static int get_ldap_seq(const char *server, int port, uint32 *seq)
720
const char *attrs[] = {"highestCommittedUSN", NULL};
721
LDAPMessage *res = NULL;
722
char **values = NULL;
725
*seq = DOM_SEQUENCE_NONE;
728
* Parameterised (5) second timeout on open. This is needed as the
729
* search timeout doesn't seem to apply to doing an open as well. JRA.
732
ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
736
/* Timeout if no response within 20 seconds. */
740
if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
741
CONST_DISCARD(char **, attrs), 0, &to, &res))
744
if (ldap_count_entries(ldp, res) != 1)
747
values = ldap_get_values(ldp, res, "highestCommittedUSN");
748
if (!values || !values[0])
751
*seq = atoi(values[0]);
757
ldap_value_free(values);
765
/**********************************************************************
766
Get the sequence number for a Windows AD native mode domain using
768
**********************************************************************/
770
static int get_ldap_sequence_number( const char* domain, uint32 *seq)
773
int i, port = LDAP_PORT;
774
struct ip_service *ip_list = NULL;
777
if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
778
DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
782
/* Finally return first DC that we can contact */
784
for (i = 0; i < count; i++) {
787
/* since the is an LDAP lookup, default to the LDAP_PORT is
789
port = (ip_list[i].port!= PORT_NONE) ?
790
ip_list[i].port : LDAP_PORT;
792
fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
794
if (is_zero_ip(ip_list[i].ip))
797
if ( (ret = get_ldap_seq( ipstr, port, seq)) == 0 )
800
/* add to failed connection cache */
801
add_failed_connection_entry( domain, ipstr,
802
NT_STATUS_UNSUCCESSFUL );
807
DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
808
"number for Domain (%s) from DC (%s:%d)\n",
809
domain, inet_ntoa(ip_list[i].ip), port));
817
#endif /* HAVE_LDAP */
819
/* find the sequence number for a domain */
820
static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
826
BOOL got_seq_num = False;
827
struct rpc_pipe_client *cli;
829
DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
831
*seq = DOM_SEQUENCE_NONE;
833
if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
834
return NT_STATUS_NO_MEMORY;
837
if ( domain->native_mode )
841
DEBUG(8,("using get_ldap_seq() to retrieve the "
842
"sequence number\n"));
844
res = get_ldap_sequence_number( domain->name, seq );
847
result = NT_STATUS_OK;
848
DEBUG(10,("domain_sequence_number: LDAP for "
850
domain->name, *seq));
854
DEBUG(10,("domain_sequence_number: failed to get LDAP "
855
"sequence number for domain %s\n",
858
#endif /* HAVE_LDAP */
860
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
861
if (!NT_STATUS_IS_OK(result)) {
865
/* Query domain info */
867
result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
869
if (NT_STATUS_IS_OK(result)) {
870
*seq = ctr.info.inf8.seq_num.low;
875
/* retry with info-level 2 in case the dc does not support info-level 8
876
* (like all older samba2 and samba3 dc's - Guenther */
878
result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
880
if (NT_STATUS_IS_OK(result)) {
881
*seq = ctr.info.inf2.seq_num.low;
887
DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
888
domain->name, (unsigned)*seq));
890
DEBUG(10,("domain_sequence_number: failed to get sequence "
891
"number (%u) for domain %s\n",
892
(unsigned)*seq, domain->name ));
897
talloc_destroy(mem_ctx);
902
/* get a list of trusted domains */
903
static NTSTATUS trusted_domains(struct winbindd_domain *domain,
910
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
912
struct rpc_pipe_client *cli;
913
POLICY_HND lsa_policy;
915
DEBUG(3,("rpc: trusted_domains\n"));
922
result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
923
if (!NT_STATUS_IS_OK(result))
926
result = STATUS_MORE_ENTRIES;
928
while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
929
uint32 start_idx, num;
934
result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
935
&lsa_policy, &enum_ctx,
939
if (!NT_STATUS_IS_OK(result) &&
940
!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
943
start_idx = *num_domains;
945
*names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
946
char *, *num_domains);
947
*dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
948
DOM_SID, *num_domains);
949
*alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
950
char *, *num_domains);
951
if ((*names == NULL) || (*dom_sids == NULL) ||
952
(*alt_names == NULL))
953
return NT_STATUS_NO_MEMORY;
955
for (i=0; i<num; i++) {
956
(*names)[start_idx+i] = tmp_names[i];
957
(*dom_sids)[start_idx+i] = tmp_sids[i];
958
(*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
964
/* find the lockout policy for a domain */
965
NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
967
SAM_UNK_INFO_12 *lockout_policy)
970
struct rpc_pipe_client *cli;
974
DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
976
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
977
if (!NT_STATUS_IS_OK(result)) {
981
result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
982
if (!NT_STATUS_IS_OK(result)) {
986
*lockout_policy = ctr.info.inf12;
988
DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n",
989
ctr.info.inf12.bad_attempt_lockout));
996
/* find the password policy for a domain */
997
NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
999
SAM_UNK_INFO_1 *password_policy)
1002
struct rpc_pipe_client *cli;
1006
DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1008
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1009
if (!NT_STATUS_IS_OK(result)) {
1013
result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
1014
if (!NT_STATUS_IS_OK(result)) {
1018
*password_policy = ctr.info.inf1;
1020
DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1021
ctr.info.inf1.min_length_password));
1029
/* the rpc backend methods are exposed via this structure */
1030
struct winbindd_methods msrpc_methods = {
1037
msrpc_rids_to_names,
1040
msrpc_lookup_useraliases,
1043
msrpc_lockout_policy,
1044
msrpc_password_policy,