Fix logic error in cm_connect_sam().
[Samba.git] / source / nsswitch / winbindd_cm.c
blob6dc2522db0729132970d9ef287d3012ab21974b9
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 static BOOL fork_child_dc_connect(struct winbindd_domain *domain)
166 struct dc_name_ip *dcs = NULL;
167 int num_dcs = 0;
168 TALLOC_CTX *mem_ctx = NULL;
169 pid_t child_pid;
170 pid_t parent_pid = sys_getpid();
172 /* Stop zombies */
173 CatchChild();
175 message_block();
177 child_pid = sys_fork();
179 if (child_pid == -1) {
180 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
181 message_unblock();
182 return False;
185 if (child_pid != 0) {
186 /* Parent */
187 message_register(MSG_WINBIND_TRY_TO_GO_ONLINE,
188 msg_try_to_go_online, NULL);
189 message_register(MSG_WINBIND_FAILED_TO_GO_ONLINE,
190 msg_failed_to_go_online, NULL);
191 message_unblock();
192 return True;
195 /* Child. */
197 /* Leave messages blocked - we will never process one. */
199 /* tdb needs special fork handling */
200 if (tdb_reopen_all(1) == -1) {
201 DEBUG(0,("tdb_reopen_all failed.\n"));
202 _exit(0);
205 close_conns_after_fork();
207 if (!override_logfile) {
208 pstring logfile;
209 pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
210 lp_set_logfile(logfile);
211 reopen_logs();
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 static void set_domain_online(struct winbindd_domain *domain)
356 struct timeval now;
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 GetTimeOfDay(&now);
375 set_event_dispatch_time(winbind_event_context(),
376 "krb5_ticket_gain_handler", now);
378 /* Ok, we're out of any startup mode now... */
379 domain->startup = False;
381 if (domain->online == False) {
382 /* We were offline - now we're online. We default to
383 using the MS-RPC backend if we started offline,
384 and if we're going online for the first time we
385 should really re-initialize the backends and the
386 checks to see if we're talking to an AD or NT domain.
389 domain->initialized = False;
391 /* 'reconnect_methods' is the MS-RPC backend. */
392 if (domain->backend == &reconnect_methods) {
393 domain->backend = NULL;
397 /* Ensure we have no online timeout checks. */
398 domain->check_online_timeout = 0;
399 TALLOC_FREE(domain->check_online_event);
401 /* Ensure we ignore any pending child messages. */
402 message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
403 message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
405 domain->online = True;
408 /****************************************************************
409 Requested to set a domain online.
410 ****************************************************************/
412 void set_domain_online_request(struct winbindd_domain *domain)
414 struct timeval tev;
416 DEBUG(10,("set_domain_online_request: called for domain %s\n",
417 domain->name ));
419 if (get_global_winbindd_state_offline()) {
420 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
421 domain->name ));
422 return;
425 /* We've been told it's safe to go online and
426 try and connect to a DC. But I don't believe it
427 because network manager seems to lie.
428 Wait at least 5 seconds. Heuristics suck... */
430 if (!domain->check_online_event) {
431 /* If we've come from being globally offline we
432 don't have a check online event handler set.
433 We need to add one now we're trying to go
434 back online. */
436 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
437 domain->name ));
439 domain->check_online_event = event_add_timed(winbind_event_context(),
440 NULL,
441 timeval_current_ofs(5, 0),
442 "check_domain_online_handler",
443 check_domain_online_handler,
444 domain);
446 /* The above *has* to succeed for winbindd to work. */
447 if (!domain->check_online_event) {
448 smb_panic("set_domain_online_request: failed to add online handler.\n");
452 GetTimeOfDay(&tev);
454 /* Go into "startup" mode again. */
455 domain->startup_time = tev.tv_sec;
456 domain->startup = True;
458 tev.tv_sec += 5;
460 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
463 /****************************************************************
464 Add -ve connection cache entries for domain and realm.
465 ****************************************************************/
467 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
468 const char *server,
469 NTSTATUS result)
471 add_failed_connection_entry(domain->name, server, result);
472 /* If this was the saf name for the last thing we talked to,
473 remove it. */
474 saf_delete(domain->name);
475 if (*domain->alt_name) {
476 add_failed_connection_entry(domain->alt_name, server, result);
477 saf_delete(domain->alt_name);
481 /* Choose between anonymous or authenticated connections. We need to use
482 an authenticated connection if DCs have the RestrictAnonymous registry
483 entry set > 0, or the "Additional restrictions for anonymous
484 connections" set in the win2k Local Security Policy.
486 Caller to free() result in domain, username, password
489 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
491 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
492 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
493 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
495 if (*username && **username) {
497 if (!*domain || !**domain)
498 *domain = smb_xstrdup(lp_workgroup());
500 if (!*password || !**password)
501 *password = smb_xstrdup("");
503 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
504 *domain, *username));
506 } else {
507 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
508 *username = smb_xstrdup("");
509 *domain = smb_xstrdup("");
510 *password = smb_xstrdup("");
514 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
515 fstring dcname, struct in_addr *dc_ip)
517 struct winbindd_domain *our_domain = NULL;
518 struct rpc_pipe_client *netlogon_pipe = NULL;
519 NTSTATUS result;
520 WERROR werr;
521 TALLOC_CTX *mem_ctx;
522 unsigned int orig_timeout;
523 fstring tmp;
524 char *p;
526 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
527 * moment.... */
529 if (IS_DC) {
530 return False;
533 if (domain->primary) {
534 return False;
537 our_domain = find_our_domain();
539 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
540 return False;
543 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
544 if (!NT_STATUS_IS_OK(result)) {
545 talloc_destroy(mem_ctx);
546 return False;
549 /* This call can take a long time - allow the server to time out.
550 35 seconds should do it. */
552 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
554 werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
555 domain->name, tmp);
557 /* And restore our original timeout. */
558 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
560 talloc_destroy(mem_ctx);
562 if (!W_ERROR_IS_OK(werr)) {
563 DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
564 dos_errstr(werr)));
565 return False;
568 /* cli_netlogon_getanydcname gives us a name with \\ */
569 p = tmp;
570 if (*p == '\\') {
571 p+=1;
573 if (*p == '\\') {
574 p+=1;
577 fstrcpy(dcname, p);
579 DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
581 if (!resolve_name(dcname, dc_ip, 0x20)) {
582 return False;
585 return True;
589 * Helper function to assemble trust password and account name
591 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
592 char **machine_password,
593 char **machine_account,
594 char **machine_krb5_principal)
596 const char *account_name;
598 if (!get_trust_pw_clear(domain->name, machine_password,
599 &account_name, NULL))
601 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
604 if ((machine_account != NULL) &&
605 (asprintf(machine_account, "%s$", account_name) == -1))
607 return NT_STATUS_NO_MEMORY;
610 /* this is at least correct when domain is our domain,
611 * which is the only case, when this is currently used: */
612 if ((machine_krb5_principal != NULL) &&
613 (asprintf(machine_krb5_principal, "%s$@%s", account_name,
614 domain->alt_name) == -1))
616 return NT_STATUS_NO_MEMORY;
619 return NT_STATUS_OK;
622 /************************************************************************
623 Given a fd with a just-connected TCP connection to a DC, open a connection
624 to the pipe.
625 ************************************************************************/
627 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
628 const int sockfd,
629 const char *controller,
630 struct cli_state **cli,
631 BOOL *retry)
633 char *machine_password = NULL;
634 char *machine_krb5_principal = NULL;
635 char *machine_account = NULL;
636 char *ipc_username = NULL;
637 char *ipc_domain = NULL;
638 char *ipc_password = NULL;
640 BOOL got_mutex;
642 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
644 struct sockaddr peeraddr;
645 socklen_t peeraddr_len;
647 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
649 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
650 controller, domain->name ));
652 *retry = True;
654 got_mutex = secrets_named_mutex(controller,
655 WINBIND_SERVER_MUTEX_WAIT_TIME);
657 if (!got_mutex) {
658 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
659 controller));
660 result = NT_STATUS_POSSIBLE_DEADLOCK;
661 goto done;
664 if ((*cli = cli_initialise()) == NULL) {
665 DEBUG(1, ("Could not cli_initialize\n"));
666 result = NT_STATUS_NO_MEMORY;
667 goto done;
670 (*cli)->timeout = 10000; /* 10 seconds */
671 (*cli)->fd = sockfd;
672 fstrcpy((*cli)->desthost, controller);
673 (*cli)->use_kerberos = True;
675 peeraddr_len = sizeof(peeraddr);
677 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
678 (peeraddr_len != sizeof(struct sockaddr_in)) ||
679 (peeraddr_in->sin_family != PF_INET))
681 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
682 result = NT_STATUS_UNSUCCESSFUL;
683 goto done;
686 if (ntohs(peeraddr_in->sin_port) == 139) {
687 struct nmb_name calling;
688 struct nmb_name called;
690 make_nmb_name(&calling, global_myname(), 0x0);
691 make_nmb_name(&called, "*SMBSERVER", 0x20);
693 if (!cli_session_request(*cli, &calling, &called)) {
694 DEBUG(8, ("cli_session_request failed for %s\n",
695 controller));
696 result = NT_STATUS_UNSUCCESSFUL;
697 goto done;
701 cli_setup_signing_state(*cli, Undefined);
703 if (!cli_negprot(*cli)) {
704 DEBUG(1, ("cli_negprot failed\n"));
705 result = NT_STATUS_UNSUCCESSFUL;
706 goto done;
709 if (!is_trusted_domain_situation(domain->name) &&
710 (*cli)->protocol >= PROTOCOL_NT1 &&
711 (*cli)->capabilities & CAP_EXTENDED_SECURITY)
713 ADS_STATUS ads_status;
715 result = get_trust_creds(domain, &machine_password,
716 &machine_account,
717 &machine_krb5_principal);
718 if (!NT_STATUS_IS_OK(result)) {
719 goto done;
722 if (lp_security() == SEC_ADS) {
724 /* Try a krb5 session */
726 (*cli)->use_kerberos = True;
727 DEBUG(5, ("connecting to %s from %s with kerberos principal "
728 "[%s]\n", controller, global_myname(),
729 machine_krb5_principal));
731 ads_status = cli_session_setup_spnego(*cli,
732 machine_krb5_principal,
733 machine_password,
734 domain->name);
736 if (!ADS_ERR_OK(ads_status)) {
737 DEBUG(4,("failed kerberos session setup with %s\n",
738 ads_errstr(ads_status)));
741 result = ads_ntstatus(ads_status);
742 if (NT_STATUS_IS_OK(result)) {
743 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
744 cli_init_creds(*cli, machine_account, domain->name, machine_password);
745 goto session_setup_done;
749 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
750 (*cli)->use_kerberos = False;
752 DEBUG(5, ("connecting to %s from %s with username "
753 "[%s]\\[%s]\n", controller, global_myname(),
754 domain->name, machine_account));
756 ads_status = cli_session_setup_spnego(*cli,
757 machine_account,
758 machine_password,
759 domain->name);
760 if (!ADS_ERR_OK(ads_status)) {
761 DEBUG(4, ("authenticated session setup failed with %s\n",
762 ads_errstr(ads_status)));
765 result = ads_ntstatus(ads_status);
766 if (NT_STATUS_IS_OK(result)) {
767 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
768 cli_init_creds(*cli, machine_account, domain->name, machine_password);
769 goto session_setup_done;
773 /* Fall back to non-kerberos session setup with auth_user */
775 (*cli)->use_kerberos = False;
777 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
779 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
780 (strlen(ipc_username) > 0)) {
782 /* Only try authenticated if we have a username */
784 DEBUG(5, ("connecting to %s from %s with username "
785 "[%s]\\[%s]\n", controller, global_myname(),
786 ipc_domain, ipc_username));
788 if (NT_STATUS_IS_OK(cli_session_setup(
789 *cli, ipc_username,
790 ipc_password, strlen(ipc_password)+1,
791 ipc_password, strlen(ipc_password)+1,
792 ipc_domain))) {
793 /* Successful logon with given username. */
794 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
795 goto session_setup_done;
796 } else {
797 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
798 ipc_domain, ipc_username ));
802 /* Fall back to anonymous connection, this might fail later */
804 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
805 NULL, 0, ""))) {
806 DEBUG(5, ("Connected anonymously\n"));
807 cli_init_creds(*cli, "", "", "");
808 goto session_setup_done;
811 result = cli_nt_error(*cli);
813 if (NT_STATUS_IS_OK(result))
814 result = NT_STATUS_UNSUCCESSFUL;
816 /* We can't session setup */
818 goto done;
820 session_setup_done:
822 /* cache the server name for later connections */
824 saf_store( domain->name, (*cli)->desthost );
825 if (domain->alt_name && (*cli)->use_kerberos) {
826 saf_store( domain->alt_name, (*cli)->desthost );
829 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
831 result = cli_nt_error(*cli);
833 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
835 if (NT_STATUS_IS_OK(result))
836 result = NT_STATUS_UNSUCCESSFUL;
838 goto done;
841 secrets_named_mutex_release(controller);
842 got_mutex = False;
843 *retry = False;
845 /* set the domain if empty; needed for schannel connections */
846 if ( !*(*cli)->domain ) {
847 fstrcpy( (*cli)->domain, domain->name );
850 result = NT_STATUS_OK;
852 done:
853 if (got_mutex) {
854 secrets_named_mutex_release(controller);
857 SAFE_FREE(machine_account);
858 SAFE_FREE(machine_password);
859 SAFE_FREE(machine_krb5_principal);
860 SAFE_FREE(ipc_username);
861 SAFE_FREE(ipc_domain);
862 SAFE_FREE(ipc_password);
864 if (!NT_STATUS_IS_OK(result)) {
865 winbind_add_failed_connection_entry(domain, controller, result);
866 if ((*cli) != NULL) {
867 cli_shutdown(*cli);
868 *cli = NULL;
872 return result;
875 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
876 const char *dcname, struct in_addr ip,
877 struct dc_name_ip **dcs, int *num)
879 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
880 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
881 return False;
884 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
886 if (*dcs == NULL)
887 return False;
889 fstrcpy((*dcs)[*num].name, dcname);
890 (*dcs)[*num].ip = ip;
891 *num += 1;
892 return True;
895 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
896 struct in_addr ip, uint16 port,
897 struct sockaddr_in **addrs, int *num)
899 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
901 if (*addrs == NULL) {
902 *num = 0;
903 return False;
906 (*addrs)[*num].sin_family = PF_INET;
907 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
908 (*addrs)[*num].sin_port = htons(port);
910 *num += 1;
911 return True;
914 static void mailslot_name(struct in_addr dc_ip, fstring name)
916 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
919 static BOOL send_getdc_request(struct in_addr dc_ip,
920 const char *domain_name,
921 const DOM_SID *sid)
923 pstring outbuf;
924 char *p;
925 fstring my_acct_name;
926 fstring my_mailslot;
928 mailslot_name(dc_ip, my_mailslot);
930 memset(outbuf, '\0', sizeof(outbuf));
932 p = outbuf;
934 SCVAL(p, 0, SAMLOGON);
935 p++;
937 SCVAL(p, 0, 0); /* Count pointer ... */
938 p++;
940 SIVAL(p, 0, 0); /* The sender's token ... */
941 p += 2;
943 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
944 fstr_sprintf(my_acct_name, "%s$", global_myname());
945 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
947 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
948 p += strlen(my_mailslot)+1;
950 SIVAL(p, 0, 0x80);
951 p+=4;
953 SIVAL(p, 0, sid_size(sid));
954 p+=4;
956 p = ALIGN4(p, outbuf);
958 sid_linearize(p, sid_size(sid), sid);
959 p += sid_size(sid);
961 SIVAL(p, 0, 1);
962 SSVAL(p, 4, 0xffff);
963 SSVAL(p, 6, 0xffff);
964 p+=8;
966 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
967 outbuf, PTR_DIFF(p, outbuf),
968 global_myname(), 0, domain_name, 0x1c,
969 dc_ip);
972 static BOOL receive_getdc_response(struct in_addr dc_ip,
973 const char *domain_name,
974 fstring dc_name)
976 struct packet_struct *packet;
977 fstring my_mailslot;
978 char *buf, *p;
979 fstring dcname, user, domain;
980 int len;
982 mailslot_name(dc_ip, my_mailslot);
984 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
986 if (packet == NULL) {
987 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
988 return False;
991 DEBUG(5, ("Received packet for %s\n", my_mailslot));
993 buf = packet->packet.dgram.data;
994 len = packet->packet.dgram.datasize;
996 if (len < 70) {
997 /* 70 is a completely arbitrary value to make sure
998 the SVAL below does not read uninitialized memory */
999 DEBUG(3, ("GetDC got short response\n"));
1000 return False;
1003 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
1004 p = buf+SVAL(buf, smb_vwv10);
1006 if (CVAL(p,0) != SAMLOGON_R) {
1007 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
1008 return False;
1011 p+=2;
1012 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1013 STR_TERMINATE|STR_NOALIGN);
1014 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1015 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1016 STR_TERMINATE|STR_NOALIGN);
1017 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1018 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1019 STR_TERMINATE|STR_NOALIGN);
1020 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1022 if (!strequal(domain, domain_name)) {
1023 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
1024 domain_name, domain));
1025 return False;
1028 p = dcname;
1029 if (*p == '\\') p += 1;
1030 if (*p == '\\') p += 1;
1032 fstrcpy(dc_name, p);
1034 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1035 dc_name, domain));
1037 return True;
1040 /*******************************************************************
1041 convert an ip to a name
1042 *******************************************************************/
1044 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1046 struct ip_service ip_list;
1048 ip_list.ip = ip;
1049 ip_list.port = 0;
1051 #ifdef WITH_ADS
1052 /* For active directory servers, try to get the ldap server name.
1053 None of these failures should be considered critical for now */
1055 if (lp_security() == SEC_ADS) {
1056 ADS_STRUCT *ads;
1058 ads = ads_init(domain->alt_name, domain->name, NULL);
1059 ads->auth.flags |= ADS_AUTH_NO_BIND;
1061 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1062 /* We got a cldap packet. */
1063 fstrcpy(name, ads->config.ldap_server_name);
1064 namecache_store(name, 0x20, 1, &ip_list);
1066 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1068 if (domain->primary && (ads->config.flags & ADS_KDC)) {
1069 if (ads_closest_dc(ads)) {
1070 char *sitename = sitename_fetch(ads->config.realm);
1072 /* We're going to use this KDC for this realm/domain.
1073 If we are using sites, then force the krb5 libs
1074 to use this KDC. */
1076 create_local_private_krb5_conf_for_domain(domain->alt_name,
1077 domain->name,
1078 sitename,
1079 ip);
1081 SAFE_FREE(sitename);
1082 } else {
1083 /* use an off site KDC */
1084 create_local_private_krb5_conf_for_domain(domain->alt_name,
1085 domain->name,
1086 NULL,
1087 ip);
1089 /* Ensure we contact this DC also. */
1090 saf_store( domain->name, name);
1091 saf_store( domain->alt_name, name);
1094 ads_destroy( &ads );
1095 return True;
1098 ads_destroy( &ads );
1100 #endif
1102 /* try GETDC requests next */
1104 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1105 int i;
1106 smb_msleep(100);
1107 for (i=0; i<5; i++) {
1108 if (receive_getdc_response(ip, domain->name, name)) {
1109 namecache_store(name, 0x20, 1, &ip_list);
1110 return True;
1112 smb_msleep(500);
1116 /* try node status request */
1118 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1119 namecache_store(name, 0x20, 1, &ip_list);
1120 return True;
1122 return False;
1125 /*******************************************************************
1126 Retreive a list of IP address for domain controllers. Fill in
1127 the dcs[] with results.
1128 *******************************************************************/
1130 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1131 struct dc_name_ip **dcs, int *num_dcs)
1133 fstring dcname;
1134 struct in_addr ip;
1135 struct ip_service *ip_list = NULL;
1136 int iplist_size = 0;
1137 int i;
1138 BOOL is_our_domain;
1139 enum security_types sec = (enum security_types)lp_security();
1141 is_our_domain = strequal(domain->name, lp_workgroup());
1143 if ( !is_our_domain
1144 && get_dc_name_via_netlogon(domain, dcname, &ip)
1145 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1147 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1148 dcname, inet_ntoa(ip)));
1149 return True;
1152 if (sec == SEC_ADS) {
1153 char *sitename = NULL;
1155 /* We need to make sure we know the local site before
1156 doing any DNS queries, as this will restrict the
1157 get_sorted_dc_list() call below to only fetching
1158 DNS records for the correct site. */
1160 /* Find any DC to get the site record.
1161 We deliberately don't care about the
1162 return here. */
1164 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
1166 sitename = sitename_fetch(domain->alt_name);
1167 if (sitename) {
1169 /* Do the site-specific AD dns lookup first. */
1170 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1172 for ( i=0; i<iplist_size; i++ ) {
1173 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1174 ip_list[i].ip, dcs, num_dcs);
1177 SAFE_FREE(ip_list);
1178 SAFE_FREE(sitename);
1179 iplist_size = 0;
1182 /* Now we add DCs from the main AD dns lookup. */
1183 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1185 for ( i=0; i<iplist_size; i++ ) {
1186 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1187 ip_list[i].ip, dcs, num_dcs);
1191 /* try standard netbios queries if no ADS */
1193 if (iplist_size==0) {
1194 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1197 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1199 /* now add to the dc array. We'll wait until the last minute
1200 to look up the name of the DC. But we fill in the char* for
1201 the ip now in to make the failed connection cache work */
1203 for ( i=0; i<iplist_size; i++ ) {
1204 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1205 ip_list[i].ip, dcs, num_dcs);
1208 SAFE_FREE( ip_list );
1210 return True;
1213 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1214 const struct winbindd_domain *domain,
1215 fstring dcname, struct sockaddr_in *addr, int *fd)
1217 struct dc_name_ip *dcs = NULL;
1218 int num_dcs = 0;
1220 const char **dcnames = NULL;
1221 int num_dcnames = 0;
1223 struct sockaddr_in *addrs = NULL;
1224 int num_addrs = 0;
1226 int i, fd_index;
1228 again:
1229 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1230 return False;
1232 for (i=0; i<num_dcs; i++) {
1234 if (!add_string_to_array(mem_ctx, dcs[i].name,
1235 &dcnames, &num_dcnames)) {
1236 return False;
1238 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1239 &addrs, &num_addrs)) {
1240 return False;
1243 if (!add_string_to_array(mem_ctx, dcs[i].name,
1244 &dcnames, &num_dcnames)) {
1245 return False;
1247 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1248 &addrs, &num_addrs)) {
1249 return False;
1253 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1254 return False;
1256 if ((addrs == NULL) || (dcnames == NULL))
1257 return False;
1259 /* 5 second timeout. */
1260 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1262 for (i=0; i<num_dcs; i++) {
1263 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1264 "domain %s address %s. Error was %s\n",
1265 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1266 winbind_add_failed_connection_entry(domain,
1267 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1269 return False;
1272 *addr = addrs[fd_index];
1274 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1275 /* Ok, we've got a name for the DC */
1276 fstrcpy(dcname, dcnames[fd_index]);
1277 return True;
1280 /* Try to figure out the name */
1281 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1282 return True;
1285 /* We can not continue without the DC's name */
1286 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1287 NT_STATUS_UNSUCCESSFUL);
1288 goto again;
1291 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1292 struct winbindd_cm_conn *new_conn)
1294 TALLOC_CTX *mem_ctx;
1295 NTSTATUS result;
1296 char *saf_servername = saf_fetch( domain->name );
1297 int retries;
1299 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1300 SAFE_FREE(saf_servername);
1301 set_domain_offline(domain);
1302 return NT_STATUS_NO_MEMORY;
1305 /* we have to check the server affinity cache here since
1306 later we selecte a DC based on response time and not preference */
1308 /* Check the negative connection cache
1309 before talking to it. It going down may have
1310 triggered the reconnection. */
1312 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1314 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1315 saf_servername, domain->name ));
1317 /* convert an ip address to a name */
1318 if ( is_ipaddress( saf_servername ) ) {
1319 fstring saf_name;
1320 struct in_addr ip;
1322 ip = *interpret_addr2( saf_servername );
1323 if (dcip_to_name( domain, ip, saf_name )) {
1324 fstrcpy( domain->dcname, saf_name );
1325 } else {
1326 winbind_add_failed_connection_entry(
1327 domain, saf_servername,
1328 NT_STATUS_UNSUCCESSFUL);
1330 } else {
1331 fstrcpy( domain->dcname, saf_servername );
1334 SAFE_FREE( saf_servername );
1337 for (retries = 0; retries < 3; retries++) {
1339 int fd = -1;
1340 BOOL retry = False;
1342 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1344 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1345 domain->dcname, domain->name ));
1347 if (*domain->dcname
1348 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1349 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1351 struct sockaddr_in *addrs = NULL;
1352 int num_addrs = 0;
1353 int dummy = 0;
1355 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1356 set_domain_offline(domain);
1357 talloc_destroy(mem_ctx);
1358 return NT_STATUS_NO_MEMORY;
1360 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1361 set_domain_offline(domain);
1362 talloc_destroy(mem_ctx);
1363 return NT_STATUS_NO_MEMORY;
1366 /* 5 second timeout. */
1367 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1368 fd = -1;
1372 if ((fd == -1)
1373 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1375 /* This is the one place where we will
1376 set the global winbindd offline state
1377 to true, if a "WINBINDD_OFFLINE" entry
1378 is found in the winbindd cache. */
1379 set_global_winbindd_state_offline();
1380 break;
1383 new_conn->cli = NULL;
1385 result = cm_prepare_connection(domain, fd, domain->dcname,
1386 &new_conn->cli, &retry);
1388 if (!retry)
1389 break;
1392 if (NT_STATUS_IS_OK(result)) {
1393 if (domain->online == False) {
1394 /* We're changing state from offline to online. */
1395 set_global_winbindd_state_online();
1397 set_domain_online(domain);
1398 } else {
1399 /* Ensure we setup the retry handler. */
1400 set_domain_offline(domain);
1403 talloc_destroy(mem_ctx);
1404 return result;
1407 /* Close down all open pipes on a connection. */
1409 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1411 /* We're closing down a possibly dead
1412 connection. Don't have impossibly long (10s) timeouts. */
1414 if (conn->cli) {
1415 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1418 if (conn->samr_pipe != NULL) {
1419 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1420 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1421 if (conn->cli) {
1422 cli_set_timeout(conn->cli, 500);
1425 conn->samr_pipe = NULL;
1428 if (conn->lsa_pipe != NULL) {
1429 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1430 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1431 if (conn->cli) {
1432 cli_set_timeout(conn->cli, 500);
1435 conn->lsa_pipe = NULL;
1438 if (conn->netlogon_pipe != NULL) {
1439 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1440 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1441 if (conn->cli) {
1442 cli_set_timeout(conn->cli, 500);
1445 conn->netlogon_pipe = NULL;
1448 if (conn->cli) {
1449 cli_shutdown(conn->cli);
1452 conn->cli = NULL;
1455 void close_conns_after_fork(void)
1457 struct winbindd_domain *domain;
1459 for (domain = domain_list(); domain; domain = domain->next) {
1460 if (domain->conn.cli == NULL)
1461 continue;
1463 if (domain->conn.cli->fd == -1)
1464 continue;
1466 close(domain->conn.cli->fd);
1467 domain->conn.cli->fd = -1;
1471 static BOOL connection_ok(struct winbindd_domain *domain)
1473 if (domain->conn.cli == NULL) {
1474 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1475 "cli!\n", domain->dcname, domain->name));
1476 return False;
1479 if (!domain->conn.cli->initialised) {
1480 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1481 "initialised!\n", domain->dcname, domain->name));
1482 return False;
1485 if (domain->conn.cli->fd == -1) {
1486 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1487 "never started (fd == -1)\n",
1488 domain->dcname, domain->name));
1489 return False;
1492 if (domain->online == False) {
1493 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1494 return False;
1497 return True;
1500 /* Initialize a new connection up to the RPC BIND.
1501 Bypass online status check so always does network calls. */
1503 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1505 NTSTATUS result;
1507 /* Internal connections never use the network. */
1508 if (domain->internal) {
1509 domain->initialized = True;
1510 return NT_STATUS_OK;
1513 if (connection_ok(domain)) {
1514 if (!domain->initialized) {
1515 set_dc_type_and_flags(domain);
1517 return NT_STATUS_OK;
1520 invalidate_cm_connection(&domain->conn);
1522 result = cm_open_connection(domain, &domain->conn);
1524 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1525 set_dc_type_and_flags(domain);
1528 return result;
1531 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1533 if (domain->initialized && !domain->online) {
1534 /* We check for online status elsewhere. */
1535 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1538 return init_dc_connection_network(domain);
1541 /******************************************************************************
1542 We can 'sense' certain things about the DC by it's replies to certain
1543 questions.
1545 This tells us if this particular remote server is Active Directory, and if it
1546 is native mode.
1547 ******************************************************************************/
1549 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1551 NTSTATUS result;
1552 DS_DOMINFO_CTR ctr;
1553 TALLOC_CTX *mem_ctx = NULL;
1554 struct rpc_pipe_client *cli;
1555 POLICY_HND pol;
1557 char *domain_name = NULL;
1558 char *dns_name = NULL;
1559 char *forest_name = NULL;
1560 DOM_SID *dom_sid = NULL;
1562 ZERO_STRUCT( ctr );
1564 if (!connection_ok(domain)) {
1565 return;
1568 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1570 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1571 &result);
1573 if (cli == NULL) {
1574 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1575 "PI_LSARPC_DS on domain %s: (%s)\n",
1576 domain->name, nt_errstr(result)));
1578 /* if this is just a non-AD domain we need to continue
1579 * identifying so that we can in the end return with
1580 * domain->initialized = True - gd */
1582 goto no_lsarpc_ds;
1585 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1586 DsRolePrimaryDomainInfoBasic,
1587 &ctr);
1588 cli_rpc_pipe_close(cli);
1590 if (!NT_STATUS_IS_OK(result)) {
1591 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1592 "on domain %s failed: (%s)\n",
1593 domain->name, nt_errstr(result)));
1595 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1596 * every opcode on the LSARPC_DS pipe, continue with
1597 * no_lsarpc_ds mode here as well to get domain->initialized
1598 * set - gd */
1600 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1601 goto no_lsarpc_ds;
1604 return;
1607 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1608 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1609 domain->native_mode = True;
1610 } else {
1611 domain->native_mode = False;
1614 no_lsarpc_ds:
1615 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1617 if (cli == NULL) {
1618 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1619 "PI_LSARPC on domain %s: (%s)\n",
1620 domain->name, nt_errstr(result)));
1621 cli_rpc_pipe_close(cli);
1622 return;
1625 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1626 domain->name);
1627 if (!mem_ctx) {
1628 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1629 cli_rpc_pipe_close(cli);
1630 return;
1633 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1634 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1636 if (NT_STATUS_IS_OK(result)) {
1637 /* This particular query is exactly what Win2k clients use
1638 to determine that the DC is active directory */
1639 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1640 12, &domain_name,
1641 &dns_name, &forest_name,
1642 NULL, &dom_sid);
1645 if (NT_STATUS_IS_OK(result)) {
1646 domain->active_directory = True;
1648 if (domain_name)
1649 fstrcpy(domain->name, domain_name);
1651 if (dns_name)
1652 fstrcpy(domain->alt_name, dns_name);
1654 if ( forest_name )
1655 fstrcpy(domain->forest_name, forest_name);
1657 if (dom_sid)
1658 sid_copy(&domain->sid, dom_sid);
1659 } else {
1660 domain->active_directory = False;
1662 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1663 SEC_RIGHTS_MAXIMUM_ALLOWED,
1664 &pol);
1666 if (!NT_STATUS_IS_OK(result))
1667 goto done;
1669 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1670 &pol, 5, &domain_name,
1671 &dom_sid);
1673 if (NT_STATUS_IS_OK(result)) {
1674 if (domain_name)
1675 fstrcpy(domain->name, domain_name);
1677 if (dom_sid)
1678 sid_copy(&domain->sid, dom_sid);
1681 done:
1683 DEBUG(5, ("set_dc_type_and_flags: domain %s is %sin native mode.\n",
1684 domain->name, domain->native_mode ? "" : "NOT "));
1686 DEBUG(5,("set_dc_type_and_flags: domain %s is %srunning active directory.\n",
1687 domain->name, domain->active_directory ? "" : "NOT "));
1689 cli_rpc_pipe_close(cli);
1691 talloc_destroy(mem_ctx);
1693 domain->initialized = True;
1696 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1697 struct dcinfo **ppdc)
1699 NTSTATUS result;
1700 struct rpc_pipe_client *netlogon_pipe;
1702 if (lp_client_schannel() == False) {
1703 return False;
1706 result = cm_connect_netlogon(domain, &netlogon_pipe);
1707 if (!NT_STATUS_IS_OK(result)) {
1708 return False;
1711 /* Return a pointer to the struct dcinfo from the
1712 netlogon pipe. */
1714 *ppdc = domain->conn.netlogon_pipe->dc;
1715 return True;
1718 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1719 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1721 struct winbindd_cm_conn *conn;
1722 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1723 fstring conn_pwd;
1724 struct dcinfo *p_dcinfo;
1725 char *machine_password = NULL;
1726 char *machine_account = NULL;
1727 char *domain_name = NULL;
1729 result = init_dc_connection(domain);
1730 if (!NT_STATUS_IS_OK(result)) {
1731 return result;
1734 conn = &domain->conn;
1736 if (conn->samr_pipe != NULL) {
1737 goto done;
1741 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1742 * sign and sealed pipe using the machine account password by
1743 * preference. If we can't - try schannel, if that fails, try
1744 * anonymous.
1747 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1748 if ((conn->cli->user_name[0] == '\0') ||
1749 (conn->cli->domain[0] == '\0') ||
1750 (conn_pwd[0] == '\0'))
1752 result = get_trust_creds(domain, &machine_password,
1753 &machine_account, NULL);
1754 if (!NT_STATUS_IS_OK(result)) {
1755 DEBUG(10, ("cm_connect_sam: No no user available for "
1756 "domain %s, trying schannel\n", conn->cli->domain));
1757 goto schannel;
1759 domain_name = domain->name;
1760 } else {
1761 machine_password = SMB_STRDUP(conn_pwd);
1762 machine_account = SMB_STRDUP(conn->cli->user_name);
1763 domain_name = conn->cli->domain;
1766 if (!machine_password || !machine_account) {
1767 result = NT_STATUS_NO_MEMORY;
1768 goto done;
1771 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1772 authenticated SAMR pipe with sign & seal. */
1773 conn->samr_pipe =
1774 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1775 PIPE_AUTH_LEVEL_PRIVACY,
1776 domain_name,
1777 machine_account,
1778 machine_password, &result);
1780 if (conn->samr_pipe == NULL) {
1781 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1782 "pipe for domain %s using NTLMSSP "
1783 "authenticated pipe: user %s\\%s. Error was "
1784 "%s\n", domain->name, domain_name,
1785 machine_account, nt_errstr(result)));
1786 goto schannel;
1789 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1790 "domain %s using NTLMSSP authenticated "
1791 "pipe: user %s\\%s\n", domain->name,
1792 domain_name, machine_account));
1794 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1795 SEC_RIGHTS_MAXIMUM_ALLOWED,
1796 &conn->sam_connect_handle);
1797 if (NT_STATUS_IS_OK(result)) {
1798 goto open_domain;
1800 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1801 "failed for domain %s, error was %s. Trying schannel\n",
1802 domain->name, nt_errstr(result) ));
1803 cli_rpc_pipe_close(conn->samr_pipe);
1805 schannel:
1807 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1809 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1810 /* If this call fails - conn->cli can now be NULL ! */
1811 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1812 "for domain %s, trying anon\n", domain->name));
1813 goto anonymous;
1815 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1816 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1817 domain->name, p_dcinfo, &result);
1819 if (conn->samr_pipe == NULL) {
1820 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1821 "domain %s using schannel. Error was %s\n",
1822 domain->name, nt_errstr(result) ));
1823 goto anonymous;
1825 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1826 "schannel.\n", domain->name ));
1828 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1829 SEC_RIGHTS_MAXIMUM_ALLOWED,
1830 &conn->sam_connect_handle);
1831 if (NT_STATUS_IS_OK(result)) {
1832 goto open_domain;
1834 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1835 "for domain %s, error was %s. Trying anonymous\n",
1836 domain->name, nt_errstr(result) ));
1837 cli_rpc_pipe_close(conn->samr_pipe);
1839 anonymous:
1841 /* Finally fall back to anonymous. */
1842 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1843 &result);
1845 if (conn->samr_pipe == NULL) {
1846 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1847 goto done;
1850 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1851 SEC_RIGHTS_MAXIMUM_ALLOWED,
1852 &conn->sam_connect_handle);
1853 if (!NT_STATUS_IS_OK(result)) {
1854 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1855 "for domain %s Error was %s\n",
1856 domain->name, nt_errstr(result) ));
1857 goto done;
1860 open_domain:
1861 result = rpccli_samr_open_domain(conn->samr_pipe,
1862 mem_ctx,
1863 &conn->sam_connect_handle,
1864 SEC_RIGHTS_MAXIMUM_ALLOWED,
1865 &domain->sid,
1866 &conn->sam_domain_handle);
1868 done:
1870 if (!NT_STATUS_IS_OK(result)) {
1871 invalidate_cm_connection(conn);
1872 return result;
1875 *cli = conn->samr_pipe;
1876 *sam_handle = conn->sam_domain_handle;
1877 SAFE_FREE(machine_password);
1878 SAFE_FREE(machine_account);
1879 return result;
1882 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1883 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1885 struct winbindd_cm_conn *conn;
1886 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1887 fstring conn_pwd;
1888 struct dcinfo *p_dcinfo;
1890 result = init_dc_connection(domain);
1891 if (!NT_STATUS_IS_OK(result))
1892 return result;
1894 conn = &domain->conn;
1896 if (conn->lsa_pipe != NULL) {
1897 goto done;
1900 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1901 if ((conn->cli->user_name[0] == '\0') ||
1902 (conn->cli->domain[0] == '\0') ||
1903 (conn_pwd[0] == '\0')) {
1904 DEBUG(10, ("cm_connect_lsa: No no user available for "
1905 "domain %s, trying schannel\n", conn->cli->domain));
1906 goto schannel;
1909 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1910 * authenticated LSA pipe with sign & seal. */
1911 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1912 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1913 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1915 if (conn->lsa_pipe == NULL) {
1916 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1917 "domain %s using NTLMSSP authenticated pipe: user "
1918 "%s\\%s. Error was %s. Trying schannel.\n",
1919 domain->name, conn->cli->domain,
1920 conn->cli->user_name, nt_errstr(result)));
1921 goto schannel;
1924 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1925 "NTLMSSP authenticated pipe: user %s\\%s\n",
1926 domain->name, conn->cli->domain, conn->cli->user_name ));
1928 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1929 SEC_RIGHTS_MAXIMUM_ALLOWED,
1930 &conn->lsa_policy);
1931 if (NT_STATUS_IS_OK(result)) {
1932 goto done;
1935 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1936 "schannel\n"));
1938 cli_rpc_pipe_close(conn->lsa_pipe);
1940 schannel:
1942 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1944 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1945 /* If this call fails - conn->cli can now be NULL ! */
1946 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1947 "for domain %s, trying anon\n", domain->name));
1948 goto anonymous;
1950 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1951 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1952 domain->name, p_dcinfo, &result);
1954 if (conn->lsa_pipe == NULL) {
1955 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1956 "domain %s using schannel. Error was %s\n",
1957 domain->name, nt_errstr(result) ));
1958 goto anonymous;
1960 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1961 "schannel.\n", domain->name ));
1963 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1964 SEC_RIGHTS_MAXIMUM_ALLOWED,
1965 &conn->lsa_policy);
1966 if (NT_STATUS_IS_OK(result)) {
1967 goto done;
1970 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1971 "anonymous\n"));
1973 cli_rpc_pipe_close(conn->lsa_pipe);
1975 anonymous:
1977 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1978 &result);
1979 if (conn->lsa_pipe == NULL) {
1980 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1981 goto done;
1984 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1985 SEC_RIGHTS_MAXIMUM_ALLOWED,
1986 &conn->lsa_policy);
1987 done:
1988 if (!NT_STATUS_IS_OK(result)) {
1989 invalidate_cm_connection(conn);
1990 return result;
1993 *cli = conn->lsa_pipe;
1994 *lsa_policy = conn->lsa_policy;
1995 return result;
1998 /****************************************************************************
1999 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2000 session key stored in conn->netlogon_pipe->dc->sess_key.
2001 ****************************************************************************/
2003 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2004 struct rpc_pipe_client **cli)
2006 struct winbindd_cm_conn *conn;
2007 NTSTATUS result;
2009 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
2010 uint8 mach_pwd[16];
2011 uint32 sec_chan_type;
2012 const char *account_name;
2013 struct rpc_pipe_client *netlogon_pipe = NULL;
2015 *cli = NULL;
2017 result = init_dc_connection(domain);
2018 if (!NT_STATUS_IS_OK(result)) {
2019 return result;
2022 conn = &domain->conn;
2024 if (conn->netlogon_pipe != NULL) {
2025 *cli = conn->netlogon_pipe;
2026 return NT_STATUS_OK;
2029 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
2030 &result);
2031 if (netlogon_pipe == NULL) {
2032 return result;
2035 if ((!IS_DC) && (!domain->primary)) {
2036 /* Clear the schannel request bit and drop down */
2037 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2038 goto no_schannel;
2041 if (lp_client_schannel() != False) {
2042 neg_flags |= NETLOGON_NEG_SCHANNEL;
2045 if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2046 &sec_chan_type))
2048 cli_rpc_pipe_close(netlogon_pipe);
2049 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2052 result = rpccli_netlogon_setup_creds(
2053 netlogon_pipe,
2054 domain->dcname, /* server name. */
2055 domain->name, /* domain name */
2056 global_myname(), /* client name */
2057 account_name, /* machine account */
2058 mach_pwd, /* machine password */
2059 sec_chan_type, /* from get_trust_pw */
2060 &neg_flags);
2062 if (!NT_STATUS_IS_OK(result)) {
2063 cli_rpc_pipe_close(netlogon_pipe);
2064 return result;
2067 if ((lp_client_schannel() == True) &&
2068 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2069 DEBUG(3, ("Server did not offer schannel\n"));
2070 cli_rpc_pipe_close(netlogon_pipe);
2071 return NT_STATUS_ACCESS_DENIED;
2074 no_schannel:
2075 if ((lp_client_schannel() == False) ||
2076 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2077 /* We're done - just keep the existing connection to NETLOGON
2078 * open */
2079 conn->netlogon_pipe = netlogon_pipe;
2080 *cli = conn->netlogon_pipe;
2081 return NT_STATUS_OK;
2084 /* Using the credentials from the first pipe, open a signed and sealed
2085 second netlogon pipe. The session key is stored in the schannel
2086 part of the new pipe auth struct.
2089 conn->netlogon_pipe =
2090 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2091 PI_NETLOGON,
2092 PIPE_AUTH_LEVEL_PRIVACY,
2093 domain->name,
2094 netlogon_pipe->dc,
2095 &result);
2097 /* We can now close the initial netlogon pipe. */
2098 cli_rpc_pipe_close(netlogon_pipe);
2100 if (conn->netlogon_pipe == NULL) {
2101 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2102 "was %s\n", nt_errstr(result)));
2104 /* make sure we return something besides OK */
2105 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2108 *cli = conn->netlogon_pipe;
2109 return NT_STATUS_OK;