r20846: Before this gets out of control...
[Samba/gbeck.git] / source3 / nsswitch / winbindd_cm.c
blob19b60c1c1731ffd3eaa7e3dbd721c3dd79729fd9
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, void *buf, size_t len)
87 struct winbindd_domain *domain;
88 const char *domainname = (const char *)buf;
90 if (buf == NULL || len == 0) {
91 return;
94 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
96 for (domain = domain_list(); domain; domain = domain->next) {
97 if (domain->internal) {
98 continue;
101 if (strequal(domain->name, domainname)) {
102 if (domain->online) {
103 /* We're already online, ignore. */
104 DEBUG(5,("msg_fail_to_go_online: domain %s "
105 "already online.\n", domainname));
106 continue;
109 /* Reschedule the online check. */
110 set_domain_offline(domain);
111 break;
116 /****************************************************************
117 Actually cause a reconnect from a message.
118 ****************************************************************/
120 static void msg_try_to_go_online(int msg_type, struct process_id src, void *buf, size_t len)
122 struct winbindd_domain *domain;
123 const char *domainname = (const char *)buf;
125 if (buf == NULL || len == 0) {
126 return;
129 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
131 for (domain = domain_list(); domain; domain = domain->next) {
132 if (domain->internal) {
133 continue;
136 if (strequal(domain->name, domainname)) {
138 if (domain->online) {
139 /* We're already online, ignore. */
140 DEBUG(5,("msg_try_to_go_online: domain %s "
141 "already online.\n", domainname));
142 continue;
145 /* This call takes care of setting the online
146 flag to true if we connected, or re-adding
147 the offline handler if false. Bypasses online
148 check so always does network calls. */
150 init_dc_connection_network(domain);
151 break;
156 /****************************************************************
157 Fork a child to try and contact a DC. Do this as contacting a
158 DC requires blocking lookups and we don't want to block our
159 parent.
160 ****************************************************************/
162 static BOOL fork_child_dc_connect(struct winbindd_domain *domain)
164 struct dc_name_ip *dcs = NULL;
165 int num_dcs = 0;
166 TALLOC_CTX *mem_ctx = NULL;
167 pid_t child_pid;
168 pid_t parent_pid = sys_getpid();
170 /* Stop zombies */
171 CatchChild();
173 message_block();
175 child_pid = sys_fork();
177 if (child_pid == -1) {
178 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
179 message_unblock();
180 return False;
183 if (child_pid != 0) {
184 /* Parent */
185 message_register(MSG_WINBIND_TRY_TO_GO_ONLINE,msg_try_to_go_online);
186 message_register(MSG_WINBIND_FAILED_TO_GO_ONLINE,msg_failed_to_go_online);
187 message_unblock();
188 return True;
191 /* Child. */
193 /* Leave messages blocked - we will never process one. */
195 /* tdb needs special fork handling */
196 if (tdb_reopen_all(1) == -1) {
197 DEBUG(0,("tdb_reopen_all failed.\n"));
198 _exit(0);
201 close_conns_after_fork();
203 if (!override_logfile) {
204 reopen_logs();
207 mem_ctx = talloc_init("fork_child_dc_connect");
208 if (!mem_ctx) {
209 DEBUG(0,("talloc_init failed.\n"));
210 _exit(0);
213 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
214 /* Still offline ? Can't find DC's. */
215 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE,
216 domain->name,
217 strlen(domain->name)+1, False);
218 _exit(0);
221 /* We got a DC. Send a message to our parent to get it to
222 try and do the same. */
224 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE,
225 domain->name,
226 strlen(domain->name)+1, False);
227 _exit(0);
230 /****************************************************************
231 Handler triggered if we're offline to try and detect a DC.
232 ****************************************************************/
234 static void check_domain_online_handler(struct event_context *ctx,
235 struct timed_event *te,
236 const struct timeval *now,
237 void *private_data)
239 struct winbindd_domain *domain =
240 (struct winbindd_domain *)private_data;
242 DEBUG(10,("check_domain_online_handler: called for domain %s\n",
243 domain->name ));
245 if (domain->check_online_event) {
246 TALLOC_FREE(domain->check_online_event);
249 /* Are we still in "startup" mode ? */
251 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
252 /* No longer in "startup" mode. */
253 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
254 domain->name ));
255 domain->startup = False;
258 /* We've been told to stay offline, so stay
259 that way. */
261 if (get_global_winbindd_state_offline()) {
262 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
263 domain->name ));
264 return;
267 /* Fork a child to test if it can contact a DC.
268 If it can then send ourselves a message to
269 cause a reconnect. */
271 fork_child_dc_connect(domain);
274 /****************************************************************
275 If we're still offline setup the timeout check.
276 ****************************************************************/
278 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
280 int wbc = lp_winbind_cache_time();
282 if (domain->startup) {
283 domain->check_online_timeout = 10;
284 } else if (domain->check_online_timeout < wbc) {
285 domain->check_online_timeout = wbc;
289 /****************************************************************
290 Set domain offline and also add handler to put us back online
291 if we detect a DC.
292 ****************************************************************/
294 void set_domain_offline(struct winbindd_domain *domain)
296 DEBUG(10,("set_domain_offline: called for domain %s\n",
297 domain->name ));
299 if (domain->check_online_event) {
300 TALLOC_FREE(domain->check_online_event);
303 if (domain->internal) {
304 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
305 domain->name ));
306 return;
309 domain->online = False;
311 /* Offline domains are always initialized. They're
312 re-initialized when they go back online. */
314 domain->initialized = True;
316 /* We only add the timeout handler that checks and
317 allows us to go back online when we've not
318 been told to remain offline. */
320 if (get_global_winbindd_state_offline()) {
321 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
322 domain->name ));
323 return;
326 /* If we're in statup mode, check again in 10 seconds, not in
327 lp_winbind_cache_time() seconds (which is 5 mins by default). */
329 calc_new_online_timeout_check(domain);
331 domain->check_online_event = event_add_timed(winbind_event_context(), NULL,
332 timeval_current_ofs(domain->check_online_timeout,0),
333 "check_domain_online_handler",
334 check_domain_online_handler,
335 domain);
337 /* The above *has* to succeed for winbindd to work. */
338 if (!domain->check_online_event) {
339 smb_panic("set_domain_offline: failed to add online handler.\n");
342 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
343 domain->name ));
346 /****************************************************************
347 Set domain online - if allowed.
348 ****************************************************************/
350 static void set_domain_online(struct winbindd_domain *domain)
352 struct timeval now;
354 DEBUG(10,("set_domain_online: called for domain %s\n",
355 domain->name ));
357 if (domain->internal) {
358 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
359 domain->name ));
360 return;
363 if (get_global_winbindd_state_offline()) {
364 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
365 domain->name ));
366 return;
369 /* If we are waiting to get a krb5 ticket, trigger immediately. */
370 GetTimeOfDay(&now);
371 set_event_dispatch_time(winbind_event_context(),
372 "krb5_ticket_gain_handler", now);
374 /* Ok, we're out of any startup mode now... */
375 domain->startup = False;
377 if (domain->online == False) {
378 /* We were offline - now we're online. We default to
379 using the MS-RPC backend if we started offline,
380 and if we're going online for the first time we
381 should really re-initialize the backends and the
382 checks to see if we're talking to an AD or NT domain.
385 domain->initialized = False;
387 /* 'reconnect_methods' is the MS-RPC backend. */
388 if (domain->backend == &reconnect_methods) {
389 domain->backend = NULL;
393 /* Ensure we have no online timeout checks. */
394 domain->check_online_timeout = 0;
395 if (domain->check_online_event) {
396 TALLOC_FREE(domain->check_online_event);
399 /* Ensure we ignore any pending child messages. */
400 message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
401 message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
403 domain->online = True;
406 /****************************************************************
407 Requested to set a domain online.
408 ****************************************************************/
410 void set_domain_online_request(struct winbindd_domain *domain)
412 struct timeval tev;
414 DEBUG(10,("set_domain_online_request: called for domain %s\n",
415 domain->name ));
417 if (get_global_winbindd_state_offline()) {
418 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
419 domain->name ));
420 return;
423 /* We've been told it's safe to go online and
424 try and connect to a DC. But I don't believe it
425 because network manager seems to lie.
426 Wait at least 5 seconds. Heuristics suck... */
428 if (!domain->check_online_event) {
429 /* If we've come from being globally offline we
430 don't have a check online event handler set.
431 We need to add one now we're trying to go
432 back online. */
434 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
435 domain->name ));
439 TALLOC_FREE(domain->check_online_event);
441 GetTimeOfDay(&tev);
443 /* Go into "startup" mode again. */
444 domain->startup_time = tev.tv_sec;
445 domain->startup = True;
447 tev.tv_sec += 5;
449 domain->check_online_event = event_add_timed(
450 winbind_event_context(), NULL, tev,
451 "check_domain_online_handler",
452 check_domain_online_handler,
453 domain);
455 /* The above *has* to succeed for winbindd to work. */
456 if (!domain->check_online_event) {
457 smb_panic("set_domain_online_request: failed to add online handler.\n");
461 /****************************************************************
462 Add -ve connection cache entries for domain and realm.
463 ****************************************************************/
465 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
466 const char *server,
467 NTSTATUS result)
469 add_failed_connection_entry(domain->name, server, result);
470 /* If this was the saf name for the last thing we talked to,
471 remove it. */
472 saf_delete(domain->name);
473 if (*domain->alt_name) {
474 add_failed_connection_entry(domain->alt_name, server, result);
475 saf_delete(domain->alt_name);
479 /* Choose between anonymous or authenticated connections. We need to use
480 an authenticated connection if DCs have the RestrictAnonymous registry
481 entry set > 0, or the "Additional restrictions for anonymous
482 connections" set in the win2k Local Security Policy.
484 Caller to free() result in domain, username, password
487 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
489 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
490 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
491 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
493 if (*username && **username) {
495 if (!*domain || !**domain)
496 *domain = smb_xstrdup(lp_workgroup());
498 if (!*password || !**password)
499 *password = smb_xstrdup("");
501 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
502 *domain, *username));
504 } else {
505 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
506 *username = smb_xstrdup("");
507 *domain = smb_xstrdup("");
508 *password = smb_xstrdup("");
512 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
513 fstring dcname, struct in_addr *dc_ip)
515 struct winbindd_domain *our_domain = NULL;
516 struct rpc_pipe_client *netlogon_pipe = NULL;
517 NTSTATUS result;
518 WERROR werr;
519 TALLOC_CTX *mem_ctx;
520 unsigned int orig_timeout;
521 fstring tmp;
522 char *p;
524 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
525 * moment.... */
527 if (IS_DC) {
528 return False;
531 if (domain->primary) {
532 return False;
535 our_domain = find_our_domain();
537 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
538 return False;
541 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
542 if (!NT_STATUS_IS_OK(result)) {
543 talloc_destroy(mem_ctx);
544 return False;
547 /* This call can take a long time - allow the server to time out.
548 35 seconds should do it. */
550 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
552 werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
553 domain->name, tmp);
555 /* And restore our original timeout. */
556 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
558 talloc_destroy(mem_ctx);
560 if (!W_ERROR_IS_OK(werr)) {
561 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
562 dos_errstr(werr)));
563 return False;
566 /* cli_netlogon_getdcname gives us a name with \\ */
567 p = tmp;
568 if (*p == '\\') {
569 p+=1;
571 if (*p == '\\') {
572 p+=1;
575 fstrcpy(dcname, p);
577 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
579 if (!resolve_name(dcname, dc_ip, 0x20)) {
580 return False;
583 return True;
586 /************************************************************************
587 Given a fd with a just-connected TCP connection to a DC, open a connection
588 to the pipe.
589 ************************************************************************/
591 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
592 const int sockfd,
593 const char *controller,
594 struct cli_state **cli,
595 BOOL *retry)
597 char *machine_password, *machine_krb5_principal, *machine_account;
598 char *ipc_username, *ipc_domain, *ipc_password;
600 BOOL got_mutex;
602 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
604 struct sockaddr peeraddr;
605 socklen_t peeraddr_len;
607 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
609 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
610 controller, domain->name ));
612 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
613 NULL);
615 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
616 SAFE_FREE(machine_password);
617 return NT_STATUS_NO_MEMORY;
620 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
621 lp_realm()) == -1) {
622 SAFE_FREE(machine_account);
623 SAFE_FREE(machine_password);
624 return NT_STATUS_NO_MEMORY;
627 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
629 *retry = True;
631 got_mutex = secrets_named_mutex(controller,
632 WINBIND_SERVER_MUTEX_WAIT_TIME);
634 if (!got_mutex) {
635 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
636 controller));
637 result = NT_STATUS_POSSIBLE_DEADLOCK;
638 goto done;
641 if ((*cli = cli_initialise()) == NULL) {
642 DEBUG(1, ("Could not cli_initialize\n"));
643 result = NT_STATUS_NO_MEMORY;
644 goto done;
647 (*cli)->timeout = 10000; /* 10 seconds */
648 (*cli)->fd = sockfd;
649 fstrcpy((*cli)->desthost, controller);
650 (*cli)->use_kerberos = True;
652 peeraddr_len = sizeof(peeraddr);
654 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
655 (peeraddr_len != sizeof(struct sockaddr_in)) ||
656 (peeraddr_in->sin_family != PF_INET))
658 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
659 result = NT_STATUS_UNSUCCESSFUL;
660 goto done;
663 if (ntohs(peeraddr_in->sin_port) == 139) {
664 struct nmb_name calling;
665 struct nmb_name called;
667 make_nmb_name(&calling, global_myname(), 0x0);
668 make_nmb_name(&called, "*SMBSERVER", 0x20);
670 if (!cli_session_request(*cli, &calling, &called)) {
671 DEBUG(8, ("cli_session_request failed for %s\n",
672 controller));
673 result = NT_STATUS_UNSUCCESSFUL;
674 goto done;
678 cli_setup_signing_state(*cli, Undefined);
680 if (!cli_negprot(*cli)) {
681 DEBUG(1, ("cli_negprot failed\n"));
682 result = NT_STATUS_UNSUCCESSFUL;
683 goto done;
686 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
687 ADS_STATUS ads_status;
689 if (lp_security() == SEC_ADS) {
691 /* Try a krb5 session */
693 (*cli)->use_kerberos = True;
694 DEBUG(5, ("connecting to %s from %s with kerberos principal "
695 "[%s]\n", controller, global_myname(),
696 machine_krb5_principal));
698 ads_status = cli_session_setup_spnego(*cli,
699 machine_krb5_principal,
700 machine_password,
701 lp_workgroup());
703 if (!ADS_ERR_OK(ads_status)) {
704 DEBUG(4,("failed kerberos session setup with %s\n",
705 ads_errstr(ads_status)));
708 result = ads_ntstatus(ads_status);
709 if (NT_STATUS_IS_OK(result)) {
710 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
711 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
712 goto session_setup_done;
716 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
717 (*cli)->use_kerberos = False;
719 DEBUG(5, ("connecting to %s from %s with username "
720 "[%s]\\[%s]\n", controller, global_myname(),
721 lp_workgroup(), machine_account));
723 ads_status = cli_session_setup_spnego(*cli,
724 machine_account,
725 machine_password,
726 lp_workgroup());
727 if (!ADS_ERR_OK(ads_status)) {
728 DEBUG(4, ("authenticated session setup failed with %s\n",
729 ads_errstr(ads_status)));
732 result = ads_ntstatus(ads_status);
733 if (NT_STATUS_IS_OK(result)) {
734 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
735 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
736 goto session_setup_done;
740 /* Fall back to non-kerberos session setup */
742 (*cli)->use_kerberos = False;
744 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
745 (strlen(ipc_username) > 0)) {
747 /* Only try authenticated if we have a username */
749 DEBUG(5, ("connecting to %s from %s with username "
750 "[%s]\\[%s]\n", controller, global_myname(),
751 ipc_domain, ipc_username));
753 if (NT_STATUS_IS_OK(cli_session_setup(
754 *cli, ipc_username,
755 ipc_password, strlen(ipc_password)+1,
756 ipc_password, strlen(ipc_password)+1,
757 ipc_domain))) {
758 /* Successful logon with given username. */
759 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
760 goto session_setup_done;
761 } else {
762 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
763 ipc_domain, ipc_username ));
767 /* Fall back to anonymous connection, this might fail later */
769 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
770 NULL, 0, ""))) {
771 DEBUG(5, ("Connected anonymously\n"));
772 cli_init_creds(*cli, "", "", "");
773 goto session_setup_done;
776 result = cli_nt_error(*cli);
778 if (NT_STATUS_IS_OK(result))
779 result = NT_STATUS_UNSUCCESSFUL;
781 /* We can't session setup */
783 goto done;
785 session_setup_done:
787 /* cache the server name for later connections */
789 saf_store( domain->name, (*cli)->desthost );
790 if (domain->alt_name && (*cli)->use_kerberos) {
791 saf_store( domain->alt_name, (*cli)->desthost );
794 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
796 result = cli_nt_error(*cli);
798 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
800 if (NT_STATUS_IS_OK(result))
801 result = NT_STATUS_UNSUCCESSFUL;
803 goto done;
806 secrets_named_mutex_release(controller);
807 got_mutex = False;
808 *retry = False;
810 /* set the domain if empty; needed for schannel connections */
811 if ( !*(*cli)->domain ) {
812 fstrcpy( (*cli)->domain, domain->name );
815 result = NT_STATUS_OK;
817 done:
818 if (got_mutex) {
819 secrets_named_mutex_release(controller);
822 SAFE_FREE(machine_account);
823 SAFE_FREE(machine_password);
824 SAFE_FREE(machine_krb5_principal);
825 SAFE_FREE(ipc_username);
826 SAFE_FREE(ipc_domain);
827 SAFE_FREE(ipc_password);
829 if (!NT_STATUS_IS_OK(result)) {
830 winbind_add_failed_connection_entry(domain, controller, result);
831 if ((*cli) != NULL) {
832 cli_shutdown(*cli);
833 *cli = NULL;
837 return result;
840 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
841 const char *dcname, struct in_addr ip,
842 struct dc_name_ip **dcs, int *num)
844 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
845 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
846 return False;
849 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
851 if (*dcs == NULL)
852 return False;
854 fstrcpy((*dcs)[*num].name, dcname);
855 (*dcs)[*num].ip = ip;
856 *num += 1;
857 return True;
860 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
861 struct in_addr ip, uint16 port,
862 struct sockaddr_in **addrs, int *num)
864 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
866 if (*addrs == NULL) {
867 *num = 0;
868 return False;
871 (*addrs)[*num].sin_family = PF_INET;
872 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
873 (*addrs)[*num].sin_port = htons(port);
875 *num += 1;
876 return True;
879 static void mailslot_name(struct in_addr dc_ip, fstring name)
881 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
884 static BOOL send_getdc_request(struct in_addr dc_ip,
885 const char *domain_name,
886 const DOM_SID *sid)
888 pstring outbuf;
889 char *p;
890 fstring my_acct_name;
891 fstring my_mailslot;
893 mailslot_name(dc_ip, my_mailslot);
895 memset(outbuf, '\0', sizeof(outbuf));
897 p = outbuf;
899 SCVAL(p, 0, SAMLOGON);
900 p++;
902 SCVAL(p, 0, 0); /* Count pointer ... */
903 p++;
905 SIVAL(p, 0, 0); /* The sender's token ... */
906 p += 2;
908 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
909 fstr_sprintf(my_acct_name, "%s$", global_myname());
910 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
912 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
913 p += strlen(my_mailslot)+1;
915 SIVAL(p, 0, 0x80);
916 p+=4;
918 SIVAL(p, 0, sid_size(sid));
919 p+=4;
921 p = ALIGN4(p, outbuf);
923 sid_linearize(p, sid_size(sid), sid);
924 p += sid_size(sid);
926 SIVAL(p, 0, 1);
927 SSVAL(p, 4, 0xffff);
928 SSVAL(p, 6, 0xffff);
929 p+=8;
931 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
932 outbuf, PTR_DIFF(p, outbuf),
933 global_myname(), 0, domain_name, 0x1c,
934 dc_ip);
937 static BOOL receive_getdc_response(struct in_addr dc_ip,
938 const char *domain_name,
939 fstring dc_name)
941 struct packet_struct *packet;
942 fstring my_mailslot;
943 char *buf, *p;
944 fstring dcname, user, domain;
945 int len;
947 mailslot_name(dc_ip, my_mailslot);
949 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
951 if (packet == NULL) {
952 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
953 return False;
956 DEBUG(5, ("Received packet for %s\n", my_mailslot));
958 buf = packet->packet.dgram.data;
959 len = packet->packet.dgram.datasize;
961 if (len < 70) {
962 /* 70 is a completely arbitrary value to make sure
963 the SVAL below does not read uninitialized memory */
964 DEBUG(3, ("GetDC got short response\n"));
965 return False;
968 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
969 p = buf+SVAL(buf, smb_vwv10);
971 if (CVAL(p,0) != SAMLOGON_R) {
972 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
973 return False;
976 p+=2;
977 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
978 STR_TERMINATE|STR_NOALIGN);
979 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
980 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
981 STR_TERMINATE|STR_NOALIGN);
982 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
983 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
984 STR_TERMINATE|STR_NOALIGN);
985 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
987 if (!strequal(domain, domain_name)) {
988 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
989 domain_name, domain));
990 return False;
993 p = dcname;
994 if (*p == '\\') p += 1;
995 if (*p == '\\') p += 1;
997 fstrcpy(dc_name, p);
999 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1000 dc_name, domain));
1002 return True;
1005 /*******************************************************************
1006 convert an ip to a name
1007 *******************************************************************/
1009 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1011 struct ip_service ip_list;
1013 ip_list.ip = ip;
1014 ip_list.port = 0;
1016 #ifdef WITH_ADS
1017 /* For active directory servers, try to get the ldap server name.
1018 None of these failures should be considered critical for now */
1020 if (lp_security() == SEC_ADS) {
1021 ADS_STRUCT *ads;
1023 ads = ads_init(domain->alt_name, domain->name, NULL);
1024 ads->auth.flags |= ADS_AUTH_NO_BIND;
1026 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1027 /* We got a cldap packet. */
1028 fstrcpy(name, ads->config.ldap_server_name);
1029 namecache_store(name, 0x20, 1, &ip_list);
1031 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1033 if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
1034 /* We're going to use this KDC for this realm/domain.
1035 If we are using sites, then force the krb5 libs
1036 to use this KDC. */
1038 create_local_private_krb5_conf_for_domain(domain->alt_name,
1039 domain->name,
1040 ip);
1042 /* Ensure we contact this DC also. */
1043 saf_store( domain->name, name);
1044 saf_store( domain->alt_name, name);
1047 ads_destroy( &ads );
1048 return True;
1051 ads_destroy( &ads );
1053 #endif
1055 /* try GETDC requests next */
1057 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1058 int i;
1059 smb_msleep(100);
1060 for (i=0; i<5; i++) {
1061 if (receive_getdc_response(ip, domain->name, name)) {
1062 namecache_store(name, 0x20, 1, &ip_list);
1063 return True;
1065 smb_msleep(500);
1069 /* try node status request */
1071 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1072 namecache_store(name, 0x20, 1, &ip_list);
1073 return True;
1075 return False;
1078 /*******************************************************************
1079 Retreive a list of IP address for domain controllers. Fill in
1080 the dcs[] with results.
1081 *******************************************************************/
1083 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1084 struct dc_name_ip **dcs, int *num_dcs)
1086 fstring dcname;
1087 struct in_addr ip;
1088 struct ip_service *ip_list = NULL;
1089 int iplist_size = 0;
1090 int i;
1091 BOOL is_our_domain;
1092 enum security_types sec = (enum security_types)lp_security();
1094 is_our_domain = strequal(domain->name, lp_workgroup());
1096 if ( !is_our_domain
1097 && get_dc_name_via_netlogon(domain, dcname, &ip)
1098 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1100 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1101 dcname, inet_ntoa(ip)));
1102 return True;
1105 if (sec == SEC_ADS) {
1106 /* We need to make sure we know the local site before
1107 doing any DNS queries, as this will restrict the
1108 get_sorted_dc_list() call below to only fetching
1109 DNS records for the correct site. */
1111 /* Find any DC to get the site record.
1112 We deliberately don't care about the
1113 return here. */
1114 get_dc_name(domain->name, lp_realm(), dcname, &ip);
1116 /* Now do the site-specific AD dns lookup. */
1117 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
1120 /* try standard netbios queries if no ADS */
1122 if (iplist_size==0)
1123 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
1125 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1127 /* now add to the dc array. We'll wait until the last minute
1128 to look up the name of the DC. But we fill in the char* for
1129 the ip now in to make the failed connection cache work */
1131 for ( i=0; i<iplist_size; i++ ) {
1132 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1133 ip_list[i].ip, dcs, num_dcs);
1136 SAFE_FREE( ip_list );
1138 return True;
1141 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1142 const struct winbindd_domain *domain,
1143 fstring dcname, struct sockaddr_in *addr, int *fd)
1145 struct dc_name_ip *dcs = NULL;
1146 int num_dcs = 0;
1148 const char **dcnames = NULL;
1149 int num_dcnames = 0;
1151 struct sockaddr_in *addrs = NULL;
1152 int num_addrs = 0;
1154 int i, fd_index;
1156 again:
1157 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1158 return False;
1160 for (i=0; i<num_dcs; i++) {
1162 if (!add_string_to_array(mem_ctx, dcs[i].name,
1163 &dcnames, &num_dcnames)) {
1164 return False;
1166 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1167 &addrs, &num_addrs)) {
1168 return False;
1171 if (!add_string_to_array(mem_ctx, dcs[i].name,
1172 &dcnames, &num_dcnames)) {
1173 return False;
1175 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1176 &addrs, &num_addrs)) {
1177 return False;
1181 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1182 return False;
1184 if ((addrs == NULL) || (dcnames == NULL))
1185 return False;
1187 /* 5 second timeout. */
1188 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1190 for (i=0; i<num_dcs; i++) {
1191 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1192 "domain %s address %s. Error was %s\n",
1193 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1194 winbind_add_failed_connection_entry(domain,
1195 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1197 return False;
1200 *addr = addrs[fd_index];
1202 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1203 /* Ok, we've got a name for the DC */
1204 fstrcpy(dcname, dcnames[fd_index]);
1205 return True;
1208 /* Try to figure out the name */
1209 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1210 return True;
1213 /* We can not continue without the DC's name */
1214 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1215 NT_STATUS_UNSUCCESSFUL);
1216 goto again;
1219 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1220 struct winbindd_cm_conn *new_conn)
1222 TALLOC_CTX *mem_ctx;
1223 NTSTATUS result;
1224 char *saf_servername = saf_fetch( domain->name );
1225 int retries;
1227 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1228 SAFE_FREE(saf_servername);
1229 set_domain_offline(domain);
1230 return NT_STATUS_NO_MEMORY;
1233 /* we have to check the server affinity cache here since
1234 later we selecte a DC based on response time and not preference */
1236 /* Check the negative connection cache
1237 before talking to it. It going down may have
1238 triggered the reconnection. */
1240 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1242 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1243 saf_servername, domain->name ));
1245 /* convert an ip address to a name */
1246 if ( is_ipaddress( saf_servername ) ) {
1247 fstring saf_name;
1248 struct in_addr ip;
1250 ip = *interpret_addr2( saf_servername );
1251 if (dcip_to_name( domain, ip, saf_name )) {
1252 fstrcpy( domain->dcname, saf_name );
1253 } else {
1254 winbind_add_failed_connection_entry(
1255 domain, saf_servername,
1256 NT_STATUS_UNSUCCESSFUL);
1258 } else {
1259 fstrcpy( domain->dcname, saf_servername );
1262 SAFE_FREE( saf_servername );
1265 for (retries = 0; retries < 3; retries++) {
1267 int fd = -1;
1268 BOOL retry = False;
1270 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1272 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1273 domain->dcname, domain->name ));
1275 if (*domain->dcname
1276 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1277 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1279 struct sockaddr_in *addrs = NULL;
1280 int num_addrs = 0;
1281 int dummy = 0;
1283 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1284 set_domain_offline(domain);
1285 talloc_destroy(mem_ctx);
1286 return NT_STATUS_NO_MEMORY;
1288 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1289 set_domain_offline(domain);
1290 talloc_destroy(mem_ctx);
1291 return NT_STATUS_NO_MEMORY;
1294 /* 5 second timeout. */
1295 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1296 fd = -1;
1300 if ((fd == -1)
1301 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1303 /* This is the one place where we will
1304 set the global winbindd offline state
1305 to true, if a "WINBINDD_OFFLINE" entry
1306 is found in the winbindd cache. */
1307 set_global_winbindd_state_offline();
1308 break;
1311 new_conn->cli = NULL;
1313 result = cm_prepare_connection(domain, fd, domain->dcname,
1314 &new_conn->cli, &retry);
1316 if (!retry)
1317 break;
1320 if (NT_STATUS_IS_OK(result)) {
1321 if (domain->online == False) {
1322 /* We're changing state from offline to online. */
1323 set_global_winbindd_state_online();
1325 set_domain_online(domain);
1326 } else {
1327 /* Ensure we setup the retry handler. */
1328 set_domain_offline(domain);
1331 talloc_destroy(mem_ctx);
1332 return result;
1335 /* Close down all open pipes on a connection. */
1337 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1339 /* We're closing down a possibly dead
1340 connection. Don't have impossibly long (10s) timeouts. */
1342 if (conn->cli) {
1343 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1346 if (conn->samr_pipe != NULL) {
1347 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1348 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1349 if (conn->cli) {
1350 cli_set_timeout(conn->cli, 500);
1353 conn->samr_pipe = NULL;
1356 if (conn->lsa_pipe != NULL) {
1357 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1358 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1359 if (conn->cli) {
1360 cli_set_timeout(conn->cli, 500);
1363 conn->lsa_pipe = NULL;
1366 if (conn->netlogon_pipe != NULL) {
1367 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1368 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1369 if (conn->cli) {
1370 cli_set_timeout(conn->cli, 500);
1373 conn->netlogon_pipe = NULL;
1376 if (conn->cli) {
1377 cli_shutdown(conn->cli);
1380 conn->cli = NULL;
1383 void close_conns_after_fork(void)
1385 struct winbindd_domain *domain;
1387 for (domain = domain_list(); domain; domain = domain->next) {
1388 if (domain->conn.cli == NULL)
1389 continue;
1391 if (domain->conn.cli->fd == -1)
1392 continue;
1394 close(domain->conn.cli->fd);
1395 domain->conn.cli->fd = -1;
1399 static BOOL connection_ok(struct winbindd_domain *domain)
1401 if (domain->conn.cli == NULL) {
1402 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1403 "cli!\n", domain->dcname, domain->name));
1404 return False;
1407 if (!domain->conn.cli->initialised) {
1408 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1409 "initialised!\n", domain->dcname, domain->name));
1410 return False;
1413 if (domain->conn.cli->fd == -1) {
1414 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1415 "never started (fd == -1)\n",
1416 domain->dcname, domain->name));
1417 return False;
1420 if (domain->online == False) {
1421 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1422 return False;
1425 return True;
1428 /* Initialize a new connection up to the RPC BIND.
1429 Bypass online status check so always does network calls. */
1431 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1433 NTSTATUS result;
1435 /* Internal connections never use the network. */
1436 if (domain->internal) {
1437 domain->initialized = True;
1438 return NT_STATUS_OK;
1441 if (connection_ok(domain)) {
1442 if (!domain->initialized) {
1443 set_dc_type_and_flags(domain);
1445 return NT_STATUS_OK;
1448 invalidate_cm_connection(&domain->conn);
1450 result = cm_open_connection(domain, &domain->conn);
1452 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1453 set_dc_type_and_flags(domain);
1456 return result;
1459 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1461 if (domain->initialized && !domain->online) {
1462 /* We check for online status elsewhere. */
1463 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1466 return init_dc_connection_network(domain);
1469 /******************************************************************************
1470 We can 'sense' certain things about the DC by it's replies to certain
1471 questions.
1473 This tells us if this particular remote server is Active Directory, and if it
1474 is native mode.
1475 ******************************************************************************/
1477 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1479 NTSTATUS result;
1480 DS_DOMINFO_CTR ctr;
1481 TALLOC_CTX *mem_ctx = NULL;
1482 struct rpc_pipe_client *cli;
1483 POLICY_HND pol;
1485 char *domain_name = NULL;
1486 char *dns_name = NULL;
1487 char *forest_name = NULL;
1488 DOM_SID *dom_sid = NULL;
1490 ZERO_STRUCT( ctr );
1492 if (!connection_ok(domain)) {
1493 return;
1496 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1498 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1499 &result);
1501 if (cli == NULL) {
1502 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1503 "PI_LSARPC_DS on domain %s: (%s)\n",
1504 domain->name, nt_errstr(result)));
1505 return;
1508 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1509 DsRolePrimaryDomainInfoBasic,
1510 &ctr);
1511 cli_rpc_pipe_close(cli);
1513 if (!NT_STATUS_IS_OK(result)) {
1514 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1515 "on domain %s failed: (%s)\n",
1516 domain->name, nt_errstr(result)));
1517 return;
1520 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1521 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1522 domain->native_mode = True;
1523 } else {
1524 domain->native_mode = False;
1527 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1529 if (cli == NULL) {
1530 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1531 "PI_LSARPC on domain %s: (%s)\n",
1532 domain->name, nt_errstr(result)));
1533 cli_rpc_pipe_close(cli);
1534 return;
1537 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1538 domain->name);
1539 if (!mem_ctx) {
1540 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1541 cli_rpc_pipe_close(cli);
1542 return;
1545 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1546 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1548 if (NT_STATUS_IS_OK(result)) {
1549 /* This particular query is exactly what Win2k clients use
1550 to determine that the DC is active directory */
1551 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1552 12, &domain_name,
1553 &dns_name, &forest_name,
1554 NULL, &dom_sid);
1557 if (NT_STATUS_IS_OK(result)) {
1558 domain->active_directory = True;
1560 if (domain_name)
1561 fstrcpy(domain->name, domain_name);
1563 if (dns_name)
1564 fstrcpy(domain->alt_name, dns_name);
1566 if ( forest_name )
1567 fstrcpy(domain->forest_name, forest_name);
1569 if (dom_sid)
1570 sid_copy(&domain->sid, dom_sid);
1571 } else {
1572 domain->active_directory = False;
1574 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1575 SEC_RIGHTS_MAXIMUM_ALLOWED,
1576 &pol);
1578 if (!NT_STATUS_IS_OK(result))
1579 goto done;
1581 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1582 &pol, 5, &domain_name,
1583 &dom_sid);
1585 if (NT_STATUS_IS_OK(result)) {
1586 if (domain_name)
1587 fstrcpy(domain->name, domain_name);
1589 if (dom_sid)
1590 sid_copy(&domain->sid, dom_sid);
1593 done:
1595 DEBUG(5, ("set_dc_type_and_flags: domain %s is %sin native mode.\n",
1596 domain->name, domain->native_mode ? "" : "NOT "));
1598 DEBUG(5,("set_dc_type_and_flags: domain %s is %srunning active directory.\n",
1599 domain->name, domain->active_directory ? "" : "NOT "));
1601 cli_rpc_pipe_close(cli);
1603 talloc_destroy(mem_ctx);
1605 domain->initialized = True;
1608 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1609 struct dcinfo **ppdc)
1611 NTSTATUS result;
1612 struct rpc_pipe_client *netlogon_pipe;
1614 if (lp_client_schannel() == False) {
1615 return False;
1618 result = cm_connect_netlogon(domain, &netlogon_pipe);
1619 if (!NT_STATUS_IS_OK(result)) {
1620 return False;
1623 /* Return a pointer to the struct dcinfo from the
1624 netlogon pipe. */
1626 *ppdc = domain->conn.netlogon_pipe->dc;
1627 return True;
1630 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1631 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1633 struct winbindd_cm_conn *conn;
1634 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1635 fstring conn_pwd;
1636 struct dcinfo *p_dcinfo;
1638 result = init_dc_connection(domain);
1639 if (!NT_STATUS_IS_OK(result)) {
1640 return result;
1643 conn = &domain->conn;
1645 if (conn->samr_pipe != NULL) {
1646 goto done;
1650 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1651 * sign and sealed pipe using the machine account password by
1652 * preference. If we can't - try schannel, if that fails, try
1653 * anonymous.
1656 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1657 if ((conn->cli->user_name[0] == '\0') ||
1658 (conn->cli->domain[0] == '\0') ||
1659 (conn_pwd[0] == '\0')) {
1660 DEBUG(10, ("cm_connect_sam: No no user available for "
1661 "domain %s, trying schannel\n", conn->cli->domain));
1662 goto schannel;
1665 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1666 authenticated SAMR pipe with sign & seal. */
1667 conn->samr_pipe =
1668 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1669 PIPE_AUTH_LEVEL_PRIVACY,
1670 conn->cli->domain,
1671 conn->cli->user_name,
1672 conn_pwd, &result);
1674 if (conn->samr_pipe == NULL) {
1675 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1676 "pipe for domain %s using NTLMSSP "
1677 "authenticated pipe: user %s\\%s. Error was "
1678 "%s\n", domain->name, conn->cli->domain,
1679 conn->cli->user_name, nt_errstr(result)));
1680 goto schannel;
1683 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1684 "domain %s using NTLMSSP authenticated "
1685 "pipe: user %s\\%s\n", domain->name,
1686 conn->cli->domain, conn->cli->user_name ));
1688 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1689 SEC_RIGHTS_MAXIMUM_ALLOWED,
1690 &conn->sam_connect_handle);
1691 if (NT_STATUS_IS_OK(result)) {
1692 goto open_domain;
1694 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1695 "failed for domain %s, error was %s. Trying schannel\n",
1696 domain->name, nt_errstr(result) ));
1697 cli_rpc_pipe_close(conn->samr_pipe);
1699 schannel:
1701 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1703 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1704 /* If this call fails - conn->cli can now be NULL ! */
1705 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1706 "for domain %s, trying anon\n", domain->name));
1707 goto anonymous;
1709 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1710 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1711 domain->name, p_dcinfo, &result);
1713 if (conn->samr_pipe == NULL) {
1714 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1715 "domain %s using schannel. Error was %s\n",
1716 domain->name, nt_errstr(result) ));
1717 goto anonymous;
1719 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1720 "schannel.\n", domain->name ));
1722 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1723 SEC_RIGHTS_MAXIMUM_ALLOWED,
1724 &conn->sam_connect_handle);
1725 if (NT_STATUS_IS_OK(result)) {
1726 goto open_domain;
1728 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1729 "for domain %s, error was %s. Trying anonymous\n",
1730 domain->name, nt_errstr(result) ));
1731 cli_rpc_pipe_close(conn->samr_pipe);
1733 anonymous:
1735 /* Finally fall back to anonymous. */
1736 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1737 &result);
1739 if (conn->samr_pipe == NULL) {
1740 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1741 goto done;
1744 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1745 SEC_RIGHTS_MAXIMUM_ALLOWED,
1746 &conn->sam_connect_handle);
1747 if (!NT_STATUS_IS_OK(result)) {
1748 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1749 "for domain %s Error was %s\n",
1750 domain->name, nt_errstr(result) ));
1751 goto done;
1754 open_domain:
1755 result = rpccli_samr_open_domain(conn->samr_pipe,
1756 mem_ctx,
1757 &conn->sam_connect_handle,
1758 SEC_RIGHTS_MAXIMUM_ALLOWED,
1759 &domain->sid,
1760 &conn->sam_domain_handle);
1762 done:
1764 if (!NT_STATUS_IS_OK(result)) {
1765 invalidate_cm_connection(conn);
1766 return result;
1769 *cli = conn->samr_pipe;
1770 *sam_handle = conn->sam_domain_handle;
1771 return result;
1774 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1775 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1777 struct winbindd_cm_conn *conn;
1778 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1779 fstring conn_pwd;
1780 struct dcinfo *p_dcinfo;
1782 result = init_dc_connection(domain);
1783 if (!NT_STATUS_IS_OK(result))
1784 return result;
1786 conn = &domain->conn;
1788 if (conn->lsa_pipe != NULL) {
1789 goto done;
1792 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1793 if ((conn->cli->user_name[0] == '\0') ||
1794 (conn->cli->domain[0] == '\0') ||
1795 (conn_pwd[0] == '\0')) {
1796 DEBUG(10, ("cm_connect_lsa: No no user available for "
1797 "domain %s, trying schannel\n", conn->cli->domain));
1798 goto schannel;
1801 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1802 * authenticated LSA pipe with sign & seal. */
1803 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1804 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1805 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1807 if (conn->lsa_pipe == NULL) {
1808 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1809 "domain %s using NTLMSSP authenticated pipe: user "
1810 "%s\\%s. Error was %s. Trying schannel.\n",
1811 domain->name, conn->cli->domain,
1812 conn->cli->user_name, nt_errstr(result)));
1813 goto schannel;
1816 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1817 "NTLMSSP authenticated pipe: user %s\\%s\n",
1818 domain->name, conn->cli->domain, conn->cli->user_name ));
1820 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1821 SEC_RIGHTS_MAXIMUM_ALLOWED,
1822 &conn->lsa_policy);
1823 if (NT_STATUS_IS_OK(result)) {
1824 goto done;
1827 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1828 "schannel\n"));
1830 cli_rpc_pipe_close(conn->lsa_pipe);
1832 schannel:
1834 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1836 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1837 /* If this call fails - conn->cli can now be NULL ! */
1838 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1839 "for domain %s, trying anon\n", domain->name));
1840 goto anonymous;
1842 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1843 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1844 domain->name, p_dcinfo, &result);
1846 if (conn->lsa_pipe == NULL) {
1847 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1848 "domain %s using schannel. Error was %s\n",
1849 domain->name, nt_errstr(result) ));
1850 goto anonymous;
1852 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1853 "schannel.\n", domain->name ));
1855 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1856 SEC_RIGHTS_MAXIMUM_ALLOWED,
1857 &conn->lsa_policy);
1858 if (NT_STATUS_IS_OK(result)) {
1859 goto done;
1862 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1863 "anonymous\n"));
1865 cli_rpc_pipe_close(conn->lsa_pipe);
1867 anonymous:
1869 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1870 &result);
1871 if (conn->lsa_pipe == NULL) {
1872 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1873 goto done;
1876 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1877 SEC_RIGHTS_MAXIMUM_ALLOWED,
1878 &conn->lsa_policy);
1879 done:
1880 if (!NT_STATUS_IS_OK(result)) {
1881 invalidate_cm_connection(conn);
1882 return result;
1885 *cli = conn->lsa_pipe;
1886 *lsa_policy = conn->lsa_policy;
1887 return result;
1890 /****************************************************************************
1891 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1892 session key stored in conn->netlogon_pipe->dc->sess_key.
1893 ****************************************************************************/
1895 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1896 struct rpc_pipe_client **cli)
1898 struct winbindd_cm_conn *conn;
1899 NTSTATUS result;
1901 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1902 uint8 mach_pwd[16];
1903 uint32 sec_chan_type;
1904 const char *account_name;
1905 struct rpc_pipe_client *netlogon_pipe = NULL;
1907 *cli = NULL;
1909 result = init_dc_connection(domain);
1910 if (!NT_STATUS_IS_OK(result)) {
1911 return result;
1914 conn = &domain->conn;
1916 if (conn->netlogon_pipe != NULL) {
1917 *cli = conn->netlogon_pipe;
1918 return NT_STATUS_OK;
1921 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1922 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1925 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1926 &result);
1927 if (netlogon_pipe == NULL) {
1928 return result;
1931 if (lp_client_schannel() != False) {
1932 neg_flags |= NETLOGON_NEG_SCHANNEL;
1935 /* if we are a DC and this is a trusted domain, then we need to use our
1936 domain name in the net_req_auth2() request */
1938 if ( IS_DC
1939 && !strequal(domain->name, lp_workgroup())
1940 && lp_allow_trusted_domains() )
1942 account_name = lp_workgroup();
1943 } else {
1944 account_name = domain->primary ?
1945 global_myname() : domain->name;
1948 if (account_name == NULL) {
1949 cli_rpc_pipe_close(netlogon_pipe);
1950 return NT_STATUS_NO_MEMORY;
1953 result = rpccli_netlogon_setup_creds(
1954 netlogon_pipe,
1955 domain->dcname, /* server name. */
1956 domain->name, /* domain name */
1957 global_myname(), /* client name */
1958 account_name, /* machine account */
1959 mach_pwd, /* machine password */
1960 sec_chan_type, /* from get_trust_pw */
1961 &neg_flags);
1963 if (!NT_STATUS_IS_OK(result)) {
1964 cli_rpc_pipe_close(netlogon_pipe);
1965 return result;
1968 if ((lp_client_schannel() == True) &&
1969 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1970 DEBUG(3, ("Server did not offer schannel\n"));
1971 cli_rpc_pipe_close(netlogon_pipe);
1972 return NT_STATUS_ACCESS_DENIED;
1975 if ((lp_client_schannel() == False) ||
1976 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1977 /* We're done - just keep the existing connection to NETLOGON
1978 * open */
1979 conn->netlogon_pipe = netlogon_pipe;
1980 *cli = conn->netlogon_pipe;
1981 return NT_STATUS_OK;
1984 /* Using the credentials from the first pipe, open a signed and sealed
1985 second netlogon pipe. The session key is stored in the schannel
1986 part of the new pipe auth struct.
1989 conn->netlogon_pipe =
1990 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1991 PI_NETLOGON,
1992 PIPE_AUTH_LEVEL_PRIVACY,
1993 domain->name,
1994 netlogon_pipe->dc,
1995 &result);
1997 /* We can now close the initial netlogon pipe. */
1998 cli_rpc_pipe_close(netlogon_pipe);
2000 if (conn->netlogon_pipe == NULL) {
2001 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2002 "was %s\n", nt_errstr(result)));
2004 /* make sure we return something besides OK */
2005 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2008 *cli = conn->netlogon_pipe;
2009 return NT_STATUS_OK;