1/*
2   Unix SMB/CIFS implementation.
3
4   Winbind daemon connection manager
5
6   Copyright (C) Tim Potter 2001
7   Copyright (C) Andrew Bartlett 2002
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24/*
25   We need to manage connections to domain controllers without having to
26   mess up the main winbindd code with other issues.  The aim of the
27   connection manager is to:
28
29       - make connections to domain controllers and cache them
30       - re-establish connections when networks or servers go down
31       - centralise the policy on connection timeouts, domain controller
32	 selection etc
33       - manage re-entrancy for when winbindd becomes able to handle
34	 multiple outstanding rpc requests
35
36   Why not have connection management as part of the rpc layer like tng?
37   Good question.  This code may morph into libsmb/rpc_cache.c or something
38   like that but at the moment it's simply staying as part of winbind.	I
39   think the TNG architecture of forcing every user of the rpc layer to use
40   the connection caching system is a bad idea.	 It should be an optional
41   method of using the routines.
42
43   The TNG design is quite good but I disagree with some aspects of the
44   implementation. -tpot
45
46 */
47
48/*
49   TODO:
50
51     - I'm pretty annoyed by all the make_nmb_name() stuff.  It should be
52       moved down into another function.
53
54     - Take care when destroying cli_structs as they can be shared between
55       various sam handles.
56
57 */
58
59#include "includes.h"
60#include "winbindd.h"
61
62#undef DBGC_CLASS
63#define DBGC_CLASS DBGC_WINBIND
64
65/* Global list of connections.	Initially a DLIST but can become a hash
66   table or whatever later. */
67
68struct winbindd_cm_conn {
69	struct winbindd_cm_conn *prev, *next;
70	fstring domain;
71	fstring controller;
72	fstring pipe_name;
73	struct cli_state *cli;
74	POLICY_HND pol;
75};
76
77static struct winbindd_cm_conn *cm_conns = NULL;
78
79static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain,
80					  const char *pipe_name,
81					  struct winbindd_cm_conn **conn_out);
82
83/* Choose between anonymous or authenticated connections.  We need to use
84   an authenticated connection if DCs have the RestrictAnonymous registry
85   entry set > 0, or the "Additional restrictions for anonymous
86   connections" set in the win2k Local Security Policy.
87
88   Caller to free() result in domain, username, password
89*/
90
91static void cm_get_ipc_userpass(char **username, char **domain, char **password)
92{
93	*username = secrets_fetch(SECRETS_AUTH_USER, NULL);
94	*domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
95	*password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
96
97	if (*username && **username) {
98
99		if (!*domain || !**domain)
100			*domain = smb_xstrdup(lp_workgroup());
101
102		if (!*password || !**password)
103			*password = smb_xstrdup("");
104
105		DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
106			  *domain, *username));
107
108	} else {
109		DEBUG(3, ("IPC$ connections done anonymously\n"));
110		*username = smb_xstrdup("");
111		*domain = smb_xstrdup("");
112		*password = smb_xstrdup("");
113	}
114}
115
116/*
117  setup for schannel on any pipes opened on this connection
118*/
119static NTSTATUS setup_schannel( struct cli_state *cli, const char *domain )
120{
121	NTSTATUS ret;
122	uchar trust_password[16];
123	uint32 sec_channel_type;
124	DOM_SID sid;
125	time_t lct;
126
127	/* use the domain trust password if we're on a DC
128	   and this is not our domain */
129
130	if ( IS_DC && !strequal(domain, lp_workgroup()) ) {
131		char *pass = NULL;
132
133		if ( !secrets_fetch_trusted_domain_password( domain,
134			&pass, &sid, &lct) )
135		{
136			return NT_STATUS_UNSUCCESSFUL;
137		}
138
139		sec_channel_type = SEC_CHAN_DOMAIN;
140		E_md4hash(pass, trust_password);
141		SAFE_FREE( pass );
142
143	} else {
144		if (!secrets_fetch_trust_account_password(lp_workgroup(),
145			trust_password, NULL, &sec_channel_type))
146		{
147			return NT_STATUS_UNSUCCESSFUL;
148		}
149	}
150
151	ret = cli_nt_setup_netsec(cli, sec_channel_type,
152		AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN, trust_password);
153
154	return ret;
155}
156
157static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
158				     fstring dcname, struct in_addr *dc_ip)
159{
160	struct winbindd_domain *our_domain;
161	NTSTATUS result;
162	struct winbindd_cm_conn *conn;
163	TALLOC_CTX *mem_ctx;
164
165	fstring tmp;
166	char *p;
167
168	if (IS_DC)
169		return False;
170
171	if (domain->primary)
172		return False;
173
174	if ((our_domain = find_our_domain()) == NULL)
175		return False;
176
177	result = get_connection_from_cache(our_domain, PIPE_NETLOGON, &conn);
178	if (!NT_STATUS_IS_OK(result))
179		return False;
180
181	if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL)
182		return False;
183
184	result = cli_netlogon_getdcname(conn->cli, mem_ctx, domain->name, tmp);
185
186	talloc_destroy(mem_ctx);
187
188	if (!NT_STATUS_IS_OK(result))
189		return False;
190
191	/* cli_netlogon_getdcname gives us a name with \\ */
192	p = tmp;
193	if (*p == '\\') p+=1;
194	if (*p == '\\') p+=1;
195
196	fstrcpy(dcname, p);
197
198	if (!resolve_name(dcname, dc_ip, 0x20))
199		return False;
200
201	return True;
202}
203
204/************************************************************************
205 Given a fd with a just-connected TCP connection to a DC, open a connection
206 to the pipe.
207************************************************************************/
208
209static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
210				      const int sockfd,
211				      const int pipe_index,
212				      const char *controller,
213				      struct cli_state **cli,
214				      BOOL *retry)
215{
216	char *machine_password, *machine_krb5_principal;
217	char *ipc_username, *ipc_domain, *ipc_password;
218
219	BOOL got_mutex;
220	BOOL add_failed_connection = True;
221
222	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
223
224	struct sockaddr peeraddr;
225	socklen_t peeraddr_len;
226
227	struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
228
229	machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
230							  NULL);
231
232	if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
233		     lp_realm()) == -1) {
234		SAFE_FREE(machine_password);
235		return NT_STATUS_NO_MEMORY;
236	}
237
238	cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
239
240	*retry = True;
241
242	got_mutex = secrets_named_mutex(controller,
243					WINBIND_SERVER_MUTEX_WAIT_TIME);
244
245	if (!got_mutex) {
246		DEBUG(0,("cm_open_connection: mutex grab failed for %s\n",
247			 controller));
248		result = NT_STATUS_POSSIBLE_DEADLOCK;
249		goto done;
250	}
251
252	if ((*cli = cli_initialise(NULL)) == NULL) {
253		DEBUG(1, ("Could not cli_initialize\n"));
254		result = NT_STATUS_NO_MEMORY;
255		goto done;
256	}
257
258	(*cli)->timeout = 10000; 	/* 10 seconds */
259	(*cli)->fd = sockfd;
260	fstrcpy((*cli)->desthost, controller);
261	(*cli)->use_kerberos = True;
262
263	peeraddr_len = sizeof(peeraddr);
264
265	if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
266	    (peeraddr_len != sizeof(struct sockaddr_in)) ||
267	    (peeraddr_in->sin_family != PF_INET))
268	{
269		DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
270		goto done;
271	}
272
273	if (ntohs(peeraddr_in->sin_port) == 139) {
274		struct nmb_name calling;
275		struct nmb_name called;
276
277		make_nmb_name(&calling, global_myname(), 0x0);
278		make_nmb_name(&called, "*SMBSERVER", 0x20);
279
280		if (!cli_session_request(*cli, &calling, &called)) {
281			DEBUG(8, ("cli_session_request failed for %s\n",
282				  controller));
283			goto done;
284		}
285	}
286
287	cli_setup_signing_state(*cli, Undefined);
288
289	if (!cli_negprot(*cli)) {
290		DEBUG(1, ("cli_negprot failed\n"));
291		cli_shutdown(*cli);
292		goto done;
293	}
294
295	/* Krb5 session */
296
297	if ((lp_security() == SEC_ADS)
298	    && ((*cli)->protocol >= PROTOCOL_NT1 &&
299		(*cli)->capabilities & CAP_EXTENDED_SECURITY)) {
300
301		ADS_STATUS ads_status;
302		(*cli)->use_kerberos = True;
303		DEBUG(5, ("connecting to %s from %s with kerberos principal "
304			  "[%s]\n", controller, global_myname(),
305			  machine_krb5_principal));
306
307		ads_status = cli_session_setup_spnego(*cli,
308						      machine_krb5_principal,
309						      machine_password,
310						      lp_workgroup());
311
312		if (!ADS_ERR_OK(ads_status))
313			DEBUG(4,("failed kerberos session setup with %s\n",
314				 ads_errstr(ads_status)));
315
316		result = ads_ntstatus(ads_status);
317	}
318
319	if (NT_STATUS_IS_OK(result))
320		goto session_setup_done;
321
322	/* Fall back to non-kerberos session setup */
323
324	(*cli)->use_kerberos = False;
325
326	if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
327	    (strlen(ipc_username) > 0)) {
328
329		/* Only try authenticated if we have a username */
330
331		DEBUG(5, ("connecting to %s from %s with username "
332			  "[%s]\\[%s]\n",  controller, global_myname(),
333			  ipc_domain, ipc_username));
334
335		if (cli_session_setup(*cli, ipc_username,
336				      ipc_password, strlen(ipc_password)+1,
337				      ipc_password, strlen(ipc_password)+1,
338				      ipc_domain)) {
339			DEBUG(5, ("authenticated session setup failed\n"));
340			goto session_setup_done;
341		}
342	}
343
344	/* Fall back to anonymous connection, this might fail later */
345
346	if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
347		DEBUG(5, ("Connected anonymously\n"));
348		goto session_setup_done;
349	}
350
351	result = cli_nt_error(*cli);
352
353	if (NT_STATUS_IS_OK(result))
354		result = NT_STATUS_UNSUCCESSFUL;
355
356	/* We can't session setup */
357
358	goto done;
359
360 session_setup_done:
361
362	if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
363
364		result = cli_nt_error(*cli);
365
366		DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
367
368		if (NT_STATUS_IS_OK(result))
369			result = NT_STATUS_UNSUCCESSFUL;
370
371		cli_shutdown(*cli);
372		goto done;
373	}
374
375	secrets_named_mutex_release(controller);
376	got_mutex = False;
377	*retry = False;
378
379	if (domain->primary || IS_DC) {
380		NTSTATUS status = setup_schannel( *cli, domain->name );
381		if (!NT_STATUS_IS_OK(status)) {
382			DEBUG(3,("schannel refused - continuing without "
383				 "schannel (%s)\n", nt_errstr(status)));
384		}
385	}
386
387	/* set the domain if empty; needed for schannel connections */
388	if ( !*(*cli)->domain )
389		fstrcpy( (*cli)->domain, domain->name );
390
391	if ( !cli_nt_session_open (*cli, pipe_index) ) {
392
393		result = NT_STATUS_PIPE_NOT_AVAILABLE;
394
395		/* This might be a NT4 DC */
396		if ( is_win2k_pipe(pipe_index) )
397			add_failed_connection = False;
398
399		cli_shutdown(*cli);
400		goto done;
401	}
402
403	result = NT_STATUS_OK;
404	add_failed_connection = False;
405
406 done:
407	if (got_mutex)
408		secrets_named_mutex_release(controller);
409
410	SAFE_FREE(machine_password);
411	SAFE_FREE(machine_krb5_principal);
412	SAFE_FREE(ipc_username);
413	SAFE_FREE(ipc_domain);
414	SAFE_FREE(ipc_password);
415
416	if (add_failed_connection)
417		add_failed_connection_entry(domain->name, controller, result);
418
419	return result;
420}
421
422struct dc_name_ip {
423	fstring name;
424	struct in_addr ip;
425};
426
427static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
428			      const char *dcname, struct in_addr ip,
429			      struct dc_name_ip **dcs, int *num)
430{
431	if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname)))
432		return False;
433
434	*dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
435
436	if (*dcs == NULL)
437		return False;
438
439	fstrcpy((*dcs)[*num].name, dcname);
440	(*dcs)[*num].ip = ip;
441	*num += 1;
442	return True;
443}
444
445static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
446				  struct in_addr ip, uint16 port,
447				  struct sockaddr_in **addrs, int *num)
448{
449	*addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
450
451	if (*addrs == NULL)
452		return False;
453
454	(*addrs)[*num].sin_family = PF_INET;
455	putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
456	(*addrs)[*num].sin_port = htons(port);
457
458	*num += 1;
459	return True;
460}
461
462/*******************************************************************
463 convert an ip to a name
464*******************************************************************/
465
466static void dcip_to_name( const char *domainname, const char *realm, struct in_addr ip, fstring name )
467{
468	/* try node status request first */
469
470	if ( name_status_find(domainname, 0x1c, 0x20, ip, name) )
471		return;
472
473	/* backup in case the ads stuff fails */
474
475	fstrcpy( name, inet_ntoa(ip) );
476
477#ifdef WITH_ADS
478	/* for active directory servers, try to get the ldap server name.
479	   None of these failure should be considered critical for now */
480
481	if ( lp_security() == SEC_ADS )
482	{
483		ADS_STRUCT *ads;
484		ADS_STATUS status;
485
486		ads = ads_init( realm, domainname, NULL );
487		ads->auth.flags |= ADS_AUTH_NO_BIND;
488
489		if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) )  {
490			ads_destroy( &ads );
491			return;
492		}
493
494		status = ads_server_info(ads);
495		if ( !ADS_ERR_OK(status) ) {
496			ads_destroy( &ads );
497			return;
498		}
499
500		fstrcpy(name, ads->config.ldap_server_name);
501
502		ads_destroy( &ads );
503	}
504#endif
505
506	return;
507}
508
509
510/*******************************************************************
511 Retreive a list of IP address for domain controllers.  Fill in
512 the dcs[]  with results.
513*******************************************************************/
514
515static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
516		    struct dc_name_ip **dcs, int *num_dcs)
517{
518	fstring dcname;
519	struct  in_addr ip;
520	struct  ip_service *ip_list = NULL;
521	int     iplist_size = 0;
522	int     i;
523	BOOL    is_our_domain;
524
525
526	is_our_domain = strequal(domain->name, lp_workgroup());
527
528	if ( !is_our_domain
529		&& get_dc_name_via_netlogon(domain, dcname, &ip)
530		&& add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
531	{
532		return True;
533	}
534
535	if ( is_our_domain
536		&& must_use_pdc(domain->name)
537		&& get_pdc_ip(domain->name, &ip))
538	{
539		if (add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip), ip, dcs, num_dcs))
540			return True;
541	}
542
543	/* try standard netbios queries first */
544
545	get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
546
547	/* check for security = ads and use DNS if we can */
548
549	if ( iplist_size==0 && lp_security() == SEC_ADS )
550		get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
551
552	/* now add to the dc array.  We'll wait until the last minute
553	   to look up the name of the DC.  But we fill in the char* for
554	   the ip now in to make the failed connection cache work */
555
556	for ( i=0; i<iplist_size; i++ ) {
557		add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
558			ip_list[i].ip, dcs, num_dcs);
559	}
560
561	SAFE_FREE( ip_list );
562
563	return True;
564}
565
566static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
567			const struct winbindd_domain *domain,
568			fstring dcname, struct sockaddr_in *addr, int *fd)
569{
570	struct dc_name_ip *dcs = NULL;
571	int num_dcs = 0;
572
573	const char **dcnames = NULL;
574	int num_dcnames = 0;
575
576	struct sockaddr_in *addrs = NULL;
577	int num_addrs = 0;
578
579	int i, fd_index;
580
581	if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
582		return False;
583
584	for (i=0; i<num_dcs; i++) {
585
586		add_string_to_array(mem_ctx, dcs[i].name,
587				    &dcnames, &num_dcnames);
588		add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
589				      &addrs, &num_addrs);
590
591		add_string_to_array(mem_ctx, dcs[i].name,
592				    &dcnames, &num_dcnames);
593		add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
594				      &addrs, &num_addrs);
595	}
596
597	if ((num_dcnames == 0) || (num_dcnames != num_addrs))
598		return False;
599
600	if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) )
601	{
602		for (i=0; i<num_dcs; i++) {
603			add_failed_connection_entry(domain->name,
604				dcs[i].name, NT_STATUS_UNSUCCESSFUL);
605		}
606		return False;
607	}
608
609	*addr = addrs[fd_index];
610
611	/* if we have no name on the server or just an IP address for
612	   the name, now try to get the name */
613
614	if ( is_ipaddress(dcnames[fd_index]) || *dcnames[fd_index] == '\0' )
615		dcip_to_name( domain->name, domain->alt_name, addr->sin_addr, dcname );
616	else
617		fstrcpy(dcname, dcnames[fd_index]);
618
619	return True;
620}
621
622static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
623				   const int pipe_index,
624				   struct winbindd_cm_conn *new_conn)
625{
626	TALLOC_CTX *mem_ctx;
627	NTSTATUS result;
628
629	int retries;
630
631	if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
632		return NT_STATUS_NO_MEMORY;
633
634	for (retries = 0; retries < 3; retries++) {
635
636		int fd = -1;
637		BOOL retry;
638
639		result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
640
641		if ((strlen(domain->dcname) > 0) &&
642		    NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
643							      domain->dcname))) {
644			int dummy;
645			if (!open_any_socket_out(&domain->dcaddr, 1, 10000,
646						 &dummy, &fd)) {
647				fd = -1;
648			}
649		}
650
651		if ((fd == -1) &&
652		    !find_new_dc(mem_ctx, domain, domain->dcname,
653				 &domain->dcaddr, &fd))
654			break;
655
656		new_conn->cli = NULL;
657
658		result = cm_prepare_connection(domain, fd, pipe_index,
659					       domain->dcname,
660					       &new_conn->cli, &retry);
661
662		if (NT_STATUS_IS_OK(result)) {
663			fstrcpy(new_conn->domain, domain->name);
664			/* Initialise SMB connection */
665			fstrcpy(new_conn->pipe_name,
666				get_pipe_name_from_index(pipe_index));
667			break;
668		}
669
670		if (!retry)
671			break;
672	}
673
674	talloc_destroy(mem_ctx);
675	return result;
676}
677
678/************************************************************************
679 Wrapper around statuc cm_open_connection to retreive a freshly
680 setup cli_state struct
681************************************************************************/
682
683NTSTATUS cm_fresh_connection(struct winbindd_domain *domain, const int pipe_index,
684			       struct cli_state **cli)
685{
686	NTSTATUS result;
687	struct winbindd_cm_conn conn;
688
689	result = cm_open_connection( domain, pipe_index, &conn );
690
691	if ( NT_STATUS_IS_OK(result) )
692		*cli = conn.cli;
693
694	return result;
695}
696
697/* Return true if a connection is still alive */
698
699static BOOL connection_ok(struct winbindd_cm_conn *conn)
700{
701	if (!conn) {
702		smb_panic("Invalid parameter passed to connection_ok():  conn was NULL!\n");
703		return False;
704	}
705
706	if (!conn->cli) {
707		DEBUG(3, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n",
708			  conn->controller, conn->domain, conn->pipe_name));
709		return False;
710	}
711
712	if (!conn->cli->initialised) {
713		DEBUG(3, ("Connection to %s for domain %s (pipe %s) was never initialised!\n",
714			  conn->controller, conn->domain, conn->pipe_name));
715		return False;
716	}
717
718	if (conn->cli->fd == -1) {
719		DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n",
720			  conn->controller, conn->domain, conn->pipe_name));
721		return False;
722	}
723
724	return True;
725}
726
727/* Search the cache for a connection. If there is a broken one,
728   shut it down properly and return NULL. */
729
730static void find_cm_connection(struct winbindd_domain *domain, const char *pipe_name,
731			       struct winbindd_cm_conn **conn_out)
732{
733	struct winbindd_cm_conn *conn;
734
735	for (conn = cm_conns; conn; ) {
736		if (strequal(conn->domain, domain->name) &&
737		    strequal(conn->pipe_name, pipe_name)) {
738			if (!connection_ok(conn)) {
739				/* Dead connection - remove it. */
740				struct winbindd_cm_conn *conn_temp = conn->next;
741				if (conn->cli)
742					cli_shutdown(conn->cli);
743				DLIST_REMOVE(cm_conns, conn);
744				SAFE_FREE(conn);
745				conn = conn_temp;  /* Keep the loop moving */
746				continue;
747			} else {
748				break;
749			}
750		}
751		conn = conn->next;
752	}
753
754	*conn_out = conn;
755}
756
757/* Initialize a new connection up to the RPC BIND. */
758
759static NTSTATUS new_cm_connection(struct winbindd_domain *domain, const char *pipe_name,
760				  struct winbindd_cm_conn **conn_out)
761{
762	struct winbindd_cm_conn *conn;
763	NTSTATUS result;
764
765	if (!(conn = SMB_MALLOC_P(struct winbindd_cm_conn)))
766		return NT_STATUS_NO_MEMORY;
767
768	ZERO_STRUCTP(conn);
769
770	if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) {
771		DEBUG(3, ("Could not open a connection to %s for %s (%s)\n",
772			  domain->name, pipe_name, nt_errstr(result)));
773		SAFE_FREE(conn);
774		return result;
775	}
776	DLIST_ADD(cm_conns, conn);
777
778	*conn_out = conn;
779	return NT_STATUS_OK;
780}
781
782/* Get a connection to the remote DC and open the pipe.  If there is already a connection, use that */
783
784static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain, const char *pipe_name,
785					  struct winbindd_cm_conn **conn_out)
786{
787	find_cm_connection(domain, pipe_name, conn_out);
788
789	if (*conn_out != NULL)
790		return NT_STATUS_OK;
791
792	return new_cm_connection(domain, pipe_name, conn_out);
793}
794
795/**********************************************************************************
796 We can 'sense' certain things about the DC by it's replies to certain questions.
797
798 This tells us if this particular remote server is Active Directory, and if it is
799 native mode.
800**********************************************************************************/
801
802void set_dc_type_and_flags( struct winbindd_domain *domain )
803{
804	NTSTATUS 		result;
805	struct winbindd_cm_conn	conn;
806	DS_DOMINFO_CTR		ctr;
807	TALLOC_CTX              *mem_ctx = NULL;
808
809	ZERO_STRUCT( conn );
810	ZERO_STRUCT( ctr );
811
812	domain->native_mode = False;
813	domain->active_directory = False;
814
815	if (domain->internal) {
816		domain->initialized = True;
817		return;
818	}
819
820	if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) {
821		DEBUG(5, ("set_dc_type_and_flags: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
822			  domain->name, nt_errstr(result)));
823		domain->initialized = True;
824		return;
825	}
826
827	if ( conn.cli ) {
828		if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli,
829				conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) {
830			goto done;
831		}
832	}
833
834	if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING)
835			&& !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
836		domain->native_mode = True;
837
838	/* Cheat - shut down the DS pipe, and open LSA */
839
840	cli_nt_session_close(conn.cli);
841
842	if ( cli_nt_session_open (conn.cli, PI_LSARPC) ) {
843		char *domain_name = NULL;
844		char *dns_name = NULL;
845		DOM_SID *dom_sid = NULL;
846
847		mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n", domain->name);
848		if (!mem_ctx) {
849			DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
850			return;
851		}
852
853		result = cli_lsa_open_policy2(conn.cli, mem_ctx, True,
854					      SEC_RIGHTS_MAXIMUM_ALLOWED,
855					      &conn.pol);
856
857		if (NT_STATUS_IS_OK(result)) {
858			/* This particular query is exactly what Win2k clients use
859			   to determine that the DC is active directory */
860			result = cli_lsa_query_info_policy2(conn.cli, mem_ctx,
861							    &conn.pol,
862							    12, &domain_name,
863							    &dns_name, NULL,
864							    NULL, &dom_sid);
865		}
866
867		if (NT_STATUS_IS_OK(result)) {
868			if (domain_name)
869				fstrcpy(domain->name, domain_name);
870
871			if (dns_name)
872				fstrcpy(domain->alt_name, dns_name);
873
874			if (dom_sid)
875				sid_copy(&domain->sid, dom_sid);
876
877			domain->active_directory = True;
878		} else {
879
880			result = cli_lsa_open_policy(conn.cli, mem_ctx, True,
881						     SEC_RIGHTS_MAXIMUM_ALLOWED,
882						     &conn.pol);
883
884			if (!NT_STATUS_IS_OK(result))
885				goto done;
886
887			result = cli_lsa_query_info_policy(conn.cli, mem_ctx,
888							   &conn.pol, 5, &domain_name,
889							   &dom_sid);
890
891			if (NT_STATUS_IS_OK(result)) {
892				if (domain_name)
893					fstrcpy(domain->name, domain_name);
894
895				if (dom_sid)
896					sid_copy(&domain->sid, dom_sid);
897			}
898		}
899	}
900
901done:
902
903	DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name,
904		domain->active_directory ? "ADS" : "NT4",
905		domain->native_mode ? "native mode" :
906		((domain->active_directory && !domain->native_mode) ? "mixed mode" : "")));
907
908	/* close the connection;  no other calls use this pipe and it is called only
909	   on reestablishing the domain list   --jerry */
910
911	if ( conn.cli )
912		cli_shutdown( conn.cli );
913
914	talloc_destroy(mem_ctx);
915
916	domain->initialized = True;
917
918	return;
919}
920
921
922
923/* Return a LSA policy handle on a domain */
924
925NTSTATUS cm_get_lsa_handle(struct winbindd_domain *domain, CLI_POLICY_HND **return_hnd)
926{
927	struct winbindd_cm_conn *conn;
928	uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
929	NTSTATUS result;
930	static CLI_POLICY_HND hnd;
931
932	/* Look for existing connections */
933
934	if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn)))
935		return result;
936
937	/* This *shitty* code needs scrapping ! JRA */
938
939	if (policy_handle_is_valid(&conn->pol)) {
940		hnd.pol = conn->pol;
941		hnd.cli = conn->cli;
942		*return_hnd = &hnd;
943
944		return NT_STATUS_OK;
945	}
946
947	result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
948				     des_access, &conn->pol);
949
950	if (!NT_STATUS_IS_OK(result)) {
951		/* Hit the cache code again.  This cleans out the old connection and gets a new one */
952		if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
953			if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn)))
954				return result;
955
956			result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
957						     des_access, &conn->pol);
958		}
959
960		if (!NT_STATUS_IS_OK(result)) {
961			cli_shutdown(conn->cli);
962			DLIST_REMOVE(cm_conns, conn);
963			SAFE_FREE(conn);
964			return result;
965		}
966	}
967
968	hnd.pol = conn->pol;
969	hnd.cli = conn->cli;
970
971	*return_hnd = &hnd;
972
973	return NT_STATUS_OK;
974}
975
976/* Return a SAM policy handle on a domain */
977
978NTSTATUS cm_get_sam_handle(struct winbindd_domain *domain, CLI_POLICY_HND **return_hnd)
979{
980	struct winbindd_cm_conn *conn;
981	uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
982	NTSTATUS result;
983	static CLI_POLICY_HND hnd;
984
985	/* Look for existing connections */
986
987	if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn)))
988		return result;
989
990	/* This *shitty* code needs scrapping ! JRA */
991
992	if (policy_handle_is_valid(&conn->pol)) {
993		hnd.pol = conn->pol;
994		hnd.cli = conn->cli;
995
996		*return_hnd = &hnd;
997
998		return NT_STATUS_OK;
999	}
1000
1001	result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
1002				  des_access, &conn->pol);
1003
1004	if (!NT_STATUS_IS_OK(result)) {
1005		/* Hit the cache code again.  This cleans out the old connection and gets a new one */
1006		if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
1007
1008			if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn)))
1009				return result;
1010
1011			result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
1012						  des_access, &conn->pol);
1013		}
1014
1015		if (!NT_STATUS_IS_OK(result)) {
1016
1017			cli_shutdown(conn->cli);
1018			DLIST_REMOVE(cm_conns, conn);
1019			SAFE_FREE(conn);
1020
1021			return result;
1022		}
1023	}
1024
1025	hnd.pol = conn->pol;
1026	hnd.cli = conn->cli;
1027
1028	*return_hnd = &hnd;
1029
1030	return NT_STATUS_OK;
1031}
1032
1033/* Get a handle on a netlogon pipe.  This is a bit of a hack to re-use the
1034   netlogon pipe as no handle is returned. */
1035
1036NTSTATUS cm_get_netlogon_cli(struct winbindd_domain *domain,
1037			     const unsigned char *trust_passwd,
1038			     uint32 sec_channel_type,
1039			     BOOL fresh,
1040			     struct cli_state **cli)
1041{
1042	NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1043	struct winbindd_cm_conn *conn;
1044	fstring lock_name;
1045	BOOL got_mutex;
1046
1047	if (!cli)
1048		return NT_STATUS_INVALID_PARAMETER;
1049
1050	/* Open an initial conection - keep the mutex. */
1051
1052	find_cm_connection(domain, PIPE_NETLOGON, &conn);
1053
1054	if ( fresh && (conn != NULL) ) {
1055		cli_shutdown(conn->cli);
1056		conn->cli = NULL;
1057
1058		conn = NULL;
1059
1060		/* purge connection from cache */
1061		find_cm_connection(domain, PIPE_NETLOGON, &conn);
1062		if (conn != NULL) {
1063			DEBUG(0,("Could not purge connection\n"));
1064			return NT_STATUS_UNSUCCESSFUL;
1065		}
1066	}
1067
1068	if (conn != NULL) {
1069		*cli = conn->cli;
1070		return NT_STATUS_OK;
1071	}
1072
1073	result = new_cm_connection(domain, PIPE_NETLOGON, &conn);
1074
1075	if (!NT_STATUS_IS_OK(result))
1076		return result;
1077
1078	fstr_sprintf(lock_name, "NETLOGON\\%s", conn->controller);
1079
1080	if (!(got_mutex = secrets_named_mutex(lock_name, WINBIND_SERVER_MUTEX_WAIT_TIME))) {
1081		DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", conn->controller));
1082	}
1083
1084	if ( sec_channel_type == SEC_CHAN_DOMAIN )
1085		fstr_sprintf(conn->cli->mach_acct, "%s$", lp_workgroup());
1086
1087	/* This must be the remote domain (not ours) for schannel */
1088
1089	fstrcpy( conn->cli->domain, domain->name);
1090
1091	result = cli_nt_establish_netlogon(conn->cli, sec_channel_type, trust_passwd);
1092
1093	if (got_mutex)
1094		secrets_named_mutex_release(lock_name);
1095
1096	if (!NT_STATUS_IS_OK(result)) {
1097		cli_shutdown(conn->cli);
1098		DLIST_REMOVE(cm_conns, conn);
1099		SAFE_FREE(conn);
1100		return result;
1101	}
1102
1103	*cli = conn->cli;
1104
1105	return result;
1106}
1107
1108/* Dump the current connection status */
1109
1110static void dump_conn_list(void)
1111{
1112	struct winbindd_cm_conn *con;
1113
1114	DEBUG(0, ("\tDomain	     Controller	     Pipe\n"));
1115
1116	for(con = cm_conns; con; con = con->next) {
1117		char *msg;
1118
1119		/* Display pipe info */
1120
1121		if (asprintf(&msg, "\t%-15s %-15s %-16s", con->domain, con->controller, con->pipe_name) < 0) {
1122			DEBUG(0, ("Error: not enough memory!\n"));
1123		} else {
1124			DEBUG(0, ("%s\n", msg));
1125			SAFE_FREE(msg);
1126		}
1127	}
1128}
1129
1130void winbindd_cm_status(void)
1131{
1132	/* List open connections */
1133
1134	DEBUG(0, ("winbindd connection manager status:\n"));
1135
1136	if (cm_conns)
1137		dump_conn_list();
1138	else
1139		DEBUG(0, ("\tNo active connections\n"));
1140}
1141
1142/* Close all cached connections */
1143
1144void winbindd_cm_flush(void)
1145{
1146	struct winbindd_cm_conn *conn, tmp;
1147
1148	/* Flush connection cache */
1149
1150	for (conn = cm_conns; conn; conn = conn->next) {
1151
1152		if (!connection_ok(conn))
1153			continue;
1154
1155		DEBUG(10, ("Closing connection to %s on %s\n",
1156			conn->pipe_name, conn->controller));
1157
1158		if (conn->cli)
1159			cli_shutdown(conn->cli);
1160
1161		tmp.next = conn->next;
1162
1163		DLIST_REMOVE(cm_conns, conn);
1164		SAFE_FREE(conn);
1165		conn = &tmp;
1166	}
1167
1168	/* Flush failed connection cache */
1169
1170	flush_negative_conn_cache();
1171}
1172