r23602: grab final changes for 3.0.25b due out tomorrow
[Samba.git] / source / nsswitch / winbindd_cm.c
blobf96478fe5163c0c410e9ab7eb174c1bd4897c36d
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Gerald (Jerry) Carter 2003-2005.
9 Copyright (C) Volker Lendecke 2004-2005
10 Copyright (C) Jeremy Allison 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 We need to manage connections to domain controllers without having to
29 mess up the main winbindd code with other issues. The aim of the
30 connection manager is to:
32 - make connections to domain controllers and cache them
33 - re-establish connections when networks or servers go down
34 - centralise the policy on connection timeouts, domain controller
35 selection etc
36 - manage re-entrancy for when winbindd becomes able to handle
37 multiple outstanding rpc requests
39 Why not have connection management as part of the rpc layer like tng?
40 Good question. This code may morph into libsmb/rpc_cache.c or something
41 like that but at the moment it's simply staying as part of winbind. I
42 think the TNG architecture of forcing every user of the rpc layer to use
43 the connection caching system is a bad idea. It should be an optional
44 method of using the routines.
46 The TNG design is quite good but I disagree with some aspects of the
47 implementation. -tpot
52 TODO:
54 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
55 moved down into another function.
57 - Take care when destroying cli_structs as they can be shared between
58 various sam handles.
62 #include "includes.h"
63 #include "winbindd.h"
65 #undef DBGC_CLASS
66 #define DBGC_CLASS DBGC_WINBIND
68 struct dc_name_ip {
69 fstring name;
70 struct in_addr ip;
73 extern struct winbindd_methods reconnect_methods;
74 extern BOOL override_logfile;
76 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
77 static void set_dc_type_and_flags( struct winbindd_domain *domain );
78 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
79 struct dc_name_ip **dcs, int *num_dcs);
81 /****************************************************************
82 Child failed to find DC's. Reschedule check.
83 ****************************************************************/
85 static void msg_failed_to_go_online(int msg_type, struct process_id src,
86 void *buf, size_t len, void *private_data)
88 struct winbindd_domain *domain;
89 const char *domainname = (const char *)buf;
91 if (buf == NULL || len == 0) {
92 return;
95 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
97 for (domain = domain_list(); domain; domain = domain->next) {
98 if (domain->internal) {
99 continue;
102 if (strequal(domain->name, domainname)) {
103 if (domain->online) {
104 /* We're already online, ignore. */
105 DEBUG(5,("msg_fail_to_go_online: domain %s "
106 "already online.\n", domainname));
107 continue;
110 /* Reschedule the online check. */
111 set_domain_offline(domain);
112 break;
117 /****************************************************************
118 Actually cause a reconnect from a message.
119 ****************************************************************/
121 static void msg_try_to_go_online(int msg_type, struct process_id src,
122 void *buf, size_t len, void *private_data)
124 struct winbindd_domain *domain;
125 const char *domainname = (const char *)buf;
127 if (buf == NULL || len == 0) {
128 return;
131 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
133 for (domain = domain_list(); domain; domain = domain->next) {
134 if (domain->internal) {
135 continue;
138 if (strequal(domain->name, domainname)) {
140 if (domain->online) {
141 /* We're already online, ignore. */
142 DEBUG(5,("msg_try_to_go_online: domain %s "
143 "already online.\n", domainname));
144 continue;
147 /* This call takes care of setting the online
148 flag to true if we connected, or re-adding
149 the offline handler if false. Bypasses online
150 check so always does network calls. */
152 init_dc_connection_network(domain);
153 break;
158 /****************************************************************
159 Fork a child to try and contact a DC. Do this as contacting a
160 DC requires blocking lookups and we don't want to block our
161 parent.
162 ****************************************************************/
164 static BOOL fork_child_dc_connect(struct winbindd_domain *domain)
166 struct dc_name_ip *dcs = NULL;
167 int num_dcs = 0;
168 TALLOC_CTX *mem_ctx = NULL;
169 pid_t child_pid;
170 pid_t parent_pid = sys_getpid();
172 /* Stop zombies */
173 CatchChild();
175 message_block();
177 child_pid = sys_fork();
179 if (child_pid == -1) {
180 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
181 message_unblock();
182 return False;
185 if (child_pid != 0) {
186 /* Parent */
187 message_register(MSG_WINBIND_TRY_TO_GO_ONLINE,
188 msg_try_to_go_online, NULL);
189 message_register(MSG_WINBIND_FAILED_TO_GO_ONLINE,
190 msg_failed_to_go_online, NULL);
191 message_unblock();
192 return True;
195 /* Child. */
197 /* Leave messages blocked - we will never process one. */
199 /* tdb needs special fork handling */
200 if (tdb_reopen_all(1) == -1) {
201 DEBUG(0,("tdb_reopen_all failed.\n"));
202 _exit(0);
205 close_conns_after_fork();
207 if (!override_logfile) {
208 pstring logfile;
209 pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
210 lp_set_logfile(logfile);
211 reopen_logs();
214 mem_ctx = talloc_init("fork_child_dc_connect");
215 if (!mem_ctx) {
216 DEBUG(0,("talloc_init failed.\n"));
217 _exit(0);
220 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
221 /* Still offline ? Can't find DC's. */
222 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE,
223 domain->name,
224 strlen(domain->name)+1, False);
225 _exit(0);
228 /* We got a DC. Send a message to our parent to get it to
229 try and do the same. */
231 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE,
232 domain->name,
233 strlen(domain->name)+1, False);
234 _exit(0);
237 /****************************************************************
238 Handler triggered if we're offline to try and detect a DC.
239 ****************************************************************/
241 static void check_domain_online_handler(struct event_context *ctx,
242 struct timed_event *te,
243 const struct timeval *now,
244 void *private_data)
246 struct winbindd_domain *domain =
247 (struct winbindd_domain *)private_data;
249 DEBUG(10,("check_domain_online_handler: called for domain %s\n",
250 domain->name ));
252 TALLOC_FREE(domain->check_online_event);
254 /* Are we still in "startup" mode ? */
256 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
257 /* No longer in "startup" mode. */
258 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
259 domain->name ));
260 domain->startup = False;
263 /* We've been told to stay offline, so stay
264 that way. */
266 if (get_global_winbindd_state_offline()) {
267 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
268 domain->name ));
269 return;
272 /* Fork a child to test if it can contact a DC.
273 If it can then send ourselves a message to
274 cause a reconnect. */
276 fork_child_dc_connect(domain);
279 /****************************************************************
280 If we're still offline setup the timeout check.
281 ****************************************************************/
283 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
285 int wbc = lp_winbind_cache_time();
287 if (domain->startup) {
288 domain->check_online_timeout = 10;
289 } else if (domain->check_online_timeout < wbc) {
290 domain->check_online_timeout = wbc;
294 /****************************************************************
295 Set domain offline and also add handler to put us back online
296 if we detect a DC.
297 ****************************************************************/
299 void set_domain_offline(struct winbindd_domain *domain)
301 DEBUG(10,("set_domain_offline: called for domain %s\n",
302 domain->name ));
304 TALLOC_FREE(domain->check_online_event);
306 if (domain->internal) {
307 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
308 domain->name ));
309 return;
312 domain->online = False;
314 /* Offline domains are always initialized. They're
315 re-initialized when they go back online. */
317 domain->initialized = True;
319 /* We only add the timeout handler that checks and
320 allows us to go back online when we've not
321 been told to remain offline. */
323 if (get_global_winbindd_state_offline()) {
324 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
325 domain->name ));
326 return;
329 /* If we're in statup mode, check again in 10 seconds, not in
330 lp_winbind_cache_time() seconds (which is 5 mins by default). */
332 calc_new_online_timeout_check(domain);
334 domain->check_online_event = event_add_timed(winbind_event_context(),
335 NULL,
336 timeval_current_ofs(domain->check_online_timeout,0),
337 "check_domain_online_handler",
338 check_domain_online_handler,
339 domain);
341 /* The above *has* to succeed for winbindd to work. */
342 if (!domain->check_online_event) {
343 smb_panic("set_domain_offline: failed to add online handler.\n");
346 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
347 domain->name ));
350 /****************************************************************
351 Set domain online - if allowed.
352 ****************************************************************/
354 static void set_domain_online(struct winbindd_domain *domain)
356 struct timeval now;
358 DEBUG(10,("set_domain_online: called for domain %s\n",
359 domain->name ));
361 if (domain->internal) {
362 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
363 domain->name ));
364 return;
367 if (get_global_winbindd_state_offline()) {
368 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
369 domain->name ));
370 return;
373 /* If we are waiting to get a krb5 ticket, trigger immediately. */
374 GetTimeOfDay(&now);
375 set_event_dispatch_time(winbind_event_context(),
376 "krb5_ticket_gain_handler", now);
378 /* Ok, we're out of any startup mode now... */
379 domain->startup = False;
381 if (domain->online == False) {
382 /* We were offline - now we're online. We default to
383 using the MS-RPC backend if we started offline,
384 and if we're going online for the first time we
385 should really re-initialize the backends and the
386 checks to see if we're talking to an AD or NT domain.
389 domain->initialized = False;
391 /* 'reconnect_methods' is the MS-RPC backend. */
392 if (domain->backend == &reconnect_methods) {
393 domain->backend = NULL;
397 /* Ensure we have no online timeout checks. */
398 domain->check_online_timeout = 0;
399 TALLOC_FREE(domain->check_online_event);
401 /* Ensure we ignore any pending child messages. */
402 message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
403 message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
405 domain->online = True;
408 /****************************************************************
409 Requested to set a domain online.
410 ****************************************************************/
412 void set_domain_online_request(struct winbindd_domain *domain)
414 struct timeval tev;
416 DEBUG(10,("set_domain_online_request: called for domain %s\n",
417 domain->name ));
419 if (get_global_winbindd_state_offline()) {
420 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
421 domain->name ));
422 return;
425 /* We've been told it's safe to go online and
426 try and connect to a DC. But I don't believe it
427 because network manager seems to lie.
428 Wait at least 5 seconds. Heuristics suck... */
430 if (!domain->check_online_event) {
431 /* If we've come from being globally offline we
432 don't have a check online event handler set.
433 We need to add one now we're trying to go
434 back online. */
436 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
437 domain->name ));
439 domain->check_online_event = event_add_timed(winbind_event_context(),
440 NULL,
441 timeval_current_ofs(5, 0),
442 "check_domain_online_handler",
443 check_domain_online_handler,
444 domain);
446 /* The above *has* to succeed for winbindd to work. */
447 if (!domain->check_online_event) {
448 smb_panic("set_domain_online_request: failed to add online handler.\n");
452 GetTimeOfDay(&tev);
454 /* Go into "startup" mode again. */
455 domain->startup_time = tev.tv_sec;
456 domain->startup = True;
458 tev.tv_sec += 5;
460 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
463 /****************************************************************
464 Add -ve connection cache entries for domain and realm.
465 ****************************************************************/
467 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
468 const char *server,
469 NTSTATUS result)
471 add_failed_connection_entry(domain->name, server, result);
472 /* If this was the saf name for the last thing we talked to,
473 remove it. */
474 saf_delete(domain->name);
475 if (*domain->alt_name) {
476 add_failed_connection_entry(domain->alt_name, server, result);
477 saf_delete(domain->alt_name);
481 /* Choose between anonymous or authenticated connections. We need to use
482 an authenticated connection if DCs have the RestrictAnonymous registry
483 entry set > 0, or the "Additional restrictions for anonymous
484 connections" set in the win2k Local Security Policy.
486 Caller to free() result in domain, username, password
489 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
491 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
492 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
493 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
495 if (*username && **username) {
497 if (!*domain || !**domain)
498 *domain = smb_xstrdup(lp_workgroup());
500 if (!*password || !**password)
501 *password = smb_xstrdup("");
503 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
504 *domain, *username));
506 } else {
507 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
508 *username = smb_xstrdup("");
509 *domain = smb_xstrdup("");
510 *password = smb_xstrdup("");
514 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
515 fstring dcname, struct in_addr *dc_ip)
517 struct winbindd_domain *our_domain = NULL;
518 struct rpc_pipe_client *netlogon_pipe = NULL;
519 NTSTATUS result;
520 WERROR werr;
521 TALLOC_CTX *mem_ctx;
522 unsigned int orig_timeout;
523 fstring tmp;
524 char *p;
526 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
527 * moment.... */
529 if (IS_DC) {
530 return False;
533 if (domain->primary) {
534 return False;
537 our_domain = find_our_domain();
539 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
540 return False;
543 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
544 if (!NT_STATUS_IS_OK(result)) {
545 talloc_destroy(mem_ctx);
546 return False;
549 /* This call can take a long time - allow the server to time out.
550 35 seconds should do it. */
552 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
554 werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
555 domain->name, tmp);
557 /* And restore our original timeout. */
558 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
560 talloc_destroy(mem_ctx);
562 if (!W_ERROR_IS_OK(werr)) {
563 DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
564 dos_errstr(werr)));
565 return False;
568 /* cli_netlogon_getanydcname gives us a name with \\ */
569 p = tmp;
570 if (*p == '\\') {
571 p+=1;
573 if (*p == '\\') {
574 p+=1;
577 fstrcpy(dcname, p);
579 DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
581 if (!resolve_name(dcname, dc_ip, 0x20)) {
582 return False;
585 return True;
588 /************************************************************************
589 Given a fd with a just-connected TCP connection to a DC, open a connection
590 to the pipe.
591 ************************************************************************/
593 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
594 const int sockfd,
595 const char *controller,
596 struct cli_state **cli,
597 BOOL *retry)
599 char *machine_password, *machine_krb5_principal, *machine_account;
600 char *ipc_username, *ipc_domain, *ipc_password;
602 BOOL got_mutex;
604 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
606 struct sockaddr peeraddr;
607 socklen_t peeraddr_len;
609 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
611 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
612 controller, domain->name ));
614 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
615 NULL);
617 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
618 SAFE_FREE(machine_password);
619 return NT_STATUS_NO_MEMORY;
622 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
623 lp_realm()) == -1) {
624 SAFE_FREE(machine_account);
625 SAFE_FREE(machine_password);
626 return NT_STATUS_NO_MEMORY;
629 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
631 *retry = True;
633 got_mutex = secrets_named_mutex(controller,
634 WINBIND_SERVER_MUTEX_WAIT_TIME);
636 if (!got_mutex) {
637 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
638 controller));
639 result = NT_STATUS_POSSIBLE_DEADLOCK;
640 goto done;
643 if ((*cli = cli_initialise()) == NULL) {
644 DEBUG(1, ("Could not cli_initialize\n"));
645 result = NT_STATUS_NO_MEMORY;
646 goto done;
649 (*cli)->timeout = 10000; /* 10 seconds */
650 (*cli)->fd = sockfd;
651 fstrcpy((*cli)->desthost, controller);
652 (*cli)->use_kerberos = True;
654 peeraddr_len = sizeof(peeraddr);
656 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
657 (peeraddr_len != sizeof(struct sockaddr_in)) ||
658 (peeraddr_in->sin_family != PF_INET))
660 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
661 result = NT_STATUS_UNSUCCESSFUL;
662 goto done;
665 if (ntohs(peeraddr_in->sin_port) == 139) {
666 struct nmb_name calling;
667 struct nmb_name called;
669 make_nmb_name(&calling, global_myname(), 0x0);
670 make_nmb_name(&called, "*SMBSERVER", 0x20);
672 if (!cli_session_request(*cli, &calling, &called)) {
673 DEBUG(8, ("cli_session_request failed for %s\n",
674 controller));
675 result = NT_STATUS_UNSUCCESSFUL;
676 goto done;
680 cli_setup_signing_state(*cli, Undefined);
682 if (!cli_negprot(*cli)) {
683 DEBUG(1, ("cli_negprot failed\n"));
684 result = NT_STATUS_UNSUCCESSFUL;
685 goto done;
688 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
689 ADS_STATUS ads_status;
691 if (lp_security() == SEC_ADS) {
693 /* Try a krb5 session */
695 (*cli)->use_kerberos = True;
696 DEBUG(5, ("connecting to %s from %s with kerberos principal "
697 "[%s]\n", controller, global_myname(),
698 machine_krb5_principal));
700 ads_status = cli_session_setup_spnego(*cli,
701 machine_krb5_principal,
702 machine_password,
703 lp_workgroup());
705 if (!ADS_ERR_OK(ads_status)) {
706 DEBUG(4,("failed kerberos session setup with %s\n",
707 ads_errstr(ads_status)));
710 result = ads_ntstatus(ads_status);
711 if (NT_STATUS_IS_OK(result)) {
712 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
713 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
714 goto session_setup_done;
718 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
719 (*cli)->use_kerberos = False;
721 DEBUG(5, ("connecting to %s from %s with username "
722 "[%s]\\[%s]\n", controller, global_myname(),
723 lp_workgroup(), machine_account));
725 ads_status = cli_session_setup_spnego(*cli,
726 machine_account,
727 machine_password,
728 lp_workgroup());
729 if (!ADS_ERR_OK(ads_status)) {
730 DEBUG(4, ("authenticated session setup failed with %s\n",
731 ads_errstr(ads_status)));
734 result = ads_ntstatus(ads_status);
735 if (NT_STATUS_IS_OK(result)) {
736 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
737 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
738 goto session_setup_done;
742 /* Fall back to non-kerberos session setup */
744 (*cli)->use_kerberos = False;
746 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
747 (strlen(ipc_username) > 0)) {
749 /* Only try authenticated if we have a username */
751 DEBUG(5, ("connecting to %s from %s with username "
752 "[%s]\\[%s]\n", controller, global_myname(),
753 ipc_domain, ipc_username));
755 if (NT_STATUS_IS_OK(cli_session_setup(
756 *cli, ipc_username,
757 ipc_password, strlen(ipc_password)+1,
758 ipc_password, strlen(ipc_password)+1,
759 ipc_domain))) {
760 /* Successful logon with given username. */
761 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
762 goto session_setup_done;
763 } else {
764 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
765 ipc_domain, ipc_username ));
769 /* Fall back to anonymous connection, this might fail later */
771 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
772 NULL, 0, ""))) {
773 DEBUG(5, ("Connected anonymously\n"));
774 cli_init_creds(*cli, "", "", "");
775 goto session_setup_done;
778 result = cli_nt_error(*cli);
780 if (NT_STATUS_IS_OK(result))
781 result = NT_STATUS_UNSUCCESSFUL;
783 /* We can't session setup */
785 goto done;
787 session_setup_done:
789 /* cache the server name for later connections */
791 saf_store( domain->name, (*cli)->desthost );
792 if (domain->alt_name && (*cli)->use_kerberos) {
793 saf_store( domain->alt_name, (*cli)->desthost );
796 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
798 result = cli_nt_error(*cli);
800 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
802 if (NT_STATUS_IS_OK(result))
803 result = NT_STATUS_UNSUCCESSFUL;
805 goto done;
808 secrets_named_mutex_release(controller);
809 got_mutex = False;
810 *retry = False;
812 /* set the domain if empty; needed for schannel connections */
813 if ( !*(*cli)->domain ) {
814 fstrcpy( (*cli)->domain, domain->name );
817 result = NT_STATUS_OK;
819 done:
820 if (got_mutex) {
821 secrets_named_mutex_release(controller);
824 SAFE_FREE(machine_account);
825 SAFE_FREE(machine_password);
826 SAFE_FREE(machine_krb5_principal);
827 SAFE_FREE(ipc_username);
828 SAFE_FREE(ipc_domain);
829 SAFE_FREE(ipc_password);
831 if (!NT_STATUS_IS_OK(result)) {
832 winbind_add_failed_connection_entry(domain, controller, result);
833 if ((*cli) != NULL) {
834 cli_shutdown(*cli);
835 *cli = NULL;
839 return result;
842 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
843 const char *dcname, struct in_addr ip,
844 struct dc_name_ip **dcs, int *num)
846 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
847 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
848 return False;
851 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
853 if (*dcs == NULL)
854 return False;
856 fstrcpy((*dcs)[*num].name, dcname);
857 (*dcs)[*num].ip = ip;
858 *num += 1;
859 return True;
862 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
863 struct in_addr ip, uint16 port,
864 struct sockaddr_in **addrs, int *num)
866 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
868 if (*addrs == NULL) {
869 *num = 0;
870 return False;
873 (*addrs)[*num].sin_family = PF_INET;
874 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
875 (*addrs)[*num].sin_port = htons(port);
877 *num += 1;
878 return True;
881 static void mailslot_name(struct in_addr dc_ip, fstring name)
883 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
886 static BOOL send_getdc_request(struct in_addr dc_ip,
887 const char *domain_name,
888 const DOM_SID *sid)
890 pstring outbuf;
891 char *p;
892 fstring my_acct_name;
893 fstring my_mailslot;
895 mailslot_name(dc_ip, my_mailslot);
897 memset(outbuf, '\0', sizeof(outbuf));
899 p = outbuf;
901 SCVAL(p, 0, SAMLOGON);
902 p++;
904 SCVAL(p, 0, 0); /* Count pointer ... */
905 p++;
907 SIVAL(p, 0, 0); /* The sender's token ... */
908 p += 2;
910 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
911 fstr_sprintf(my_acct_name, "%s$", global_myname());
912 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
914 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
915 p += strlen(my_mailslot)+1;
917 SIVAL(p, 0, 0x80);
918 p+=4;
920 SIVAL(p, 0, sid_size(sid));
921 p+=4;
923 p = ALIGN4(p, outbuf);
925 sid_linearize(p, sid_size(sid), sid);
926 p += sid_size(sid);
928 SIVAL(p, 0, 1);
929 SSVAL(p, 4, 0xffff);
930 SSVAL(p, 6, 0xffff);
931 p+=8;
933 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
934 outbuf, PTR_DIFF(p, outbuf),
935 global_myname(), 0, domain_name, 0x1c,
936 dc_ip);
939 static BOOL receive_getdc_response(struct in_addr dc_ip,
940 const char *domain_name,
941 fstring dc_name)
943 struct packet_struct *packet;
944 fstring my_mailslot;
945 char *buf, *p;
946 fstring dcname, user, domain;
947 int len;
949 mailslot_name(dc_ip, my_mailslot);
951 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
953 if (packet == NULL) {
954 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
955 return False;
958 DEBUG(5, ("Received packet for %s\n", my_mailslot));
960 buf = packet->packet.dgram.data;
961 len = packet->packet.dgram.datasize;
963 if (len < 70) {
964 /* 70 is a completely arbitrary value to make sure
965 the SVAL below does not read uninitialized memory */
966 DEBUG(3, ("GetDC got short response\n"));
967 return False;
970 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
971 p = buf+SVAL(buf, smb_vwv10);
973 if (CVAL(p,0) != SAMLOGON_R) {
974 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
975 return False;
978 p+=2;
979 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
980 STR_TERMINATE|STR_NOALIGN);
981 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
982 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
983 STR_TERMINATE|STR_NOALIGN);
984 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
985 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
986 STR_TERMINATE|STR_NOALIGN);
987 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
989 if (!strequal(domain, domain_name)) {
990 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
991 domain_name, domain));
992 return False;
995 p = dcname;
996 if (*p == '\\') p += 1;
997 if (*p == '\\') p += 1;
999 fstrcpy(dc_name, p);
1001 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1002 dc_name, domain));
1004 return True;
1007 /*******************************************************************
1008 convert an ip to a name
1009 *******************************************************************/
1011 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1013 struct ip_service ip_list;
1015 ip_list.ip = ip;
1016 ip_list.port = 0;
1018 #ifdef WITH_ADS
1019 /* For active directory servers, try to get the ldap server name.
1020 None of these failures should be considered critical for now */
1022 if (lp_security() == SEC_ADS) {
1023 ADS_STRUCT *ads;
1025 ads = ads_init(domain->alt_name, domain->name, NULL);
1026 ads->auth.flags |= ADS_AUTH_NO_BIND;
1028 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1029 /* We got a cldap packet. */
1030 fstrcpy(name, ads->config.ldap_server_name);
1031 namecache_store(name, 0x20, 1, &ip_list);
1033 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1035 if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
1036 char *sitename = sitename_fetch(ads->config.realm);
1038 /* We're going to use this KDC for this realm/domain.
1039 If we are using sites, then force the krb5 libs
1040 to use this KDC. */
1042 create_local_private_krb5_conf_for_domain(domain->alt_name,
1043 domain->name,
1044 sitename,
1045 ip);
1047 SAFE_FREE(sitename);
1048 /* Ensure we contact this DC also. */
1049 saf_store( domain->name, name);
1050 saf_store( domain->alt_name, name);
1053 ads_destroy( &ads );
1054 return True;
1057 ads_destroy( &ads );
1059 #endif
1061 /* try GETDC requests next */
1063 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1064 int i;
1065 smb_msleep(100);
1066 for (i=0; i<5; i++) {
1067 if (receive_getdc_response(ip, domain->name, name)) {
1068 namecache_store(name, 0x20, 1, &ip_list);
1069 return True;
1071 smb_msleep(500);
1075 /* try node status request */
1077 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1078 namecache_store(name, 0x20, 1, &ip_list);
1079 return True;
1081 return False;
1084 /*******************************************************************
1085 Retreive a list of IP address for domain controllers. Fill in
1086 the dcs[] with results.
1087 *******************************************************************/
1089 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1090 struct dc_name_ip **dcs, int *num_dcs)
1092 fstring dcname;
1093 struct in_addr ip;
1094 struct ip_service *ip_list = NULL;
1095 int iplist_size = 0;
1096 int i;
1097 BOOL is_our_domain;
1098 enum security_types sec = (enum security_types)lp_security();
1100 is_our_domain = strequal(domain->name, lp_workgroup());
1102 if ( !is_our_domain
1103 && get_dc_name_via_netlogon(domain, dcname, &ip)
1104 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1106 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1107 dcname, inet_ntoa(ip)));
1108 return True;
1111 if (sec == SEC_ADS) {
1112 char *sitename = NULL;
1114 /* We need to make sure we know the local site before
1115 doing any DNS queries, as this will restrict the
1116 get_sorted_dc_list() call below to only fetching
1117 DNS records for the correct site. */
1119 /* Find any DC to get the site record.
1120 We deliberately don't care about the
1121 return here. */
1123 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
1125 sitename = sitename_fetch(domain->alt_name);
1126 if (sitename) {
1128 /* Do the site-specific AD dns lookup first. */
1129 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
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);
1137 SAFE_FREE(sitename);
1138 iplist_size = 0;
1141 /* Now we add DCs from the main AD dns lookup. */
1142 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1144 for ( i=0; i<iplist_size; i++ ) {
1145 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1146 ip_list[i].ip, dcs, num_dcs);
1150 /* try standard netbios queries if no ADS */
1152 if (iplist_size==0) {
1153 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1156 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1158 /* now add to the dc array. We'll wait until the last minute
1159 to look up the name of the DC. But we fill in the char* for
1160 the ip now in to make the failed connection cache work */
1162 for ( i=0; i<iplist_size; i++ ) {
1163 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1164 ip_list[i].ip, dcs, num_dcs);
1167 SAFE_FREE( ip_list );
1169 return True;
1172 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1173 const struct winbindd_domain *domain,
1174 fstring dcname, struct sockaddr_in *addr, int *fd)
1176 struct dc_name_ip *dcs = NULL;
1177 int num_dcs = 0;
1179 const char **dcnames = NULL;
1180 int num_dcnames = 0;
1182 struct sockaddr_in *addrs = NULL;
1183 int num_addrs = 0;
1185 int i, fd_index;
1187 again:
1188 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1189 return False;
1191 for (i=0; i<num_dcs; i++) {
1193 if (!add_string_to_array(mem_ctx, dcs[i].name,
1194 &dcnames, &num_dcnames)) {
1195 return False;
1197 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1198 &addrs, &num_addrs)) {
1199 return False;
1202 if (!add_string_to_array(mem_ctx, dcs[i].name,
1203 &dcnames, &num_dcnames)) {
1204 return False;
1206 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1207 &addrs, &num_addrs)) {
1208 return False;
1212 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1213 return False;
1215 if ((addrs == NULL) || (dcnames == NULL))
1216 return False;
1218 /* 5 second timeout. */
1219 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1221 for (i=0; i<num_dcs; i++) {
1222 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1223 "domain %s address %s. Error was %s\n",
1224 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1225 winbind_add_failed_connection_entry(domain,
1226 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1228 return False;
1231 *addr = addrs[fd_index];
1233 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1234 /* Ok, we've got a name for the DC */
1235 fstrcpy(dcname, dcnames[fd_index]);
1236 return True;
1239 /* Try to figure out the name */
1240 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1241 return True;
1244 /* We can not continue without the DC's name */
1245 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1246 NT_STATUS_UNSUCCESSFUL);
1247 goto again;
1250 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1251 struct winbindd_cm_conn *new_conn)
1253 TALLOC_CTX *mem_ctx;
1254 NTSTATUS result;
1255 char *saf_servername = saf_fetch( domain->name );
1256 int retries;
1258 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1259 SAFE_FREE(saf_servername);
1260 set_domain_offline(domain);
1261 return NT_STATUS_NO_MEMORY;
1264 /* we have to check the server affinity cache here since
1265 later we selecte a DC based on response time and not preference */
1267 /* Check the negative connection cache
1268 before talking to it. It going down may have
1269 triggered the reconnection. */
1271 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1273 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1274 saf_servername, domain->name ));
1276 /* convert an ip address to a name */
1277 if ( is_ipaddress( saf_servername ) ) {
1278 fstring saf_name;
1279 struct in_addr ip;
1281 ip = *interpret_addr2( saf_servername );
1282 if (dcip_to_name( domain, ip, saf_name )) {
1283 fstrcpy( domain->dcname, saf_name );
1284 } else {
1285 winbind_add_failed_connection_entry(
1286 domain, saf_servername,
1287 NT_STATUS_UNSUCCESSFUL);
1289 } else {
1290 fstrcpy( domain->dcname, saf_servername );
1293 SAFE_FREE( saf_servername );
1296 for (retries = 0; retries < 3; retries++) {
1298 int fd = -1;
1299 BOOL retry = False;
1301 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1303 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1304 domain->dcname, domain->name ));
1306 if (*domain->dcname
1307 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1308 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1310 struct sockaddr_in *addrs = NULL;
1311 int num_addrs = 0;
1312 int dummy = 0;
1314 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1315 set_domain_offline(domain);
1316 talloc_destroy(mem_ctx);
1317 return NT_STATUS_NO_MEMORY;
1319 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1320 set_domain_offline(domain);
1321 talloc_destroy(mem_ctx);
1322 return NT_STATUS_NO_MEMORY;
1325 /* 5 second timeout. */
1326 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1327 fd = -1;
1331 if ((fd == -1)
1332 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1334 /* This is the one place where we will
1335 set the global winbindd offline state
1336 to true, if a "WINBINDD_OFFLINE" entry
1337 is found in the winbindd cache. */
1338 set_global_winbindd_state_offline();
1339 break;
1342 new_conn->cli = NULL;
1344 result = cm_prepare_connection(domain, fd, domain->dcname,
1345 &new_conn->cli, &retry);
1347 if (!retry)
1348 break;
1351 if (NT_STATUS_IS_OK(result)) {
1352 if (domain->online == False) {
1353 /* We're changing state from offline to online. */
1354 set_global_winbindd_state_online();
1356 set_domain_online(domain);
1357 } else {
1358 /* Ensure we setup the retry handler. */
1359 set_domain_offline(domain);
1362 talloc_destroy(mem_ctx);
1363 return result;
1366 /* Close down all open pipes on a connection. */
1368 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1370 /* We're closing down a possibly dead
1371 connection. Don't have impossibly long (10s) timeouts. */
1373 if (conn->cli) {
1374 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1377 if (conn->samr_pipe != NULL) {
1378 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1379 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1380 if (conn->cli) {
1381 cli_set_timeout(conn->cli, 500);
1384 conn->samr_pipe = NULL;
1387 if (conn->lsa_pipe != NULL) {
1388 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1389 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1390 if (conn->cli) {
1391 cli_set_timeout(conn->cli, 500);
1394 conn->lsa_pipe = NULL;
1397 if (conn->netlogon_pipe != NULL) {
1398 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1399 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1400 if (conn->cli) {
1401 cli_set_timeout(conn->cli, 500);
1404 conn->netlogon_pipe = NULL;
1407 if (conn->cli) {
1408 cli_shutdown(conn->cli);
1411 conn->cli = NULL;
1414 void close_conns_after_fork(void)
1416 struct winbindd_domain *domain;
1418 for (domain = domain_list(); domain; domain = domain->next) {
1419 if (domain->conn.cli == NULL)
1420 continue;
1422 if (domain->conn.cli->fd == -1)
1423 continue;
1425 close(domain->conn.cli->fd);
1426 domain->conn.cli->fd = -1;
1430 static BOOL connection_ok(struct winbindd_domain *domain)
1432 if (domain->conn.cli == NULL) {
1433 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1434 "cli!\n", domain->dcname, domain->name));
1435 return False;
1438 if (!domain->conn.cli->initialised) {
1439 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1440 "initialised!\n", domain->dcname, domain->name));
1441 return False;
1444 if (domain->conn.cli->fd == -1) {
1445 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1446 "never started (fd == -1)\n",
1447 domain->dcname, domain->name));
1448 return False;
1451 if (domain->online == False) {
1452 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1453 return False;
1456 return True;
1459 /* Initialize a new connection up to the RPC BIND.
1460 Bypass online status check so always does network calls. */
1462 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1464 NTSTATUS result;
1466 /* Internal connections never use the network. */
1467 if (domain->internal) {
1468 domain->initialized = True;
1469 return NT_STATUS_OK;
1472 if (connection_ok(domain)) {
1473 if (!domain->initialized) {
1474 set_dc_type_and_flags(domain);
1476 return NT_STATUS_OK;
1479 invalidate_cm_connection(&domain->conn);
1481 result = cm_open_connection(domain, &domain->conn);
1483 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1484 set_dc_type_and_flags(domain);
1487 return result;
1490 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1492 if (domain->initialized && !domain->online) {
1493 /* We check for online status elsewhere. */
1494 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1497 return init_dc_connection_network(domain);
1500 /******************************************************************************
1501 We can 'sense' certain things about the DC by it's replies to certain
1502 questions.
1504 This tells us if this particular remote server is Active Directory, and if it
1505 is native mode.
1506 ******************************************************************************/
1508 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1510 NTSTATUS result;
1511 DS_DOMINFO_CTR ctr;
1512 TALLOC_CTX *mem_ctx = NULL;
1513 struct rpc_pipe_client *cli;
1514 POLICY_HND pol;
1516 char *domain_name = NULL;
1517 char *dns_name = NULL;
1518 char *forest_name = NULL;
1519 DOM_SID *dom_sid = NULL;
1521 ZERO_STRUCT( ctr );
1523 if (!connection_ok(domain)) {
1524 return;
1527 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1529 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1530 &result);
1532 if (cli == NULL) {
1533 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1534 "PI_LSARPC_DS on domain %s: (%s)\n",
1535 domain->name, nt_errstr(result)));
1537 /* if this is just a non-AD domain we need to continue
1538 * identifying so that we can in the end return with
1539 * domain->initialized = True - gd */
1541 goto no_lsarpc_ds;
1544 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1545 DsRolePrimaryDomainInfoBasic,
1546 &ctr);
1547 cli_rpc_pipe_close(cli);
1549 if (!NT_STATUS_IS_OK(result)) {
1550 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1551 "on domain %s failed: (%s)\n",
1552 domain->name, nt_errstr(result)));
1553 return;
1556 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1557 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1558 domain->native_mode = True;
1559 } else {
1560 domain->native_mode = False;
1563 no_lsarpc_ds:
1564 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1566 if (cli == NULL) {
1567 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1568 "PI_LSARPC on domain %s: (%s)\n",
1569 domain->name, nt_errstr(result)));
1570 cli_rpc_pipe_close(cli);
1571 return;
1574 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1575 domain->name);
1576 if (!mem_ctx) {
1577 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1578 cli_rpc_pipe_close(cli);
1579 return;
1582 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1583 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1585 if (NT_STATUS_IS_OK(result)) {
1586 /* This particular query is exactly what Win2k clients use
1587 to determine that the DC is active directory */
1588 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1589 12, &domain_name,
1590 &dns_name, &forest_name,
1591 NULL, &dom_sid);
1594 if (NT_STATUS_IS_OK(result)) {
1595 domain->active_directory = True;
1597 if (domain_name)
1598 fstrcpy(domain->name, domain_name);
1600 if (dns_name)
1601 fstrcpy(domain->alt_name, dns_name);
1603 if ( forest_name )
1604 fstrcpy(domain->forest_name, forest_name);
1606 if (dom_sid)
1607 sid_copy(&domain->sid, dom_sid);
1608 } else {
1609 domain->active_directory = False;
1611 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1612 SEC_RIGHTS_MAXIMUM_ALLOWED,
1613 &pol);
1615 if (!NT_STATUS_IS_OK(result))
1616 goto done;
1618 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1619 &pol, 5, &domain_name,
1620 &dom_sid);
1622 if (NT_STATUS_IS_OK(result)) {
1623 if (domain_name)
1624 fstrcpy(domain->name, domain_name);
1626 if (dom_sid)
1627 sid_copy(&domain->sid, dom_sid);
1630 done:
1632 DEBUG(5, ("set_dc_type_and_flags: domain %s is %sin native mode.\n",
1633 domain->name, domain->native_mode ? "" : "NOT "));
1635 DEBUG(5,("set_dc_type_and_flags: domain %s is %srunning active directory.\n",
1636 domain->name, domain->active_directory ? "" : "NOT "));
1638 cli_rpc_pipe_close(cli);
1640 talloc_destroy(mem_ctx);
1642 domain->initialized = True;
1645 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1646 struct dcinfo **ppdc)
1648 NTSTATUS result;
1649 struct rpc_pipe_client *netlogon_pipe;
1651 if (lp_client_schannel() == False) {
1652 return False;
1655 result = cm_connect_netlogon(domain, &netlogon_pipe);
1656 if (!NT_STATUS_IS_OK(result)) {
1657 return False;
1660 /* Return a pointer to the struct dcinfo from the
1661 netlogon pipe. */
1663 *ppdc = domain->conn.netlogon_pipe->dc;
1664 return True;
1667 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1668 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1670 struct winbindd_cm_conn *conn;
1671 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1672 fstring conn_pwd;
1673 struct dcinfo *p_dcinfo;
1675 result = init_dc_connection(domain);
1676 if (!NT_STATUS_IS_OK(result)) {
1677 return result;
1680 conn = &domain->conn;
1682 if (conn->samr_pipe != NULL) {
1683 goto done;
1687 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1688 * sign and sealed pipe using the machine account password by
1689 * preference. If we can't - try schannel, if that fails, try
1690 * anonymous.
1693 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1694 if ((conn->cli->user_name[0] == '\0') ||
1695 (conn->cli->domain[0] == '\0') ||
1696 (conn_pwd[0] == '\0')) {
1697 DEBUG(10, ("cm_connect_sam: No no user available for "
1698 "domain %s, trying schannel\n", conn->cli->domain));
1699 goto schannel;
1702 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1703 authenticated SAMR pipe with sign & seal. */
1704 conn->samr_pipe =
1705 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1706 PIPE_AUTH_LEVEL_PRIVACY,
1707 conn->cli->domain,
1708 conn->cli->user_name,
1709 conn_pwd, &result);
1711 if (conn->samr_pipe == NULL) {
1712 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1713 "pipe for domain %s using NTLMSSP "
1714 "authenticated pipe: user %s\\%s. Error was "
1715 "%s\n", domain->name, conn->cli->domain,
1716 conn->cli->user_name, nt_errstr(result)));
1717 goto schannel;
1720 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1721 "domain %s using NTLMSSP authenticated "
1722 "pipe: user %s\\%s\n", domain->name,
1723 conn->cli->domain, conn->cli->user_name ));
1725 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1726 SEC_RIGHTS_MAXIMUM_ALLOWED,
1727 &conn->sam_connect_handle);
1728 if (NT_STATUS_IS_OK(result)) {
1729 goto open_domain;
1731 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1732 "failed for domain %s, error was %s. Trying schannel\n",
1733 domain->name, nt_errstr(result) ));
1734 cli_rpc_pipe_close(conn->samr_pipe);
1736 schannel:
1738 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1740 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1741 /* If this call fails - conn->cli can now be NULL ! */
1742 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1743 "for domain %s, trying anon\n", domain->name));
1744 goto anonymous;
1746 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1747 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1748 domain->name, p_dcinfo, &result);
1750 if (conn->samr_pipe == NULL) {
1751 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1752 "domain %s using schannel. Error was %s\n",
1753 domain->name, nt_errstr(result) ));
1754 goto anonymous;
1756 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1757 "schannel.\n", domain->name ));
1759 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1760 SEC_RIGHTS_MAXIMUM_ALLOWED,
1761 &conn->sam_connect_handle);
1762 if (NT_STATUS_IS_OK(result)) {
1763 goto open_domain;
1765 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1766 "for domain %s, error was %s. Trying anonymous\n",
1767 domain->name, nt_errstr(result) ));
1768 cli_rpc_pipe_close(conn->samr_pipe);
1770 anonymous:
1772 /* Finally fall back to anonymous. */
1773 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1774 &result);
1776 if (conn->samr_pipe == NULL) {
1777 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1778 goto done;
1781 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1782 SEC_RIGHTS_MAXIMUM_ALLOWED,
1783 &conn->sam_connect_handle);
1784 if (!NT_STATUS_IS_OK(result)) {
1785 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1786 "for domain %s Error was %s\n",
1787 domain->name, nt_errstr(result) ));
1788 goto done;
1791 open_domain:
1792 result = rpccli_samr_open_domain(conn->samr_pipe,
1793 mem_ctx,
1794 &conn->sam_connect_handle,
1795 SEC_RIGHTS_MAXIMUM_ALLOWED,
1796 &domain->sid,
1797 &conn->sam_domain_handle);
1799 done:
1801 if (!NT_STATUS_IS_OK(result)) {
1802 invalidate_cm_connection(conn);
1803 return result;
1806 *cli = conn->samr_pipe;
1807 *sam_handle = conn->sam_domain_handle;
1808 return result;
1811 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1812 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1814 struct winbindd_cm_conn *conn;
1815 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1816 fstring conn_pwd;
1817 struct dcinfo *p_dcinfo;
1819 result = init_dc_connection(domain);
1820 if (!NT_STATUS_IS_OK(result))
1821 return result;
1823 conn = &domain->conn;
1825 if (conn->lsa_pipe != NULL) {
1826 goto done;
1829 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1830 if ((conn->cli->user_name[0] == '\0') ||
1831 (conn->cli->domain[0] == '\0') ||
1832 (conn_pwd[0] == '\0')) {
1833 DEBUG(10, ("cm_connect_lsa: No no user available for "
1834 "domain %s, trying schannel\n", conn->cli->domain));
1835 goto schannel;
1838 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1839 * authenticated LSA pipe with sign & seal. */
1840 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1841 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1842 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1844 if (conn->lsa_pipe == NULL) {
1845 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1846 "domain %s using NTLMSSP authenticated pipe: user "
1847 "%s\\%s. Error was %s. Trying schannel.\n",
1848 domain->name, conn->cli->domain,
1849 conn->cli->user_name, nt_errstr(result)));
1850 goto schannel;
1853 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1854 "NTLMSSP authenticated pipe: user %s\\%s\n",
1855 domain->name, conn->cli->domain, conn->cli->user_name ));
1857 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1858 SEC_RIGHTS_MAXIMUM_ALLOWED,
1859 &conn->lsa_policy);
1860 if (NT_STATUS_IS_OK(result)) {
1861 goto done;
1864 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1865 "schannel\n"));
1867 cli_rpc_pipe_close(conn->lsa_pipe);
1869 schannel:
1871 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1873 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1874 /* If this call fails - conn->cli can now be NULL ! */
1875 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1876 "for domain %s, trying anon\n", domain->name));
1877 goto anonymous;
1879 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1880 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1881 domain->name, p_dcinfo, &result);
1883 if (conn->lsa_pipe == NULL) {
1884 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1885 "domain %s using schannel. Error was %s\n",
1886 domain->name, nt_errstr(result) ));
1887 goto anonymous;
1889 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1890 "schannel.\n", domain->name ));
1892 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1893 SEC_RIGHTS_MAXIMUM_ALLOWED,
1894 &conn->lsa_policy);
1895 if (NT_STATUS_IS_OK(result)) {
1896 goto done;
1899 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1900 "anonymous\n"));
1902 cli_rpc_pipe_close(conn->lsa_pipe);
1904 anonymous:
1906 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1907 &result);
1908 if (conn->lsa_pipe == NULL) {
1909 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1910 goto done;
1913 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1914 SEC_RIGHTS_MAXIMUM_ALLOWED,
1915 &conn->lsa_policy);
1916 done:
1917 if (!NT_STATUS_IS_OK(result)) {
1918 invalidate_cm_connection(conn);
1919 return result;
1922 *cli = conn->lsa_pipe;
1923 *lsa_policy = conn->lsa_policy;
1924 return result;
1927 /****************************************************************************
1928 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1929 session key stored in conn->netlogon_pipe->dc->sess_key.
1930 ****************************************************************************/
1932 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1933 struct rpc_pipe_client **cli)
1935 struct winbindd_cm_conn *conn;
1936 NTSTATUS result;
1938 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1939 uint8 mach_pwd[16];
1940 uint32 sec_chan_type;
1941 const char *account_name;
1942 struct rpc_pipe_client *netlogon_pipe = NULL;
1944 *cli = NULL;
1946 result = init_dc_connection(domain);
1947 if (!NT_STATUS_IS_OK(result)) {
1948 return result;
1951 conn = &domain->conn;
1953 if (conn->netlogon_pipe != NULL) {
1954 *cli = conn->netlogon_pipe;
1955 return NT_STATUS_OK;
1958 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1959 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1962 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1963 &result);
1964 if (netlogon_pipe == NULL) {
1965 return result;
1968 if (lp_client_schannel() != False) {
1969 neg_flags |= NETLOGON_NEG_SCHANNEL;
1972 /* if we are a DC and this is a trusted domain, then we need to use our
1973 domain name in the net_req_auth2() request */
1975 if ( IS_DC
1976 && !strequal(domain->name, lp_workgroup())
1977 && lp_allow_trusted_domains() )
1979 account_name = lp_workgroup();
1980 } else {
1981 account_name = domain->primary ?
1982 global_myname() : domain->name;
1985 if (account_name == NULL) {
1986 cli_rpc_pipe_close(netlogon_pipe);
1987 return NT_STATUS_NO_MEMORY;
1990 result = rpccli_netlogon_setup_creds(
1991 netlogon_pipe,
1992 domain->dcname, /* server name. */
1993 domain->name, /* domain name */
1994 global_myname(), /* client name */
1995 account_name, /* machine account */
1996 mach_pwd, /* machine password */
1997 sec_chan_type, /* from get_trust_pw */
1998 &neg_flags);
2000 if (!NT_STATUS_IS_OK(result)) {
2001 cli_rpc_pipe_close(netlogon_pipe);
2002 return result;
2005 if ((lp_client_schannel() == True) &&
2006 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2007 DEBUG(3, ("Server did not offer schannel\n"));
2008 cli_rpc_pipe_close(netlogon_pipe);
2009 return NT_STATUS_ACCESS_DENIED;
2012 if ((lp_client_schannel() == False) ||
2013 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2014 /* We're done - just keep the existing connection to NETLOGON
2015 * open */
2016 conn->netlogon_pipe = netlogon_pipe;
2017 *cli = conn->netlogon_pipe;
2018 return NT_STATUS_OK;
2021 /* Using the credentials from the first pipe, open a signed and sealed
2022 second netlogon pipe. The session key is stored in the schannel
2023 part of the new pipe auth struct.
2026 conn->netlogon_pipe =
2027 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2028 PI_NETLOGON,
2029 PIPE_AUTH_LEVEL_PRIVACY,
2030 domain->name,
2031 netlogon_pipe->dc,
2032 &result);
2034 /* We can now close the initial netlogon pipe. */
2035 cli_rpc_pipe_close(netlogon_pipe);
2037 if (conn->netlogon_pipe == NULL) {
2038 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2039 "was %s\n", nt_errstr(result)));
2041 /* make sure we return something besides OK */
2042 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2045 *cli = conn->netlogon_pipe;
2046 return NT_STATUS_OK;