r22712: Inform the user when logging in via pam_winbind
[Samba/gbeck.git] / source3 / nsswitch / winbindd_cm.c
blobf7b7410ba236bc7b1cdd9be7d47a3b84ecdeb90d
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 if (domain->check_online_event) {
253 TALLOC_FREE(domain->check_online_event);
256 /* Are we still in "startup" mode ? */
258 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
259 /* No longer in "startup" mode. */
260 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
261 domain->name ));
262 domain->startup = False;
265 /* We've been told to stay offline, so stay
266 that way. */
268 if (get_global_winbindd_state_offline()) {
269 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
270 domain->name ));
271 return;
274 /* Fork a child to test if it can contact a DC.
275 If it can then send ourselves a message to
276 cause a reconnect. */
278 fork_child_dc_connect(domain);
281 /****************************************************************
282 If we're still offline setup the timeout check.
283 ****************************************************************/
285 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
287 int wbc = lp_winbind_cache_time();
289 if (domain->startup) {
290 domain->check_online_timeout = 10;
291 } else if (domain->check_online_timeout < wbc) {
292 domain->check_online_timeout = wbc;
296 /****************************************************************
297 Set domain offline and also add handler to put us back online
298 if we detect a DC.
299 ****************************************************************/
301 void set_domain_offline(struct winbindd_domain *domain)
303 DEBUG(10,("set_domain_offline: called for domain %s\n",
304 domain->name ));
306 if (domain->check_online_event) {
307 TALLOC_FREE(domain->check_online_event);
310 if (domain->internal) {
311 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
312 domain->name ));
313 return;
316 domain->online = False;
318 /* Offline domains are always initialized. They're
319 re-initialized when they go back online. */
321 domain->initialized = True;
323 /* We only add the timeout handler that checks and
324 allows us to go back online when we've not
325 been told to remain offline. */
327 if (get_global_winbindd_state_offline()) {
328 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
329 domain->name ));
330 return;
333 /* If we're in statup mode, check again in 10 seconds, not in
334 lp_winbind_cache_time() seconds (which is 5 mins by default). */
336 calc_new_online_timeout_check(domain);
338 domain->check_online_event = event_add_timed(winbind_event_context(),
339 NULL,
340 timeval_current_ofs(domain->check_online_timeout,0),
341 "check_domain_online_handler",
342 check_domain_online_handler,
343 domain);
345 /* The above *has* to succeed for winbindd to work. */
346 if (!domain->check_online_event) {
347 smb_panic("set_domain_offline: failed to add online handler.\n");
350 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
351 domain->name ));
354 /****************************************************************
355 Set domain online - if allowed.
356 ****************************************************************/
358 static void set_domain_online(struct winbindd_domain *domain)
360 struct timeval now;
362 DEBUG(10,("set_domain_online: called for domain %s\n",
363 domain->name ));
365 if (domain->internal) {
366 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
367 domain->name ));
368 return;
371 if (get_global_winbindd_state_offline()) {
372 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
373 domain->name ));
374 return;
377 /* If we are waiting to get a krb5 ticket, trigger immediately. */
378 GetTimeOfDay(&now);
379 set_event_dispatch_time(winbind_event_context(),
380 "krb5_ticket_gain_handler", now);
382 /* Ok, we're out of any startup mode now... */
383 domain->startup = False;
385 if (domain->online == False) {
386 /* We were offline - now we're online. We default to
387 using the MS-RPC backend if we started offline,
388 and if we're going online for the first time we
389 should really re-initialize the backends and the
390 checks to see if we're talking to an AD or NT domain.
393 domain->initialized = False;
395 /* 'reconnect_methods' is the MS-RPC backend. */
396 if (domain->backend == &reconnect_methods) {
397 domain->backend = NULL;
401 /* Ensure we have no online timeout checks. */
402 domain->check_online_timeout = 0;
403 if (domain->check_online_event) {
404 TALLOC_FREE(domain->check_online_event);
407 /* Ensure we ignore any pending child messages. */
408 message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
409 message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
411 domain->online = True;
414 /****************************************************************
415 Requested to set a domain online.
416 ****************************************************************/
418 void set_domain_online_request(struct winbindd_domain *domain)
420 struct timeval tev;
422 DEBUG(10,("set_domain_online_request: called for domain %s\n",
423 domain->name ));
425 if (get_global_winbindd_state_offline()) {
426 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
427 domain->name ));
428 return;
431 /* We've been told it's safe to go online and
432 try and connect to a DC. But I don't believe it
433 because network manager seems to lie.
434 Wait at least 5 seconds. Heuristics suck... */
436 if (!domain->check_online_event) {
437 /* If we've come from being globally offline we
438 don't have a check online event handler set.
439 We need to add one now we're trying to go
440 back online. */
442 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
443 domain->name ));
445 domain->check_online_event = event_add_timed(winbind_event_context(),
446 NULL,
447 timeval_current_ofs(5, 0),
448 "check_domain_online_handler",
449 check_domain_online_handler,
450 domain);
452 /* The above *has* to succeed for winbindd to work. */
453 if (!domain->check_online_event) {
454 smb_panic("set_domain_online_request: failed to add online handler.\n");
458 GetTimeOfDay(&tev);
460 /* Go into "startup" mode again. */
461 domain->startup_time = tev.tv_sec;
462 domain->startup = True;
464 tev.tv_sec += 5;
466 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
469 /****************************************************************
470 Add -ve connection cache entries for domain and realm.
471 ****************************************************************/
473 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
474 const char *server,
475 NTSTATUS result)
477 add_failed_connection_entry(domain->name, server, result);
478 /* If this was the saf name for the last thing we talked to,
479 remove it. */
480 saf_delete(domain->name);
481 if (*domain->alt_name) {
482 add_failed_connection_entry(domain->alt_name, server, result);
483 saf_delete(domain->alt_name);
487 /* Choose between anonymous or authenticated connections. We need to use
488 an authenticated connection if DCs have the RestrictAnonymous registry
489 entry set > 0, or the "Additional restrictions for anonymous
490 connections" set in the win2k Local Security Policy.
492 Caller to free() result in domain, username, password
495 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
497 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
498 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
499 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
501 if (*username && **username) {
503 if (!*domain || !**domain)
504 *domain = smb_xstrdup(lp_workgroup());
506 if (!*password || !**password)
507 *password = smb_xstrdup("");
509 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
510 *domain, *username));
512 } else {
513 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
514 *username = smb_xstrdup("");
515 *domain = smb_xstrdup("");
516 *password = smb_xstrdup("");
520 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
521 fstring dcname, struct in_addr *dc_ip)
523 struct winbindd_domain *our_domain = NULL;
524 struct rpc_pipe_client *netlogon_pipe = NULL;
525 NTSTATUS result;
526 WERROR werr;
527 TALLOC_CTX *mem_ctx;
528 unsigned int orig_timeout;
529 fstring tmp;
530 char *p;
532 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
533 * moment.... */
535 if (IS_DC) {
536 return False;
539 if (domain->primary) {
540 return False;
543 our_domain = find_our_domain();
545 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
546 return False;
549 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
550 if (!NT_STATUS_IS_OK(result)) {
551 talloc_destroy(mem_ctx);
552 return False;
555 /* This call can take a long time - allow the server to time out.
556 35 seconds should do it. */
558 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
560 werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
561 domain->name, tmp);
563 /* And restore our original timeout. */
564 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
566 talloc_destroy(mem_ctx);
568 if (!W_ERROR_IS_OK(werr)) {
569 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
570 dos_errstr(werr)));
571 return False;
574 /* cli_netlogon_getdcname gives us a name with \\ */
575 p = tmp;
576 if (*p == '\\') {
577 p+=1;
579 if (*p == '\\') {
580 p+=1;
583 fstrcpy(dcname, p);
585 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
587 if (!resolve_name(dcname, dc_ip, 0x20)) {
588 return False;
591 return True;
594 /************************************************************************
595 Given a fd with a just-connected TCP connection to a DC, open a connection
596 to the pipe.
597 ************************************************************************/
599 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
600 const int sockfd,
601 const char *controller,
602 struct cli_state **cli,
603 BOOL *retry)
605 char *machine_password, *machine_krb5_principal, *machine_account;
606 char *ipc_username, *ipc_domain, *ipc_password;
608 BOOL got_mutex;
610 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
612 struct sockaddr peeraddr;
613 socklen_t peeraddr_len;
615 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
617 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
618 controller, domain->name ));
620 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
621 NULL);
623 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
624 SAFE_FREE(machine_password);
625 return NT_STATUS_NO_MEMORY;
628 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
629 lp_realm()) == -1) {
630 SAFE_FREE(machine_account);
631 SAFE_FREE(machine_password);
632 return NT_STATUS_NO_MEMORY;
635 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
637 *retry = True;
639 got_mutex = secrets_named_mutex(controller,
640 WINBIND_SERVER_MUTEX_WAIT_TIME);
642 if (!got_mutex) {
643 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
644 controller));
645 result = NT_STATUS_POSSIBLE_DEADLOCK;
646 goto done;
649 if ((*cli = cli_initialise()) == NULL) {
650 DEBUG(1, ("Could not cli_initialize\n"));
651 result = NT_STATUS_NO_MEMORY;
652 goto done;
655 (*cli)->timeout = 10000; /* 10 seconds */
656 (*cli)->fd = sockfd;
657 fstrcpy((*cli)->desthost, controller);
658 (*cli)->use_kerberos = True;
660 peeraddr_len = sizeof(peeraddr);
662 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
663 (peeraddr_len != sizeof(struct sockaddr_in)) ||
664 (peeraddr_in->sin_family != PF_INET))
666 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
667 result = NT_STATUS_UNSUCCESSFUL;
668 goto done;
671 if (ntohs(peeraddr_in->sin_port) == 139) {
672 struct nmb_name calling;
673 struct nmb_name called;
675 make_nmb_name(&calling, global_myname(), 0x0);
676 make_nmb_name(&called, "*SMBSERVER", 0x20);
678 if (!cli_session_request(*cli, &calling, &called)) {
679 DEBUG(8, ("cli_session_request failed for %s\n",
680 controller));
681 result = NT_STATUS_UNSUCCESSFUL;
682 goto done;
686 cli_setup_signing_state(*cli, Undefined);
688 if (!cli_negprot(*cli)) {
689 DEBUG(1, ("cli_negprot failed\n"));
690 result = NT_STATUS_UNSUCCESSFUL;
691 goto done;
694 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
695 ADS_STATUS ads_status;
697 if (lp_security() == SEC_ADS) {
699 /* Try a krb5 session */
701 (*cli)->use_kerberos = True;
702 DEBUG(5, ("connecting to %s from %s with kerberos principal "
703 "[%s]\n", controller, global_myname(),
704 machine_krb5_principal));
706 ads_status = cli_session_setup_spnego(*cli,
707 machine_krb5_principal,
708 machine_password,
709 lp_workgroup());
711 if (!ADS_ERR_OK(ads_status)) {
712 DEBUG(4,("failed kerberos session setup with %s\n",
713 ads_errstr(ads_status)));
716 result = ads_ntstatus(ads_status);
717 if (NT_STATUS_IS_OK(result)) {
718 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
719 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
720 goto session_setup_done;
724 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
725 (*cli)->use_kerberos = False;
727 DEBUG(5, ("connecting to %s from %s with username "
728 "[%s]\\[%s]\n", controller, global_myname(),
729 lp_workgroup(), machine_account));
731 ads_status = cli_session_setup_spnego(*cli,
732 machine_account,
733 machine_password,
734 lp_workgroup());
735 if (!ADS_ERR_OK(ads_status)) {
736 DEBUG(4, ("authenticated session setup failed with %s\n",
737 ads_errstr(ads_status)));
740 result = ads_ntstatus(ads_status);
741 if (NT_STATUS_IS_OK(result)) {
742 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
743 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
744 goto session_setup_done;
748 /* Fall back to non-kerberos session setup */
750 (*cli)->use_kerberos = False;
752 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
753 (strlen(ipc_username) > 0)) {
755 /* Only try authenticated if we have a username */
757 DEBUG(5, ("connecting to %s from %s with username "
758 "[%s]\\[%s]\n", controller, global_myname(),
759 ipc_domain, ipc_username));
761 if (NT_STATUS_IS_OK(cli_session_setup(
762 *cli, ipc_username,
763 ipc_password, strlen(ipc_password)+1,
764 ipc_password, strlen(ipc_password)+1,
765 ipc_domain))) {
766 /* Successful logon with given username. */
767 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
768 goto session_setup_done;
769 } else {
770 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
771 ipc_domain, ipc_username ));
775 /* Fall back to anonymous connection, this might fail later */
777 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
778 NULL, 0, ""))) {
779 DEBUG(5, ("Connected anonymously\n"));
780 cli_init_creds(*cli, "", "", "");
781 goto session_setup_done;
784 result = cli_nt_error(*cli);
786 if (NT_STATUS_IS_OK(result))
787 result = NT_STATUS_UNSUCCESSFUL;
789 /* We can't session setup */
791 goto done;
793 session_setup_done:
795 /* cache the server name for later connections */
797 saf_store( domain->name, (*cli)->desthost );
798 if (domain->alt_name && (*cli)->use_kerberos) {
799 saf_store( domain->alt_name, (*cli)->desthost );
802 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
804 result = cli_nt_error(*cli);
806 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
808 if (NT_STATUS_IS_OK(result))
809 result = NT_STATUS_UNSUCCESSFUL;
811 goto done;
814 secrets_named_mutex_release(controller);
815 got_mutex = False;
816 *retry = False;
818 /* set the domain if empty; needed for schannel connections */
819 if ( !*(*cli)->domain ) {
820 fstrcpy( (*cli)->domain, domain->name );
823 result = NT_STATUS_OK;
825 done:
826 if (got_mutex) {
827 secrets_named_mutex_release(controller);
830 SAFE_FREE(machine_account);
831 SAFE_FREE(machine_password);
832 SAFE_FREE(machine_krb5_principal);
833 SAFE_FREE(ipc_username);
834 SAFE_FREE(ipc_domain);
835 SAFE_FREE(ipc_password);
837 if (!NT_STATUS_IS_OK(result)) {
838 winbind_add_failed_connection_entry(domain, controller, result);
839 if ((*cli) != NULL) {
840 cli_shutdown(*cli);
841 *cli = NULL;
845 return result;
848 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
849 const char *dcname, struct in_addr ip,
850 struct dc_name_ip **dcs, int *num)
852 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
853 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
854 return False;
857 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
859 if (*dcs == NULL)
860 return False;
862 fstrcpy((*dcs)[*num].name, dcname);
863 (*dcs)[*num].ip = ip;
864 *num += 1;
865 return True;
868 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
869 struct in_addr ip, uint16 port,
870 struct sockaddr_in **addrs, int *num)
872 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
874 if (*addrs == NULL) {
875 *num = 0;
876 return False;
879 (*addrs)[*num].sin_family = PF_INET;
880 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
881 (*addrs)[*num].sin_port = htons(port);
883 *num += 1;
884 return True;
887 static void mailslot_name(struct in_addr dc_ip, fstring name)
889 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
892 static BOOL send_getdc_request(struct in_addr dc_ip,
893 const char *domain_name,
894 const DOM_SID *sid)
896 pstring outbuf;
897 char *p;
898 fstring my_acct_name;
899 fstring my_mailslot;
901 mailslot_name(dc_ip, my_mailslot);
903 memset(outbuf, '\0', sizeof(outbuf));
905 p = outbuf;
907 SCVAL(p, 0, SAMLOGON);
908 p++;
910 SCVAL(p, 0, 0); /* Count pointer ... */
911 p++;
913 SIVAL(p, 0, 0); /* The sender's token ... */
914 p += 2;
916 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
917 fstr_sprintf(my_acct_name, "%s$", global_myname());
918 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
920 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
921 p += strlen(my_mailslot)+1;
923 SIVAL(p, 0, 0x80);
924 p+=4;
926 SIVAL(p, 0, sid_size(sid));
927 p+=4;
929 p = ALIGN4(p, outbuf);
931 sid_linearize(p, sid_size(sid), sid);
932 p += sid_size(sid);
934 SIVAL(p, 0, 1);
935 SSVAL(p, 4, 0xffff);
936 SSVAL(p, 6, 0xffff);
937 p+=8;
939 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
940 outbuf, PTR_DIFF(p, outbuf),
941 global_myname(), 0, domain_name, 0x1c,
942 dc_ip);
945 static BOOL receive_getdc_response(struct in_addr dc_ip,
946 const char *domain_name,
947 fstring dc_name)
949 struct packet_struct *packet;
950 fstring my_mailslot;
951 char *buf, *p;
952 fstring dcname, user, domain;
953 int len;
955 mailslot_name(dc_ip, my_mailslot);
957 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
959 if (packet == NULL) {
960 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
961 return False;
964 DEBUG(5, ("Received packet for %s\n", my_mailslot));
966 buf = packet->packet.dgram.data;
967 len = packet->packet.dgram.datasize;
969 if (len < 70) {
970 /* 70 is a completely arbitrary value to make sure
971 the SVAL below does not read uninitialized memory */
972 DEBUG(3, ("GetDC got short response\n"));
973 return False;
976 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
977 p = buf+SVAL(buf, smb_vwv10);
979 if (CVAL(p,0) != SAMLOGON_R) {
980 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
981 return False;
984 p+=2;
985 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
986 STR_TERMINATE|STR_NOALIGN);
987 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
988 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
989 STR_TERMINATE|STR_NOALIGN);
990 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
991 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
992 STR_TERMINATE|STR_NOALIGN);
993 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
995 if (!strequal(domain, domain_name)) {
996 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
997 domain_name, domain));
998 return False;
1001 p = dcname;
1002 if (*p == '\\') p += 1;
1003 if (*p == '\\') p += 1;
1005 fstrcpy(dc_name, p);
1007 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1008 dc_name, domain));
1010 return True;
1013 /*******************************************************************
1014 convert an ip to a name
1015 *******************************************************************/
1017 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1019 struct ip_service ip_list;
1021 ip_list.ip = ip;
1022 ip_list.port = 0;
1024 #ifdef WITH_ADS
1025 /* For active directory servers, try to get the ldap server name.
1026 None of these failures should be considered critical for now */
1028 if (lp_security() == SEC_ADS) {
1029 ADS_STRUCT *ads;
1031 ads = ads_init(domain->alt_name, domain->name, NULL);
1032 ads->auth.flags |= ADS_AUTH_NO_BIND;
1034 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1035 /* We got a cldap packet. */
1036 fstrcpy(name, ads->config.ldap_server_name);
1037 namecache_store(name, 0x20, 1, &ip_list);
1039 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1041 if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
1042 char *sitename = sitename_fetch(ads->config.realm);
1044 /* We're going to use this KDC for this realm/domain.
1045 If we are using sites, then force the krb5 libs
1046 to use this KDC. */
1048 create_local_private_krb5_conf_for_domain(domain->alt_name,
1049 domain->name,
1050 sitename,
1051 ip);
1053 SAFE_FREE(sitename);
1054 /* Ensure we contact this DC also. */
1055 saf_store( domain->name, name);
1056 saf_store( domain->alt_name, name);
1059 ads_destroy( &ads );
1060 return True;
1063 ads_destroy( &ads );
1065 #endif
1067 /* try GETDC requests next */
1069 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1070 int i;
1071 smb_msleep(100);
1072 for (i=0; i<5; i++) {
1073 if (receive_getdc_response(ip, domain->name, name)) {
1074 namecache_store(name, 0x20, 1, &ip_list);
1075 return True;
1077 smb_msleep(500);
1081 /* try node status request */
1083 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1084 namecache_store(name, 0x20, 1, &ip_list);
1085 return True;
1087 return False;
1090 /*******************************************************************
1091 Retreive a list of IP address for domain controllers. Fill in
1092 the dcs[] with results.
1093 *******************************************************************/
1095 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1096 struct dc_name_ip **dcs, int *num_dcs)
1098 fstring dcname;
1099 struct in_addr ip;
1100 struct ip_service *ip_list = NULL;
1101 int iplist_size = 0;
1102 int i;
1103 BOOL is_our_domain;
1104 enum security_types sec = (enum security_types)lp_security();
1106 is_our_domain = strequal(domain->name, lp_workgroup());
1108 if ( !is_our_domain
1109 && get_dc_name_via_netlogon(domain, dcname, &ip)
1110 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1112 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1113 dcname, inet_ntoa(ip)));
1114 return True;
1117 if (sec == SEC_ADS) {
1118 char *sitename = NULL;
1120 /* We need to make sure we know the local site before
1121 doing any DNS queries, as this will restrict the
1122 get_sorted_dc_list() call below to only fetching
1123 DNS records for the correct site. */
1125 /* Find any DC to get the site record.
1126 We deliberately don't care about the
1127 return here. */
1129 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
1131 sitename = sitename_fetch(domain->alt_name);
1132 if (sitename) {
1134 /* Do the site-specific AD dns lookup first. */
1135 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1137 for ( i=0; i<iplist_size; i++ ) {
1138 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1139 ip_list[i].ip, dcs, num_dcs);
1142 SAFE_FREE(ip_list);
1143 SAFE_FREE(sitename);
1144 iplist_size = 0;
1147 /* Now we add DCs from the main AD dns lookup. */
1148 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1150 for ( i=0; i<iplist_size; i++ ) {
1151 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1152 ip_list[i].ip, dcs, num_dcs);
1156 /* try standard netbios queries if no ADS */
1158 if (iplist_size==0) {
1159 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1162 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1164 /* now add to the dc array. We'll wait until the last minute
1165 to look up the name of the DC. But we fill in the char* for
1166 the ip now in to make the failed connection cache work */
1168 for ( i=0; i<iplist_size; i++ ) {
1169 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1170 ip_list[i].ip, dcs, num_dcs);
1173 SAFE_FREE( ip_list );
1175 return True;
1178 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1179 const struct winbindd_domain *domain,
1180 fstring dcname, struct sockaddr_in *addr, int *fd)
1182 struct dc_name_ip *dcs = NULL;
1183 int num_dcs = 0;
1185 const char **dcnames = NULL;
1186 int num_dcnames = 0;
1188 struct sockaddr_in *addrs = NULL;
1189 int num_addrs = 0;
1191 int i, fd_index;
1193 again:
1194 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1195 return False;
1197 for (i=0; i<num_dcs; i++) {
1199 if (!add_string_to_array(mem_ctx, dcs[i].name,
1200 &dcnames, &num_dcnames)) {
1201 return False;
1203 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1204 &addrs, &num_addrs)) {
1205 return False;
1208 if (!add_string_to_array(mem_ctx, dcs[i].name,
1209 &dcnames, &num_dcnames)) {
1210 return False;
1212 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1213 &addrs, &num_addrs)) {
1214 return False;
1218 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1219 return False;
1221 if ((addrs == NULL) || (dcnames == NULL))
1222 return False;
1224 /* 5 second timeout. */
1225 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1227 for (i=0; i<num_dcs; i++) {
1228 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1229 "domain %s address %s. Error was %s\n",
1230 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1231 winbind_add_failed_connection_entry(domain,
1232 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1234 return False;
1237 *addr = addrs[fd_index];
1239 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1240 /* Ok, we've got a name for the DC */
1241 fstrcpy(dcname, dcnames[fd_index]);
1242 return True;
1245 /* Try to figure out the name */
1246 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1247 return True;
1250 /* We can not continue without the DC's name */
1251 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1252 NT_STATUS_UNSUCCESSFUL);
1253 goto again;
1256 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1257 struct winbindd_cm_conn *new_conn)
1259 TALLOC_CTX *mem_ctx;
1260 NTSTATUS result;
1261 char *saf_servername = saf_fetch( domain->name );
1262 int retries;
1264 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1265 SAFE_FREE(saf_servername);
1266 set_domain_offline(domain);
1267 return NT_STATUS_NO_MEMORY;
1270 /* we have to check the server affinity cache here since
1271 later we selecte a DC based on response time and not preference */
1273 /* Check the negative connection cache
1274 before talking to it. It going down may have
1275 triggered the reconnection. */
1277 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1279 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1280 saf_servername, domain->name ));
1282 /* convert an ip address to a name */
1283 if ( is_ipaddress( saf_servername ) ) {
1284 fstring saf_name;
1285 struct in_addr ip;
1287 ip = *interpret_addr2( saf_servername );
1288 if (dcip_to_name( domain, ip, saf_name )) {
1289 fstrcpy( domain->dcname, saf_name );
1290 } else {
1291 winbind_add_failed_connection_entry(
1292 domain, saf_servername,
1293 NT_STATUS_UNSUCCESSFUL);
1295 } else {
1296 fstrcpy( domain->dcname, saf_servername );
1299 SAFE_FREE( saf_servername );
1302 for (retries = 0; retries < 3; retries++) {
1304 int fd = -1;
1305 BOOL retry = False;
1307 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1309 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1310 domain->dcname, domain->name ));
1312 if (*domain->dcname
1313 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1314 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1316 struct sockaddr_in *addrs = NULL;
1317 int num_addrs = 0;
1318 int dummy = 0;
1320 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1321 set_domain_offline(domain);
1322 talloc_destroy(mem_ctx);
1323 return NT_STATUS_NO_MEMORY;
1325 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1326 set_domain_offline(domain);
1327 talloc_destroy(mem_ctx);
1328 return NT_STATUS_NO_MEMORY;
1331 /* 5 second timeout. */
1332 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1333 fd = -1;
1337 if ((fd == -1)
1338 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1340 /* This is the one place where we will
1341 set the global winbindd offline state
1342 to true, if a "WINBINDD_OFFLINE" entry
1343 is found in the winbindd cache. */
1344 set_global_winbindd_state_offline();
1345 break;
1348 new_conn->cli = NULL;
1350 result = cm_prepare_connection(domain, fd, domain->dcname,
1351 &new_conn->cli, &retry);
1353 if (!retry)
1354 break;
1357 if (NT_STATUS_IS_OK(result)) {
1358 if (domain->online == False) {
1359 /* We're changing state from offline to online. */
1360 set_global_winbindd_state_online();
1362 set_domain_online(domain);
1363 } else {
1364 /* Ensure we setup the retry handler. */
1365 set_domain_offline(domain);
1368 talloc_destroy(mem_ctx);
1369 return result;
1372 /* Close down all open pipes on a connection. */
1374 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1376 /* We're closing down a possibly dead
1377 connection. Don't have impossibly long (10s) timeouts. */
1379 if (conn->cli) {
1380 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1383 if (conn->samr_pipe != NULL) {
1384 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1385 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1386 if (conn->cli) {
1387 cli_set_timeout(conn->cli, 500);
1390 conn->samr_pipe = NULL;
1393 if (conn->lsa_pipe != NULL) {
1394 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1395 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1396 if (conn->cli) {
1397 cli_set_timeout(conn->cli, 500);
1400 conn->lsa_pipe = NULL;
1403 if (conn->netlogon_pipe != NULL) {
1404 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1405 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1406 if (conn->cli) {
1407 cli_set_timeout(conn->cli, 500);
1410 conn->netlogon_pipe = NULL;
1413 if (conn->cli) {
1414 cli_shutdown(conn->cli);
1417 conn->cli = NULL;
1420 void close_conns_after_fork(void)
1422 struct winbindd_domain *domain;
1424 for (domain = domain_list(); domain; domain = domain->next) {
1425 if (domain->conn.cli == NULL)
1426 continue;
1428 if (domain->conn.cli->fd == -1)
1429 continue;
1431 close(domain->conn.cli->fd);
1432 domain->conn.cli->fd = -1;
1436 static BOOL connection_ok(struct winbindd_domain *domain)
1438 if (domain->conn.cli == NULL) {
1439 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1440 "cli!\n", domain->dcname, domain->name));
1441 return False;
1444 if (!domain->conn.cli->initialised) {
1445 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1446 "initialised!\n", domain->dcname, domain->name));
1447 return False;
1450 if (domain->conn.cli->fd == -1) {
1451 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1452 "never started (fd == -1)\n",
1453 domain->dcname, domain->name));
1454 return False;
1457 if (domain->online == False) {
1458 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1459 return False;
1462 return True;
1465 /* Initialize a new connection up to the RPC BIND.
1466 Bypass online status check so always does network calls. */
1468 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1470 NTSTATUS result;
1472 /* Internal connections never use the network. */
1473 if (domain->internal) {
1474 domain->initialized = True;
1475 return NT_STATUS_OK;
1478 if (connection_ok(domain)) {
1479 if (!domain->initialized) {
1480 set_dc_type_and_flags(domain);
1482 return NT_STATUS_OK;
1485 invalidate_cm_connection(&domain->conn);
1487 result = cm_open_connection(domain, &domain->conn);
1489 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1490 set_dc_type_and_flags(domain);
1493 return result;
1496 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1498 if (domain->initialized && !domain->online) {
1499 /* We check for online status elsewhere. */
1500 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1503 return init_dc_connection_network(domain);
1506 /******************************************************************************
1507 Set the trust flags (direction and forest location) for a domain
1508 ******************************************************************************/
1510 static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1512 struct winbindd_domain *our_domain;
1513 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1514 struct ds_domain_trust *domains = NULL;
1515 int count = 0;
1516 int i;
1517 uint32 flags = (DS_DOMAIN_IN_FOREST |
1518 DS_DOMAIN_DIRECT_OUTBOUND |
1519 DS_DOMAIN_DIRECT_INBOUND);
1520 struct rpc_pipe_client *cli;
1521 TALLOC_CTX *mem_ctx = NULL;
1523 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1525 /* Our primary domain doesn't need to worry about trust flags.
1526 Force it to go through the network setup */
1527 if ( domain->primary ) {
1528 return False;
1531 our_domain = find_our_domain();
1533 if ( !connection_ok(our_domain) ) {
1534 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1535 return False;
1538 /* This won't work unless our domain is AD */
1540 if ( !our_domain->active_directory ) {
1541 return False;
1544 /* Use DsEnumerateDomainTrusts to get us the trust direction
1545 and type */
1547 result = cm_connect_netlogon(our_domain, &cli);
1549 if (!NT_STATUS_IS_OK(result)) {
1550 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1551 "a connection to %s for PIPE_NETLOGON (%s)\n",
1552 domain->name, nt_errstr(result)));
1553 return False;
1556 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1557 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1558 return False;
1561 result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
1562 cli->cli->desthost,
1563 flags, &domains,
1564 (unsigned int *)&count);
1566 /* Now find the domain name and get the flags */
1568 for ( i=0; i<count; i++ ) {
1569 if ( strequal( domain->name, domains[i].netbios_domain ) ) {
1570 domain->domain_flags = domains[i].flags;
1571 domain->domain_type = domains[i].trust_type;
1572 domain->domain_trust_attribs = domains[i].trust_attributes;
1574 if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
1575 domain->active_directory = True;
1577 /* This flag is only set if the domain is *our*
1578 primary domain and the primary domain is in
1579 native mode */
1581 domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
1583 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1584 "native mode.\n", domain->name,
1585 domain->native_mode ? "" : "NOT "));
1587 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1588 "running active directory.\n", domain->name,
1589 domain->active_directory ? "" : "NOT "));
1592 domain->initialized = True;
1594 if ( !winbindd_can_contact_domain( domain) )
1595 domain->internal = True;
1597 break;
1601 talloc_destroy( mem_ctx );
1603 return domain->initialized;
1606 /******************************************************************************
1607 We can 'sense' certain things about the DC by it's replies to certain
1608 questions.
1610 This tells us if this particular remote server is Active Directory, and if it
1611 is native mode.
1612 ******************************************************************************/
1614 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1616 NTSTATUS result;
1617 DS_DOMINFO_CTR ctr;
1618 TALLOC_CTX *mem_ctx = NULL;
1619 struct rpc_pipe_client *cli;
1620 POLICY_HND pol;
1622 char *domain_name = NULL;
1623 char *dns_name = NULL;
1624 char *forest_name = NULL;
1625 DOM_SID *dom_sid = NULL;
1627 ZERO_STRUCT( ctr );
1629 if (!connection_ok(domain)) {
1630 return;
1633 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1635 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1636 &result);
1638 if (cli == NULL) {
1639 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1640 "PI_LSARPC_DS on domain %s: (%s)\n",
1641 domain->name, nt_errstr(result)));
1643 /* if this is just a non-AD domain we need to continue
1644 * identifying so that we can in the end return with
1645 * domain->initialized = True - gd */
1647 goto no_lsarpc_ds;
1650 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1651 DsRolePrimaryDomainInfoBasic,
1652 &ctr);
1653 cli_rpc_pipe_close(cli);
1655 if (!NT_STATUS_IS_OK(result)) {
1656 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1657 "on domain %s failed: (%s)\n",
1658 domain->name, nt_errstr(result)));
1659 return;
1662 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1663 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1664 domain->native_mode = True;
1665 } else {
1666 domain->native_mode = False;
1669 no_lsarpc_ds:
1670 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1672 if (cli == NULL) {
1673 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1674 "PI_LSARPC on domain %s: (%s)\n",
1675 domain->name, nt_errstr(result)));
1676 cli_rpc_pipe_close(cli);
1677 return;
1680 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1681 domain->name);
1682 if (!mem_ctx) {
1683 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1684 cli_rpc_pipe_close(cli);
1685 return;
1688 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1689 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1691 if (NT_STATUS_IS_OK(result)) {
1692 /* This particular query is exactly what Win2k clients use
1693 to determine that the DC is active directory */
1694 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1695 12, &domain_name,
1696 &dns_name, &forest_name,
1697 NULL, &dom_sid);
1700 if (NT_STATUS_IS_OK(result)) {
1701 domain->active_directory = True;
1703 if (domain_name)
1704 fstrcpy(domain->name, domain_name);
1706 if (dns_name)
1707 fstrcpy(domain->alt_name, dns_name);
1709 if ( forest_name )
1710 fstrcpy(domain->forest_name, forest_name);
1712 if (dom_sid)
1713 sid_copy(&domain->sid, dom_sid);
1714 } else {
1715 domain->active_directory = False;
1717 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1718 SEC_RIGHTS_MAXIMUM_ALLOWED,
1719 &pol);
1721 if (!NT_STATUS_IS_OK(result))
1722 goto done;
1724 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1725 &pol, 5, &domain_name,
1726 &dom_sid);
1728 if (NT_STATUS_IS_OK(result)) {
1729 if (domain_name)
1730 fstrcpy(domain->name, domain_name);
1732 if (dom_sid)
1733 sid_copy(&domain->sid, dom_sid);
1736 done:
1738 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1739 domain->name, domain->native_mode ? "" : "NOT "));
1741 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1742 domain->name, domain->active_directory ? "" : "NOT "));
1744 cli_rpc_pipe_close(cli);
1746 talloc_destroy(mem_ctx);
1748 domain->initialized = True;
1751 /**********************************************************************
1752 Set the domain_flags (trust attributes, domain operating modes, etc...
1753 ***********************************************************************/
1755 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1757 /* we always have to contact our primary domain */
1759 if ( domain->primary ) {
1760 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1761 "primary domain\n"));
1762 set_dc_type_and_flags_connect( domain );
1763 return;
1766 /* Use our DC to get the information if possible */
1768 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1769 /* Otherwise, fallback to contacting the
1770 domain directly */
1771 set_dc_type_and_flags_connect( domain );
1774 return;
1779 /**********************************************************************
1780 ***********************************************************************/
1782 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1783 struct dcinfo **ppdc)
1785 NTSTATUS result;
1786 struct rpc_pipe_client *netlogon_pipe;
1788 if (lp_client_schannel() == False) {
1789 return False;
1792 result = cm_connect_netlogon(domain, &netlogon_pipe);
1793 if (!NT_STATUS_IS_OK(result)) {
1794 return False;
1797 /* Return a pointer to the struct dcinfo from the
1798 netlogon pipe. */
1800 *ppdc = domain->conn.netlogon_pipe->dc;
1801 return True;
1804 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1805 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1807 struct winbindd_cm_conn *conn;
1808 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1809 fstring conn_pwd;
1810 struct dcinfo *p_dcinfo;
1812 result = init_dc_connection(domain);
1813 if (!NT_STATUS_IS_OK(result)) {
1814 return result;
1817 conn = &domain->conn;
1819 if (conn->samr_pipe != NULL) {
1820 goto done;
1824 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1825 * sign and sealed pipe using the machine account password by
1826 * preference. If we can't - try schannel, if that fails, try
1827 * anonymous.
1830 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1831 if ((conn->cli->user_name[0] == '\0') ||
1832 (conn->cli->domain[0] == '\0') ||
1833 (conn_pwd[0] == '\0')) {
1834 DEBUG(10, ("cm_connect_sam: No no user available for "
1835 "domain %s, trying schannel\n", conn->cli->domain));
1836 goto schannel;
1839 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1840 authenticated SAMR pipe with sign & seal. */
1841 conn->samr_pipe =
1842 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1843 PIPE_AUTH_LEVEL_PRIVACY,
1844 conn->cli->domain,
1845 conn->cli->user_name,
1846 conn_pwd, &result);
1848 if (conn->samr_pipe == NULL) {
1849 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1850 "pipe for domain %s using NTLMSSP "
1851 "authenticated pipe: user %s\\%s. Error was "
1852 "%s\n", domain->name, conn->cli->domain,
1853 conn->cli->user_name, nt_errstr(result)));
1854 goto schannel;
1857 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1858 "domain %s using NTLMSSP authenticated "
1859 "pipe: user %s\\%s\n", domain->name,
1860 conn->cli->domain, conn->cli->user_name ));
1862 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1863 SEC_RIGHTS_MAXIMUM_ALLOWED,
1864 &conn->sam_connect_handle);
1865 if (NT_STATUS_IS_OK(result)) {
1866 goto open_domain;
1868 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1869 "failed for domain %s, error was %s. Trying schannel\n",
1870 domain->name, nt_errstr(result) ));
1871 cli_rpc_pipe_close(conn->samr_pipe);
1873 schannel:
1875 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1877 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1878 /* If this call fails - conn->cli can now be NULL ! */
1879 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1880 "for domain %s, trying anon\n", domain->name));
1881 goto anonymous;
1883 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1884 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1885 domain->name, p_dcinfo, &result);
1887 if (conn->samr_pipe == NULL) {
1888 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1889 "domain %s using schannel. Error was %s\n",
1890 domain->name, nt_errstr(result) ));
1891 goto anonymous;
1893 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1894 "schannel.\n", domain->name ));
1896 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1897 SEC_RIGHTS_MAXIMUM_ALLOWED,
1898 &conn->sam_connect_handle);
1899 if (NT_STATUS_IS_OK(result)) {
1900 goto open_domain;
1902 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1903 "for domain %s, error was %s. Trying anonymous\n",
1904 domain->name, nt_errstr(result) ));
1905 cli_rpc_pipe_close(conn->samr_pipe);
1907 anonymous:
1909 /* Finally fall back to anonymous. */
1910 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1911 &result);
1913 if (conn->samr_pipe == NULL) {
1914 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1915 goto done;
1918 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1919 SEC_RIGHTS_MAXIMUM_ALLOWED,
1920 &conn->sam_connect_handle);
1921 if (!NT_STATUS_IS_OK(result)) {
1922 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1923 "for domain %s Error was %s\n",
1924 domain->name, nt_errstr(result) ));
1925 goto done;
1928 open_domain:
1929 result = rpccli_samr_open_domain(conn->samr_pipe,
1930 mem_ctx,
1931 &conn->sam_connect_handle,
1932 SEC_RIGHTS_MAXIMUM_ALLOWED,
1933 &domain->sid,
1934 &conn->sam_domain_handle);
1936 done:
1938 if (!NT_STATUS_IS_OK(result)) {
1939 invalidate_cm_connection(conn);
1940 return result;
1943 *cli = conn->samr_pipe;
1944 *sam_handle = conn->sam_domain_handle;
1945 return result;
1948 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1949 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1951 struct winbindd_cm_conn *conn;
1952 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1953 fstring conn_pwd;
1954 struct dcinfo *p_dcinfo;
1956 result = init_dc_connection(domain);
1957 if (!NT_STATUS_IS_OK(result))
1958 return result;
1960 conn = &domain->conn;
1962 if (conn->lsa_pipe != NULL) {
1963 goto done;
1966 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1967 if ((conn->cli->user_name[0] == '\0') ||
1968 (conn->cli->domain[0] == '\0') ||
1969 (conn_pwd[0] == '\0')) {
1970 DEBUG(10, ("cm_connect_lsa: No no user available for "
1971 "domain %s, trying schannel\n", conn->cli->domain));
1972 goto schannel;
1975 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1976 * authenticated LSA pipe with sign & seal. */
1977 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1978 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1979 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1981 if (conn->lsa_pipe == NULL) {
1982 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1983 "domain %s using NTLMSSP authenticated pipe: user "
1984 "%s\\%s. Error was %s. Trying schannel.\n",
1985 domain->name, conn->cli->domain,
1986 conn->cli->user_name, nt_errstr(result)));
1987 goto schannel;
1990 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1991 "NTLMSSP authenticated pipe: user %s\\%s\n",
1992 domain->name, conn->cli->domain, conn->cli->user_name ));
1994 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1995 SEC_RIGHTS_MAXIMUM_ALLOWED,
1996 &conn->lsa_policy);
1997 if (NT_STATUS_IS_OK(result)) {
1998 goto done;
2001 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2002 "schannel\n"));
2004 cli_rpc_pipe_close(conn->lsa_pipe);
2006 schannel:
2008 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2010 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2011 /* If this call fails - conn->cli can now be NULL ! */
2012 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2013 "for domain %s, trying anon\n", domain->name));
2014 goto anonymous;
2016 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
2017 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2018 domain->name, p_dcinfo, &result);
2020 if (conn->lsa_pipe == NULL) {
2021 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2022 "domain %s using schannel. Error was %s\n",
2023 domain->name, nt_errstr(result) ));
2024 goto anonymous;
2026 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2027 "schannel.\n", domain->name ));
2029 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2030 SEC_RIGHTS_MAXIMUM_ALLOWED,
2031 &conn->lsa_policy);
2032 if (NT_STATUS_IS_OK(result)) {
2033 goto done;
2036 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2037 "anonymous\n"));
2039 cli_rpc_pipe_close(conn->lsa_pipe);
2041 anonymous:
2043 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
2044 &result);
2045 if (conn->lsa_pipe == NULL) {
2046 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2047 goto done;
2050 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2051 SEC_RIGHTS_MAXIMUM_ALLOWED,
2052 &conn->lsa_policy);
2053 done:
2054 if (!NT_STATUS_IS_OK(result)) {
2055 invalidate_cm_connection(conn);
2056 return result;
2059 *cli = conn->lsa_pipe;
2060 *lsa_policy = conn->lsa_policy;
2061 return result;
2064 /****************************************************************************
2065 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2066 session key stored in conn->netlogon_pipe->dc->sess_key.
2067 ****************************************************************************/
2069 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2070 struct rpc_pipe_client **cli)
2072 struct winbindd_cm_conn *conn;
2073 NTSTATUS result;
2075 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
2076 uint8 mach_pwd[16];
2077 uint32 sec_chan_type;
2078 const char *account_name;
2079 struct rpc_pipe_client *netlogon_pipe = NULL;
2081 *cli = NULL;
2083 result = init_dc_connection(domain);
2084 if (!NT_STATUS_IS_OK(result)) {
2085 return result;
2088 conn = &domain->conn;
2090 if (conn->netlogon_pipe != NULL) {
2091 *cli = conn->netlogon_pipe;
2092 return NT_STATUS_OK;
2095 if (domain->primary && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
2096 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2099 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
2100 &result);
2101 if (netlogon_pipe == NULL) {
2102 return result;
2105 if ( !domain->primary ) {
2106 /* Clear the schannel request bit and drop down */
2107 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2108 goto no_schannel;
2111 if (lp_client_schannel() != False) {
2112 neg_flags |= NETLOGON_NEG_SCHANNEL;
2115 /* if we are a DC and this is a trusted domain, then we need to use our
2116 domain name in the net_req_auth2() request */
2118 if ( IS_DC
2119 && !strequal(domain->name, lp_workgroup())
2120 && lp_allow_trusted_domains() )
2122 account_name = lp_workgroup();
2123 } else {
2124 account_name = domain->primary ?
2125 global_myname() : domain->name;
2128 if (account_name == NULL) {
2129 cli_rpc_pipe_close(netlogon_pipe);
2130 return NT_STATUS_NO_MEMORY;
2133 result = rpccli_netlogon_setup_creds(
2134 netlogon_pipe,
2135 domain->dcname, /* server name. */
2136 domain->name, /* domain name */
2137 global_myname(), /* client name */
2138 account_name, /* machine account */
2139 mach_pwd, /* machine password */
2140 sec_chan_type, /* from get_trust_pw */
2141 &neg_flags);
2143 if (!NT_STATUS_IS_OK(result)) {
2144 cli_rpc_pipe_close(netlogon_pipe);
2145 return result;
2148 if ((lp_client_schannel() == True) &&
2149 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2150 DEBUG(3, ("Server did not offer schannel\n"));
2151 cli_rpc_pipe_close(netlogon_pipe);
2152 return NT_STATUS_ACCESS_DENIED;
2155 no_schannel:
2156 if ((lp_client_schannel() == False) ||
2157 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2158 /* We're done - just keep the existing connection to NETLOGON
2159 * open */
2160 conn->netlogon_pipe = netlogon_pipe;
2161 *cli = conn->netlogon_pipe;
2162 return NT_STATUS_OK;
2165 /* Using the credentials from the first pipe, open a signed and sealed
2166 second netlogon pipe. The session key is stored in the schannel
2167 part of the new pipe auth struct.
2170 conn->netlogon_pipe =
2171 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2172 PI_NETLOGON,
2173 PIPE_AUTH_LEVEL_PRIVACY,
2174 domain->name,
2175 netlogon_pipe->dc,
2176 &result);
2178 /* We can now close the initial netlogon pipe. */
2179 cli_rpc_pipe_close(netlogon_pipe);
2181 if (conn->netlogon_pipe == NULL) {
2182 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2183 "was %s\n", nt_errstr(result)));
2185 /* make sure we return something besides OK */
2186 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2189 *cli = conn->netlogon_pipe;
2190 return NT_STATUS_OK;