VERSION: Raise version number up to 3.0.36.
[Samba.git] / source / nsswitch / winbindd_cm.c
blob1fa40caf6ddc276a639ddc5bd636a7799d1f0308
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
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
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 2 of the License, or
15 (at your option) any later version.
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.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 We need to manage connections to domain controllers without having to
29 mess up the main winbindd code with other issues. The aim of the
30 connection manager is to:
32 - make connections to domain controllers and cache them
33 - re-establish connections when networks or servers go down
34 - centralise the policy on connection timeouts, domain controller
35 selection etc
36 - manage re-entrancy for when winbindd becomes able to handle
37 multiple outstanding rpc requests
39 Why not have connection management as part of the rpc layer like tng?
40 Good question. This code may morph into libsmb/rpc_cache.c or something
41 like that but at the moment it's simply staying as part of winbind. I
42 think the TNG architecture of forcing every user of the rpc layer to use
43 the connection caching system is a bad idea. It should be an optional
44 method of using the routines.
46 The TNG design is quite good but I disagree with some aspects of the
47 implementation. -tpot
52 TODO:
54 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
55 moved down into another function.
57 - Take care when destroying cli_structs as they can be shared between
58 various sam handles.
62 #include "includes.h"
63 #include "winbindd.h"
65 #undef DBGC_CLASS
66 #define DBGC_CLASS DBGC_WINBIND
68 struct dc_name_ip {
69 fstring name;
70 struct in_addr ip;
73 extern struct winbindd_methods reconnect_methods;
74 extern BOOL override_logfile;
76 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
77 static void set_dc_type_and_flags( struct winbindd_domain *domain );
78 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
79 struct dc_name_ip **dcs, int *num_dcs);
81 /****************************************************************
82 Child failed to find DC's. Reschedule check.
83 ****************************************************************/
85 static void msg_failed_to_go_online(int msg_type, struct process_id src,
86 void *buf, size_t len, void *private_data)
88 struct winbindd_domain *domain;
89 const char *domainname = (const char *)buf;
91 if (buf == NULL || len == 0) {
92 return;
95 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
97 for (domain = domain_list(); domain; domain = domain->next) {
98 if (domain->internal) {
99 continue;
102 if (strequal(domain->name, domainname)) {
103 if (domain->online) {
104 /* We're already online, ignore. */
105 DEBUG(5,("msg_fail_to_go_online: domain %s "
106 "already online.\n", domainname));
107 continue;
110 /* Reschedule the online check. */
111 set_domain_offline(domain);
112 break;
117 /****************************************************************
118 Actually cause a reconnect from a message.
119 ****************************************************************/
121 static void msg_try_to_go_online(int msg_type, struct process_id src,
122 void *buf, size_t len, void *private_data)
124 struct winbindd_domain *domain;
125 const char *domainname = (const char *)buf;
127 if (buf == NULL || len == 0) {
128 return;
131 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
133 for (domain = domain_list(); domain; domain = domain->next) {
134 if (domain->internal) {
135 continue;
138 if (strequal(domain->name, domainname)) {
140 if (domain->online) {
141 /* We're already online, ignore. */
142 DEBUG(5,("msg_try_to_go_online: domain %s "
143 "already online.\n", domainname));
144 continue;
147 /* This call takes care of setting the online
148 flag to true if we connected, or re-adding
149 the offline handler if false. Bypasses online
150 check so always does network calls. */
152 init_dc_connection_network(domain);
153 break;
158 /****************************************************************
159 Fork a child to try and contact a DC. Do this as contacting a
160 DC requires blocking lookups and we don't want to block our
161 parent.
162 ****************************************************************/
164 bool winbindd_reinit_after_fork(const char *logfile);
166 static BOOL fork_child_dc_connect(struct winbindd_domain *domain)
168 struct dc_name_ip *dcs = NULL;
169 int num_dcs = 0;
170 TALLOC_CTX *mem_ctx = NULL;
171 pid_t child_pid;
172 pid_t parent_pid = sys_getpid();
173 pstring logfile;
175 /* Stop zombies */
176 CatchChild();
178 message_block();
180 child_pid = sys_fork();
182 if (child_pid == -1) {
183 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
184 message_unblock();
185 return False;
188 if (child_pid != 0) {
189 /* Parent */
190 message_register(MSG_WINBIND_TRY_TO_GO_ONLINE,
191 msg_try_to_go_online, NULL);
192 message_register(MSG_WINBIND_FAILED_TO_GO_ONLINE,
193 msg_failed_to_go_online, NULL);
194 message_unblock();
195 return True;
198 /* Child. */
200 /* Leave messages blocked - we will never process one. */
202 /* tdb needs special fork handling */
203 if (!override_logfile) {
204 pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
206 if (!winbindd_reinit_after_fork(logfile)) {
207 DEBUG(0,("winbindd_reinit_after_fork failed.\n"));
208 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE,
209 domain->name,
210 strlen(domain->name)+1, False);
211 _exit(0);
214 mem_ctx = talloc_init("fork_child_dc_connect");
215 if (!mem_ctx) {
216 DEBUG(0,("talloc_init failed.\n"));
217 _exit(0);
220 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
221 /* Still offline ? Can't find DC's. */
222 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE,
223 domain->name,
224 strlen(domain->name)+1, False);
225 _exit(0);
228 /* We got a DC. Send a message to our parent to get it to
229 try and do the same. */
231 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE,
232 domain->name,
233 strlen(domain->name)+1, False);
234 _exit(0);
237 /****************************************************************
238 Handler triggered if we're offline to try and detect a DC.
239 ****************************************************************/
241 static void check_domain_online_handler(struct event_context *ctx,
242 struct timed_event *te,
243 const struct timeval *now,
244 void *private_data)
246 struct winbindd_domain *domain =
247 (struct winbindd_domain *)private_data;
249 DEBUG(10,("check_domain_online_handler: called for domain %s\n",
250 domain->name ));
252 TALLOC_FREE(domain->check_online_event);
254 /* Are we still in "startup" mode ? */
256 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
257 /* No longer in "startup" mode. */
258 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
259 domain->name ));
260 domain->startup = False;
263 /* We've been told to stay offline, so stay
264 that way. */
266 if (get_global_winbindd_state_offline()) {
267 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
268 domain->name ));
269 return;
272 /* Fork a child to test if it can contact a DC.
273 If it can then send ourselves a message to
274 cause a reconnect. */
276 fork_child_dc_connect(domain);
279 /****************************************************************
280 If we're still offline setup the timeout check.
281 ****************************************************************/
283 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
285 int wbc = lp_winbind_cache_time();
287 if (domain->startup) {
288 domain->check_online_timeout = 10;
289 } else if (domain->check_online_timeout < wbc) {
290 domain->check_online_timeout = wbc;
294 /****************************************************************
295 Set domain offline and also add handler to put us back online
296 if we detect a DC.
297 ****************************************************************/
299 void set_domain_offline(struct winbindd_domain *domain)
301 DEBUG(10,("set_domain_offline: called for domain %s\n",
302 domain->name ));
304 TALLOC_FREE(domain->check_online_event);
306 if (domain->internal) {
307 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
308 domain->name ));
309 return;
312 domain->online = False;
314 /* Offline domains are always initialized. They're
315 re-initialized when they go back online. */
317 domain->initialized = True;
319 /* We only add the timeout handler that checks and
320 allows us to go back online when we've not
321 been told to remain offline. */
323 if (get_global_winbindd_state_offline()) {
324 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
325 domain->name ));
326 return;
329 /* If we're in statup mode, check again in 10 seconds, not in
330 lp_winbind_cache_time() seconds (which is 5 mins by default). */
332 calc_new_online_timeout_check(domain);
334 domain->check_online_event = event_add_timed(winbind_event_context(),
335 NULL,
336 timeval_current_ofs(domain->check_online_timeout,0),
337 "check_domain_online_handler",
338 check_domain_online_handler,
339 domain);
341 /* The above *has* to succeed for winbindd to work. */
342 if (!domain->check_online_event) {
343 smb_panic("set_domain_offline: failed to add online handler.\n");
346 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
347 domain->name ));
350 /****************************************************************
351 Set domain online - if allowed.
352 ****************************************************************/
354 void ccache_regain_all_now(void);
356 static void set_domain_online(struct winbindd_domain *domain)
358 DEBUG(10,("set_domain_online: called for domain %s\n",
359 domain->name ));
361 if (domain->internal) {
362 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
363 domain->name ));
364 return;
367 if (get_global_winbindd_state_offline()) {
368 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
369 domain->name ));
370 return;
373 /* If we are waiting to get a krb5 ticket, trigger immediately. */
374 ccache_regain_all_now();
376 /* Ok, we're out of any startup mode now... */
377 domain->startup = False;
379 if (domain->online == False) {
380 /* We were offline - now we're online. We default to
381 using the MS-RPC backend if we started offline,
382 and if we're going online for the first time we
383 should really re-initialize the backends and the
384 checks to see if we're talking to an AD or NT domain.
387 domain->initialized = False;
389 /* 'reconnect_methods' is the MS-RPC backend. */
390 if (domain->backend == &reconnect_methods) {
391 domain->backend = NULL;
395 /* Ensure we have no online timeout checks. */
396 domain->check_online_timeout = 0;
397 TALLOC_FREE(domain->check_online_event);
399 /* Ensure we ignore any pending child messages. */
400 message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
401 message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
403 domain->online = True;
406 /****************************************************************
407 Requested to set a domain online.
408 ****************************************************************/
410 void set_domain_online_request(struct winbindd_domain *domain)
412 struct timeval tev;
414 DEBUG(10,("set_domain_online_request: called for domain %s\n",
415 domain->name ));
417 if (get_global_winbindd_state_offline()) {
418 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
419 domain->name ));
420 return;
423 /* We've been told it's safe to go online and
424 try and connect to a DC. But I don't believe it
425 because network manager seems to lie.
426 Wait at least 5 seconds. Heuristics suck... */
427 GetTimeOfDay(&tev);
429 /* Go into "startup" mode again. */
430 domain->startup_time = tev.tv_sec;
431 domain->startup = True;
433 tev.tv_sec += 5;
435 if (!domain->check_online_event) {
436 /* If we've come from being globally offline we
437 don't have a check online event handler set.
438 We need to add one now we're trying to go
439 back online. */
441 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
442 domain->name ));
445 TALLOC_FREE(domain->check_online_event);
447 domain->check_online_event = event_add_timed(winbind_event_context(),
448 NULL,
449 tev,
450 "check_domain_online_handler",
451 check_domain_online_handler,
452 domain);
454 /* The above *has* to succeed for winbindd to work. */
455 if (!domain->check_online_event) {
456 smb_panic("set_domain_online_request: failed to add online handler.\n");
460 /****************************************************************
461 Add -ve connection cache entries for domain and realm.
462 ****************************************************************/
464 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
465 const char *server,
466 NTSTATUS result)
468 add_failed_connection_entry(domain->name, server, result);
469 /* If this was the saf name for the last thing we talked to,
470 remove it. */
471 saf_delete(domain->name);
472 if (*domain->alt_name) {
473 add_failed_connection_entry(domain->alt_name, server, result);
474 saf_delete(domain->alt_name);
478 /* Choose between anonymous or authenticated connections. We need to use
479 an authenticated connection if DCs have the RestrictAnonymous registry
480 entry set > 0, or the "Additional restrictions for anonymous
481 connections" set in the win2k Local Security Policy.
483 Caller to free() result in domain, username, password
486 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
488 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
489 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
490 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
492 if (*username && **username) {
494 if (!*domain || !**domain)
495 *domain = smb_xstrdup(lp_workgroup());
497 if (!*password || !**password)
498 *password = smb_xstrdup("");
500 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
501 *domain, *username));
503 } else {
504 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
505 *username = smb_xstrdup("");
506 *domain = smb_xstrdup("");
507 *password = smb_xstrdup("");
511 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
512 fstring dcname, struct in_addr *dc_ip)
514 struct winbindd_domain *our_domain = NULL;
515 struct rpc_pipe_client *netlogon_pipe = NULL;
516 NTSTATUS result;
517 WERROR werr;
518 TALLOC_CTX *mem_ctx;
519 unsigned int orig_timeout;
520 fstring tmp;
521 char *p;
523 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
524 * moment.... */
526 if (IS_DC) {
527 return False;
530 if (domain->primary) {
531 return False;
534 our_domain = find_our_domain();
536 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
537 return False;
540 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
541 if (!NT_STATUS_IS_OK(result)) {
542 talloc_destroy(mem_ctx);
543 return False;
546 /* This call can take a long time - allow the server to time out.
547 35 seconds should do it. */
549 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
551 werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
552 domain->name, tmp);
554 /* And restore our original timeout. */
555 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
557 talloc_destroy(mem_ctx);
559 if (!W_ERROR_IS_OK(werr)) {
560 DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
561 dos_errstr(werr)));
562 return False;
565 /* cli_netlogon_getanydcname gives us a name with \\ */
566 p = tmp;
567 if (*p == '\\') {
568 p+=1;
570 if (*p == '\\') {
571 p+=1;
574 fstrcpy(dcname, p);
576 DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
578 if (!resolve_name(dcname, dc_ip, 0x20)) {
579 return False;
582 return True;
586 * Helper function to assemble trust password and account name
588 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
589 char **machine_password,
590 char **machine_account,
591 char **machine_krb5_principal)
593 const char *account_name;
595 if (!get_trust_pw_clear(domain->name, machine_password,
596 &account_name, NULL))
598 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
601 if ((machine_account != NULL) &&
602 (asprintf(machine_account, "%s$", account_name) == -1))
604 return NT_STATUS_NO_MEMORY;
607 /* For now assume our machine account only exists in our domain */
609 if (machine_krb5_principal != NULL)
611 if (asprintf(machine_krb5_principal, "%s$@%s",
612 account_name, lp_realm()) == -1)
614 return NT_STATUS_NO_MEMORY;
617 strupper_m(*machine_krb5_principal);
620 return NT_STATUS_OK;
623 /************************************************************************
624 Given a fd with a just-connected TCP connection to a DC, open a connection
625 to the pipe.
626 ************************************************************************/
628 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
629 const int sockfd,
630 const char *controller,
631 struct cli_state **cli,
632 BOOL *retry)
634 char *machine_password = NULL;
635 char *machine_krb5_principal = NULL;
636 char *machine_account = NULL;
637 char *ipc_username = NULL;
638 char *ipc_domain = NULL;
639 char *ipc_password = NULL;
641 BOOL got_mutex;
643 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
645 struct sockaddr peeraddr;
646 socklen_t peeraddr_len;
648 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
650 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
651 controller, domain->name ));
653 *retry = True;
655 got_mutex = secrets_named_mutex(controller,
656 WINBIND_SERVER_MUTEX_WAIT_TIME);
658 if (!got_mutex) {
659 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
660 controller));
661 result = NT_STATUS_POSSIBLE_DEADLOCK;
662 goto done;
665 if ((*cli = cli_initialise()) == NULL) {
666 DEBUG(1, ("Could not cli_initialize\n"));
667 result = NT_STATUS_NO_MEMORY;
668 goto done;
671 (*cli)->timeout = 10000; /* 10 seconds */
672 (*cli)->fd = sockfd;
673 fstrcpy((*cli)->desthost, controller);
674 (*cli)->use_kerberos = True;
676 peeraddr_len = sizeof(peeraddr);
678 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
679 (peeraddr_len != sizeof(struct sockaddr_in)) ||
680 (peeraddr_in->sin_family != PF_INET))
682 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
683 result = NT_STATUS_UNSUCCESSFUL;
684 goto done;
687 if (ntohs(peeraddr_in->sin_port) == 139) {
688 struct nmb_name calling;
689 struct nmb_name called;
691 make_nmb_name(&calling, global_myname(), 0x0);
692 make_nmb_name(&called, "*SMBSERVER", 0x20);
694 if (!cli_session_request(*cli, &calling, &called)) {
695 DEBUG(8, ("cli_session_request failed for %s\n",
696 controller));
697 result = NT_STATUS_UNSUCCESSFUL;
698 goto done;
702 cli_setup_signing_state(*cli, Undefined);
704 if (!cli_negprot(*cli)) {
705 DEBUG(1, ("cli_negprot failed\n"));
706 result = NT_STATUS_UNSUCCESSFUL;
707 goto done;
710 if (!is_trusted_domain_situation(domain->name) &&
711 (*cli)->protocol >= PROTOCOL_NT1 &&
712 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
714 ADS_STATUS ads_status;
716 result = get_trust_creds(domain, &machine_password,
717 &machine_account,
718 &machine_krb5_principal);
719 if (!NT_STATUS_IS_OK(result)) {
720 goto anon_fallback;
723 if (lp_security() == SEC_ADS) {
725 /* Try a krb5 session */
727 (*cli)->use_kerberos = True;
728 DEBUG(5, ("connecting to %s from %s with kerberos principal "
729 "[%s] and realm [%s]\n", controller, global_myname(),
730 machine_krb5_principal, domain->alt_name));
732 ads_status = cli_session_setup_spnego(*cli,
733 machine_krb5_principal,
734 machine_password,
735 lp_workgroup(),
736 domain->alt_name);
738 if (!ADS_ERR_OK(ads_status)) {
739 DEBUG(4,("failed kerberos session setup with %s\n",
740 ads_errstr(ads_status)));
743 result = ads_ntstatus(ads_status);
744 if (NT_STATUS_IS_OK(result)) {
745 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
746 cli_init_creds(*cli, machine_account, domain->name, machine_password);
747 goto session_setup_done;
751 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
752 (*cli)->use_kerberos = False;
754 DEBUG(5, ("connecting to %s from %s with username "
755 "[%s]\\[%s]\n", controller, global_myname(),
756 lp_workgroup(), machine_account));
758 ads_status = cli_session_setup_spnego(*cli,
759 machine_account,
760 machine_password,
761 lp_workgroup(),
762 NULL);
763 if (!ADS_ERR_OK(ads_status)) {
764 DEBUG(4, ("authenticated session setup failed with %s\n",
765 ads_errstr(ads_status)));
768 result = ads_ntstatus(ads_status);
769 if (NT_STATUS_IS_OK(result)) {
770 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
771 cli_init_creds(*cli, machine_account, domain->name, machine_password);
772 goto session_setup_done;
776 /* Fall back to non-kerberos session setup with auth_user */
778 (*cli)->use_kerberos = False;
780 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
782 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
783 (strlen(ipc_username) > 0)) {
785 /* Only try authenticated if we have a username */
787 DEBUG(5, ("connecting to %s from %s with username "
788 "[%s]\\[%s]\n", controller, global_myname(),
789 ipc_domain, ipc_username));
791 if (NT_STATUS_IS_OK(cli_session_setup(
792 *cli, ipc_username,
793 ipc_password, strlen(ipc_password)+1,
794 ipc_password, strlen(ipc_password)+1,
795 ipc_domain))) {
796 /* Successful logon with given username. */
797 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
798 goto session_setup_done;
799 } else {
800 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
801 ipc_domain, ipc_username ));
805 anon_fallback:
807 /* Fall back to anonymous connection, this might fail later */
809 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
810 NULL, 0, ""))) {
811 DEBUG(5, ("Connected anonymously\n"));
812 cli_init_creds(*cli, "", "", "");
813 goto session_setup_done;
816 result = cli_nt_error(*cli);
818 if (NT_STATUS_IS_OK(result))
819 result = NT_STATUS_UNSUCCESSFUL;
821 /* We can't session setup */
823 goto done;
825 session_setup_done:
827 /* cache the server name for later connections */
829 saf_store( domain->name, (*cli)->desthost );
830 if (domain->alt_name && (*cli)->use_kerberos) {
831 saf_store( domain->alt_name, (*cli)->desthost );
834 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
836 result = cli_nt_error(*cli);
838 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
840 if (NT_STATUS_IS_OK(result))
841 result = NT_STATUS_UNSUCCESSFUL;
843 goto done;
846 secrets_named_mutex_release(controller);
847 got_mutex = False;
848 *retry = False;
850 /* set the domain if empty; needed for schannel connections */
851 if ( !*(*cli)->domain ) {
852 fstrcpy( (*cli)->domain, domain->name );
855 result = NT_STATUS_OK;
857 done:
858 if (got_mutex) {
859 secrets_named_mutex_release(controller);
862 SAFE_FREE(machine_account);
863 SAFE_FREE(machine_password);
864 SAFE_FREE(machine_krb5_principal);
865 SAFE_FREE(ipc_username);
866 SAFE_FREE(ipc_domain);
867 SAFE_FREE(ipc_password);
869 if (!NT_STATUS_IS_OK(result)) {
870 winbind_add_failed_connection_entry(domain, controller, result);
871 if ((*cli) != NULL) {
872 cli_shutdown(*cli);
873 *cli = NULL;
877 return result;
880 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
881 const char *dcname, struct in_addr ip,
882 struct dc_name_ip **dcs, int *num)
884 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
885 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
886 return False;
889 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
891 if (*dcs == NULL)
892 return False;
894 fstrcpy((*dcs)[*num].name, dcname);
895 (*dcs)[*num].ip = ip;
896 *num += 1;
897 return True;
900 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
901 struct in_addr ip, uint16 port,
902 struct sockaddr_in **addrs, int *num)
904 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
906 if (*addrs == NULL) {
907 *num = 0;
908 return False;
911 (*addrs)[*num].sin_family = PF_INET;
912 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
913 (*addrs)[*num].sin_port = htons(port);
915 *num += 1;
916 return True;
919 static void mailslot_name(struct in_addr dc_ip, fstring name)
921 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
924 static BOOL send_getdc_request(struct in_addr dc_ip,
925 const char *domain_name,
926 const DOM_SID *sid)
928 pstring outbuf;
929 char *p;
930 fstring my_acct_name;
931 fstring my_mailslot;
933 mailslot_name(dc_ip, my_mailslot);
935 memset(outbuf, '\0', sizeof(outbuf));
937 p = outbuf;
939 SCVAL(p, 0, SAMLOGON);
940 p++;
942 SCVAL(p, 0, 0); /* Count pointer ... */
943 p++;
945 SIVAL(p, 0, 0); /* The sender's token ... */
946 p += 2;
948 p += dos_PutUniCode(p, global_myname(),
949 sizeof(outbuf) - PTR_DIFF(p, outbuf), True);
950 fstr_sprintf(my_acct_name, "%s$", global_myname());
951 p += dos_PutUniCode(p, my_acct_name,
952 sizeof(outbuf) - PTR_DIFF(p, outbuf), True);
954 if (strlen(my_mailslot)+1 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
955 return False;
958 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
959 p += strlen(my_mailslot)+1;
961 if (sizeof(outbuf) - PTR_DIFF(p, outbuf) < 8) {
962 return False;
964 SIVAL(p, 0, 0x80);
965 p+=4;
967 SIVAL(p, 0, sid_size(sid));
968 p+=4;
970 p = ALIGN4(p, outbuf);
972 if (PTR_DIFF(p, outbuf) > sizeof(outbuf)) {
973 return False;
976 if (sid_size(sid) + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
977 return False;
980 sid_linearize(p, sizeof(outbuf) - PTR_DIFF(p, outbuf), sid);
981 p += sid_size(sid);
983 SIVAL(p, 0, 1);
984 SSVAL(p, 4, 0xffff);
985 SSVAL(p, 6, 0xffff);
986 p+=8;
988 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
989 outbuf, PTR_DIFF(p, outbuf),
990 global_myname(), 0, domain_name, 0x1c,
991 dc_ip);
994 static BOOL receive_getdc_response(struct in_addr dc_ip,
995 const char *domain_name,
996 fstring dc_name)
998 struct packet_struct *packet;
999 fstring my_mailslot;
1000 char *buf, *p;
1001 fstring dcname, user, domain;
1002 int len;
1004 mailslot_name(dc_ip, my_mailslot);
1006 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
1008 if (packet == NULL) {
1009 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
1010 return False;
1013 DEBUG(5, ("Received packet for %s\n", my_mailslot));
1015 buf = packet->packet.dgram.data;
1016 len = packet->packet.dgram.datasize;
1018 if (len < 70) {
1019 /* 70 is a completely arbitrary value to make sure
1020 the SVAL below does not read uninitialized memory */
1021 DEBUG(3, ("GetDC got short response\n"));
1022 return False;
1025 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
1026 p = buf+SVAL(buf, smb_vwv10);
1028 if (CVAL(p,0) != SAMLOGON_R) {
1029 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
1030 return False;
1033 p+=2;
1034 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1035 STR_TERMINATE|STR_NOALIGN);
1036 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1037 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1038 STR_TERMINATE|STR_NOALIGN);
1039 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1040 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1041 STR_TERMINATE|STR_NOALIGN);
1042 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1044 if (!strequal(domain, domain_name)) {
1045 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
1046 domain_name, domain));
1047 return False;
1050 p = dcname;
1051 if (*p == '\\') p += 1;
1052 if (*p == '\\') p += 1;
1054 fstrcpy(dc_name, p);
1056 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1057 dc_name, domain));
1059 return True;
1062 /*******************************************************************
1063 convert an ip to a name
1064 *******************************************************************/
1066 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1068 struct ip_service ip_list;
1070 ip_list.ip = ip;
1071 ip_list.port = 0;
1073 #ifdef WITH_ADS
1074 /* For active directory servers, try to get the ldap server name.
1075 None of these failures should be considered critical for now */
1077 if (lp_security() == SEC_ADS) {
1078 ADS_STRUCT *ads;
1080 ads = ads_init(domain->alt_name, domain->name, NULL);
1081 ads->auth.flags |= ADS_AUTH_NO_BIND;
1083 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1084 /* We got a cldap packet. */
1085 fstrcpy(name, ads->config.ldap_server_name);
1086 namecache_store(name, 0x20, 1, &ip_list);
1088 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1090 if (domain->primary && (ads->config.flags & ADS_KDC)) {
1091 if (ads_closest_dc(ads)) {
1092 char *sitename = sitename_fetch(ads->config.realm);
1094 /* We're going to use this KDC for this realm/domain.
1095 If we are using sites, then force the krb5 libs
1096 to use this KDC. */
1098 create_local_private_krb5_conf_for_domain(domain->alt_name,
1099 domain->name,
1100 sitename,
1101 ip);
1103 SAFE_FREE(sitename);
1104 } else {
1105 /* use an off site KDC */
1106 create_local_private_krb5_conf_for_domain(domain->alt_name,
1107 domain->name,
1108 NULL,
1109 ip);
1111 /* Ensure we contact this DC also. */
1112 saf_store( domain->name, name);
1113 saf_store( domain->alt_name, name);
1116 ads_destroy( &ads );
1117 return True;
1120 ads_destroy( &ads );
1122 #endif
1124 /* try GETDC requests next */
1126 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1127 int i;
1128 smb_msleep(100);
1129 for (i=0; i<5; i++) {
1130 if (receive_getdc_response(ip, domain->name, name)) {
1131 namecache_store(name, 0x20, 1, &ip_list);
1132 return True;
1134 smb_msleep(500);
1138 /* try node status request */
1140 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1141 namecache_store(name, 0x20, 1, &ip_list);
1142 return True;
1144 return False;
1147 /*******************************************************************
1148 Retreive a list of IP address for domain controllers. Fill in
1149 the dcs[] with results.
1150 *******************************************************************/
1152 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1153 struct dc_name_ip **dcs, int *num_dcs)
1155 fstring dcname;
1156 struct in_addr ip;
1157 struct ip_service *ip_list = NULL;
1158 int iplist_size = 0;
1159 int i;
1160 BOOL is_our_domain;
1161 enum security_types sec = (enum security_types)lp_security();
1163 is_our_domain = strequal(domain->name, lp_workgroup());
1165 if ( !is_our_domain
1166 && get_dc_name_via_netlogon(domain, dcname, &ip)
1167 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1169 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1170 dcname, inet_ntoa(ip)));
1171 return True;
1174 if (sec == SEC_ADS) {
1175 char *sitename = NULL;
1177 /* We need to make sure we know the local site before
1178 doing any DNS queries, as this will restrict the
1179 get_sorted_dc_list() call below to only fetching
1180 DNS records for the correct site. */
1182 /* Find any DC to get the site record.
1183 We deliberately don't care about the
1184 return here. */
1186 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
1188 sitename = sitename_fetch(domain->alt_name);
1189 if (sitename) {
1191 /* Do the site-specific AD dns lookup first. */
1192 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1194 for ( i=0; i<iplist_size; i++ ) {
1195 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1196 ip_list[i].ip, dcs, num_dcs);
1199 SAFE_FREE(ip_list);
1200 SAFE_FREE(sitename);
1201 iplist_size = 0;
1204 /* Now we add DCs from the main AD dns lookup. */
1205 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1207 for ( i=0; i<iplist_size; i++ ) {
1208 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1209 ip_list[i].ip, dcs, num_dcs);
1213 /* try standard netbios queries if no ADS */
1215 if (iplist_size==0) {
1216 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1219 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1221 /* now add to the dc array. We'll wait until the last minute
1222 to look up the name of the DC. But we fill in the char* for
1223 the ip now in to make the failed connection cache work */
1225 for ( i=0; i<iplist_size; i++ ) {
1226 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1227 ip_list[i].ip, dcs, num_dcs);
1230 SAFE_FREE( ip_list );
1232 return True;
1235 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1236 const struct winbindd_domain *domain,
1237 fstring dcname, struct sockaddr_in *addr, int *fd)
1239 struct dc_name_ip *dcs = NULL;
1240 int num_dcs = 0;
1242 const char **dcnames = NULL;
1243 int num_dcnames = 0;
1245 struct sockaddr_in *addrs = NULL;
1246 int num_addrs = 0;
1248 int i, fd_index;
1250 *fd = -1;
1252 again:
1253 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1254 return False;
1256 for (i=0; i<num_dcs; i++) {
1258 if (!add_string_to_array(mem_ctx, dcs[i].name,
1259 &dcnames, &num_dcnames)) {
1260 return False;
1262 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1263 &addrs, &num_addrs)) {
1264 return False;
1267 if (!add_string_to_array(mem_ctx, dcs[i].name,
1268 &dcnames, &num_dcnames)) {
1269 return False;
1271 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1272 &addrs, &num_addrs)) {
1273 return False;
1277 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1278 return False;
1280 if ((addrs == NULL) || (dcnames == NULL))
1281 return False;
1283 /* 5 second timeout. */
1284 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1286 for (i=0; i<num_dcs; i++) {
1287 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1288 "domain %s address %s. Error was %s\n",
1289 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1290 winbind_add_failed_connection_entry(domain,
1291 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1293 return False;
1296 *addr = addrs[fd_index];
1298 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1299 /* Ok, we've got a name for the DC */
1300 fstrcpy(dcname, dcnames[fd_index]);
1301 return True;
1304 /* Try to figure out the name */
1305 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1306 return True;
1309 /* We can not continue without the DC's name */
1310 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1311 NT_STATUS_UNSUCCESSFUL);
1313 /* Throw away all arrays as we're doing this again. */
1314 TALLOC_FREE(dcs);
1315 num_dcs = 0;
1317 TALLOC_FREE(dcnames);
1318 num_dcnames = 0;
1320 TALLOC_FREE(addrs);
1321 num_addrs = 0;
1323 *fd = -1;
1325 goto again;
1328 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1329 struct winbindd_cm_conn *new_conn)
1331 TALLOC_CTX *mem_ctx;
1332 NTSTATUS result;
1333 char *saf_servername = saf_fetch( domain->name );
1334 int retries;
1336 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1337 SAFE_FREE(saf_servername);
1338 set_domain_offline(domain);
1339 return NT_STATUS_NO_MEMORY;
1342 /* we have to check the server affinity cache here since
1343 later we selecte a DC based on response time and not preference */
1345 /* Check the negative connection cache
1346 before talking to it. It going down may have
1347 triggered the reconnection. */
1349 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1351 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1352 saf_servername, domain->name ));
1354 /* convert an ip address to a name */
1355 if ( is_ipaddress( saf_servername ) ) {
1356 fstring saf_name;
1357 struct in_addr ip;
1359 ip = *interpret_addr2( saf_servername );
1360 if (dcip_to_name( domain, ip, saf_name )) {
1361 fstrcpy( domain->dcname, saf_name );
1362 } else {
1363 winbind_add_failed_connection_entry(
1364 domain, saf_servername,
1365 NT_STATUS_UNSUCCESSFUL);
1367 } else {
1368 fstrcpy( domain->dcname, saf_servername );
1371 SAFE_FREE( saf_servername );
1374 for (retries = 0; retries < 3; retries++) {
1376 int fd = -1;
1377 BOOL retry = False;
1379 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1381 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1382 domain->dcname, domain->name ));
1384 if (*domain->dcname
1385 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1386 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1388 struct sockaddr_in *addrs = NULL;
1389 int num_addrs = 0;
1390 int dummy = 0;
1392 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1393 set_domain_offline(domain);
1394 talloc_destroy(mem_ctx);
1395 return NT_STATUS_NO_MEMORY;
1397 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1398 set_domain_offline(domain);
1399 talloc_destroy(mem_ctx);
1400 return NT_STATUS_NO_MEMORY;
1403 /* 5 second timeout. */
1404 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1405 fd = -1;
1409 if ((fd == -1)
1410 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1412 /* This is the one place where we will
1413 set the global winbindd offline state
1414 to true, if a "WINBINDD_OFFLINE" entry
1415 is found in the winbindd cache. */
1416 set_global_winbindd_state_offline();
1417 break;
1420 new_conn->cli = NULL;
1422 result = cm_prepare_connection(domain, fd, domain->dcname,
1423 &new_conn->cli, &retry);
1425 if (!retry)
1426 break;
1429 if (NT_STATUS_IS_OK(result)) {
1430 if (domain->online == False) {
1431 /* We're changing state from offline to online. */
1432 set_global_winbindd_state_online();
1434 set_domain_online(domain);
1435 } else {
1436 /* Ensure we setup the retry handler. */
1437 set_domain_offline(domain);
1440 talloc_destroy(mem_ctx);
1441 return result;
1444 /* Close down all open pipes on a connection. */
1446 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1448 /* We're closing down a possibly dead
1449 connection. Don't have impossibly long (10s) timeouts. */
1451 if (conn->cli) {
1452 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1455 if (conn->samr_pipe != NULL) {
1456 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1457 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1458 if (conn->cli) {
1459 cli_set_timeout(conn->cli, 500);
1462 conn->samr_pipe = NULL;
1465 if (conn->lsa_pipe != NULL) {
1466 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1467 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1468 if (conn->cli) {
1469 cli_set_timeout(conn->cli, 500);
1472 conn->lsa_pipe = NULL;
1475 if (conn->netlogon_pipe != NULL) {
1476 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1477 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1478 if (conn->cli) {
1479 cli_set_timeout(conn->cli, 500);
1482 conn->netlogon_pipe = NULL;
1485 if (conn->cli) {
1486 cli_shutdown(conn->cli);
1489 conn->cli = NULL;
1492 void close_conns_after_fork(void)
1494 struct winbindd_domain *domain;
1496 for (domain = domain_list(); domain; domain = domain->next) {
1497 if (domain->conn.cli == NULL)
1498 continue;
1500 if (domain->conn.cli->fd == -1)
1501 continue;
1503 close(domain->conn.cli->fd);
1504 domain->conn.cli->fd = -1;
1508 static BOOL connection_ok(struct winbindd_domain *domain)
1510 if (domain->conn.cli == NULL) {
1511 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1512 "cli!\n", domain->dcname, domain->name));
1513 return False;
1516 if (!domain->conn.cli->initialised) {
1517 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1518 "initialised!\n", domain->dcname, domain->name));
1519 return False;
1522 if (domain->conn.cli->fd == -1) {
1523 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1524 "never started (fd == -1)\n",
1525 domain->dcname, domain->name));
1526 return False;
1529 if (domain->online == False) {
1530 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1531 return False;
1534 return True;
1537 /* Initialize a new connection up to the RPC BIND.
1538 Bypass online status check so always does network calls. */
1540 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1542 NTSTATUS result;
1544 /* Internal connections never use the network. */
1545 if (domain->internal) {
1546 domain->initialized = True;
1547 return NT_STATUS_OK;
1550 if (connection_ok(domain)) {
1551 if (!domain->initialized) {
1552 set_dc_type_and_flags(domain);
1554 return NT_STATUS_OK;
1557 invalidate_cm_connection(&domain->conn);
1559 result = cm_open_connection(domain, &domain->conn);
1561 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1562 set_dc_type_and_flags(domain);
1565 return result;
1568 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1570 if (domain->initialized && !domain->online) {
1571 /* We check for online status elsewhere. */
1572 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1575 return init_dc_connection_network(domain);
1578 /******************************************************************************
1579 We can 'sense' certain things about the DC by it's replies to certain
1580 questions.
1582 This tells us if this particular remote server is Active Directory, and if it
1583 is native mode.
1584 ******************************************************************************/
1586 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1588 NTSTATUS result;
1589 DS_DOMINFO_CTR ctr;
1590 TALLOC_CTX *mem_ctx = NULL;
1591 struct rpc_pipe_client *cli;
1592 POLICY_HND pol;
1594 char *domain_name = NULL;
1595 char *dns_name = NULL;
1596 char *forest_name = NULL;
1597 DOM_SID *dom_sid = NULL;
1599 ZERO_STRUCT( ctr );
1601 if (!connection_ok(domain)) {
1602 return;
1605 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1607 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1608 &result);
1610 if (cli == NULL) {
1611 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1612 "PI_LSARPC_DS on domain %s: (%s)\n",
1613 domain->name, nt_errstr(result)));
1615 /* if this is just a non-AD domain we need to continue
1616 * identifying so that we can in the end return with
1617 * domain->initialized = True - gd */
1619 goto no_lsarpc_ds;
1622 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1623 DsRolePrimaryDomainInfoBasic,
1624 &ctr);
1625 cli_rpc_pipe_close(cli);
1627 if (!NT_STATUS_IS_OK(result)) {
1628 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1629 "on domain %s failed: (%s)\n",
1630 domain->name, nt_errstr(result)));
1632 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1633 * every opcode on the LSARPC_DS pipe, continue with
1634 * no_lsarpc_ds mode here as well to get domain->initialized
1635 * set - gd */
1637 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1638 goto no_lsarpc_ds;
1641 return;
1644 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1645 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1646 domain->native_mode = True;
1647 } else {
1648 domain->native_mode = False;
1651 no_lsarpc_ds:
1652 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1654 if (cli == NULL) {
1655 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1656 "PI_LSARPC on domain %s: (%s)\n",
1657 domain->name, nt_errstr(result)));
1658 cli_rpc_pipe_close(cli);
1659 return;
1662 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1663 domain->name);
1664 if (!mem_ctx) {
1665 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1666 cli_rpc_pipe_close(cli);
1667 return;
1670 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1671 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1673 if (NT_STATUS_IS_OK(result)) {
1674 /* This particular query is exactly what Win2k clients use
1675 to determine that the DC is active directory */
1676 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1677 12, &domain_name,
1678 &dns_name, &forest_name,
1679 NULL, &dom_sid);
1682 if (NT_STATUS_IS_OK(result)) {
1683 domain->active_directory = True;
1685 if (domain_name)
1686 fstrcpy(domain->name, domain_name);
1688 if (dns_name)
1689 fstrcpy(domain->alt_name, dns_name);
1691 if ( forest_name )
1692 fstrcpy(domain->forest_name, forest_name);
1694 if (dom_sid)
1695 sid_copy(&domain->sid, dom_sid);
1696 } else {
1697 domain->active_directory = False;
1699 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1700 SEC_RIGHTS_MAXIMUM_ALLOWED,
1701 &pol);
1703 if (!NT_STATUS_IS_OK(result))
1704 goto done;
1706 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1707 &pol, 5, &domain_name,
1708 &dom_sid);
1710 if (NT_STATUS_IS_OK(result)) {
1711 if (domain_name)
1712 fstrcpy(domain->name, domain_name);
1714 if (dom_sid)
1715 sid_copy(&domain->sid, dom_sid);
1718 done:
1720 DEBUG(5, ("set_dc_type_and_flags: domain %s is %sin native mode.\n",
1721 domain->name, domain->native_mode ? "" : "NOT "));
1723 DEBUG(5,("set_dc_type_and_flags: domain %s is %srunning active directory.\n",
1724 domain->name, domain->active_directory ? "" : "NOT "));
1726 cli_rpc_pipe_close(cli);
1728 talloc_destroy(mem_ctx);
1730 domain->initialized = True;
1733 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1734 struct dcinfo **ppdc)
1736 NTSTATUS result;
1737 struct rpc_pipe_client *netlogon_pipe;
1739 if (lp_client_schannel() == False) {
1740 return False;
1743 result = cm_connect_netlogon(domain, &netlogon_pipe);
1744 if (!NT_STATUS_IS_OK(result)) {
1745 return False;
1748 /* Return a pointer to the struct dcinfo from the
1749 netlogon pipe. */
1751 *ppdc = domain->conn.netlogon_pipe->dc;
1752 return True;
1755 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1756 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1758 struct winbindd_cm_conn *conn;
1759 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1760 fstring conn_pwd;
1761 struct dcinfo *p_dcinfo;
1762 char *machine_password = NULL;
1763 char *machine_account = NULL;
1764 char *domain_name = NULL;
1766 result = init_dc_connection(domain);
1767 if (!NT_STATUS_IS_OK(result)) {
1768 return result;
1771 conn = &domain->conn;
1773 if (conn->samr_pipe != NULL) {
1774 goto done;
1778 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1779 * sign and sealed pipe using the machine account password by
1780 * preference. If we can't - try schannel, if that fails, try
1781 * anonymous.
1784 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1785 if ((conn->cli->user_name[0] == '\0') ||
1786 (conn->cli->domain[0] == '\0') ||
1787 (conn_pwd[0] == '\0'))
1789 result = get_trust_creds(domain, &machine_password,
1790 &machine_account, NULL);
1791 if (!NT_STATUS_IS_OK(result)) {
1792 DEBUG(10, ("cm_connect_sam: No no user available for "
1793 "domain %s, trying schannel\n", conn->cli->domain));
1794 goto schannel;
1796 domain_name = domain->name;
1797 } else {
1798 machine_password = SMB_STRDUP(conn_pwd);
1799 machine_account = SMB_STRDUP(conn->cli->user_name);
1800 domain_name = conn->cli->domain;
1803 if (!machine_password || !machine_account) {
1804 result = NT_STATUS_NO_MEMORY;
1805 goto done;
1808 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1809 authenticated SAMR pipe with sign & seal. */
1810 conn->samr_pipe =
1811 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1812 PIPE_AUTH_LEVEL_PRIVACY,
1813 domain_name,
1814 machine_account,
1815 machine_password, &result);
1817 if (conn->samr_pipe == NULL) {
1818 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1819 "pipe for domain %s using NTLMSSP "
1820 "authenticated pipe: user %s\\%s. Error was "
1821 "%s\n", domain->name, domain_name,
1822 machine_account, nt_errstr(result)));
1823 goto schannel;
1826 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1827 "domain %s using NTLMSSP authenticated "
1828 "pipe: user %s\\%s\n", domain->name,
1829 domain_name, machine_account));
1831 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1832 SEC_RIGHTS_MAXIMUM_ALLOWED,
1833 &conn->sam_connect_handle);
1834 if (NT_STATUS_IS_OK(result)) {
1835 goto open_domain;
1837 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1838 "failed for domain %s, error was %s. Trying schannel\n",
1839 domain->name, nt_errstr(result) ));
1840 cli_rpc_pipe_close(conn->samr_pipe);
1842 schannel:
1844 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1846 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1847 /* If this call fails - conn->cli can now be NULL ! */
1848 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1849 "for domain %s, trying anon\n", domain->name));
1850 goto anonymous;
1852 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1853 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1854 domain->name, p_dcinfo, &result);
1856 if (conn->samr_pipe == NULL) {
1857 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1858 "domain %s using schannel. Error was %s\n",
1859 domain->name, nt_errstr(result) ));
1860 goto anonymous;
1862 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1863 "schannel.\n", domain->name ));
1865 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1866 SEC_RIGHTS_MAXIMUM_ALLOWED,
1867 &conn->sam_connect_handle);
1868 if (NT_STATUS_IS_OK(result)) {
1869 goto open_domain;
1871 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1872 "for domain %s, error was %s. Trying anonymous\n",
1873 domain->name, nt_errstr(result) ));
1874 cli_rpc_pipe_close(conn->samr_pipe);
1876 anonymous:
1878 /* Finally fall back to anonymous. */
1879 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1880 &result);
1882 if (conn->samr_pipe == NULL) {
1883 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1884 goto done;
1887 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1888 SEC_RIGHTS_MAXIMUM_ALLOWED,
1889 &conn->sam_connect_handle);
1890 if (!NT_STATUS_IS_OK(result)) {
1891 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1892 "for domain %s Error was %s\n",
1893 domain->name, nt_errstr(result) ));
1894 goto done;
1897 open_domain:
1898 result = rpccli_samr_open_domain(conn->samr_pipe,
1899 mem_ctx,
1900 &conn->sam_connect_handle,
1901 SEC_RIGHTS_MAXIMUM_ALLOWED,
1902 &domain->sid,
1903 &conn->sam_domain_handle);
1905 done:
1907 if (!NT_STATUS_IS_OK(result)) {
1908 invalidate_cm_connection(conn);
1909 return result;
1912 *cli = conn->samr_pipe;
1913 *sam_handle = conn->sam_domain_handle;
1914 SAFE_FREE(machine_password);
1915 SAFE_FREE(machine_account);
1916 return result;
1919 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1920 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1922 struct winbindd_cm_conn *conn;
1923 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1924 fstring conn_pwd;
1925 struct dcinfo *p_dcinfo;
1927 result = init_dc_connection(domain);
1928 if (!NT_STATUS_IS_OK(result))
1929 return result;
1931 conn = &domain->conn;
1933 if (conn->lsa_pipe != NULL) {
1934 goto done;
1937 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1938 if ((conn->cli->user_name[0] == '\0') ||
1939 (conn->cli->domain[0] == '\0') ||
1940 (conn_pwd[0] == '\0')) {
1941 DEBUG(10, ("cm_connect_lsa: No no user available for "
1942 "domain %s, trying schannel\n", conn->cli->domain));
1943 goto schannel;
1946 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1947 * authenticated LSA pipe with sign & seal. */
1948 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1949 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1950 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1952 if (conn->lsa_pipe == NULL) {
1953 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1954 "domain %s using NTLMSSP authenticated pipe: user "
1955 "%s\\%s. Error was %s. Trying schannel.\n",
1956 domain->name, conn->cli->domain,
1957 conn->cli->user_name, nt_errstr(result)));
1958 goto schannel;
1961 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1962 "NTLMSSP authenticated pipe: user %s\\%s\n",
1963 domain->name, conn->cli->domain, conn->cli->user_name ));
1965 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1966 SEC_RIGHTS_MAXIMUM_ALLOWED,
1967 &conn->lsa_policy);
1968 if (NT_STATUS_IS_OK(result)) {
1969 goto done;
1972 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1973 "schannel\n"));
1975 cli_rpc_pipe_close(conn->lsa_pipe);
1977 schannel:
1979 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1981 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1982 /* If this call fails - conn->cli can now be NULL ! */
1983 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1984 "for domain %s, trying anon\n", domain->name));
1985 goto anonymous;
1987 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1988 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1989 domain->name, p_dcinfo, &result);
1991 if (conn->lsa_pipe == NULL) {
1992 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1993 "domain %s using schannel. Error was %s\n",
1994 domain->name, nt_errstr(result) ));
1995 goto anonymous;
1997 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1998 "schannel.\n", domain->name ));
2000 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2001 SEC_RIGHTS_MAXIMUM_ALLOWED,
2002 &conn->lsa_policy);
2003 if (NT_STATUS_IS_OK(result)) {
2004 goto done;
2007 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2008 "anonymous\n"));
2010 cli_rpc_pipe_close(conn->lsa_pipe);
2012 anonymous:
2014 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
2015 &result);
2016 if (conn->lsa_pipe == NULL) {
2017 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2018 goto done;
2021 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2022 SEC_RIGHTS_MAXIMUM_ALLOWED,
2023 &conn->lsa_policy);
2024 done:
2025 if (!NT_STATUS_IS_OK(result)) {
2026 invalidate_cm_connection(conn);
2027 return result;
2030 *cli = conn->lsa_pipe;
2031 *lsa_policy = conn->lsa_policy;
2032 return result;
2035 /****************************************************************************
2036 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2037 session key stored in conn->netlogon_pipe->dc->sess_key.
2038 ****************************************************************************/
2040 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2041 struct rpc_pipe_client **cli)
2043 struct winbindd_cm_conn *conn;
2044 NTSTATUS result;
2046 uint32 neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2047 uint8 mach_pwd[16];
2048 uint32 sec_chan_type;
2049 const char *account_name;
2050 struct rpc_pipe_client *netlogon_pipe = NULL;
2052 *cli = NULL;
2054 result = init_dc_connection(domain);
2055 if (!NT_STATUS_IS_OK(result)) {
2056 return result;
2059 conn = &domain->conn;
2061 if (conn->netlogon_pipe != NULL) {
2062 *cli = conn->netlogon_pipe;
2063 return NT_STATUS_OK;
2066 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
2067 &result);
2068 if (netlogon_pipe == NULL) {
2069 return result;
2072 if ((!IS_DC) && (!domain->primary)) {
2073 /* Clear the schannel request bit and drop down */
2074 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2075 goto no_schannel;
2078 if (lp_client_schannel() != False) {
2079 neg_flags |= NETLOGON_NEG_SCHANNEL;
2082 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2083 &sec_chan_type))
2085 cli_rpc_pipe_close(netlogon_pipe);
2086 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2089 result = rpccli_netlogon_setup_creds(
2090 netlogon_pipe,
2091 domain->dcname, /* server name. */
2092 domain->name, /* domain name */
2093 global_myname(), /* client name */
2094 account_name, /* machine account */
2095 mach_pwd, /* machine password */
2096 sec_chan_type, /* from get_trust_pw */
2097 &neg_flags);
2099 if (!NT_STATUS_IS_OK(result)) {
2100 cli_rpc_pipe_close(netlogon_pipe);
2101 return result;
2104 if ((lp_client_schannel() == True) &&
2105 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2106 DEBUG(3, ("Server did not offer schannel\n"));
2107 cli_rpc_pipe_close(netlogon_pipe);
2108 return NT_STATUS_ACCESS_DENIED;
2111 no_schannel:
2112 if ((lp_client_schannel() == False) ||
2113 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2114 /* We're done - just keep the existing connection to NETLOGON
2115 * open */
2116 conn->netlogon_pipe = netlogon_pipe;
2117 *cli = conn->netlogon_pipe;
2118 return NT_STATUS_OK;
2121 /* Using the credentials from the first pipe, open a signed and sealed
2122 second netlogon pipe. The session key is stored in the schannel
2123 part of the new pipe auth struct.
2126 conn->netlogon_pipe =
2127 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2128 PI_NETLOGON,
2129 PIPE_AUTH_LEVEL_PRIVACY,
2130 domain->name,
2131 netlogon_pipe->dc,
2132 &result);
2134 /* We can now close the initial netlogon pipe. */
2135 cli_rpc_pipe_close(netlogon_pipe);
2137 if (conn->netlogon_pipe == NULL) {
2138 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2139 "was %s\n", nt_errstr(result)));
2141 /* make sure we return something besides OK */
2142 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2145 *cli = conn->netlogon_pipe;
2146 return NT_STATUS_OK;