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 3 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
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
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
66 #define DBGC_CLASS DBGC_WINBIND
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(struct messaging_context *msg,
88 struct server_id server_id,
91 struct winbindd_domain *domain;
92 const char *domainname = (const char *)data->data;
94 if (data->data == NULL || data->length == 0) {
98 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
100 for (domain = domain_list(); domain; domain = domain->next) {
101 if (domain->internal) {
105 if (strequal(domain->name, domainname)) {
106 if (domain->online) {
107 /* We're already online, ignore. */
108 DEBUG(5,("msg_fail_to_go_online: domain %s "
109 "already online.\n", domainname));
113 /* Reschedule the online check. */
114 set_domain_offline(domain);
120 /****************************************************************
121 Actually cause a reconnect from a message.
122 ****************************************************************/
124 static void msg_try_to_go_online(struct messaging_context *msg,
127 struct server_id server_id,
130 struct winbindd_domain *domain;
131 const char *domainname = (const char *)data->data;
133 if (data->data == NULL || data->length == 0) {
137 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
139 for (domain = domain_list(); domain; domain = domain->next) {
140 if (domain->internal) {
144 if (strequal(domain->name, domainname)) {
146 if (domain->online) {
147 /* We're already online, ignore. */
148 DEBUG(5,("msg_try_to_go_online: domain %s "
149 "already online.\n", domainname));
153 /* This call takes care of setting the online
154 flag to true if we connected, or re-adding
155 the offline handler if false. Bypasses online
156 check so always does network calls. */
158 init_dc_connection_network(domain);
164 /****************************************************************
165 Fork a child to try and contact a DC. Do this as contacting a
166 DC requires blocking lookups and we don't want to block our
168 ****************************************************************/
170 static BOOL fork_child_dc_connect(struct winbindd_domain *domain)
172 struct dc_name_ip *dcs = NULL;
174 TALLOC_CTX *mem_ctx = NULL;
176 pid_t parent_pid = sys_getpid();
181 child_pid = sys_fork();
183 if (child_pid == -1) {
184 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
188 if (child_pid != 0) {
190 messaging_register(winbind_messaging_context(), NULL,
191 MSG_WINBIND_TRY_TO_GO_ONLINE,
192 msg_try_to_go_online);
193 messaging_register(winbind_messaging_context(), NULL,
194 MSG_WINBIND_FAILED_TO_GO_ONLINE,
195 msg_failed_to_go_online);
201 /* Leave messages blocked - we will never process one. */
203 /* tdb needs special fork handling */
204 if (tdb_reopen_all(1) == -1) {
205 DEBUG(0,("tdb_reopen_all failed.\n"));
209 close_conns_after_fork();
211 if (!override_logfile) {
213 pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
214 lp_set_logfile(logfile);
218 mem_ctx = talloc_init("fork_child_dc_connect");
220 DEBUG(0,("talloc_init failed.\n"));
224 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
225 /* Still offline ? Can't find DC's. */
226 messaging_send_buf(winbind_messaging_context(),
227 pid_to_procid(parent_pid),
228 MSG_WINBIND_FAILED_TO_GO_ONLINE,
229 (uint8 *)domain->name,
230 strlen(domain->name)+1);
234 /* We got a DC. Send a message to our parent to get it to
235 try and do the same. */
237 messaging_send_buf(winbind_messaging_context(),
238 pid_to_procid(parent_pid),
239 MSG_WINBIND_TRY_TO_GO_ONLINE,
240 (uint8 *)domain->name,
241 strlen(domain->name)+1);
245 /****************************************************************
246 Handler triggered if we're offline to try and detect a DC.
247 ****************************************************************/
249 static void check_domain_online_handler(struct event_context *ctx,
250 struct timed_event *te,
251 const struct timeval *now,
254 struct winbindd_domain *domain =
255 (struct winbindd_domain *)private_data;
257 DEBUG(10,("check_domain_online_handler: called for domain "
258 "%s (online = %s)\n", domain->name,
259 domain->online ? "True" : "False" ));
261 TALLOC_FREE(domain->check_online_event);
263 /* Are we still in "startup" mode ? */
265 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
266 /* No longer in "startup" mode. */
267 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
269 domain->startup = False;
272 /* We've been told to stay offline, so stay
275 if (get_global_winbindd_state_offline()) {
276 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
281 /* Fork a child to test if it can contact a DC.
282 If it can then send ourselves a message to
283 cause a reconnect. */
285 fork_child_dc_connect(domain);
288 /****************************************************************
289 If we're still offline setup the timeout check.
290 ****************************************************************/
292 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
294 int wbc = lp_winbind_cache_time();
296 if (domain->startup) {
297 domain->check_online_timeout = 10;
298 } else if (domain->check_online_timeout < wbc) {
299 domain->check_online_timeout = wbc;
303 /****************************************************************
304 Set domain offline and also add handler to put us back online
306 ****************************************************************/
308 void set_domain_offline(struct winbindd_domain *domain)
310 DEBUG(10,("set_domain_offline: called for domain %s\n",
313 TALLOC_FREE(domain->check_online_event);
315 if (domain->internal) {
316 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
321 domain->online = False;
323 /* Offline domains are always initialized. They're
324 re-initialized when they go back online. */
326 domain->initialized = True;
328 /* We only add the timeout handler that checks and
329 allows us to go back online when we've not
330 been told to remain offline. */
332 if (get_global_winbindd_state_offline()) {
333 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
338 /* If we're in statup mode, check again in 10 seconds, not in
339 lp_winbind_cache_time() seconds (which is 5 mins by default). */
341 calc_new_online_timeout_check(domain);
343 domain->check_online_event = event_add_timed(winbind_event_context(),
345 timeval_current_ofs(domain->check_online_timeout,0),
346 "check_domain_online_handler",
347 check_domain_online_handler,
350 /* The above *has* to succeed for winbindd to work. */
351 if (!domain->check_online_event) {
352 smb_panic("set_domain_offline: failed to add online handler");
355 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
358 /* Send an offline message to the idmap child when our
359 primary domain goes offline */
361 if ( domain->primary ) {
362 struct winbindd_child *idmap = idmap_child();
364 if ( idmap->pid != 0 ) {
365 messaging_send_buf(winbind_messaging_context(),
366 pid_to_procid(idmap->pid),
368 (uint8 *)domain->name,
369 strlen(domain->name)+1);
376 /****************************************************************
377 Set domain online - if allowed.
378 ****************************************************************/
380 static void set_domain_online(struct winbindd_domain *domain)
384 DEBUG(10,("set_domain_online: called for domain %s\n",
387 if (domain->internal) {
388 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
393 if (get_global_winbindd_state_offline()) {
394 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
399 /* If we are waiting to get a krb5 ticket, trigger immediately. */
401 set_event_dispatch_time(winbind_event_context(),
402 "krb5_ticket_gain_handler", now);
404 /* Ok, we're out of any startup mode now... */
405 domain->startup = False;
407 if (domain->online == False) {
408 /* We were offline - now we're online. We default to
409 using the MS-RPC backend if we started offline,
410 and if we're going online for the first time we
411 should really re-initialize the backends and the
412 checks to see if we're talking to an AD or NT domain.
415 domain->initialized = False;
417 /* 'reconnect_methods' is the MS-RPC backend. */
418 if (domain->backend == &reconnect_methods) {
419 domain->backend = NULL;
423 /* Ensure we have no online timeout checks. */
424 domain->check_online_timeout = 0;
425 TALLOC_FREE(domain->check_online_event);
427 /* Ensure we ignore any pending child messages. */
428 messaging_deregister(winbind_messaging_context(),
429 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
430 messaging_deregister(winbind_messaging_context(),
431 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
433 domain->online = True;
435 /* Send an online message to the idmap child when our
436 primary domain comes online */
438 if ( domain->primary ) {
439 struct winbindd_child *idmap = idmap_child();
441 if ( idmap->pid != 0 ) {
442 messaging_send_buf(winbind_messaging_context(),
443 pid_to_procid(idmap->pid),
445 (uint8 *)domain->name,
446 strlen(domain->name)+1);
453 /****************************************************************
454 Requested to set a domain online.
455 ****************************************************************/
457 void set_domain_online_request(struct winbindd_domain *domain)
461 DEBUG(10,("set_domain_online_request: called for domain %s\n",
464 if (get_global_winbindd_state_offline()) {
465 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
470 /* We've been told it's safe to go online and
471 try and connect to a DC. But I don't believe it
472 because network manager seems to lie.
473 Wait at least 5 seconds. Heuristics suck... */
475 if (!domain->check_online_event) {
476 /* If we've come from being globally offline we
477 don't have a check online event handler set.
478 We need to add one now we're trying to go
481 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
484 domain->check_online_event = event_add_timed(winbind_event_context(),
486 timeval_current_ofs(5, 0),
487 "check_domain_online_handler",
488 check_domain_online_handler,
491 /* The above *has* to succeed for winbindd to work. */
492 if (!domain->check_online_event) {
493 smb_panic("set_domain_online_request: failed to add online handler");
499 /* Go into "startup" mode again. */
500 domain->startup_time = tev.tv_sec;
501 domain->startup = True;
505 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
508 /****************************************************************
509 Add -ve connection cache entries for domain and realm.
510 ****************************************************************/
512 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
516 add_failed_connection_entry(domain->name, server, result);
517 /* If this was the saf name for the last thing we talked to,
519 saf_delete(domain->name);
520 if (*domain->alt_name) {
521 add_failed_connection_entry(domain->alt_name, server, result);
522 saf_delete(domain->alt_name);
526 /* Choose between anonymous or authenticated connections. We need to use
527 an authenticated connection if DCs have the RestrictAnonymous registry
528 entry set > 0, or the "Additional restrictions for anonymous
529 connections" set in the win2k Local Security Policy.
531 Caller to free() result in domain, username, password
534 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
536 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
537 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
538 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
540 if (*username && **username) {
542 if (!*domain || !**domain)
543 *domain = smb_xstrdup(lp_workgroup());
545 if (!*password || !**password)
546 *password = smb_xstrdup("");
548 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
549 *domain, *username));
552 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
553 *username = smb_xstrdup("");
554 *domain = smb_xstrdup("");
555 *password = smb_xstrdup("");
559 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
560 fstring dcname, struct in_addr *dc_ip)
562 struct winbindd_domain *our_domain = NULL;
563 struct rpc_pipe_client *netlogon_pipe = NULL;
567 unsigned int orig_timeout;
571 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
578 if (domain->primary) {
582 our_domain = find_our_domain();
584 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
588 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
589 if (!NT_STATUS_IS_OK(result)) {
590 talloc_destroy(mem_ctx);
594 /* This call can take a long time - allow the server to time out.
595 35 seconds should do it. */
597 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
599 werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
602 /* And restore our original timeout. */
603 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
605 talloc_destroy(mem_ctx);
607 if (!W_ERROR_IS_OK(werr)) {
608 DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
613 /* cli_netlogon_getanydcname gives us a name with \\ */
624 DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
626 if (!resolve_name(dcname, dc_ip, 0x20)) {
633 /************************************************************************
634 Given a fd with a just-connected TCP connection to a DC, open a connection
636 ************************************************************************/
638 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
640 const char *controller,
641 struct cli_state **cli,
644 char *machine_password, *machine_krb5_principal, *machine_account;
645 char *ipc_username, *ipc_domain, *ipc_password;
649 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
651 struct sockaddr peeraddr;
652 socklen_t peeraddr_len;
654 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
656 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
657 controller, domain->name ));
659 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
662 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
663 SAFE_FREE(machine_password);
664 return NT_STATUS_NO_MEMORY;
667 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
669 SAFE_FREE(machine_account);
670 SAFE_FREE(machine_password);
671 return NT_STATUS_NO_MEMORY;
674 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
678 got_mutex = secrets_named_mutex(controller,
679 WINBIND_SERVER_MUTEX_WAIT_TIME);
682 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
684 result = NT_STATUS_POSSIBLE_DEADLOCK;
688 if ((*cli = cli_initialise()) == NULL) {
689 DEBUG(1, ("Could not cli_initialize\n"));
690 result = NT_STATUS_NO_MEMORY;
694 (*cli)->timeout = 10000; /* 10 seconds */
696 fstrcpy((*cli)->desthost, controller);
697 (*cli)->use_kerberos = True;
699 peeraddr_len = sizeof(peeraddr);
701 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
702 (peeraddr_len != sizeof(struct sockaddr_in)) ||
703 (peeraddr_in->sin_family != PF_INET))
705 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
706 result = NT_STATUS_UNSUCCESSFUL;
710 if (ntohs(peeraddr_in->sin_port) == 139) {
711 struct nmb_name calling;
712 struct nmb_name called;
714 make_nmb_name(&calling, global_myname(), 0x0);
715 make_nmb_name(&called, "*SMBSERVER", 0x20);
717 if (!cli_session_request(*cli, &calling, &called)) {
718 DEBUG(8, ("cli_session_request failed for %s\n",
720 result = NT_STATUS_UNSUCCESSFUL;
725 cli_setup_signing_state(*cli, Undefined);
727 if (!cli_negprot(*cli)) {
728 DEBUG(1, ("cli_negprot failed\n"));
729 result = NT_STATUS_UNSUCCESSFUL;
733 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
734 ADS_STATUS ads_status;
736 if (lp_security() == SEC_ADS) {
738 /* Try a krb5 session */
740 (*cli)->use_kerberos = True;
741 DEBUG(5, ("connecting to %s from %s with kerberos principal "
742 "[%s]\n", controller, global_myname(),
743 machine_krb5_principal));
745 ads_status = cli_session_setup_spnego(*cli,
746 machine_krb5_principal,
750 if (!ADS_ERR_OK(ads_status)) {
751 DEBUG(4,("failed kerberos session setup with %s\n",
752 ads_errstr(ads_status)));
755 result = ads_ntstatus(ads_status);
756 if (NT_STATUS_IS_OK(result)) {
757 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
758 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
759 goto session_setup_done;
763 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
764 (*cli)->use_kerberos = False;
766 DEBUG(5, ("connecting to %s from %s with username "
767 "[%s]\\[%s]\n", controller, global_myname(),
768 lp_workgroup(), machine_account));
770 ads_status = cli_session_setup_spnego(*cli,
774 if (!ADS_ERR_OK(ads_status)) {
775 DEBUG(4, ("authenticated session setup failed with %s\n",
776 ads_errstr(ads_status)));
779 result = ads_ntstatus(ads_status);
780 if (NT_STATUS_IS_OK(result)) {
781 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
782 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
783 goto session_setup_done;
787 /* Fall back to non-kerberos session setup */
789 (*cli)->use_kerberos = False;
791 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
792 (strlen(ipc_username) > 0)) {
794 /* Only try authenticated if we have a username */
796 DEBUG(5, ("connecting to %s from %s with username "
797 "[%s]\\[%s]\n", controller, global_myname(),
798 ipc_domain, ipc_username));
800 if (NT_STATUS_IS_OK(cli_session_setup(
802 ipc_password, strlen(ipc_password)+1,
803 ipc_password, strlen(ipc_password)+1,
805 /* Successful logon with given username. */
806 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
807 goto session_setup_done;
809 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
810 ipc_domain, ipc_username ));
814 /* Fall back to anonymous connection, this might fail later */
816 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
818 DEBUG(5, ("Connected anonymously\n"));
819 cli_init_creds(*cli, "", "", "");
820 goto session_setup_done;
823 result = cli_nt_error(*cli);
825 if (NT_STATUS_IS_OK(result))
826 result = NT_STATUS_UNSUCCESSFUL;
828 /* We can't session setup */
834 /* cache the server name for later connections */
836 saf_store( domain->name, (*cli)->desthost );
837 if (domain->alt_name && (*cli)->use_kerberos) {
838 saf_store( domain->alt_name, (*cli)->desthost );
841 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
843 result = cli_nt_error(*cli);
845 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
847 if (NT_STATUS_IS_OK(result))
848 result = NT_STATUS_UNSUCCESSFUL;
853 secrets_named_mutex_release(controller);
857 /* set the domain if empty; needed for schannel connections */
858 if ( !*(*cli)->domain ) {
859 fstrcpy( (*cli)->domain, domain->name );
862 result = NT_STATUS_OK;
866 secrets_named_mutex_release(controller);
869 SAFE_FREE(machine_account);
870 SAFE_FREE(machine_password);
871 SAFE_FREE(machine_krb5_principal);
872 SAFE_FREE(ipc_username);
873 SAFE_FREE(ipc_domain);
874 SAFE_FREE(ipc_password);
876 if (!NT_STATUS_IS_OK(result)) {
877 winbind_add_failed_connection_entry(domain, controller, result);
878 if ((*cli) != NULL) {
887 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
888 const char *dcname, struct in_addr ip,
889 struct dc_name_ip **dcs, int *num)
891 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
892 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
896 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
901 fstrcpy((*dcs)[*num].name, dcname);
902 (*dcs)[*num].ip = ip;
907 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
908 struct in_addr ip, uint16 port,
909 struct sockaddr_in **addrs, int *num)
911 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
913 if (*addrs == NULL) {
918 (*addrs)[*num].sin_family = PF_INET;
919 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
920 (*addrs)[*num].sin_port = htons(port);
926 static void mailslot_name(struct in_addr dc_ip, fstring name)
928 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
931 static BOOL send_getdc_request(struct in_addr dc_ip,
932 const char *domain_name,
937 fstring my_acct_name;
940 mailslot_name(dc_ip, my_mailslot);
942 memset(outbuf, '\0', sizeof(outbuf));
946 SCVAL(p, 0, SAMLOGON);
949 SCVAL(p, 0, 0); /* Count pointer ... */
952 SIVAL(p, 0, 0); /* The sender's token ... */
955 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
956 fstr_sprintf(my_acct_name, "%s$", global_myname());
957 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
959 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
960 p += strlen(my_mailslot)+1;
965 SIVAL(p, 0, sid_size(sid));
968 p = ALIGN4(p, outbuf);
970 sid_linearize(p, sid_size(sid), sid);
978 return cli_send_mailslot(winbind_messaging_context(),
979 False, "\\MAILSLOT\\NET\\NTLOGON", 0,
980 outbuf, PTR_DIFF(p, outbuf),
981 global_myname(), 0, domain_name, 0x1c,
985 static BOOL receive_getdc_response(struct in_addr dc_ip,
986 const char *domain_name,
989 struct packet_struct *packet;
992 fstring dcname, user, domain;
995 mailslot_name(dc_ip, my_mailslot);
997 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
999 if (packet == NULL) {
1000 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
1004 DEBUG(5, ("Received packet for %s\n", my_mailslot));
1006 buf = packet->packet.dgram.data;
1007 len = packet->packet.dgram.datasize;
1010 /* 70 is a completely arbitrary value to make sure
1011 the SVAL below does not read uninitialized memory */
1012 DEBUG(3, ("GetDC got short response\n"));
1016 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
1017 p = buf+SVAL(buf, smb_vwv10);
1019 if (CVAL(p,0) != SAMLOGON_R) {
1020 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
1025 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1026 STR_TERMINATE|STR_NOALIGN);
1027 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1028 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1029 STR_TERMINATE|STR_NOALIGN);
1030 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1031 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1032 STR_TERMINATE|STR_NOALIGN);
1033 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1035 if (!strequal(domain, domain_name)) {
1036 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
1037 domain_name, domain));
1042 if (*p == '\\') p += 1;
1043 if (*p == '\\') p += 1;
1045 fstrcpy(dc_name, p);
1047 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1053 /*******************************************************************
1054 convert an ip to a name
1055 *******************************************************************/
1057 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1059 struct ip_service ip_list;
1065 /* For active directory servers, try to get the ldap server name.
1066 None of these failures should be considered critical for now */
1068 if (lp_security() == SEC_ADS) {
1071 ads = ads_init(domain->alt_name, domain->name, NULL);
1072 ads->auth.flags |= ADS_AUTH_NO_BIND;
1074 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1075 /* We got a cldap packet. */
1076 fstrcpy(name, ads->config.ldap_server_name);
1077 namecache_store(name, 0x20, 1, &ip_list);
1079 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1081 if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
1082 char *sitename = sitename_fetch(ads->config.realm);
1084 /* We're going to use this KDC for this realm/domain.
1085 If we are using sites, then force the krb5 libs
1088 create_local_private_krb5_conf_for_domain(domain->alt_name,
1093 SAFE_FREE(sitename);
1094 /* Ensure we contact this DC also. */
1095 saf_store( domain->name, name);
1096 saf_store( domain->alt_name, name);
1099 ads_destroy( &ads );
1103 ads_destroy( &ads );
1107 /* try GETDC requests next */
1109 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1112 for (i=0; i<5; i++) {
1113 if (receive_getdc_response(ip, domain->name, name)) {
1114 namecache_store(name, 0x20, 1, &ip_list);
1121 /* try node status request */
1123 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1124 namecache_store(name, 0x20, 1, &ip_list);
1130 /*******************************************************************
1131 Retreive a list of IP address for domain controllers. Fill in
1132 the dcs[] with results.
1133 *******************************************************************/
1135 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1136 struct dc_name_ip **dcs, int *num_dcs)
1140 struct ip_service *ip_list = NULL;
1141 int iplist_size = 0;
1144 enum security_types sec = (enum security_types)lp_security();
1146 is_our_domain = strequal(domain->name, lp_workgroup());
1149 && get_dc_name_via_netlogon(domain, dcname, &ip)
1150 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1152 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1153 dcname, inet_ntoa(ip)));
1157 if (sec == SEC_ADS) {
1158 char *sitename = NULL;
1160 /* We need to make sure we know the local site before
1161 doing any DNS queries, as this will restrict the
1162 get_sorted_dc_list() call below to only fetching
1163 DNS records for the correct site. */
1165 /* Find any DC to get the site record.
1166 We deliberately don't care about the
1169 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
1171 sitename = sitename_fetch(domain->alt_name);
1174 /* Do the site-specific AD dns lookup first. */
1175 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1177 for ( i=0; i<iplist_size; i++ ) {
1178 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1179 ip_list[i].ip, dcs, num_dcs);
1183 SAFE_FREE(sitename);
1187 /* Now we add DCs from the main AD dns lookup. */
1188 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1190 for ( i=0; i<iplist_size; i++ ) {
1191 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1192 ip_list[i].ip, dcs, num_dcs);
1196 /* try standard netbios queries if no ADS */
1198 if (iplist_size==0) {
1199 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1202 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1204 /* now add to the dc array. We'll wait until the last minute
1205 to look up the name of the DC. But we fill in the char* for
1206 the ip now in to make the failed connection cache work */
1208 for ( i=0; i<iplist_size; i++ ) {
1209 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1210 ip_list[i].ip, dcs, num_dcs);
1213 SAFE_FREE( ip_list );
1218 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1219 const struct winbindd_domain *domain,
1220 fstring dcname, struct sockaddr_in *addr, int *fd)
1222 struct dc_name_ip *dcs = NULL;
1225 const char **dcnames = NULL;
1226 int num_dcnames = 0;
1228 struct sockaddr_in *addrs = NULL;
1234 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1237 for (i=0; i<num_dcs; i++) {
1239 if (!add_string_to_array(mem_ctx, dcs[i].name,
1240 &dcnames, &num_dcnames)) {
1243 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1244 &addrs, &num_addrs)) {
1248 if (!add_string_to_array(mem_ctx, dcs[i].name,
1249 &dcnames, &num_dcnames)) {
1252 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1253 &addrs, &num_addrs)) {
1258 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1261 if ((addrs == NULL) || (dcnames == NULL))
1264 /* 5 second timeout. */
1265 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1267 for (i=0; i<num_dcs; i++) {
1268 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1269 "domain %s address %s. Error was %s\n",
1270 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1271 winbind_add_failed_connection_entry(domain,
1272 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1277 *addr = addrs[fd_index];
1279 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1280 /* Ok, we've got a name for the DC */
1281 fstrcpy(dcname, dcnames[fd_index]);
1285 /* Try to figure out the name */
1286 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1290 /* We can not continue without the DC's name */
1291 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1292 NT_STATUS_UNSUCCESSFUL);
1296 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1297 struct winbindd_cm_conn *new_conn)
1299 TALLOC_CTX *mem_ctx;
1301 char *saf_servername = saf_fetch( domain->name );
1304 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1305 SAFE_FREE(saf_servername);
1306 set_domain_offline(domain);
1307 return NT_STATUS_NO_MEMORY;
1310 /* we have to check the server affinity cache here since
1311 later we selecte a DC based on response time and not preference */
1313 /* Check the negative connection cache
1314 before talking to it. It going down may have
1315 triggered the reconnection. */
1317 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1319 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1320 saf_servername, domain->name ));
1322 /* convert an ip address to a name */
1323 if ( is_ipaddress( saf_servername ) ) {
1327 ip = *interpret_addr2( saf_servername );
1328 if (dcip_to_name( domain, ip, saf_name )) {
1329 fstrcpy( domain->dcname, saf_name );
1331 winbind_add_failed_connection_entry(
1332 domain, saf_servername,
1333 NT_STATUS_UNSUCCESSFUL);
1336 fstrcpy( domain->dcname, saf_servername );
1339 SAFE_FREE( saf_servername );
1342 for (retries = 0; retries < 3; retries++) {
1347 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1349 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1350 domain->dcname, domain->name ));
1353 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1354 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1356 struct sockaddr_in *addrs = NULL;
1360 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1361 set_domain_offline(domain);
1362 talloc_destroy(mem_ctx);
1363 return NT_STATUS_NO_MEMORY;
1365 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1366 set_domain_offline(domain);
1367 talloc_destroy(mem_ctx);
1368 return NT_STATUS_NO_MEMORY;
1371 /* 5 second timeout. */
1372 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1378 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1380 /* This is the one place where we will
1381 set the global winbindd offline state
1382 to true, if a "WINBINDD_OFFLINE" entry
1383 is found in the winbindd cache. */
1384 set_global_winbindd_state_offline();
1388 new_conn->cli = NULL;
1390 result = cm_prepare_connection(domain, fd, domain->dcname,
1391 &new_conn->cli, &retry);
1397 if (NT_STATUS_IS_OK(result)) {
1398 if (domain->online == False) {
1399 /* We're changing state from offline to online. */
1400 set_global_winbindd_state_online();
1402 set_domain_online(domain);
1404 /* Ensure we setup the retry handler. */
1405 set_domain_offline(domain);
1408 talloc_destroy(mem_ctx);
1412 /* Close down all open pipes on a connection. */
1414 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1416 /* We're closing down a possibly dead
1417 connection. Don't have impossibly long (10s) timeouts. */
1420 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1423 if (conn->samr_pipe != NULL) {
1424 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1425 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1427 cli_set_timeout(conn->cli, 500);
1430 conn->samr_pipe = NULL;
1433 if (conn->lsa_pipe != NULL) {
1434 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1435 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1437 cli_set_timeout(conn->cli, 500);
1440 conn->lsa_pipe = NULL;
1443 if (conn->netlogon_pipe != NULL) {
1444 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1445 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1447 cli_set_timeout(conn->cli, 500);
1450 conn->netlogon_pipe = NULL;
1454 cli_shutdown(conn->cli);
1460 void close_conns_after_fork(void)
1462 struct winbindd_domain *domain;
1464 for (domain = domain_list(); domain; domain = domain->next) {
1465 if (domain->conn.cli == NULL)
1468 if (domain->conn.cli->fd == -1)
1471 close(domain->conn.cli->fd);
1472 domain->conn.cli->fd = -1;
1476 static BOOL connection_ok(struct winbindd_domain *domain)
1478 if (domain->conn.cli == NULL) {
1479 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1480 "cli!\n", domain->dcname, domain->name));
1484 if (!domain->conn.cli->initialised) {
1485 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1486 "initialised!\n", domain->dcname, domain->name));
1490 if (domain->conn.cli->fd == -1) {
1491 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1492 "never started (fd == -1)\n",
1493 domain->dcname, domain->name));
1497 if (domain->online == False) {
1498 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1505 /* Initialize a new connection up to the RPC BIND.
1506 Bypass online status check so always does network calls. */
1508 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1512 /* Internal connections never use the network. */
1513 if (domain->internal) {
1514 domain->initialized = True;
1515 return NT_STATUS_OK;
1518 if (connection_ok(domain)) {
1519 if (!domain->initialized) {
1520 set_dc_type_and_flags(domain);
1522 return NT_STATUS_OK;
1525 invalidate_cm_connection(&domain->conn);
1527 result = cm_open_connection(domain, &domain->conn);
1529 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1530 set_dc_type_and_flags(domain);
1536 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1538 if (domain->initialized && !domain->online) {
1539 /* We check for online status elsewhere. */
1540 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1543 return init_dc_connection_network(domain);
1546 /******************************************************************************
1547 Set the trust flags (direction and forest location) for a domain
1548 ******************************************************************************/
1550 static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1552 struct winbindd_domain *our_domain;
1553 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1554 struct ds_domain_trust *domains = NULL;
1557 uint32 flags = (DS_DOMAIN_IN_FOREST |
1558 DS_DOMAIN_DIRECT_OUTBOUND |
1559 DS_DOMAIN_DIRECT_INBOUND);
1560 struct rpc_pipe_client *cli;
1561 TALLOC_CTX *mem_ctx = NULL;
1563 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1565 /* Our primary domain doesn't need to worry about trust flags.
1566 Force it to go through the network setup */
1567 if ( domain->primary ) {
1571 our_domain = find_our_domain();
1573 if ( !connection_ok(our_domain) ) {
1574 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1578 /* This won't work unless our domain is AD */
1580 if ( !our_domain->active_directory ) {
1584 /* Use DsEnumerateDomainTrusts to get us the trust direction
1587 result = cm_connect_netlogon(our_domain, &cli);
1589 if (!NT_STATUS_IS_OK(result)) {
1590 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1591 "a connection to %s for PIPE_NETLOGON (%s)\n",
1592 domain->name, nt_errstr(result)));
1596 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1597 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1601 result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
1604 (unsigned int *)&count);
1606 /* Now find the domain name and get the flags */
1608 for ( i=0; i<count; i++ ) {
1609 if ( strequal( domain->name, domains[i].netbios_domain ) ) {
1610 domain->domain_flags = domains[i].flags;
1611 domain->domain_type = domains[i].trust_type;
1612 domain->domain_trust_attribs = domains[i].trust_attributes;
1614 if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
1615 domain->active_directory = True;
1617 /* This flag is only set if the domain is *our*
1618 primary domain and the primary domain is in
1621 domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
1623 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1624 "native mode.\n", domain->name,
1625 domain->native_mode ? "" : "NOT "));
1627 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1628 "running active directory.\n", domain->name,
1629 domain->active_directory ? "" : "NOT "));
1632 domain->initialized = True;
1634 if ( !winbindd_can_contact_domain( domain) )
1635 domain->internal = True;
1641 talloc_destroy( mem_ctx );
1643 return domain->initialized;
1646 /******************************************************************************
1647 We can 'sense' certain things about the DC by it's replies to certain
1650 This tells us if this particular remote server is Active Directory, and if it
1652 ******************************************************************************/
1654 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1658 TALLOC_CTX *mem_ctx = NULL;
1659 struct rpc_pipe_client *cli;
1662 char *domain_name = NULL;
1663 char *dns_name = NULL;
1664 char *forest_name = NULL;
1665 DOM_SID *dom_sid = NULL;
1669 if (!connection_ok(domain)) {
1673 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1675 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1679 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1680 "PI_LSARPC_DS on domain %s: (%s)\n",
1681 domain->name, nt_errstr(result)));
1683 /* if this is just a non-AD domain we need to continue
1684 * identifying so that we can in the end return with
1685 * domain->initialized = True - gd */
1690 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1691 DsRolePrimaryDomainInfoBasic,
1693 cli_rpc_pipe_close(cli);
1695 if (!NT_STATUS_IS_OK(result)) {
1696 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1697 "on domain %s failed: (%s)\n",
1698 domain->name, nt_errstr(result)));
1702 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1703 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1704 domain->native_mode = True;
1706 domain->native_mode = False;
1710 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1713 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1714 "PI_LSARPC on domain %s: (%s)\n",
1715 domain->name, nt_errstr(result)));
1716 cli_rpc_pipe_close(cli);
1720 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1723 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1724 cli_rpc_pipe_close(cli);
1728 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1729 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1731 if (NT_STATUS_IS_OK(result)) {
1732 /* This particular query is exactly what Win2k clients use
1733 to determine that the DC is active directory */
1734 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1736 &dns_name, &forest_name,
1740 if (NT_STATUS_IS_OK(result)) {
1741 domain->active_directory = True;
1744 fstrcpy(domain->name, domain_name);
1747 fstrcpy(domain->alt_name, dns_name);
1750 fstrcpy(domain->forest_name, forest_name);
1753 sid_copy(&domain->sid, dom_sid);
1755 domain->active_directory = False;
1757 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1758 SEC_RIGHTS_MAXIMUM_ALLOWED,
1761 if (!NT_STATUS_IS_OK(result))
1764 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1765 &pol, 5, &domain_name,
1768 if (NT_STATUS_IS_OK(result)) {
1770 fstrcpy(domain->name, domain_name);
1773 sid_copy(&domain->sid, dom_sid);
1778 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1779 domain->name, domain->native_mode ? "" : "NOT "));
1781 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1782 domain->name, domain->active_directory ? "" : "NOT "));
1784 cli_rpc_pipe_close(cli);
1786 talloc_destroy(mem_ctx);
1788 domain->initialized = True;
1791 /**********************************************************************
1792 Set the domain_flags (trust attributes, domain operating modes, etc...
1793 ***********************************************************************/
1795 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1797 /* we always have to contact our primary domain */
1799 if ( domain->primary ) {
1800 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1801 "primary domain\n"));
1802 set_dc_type_and_flags_connect( domain );
1806 /* Use our DC to get the information if possible */
1808 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1809 /* Otherwise, fallback to contacting the
1811 set_dc_type_and_flags_connect( domain );
1819 /**********************************************************************
1820 ***********************************************************************/
1822 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1823 struct dcinfo **ppdc)
1826 struct rpc_pipe_client *netlogon_pipe;
1828 if (lp_client_schannel() == False) {
1832 result = cm_connect_netlogon(domain, &netlogon_pipe);
1833 if (!NT_STATUS_IS_OK(result)) {
1837 /* Return a pointer to the struct dcinfo from the
1840 *ppdc = domain->conn.netlogon_pipe->dc;
1844 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1845 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1847 struct winbindd_cm_conn *conn;
1848 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1850 struct dcinfo *p_dcinfo;
1852 result = init_dc_connection(domain);
1853 if (!NT_STATUS_IS_OK(result)) {
1857 conn = &domain->conn;
1859 if (conn->samr_pipe != NULL) {
1864 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1865 * sign and sealed pipe using the machine account password by
1866 * preference. If we can't - try schannel, if that fails, try
1870 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1871 if ((conn->cli->user_name[0] == '\0') ||
1872 (conn->cli->domain[0] == '\0') ||
1873 (conn_pwd[0] == '\0')) {
1874 DEBUG(10, ("cm_connect_sam: No no user available for "
1875 "domain %s, trying schannel\n", conn->cli->domain));
1879 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1880 authenticated SAMR pipe with sign & seal. */
1882 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1883 PIPE_AUTH_LEVEL_PRIVACY,
1885 conn->cli->user_name,
1888 if (conn->samr_pipe == NULL) {
1889 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1890 "pipe for domain %s using NTLMSSP "
1891 "authenticated pipe: user %s\\%s. Error was "
1892 "%s\n", domain->name, conn->cli->domain,
1893 conn->cli->user_name, nt_errstr(result)));
1897 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1898 "domain %s using NTLMSSP authenticated "
1899 "pipe: user %s\\%s\n", domain->name,
1900 conn->cli->domain, conn->cli->user_name ));
1902 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1903 SEC_RIGHTS_MAXIMUM_ALLOWED,
1904 &conn->sam_connect_handle);
1905 if (NT_STATUS_IS_OK(result)) {
1908 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1909 "failed for domain %s, error was %s. Trying schannel\n",
1910 domain->name, nt_errstr(result) ));
1911 cli_rpc_pipe_close(conn->samr_pipe);
1915 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1917 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1918 /* If this call fails - conn->cli can now be NULL ! */
1919 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1920 "for domain %s, trying anon\n", domain->name));
1923 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1924 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1925 domain->name, p_dcinfo, &result);
1927 if (conn->samr_pipe == NULL) {
1928 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1929 "domain %s using schannel. Error was %s\n",
1930 domain->name, nt_errstr(result) ));
1933 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1934 "schannel.\n", domain->name ));
1936 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1937 SEC_RIGHTS_MAXIMUM_ALLOWED,
1938 &conn->sam_connect_handle);
1939 if (NT_STATUS_IS_OK(result)) {
1942 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1943 "for domain %s, error was %s. Trying anonymous\n",
1944 domain->name, nt_errstr(result) ));
1945 cli_rpc_pipe_close(conn->samr_pipe);
1949 /* Finally fall back to anonymous. */
1950 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1953 if (conn->samr_pipe == NULL) {
1954 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1958 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1959 SEC_RIGHTS_MAXIMUM_ALLOWED,
1960 &conn->sam_connect_handle);
1961 if (!NT_STATUS_IS_OK(result)) {
1962 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1963 "for domain %s Error was %s\n",
1964 domain->name, nt_errstr(result) ));
1969 result = rpccli_samr_open_domain(conn->samr_pipe,
1971 &conn->sam_connect_handle,
1972 SEC_RIGHTS_MAXIMUM_ALLOWED,
1974 &conn->sam_domain_handle);
1978 if (!NT_STATUS_IS_OK(result)) {
1979 invalidate_cm_connection(conn);
1983 *cli = conn->samr_pipe;
1984 *sam_handle = conn->sam_domain_handle;
1988 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1989 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1991 struct winbindd_cm_conn *conn;
1992 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1994 struct dcinfo *p_dcinfo;
1996 result = init_dc_connection(domain);
1997 if (!NT_STATUS_IS_OK(result))
2000 conn = &domain->conn;
2002 if (conn->lsa_pipe != NULL) {
2006 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2007 if ((conn->cli->user_name[0] == '\0') ||
2008 (conn->cli->domain[0] == '\0') ||
2009 (conn_pwd[0] == '\0')) {
2010 DEBUG(10, ("cm_connect_lsa: No no user available for "
2011 "domain %s, trying schannel\n", conn->cli->domain));
2015 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2016 * authenticated LSA pipe with sign & seal. */
2017 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
2018 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2019 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
2021 if (conn->lsa_pipe == NULL) {
2022 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2023 "domain %s using NTLMSSP authenticated pipe: user "
2024 "%s\\%s. Error was %s. Trying schannel.\n",
2025 domain->name, conn->cli->domain,
2026 conn->cli->user_name, nt_errstr(result)));
2030 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2031 "NTLMSSP authenticated pipe: user %s\\%s\n",
2032 domain->name, conn->cli->domain, conn->cli->user_name ));
2034 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2035 SEC_RIGHTS_MAXIMUM_ALLOWED,
2037 if (NT_STATUS_IS_OK(result)) {
2041 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2044 cli_rpc_pipe_close(conn->lsa_pipe);
2048 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2050 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2051 /* If this call fails - conn->cli can now be NULL ! */
2052 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2053 "for domain %s, trying anon\n", domain->name));
2056 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
2057 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2058 domain->name, p_dcinfo, &result);
2060 if (conn->lsa_pipe == NULL) {
2061 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2062 "domain %s using schannel. Error was %s\n",
2063 domain->name, nt_errstr(result) ));
2066 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2067 "schannel.\n", domain->name ));
2069 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2070 SEC_RIGHTS_MAXIMUM_ALLOWED,
2072 if (NT_STATUS_IS_OK(result)) {
2076 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2079 cli_rpc_pipe_close(conn->lsa_pipe);
2083 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
2085 if (conn->lsa_pipe == NULL) {
2086 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2090 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2091 SEC_RIGHTS_MAXIMUM_ALLOWED,
2094 if (!NT_STATUS_IS_OK(result)) {
2095 invalidate_cm_connection(conn);
2099 *cli = conn->lsa_pipe;
2100 *lsa_policy = conn->lsa_policy;
2104 /****************************************************************************
2105 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2106 session key stored in conn->netlogon_pipe->dc->sess_key.
2107 ****************************************************************************/
2109 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2110 struct rpc_pipe_client **cli)
2112 struct winbindd_cm_conn *conn;
2115 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
2117 uint32 sec_chan_type;
2118 const char *account_name;
2119 struct rpc_pipe_client *netlogon_pipe = NULL;
2123 result = init_dc_connection(domain);
2124 if (!NT_STATUS_IS_OK(result)) {
2128 conn = &domain->conn;
2130 if (conn->netlogon_pipe != NULL) {
2131 *cli = conn->netlogon_pipe;
2132 return NT_STATUS_OK;
2135 if (domain->primary && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
2136 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2139 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
2141 if (netlogon_pipe == NULL) {
2145 if ( !domain->primary ) {
2146 /* Clear the schannel request bit and drop down */
2147 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2151 if (lp_client_schannel() != False) {
2152 neg_flags |= NETLOGON_NEG_SCHANNEL;
2155 /* if we are a DC and this is a trusted domain, then we need to use our
2156 domain name in the net_req_auth2() request */
2159 && !strequal(domain->name, lp_workgroup())
2160 && lp_allow_trusted_domains() )
2162 account_name = lp_workgroup();
2164 account_name = domain->primary ?
2165 global_myname() : domain->name;
2168 if (account_name == NULL) {
2169 cli_rpc_pipe_close(netlogon_pipe);
2170 return NT_STATUS_NO_MEMORY;
2173 result = rpccli_netlogon_setup_creds(
2175 domain->dcname, /* server name. */
2176 domain->name, /* domain name */
2177 global_myname(), /* client name */
2178 account_name, /* machine account */
2179 mach_pwd, /* machine password */
2180 sec_chan_type, /* from get_trust_pw */
2183 if (!NT_STATUS_IS_OK(result)) {
2184 cli_rpc_pipe_close(netlogon_pipe);
2188 if ((lp_client_schannel() == True) &&
2189 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2190 DEBUG(3, ("Server did not offer schannel\n"));
2191 cli_rpc_pipe_close(netlogon_pipe);
2192 return NT_STATUS_ACCESS_DENIED;
2196 if ((lp_client_schannel() == False) ||
2197 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2200 * NetSamLogonEx only works for schannel
2202 domain->can_do_samlogon_ex = False;
2204 /* We're done - just keep the existing connection to NETLOGON
2206 conn->netlogon_pipe = netlogon_pipe;
2207 *cli = conn->netlogon_pipe;
2208 return NT_STATUS_OK;
2211 /* Using the credentials from the first pipe, open a signed and sealed
2212 second netlogon pipe. The session key is stored in the schannel
2213 part of the new pipe auth struct.
2216 conn->netlogon_pipe =
2217 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2219 PIPE_AUTH_LEVEL_PRIVACY,
2224 /* We can now close the initial netlogon pipe. */
2225 cli_rpc_pipe_close(netlogon_pipe);
2227 if (conn->netlogon_pipe == NULL) {
2228 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2229 "was %s\n", nt_errstr(result)));
2231 /* make sure we return something besides OK */
2232 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2236 * Try NetSamLogonEx for AD domains
2238 domain->can_do_samlogon_ex = domain->active_directory;
2240 *cli = conn->netlogon_pipe;
2241 return NT_STATUS_OK;