• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.0.25b/source/nsswitch/
1/*
2   Unix SMB/CIFS implementation.
3
4   Winbind rpc backend functions
5
6   Copyright (C) Tim Potter 2000-2001,2003
7   Copyright (C) Andrew Tridgell 2001
8   Copyright (C) Volker Lendecke 2005
9
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.
14
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.
19
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.
23*/
24
25#include "includes.h"
26#include "winbindd.h"
27
28#undef DBGC_CLASS
29#define DBGC_CLASS DBGC_WINBIND
30
31
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
34   application. */
35static NTSTATUS query_user_list(struct winbindd_domain *domain,
36			       TALLOC_CTX *mem_ctx,
37			       uint32 *num_entries,
38			       WINBIND_USERINFO **info)
39{
40	NTSTATUS result;
41	POLICY_HND dom_pol;
42	unsigned int i, start_idx;
43	uint32 loop_count;
44	struct rpc_pipe_client *cli;
45
46	DEBUG(3,("rpc: query_user_list\n"));
47
48	*num_entries = 0;
49	*info = NULL;
50
51	result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
52	if (!NT_STATUS_IS_OK(result))
53		return result;
54
55	i = start_idx = 0;
56	loop_count = 0;
57
58	do {
59		TALLOC_CTX *ctx2;
60		uint32 num_dom_users, j;
61		uint32 max_entries, max_size;
62		SAM_DISPINFO_CTR ctr;
63		SAM_DISPINFO_1 info1;
64
65		ZERO_STRUCT( ctr );
66		ZERO_STRUCT( info1 );
67		ctr.sam.info1 = &info1;
68
69		if (!(ctx2 = talloc_init("winbindd enum_users")))
70			return NT_STATUS_NO_MEMORY;
71
72		/* this next bit is copied from net_user_list_internal() */
73
74		get_query_dispinfo_params(loop_count, &max_entries,
75					  &max_size);
76
77		result = rpccli_samr_query_dispinfo(cli, mem_ctx, &dom_pol,
78						    &start_idx, 1,
79						    &num_dom_users,
80						    max_entries, max_size,
81						    &ctr);
82
83		loop_count++;
84
85		*num_entries += num_dom_users;
86
87		*info = TALLOC_REALLOC_ARRAY(mem_ctx, *info, WINBIND_USERINFO,
88					     *num_entries);
89
90		if (!(*info)) {
91			talloc_destroy(ctx2);
92			return NT_STATUS_NO_MEMORY;
93		}
94
95		for (j = 0; j < num_dom_users; i++, j++) {
96			fstring username, fullname;
97			uint32 rid = ctr.sam.info1->sam[j].rid_user;
98
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);
101
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);
107
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. */
115
116			sid_compose(&(*info)[i].group_sid, &domain->sid,
117				    DOMAIN_GROUP_RID_USERS);
118		}
119
120		talloc_destroy(ctx2);
121
122	} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
123
124	return result;
125}
126
127/* list all domain groups */
128static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
129				TALLOC_CTX *mem_ctx,
130				uint32 *num_entries,
131				struct acct_info **info)
132{
133	POLICY_HND dom_pol;
134	NTSTATUS status;
135	uint32 start = 0;
136	struct rpc_pipe_client *cli;
137
138	*num_entries = 0;
139	*info = NULL;
140
141	DEBUG(3,("rpc: enum_dom_groups\n"));
142
143	status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
144	if (!NT_STATUS_IS_OK(status))
145		return status;
146
147	do {
148		struct acct_info *info2 = NULL;
149		uint32 count = 0;
150		TALLOC_CTX *mem_ctx2;
151
152		mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
153
154		/* start is updated by this call. */
155		status = rpccli_samr_enum_dom_groups(cli, mem_ctx2, &dom_pol,
156						     &start,
157						     0xFFFF, /* buffer size? */
158						     &info2, &count);
159
160		if (!NT_STATUS_IS_OK(status) &&
161		    !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
162			talloc_destroy(mem_ctx2);
163			break;
164		}
165
166		(*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
167					       struct acct_info,
168					       (*num_entries) + count);
169		if (! *info) {
170			talloc_destroy(mem_ctx2);
171			status = NT_STATUS_NO_MEMORY;
172			break;
173		}
174
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));
179
180	return NT_STATUS_OK;
181}
182
183/* List all domain groups */
184
185static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
186				TALLOC_CTX *mem_ctx,
187				uint32 *num_entries,
188				struct acct_info **info)
189{
190	POLICY_HND dom_pol;
191	NTSTATUS result;
192	struct rpc_pipe_client *cli;
193
194	*num_entries = 0;
195	*info = NULL;
196
197	DEBUG(3,("rpc: enum_local_groups\n"));
198
199	result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
200	if (!NT_STATUS_IS_OK(result))
201		return result;
202
203	do {
204		struct acct_info *info2 = NULL;
205		uint32 count = 0, start = *num_entries;
206		TALLOC_CTX *mem_ctx2;
207
208		mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
209
210		result = rpccli_samr_enum_als_groups( cli, mem_ctx2, &dom_pol,
211						      &start, 0xFFFF, &info2,
212						      &count);
213
214		if (!NT_STATUS_IS_OK(result) &&
215		    !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
216		{
217			talloc_destroy(mem_ctx2);
218			return result;
219		}
220
221		(*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
222					       struct acct_info,
223					       (*num_entries) + count);
224		if (! *info) {
225			talloc_destroy(mem_ctx2);
226			return NT_STATUS_NO_MEMORY;
227		}
228
229		memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
230		(*num_entries) += count;
231		talloc_destroy(mem_ctx2);
232
233	} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
234
235	return NT_STATUS_OK;
236}
237
238/* convert a single name to a sid in a domain */
239NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
240			    TALLOC_CTX *mem_ctx,
241			    const char *domain_name,
242			    const char *name,
243			    DOM_SID *sid,
244			    enum lsa_SidType *type)
245{
246	NTSTATUS result;
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;
252
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);
256        } else {
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);
259        }
260	if (!full_name) {
261		DEBUG(0, ("talloc_asprintf failed!\n"));
262		return NT_STATUS_NO_MEMORY;
263	}
264
265	ws_name_return( full_name, WB_REPLACE_CHAR );
266
267	DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
268
269	result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
270	if (!NT_STATUS_IS_OK(result))
271		return result;
272
273	result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
274					 (const char**) &full_name, NULL, &sids, &types);
275
276	if (!NT_STATUS_IS_OK(result))
277		return result;
278
279	/* Return rid and type if lookup successful */
280
281	sid_copy(sid, &sids[0]);
282	*type = types[0];
283
284	return NT_STATUS_OK;
285}
286
287/*
288  convert a domain SID to a user or group name
289*/
290NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
291			    TALLOC_CTX *mem_ctx,
292			    const DOM_SID *sid,
293			    char **domain_name,
294			    char **name,
295			    enum lsa_SidType *type)
296{
297	char **domains;
298	char **names;
299	enum lsa_SidType *types;
300	NTSTATUS result;
301	struct rpc_pipe_client *cli;
302	POLICY_HND lsa_policy;
303
304	DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
305			domain->name ));
306
307	result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
308	if (!NT_STATUS_IS_OK(result))
309		return result;
310
311	result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
312					1, sid, &domains, &names, &types);
313	if (!NT_STATUS_IS_OK(result))
314		return result;
315
316	*type = (enum lsa_SidType)types[0];
317	*domain_name = domains[0];
318	*name = names[0];
319
320	ws_name_replace( *name, WB_REPLACE_CHAR );
321
322	DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
323	return NT_STATUS_OK;
324}
325
326NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
327			     TALLOC_CTX *mem_ctx,
328			     const DOM_SID *sid,
329			     uint32 *rids,
330			     size_t num_rids,
331			     char **domain_name,
332			     char ***names,
333			     enum lsa_SidType **types)
334{
335	char **domains;
336	NTSTATUS result;
337	struct rpc_pipe_client *cli;
338	POLICY_HND lsa_policy;
339	DOM_SID *sids;
340	size_t i;
341	char **ret_names;
342
343	DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
344
345	if (num_rids) {
346		sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
347		if (sids == NULL) {
348			return NT_STATUS_NO_MEMORY;
349		}
350	} else {
351		sids = NULL;
352	}
353
354	for (i=0; i<num_rids; i++) {
355		if (!sid_compose(&sids[i], sid, rids[i])) {
356			return NT_STATUS_INTERNAL_ERROR;
357		}
358	}
359
360	result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
361	if (!NT_STATUS_IS_OK(result)) {
362		return result;
363	}
364
365	result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
366					num_rids, sids, &domains,
367					names, types);
368	if (!NT_STATUS_IS_OK(result) &&
369	    !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
370		return result;
371	}
372
373	ret_names = *names;
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];
378		}
379	}
380
381	return result;
382}
383
384/* Lookup user information from a rid or username. */
385static NTSTATUS query_user(struct winbindd_domain *domain,
386			   TALLOC_CTX *mem_ctx,
387			   const DOM_SID *user_sid,
388			   WINBIND_USERINFO *user_info)
389{
390	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
391	POLICY_HND dom_pol, user_pol;
392	SAM_USERINFO_CTR *ctr;
393	fstring sid_string;
394	uint32 user_rid;
395	NET_USER_INFO_3 *user;
396	struct rpc_pipe_client *cli;
397
398	DEBUG(3,("rpc: query_user sid=%s\n",
399		 sid_to_string(sid_string, user_sid)));
400
401	if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
402		return NT_STATUS_UNSUCCESSFUL;
403
404	/* try netsamlogon cache first */
405
406	if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
407	{
408
409		DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
410			sid_string_static(user_sid)));
411
412		sid_compose(&user_info->user_sid, &domain->sid, user_rid);
413		sid_compose(&user_info->group_sid, &domain->sid,
414			    user->group_rid);
415
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);
420
421		user_info->homedir = NULL;
422		user_info->shell = NULL;
423		user_info->primary_gid = (gid_t)-1;
424
425		TALLOC_FREE(user);
426
427		return NT_STATUS_OK;
428	}
429
430	/* no cache; hit the wire */
431
432	result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
433	if (!NT_STATUS_IS_OK(result))
434		return result;
435
436	/* Get user handle */
437	result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
438				       SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
439				       &user_pol);
440
441	if (!NT_STATUS_IS_OK(result))
442		return result;
443
444	/* Get user info */
445	result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
446					    0x15, &ctr);
447
448	rpccli_samr_close(cli, mem_ctx, &user_pol);
449
450	if (!NT_STATUS_IS_OK(result))
451		return result;
452
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;
463
464	return NT_STATUS_OK;
465}
466
467/* Lookup groups a user is a member of.  I wish Unix had a call like this! */
468static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
469				  TALLOC_CTX *mem_ctx,
470				  const DOM_SID *user_sid,
471				  uint32 *num_groups, DOM_SID **user_grpsids)
472{
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;
477	unsigned int i;
478	fstring sid_string;
479	uint32 user_rid;
480	struct rpc_pipe_client *cli;
481
482	DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
483		 sid_to_string(sid_string, user_sid)));
484
485	if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
486		return NT_STATUS_UNSUCCESSFUL;
487
488	*num_groups = 0;
489	*user_grpsids = NULL;
490
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);
494
495	if (NT_STATUS_IS_OK(result)) {
496		return NT_STATUS_OK;
497	}
498
499	/* no cache; hit the wire */
500
501	result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
502	if (!NT_STATUS_IS_OK(result))
503		return result;
504
505	/* Get user handle */
506	result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
507					des_access, user_rid, &user_pol);
508
509	if (!NT_STATUS_IS_OK(result))
510		return result;
511
512	/* Query user rids */
513	result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
514					   num_groups, &user_groups);
515
516	rpccli_samr_close(cli, mem_ctx, &user_pol);
517
518	if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
519		return result;
520
521	(*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
522	if (!(*user_grpsids))
523		return NT_STATUS_NO_MEMORY;
524
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);
529	}
530
531	return NT_STATUS_OK;
532}
533
534NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
535				  TALLOC_CTX *mem_ctx,
536				  uint32 num_sids, const DOM_SID *sids,
537				  uint32 *num_aliases, uint32 **alias_rids)
538{
539	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
540	POLICY_HND dom_pol;
541	DOM_SID2 *query_sids;
542	uint32 num_query_sids = 0;
543	int i;
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;
548	int num_queries = 1;
549
550	*num_aliases = 0;
551	*alias_rids = NULL;
552
553	DEBUG(3,("rpc: lookup_useraliases\n"));
554
555	result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
556	if (!NT_STATUS_IS_OK(result))
557		return result;
558
559	do {
560		/* prepare query */
561
562		num_query_sids = MIN(num_sids - total_sids, rangesize);
563
564		DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
565			num_queries, num_query_sids));
566
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;
571			}
572		} else {
573			query_sids = NULL;
574		}
575
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;
579		}
580
581		/* do request */
582
583		result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
584						       num_query_sids, query_sids,
585						       &num_aliases_query,
586						       &alias_rids_query);
587
588		if (!NT_STATUS_IS_OK(result)) {
589			*num_aliases = 0;
590			*alias_rids = NULL;
591			TALLOC_FREE(query_sids);
592			goto done;
593		}
594
595		/* process output */
596
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],
600						alias_rids, &na)) {
601				return NT_STATUS_NO_MEMORY;
602			}
603			*num_aliases = na;
604		}
605
606		TALLOC_FREE(query_sids);
607
608		num_queries++;
609
610	} while (total_sids < num_sids);
611
612 done:
613	DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
614		"(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
615
616	return result;
617}
618
619
620/* Lookup group membership given a rid.   */
621static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
622				TALLOC_CTX *mem_ctx,
623				const DOM_SID *group_sid, uint32 *num_names,
624				DOM_SID **sid_mem, char ***names,
625				uint32 **name_types)
626{
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;
632	uint32 group_rid;
633	unsigned int j;
634	fstring sid_string;
635	struct rpc_pipe_client *cli;
636	unsigned int orig_timeout;
637
638	DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
639		  sid_to_string(sid_string, group_sid)));
640
641	if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
642		return NT_STATUS_UNSUCCESSFUL;
643
644	*num_names = 0;
645
646	result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
647	if (!NT_STATUS_IS_OK(result))
648		return result;
649
650        result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
651					des_access, group_rid, &group_pol);
652
653        if (!NT_STATUS_IS_OK(result))
654		return result;
655
656        /* Step #1: Get a list of user rids that are the members of the
657           group. */
658
659	/* This call can take a long time - allow the server to time out.
660	   35 seconds should do it. */
661
662	orig_timeout = cli_set_timeout(cli->cli, 35000);
663
664        result = rpccli_samr_query_groupmem(cli, mem_ctx,
665					    &group_pol, num_names, &rid_mem,
666					    name_types);
667
668	/* And restore our original timeout. */
669	cli_set_timeout(cli->cli, orig_timeout);
670
671	rpccli_samr_close(cli, mem_ctx, &group_pol);
672
673        if (!NT_STATUS_IS_OK(result))
674		return result;
675
676	if (!*num_names) {
677		names = NULL;
678		name_types = NULL;
679		sid_mem = NULL;
680		return NT_STATUS_OK;
681	}
682
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
686           somewhere. */
687
688#define MAX_LOOKUP_RIDS 900
689
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);
693
694	for (j=0;j<(*num_names);j++)
695		sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
696
697	if (*num_names>0 && (!*names || !*name_types))
698		return NT_STATUS_NO_MEMORY;
699
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;
705
706                /* Lookup a chunk of rids */
707
708                result = rpccli_samr_lookup_rids(cli, mem_ctx,
709						 &dom_pol,
710						 num_lookup_rids,
711						 &rid_mem[i],
712						 &tmp_num_names,
713						 &tmp_names, &tmp_types);
714
715		/* see if we have a real error (and yes the
716		   STATUS_SOME_UNMAPPED is the one returned from 2k) */
717
718                if (!NT_STATUS_IS_OK(result) &&
719		    !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
720			return result;
721
722                /* Copy result into array.  The talloc system will take
723                   care of freeing the temporary arrays later on. */
724
725                memcpy(&(*names)[i], tmp_names, sizeof(char *) *
726                       tmp_num_names);
727
728                memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
729                       tmp_num_names);
730
731                total_names += tmp_num_names;
732        }
733
734        *num_names = total_names;
735
736	return NT_STATUS_OK;
737}
738
739#ifdef HAVE_LDAP
740
741#include <ldap.h>
742
743static int get_ldap_seq(const char *server, int port, uint32 *seq)
744{
745	int ret = -1;
746	struct timeval to;
747	const char *attrs[] = {"highestCommittedUSN", NULL};
748	LDAPMessage *res = NULL;
749	char **values = NULL;
750	LDAP *ldp = NULL;
751
752	*seq = DOM_SEQUENCE_NONE;
753
754	/*
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.
757	 */
758
759	ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
760	if (ldp == NULL)
761		return -1;
762
763	/* Timeout if no response within 20 seconds. */
764	to.tv_sec = 10;
765	to.tv_usec = 0;
766
767	if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
768			   CONST_DISCARD(char **, attrs), 0, &to, &res))
769		goto done;
770
771	if (ldap_count_entries(ldp, res) != 1)
772		goto done;
773
774	values = ldap_get_values(ldp, res, "highestCommittedUSN");
775	if (!values || !values[0])
776		goto done;
777
778	*seq = atoi(values[0]);
779	ret = 0;
780
781  done:
782
783	if (values)
784		ldap_value_free(values);
785	if (res)
786		ldap_msgfree(res);
787	if (ldp)
788		ldap_unbind(ldp);
789	return ret;
790}
791
792/**********************************************************************
793 Get the sequence number for a Windows AD native mode domain using
794 LDAP queries.
795**********************************************************************/
796
797static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
798{
799	int ret = -1;
800	fstring ipstr;
801
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));
807	}
808	return ret;
809}
810
811#endif /* HAVE_LDAP */
812
813/* find the sequence number for a domain */
814static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
815{
816	TALLOC_CTX *mem_ctx;
817	SAM_UNK_CTR ctr;
818	NTSTATUS result;
819	POLICY_HND dom_pol;
820	BOOL got_seq_num = False;
821	struct rpc_pipe_client *cli;
822
823	DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
824
825	*seq = DOM_SEQUENCE_NONE;
826
827	if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
828		return NT_STATUS_NO_MEMORY;
829
830#ifdef HAVE_LDAP
831	if ( domain->native_mode )
832	{
833		int res;
834
835		DEBUG(8,("using get_ldap_seq() to retrieve the "
836			 "sequence number\n"));
837
838		res =  get_ldap_sequence_number( domain, seq );
839		if (res == 0)
840		{
841			result = NT_STATUS_OK;
842			DEBUG(10,("domain_sequence_number: LDAP for "
843				  "domain %s is %u\n",
844				  domain->name, *seq));
845			goto done;
846		}
847
848		DEBUG(10,("domain_sequence_number: failed to get LDAP "
849			  "sequence number for domain %s\n",
850			  domain->name ));
851	}
852#endif /* HAVE_LDAP */
853
854	result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
855	if (!NT_STATUS_IS_OK(result)) {
856		goto done;
857	}
858
859	/* Query domain info */
860
861	result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
862
863	if (NT_STATUS_IS_OK(result)) {
864		*seq = ctr.info.inf8.seq_num;
865		got_seq_num = True;
866		goto seq_num;
867	}
868
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 */
871
872	result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
873
874	if (NT_STATUS_IS_OK(result)) {
875		*seq = ctr.info.inf2.seq_num;
876		got_seq_num = True;
877	}
878
879 seq_num:
880	if (got_seq_num) {
881		DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
882			  domain->name, (unsigned)*seq));
883	} else {
884		DEBUG(10,("domain_sequence_number: failed to get sequence "
885			  "number (%u) for domain %s\n",
886			  (unsigned)*seq, domain->name ));
887	}
888
889  done:
890
891	talloc_destroy(mem_ctx);
892
893	return result;
894}
895
896/* get a list of trusted domains */
897static NTSTATUS trusted_domains(struct winbindd_domain *domain,
898				TALLOC_CTX *mem_ctx,
899				uint32 *num_domains,
900				char ***names,
901				char ***alt_names,
902				DOM_SID **dom_sids)
903{
904	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
905	uint32 enum_ctx = 0;
906	struct rpc_pipe_client *cli;
907	POLICY_HND lsa_policy;
908
909	DEBUG(3,("rpc: trusted_domains\n"));
910
911	*num_domains = 0;
912	*names = NULL;
913	*alt_names = NULL;
914	*dom_sids = NULL;
915
916	result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
917	if (!NT_STATUS_IS_OK(result))
918		return result;
919
920	result = STATUS_MORE_ENTRIES;
921
922	while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
923		uint32 start_idx, num;
924		char **tmp_names;
925		DOM_SID *tmp_sids;
926		int i;
927
928		result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
929						   &lsa_policy, &enum_ctx,
930						   &num, &tmp_names,
931						   &tmp_sids);
932
933		if (!NT_STATUS_IS_OK(result) &&
934		    !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
935			break;
936
937		start_idx = *num_domains;
938		*num_domains += num;
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;
948
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, "");
953		}
954	}
955	return result;
956}
957
958/* find the lockout policy for a domain */
959NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
960			      TALLOC_CTX *mem_ctx,
961			      SAM_UNK_INFO_12 *lockout_policy)
962{
963	NTSTATUS result;
964	struct rpc_pipe_client *cli;
965	POLICY_HND dom_pol;
966	SAM_UNK_CTR ctr;
967
968	DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
969
970	result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
971	if (!NT_STATUS_IS_OK(result)) {
972		goto done;
973	}
974
975	result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
976	if (!NT_STATUS_IS_OK(result)) {
977		goto done;
978	}
979
980	*lockout_policy = ctr.info.inf12;
981
982	DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n",
983		ctr.info.inf12.bad_attempt_lockout));
984
985  done:
986
987	return result;
988}
989
990/* find the password policy for a domain */
991NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
992			       TALLOC_CTX *mem_ctx,
993			       SAM_UNK_INFO_1 *password_policy)
994{
995	NTSTATUS result;
996	struct rpc_pipe_client *cli;
997	POLICY_HND dom_pol;
998	SAM_UNK_CTR ctr;
999
1000	DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1001
1002	result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1003	if (!NT_STATUS_IS_OK(result)) {
1004		goto done;
1005	}
1006
1007	result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
1008	if (!NT_STATUS_IS_OK(result)) {
1009		goto done;
1010	}
1011
1012	*password_policy = ctr.info.inf1;
1013
1014	DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1015		ctr.info.inf1.min_length_password));
1016
1017  done:
1018
1019	return result;
1020}
1021
1022
1023/* the rpc backend methods are exposed via this structure */
1024struct winbindd_methods msrpc_methods = {
1025	False,
1026	query_user_list,
1027	enum_dom_groups,
1028	enum_local_groups,
1029	msrpc_name_to_sid,
1030	msrpc_sid_to_name,
1031	msrpc_rids_to_names,
1032	query_user,
1033	lookup_usergroups,
1034	msrpc_lookup_useraliases,
1035	lookup_groupmem,
1036	sequence_number,
1037	msrpc_lockout_policy,
1038	msrpc_password_policy,
1039	trusted_domains,
1040};
1041