• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source3/winbindd/
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   Copyright (C) Gerald (Jerry) Carter     2003-2005.
9   Copyright (C) Volker Lendecke           2004-2005
10   Copyright (C) Jeremy Allison		   2006
11
12   This program is free software; you can redistribute it and/or modify
13   it under the terms of the GNU General Public License as published by
14   the Free Software Foundation; either version 3 of the License, or
15   (at your option) any later version.
16
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
20   GNU General Public License for more details.
21
22   You should have received a copy of the GNU General Public License
23   along with this program.  If not, see <http://www.gnu.org/licenses/>.
24*/
25
26/*
27   We need to manage connections to domain controllers without having to
28   mess up the main winbindd code with other issues.  The aim of the
29   connection manager is to:
30
31       - make connections to domain controllers and cache them
32       - re-establish connections when networks or servers go down
33       - centralise the policy on connection timeouts, domain controller
34	 selection etc
35       - manage re-entrancy for when winbindd becomes able to handle
36	 multiple outstanding rpc requests
37
38   Why not have connection management as part of the rpc layer like tng?
39   Good question.  This code may morph into libsmb/rpc_cache.c or something
40   like that but at the moment it's simply staying as part of winbind.	I
41   think the TNG architecture of forcing every user of the rpc layer to use
42   the connection caching system is a bad idea.	 It should be an optional
43   method of using the routines.
44
45   The TNG design is quite good but I disagree with some aspects of the
46   implementation. -tpot
47
48 */
49
50/*
51   TODO:
52
53     - I'm pretty annoyed by all the make_nmb_name() stuff.  It should be
54       moved down into another function.
55
56     - Take care when destroying cli_structs as they can be shared between
57       various sam handles.
58
59 */
60
61#include "includes.h"
62#include "winbindd.h"
63#include "../libcli/auth/libcli_auth.h"
64#include "../librpc/gen_ndr/cli_netlogon.h"
65#include "../librpc/gen_ndr/cli_samr.h"
66#include "../librpc/gen_ndr/cli_lsa.h"
67#include "../librpc/gen_ndr/cli_dssetup.h"
68
69#undef DBGC_CLASS
70#define DBGC_CLASS DBGC_WINBIND
71
72struct dc_name_ip {
73	fstring name;
74	struct sockaddr_storage ss;
75};
76
77extern struct winbindd_methods reconnect_methods;
78extern bool override_logfile;
79
80static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
81static void set_dc_type_and_flags( struct winbindd_domain *domain );
82static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
83		    struct dc_name_ip **dcs, int *num_dcs);
84
85/****************************************************************
86 Child failed to find DC's. Reschedule check.
87****************************************************************/
88
89static void msg_failed_to_go_online(struct messaging_context *msg,
90				    void *private_data,
91				    uint32_t msg_type,
92				    struct server_id server_id,
93				    DATA_BLOB *data)
94{
95	struct winbindd_domain *domain;
96	const char *domainname = (const char *)data->data;
97
98	if (data->data == NULL || data->length == 0) {
99		return;
100	}
101
102	DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
103
104	for (domain = domain_list(); domain; domain = domain->next) {
105		if (domain->internal) {
106			continue;
107		}
108
109		if (strequal(domain->name, domainname)) {
110			if (domain->online) {
111				/* We're already online, ignore. */
112				DEBUG(5,("msg_fail_to_go_online: domain %s "
113					"already online.\n", domainname));
114				continue;
115			}
116
117			/* Reschedule the online check. */
118			set_domain_offline(domain);
119			break;
120		}
121	}
122}
123
124/****************************************************************
125 Actually cause a reconnect from a message.
126****************************************************************/
127
128static void msg_try_to_go_online(struct messaging_context *msg,
129				 void *private_data,
130				 uint32_t msg_type,
131				 struct server_id server_id,
132				 DATA_BLOB *data)
133{
134	struct winbindd_domain *domain;
135	const char *domainname = (const char *)data->data;
136
137	if (data->data == NULL || data->length == 0) {
138		return;
139	}
140
141	DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
142
143	for (domain = domain_list(); domain; domain = domain->next) {
144		if (domain->internal) {
145			continue;
146		}
147
148		if (strequal(domain->name, domainname)) {
149
150			if (domain->online) {
151				/* We're already online, ignore. */
152				DEBUG(5,("msg_try_to_go_online: domain %s "
153					"already online.\n", domainname));
154				continue;
155			}
156
157			/* This call takes care of setting the online
158			   flag to true if we connected, or re-adding
159			   the offline handler if false. Bypasses online
160			   check so always does network calls. */
161
162			init_dc_connection_network(domain);
163			break;
164		}
165	}
166}
167
168/****************************************************************
169 Fork a child to try and contact a DC. Do this as contacting a
170 DC requires blocking lookups and we don't want to block our
171 parent.
172****************************************************************/
173
174static bool fork_child_dc_connect(struct winbindd_domain *domain)
175{
176	struct dc_name_ip *dcs = NULL;
177	int num_dcs = 0;
178	TALLOC_CTX *mem_ctx = NULL;
179	pid_t parent_pid = sys_getpid();
180	char *lfile = NULL;
181
182	if (domain->dc_probe_pid != (pid_t)-1) {
183		/*
184		 * We might already have a DC probe
185		 * child working, check.
186		 */
187		if (process_exists_by_pid(domain->dc_probe_pid)) {
188			DEBUG(10,("fork_child_dc_connect: pid %u already "
189				"checking for DC's.\n",
190				(unsigned int)domain->dc_probe_pid));
191			return true;
192		}
193		domain->dc_probe_pid = (pid_t)-1;
194	}
195
196	domain->dc_probe_pid = sys_fork();
197
198	if (domain->dc_probe_pid == (pid_t)-1) {
199		DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
200		return False;
201	}
202
203	if (domain->dc_probe_pid != (pid_t)0) {
204		/* Parent */
205		messaging_register(winbind_messaging_context(), NULL,
206				   MSG_WINBIND_TRY_TO_GO_ONLINE,
207				   msg_try_to_go_online);
208		messaging_register(winbind_messaging_context(), NULL,
209				   MSG_WINBIND_FAILED_TO_GO_ONLINE,
210				   msg_failed_to_go_online);
211		return True;
212	}
213
214	/* Child. */
215
216	/* Leave messages blocked - we will never process one. */
217
218	if (!override_logfile) {
219		if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
220			DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
221			_exit(1);
222		}
223	}
224
225	if (!winbindd_reinit_after_fork(lfile)) {
226		messaging_send_buf(winbind_messaging_context(),
227				   pid_to_procid(parent_pid),
228				   MSG_WINBIND_FAILED_TO_GO_ONLINE,
229				   (uint8 *)domain->name,
230				   strlen(domain->name)+1);
231		_exit(1);
232	}
233	SAFE_FREE(lfile);
234
235	mem_ctx = talloc_init("fork_child_dc_connect");
236	if (!mem_ctx) {
237		DEBUG(0,("talloc_init failed.\n"));
238		messaging_send_buf(winbind_messaging_context(),
239				   pid_to_procid(parent_pid),
240				   MSG_WINBIND_FAILED_TO_GO_ONLINE,
241				   (uint8 *)domain->name,
242				   strlen(domain->name)+1);
243		_exit(1);
244	}
245
246	if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
247		/* Still offline ? Can't find DC's. */
248		messaging_send_buf(winbind_messaging_context(),
249				   pid_to_procid(parent_pid),
250				   MSG_WINBIND_FAILED_TO_GO_ONLINE,
251				   (uint8 *)domain->name,
252				   strlen(domain->name)+1);
253		_exit(0);
254	}
255
256	/* We got a DC. Send a message to our parent to get it to
257	   try and do the same. */
258
259	messaging_send_buf(winbind_messaging_context(),
260			   pid_to_procid(parent_pid),
261			   MSG_WINBIND_TRY_TO_GO_ONLINE,
262			   (uint8 *)domain->name,
263			   strlen(domain->name)+1);
264	_exit(0);
265}
266
267/****************************************************************
268 Handler triggered if we're offline to try and detect a DC.
269****************************************************************/
270
271static void check_domain_online_handler(struct event_context *ctx,
272					struct timed_event *te,
273					struct timeval now,
274					void *private_data)
275{
276        struct winbindd_domain *domain =
277                (struct winbindd_domain *)private_data;
278
279	DEBUG(10,("check_domain_online_handler: called for domain "
280		  "%s (online = %s)\n", domain->name,
281		  domain->online ? "True" : "False" ));
282
283	TALLOC_FREE(domain->check_online_event);
284
285	/* Are we still in "startup" mode ? */
286
287	if (domain->startup && (now.tv_sec > domain->startup_time + 30)) {
288		/* No longer in "startup" mode. */
289		DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
290			domain->name ));
291		domain->startup = False;
292	}
293
294	/* We've been told to stay offline, so stay
295	   that way. */
296
297	if (get_global_winbindd_state_offline()) {
298		DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
299			domain->name ));
300		return;
301	}
302
303	/* Fork a child to test if it can contact a DC.
304	   If it can then send ourselves a message to
305	   cause a reconnect. */
306
307	fork_child_dc_connect(domain);
308}
309
310/****************************************************************
311 If we're still offline setup the timeout check.
312****************************************************************/
313
314static void calc_new_online_timeout_check(struct winbindd_domain *domain)
315{
316	int wbr = lp_winbind_reconnect_delay();
317
318	if (domain->startup) {
319		domain->check_online_timeout = 10;
320	} else if (domain->check_online_timeout < wbr) {
321		domain->check_online_timeout = wbr;
322	}
323}
324
325/****************************************************************
326 Set domain offline and also add handler to put us back online
327 if we detect a DC.
328****************************************************************/
329
330void set_domain_offline(struct winbindd_domain *domain)
331{
332	DEBUG(10,("set_domain_offline: called for domain %s\n",
333		domain->name ));
334
335	TALLOC_FREE(domain->check_online_event);
336
337	if (domain->internal) {
338		DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
339			domain->name ));
340		return;
341	}
342
343	domain->online = False;
344
345	/* Offline domains are always initialized. They're
346	   re-initialized when they go back online. */
347
348	domain->initialized = True;
349
350	/* We only add the timeout handler that checks and
351	   allows us to go back online when we've not
352	   been told to remain offline. */
353
354	if (get_global_winbindd_state_offline()) {
355		DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
356			domain->name ));
357		return;
358	}
359
360	/* If we're in startup mode, check again in 10 seconds, not in
361	   lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
362
363	calc_new_online_timeout_check(domain);
364
365	domain->check_online_event = event_add_timed(winbind_event_context(),
366						NULL,
367						timeval_current_ofs(domain->check_online_timeout,0),
368						check_domain_online_handler,
369						domain);
370
371	/* The above *has* to succeed for winbindd to work. */
372	if (!domain->check_online_event) {
373		smb_panic("set_domain_offline: failed to add online handler");
374	}
375
376	DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
377		domain->name ));
378
379	/* Send an offline message to the idmap child when our
380	   primary domain goes offline */
381
382	if ( domain->primary ) {
383		struct winbindd_child *idmap = idmap_child();
384
385		if ( idmap->pid != 0 ) {
386			messaging_send_buf(winbind_messaging_context(),
387					   pid_to_procid(idmap->pid),
388					   MSG_WINBIND_OFFLINE,
389					   (uint8 *)domain->name,
390					   strlen(domain->name)+1);
391		}
392	}
393
394	return;
395}
396
397/****************************************************************
398 Set domain online - if allowed.
399****************************************************************/
400
401static void set_domain_online(struct winbindd_domain *domain)
402{
403	DEBUG(10,("set_domain_online: called for domain %s\n",
404		domain->name ));
405
406	if (domain->internal) {
407		DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
408			domain->name ));
409		return;
410	}
411
412	if (get_global_winbindd_state_offline()) {
413		DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
414			domain->name ));
415		return;
416	}
417
418	winbindd_set_locator_kdc_envs(domain);
419
420	/* If we are waiting to get a krb5 ticket, trigger immediately. */
421	ccache_regain_all_now();
422
423	/* Ok, we're out of any startup mode now... */
424	domain->startup = False;
425
426	if (domain->online == False) {
427		/* We were offline - now we're online. We default to
428		   using the MS-RPC backend if we started offline,
429		   and if we're going online for the first time we
430		   should really re-initialize the backends and the
431		   checks to see if we're talking to an AD or NT domain.
432		*/
433
434		domain->initialized = False;
435
436		/* 'reconnect_methods' is the MS-RPC backend. */
437		if (domain->backend == &reconnect_methods) {
438			domain->backend = NULL;
439		}
440	}
441
442	/* Ensure we have no online timeout checks. */
443	domain->check_online_timeout = 0;
444	TALLOC_FREE(domain->check_online_event);
445
446	/* Ensure we ignore any pending child messages. */
447	messaging_deregister(winbind_messaging_context(),
448			     MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
449	messaging_deregister(winbind_messaging_context(),
450			     MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
451
452	domain->online = True;
453
454	/* Send an online message to the idmap child when our
455	   primary domain comes online */
456
457	if ( domain->primary ) {
458		struct winbindd_child *idmap = idmap_child();
459
460		if ( idmap->pid != 0 ) {
461			messaging_send_buf(winbind_messaging_context(),
462					   pid_to_procid(idmap->pid),
463					   MSG_WINBIND_ONLINE,
464					   (uint8 *)domain->name,
465					   strlen(domain->name)+1);
466		}
467	}
468
469	return;
470}
471
472/****************************************************************
473 Requested to set a domain online.
474****************************************************************/
475
476void set_domain_online_request(struct winbindd_domain *domain)
477{
478	struct timeval tev;
479
480	DEBUG(10,("set_domain_online_request: called for domain %s\n",
481		domain->name ));
482
483	if (get_global_winbindd_state_offline()) {
484		DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
485			domain->name ));
486		return;
487	}
488
489	if (domain->internal) {
490		DEBUG(10, ("set_domain_online_request: Internal domains are "
491			   "always online\n"));
492		return;
493	}
494
495	/* We've been told it's safe to go online and
496	   try and connect to a DC. But I don't believe it
497	   because network manager seems to lie.
498	   Wait at least 5 seconds. Heuristics suck... */
499
500
501	GetTimeOfDay(&tev);
502
503	/* Go into "startup" mode again. */
504	domain->startup_time = tev.tv_sec;
505	domain->startup = True;
506
507	tev.tv_sec += 5;
508
509	if (!domain->check_online_event) {
510		/* If we've come from being globally offline we
511		   don't have a check online event handler set.
512		   We need to add one now we're trying to go
513		   back online. */
514
515		DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
516			domain->name ));
517	}
518
519	TALLOC_FREE(domain->check_online_event);
520
521	domain->check_online_event = event_add_timed(winbind_event_context(),
522						     NULL,
523						     tev,
524						     check_domain_online_handler,
525						     domain);
526
527	/* The above *has* to succeed for winbindd to work. */
528	if (!domain->check_online_event) {
529		smb_panic("set_domain_online_request: failed to add online handler");
530	}
531}
532
533/****************************************************************
534 Add -ve connection cache entries for domain and realm.
535****************************************************************/
536
537void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
538					const char *server,
539					NTSTATUS result)
540{
541	add_failed_connection_entry(domain->name, server, result);
542	/* If this was the saf name for the last thing we talked to,
543	   remove it. */
544	saf_delete(domain->name);
545	if (*domain->alt_name) {
546		add_failed_connection_entry(domain->alt_name, server, result);
547		saf_delete(domain->alt_name);
548	}
549	winbindd_unset_locator_kdc_env(domain);
550}
551
552/* Choose between anonymous or authenticated connections.  We need to use
553   an authenticated connection if DCs have the RestrictAnonymous registry
554   entry set > 0, or the "Additional restrictions for anonymous
555   connections" set in the win2k Local Security Policy.
556
557   Caller to free() result in domain, username, password
558*/
559
560static void cm_get_ipc_userpass(char **username, char **domain, char **password)
561{
562	*username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
563	*domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
564	*password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
565
566	if (*username && **username) {
567
568		if (!*domain || !**domain)
569			*domain = smb_xstrdup(lp_workgroup());
570
571		if (!*password || !**password)
572			*password = smb_xstrdup("");
573
574		DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
575			  *domain, *username));
576
577	} else {
578		DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
579		*username = smb_xstrdup("");
580		*domain = smb_xstrdup("");
581		*password = smb_xstrdup("");
582	}
583}
584
585static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
586				     fstring dcname,
587				     struct sockaddr_storage *dc_ss)
588{
589	struct winbindd_domain *our_domain = NULL;
590	struct rpc_pipe_client *netlogon_pipe = NULL;
591	NTSTATUS result;
592	WERROR werr;
593	TALLOC_CTX *mem_ctx;
594	unsigned int orig_timeout;
595	const char *tmp = NULL;
596	const char *p;
597
598	/* Hmmmm. We can only open one connection to the NETLOGON pipe at the
599	 * moment.... */
600
601	if (IS_DC) {
602		return False;
603	}
604
605	if (domain->primary) {
606		return False;
607	}
608
609	our_domain = find_our_domain();
610
611	if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
612		return False;
613	}
614
615	result = cm_connect_netlogon(our_domain, &netlogon_pipe);
616	if (!NT_STATUS_IS_OK(result)) {
617		talloc_destroy(mem_ctx);
618		return False;
619	}
620
621	/* This call can take a long time - allow the server to time out.
622	   35 seconds should do it. */
623
624	orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
625
626	if (our_domain->active_directory) {
627		struct netr_DsRGetDCNameInfo *domain_info = NULL;
628
629		result = rpccli_netr_DsRGetDCName(netlogon_pipe,
630						  mem_ctx,
631						  our_domain->dcname,
632						  domain->name,
633						  NULL,
634						  NULL,
635						  DS_RETURN_DNS_NAME,
636						  &domain_info,
637						  &werr);
638		if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
639			tmp = talloc_strdup(
640				mem_ctx, domain_info->dc_unc);
641			if (tmp == NULL) {
642				DEBUG(0, ("talloc_strdup failed\n"));
643				talloc_destroy(mem_ctx);
644				return false;
645			}
646			if (strlen(domain->alt_name) == 0) {
647				fstrcpy(domain->alt_name,
648					domain_info->domain_name);
649			}
650			if (strlen(domain->forest_name) == 0) {
651				fstrcpy(domain->forest_name,
652					domain_info->forest_name);
653			}
654		}
655	} else {
656		result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
657						  our_domain->dcname,
658						  domain->name,
659						  &tmp,
660						  &werr);
661	}
662
663	/* And restore our original timeout. */
664	rpccli_set_timeout(netlogon_pipe, orig_timeout);
665
666	if (!NT_STATUS_IS_OK(result)) {
667		DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
668			nt_errstr(result)));
669		talloc_destroy(mem_ctx);
670		return false;
671	}
672
673	if (!W_ERROR_IS_OK(werr)) {
674		DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
675			   win_errstr(werr)));
676		talloc_destroy(mem_ctx);
677		return false;
678	}
679
680	/* rpccli_netr_GetAnyDCName gives us a name with \\ */
681	p = strip_hostname(tmp);
682
683	fstrcpy(dcname, p);
684
685	talloc_destroy(mem_ctx);
686
687	DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
688
689	if (!resolve_name(dcname, dc_ss, 0x20, true)) {
690		return False;
691	}
692
693	return True;
694}
695
696/**
697 * Helper function to assemble trust password and account name
698 */
699static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
700				char **machine_password,
701				char **machine_account,
702				char **machine_krb5_principal)
703{
704	const char *account_name;
705	const char *name = NULL;
706
707	/* If we are a DC and this is not our own domain */
708
709	if (IS_DC) {
710		name = domain->name;
711	} else {
712		struct winbindd_domain *our_domain = find_our_domain();
713
714		if (!our_domain)
715			return NT_STATUS_INVALID_SERVER_STATE;
716
717		name = our_domain->name;
718	}
719
720	if (!get_trust_pw_clear(name, machine_password,
721				&account_name, NULL))
722	{
723		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
724	}
725
726	if ((machine_account != NULL) &&
727	    (asprintf(machine_account, "%s$", account_name) == -1))
728	{
729		return NT_STATUS_NO_MEMORY;
730	}
731
732	/* For now assume our machine account only exists in our domain */
733
734	if (machine_krb5_principal != NULL)
735	{
736		struct winbindd_domain *our_domain = find_our_domain();
737
738		if (!our_domain) {
739			return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
740		}
741
742		if (asprintf(machine_krb5_principal, "%s$@%s",
743			     account_name, our_domain->alt_name) == -1)
744		{
745			return NT_STATUS_NO_MEMORY;
746		}
747
748		strupper_m(*machine_krb5_principal);
749	}
750
751	return NT_STATUS_OK;
752}
753
754/************************************************************************
755 Given a fd with a just-connected TCP connection to a DC, open a connection
756 to the pipe.
757************************************************************************/
758
759static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
760				      const int sockfd,
761				      const char *controller,
762				      struct cli_state **cli,
763				      bool *retry)
764{
765	char *machine_password = NULL;
766	char *machine_krb5_principal = NULL;
767	char *machine_account = NULL;
768	char *ipc_username = NULL;
769	char *ipc_domain = NULL;
770	char *ipc_password = NULL;
771
772	struct named_mutex *mutex;
773
774	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
775
776	struct sockaddr peeraddr;
777	socklen_t peeraddr_len;
778
779	struct sockaddr_in *peeraddr_in =
780		(struct sockaddr_in *)(void *)&peeraddr;
781
782	DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
783		controller, domain->name ));
784
785	*retry = True;
786
787	mutex = grab_named_mutex(talloc_tos(), controller,
788				 WINBIND_SERVER_MUTEX_WAIT_TIME);
789	if (mutex == NULL) {
790		DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
791			 controller));
792		result = NT_STATUS_POSSIBLE_DEADLOCK;
793		goto done;
794	}
795
796	if ((*cli = cli_initialise()) == NULL) {
797		DEBUG(1, ("Could not cli_initialize\n"));
798		result = NT_STATUS_NO_MEMORY;
799		goto done;
800	}
801
802	(*cli)->timeout = 10000; 	/* 10 seconds */
803	(*cli)->fd = sockfd;
804	fstrcpy((*cli)->desthost, controller);
805	(*cli)->use_kerberos = True;
806
807	peeraddr_len = sizeof(peeraddr);
808
809	if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0)) {
810		DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
811			strerror(errno)));
812		result = NT_STATUS_UNSUCCESSFUL;
813		goto done;
814	}
815
816	if ((peeraddr_len != sizeof(struct sockaddr_in))
817#ifdef HAVE_IPV6
818	    && (peeraddr_len != sizeof(struct sockaddr_in6))
819#endif
820	    ) {
821		DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
822			peeraddr_len));
823		result = NT_STATUS_UNSUCCESSFUL;
824		goto done;
825	}
826
827	if ((peeraddr_in->sin_family != PF_INET)
828#ifdef HAVE_IPV6
829	    && (peeraddr_in->sin_family != PF_INET6)
830#endif
831	    ) {
832		DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
833			peeraddr_in->sin_family));
834		result = NT_STATUS_UNSUCCESSFUL;
835		goto done;
836	}
837
838	result = cli_negprot(*cli);
839
840	if (!NT_STATUS_IS_OK(result)) {
841		DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
842		goto done;
843	}
844
845	if (!is_dc_trusted_domain_situation(domain->name) &&
846	    (*cli)->protocol >= PROTOCOL_NT1 &&
847	    (*cli)->capabilities & CAP_EXTENDED_SECURITY)
848	{
849		ADS_STATUS ads_status;
850
851		result = get_trust_creds(domain, &machine_password,
852					 &machine_account,
853					 &machine_krb5_principal);
854		if (!NT_STATUS_IS_OK(result)) {
855			goto anon_fallback;
856		}
857
858		if (lp_security() == SEC_ADS) {
859
860			/* Try a krb5 session */
861
862			(*cli)->use_kerberos = True;
863			DEBUG(5, ("connecting to %s from %s with kerberos principal "
864				  "[%s] and realm [%s]\n", controller, global_myname(),
865				  machine_krb5_principal, domain->alt_name));
866
867			winbindd_set_locator_kdc_envs(domain);
868
869			ads_status = cli_session_setup_spnego(*cli,
870							      machine_krb5_principal,
871							      machine_password,
872							      lp_workgroup(),
873							      domain->alt_name);
874
875			if (!ADS_ERR_OK(ads_status)) {
876				DEBUG(4,("failed kerberos session setup with %s\n",
877					 ads_errstr(ads_status)));
878			}
879
880			result = ads_ntstatus(ads_status);
881			if (NT_STATUS_IS_OK(result)) {
882				/* Ensure creds are stored for NTLMSSP authenticated pipe access. */
883				result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
884				if (!NT_STATUS_IS_OK(result)) {
885					goto done;
886				}
887				goto session_setup_done;
888			}
889		}
890
891		/* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
892		(*cli)->use_kerberos = False;
893
894		DEBUG(5, ("connecting to %s from %s with username "
895			  "[%s]\\[%s]\n",  controller, global_myname(),
896			  lp_workgroup(), machine_account));
897
898		ads_status = cli_session_setup_spnego(*cli,
899						      machine_account,
900						      machine_password,
901						      lp_workgroup(),
902						      NULL);
903		if (!ADS_ERR_OK(ads_status)) {
904			DEBUG(4, ("authenticated session setup failed with %s\n",
905				ads_errstr(ads_status)));
906		}
907
908		result = ads_ntstatus(ads_status);
909		if (NT_STATUS_IS_OK(result)) {
910			/* Ensure creds are stored for NTLMSSP authenticated pipe access. */
911			result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
912			if (!NT_STATUS_IS_OK(result)) {
913				goto done;
914			}
915			goto session_setup_done;
916		}
917	}
918
919	/* Fall back to non-kerberos session setup with auth_user */
920
921	(*cli)->use_kerberos = False;
922
923	cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
924
925	if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
926	    (strlen(ipc_username) > 0)) {
927
928		/* Only try authenticated if we have a username */
929
930		DEBUG(5, ("connecting to %s from %s with username "
931			  "[%s]\\[%s]\n",  controller, global_myname(),
932			  ipc_domain, ipc_username));
933
934		if (NT_STATUS_IS_OK(cli_session_setup(
935					    *cli, ipc_username,
936					    ipc_password, strlen(ipc_password)+1,
937					    ipc_password, strlen(ipc_password)+1,
938					    ipc_domain))) {
939			/* Successful logon with given username. */
940			result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
941			if (!NT_STATUS_IS_OK(result)) {
942				goto done;
943			}
944			goto session_setup_done;
945		} else {
946			DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
947				ipc_domain, ipc_username ));
948		}
949	}
950
951 anon_fallback:
952
953	/* Fall back to anonymous connection, this might fail later */
954	DEBUG(10,("cm_prepare_connection: falling back to anonymous "
955		"connection for DC %s\n",
956		controller ));
957
958	if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
959					      NULL, 0, ""))) {
960		DEBUG(5, ("Connected anonymously\n"));
961		result = cli_init_creds(*cli, "", "", "");
962		if (!NT_STATUS_IS_OK(result)) {
963			goto done;
964		}
965		goto session_setup_done;
966	}
967
968	result = cli_nt_error(*cli);
969
970	if (NT_STATUS_IS_OK(result))
971		result = NT_STATUS_UNSUCCESSFUL;
972
973	/* We can't session setup */
974
975	goto done;
976
977 session_setup_done:
978
979	/* cache the server name for later connections */
980
981	saf_store( domain->name, (*cli)->desthost );
982	if (domain->alt_name && (*cli)->use_kerberos) {
983		saf_store( domain->alt_name, (*cli)->desthost );
984	}
985
986	winbindd_set_locator_kdc_envs(domain);
987
988	result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
989
990	if (!NT_STATUS_IS_OK(result)) {
991		DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
992		goto done;
993	}
994
995	TALLOC_FREE(mutex);
996	*retry = False;
997
998	/* set the domain if empty; needed for schannel connections */
999	if ( !(*cli)->domain[0] ) {
1000		result = cli_set_domain((*cli), domain->name);
1001		if (!NT_STATUS_IS_OK(result)) {
1002			return result;
1003		}
1004	}
1005
1006	result = NT_STATUS_OK;
1007
1008 done:
1009	TALLOC_FREE(mutex);
1010	SAFE_FREE(machine_account);
1011	SAFE_FREE(machine_password);
1012	SAFE_FREE(machine_krb5_principal);
1013	SAFE_FREE(ipc_username);
1014	SAFE_FREE(ipc_domain);
1015	SAFE_FREE(ipc_password);
1016
1017	if (!NT_STATUS_IS_OK(result)) {
1018		winbind_add_failed_connection_entry(domain, controller, result);
1019		if ((*cli) != NULL) {
1020			cli_shutdown(*cli);
1021			*cli = NULL;
1022		}
1023	}
1024
1025	return result;
1026}
1027
1028/*******************************************************************
1029 Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1030 array.
1031
1032 Keeps the list unique by not adding duplicate entries.
1033
1034 @param[in] mem_ctx talloc memory context to allocate from
1035 @param[in] domain_name domain of the DC
1036 @param[in] dcname name of the DC to add to the list
1037 @param[in] pss Internet address and port pair to add to the list
1038 @param[in,out] dcs array of dc_name_ip structures to add to
1039 @param[in,out] num_dcs number of dcs returned in the dcs array
1040 @return true if the list was added to, false otherwise
1041*******************************************************************/
1042
1043static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1044			      const char *dcname, struct sockaddr_storage *pss,
1045			      struct dc_name_ip **dcs, int *num)
1046{
1047	int i = 0;
1048
1049	if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1050		DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1051		return False;
1052	}
1053
1054	/* Make sure there's no duplicates in the list */
1055	for (i=0; i<*num; i++)
1056		if (sockaddr_equal(
1057			    (struct sockaddr *)(void *)&(*dcs)[i].ss,
1058			    (struct sockaddr *)(void *)pss))
1059			return False;
1060
1061	*dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1062
1063	if (*dcs == NULL)
1064		return False;
1065
1066	fstrcpy((*dcs)[*num].name, dcname);
1067	(*dcs)[*num].ss = *pss;
1068	*num += 1;
1069	return True;
1070}
1071
1072static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1073				  struct sockaddr_storage *pss, uint16 port,
1074				  struct sockaddr_storage **addrs, int *num)
1075{
1076	*addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1077
1078	if (*addrs == NULL) {
1079		*num = 0;
1080		return False;
1081	}
1082
1083	(*addrs)[*num] = *pss;
1084	set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1085
1086	*num += 1;
1087	return True;
1088}
1089
1090/*******************************************************************
1091 convert an ip to a name
1092*******************************************************************/
1093
1094static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1095		const struct winbindd_domain *domain,
1096		struct sockaddr_storage *pss,
1097		fstring name )
1098{
1099	struct ip_service ip_list;
1100	uint32_t nt_version = NETLOGON_NT_VERSION_1;
1101
1102	ip_list.ss = *pss;
1103	ip_list.port = 0;
1104
1105#ifdef WITH_ADS
1106	/* For active directory servers, try to get the ldap server name.
1107	   None of these failures should be considered critical for now */
1108
1109	if (lp_security() == SEC_ADS) {
1110		ADS_STRUCT *ads;
1111		ADS_STATUS ads_status;
1112		char addr[INET6_ADDRSTRLEN];
1113
1114		print_sockaddr(addr, sizeof(addr), pss);
1115
1116		ads = ads_init(domain->alt_name, domain->name, addr);
1117		ads->auth.flags |= ADS_AUTH_NO_BIND;
1118
1119		ads_status = ads_connect(ads);
1120		if (ADS_ERR_OK(ads_status)) {
1121			/* We got a cldap packet. */
1122			fstrcpy(name, ads->config.ldap_server_name);
1123			namecache_store(name, 0x20, 1, &ip_list);
1124
1125			DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1126
1127			if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1128				if (ads_closest_dc(ads)) {
1129					char *sitename = sitename_fetch(ads->config.realm);
1130
1131					/* We're going to use this KDC for this realm/domain.
1132					   If we are using sites, then force the krb5 libs
1133					   to use this KDC. */
1134
1135					create_local_private_krb5_conf_for_domain(domain->alt_name,
1136									domain->name,
1137									sitename,
1138									pss,
1139									name);
1140
1141					SAFE_FREE(sitename);
1142				} else {
1143					/* use an off site KDC */
1144					create_local_private_krb5_conf_for_domain(domain->alt_name,
1145									domain->name,
1146									NULL,
1147									pss,
1148									name);
1149				}
1150				winbindd_set_locator_kdc_envs(domain);
1151
1152				/* Ensure we contact this DC also. */
1153				saf_store( domain->name, name);
1154				saf_store( domain->alt_name, name);
1155			}
1156
1157			ads_destroy( &ads );
1158			return True;
1159		}
1160
1161		ads_destroy( &ads );
1162	}
1163#endif
1164
1165	/* try GETDC requests next */
1166
1167	if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1168			       pss, domain->name, &domain->sid,
1169			       nt_version)) {
1170		const char *dc_name = NULL;
1171		int i;
1172		smb_msleep(100);
1173		for (i=0; i<5; i++) {
1174			if (receive_getdc_response(mem_ctx, pss, domain->name,
1175						   &nt_version,
1176						   &dc_name, NULL)) {
1177				fstrcpy(name, dc_name);
1178				namecache_store(name, 0x20, 1, &ip_list);
1179				return True;
1180			}
1181			smb_msleep(500);
1182		}
1183	}
1184
1185	/* try node status request */
1186
1187	if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1188		namecache_store(name, 0x20, 1, &ip_list);
1189		return True;
1190	}
1191	return False;
1192}
1193
1194/*******************************************************************
1195 Retrieve a list of IP addresses for domain controllers.
1196
1197 The array is sorted in the preferred connection order.
1198
1199 @param[in] mem_ctx talloc memory context to allocate from
1200 @param[in] domain domain to retrieve DCs for
1201 @param[out] dcs array of dcs that will be returned
1202 @param[out] num_dcs number of dcs returned in the dcs array
1203 @return always true
1204*******************************************************************/
1205
1206static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1207		    struct dc_name_ip **dcs, int *num_dcs)
1208{
1209	fstring dcname;
1210	struct  sockaddr_storage ss;
1211	struct  ip_service *ip_list = NULL;
1212	int     iplist_size = 0;
1213	int     i;
1214	bool    is_our_domain;
1215	enum security_types sec = (enum security_types)lp_security();
1216
1217	is_our_domain = strequal(domain->name, lp_workgroup());
1218
1219	/* If not our domain, get the preferred DC, by asking our primary DC */
1220	if ( !is_our_domain
1221		&& get_dc_name_via_netlogon(domain, dcname, &ss)
1222		&& add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1223		       num_dcs) )
1224	{
1225		char addr[INET6_ADDRSTRLEN];
1226		print_sockaddr(addr, sizeof(addr), &ss);
1227		DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1228			   dcname, addr));
1229		return True;
1230	}
1231
1232	if (sec == SEC_ADS) {
1233		char *sitename = NULL;
1234
1235		/* We need to make sure we know the local site before
1236		   doing any DNS queries, as this will restrict the
1237		   get_sorted_dc_list() call below to only fetching
1238		   DNS records for the correct site. */
1239
1240		/* Find any DC to get the site record.
1241		   We deliberately don't care about the
1242		   return here. */
1243
1244		get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1245
1246		sitename = sitename_fetch(domain->alt_name);
1247		if (sitename) {
1248
1249			/* Do the site-specific AD dns lookup first. */
1250			get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1251			       &iplist_size, True);
1252
1253			/* Add ips to the DC array.  We don't look up the name
1254			   of the DC in this function, but we fill in the char*
1255			   of the ip now to make the failed connection cache
1256			   work */
1257			for ( i=0; i<iplist_size; i++ ) {
1258				char addr[INET6_ADDRSTRLEN];
1259				print_sockaddr(addr, sizeof(addr),
1260						&ip_list[i].ss);
1261				add_one_dc_unique(mem_ctx,
1262						domain->name,
1263						addr,
1264						&ip_list[i].ss,
1265						dcs,
1266						num_dcs);
1267			}
1268
1269			SAFE_FREE(ip_list);
1270			SAFE_FREE(sitename);
1271			iplist_size = 0;
1272		}
1273
1274		/* Now we add DCs from the main AD DNS lookup. */
1275		get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1276			&iplist_size, True);
1277
1278		for ( i=0; i<iplist_size; i++ ) {
1279			char addr[INET6_ADDRSTRLEN];
1280			print_sockaddr(addr, sizeof(addr),
1281					&ip_list[i].ss);
1282			add_one_dc_unique(mem_ctx,
1283					domain->name,
1284					addr,
1285					&ip_list[i].ss,
1286					dcs,
1287					num_dcs);
1288		}
1289
1290		SAFE_FREE(ip_list);
1291		iplist_size = 0;
1292        }
1293
1294	/* Try standard netbios queries if no ADS */
1295	if (*num_dcs == 0) {
1296		get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1297		       False);
1298
1299		for ( i=0; i<iplist_size; i++ ) {
1300			char addr[INET6_ADDRSTRLEN];
1301			print_sockaddr(addr, sizeof(addr),
1302					&ip_list[i].ss);
1303			add_one_dc_unique(mem_ctx,
1304					domain->name,
1305					addr,
1306					&ip_list[i].ss,
1307					dcs,
1308					num_dcs);
1309		}
1310
1311		SAFE_FREE(ip_list);
1312		iplist_size = 0;
1313	}
1314
1315	return True;
1316}
1317
1318/*******************************************************************
1319 Find and make a connection to a DC in the given domain.
1320
1321 @param[in] mem_ctx talloc memory context to allocate from
1322 @param[in] domain domain to find a dc in
1323 @param[out] dcname NetBIOS or FQDN of DC that's connected to
1324 @param[out] pss DC Internet address and port
1325 @param[out] fd fd of the open socket connected to the newly found dc
1326 @return true when a DC connection is made, false otherwise
1327*******************************************************************/
1328
1329static bool find_new_dc(TALLOC_CTX *mem_ctx,
1330			struct winbindd_domain *domain,
1331			fstring dcname, struct sockaddr_storage *pss, int *fd)
1332{
1333	struct dc_name_ip *dcs = NULL;
1334	int num_dcs = 0;
1335
1336	const char **dcnames = NULL;
1337	int num_dcnames = 0;
1338
1339	struct sockaddr_storage *addrs = NULL;
1340	int num_addrs = 0;
1341
1342	int i;
1343	size_t fd_index;
1344
1345	NTSTATUS status;
1346
1347	*fd = -1;
1348
1349 again:
1350	if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1351		return False;
1352
1353	for (i=0; i<num_dcs; i++) {
1354
1355		if (!add_string_to_array(mem_ctx, dcs[i].name,
1356				    &dcnames, &num_dcnames)) {
1357			return False;
1358		}
1359		if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1360				      &addrs, &num_addrs)) {
1361			return False;
1362		}
1363	}
1364
1365	if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1366		return False;
1367
1368	if ((addrs == NULL) || (dcnames == NULL))
1369		return False;
1370
1371	status = smbsock_any_connect(addrs, dcnames, num_addrs,
1372				     fd, &fd_index, NULL);
1373	if (!NT_STATUS_IS_OK(status)) {
1374		for (i=0; i<num_dcs; i++) {
1375			char ab[INET6_ADDRSTRLEN];
1376			print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1377			DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1378				"domain %s address %s. Error was %s\n",
1379				   domain->name, ab, nt_errstr(status) ));
1380			winbind_add_failed_connection_entry(domain,
1381				dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1382		}
1383		return False;
1384	}
1385
1386	*pss = addrs[fd_index];
1387
1388	if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1389		/* Ok, we've got a name for the DC */
1390		fstrcpy(dcname, dcnames[fd_index]);
1391		return True;
1392	}
1393
1394	/* Try to figure out the name */
1395	if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1396		return True;
1397	}
1398
1399	/* We can not continue without the DC's name */
1400	winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1401				    NT_STATUS_UNSUCCESSFUL);
1402
1403	/* Throw away all arrays as we're doing this again. */
1404	TALLOC_FREE(dcs);
1405	num_dcs = 0;
1406
1407	TALLOC_FREE(dcnames);
1408	num_dcnames = 0;
1409
1410	TALLOC_FREE(addrs);
1411	num_addrs = 0;
1412
1413	close(*fd);
1414	*fd = -1;
1415
1416	goto again;
1417}
1418
1419static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1420				   struct winbindd_cm_conn *new_conn)
1421{
1422	TALLOC_CTX *mem_ctx;
1423	NTSTATUS result;
1424	char *saf_servername = saf_fetch( domain->name );
1425	int retries;
1426
1427	if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1428		SAFE_FREE(saf_servername);
1429		set_domain_offline(domain);
1430		return NT_STATUS_NO_MEMORY;
1431	}
1432
1433	/* we have to check the server affinity cache here since
1434	   later we selecte a DC based on response time and not preference */
1435
1436	/* Check the negative connection cache
1437	   before talking to it. It going down may have
1438	   triggered the reconnection. */
1439
1440	if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1441
1442		DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1443			saf_servername, domain->name ));
1444
1445		/* convert an ip address to a name */
1446		if (is_ipaddress( saf_servername ) ) {
1447			fstring saf_name;
1448			struct sockaddr_storage ss;
1449
1450			if (!interpret_string_addr(&ss, saf_servername,
1451						AI_NUMERICHOST)) {
1452				return NT_STATUS_UNSUCCESSFUL;
1453			}
1454			if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1455				fstrcpy( domain->dcname, saf_name );
1456			} else {
1457				winbind_add_failed_connection_entry(
1458					domain, saf_servername,
1459					NT_STATUS_UNSUCCESSFUL);
1460			}
1461		} else {
1462			fstrcpy( domain->dcname, saf_servername );
1463		}
1464
1465		SAFE_FREE( saf_servername );
1466	}
1467
1468	for (retries = 0; retries < 3; retries++) {
1469		int fd = -1;
1470		bool retry = False;
1471
1472		result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1473
1474		DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1475			domain->dcname, domain->name ));
1476
1477		if (*domain->dcname
1478			&& NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1479			&& (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1480		{
1481			NTSTATUS status;
1482
1483			status = smbsock_connect(&domain->dcaddr, NULL, NULL,
1484						 &fd, NULL);
1485			if (!NT_STATUS_IS_OK(status)) {
1486				fd = -1;
1487			}
1488		}
1489
1490		if ((fd == -1)
1491			&& !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1492		{
1493			/* This is the one place where we will
1494			   set the global winbindd offline state
1495			   to true, if a "WINBINDD_OFFLINE" entry
1496			   is found in the winbindd cache. */
1497			set_global_winbindd_state_offline();
1498			break;
1499		}
1500
1501		new_conn->cli = NULL;
1502
1503		result = cm_prepare_connection(domain, fd, domain->dcname,
1504			&new_conn->cli, &retry);
1505
1506		if (!retry)
1507			break;
1508	}
1509
1510	if (NT_STATUS_IS_OK(result)) {
1511
1512		winbindd_set_locator_kdc_envs(domain);
1513
1514		if (domain->online == False) {
1515			/* We're changing state from offline to online. */
1516			set_global_winbindd_state_online();
1517		}
1518		set_domain_online(domain);
1519	} else {
1520		/* Ensure we setup the retry handler. */
1521		set_domain_offline(domain);
1522	}
1523
1524	talloc_destroy(mem_ctx);
1525	return result;
1526}
1527
1528/* Close down all open pipes on a connection. */
1529
1530void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1531{
1532	/* We're closing down a possibly dead
1533	   connection. Don't have impossibly long (10s) timeouts. */
1534
1535	if (conn->cli) {
1536		cli_set_timeout(conn->cli, 1000); /* 1 second. */
1537	}
1538
1539	if (conn->samr_pipe != NULL) {
1540		TALLOC_FREE(conn->samr_pipe);
1541		/* Ok, it must be dead. Drop timeout to 0.5 sec. */
1542		if (conn->cli) {
1543			cli_set_timeout(conn->cli, 500);
1544		}
1545	}
1546
1547	if (conn->lsa_pipe != NULL) {
1548		TALLOC_FREE(conn->lsa_pipe);
1549		/* Ok, it must be dead. Drop timeout to 0.5 sec. */
1550		if (conn->cli) {
1551			cli_set_timeout(conn->cli, 500);
1552		}
1553	}
1554
1555	if (conn->lsa_pipe_tcp != NULL) {
1556		TALLOC_FREE(conn->lsa_pipe_tcp);
1557		/* Ok, it must be dead. Drop timeout to 0.5 sec. */
1558		if (conn->cli) {
1559			cli_set_timeout(conn->cli, 500);
1560		}
1561	}
1562
1563	if (conn->netlogon_pipe != NULL) {
1564		TALLOC_FREE(conn->netlogon_pipe);
1565		/* Ok, it must be dead. Drop timeout to 0.5 sec. */
1566		if (conn->cli) {
1567			cli_set_timeout(conn->cli, 500);
1568		}
1569	}
1570
1571	if (conn->cli) {
1572		cli_shutdown(conn->cli);
1573	}
1574
1575	conn->cli = NULL;
1576}
1577
1578void close_conns_after_fork(void)
1579{
1580	struct winbindd_domain *domain;
1581
1582	for (domain = domain_list(); domain; domain = domain->next) {
1583		if (domain->conn.cli == NULL)
1584			continue;
1585
1586		if (domain->conn.cli->fd == -1)
1587			continue;
1588
1589		close(domain->conn.cli->fd);
1590		domain->conn.cli->fd = -1;
1591	}
1592}
1593
1594static bool connection_ok(struct winbindd_domain *domain)
1595{
1596	bool ok;
1597
1598	ok = cli_state_is_connected(domain->conn.cli);
1599	if (!ok) {
1600		DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1601			  domain->dcname, domain->name));
1602		return False;
1603	}
1604
1605	if (domain->online == False) {
1606		DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1607		return False;
1608	}
1609
1610	return True;
1611}
1612
1613/* Initialize a new connection up to the RPC BIND.
1614   Bypass online status check so always does network calls. */
1615
1616static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1617{
1618	NTSTATUS result;
1619
1620	/* Internal connections never use the network. */
1621	if (domain->internal) {
1622		domain->initialized = True;
1623		return NT_STATUS_OK;
1624	}
1625
1626	if (!winbindd_can_contact_domain(domain)) {
1627		invalidate_cm_connection(&domain->conn);
1628		domain->initialized = True;
1629		return NT_STATUS_OK;
1630	}
1631
1632	if (connection_ok(domain)) {
1633		if (!domain->initialized) {
1634			set_dc_type_and_flags(domain);
1635		}
1636		return NT_STATUS_OK;
1637	}
1638
1639	invalidate_cm_connection(&domain->conn);
1640
1641	result = cm_open_connection(domain, &domain->conn);
1642
1643	if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1644		set_dc_type_and_flags(domain);
1645	}
1646
1647	return result;
1648}
1649
1650NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1651{
1652	if (domain->initialized && !domain->online) {
1653		/* We check for online status elsewhere. */
1654		return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1655	}
1656
1657	return init_dc_connection_network(domain);
1658}
1659
1660static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1661{
1662	NTSTATUS status;
1663
1664	status = init_dc_connection(domain);
1665	if (!NT_STATUS_IS_OK(status)) {
1666		return status;
1667	}
1668
1669	if (!domain->internal && domain->conn.cli == NULL) {
1670		/* happens for trusted domains without inbound trust */
1671		return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1672	}
1673
1674	return NT_STATUS_OK;
1675}
1676
1677/******************************************************************************
1678 Set the trust flags (direction and forest location) for a domain
1679******************************************************************************/
1680
1681static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1682{
1683	struct winbindd_domain *our_domain;
1684	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1685	struct netr_DomainTrustList trusts;
1686	int i;
1687	uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1688			NETR_TRUST_FLAG_OUTBOUND |
1689			NETR_TRUST_FLAG_INBOUND);
1690	struct rpc_pipe_client *cli;
1691	TALLOC_CTX *mem_ctx = NULL;
1692
1693	DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1694
1695	/* Our primary domain doesn't need to worry about trust flags.
1696	   Force it to go through the network setup */
1697	if ( domain->primary ) {
1698		return False;
1699	}
1700
1701	our_domain = find_our_domain();
1702
1703	if ( !connection_ok(our_domain) ) {
1704		DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1705		return False;
1706	}
1707
1708	/* This won't work unless our domain is AD */
1709
1710	if ( !our_domain->active_directory ) {
1711		return False;
1712	}
1713
1714	/* Use DsEnumerateDomainTrusts to get us the trust direction
1715	   and type */
1716
1717	result = cm_connect_netlogon(our_domain, &cli);
1718
1719	if (!NT_STATUS_IS_OK(result)) {
1720		DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1721			  "a connection to %s for PIPE_NETLOGON (%s)\n",
1722			  domain->name, nt_errstr(result)));
1723		return False;
1724	}
1725
1726	if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1727		DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1728		return False;
1729	}
1730
1731	result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1732						      cli->desthost,
1733						      flags,
1734						      &trusts,
1735						      NULL);
1736	if (!NT_STATUS_IS_OK(result)) {
1737		DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1738			"failed to query trusted domain list: %s\n",
1739			nt_errstr(result)));
1740		talloc_destroy(mem_ctx);
1741		return false;
1742	}
1743
1744	/* Now find the domain name and get the flags */
1745
1746	for ( i=0; i<trusts.count; i++ ) {
1747		if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1748			domain->domain_flags          = trusts.array[i].trust_flags;
1749			domain->domain_type           = trusts.array[i].trust_type;
1750			domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
1751
1752			if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1753				domain->active_directory = True;
1754
1755			/* This flag is only set if the domain is *our*
1756			   primary domain and the primary domain is in
1757			   native mode */
1758
1759			domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1760
1761			DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1762				  "native mode.\n", domain->name,
1763				  domain->native_mode ? "" : "NOT "));
1764
1765			DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1766				 "running active directory.\n", domain->name,
1767				 domain->active_directory ? "" : "NOT "));
1768
1769
1770			domain->initialized = True;
1771
1772			break;
1773		}
1774	}
1775
1776	talloc_destroy( mem_ctx );
1777
1778	return domain->initialized;
1779}
1780
1781/******************************************************************************
1782 We can 'sense' certain things about the DC by it's replies to certain
1783 questions.
1784
1785 This tells us if this particular remote server is Active Directory, and if it
1786 is native mode.
1787******************************************************************************/
1788
1789static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1790{
1791	NTSTATUS 		result;
1792	WERROR werr;
1793	TALLOC_CTX              *mem_ctx = NULL;
1794	struct rpc_pipe_client  *cli = NULL;
1795	struct policy_handle pol;
1796	union dssetup_DsRoleInfo info;
1797	union lsa_PolicyInformation *lsa_info = NULL;
1798
1799	if (!connection_ok(domain)) {
1800		return;
1801	}
1802
1803	mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1804			      domain->name);
1805	if (!mem_ctx) {
1806		DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1807		return;
1808	}
1809
1810	DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1811
1812	result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1813					  &ndr_table_dssetup.syntax_id,
1814					  &cli);
1815
1816	if (!NT_STATUS_IS_OK(result)) {
1817		DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1818			  "PI_DSSETUP on domain %s: (%s)\n",
1819			  domain->name, nt_errstr(result)));
1820
1821		/* if this is just a non-AD domain we need to continue
1822		 * identifying so that we can in the end return with
1823		 * domain->initialized = True - gd */
1824
1825		goto no_dssetup;
1826	}
1827
1828	result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1829								  DS_ROLE_BASIC_INFORMATION,
1830								  &info,
1831								  &werr);
1832	TALLOC_FREE(cli);
1833
1834	if (!NT_STATUS_IS_OK(result)) {
1835		DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1836			  "on domain %s failed: (%s)\n",
1837			  domain->name, nt_errstr(result)));
1838
1839		/* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1840		 * every opcode on the DSSETUP pipe, continue with
1841		 * no_dssetup mode here as well to get domain->initialized
1842		 * set - gd */
1843
1844		if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1845			goto no_dssetup;
1846		}
1847
1848		TALLOC_FREE(mem_ctx);
1849		return;
1850	}
1851
1852	if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1853	    !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1854		domain->native_mode = True;
1855	} else {
1856		domain->native_mode = False;
1857	}
1858
1859no_dssetup:
1860	result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1861					  &ndr_table_lsarpc.syntax_id, &cli);
1862
1863	if (!NT_STATUS_IS_OK(result)) {
1864		DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1865			  "PI_LSARPC on domain %s: (%s)\n",
1866			  domain->name, nt_errstr(result)));
1867		TALLOC_FREE(cli);
1868		TALLOC_FREE(mem_ctx);
1869		return;
1870	}
1871
1872	result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1873					 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
1874
1875	if (NT_STATUS_IS_OK(result)) {
1876		/* This particular query is exactly what Win2k clients use
1877		   to determine that the DC is active directory */
1878		result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1879						     &pol,
1880						     LSA_POLICY_INFO_DNS,
1881						     &lsa_info);
1882	}
1883
1884	if (NT_STATUS_IS_OK(result)) {
1885		domain->active_directory = True;
1886
1887		if (lsa_info->dns.name.string) {
1888			fstrcpy(domain->name, lsa_info->dns.name.string);
1889		}
1890
1891		if (lsa_info->dns.dns_domain.string) {
1892			fstrcpy(domain->alt_name,
1893				lsa_info->dns.dns_domain.string);
1894		}
1895
1896		/* See if we can set some domain trust flags about
1897		   ourself */
1898
1899		if (lsa_info->dns.dns_forest.string) {
1900			fstrcpy(domain->forest_name,
1901				lsa_info->dns.dns_forest.string);
1902
1903			if (strequal(domain->forest_name, domain->alt_name)) {
1904				domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1905			}
1906		}
1907
1908		if (lsa_info->dns.sid) {
1909			sid_copy(&domain->sid, lsa_info->dns.sid);
1910		}
1911	} else {
1912		domain->active_directory = False;
1913
1914		result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1915						SEC_FLAG_MAXIMUM_ALLOWED,
1916						&pol);
1917
1918		if (!NT_STATUS_IS_OK(result)) {
1919			goto done;
1920		}
1921
1922		result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1923						    &pol,
1924						    LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1925						    &lsa_info);
1926
1927		if (NT_STATUS_IS_OK(result)) {
1928
1929			if (lsa_info->account_domain.name.string) {
1930				fstrcpy(domain->name,
1931					lsa_info->account_domain.name.string);
1932			}
1933
1934			if (lsa_info->account_domain.sid) {
1935				sid_copy(&domain->sid, lsa_info->account_domain.sid);
1936			}
1937		}
1938	}
1939done:
1940
1941	DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1942		  domain->name, domain->native_mode ? "" : "NOT "));
1943
1944	DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1945		  domain->name, domain->active_directory ? "" : "NOT "));
1946
1947	domain->can_do_ncacn_ip_tcp = domain->active_directory;
1948	domain->can_do_validation6 = domain->active_directory;
1949
1950	TALLOC_FREE(cli);
1951
1952	TALLOC_FREE(mem_ctx);
1953
1954	domain->initialized = True;
1955}
1956
1957/**********************************************************************
1958 Set the domain_flags (trust attributes, domain operating modes, etc...
1959***********************************************************************/
1960
1961static void set_dc_type_and_flags( struct winbindd_domain *domain )
1962{
1963	/* we always have to contact our primary domain */
1964
1965	if ( domain->primary ) {
1966		DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1967			  "primary domain\n"));
1968		set_dc_type_and_flags_connect( domain );
1969		return;
1970	}
1971
1972	/* Use our DC to get the information if possible */
1973
1974	if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1975		/* Otherwise, fallback to contacting the
1976		   domain directly */
1977		set_dc_type_and_flags_connect( domain );
1978	}
1979
1980	return;
1981}
1982
1983
1984
1985/**********************************************************************
1986***********************************************************************/
1987
1988static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
1989				   struct netlogon_creds_CredentialState **ppdc)
1990{
1991	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1992	struct rpc_pipe_client *netlogon_pipe;
1993
1994	if (lp_client_schannel() == False) {
1995		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;;
1996	}
1997
1998	result = cm_connect_netlogon(domain, &netlogon_pipe);
1999	if (!NT_STATUS_IS_OK(result)) {
2000		return result;
2001	}
2002
2003	/* Return a pointer to the struct netlogon_creds_CredentialState from the
2004	   netlogon pipe. */
2005
2006	if (!domain->conn.netlogon_pipe->dc) {
2007		return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2008	}
2009
2010	*ppdc = domain->conn.netlogon_pipe->dc;
2011	return NT_STATUS_OK;
2012}
2013
2014NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2015			struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2016{
2017	struct winbindd_cm_conn *conn;
2018	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2019	struct netlogon_creds_CredentialState *p_creds;
2020	char *machine_password = NULL;
2021	char *machine_account = NULL;
2022	char *domain_name = NULL;
2023
2024	result = init_dc_connection_rpc(domain);
2025	if (!NT_STATUS_IS_OK(result)) {
2026		return result;
2027	}
2028
2029	conn = &domain->conn;
2030
2031	if (rpccli_is_connected(conn->samr_pipe)) {
2032		goto done;
2033	}
2034
2035	TALLOC_FREE(conn->samr_pipe);
2036
2037	/*
2038	 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2039	 * sign and sealed pipe using the machine account password by
2040	 * preference. If we can't - try schannel, if that fails, try
2041	 * anonymous.
2042	 */
2043
2044	if ((conn->cli->user_name[0] == '\0') ||
2045	    (conn->cli->domain[0] == '\0') ||
2046	    (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2047	{
2048		result = get_trust_creds(domain, &machine_password,
2049					 &machine_account, NULL);
2050		if (!NT_STATUS_IS_OK(result)) {
2051			DEBUG(10, ("cm_connect_sam: No no user available for "
2052				   "domain %s, trying schannel\n", conn->cli->domain));
2053			goto schannel;
2054		}
2055		domain_name = domain->name;
2056	} else {
2057		machine_password = SMB_STRDUP(conn->cli->password);
2058		machine_account = SMB_STRDUP(conn->cli->user_name);
2059		domain_name = conn->cli->domain;
2060	}
2061
2062	if (!machine_password || !machine_account) {
2063		result = NT_STATUS_NO_MEMORY;
2064		goto done;
2065	}
2066
2067	/* We have an authenticated connection. Use a NTLMSSP SPNEGO
2068	   authenticated SAMR pipe with sign & seal. */
2069	result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2070						  &ndr_table_samr.syntax_id,
2071						  NCACN_NP,
2072						  DCERPC_AUTH_LEVEL_PRIVACY,
2073						  domain_name,
2074						  machine_account,
2075						  machine_password,
2076						  &conn->samr_pipe);
2077
2078	if (!NT_STATUS_IS_OK(result)) {
2079		DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2080			  "pipe for domain %s using NTLMSSP "
2081			  "authenticated pipe: user %s\\%s. Error was "
2082			  "%s\n", domain->name, domain_name,
2083			  machine_account, nt_errstr(result)));
2084		goto schannel;
2085	}
2086
2087	DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2088		  "domain %s using NTLMSSP authenticated "
2089		  "pipe: user %s\\%s\n", domain->name,
2090		  domain_name, machine_account));
2091
2092	result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2093				      conn->samr_pipe->desthost,
2094				      SEC_FLAG_MAXIMUM_ALLOWED,
2095				      &conn->sam_connect_handle);
2096	if (NT_STATUS_IS_OK(result)) {
2097		goto open_domain;
2098	}
2099	DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2100		  "failed for domain %s, error was %s. Trying schannel\n",
2101		  domain->name, nt_errstr(result) ));
2102	TALLOC_FREE(conn->samr_pipe);
2103
2104 schannel:
2105
2106	/* Fall back to schannel if it's a W2K pre-SP1 box. */
2107
2108	result = cm_get_schannel_creds(domain, &p_creds);
2109	if (!NT_STATUS_IS_OK(result)) {
2110		/* If this call fails - conn->cli can now be NULL ! */
2111		DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2112			   "for domain %s (error %s), trying anon\n",
2113			domain->name,
2114			nt_errstr(result) ));
2115		goto anonymous;
2116	}
2117	result = cli_rpc_pipe_open_schannel_with_key
2118		(conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2119		 DCERPC_AUTH_LEVEL_PRIVACY,
2120		 domain->name, &p_creds, &conn->samr_pipe);
2121
2122	if (!NT_STATUS_IS_OK(result)) {
2123		DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2124			  "domain %s using schannel. Error was %s\n",
2125			  domain->name, nt_errstr(result) ));
2126		goto anonymous;
2127	}
2128	DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2129		  "schannel.\n", domain->name ));
2130
2131	result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2132				      conn->samr_pipe->desthost,
2133				      SEC_FLAG_MAXIMUM_ALLOWED,
2134				      &conn->sam_connect_handle);
2135	if (NT_STATUS_IS_OK(result)) {
2136		goto open_domain;
2137	}
2138	DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2139		  "for domain %s, error was %s. Trying anonymous\n",
2140		  domain->name, nt_errstr(result) ));
2141	TALLOC_FREE(conn->samr_pipe);
2142
2143 anonymous:
2144
2145	/* Finally fall back to anonymous. */
2146	result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2147					  &conn->samr_pipe);
2148
2149	if (!NT_STATUS_IS_OK(result)) {
2150		goto done;
2151	}
2152
2153	result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2154				      conn->samr_pipe->desthost,
2155				      SEC_FLAG_MAXIMUM_ALLOWED,
2156				      &conn->sam_connect_handle);
2157	if (!NT_STATUS_IS_OK(result)) {
2158		DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2159			  "for domain %s Error was %s\n",
2160			  domain->name, nt_errstr(result) ));
2161		goto done;
2162	}
2163
2164 open_domain:
2165	result = rpccli_samr_OpenDomain(conn->samr_pipe,
2166					mem_ctx,
2167					&conn->sam_connect_handle,
2168					SEC_FLAG_MAXIMUM_ALLOWED,
2169					&domain->sid,
2170					&conn->sam_domain_handle);
2171
2172 done:
2173
2174	if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
2175		/*
2176		 * if we got access denied, we might just have no access rights
2177		 * to talk to the remote samr server server (e.g. when we are a
2178		 * PDC and we are connecting a w2k8 pdc via an interdomain
2179		 * trust). In that case do not invalidate the whole connection
2180		 * stack
2181		 */
2182		TALLOC_FREE(conn->samr_pipe);
2183		ZERO_STRUCT(conn->sam_domain_handle);
2184		return result;
2185	} else if (!NT_STATUS_IS_OK(result)) {
2186		invalidate_cm_connection(conn);
2187		return result;
2188	}
2189
2190	*cli = conn->samr_pipe;
2191	*sam_handle = conn->sam_domain_handle;
2192	SAFE_FREE(machine_password);
2193	SAFE_FREE(machine_account);
2194	return result;
2195}
2196
2197/**********************************************************************
2198 open an schanneld ncacn_ip_tcp connection to LSA
2199***********************************************************************/
2200
2201NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2202			    TALLOC_CTX *mem_ctx,
2203			    struct rpc_pipe_client **cli)
2204{
2205	struct winbindd_cm_conn *conn;
2206	struct netlogon_creds_CredentialState *creds;
2207	NTSTATUS status;
2208
2209	DEBUG(10,("cm_connect_lsa_tcp\n"));
2210
2211	status = init_dc_connection_rpc(domain);
2212	if (!NT_STATUS_IS_OK(status)) {
2213		return status;
2214	}
2215
2216	conn = &domain->conn;
2217
2218	if (conn->lsa_pipe_tcp &&
2219	    conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2220	    conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2221	    rpccli_is_connected(conn->lsa_pipe_tcp)) {
2222		goto done;
2223	}
2224
2225	TALLOC_FREE(conn->lsa_pipe_tcp);
2226
2227	status = cm_get_schannel_creds(domain, &creds);
2228	if (!NT_STATUS_IS_OK(status)) {
2229		goto done;
2230	}
2231
2232	status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2233						     &ndr_table_lsarpc.syntax_id,
2234						     NCACN_IP_TCP,
2235						     DCERPC_AUTH_LEVEL_PRIVACY,
2236						     domain->name,
2237						     &creds,
2238						     &conn->lsa_pipe_tcp);
2239	if (!NT_STATUS_IS_OK(status)) {
2240		DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2241			nt_errstr(status)));
2242		goto done;
2243	}
2244
2245 done:
2246	if (!NT_STATUS_IS_OK(status)) {
2247		TALLOC_FREE(conn->lsa_pipe_tcp);
2248		return status;
2249	}
2250
2251	*cli = conn->lsa_pipe_tcp;
2252
2253	return status;
2254}
2255
2256NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2257			struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2258{
2259	struct winbindd_cm_conn *conn;
2260	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2261	struct netlogon_creds_CredentialState *p_creds;
2262
2263	result = init_dc_connection_rpc(domain);
2264	if (!NT_STATUS_IS_OK(result))
2265		return result;
2266
2267	conn = &domain->conn;
2268
2269	if (rpccli_is_connected(conn->lsa_pipe)) {
2270		goto done;
2271	}
2272
2273	TALLOC_FREE(conn->lsa_pipe);
2274
2275	if ((conn->cli->user_name[0] == '\0') ||
2276	    (conn->cli->domain[0] == '\0') ||
2277	    (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2278		DEBUG(10, ("cm_connect_lsa: No no user available for "
2279			   "domain %s, trying schannel\n", conn->cli->domain));
2280		goto schannel;
2281	}
2282
2283	/* We have an authenticated connection. Use a NTLMSSP SPNEGO
2284	 * authenticated LSA pipe with sign & seal. */
2285	result = cli_rpc_pipe_open_spnego_ntlmssp
2286		(conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2287		 DCERPC_AUTH_LEVEL_PRIVACY,
2288		 conn->cli->domain, conn->cli->user_name, conn->cli->password,
2289		 &conn->lsa_pipe);
2290
2291	if (!NT_STATUS_IS_OK(result)) {
2292		DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2293			  "domain %s using NTLMSSP authenticated pipe: user "
2294			  "%s\\%s. Error was %s. Trying schannel.\n",
2295			  domain->name, conn->cli->domain,
2296			  conn->cli->user_name, nt_errstr(result)));
2297		goto schannel;
2298	}
2299
2300	DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2301		  "NTLMSSP authenticated pipe: user %s\\%s\n",
2302		  domain->name, conn->cli->domain, conn->cli->user_name ));
2303
2304	result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2305					SEC_FLAG_MAXIMUM_ALLOWED,
2306					&conn->lsa_policy);
2307	if (NT_STATUS_IS_OK(result)) {
2308		goto done;
2309	}
2310
2311	DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2312		  "schannel\n"));
2313
2314	TALLOC_FREE(conn->lsa_pipe);
2315
2316 schannel:
2317
2318	/* Fall back to schannel if it's a W2K pre-SP1 box. */
2319
2320	result = cm_get_schannel_creds(domain, &p_creds);
2321	if (!NT_STATUS_IS_OK(result)) {
2322		/* If this call fails - conn->cli can now be NULL ! */
2323		DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2324			   "for domain %s (error %s), trying anon\n",
2325			domain->name,
2326			nt_errstr(result) ));
2327		goto anonymous;
2328	}
2329	result = cli_rpc_pipe_open_schannel_with_key
2330		(conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2331		 DCERPC_AUTH_LEVEL_PRIVACY,
2332		 domain->name, &p_creds, &conn->lsa_pipe);
2333
2334	if (!NT_STATUS_IS_OK(result)) {
2335		DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2336			  "domain %s using schannel. Error was %s\n",
2337			  domain->name, nt_errstr(result) ));
2338		goto anonymous;
2339	}
2340	DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2341		  "schannel.\n", domain->name ));
2342
2343	result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2344					SEC_FLAG_MAXIMUM_ALLOWED,
2345					&conn->lsa_policy);
2346	if (NT_STATUS_IS_OK(result)) {
2347		goto done;
2348	}
2349
2350	DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2351		  "anonymous\n"));
2352
2353	TALLOC_FREE(conn->lsa_pipe);
2354
2355 anonymous:
2356
2357	result = cli_rpc_pipe_open_noauth(conn->cli,
2358					  &ndr_table_lsarpc.syntax_id,
2359					  &conn->lsa_pipe);
2360	if (!NT_STATUS_IS_OK(result)) {
2361		result = NT_STATUS_PIPE_NOT_AVAILABLE;
2362		goto done;
2363	}
2364
2365	result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2366					SEC_FLAG_MAXIMUM_ALLOWED,
2367					&conn->lsa_policy);
2368 done:
2369	if (!NT_STATUS_IS_OK(result)) {
2370		invalidate_cm_connection(conn);
2371		return result;
2372	}
2373
2374	*cli = conn->lsa_pipe;
2375	*lsa_policy = conn->lsa_policy;
2376	return result;
2377}
2378
2379/****************************************************************************
2380 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2381 session key stored in conn->netlogon_pipe->dc->sess_key.
2382****************************************************************************/
2383
2384NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2385			     struct rpc_pipe_client **cli)
2386{
2387	struct winbindd_cm_conn *conn;
2388	NTSTATUS result;
2389
2390	uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2391	uint8  mach_pwd[16];
2392	enum netr_SchannelType sec_chan_type;
2393	const char *account_name;
2394	struct rpc_pipe_client *netlogon_pipe = NULL;
2395
2396	*cli = NULL;
2397
2398	result = init_dc_connection_rpc(domain);
2399	if (!NT_STATUS_IS_OK(result)) {
2400		return result;
2401	}
2402
2403	conn = &domain->conn;
2404
2405	if (rpccli_is_connected(conn->netlogon_pipe)) {
2406		*cli = conn->netlogon_pipe;
2407		return NT_STATUS_OK;
2408	}
2409
2410	TALLOC_FREE(conn->netlogon_pipe);
2411
2412	result = cli_rpc_pipe_open_noauth(conn->cli,
2413					  &ndr_table_netlogon.syntax_id,
2414					  &netlogon_pipe);
2415	if (!NT_STATUS_IS_OK(result)) {
2416		return result;
2417	}
2418
2419	if ((!IS_DC) && (!domain->primary)) {
2420		/* Clear the schannel request bit and drop down */
2421		neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2422		goto no_schannel;
2423	}
2424
2425	if (lp_client_schannel() != False) {
2426		neg_flags |= NETLOGON_NEG_SCHANNEL;
2427	}
2428
2429	if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2430			       &sec_chan_type))
2431	{
2432		TALLOC_FREE(netlogon_pipe);
2433		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2434	}
2435
2436	result = rpccli_netlogon_setup_creds(
2437		 netlogon_pipe,
2438		 domain->dcname, /* server name. */
2439		 domain->name,   /* domain name */
2440		 global_myname(), /* client name */
2441		 account_name,   /* machine account */
2442		 mach_pwd,       /* machine password */
2443		 sec_chan_type,  /* from get_trust_pw */
2444		 &neg_flags);
2445
2446	if (!NT_STATUS_IS_OK(result)) {
2447		TALLOC_FREE(netlogon_pipe);
2448		return result;
2449	}
2450
2451	if ((lp_client_schannel() == True) &&
2452			((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2453		DEBUG(3, ("Server did not offer schannel\n"));
2454		TALLOC_FREE(netlogon_pipe);
2455		return NT_STATUS_ACCESS_DENIED;
2456	}
2457
2458 no_schannel:
2459	if ((lp_client_schannel() == False) ||
2460			((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2461		/*
2462		 * NetSamLogonEx only works for schannel
2463		 */
2464		domain->can_do_samlogon_ex = False;
2465
2466		/* We're done - just keep the existing connection to NETLOGON
2467		 * open */
2468		conn->netlogon_pipe = netlogon_pipe;
2469		*cli = conn->netlogon_pipe;
2470		return NT_STATUS_OK;
2471	}
2472
2473	/* Using the credentials from the first pipe, open a signed and sealed
2474	   second netlogon pipe. The session key is stored in the schannel
2475	   part of the new pipe auth struct.
2476	*/
2477
2478	result = cli_rpc_pipe_open_schannel_with_key(
2479		conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2480		DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2481		&conn->netlogon_pipe);
2482
2483	/* We can now close the initial netlogon pipe. */
2484	TALLOC_FREE(netlogon_pipe);
2485
2486	if (!NT_STATUS_IS_OK(result)) {
2487		DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2488			  "was %s\n", nt_errstr(result)));
2489
2490		invalidate_cm_connection(conn);
2491		return result;
2492	}
2493
2494	/*
2495	 * Always try netr_LogonSamLogonEx. We will fall back for NT4
2496	 * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2497	 * supported). We used to only try SamLogonEx for AD, but
2498	 * Samba DCs can also do it. And because we don't distinguish
2499	 * between Samba and NT4, always try it once.
2500	 */
2501	domain->can_do_samlogon_ex = true;
2502
2503	*cli = conn->netlogon_pipe;
2504	return NT_STATUS_OK;
2505}
2506