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
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();
183 child_pid = sys_fork();
185 if (child_pid == -1) {
186 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
191 if (child_pid != 0) {
193 messaging_register(winbind_messaging_context(), NULL,
194 MSG_WINBIND_TRY_TO_GO_ONLINE,
195 msg_try_to_go_online);
196 messaging_register(winbind_messaging_context(), NULL,
197 MSG_WINBIND_FAILED_TO_GO_ONLINE,
198 msg_failed_to_go_online);
205 /* Leave messages blocked - we will never process one. */
207 /* tdb needs special fork handling */
208 if (tdb_reopen_all(1) == -1) {
209 DEBUG(0,("tdb_reopen_all failed.\n"));
213 close_conns_after_fork();
215 if (!override_logfile) {
217 pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
218 lp_set_logfile(logfile);
222 mem_ctx = talloc_init("fork_child_dc_connect");
224 DEBUG(0,("talloc_init failed.\n"));
228 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
229 /* Still offline ? Can't find DC's. */
230 messaging_send_buf(winbind_messaging_context(),
231 pid_to_procid(parent_pid),
232 MSG_WINBIND_FAILED_TO_GO_ONLINE,
233 (uint8 *)domain->name,
234 strlen(domain->name)+1);
238 /* We got a DC. Send a message to our parent to get it to
239 try and do the same. */
241 messaging_send_buf(winbind_messaging_context(),
242 pid_to_procid(parent_pid),
243 MSG_WINBIND_TRY_TO_GO_ONLINE,
244 (uint8 *)domain->name,
245 strlen(domain->name)+1);
249 /****************************************************************
250 Handler triggered if we're offline to try and detect a DC.
251 ****************************************************************/
253 static void check_domain_online_handler(struct event_context *ctx,
254 struct timed_event *te,
255 const struct timeval *now,
258 struct winbindd_domain *domain =
259 (struct winbindd_domain *)private_data;
261 DEBUG(10,("check_domain_online_handler: called for domain "
262 "%s (online = %s)\n", domain->name,
263 domain->online ? "True" : "False" ));
265 if (domain->check_online_event) {
266 TALLOC_FREE(domain->check_online_event);
269 /* Are we still in "startup" mode ? */
271 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
272 /* No longer in "startup" mode. */
273 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
275 domain->startup = False;
278 /* We've been told to stay offline, so stay
281 if (get_global_winbindd_state_offline()) {
282 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
287 /* Fork a child to test if it can contact a DC.
288 If it can then send ourselves a message to
289 cause a reconnect. */
291 fork_child_dc_connect(domain);
294 /****************************************************************
295 If we're still offline setup the timeout check.
296 ****************************************************************/
298 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
300 int wbc = lp_winbind_cache_time();
302 if (domain->startup) {
303 domain->check_online_timeout = 10;
304 } else if (domain->check_online_timeout < wbc) {
305 domain->check_online_timeout = wbc;
309 /****************************************************************
310 Set domain offline and also add handler to put us back online
312 ****************************************************************/
314 void set_domain_offline(struct winbindd_domain *domain)
316 DEBUG(10,("set_domain_offline: called for domain %s\n",
319 if (domain->check_online_event) {
320 TALLOC_FREE(domain->check_online_event);
323 if (domain->internal) {
324 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
329 domain->online = False;
331 /* Offline domains are always initialized. They're
332 re-initialized when they go back online. */
334 domain->initialized = True;
336 /* We only add the timeout handler that checks and
337 allows us to go back online when we've not
338 been told to remain offline. */
340 if (get_global_winbindd_state_offline()) {
341 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
346 /* If we're in statup mode, check again in 10 seconds, not in
347 lp_winbind_cache_time() seconds (which is 5 mins by default). */
349 calc_new_online_timeout_check(domain);
351 domain->check_online_event = event_add_timed(winbind_event_context(),
353 timeval_current_ofs(domain->check_online_timeout,0),
354 "check_domain_online_handler",
355 check_domain_online_handler,
358 /* The above *has* to succeed for winbindd to work. */
359 if (!domain->check_online_event) {
360 smb_panic("set_domain_offline: failed to add online handler.\n");
363 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
366 /* Send an offline message to the idmap child when our
367 primary domain goes offline */
369 if ( domain->primary ) {
370 struct winbindd_child *idmap = idmap_child();
372 if ( idmap->pid != 0 ) {
373 messaging_send_buf(winbind_messaging_context(),
374 pid_to_procid(idmap->pid),
376 (uint8 *)domain->name,
377 strlen(domain->name)+1);
384 /****************************************************************
385 Set domain online - if allowed.
386 ****************************************************************/
388 static void set_domain_online(struct winbindd_domain *domain)
392 DEBUG(10,("set_domain_online: called for domain %s\n",
395 if (domain->internal) {
396 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
401 if (get_global_winbindd_state_offline()) {
402 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
407 /* If we are waiting to get a krb5 ticket, trigger immediately. */
409 set_event_dispatch_time(winbind_event_context(),
410 "krb5_ticket_gain_handler", now);
412 /* Ok, we're out of any startup mode now... */
413 domain->startup = False;
415 if (domain->online == False) {
416 /* We were offline - now we're online. We default to
417 using the MS-RPC backend if we started offline,
418 and if we're going online for the first time we
419 should really re-initialize the backends and the
420 checks to see if we're talking to an AD or NT domain.
423 domain->initialized = False;
425 /* 'reconnect_methods' is the MS-RPC backend. */
426 if (domain->backend == &reconnect_methods) {
427 domain->backend = NULL;
431 /* Ensure we have no online timeout checks. */
432 domain->check_online_timeout = 0;
433 if (domain->check_online_event) {
434 TALLOC_FREE(domain->check_online_event);
437 /* Ensure we ignore any pending child messages. */
438 messaging_deregister(winbind_messaging_context(),
439 MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
440 messaging_deregister(winbind_messaging_context(),
441 MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
443 domain->online = True;
445 /* Send an online message to the idmap child when our
446 primary domain comes online */
448 if ( domain->primary ) {
449 struct winbindd_child *idmap = idmap_child();
451 if ( idmap->pid != 0 ) {
452 messaging_send_buf(winbind_messaging_context(),
453 pid_to_procid(idmap->pid),
455 (uint8 *)domain->name,
456 strlen(domain->name)+1);
463 /****************************************************************
464 Requested to set a domain online.
465 ****************************************************************/
467 void set_domain_online_request(struct winbindd_domain *domain)
471 DEBUG(10,("set_domain_online_request: called for domain %s\n",
474 if (get_global_winbindd_state_offline()) {
475 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
480 /* We've been told it's safe to go online and
481 try and connect to a DC. But I don't believe it
482 because network manager seems to lie.
483 Wait at least 5 seconds. Heuristics suck... */
485 if (!domain->check_online_event) {
486 /* If we've come from being globally offline we
487 don't have a check online event handler set.
488 We need to add one now we're trying to go
491 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
494 domain->check_online_event = event_add_timed(winbind_event_context(),
496 timeval_current_ofs(5, 0),
497 "check_domain_online_handler",
498 check_domain_online_handler,
501 /* The above *has* to succeed for winbindd to work. */
502 if (!domain->check_online_event) {
503 smb_panic("set_domain_online_request: failed to add online handler.\n");
509 /* Go into "startup" mode again. */
510 domain->startup_time = tev.tv_sec;
511 domain->startup = True;
515 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
518 /****************************************************************
519 Add -ve connection cache entries for domain and realm.
520 ****************************************************************/
522 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
526 add_failed_connection_entry(domain->name, server, result);
527 /* If this was the saf name for the last thing we talked to,
529 saf_delete(domain->name);
530 if (*domain->alt_name) {
531 add_failed_connection_entry(domain->alt_name, server, result);
532 saf_delete(domain->alt_name);
536 /* Choose between anonymous or authenticated connections. We need to use
537 an authenticated connection if DCs have the RestrictAnonymous registry
538 entry set > 0, or the "Additional restrictions for anonymous
539 connections" set in the win2k Local Security Policy.
541 Caller to free() result in domain, username, password
544 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
546 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
547 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
548 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
550 if (*username && **username) {
552 if (!*domain || !**domain)
553 *domain = smb_xstrdup(lp_workgroup());
555 if (!*password || !**password)
556 *password = smb_xstrdup("");
558 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
559 *domain, *username));
562 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
563 *username = smb_xstrdup("");
564 *domain = smb_xstrdup("");
565 *password = smb_xstrdup("");
569 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
570 fstring dcname, struct in_addr *dc_ip)
572 struct winbindd_domain *our_domain = NULL;
573 struct rpc_pipe_client *netlogon_pipe = NULL;
577 unsigned int orig_timeout;
581 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
588 if (domain->primary) {
592 our_domain = find_our_domain();
594 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
598 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
599 if (!NT_STATUS_IS_OK(result)) {
600 talloc_destroy(mem_ctx);
604 /* This call can take a long time - allow the server to time out.
605 35 seconds should do it. */
607 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
609 werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
612 /* And restore our original timeout. */
613 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
615 talloc_destroy(mem_ctx);
617 if (!W_ERROR_IS_OK(werr)) {
618 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
623 /* cli_netlogon_getdcname gives us a name with \\ */
634 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
636 if (!resolve_name(dcname, dc_ip, 0x20)) {
643 /************************************************************************
644 Given a fd with a just-connected TCP connection to a DC, open a connection
646 ************************************************************************/
648 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
650 const char *controller,
651 struct cli_state **cli,
654 char *machine_password, *machine_krb5_principal, *machine_account;
655 char *ipc_username, *ipc_domain, *ipc_password;
659 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
661 struct sockaddr peeraddr;
662 socklen_t peeraddr_len;
664 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
666 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
667 controller, domain->name ));
669 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
672 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
673 SAFE_FREE(machine_password);
674 return NT_STATUS_NO_MEMORY;
677 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
679 SAFE_FREE(machine_account);
680 SAFE_FREE(machine_password);
681 return NT_STATUS_NO_MEMORY;
684 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
688 got_mutex = secrets_named_mutex(controller,
689 WINBIND_SERVER_MUTEX_WAIT_TIME);
692 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
694 result = NT_STATUS_POSSIBLE_DEADLOCK;
698 if ((*cli = cli_initialise()) == NULL) {
699 DEBUG(1, ("Could not cli_initialize\n"));
700 result = NT_STATUS_NO_MEMORY;
704 (*cli)->timeout = 10000; /* 10 seconds */
706 fstrcpy((*cli)->desthost, controller);
707 (*cli)->use_kerberos = True;
709 peeraddr_len = sizeof(peeraddr);
711 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
712 (peeraddr_len != sizeof(struct sockaddr_in)) ||
713 (peeraddr_in->sin_family != PF_INET))
715 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
716 result = NT_STATUS_UNSUCCESSFUL;
720 if (ntohs(peeraddr_in->sin_port) == 139) {
721 struct nmb_name calling;
722 struct nmb_name called;
724 make_nmb_name(&calling, global_myname(), 0x0);
725 make_nmb_name(&called, "*SMBSERVER", 0x20);
727 if (!cli_session_request(*cli, &calling, &called)) {
728 DEBUG(8, ("cli_session_request failed for %s\n",
730 result = NT_STATUS_UNSUCCESSFUL;
735 cli_setup_signing_state(*cli, Undefined);
737 if (!cli_negprot(*cli)) {
738 DEBUG(1, ("cli_negprot failed\n"));
739 result = NT_STATUS_UNSUCCESSFUL;
743 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
744 ADS_STATUS ads_status;
746 if (lp_security() == SEC_ADS) {
748 /* Try a krb5 session */
750 (*cli)->use_kerberos = True;
751 DEBUG(5, ("connecting to %s from %s with kerberos principal "
752 "[%s]\n", controller, global_myname(),
753 machine_krb5_principal));
755 ads_status = cli_session_setup_spnego(*cli,
756 machine_krb5_principal,
760 if (!ADS_ERR_OK(ads_status)) {
761 DEBUG(4,("failed kerberos session setup with %s\n",
762 ads_errstr(ads_status)));
765 result = ads_ntstatus(ads_status);
766 if (NT_STATUS_IS_OK(result)) {
767 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
768 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
769 goto session_setup_done;
773 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
774 (*cli)->use_kerberos = False;
776 DEBUG(5, ("connecting to %s from %s with username "
777 "[%s]\\[%s]\n", controller, global_myname(),
778 lp_workgroup(), machine_account));
780 ads_status = cli_session_setup_spnego(*cli,
784 if (!ADS_ERR_OK(ads_status)) {
785 DEBUG(4, ("authenticated session setup failed with %s\n",
786 ads_errstr(ads_status)));
789 result = ads_ntstatus(ads_status);
790 if (NT_STATUS_IS_OK(result)) {
791 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
792 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
793 goto session_setup_done;
797 /* Fall back to non-kerberos session setup */
799 (*cli)->use_kerberos = False;
801 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
802 (strlen(ipc_username) > 0)) {
804 /* Only try authenticated if we have a username */
806 DEBUG(5, ("connecting to %s from %s with username "
807 "[%s]\\[%s]\n", controller, global_myname(),
808 ipc_domain, ipc_username));
810 if (NT_STATUS_IS_OK(cli_session_setup(
812 ipc_password, strlen(ipc_password)+1,
813 ipc_password, strlen(ipc_password)+1,
815 /* Successful logon with given username. */
816 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
817 goto session_setup_done;
819 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
820 ipc_domain, ipc_username ));
824 /* Fall back to anonymous connection, this might fail later */
826 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
828 DEBUG(5, ("Connected anonymously\n"));
829 cli_init_creds(*cli, "", "", "");
830 goto session_setup_done;
833 result = cli_nt_error(*cli);
835 if (NT_STATUS_IS_OK(result))
836 result = NT_STATUS_UNSUCCESSFUL;
838 /* We can't session setup */
844 /* cache the server name for later connections */
846 saf_store( domain->name, (*cli)->desthost );
847 if (domain->alt_name && (*cli)->use_kerberos) {
848 saf_store( domain->alt_name, (*cli)->desthost );
851 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
853 result = cli_nt_error(*cli);
855 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
857 if (NT_STATUS_IS_OK(result))
858 result = NT_STATUS_UNSUCCESSFUL;
863 secrets_named_mutex_release(controller);
867 /* set the domain if empty; needed for schannel connections */
868 if ( !*(*cli)->domain ) {
869 fstrcpy( (*cli)->domain, domain->name );
872 result = NT_STATUS_OK;
876 secrets_named_mutex_release(controller);
879 SAFE_FREE(machine_account);
880 SAFE_FREE(machine_password);
881 SAFE_FREE(machine_krb5_principal);
882 SAFE_FREE(ipc_username);
883 SAFE_FREE(ipc_domain);
884 SAFE_FREE(ipc_password);
886 if (!NT_STATUS_IS_OK(result)) {
887 winbind_add_failed_connection_entry(domain, controller, result);
888 if ((*cli) != NULL) {
897 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
898 const char *dcname, struct in_addr ip,
899 struct dc_name_ip **dcs, int *num)
901 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
902 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
906 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
911 fstrcpy((*dcs)[*num].name, dcname);
912 (*dcs)[*num].ip = ip;
917 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
918 struct in_addr ip, uint16 port,
919 struct sockaddr_in **addrs, int *num)
921 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
923 if (*addrs == NULL) {
928 (*addrs)[*num].sin_family = PF_INET;
929 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
930 (*addrs)[*num].sin_port = htons(port);
936 static void mailslot_name(struct in_addr dc_ip, fstring name)
938 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
941 static BOOL send_getdc_request(struct in_addr dc_ip,
942 const char *domain_name,
947 fstring my_acct_name;
950 mailslot_name(dc_ip, my_mailslot);
952 memset(outbuf, '\0', sizeof(outbuf));
956 SCVAL(p, 0, SAMLOGON);
959 SCVAL(p, 0, 0); /* Count pointer ... */
962 SIVAL(p, 0, 0); /* The sender's token ... */
965 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
966 fstr_sprintf(my_acct_name, "%s$", global_myname());
967 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
969 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
970 p += strlen(my_mailslot)+1;
975 SIVAL(p, 0, sid_size(sid));
978 p = ALIGN4(p, outbuf);
980 sid_linearize(p, sid_size(sid), sid);
988 return cli_send_mailslot(winbind_messaging_context(),
989 False, "\\MAILSLOT\\NET\\NTLOGON", 0,
990 outbuf, PTR_DIFF(p, outbuf),
991 global_myname(), 0, domain_name, 0x1c,
995 static BOOL receive_getdc_response(struct in_addr dc_ip,
996 const char *domain_name,
999 struct packet_struct *packet;
1000 fstring my_mailslot;
1002 fstring dcname, user, domain;
1005 mailslot_name(dc_ip, my_mailslot);
1007 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
1009 if (packet == NULL) {
1010 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
1014 DEBUG(5, ("Received packet for %s\n", my_mailslot));
1016 buf = packet->packet.dgram.data;
1017 len = packet->packet.dgram.datasize;
1020 /* 70 is a completely arbitrary value to make sure
1021 the SVAL below does not read uninitialized memory */
1022 DEBUG(3, ("GetDC got short response\n"));
1026 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
1027 p = buf+SVAL(buf, smb_vwv10);
1029 if (CVAL(p,0) != SAMLOGON_R) {
1030 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
1035 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1036 STR_TERMINATE|STR_NOALIGN);
1037 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1038 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1039 STR_TERMINATE|STR_NOALIGN);
1040 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1041 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1042 STR_TERMINATE|STR_NOALIGN);
1043 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1045 if (!strequal(domain, domain_name)) {
1046 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
1047 domain_name, domain));
1052 if (*p == '\\') p += 1;
1053 if (*p == '\\') p += 1;
1055 fstrcpy(dc_name, p);
1057 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1063 /*******************************************************************
1064 convert an ip to a name
1065 *******************************************************************/
1067 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1069 struct ip_service ip_list;
1075 /* For active directory servers, try to get the ldap server name.
1076 None of these failures should be considered critical for now */
1078 if (lp_security() == SEC_ADS) {
1081 ads = ads_init(domain->alt_name, domain->name, NULL);
1082 ads->auth.flags |= ADS_AUTH_NO_BIND;
1084 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1085 /* We got a cldap packet. */
1086 fstrcpy(name, ads->config.ldap_server_name);
1087 namecache_store(name, 0x20, 1, &ip_list);
1089 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1091 if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
1092 char *sitename = sitename_fetch(ads->config.realm);
1094 /* We're going to use this KDC for this realm/domain.
1095 If we are using sites, then force the krb5 libs
1098 create_local_private_krb5_conf_for_domain(domain->alt_name,
1103 SAFE_FREE(sitename);
1104 /* Ensure we contact this DC also. */
1105 saf_store( domain->name, name);
1106 saf_store( domain->alt_name, name);
1109 ads_destroy( &ads );
1113 ads_destroy( &ads );
1117 /* try GETDC requests next */
1119 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1122 for (i=0; i<5; i++) {
1123 if (receive_getdc_response(ip, domain->name, name)) {
1124 namecache_store(name, 0x20, 1, &ip_list);
1131 /* try node status request */
1133 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1134 namecache_store(name, 0x20, 1, &ip_list);
1140 /*******************************************************************
1141 Retreive a list of IP address for domain controllers. Fill in
1142 the dcs[] with results.
1143 *******************************************************************/
1145 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1146 struct dc_name_ip **dcs, int *num_dcs)
1150 struct ip_service *ip_list = NULL;
1151 int iplist_size = 0;
1154 enum security_types sec = (enum security_types)lp_security();
1156 is_our_domain = strequal(domain->name, lp_workgroup());
1159 && get_dc_name_via_netlogon(domain, dcname, &ip)
1160 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1162 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1163 dcname, inet_ntoa(ip)));
1167 if (sec == SEC_ADS) {
1168 char *sitename = NULL;
1170 /* We need to make sure we know the local site before
1171 doing any DNS queries, as this will restrict the
1172 get_sorted_dc_list() call below to only fetching
1173 DNS records for the correct site. */
1175 /* Find any DC to get the site record.
1176 We deliberately don't care about the
1179 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
1181 sitename = sitename_fetch(domain->alt_name);
1184 /* Do the site-specific AD dns lookup first. */
1185 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1187 for ( i=0; i<iplist_size; i++ ) {
1188 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1189 ip_list[i].ip, dcs, num_dcs);
1193 SAFE_FREE(sitename);
1197 /* Now we add DCs from the main AD dns lookup. */
1198 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1200 for ( i=0; i<iplist_size; i++ ) {
1201 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1202 ip_list[i].ip, dcs, num_dcs);
1206 /* try standard netbios queries if no ADS */
1208 if (iplist_size==0) {
1209 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1212 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1214 /* now add to the dc array. We'll wait until the last minute
1215 to look up the name of the DC. But we fill in the char* for
1216 the ip now in to make the failed connection cache work */
1218 for ( i=0; i<iplist_size; i++ ) {
1219 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1220 ip_list[i].ip, dcs, num_dcs);
1223 SAFE_FREE( ip_list );
1228 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1229 const struct winbindd_domain *domain,
1230 fstring dcname, struct sockaddr_in *addr, int *fd)
1232 struct dc_name_ip *dcs = NULL;
1235 const char **dcnames = NULL;
1236 int num_dcnames = 0;
1238 struct sockaddr_in *addrs = NULL;
1244 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1247 for (i=0; i<num_dcs; i++) {
1249 if (!add_string_to_array(mem_ctx, dcs[i].name,
1250 &dcnames, &num_dcnames)) {
1253 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1254 &addrs, &num_addrs)) {
1258 if (!add_string_to_array(mem_ctx, dcs[i].name,
1259 &dcnames, &num_dcnames)) {
1262 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1263 &addrs, &num_addrs)) {
1268 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1271 if ((addrs == NULL) || (dcnames == NULL))
1274 /* 5 second timeout. */
1275 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1277 for (i=0; i<num_dcs; i++) {
1278 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1279 "domain %s address %s. Error was %s\n",
1280 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1281 winbind_add_failed_connection_entry(domain,
1282 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1287 *addr = addrs[fd_index];
1289 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1290 /* Ok, we've got a name for the DC */
1291 fstrcpy(dcname, dcnames[fd_index]);
1295 /* Try to figure out the name */
1296 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1300 /* We can not continue without the DC's name */
1301 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1302 NT_STATUS_UNSUCCESSFUL);
1306 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1307 struct winbindd_cm_conn *new_conn)
1309 TALLOC_CTX *mem_ctx;
1311 char *saf_servername = saf_fetch( domain->name );
1314 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1315 SAFE_FREE(saf_servername);
1316 set_domain_offline(domain);
1317 return NT_STATUS_NO_MEMORY;
1320 /* we have to check the server affinity cache here since
1321 later we selecte a DC based on response time and not preference */
1323 /* Check the negative connection cache
1324 before talking to it. It going down may have
1325 triggered the reconnection. */
1327 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1329 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1330 saf_servername, domain->name ));
1332 /* convert an ip address to a name */
1333 if ( is_ipaddress( saf_servername ) ) {
1337 ip = *interpret_addr2( saf_servername );
1338 if (dcip_to_name( domain, ip, saf_name )) {
1339 fstrcpy( domain->dcname, saf_name );
1341 winbind_add_failed_connection_entry(
1342 domain, saf_servername,
1343 NT_STATUS_UNSUCCESSFUL);
1346 fstrcpy( domain->dcname, saf_servername );
1349 SAFE_FREE( saf_servername );
1352 for (retries = 0; retries < 3; retries++) {
1357 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1359 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1360 domain->dcname, domain->name ));
1363 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1364 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1366 struct sockaddr_in *addrs = NULL;
1370 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1371 set_domain_offline(domain);
1372 talloc_destroy(mem_ctx);
1373 return NT_STATUS_NO_MEMORY;
1375 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1376 set_domain_offline(domain);
1377 talloc_destroy(mem_ctx);
1378 return NT_STATUS_NO_MEMORY;
1381 /* 5 second timeout. */
1382 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1388 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1390 /* This is the one place where we will
1391 set the global winbindd offline state
1392 to true, if a "WINBINDD_OFFLINE" entry
1393 is found in the winbindd cache. */
1394 set_global_winbindd_state_offline();
1398 new_conn->cli = NULL;
1400 result = cm_prepare_connection(domain, fd, domain->dcname,
1401 &new_conn->cli, &retry);
1407 if (NT_STATUS_IS_OK(result)) {
1408 if (domain->online == False) {
1409 /* We're changing state from offline to online. */
1410 set_global_winbindd_state_online();
1412 set_domain_online(domain);
1414 /* Ensure we setup the retry handler. */
1415 set_domain_offline(domain);
1418 talloc_destroy(mem_ctx);
1422 /* Close down all open pipes on a connection. */
1424 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1426 /* We're closing down a possibly dead
1427 connection. Don't have impossibly long (10s) timeouts. */
1430 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1433 if (conn->samr_pipe != NULL) {
1434 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1435 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1437 cli_set_timeout(conn->cli, 500);
1440 conn->samr_pipe = NULL;
1443 if (conn->lsa_pipe != NULL) {
1444 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1445 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1447 cli_set_timeout(conn->cli, 500);
1450 conn->lsa_pipe = NULL;
1453 if (conn->netlogon_pipe != NULL) {
1454 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1455 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1457 cli_set_timeout(conn->cli, 500);
1460 conn->netlogon_pipe = NULL;
1464 cli_shutdown(conn->cli);
1470 void close_conns_after_fork(void)
1472 struct winbindd_domain *domain;
1474 for (domain = domain_list(); domain; domain = domain->next) {
1475 if (domain->conn.cli == NULL)
1478 if (domain->conn.cli->fd == -1)
1481 close(domain->conn.cli->fd);
1482 domain->conn.cli->fd = -1;
1486 static BOOL connection_ok(struct winbindd_domain *domain)
1488 if (domain->conn.cli == NULL) {
1489 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1490 "cli!\n", domain->dcname, domain->name));
1494 if (!domain->conn.cli->initialised) {
1495 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1496 "initialised!\n", domain->dcname, domain->name));
1500 if (domain->conn.cli->fd == -1) {
1501 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1502 "never started (fd == -1)\n",
1503 domain->dcname, domain->name));
1507 if (domain->online == False) {
1508 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1515 /* Initialize a new connection up to the RPC BIND.
1516 Bypass online status check so always does network calls. */
1518 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1522 /* Internal connections never use the network. */
1523 if (domain->internal) {
1524 domain->initialized = True;
1525 return NT_STATUS_OK;
1528 if (connection_ok(domain)) {
1529 if (!domain->initialized) {
1530 set_dc_type_and_flags(domain);
1532 return NT_STATUS_OK;
1535 invalidate_cm_connection(&domain->conn);
1537 result = cm_open_connection(domain, &domain->conn);
1539 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1540 set_dc_type_and_flags(domain);
1546 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1548 if (domain->initialized && !domain->online) {
1549 /* We check for online status elsewhere. */
1550 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1553 return init_dc_connection_network(domain);
1556 /******************************************************************************
1557 Set the trust flags (direction and forest location) for a domain
1558 ******************************************************************************/
1560 static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1562 struct winbindd_domain *our_domain;
1563 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1564 struct ds_domain_trust *domains = NULL;
1567 uint32 flags = (DS_DOMAIN_IN_FOREST |
1568 DS_DOMAIN_DIRECT_OUTBOUND |
1569 DS_DOMAIN_DIRECT_INBOUND);
1570 struct rpc_pipe_client *cli;
1571 TALLOC_CTX *mem_ctx = NULL;
1573 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1575 /* Our primary domain doesn't need to worry about trust flags.
1576 Force it to go through the network setup */
1577 if ( domain->primary ) {
1581 our_domain = find_our_domain();
1583 if ( !connection_ok(our_domain) ) {
1584 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1588 /* This won't work unless our domain is AD */
1590 if ( !our_domain->active_directory ) {
1594 /* Use DsEnumerateDomainTrusts to get us the trust direction
1597 result = cm_connect_netlogon(our_domain, &cli);
1599 if (!NT_STATUS_IS_OK(result)) {
1600 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1601 "a connection to %s for PIPE_NETLOGON (%s)\n",
1602 domain->name, nt_errstr(result)));
1606 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1607 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1611 result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
1614 (unsigned int *)&count);
1616 /* Now find the domain name and get the flags */
1618 for ( i=0; i<count; i++ ) {
1619 if ( strequal( domain->name, domains[i].netbios_domain ) ) {
1620 domain->domain_flags = domains[i].flags;
1621 domain->domain_type = domains[i].trust_type;
1622 domain->domain_trust_attribs = domains[i].trust_attributes;
1624 if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
1625 domain->active_directory = True;
1627 /* This flag is only set if the domain is *our*
1628 primary domain and the primary domain is in
1631 domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
1633 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1634 "native mode.\n", domain->name,
1635 domain->native_mode ? "" : "NOT "));
1637 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1638 "running active directory.\n", domain->name,
1639 domain->active_directory ? "" : "NOT "));
1642 domain->initialized = True;
1644 if ( !winbindd_can_contact_domain( domain) )
1645 domain->internal = True;
1651 talloc_destroy( mem_ctx );
1653 return domain->initialized;
1656 /******************************************************************************
1657 We can 'sense' certain things about the DC by it's replies to certain
1660 This tells us if this particular remote server is Active Directory, and if it
1662 ******************************************************************************/
1664 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1668 TALLOC_CTX *mem_ctx = NULL;
1669 struct rpc_pipe_client *cli;
1672 char *domain_name = NULL;
1673 char *dns_name = NULL;
1674 char *forest_name = NULL;
1675 DOM_SID *dom_sid = NULL;
1679 if (!connection_ok(domain)) {
1683 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1685 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1689 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1690 "PI_LSARPC_DS on domain %s: (%s)\n",
1691 domain->name, nt_errstr(result)));
1693 /* if this is just a non-AD domain we need to continue
1694 * identifying so that we can in the end return with
1695 * domain->initialized = True - gd */
1700 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1701 DsRolePrimaryDomainInfoBasic,
1703 cli_rpc_pipe_close(cli);
1705 if (!NT_STATUS_IS_OK(result)) {
1706 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1707 "on domain %s failed: (%s)\n",
1708 domain->name, nt_errstr(result)));
1712 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1713 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1714 domain->native_mode = True;
1716 domain->native_mode = False;
1720 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1723 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1724 "PI_LSARPC on domain %s: (%s)\n",
1725 domain->name, nt_errstr(result)));
1726 cli_rpc_pipe_close(cli);
1730 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1733 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1734 cli_rpc_pipe_close(cli);
1738 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1739 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1741 if (NT_STATUS_IS_OK(result)) {
1742 /* This particular query is exactly what Win2k clients use
1743 to determine that the DC is active directory */
1744 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1746 &dns_name, &forest_name,
1750 if (NT_STATUS_IS_OK(result)) {
1751 domain->active_directory = True;
1754 fstrcpy(domain->name, domain_name);
1757 fstrcpy(domain->alt_name, dns_name);
1760 fstrcpy(domain->forest_name, forest_name);
1763 sid_copy(&domain->sid, dom_sid);
1765 domain->active_directory = False;
1767 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1768 SEC_RIGHTS_MAXIMUM_ALLOWED,
1771 if (!NT_STATUS_IS_OK(result))
1774 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1775 &pol, 5, &domain_name,
1778 if (NT_STATUS_IS_OK(result)) {
1780 fstrcpy(domain->name, domain_name);
1783 sid_copy(&domain->sid, dom_sid);
1788 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1789 domain->name, domain->native_mode ? "" : "NOT "));
1791 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1792 domain->name, domain->active_directory ? "" : "NOT "));
1794 cli_rpc_pipe_close(cli);
1796 talloc_destroy(mem_ctx);
1798 domain->initialized = True;
1801 /**********************************************************************
1802 Set the domain_flags (trust attributes, domain operating modes, etc...
1803 ***********************************************************************/
1805 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1807 /* we always have to contact our primary domain */
1809 if ( domain->primary ) {
1810 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1811 "primary domain\n"));
1812 set_dc_type_and_flags_connect( domain );
1816 /* Use our DC to get the information if possible */
1818 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1819 /* Otherwise, fallback to contacting the
1821 set_dc_type_and_flags_connect( domain );
1829 /**********************************************************************
1830 ***********************************************************************/
1832 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1833 struct dcinfo **ppdc)
1836 struct rpc_pipe_client *netlogon_pipe;
1838 if (lp_client_schannel() == False) {
1842 result = cm_connect_netlogon(domain, &netlogon_pipe);
1843 if (!NT_STATUS_IS_OK(result)) {
1847 /* Return a pointer to the struct dcinfo from the
1850 *ppdc = domain->conn.netlogon_pipe->dc;
1854 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1855 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1857 struct winbindd_cm_conn *conn;
1858 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1860 struct dcinfo *p_dcinfo;
1862 result = init_dc_connection(domain);
1863 if (!NT_STATUS_IS_OK(result)) {
1867 conn = &domain->conn;
1869 if (conn->samr_pipe != NULL) {
1874 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1875 * sign and sealed pipe using the machine account password by
1876 * preference. If we can't - try schannel, if that fails, try
1880 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1881 if ((conn->cli->user_name[0] == '\0') ||
1882 (conn->cli->domain[0] == '\0') ||
1883 (conn_pwd[0] == '\0')) {
1884 DEBUG(10, ("cm_connect_sam: No no user available for "
1885 "domain %s, trying schannel\n", conn->cli->domain));
1889 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1890 authenticated SAMR pipe with sign & seal. */
1892 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1893 PIPE_AUTH_LEVEL_PRIVACY,
1895 conn->cli->user_name,
1898 if (conn->samr_pipe == NULL) {
1899 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1900 "pipe for domain %s using NTLMSSP "
1901 "authenticated pipe: user %s\\%s. Error was "
1902 "%s\n", domain->name, conn->cli->domain,
1903 conn->cli->user_name, nt_errstr(result)));
1907 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1908 "domain %s using NTLMSSP authenticated "
1909 "pipe: user %s\\%s\n", domain->name,
1910 conn->cli->domain, conn->cli->user_name ));
1912 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1913 SEC_RIGHTS_MAXIMUM_ALLOWED,
1914 &conn->sam_connect_handle);
1915 if (NT_STATUS_IS_OK(result)) {
1918 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1919 "failed for domain %s, error was %s. Trying schannel\n",
1920 domain->name, nt_errstr(result) ));
1921 cli_rpc_pipe_close(conn->samr_pipe);
1925 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1927 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1928 /* If this call fails - conn->cli can now be NULL ! */
1929 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1930 "for domain %s, trying anon\n", domain->name));
1933 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1934 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1935 domain->name, p_dcinfo, &result);
1937 if (conn->samr_pipe == NULL) {
1938 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1939 "domain %s using schannel. Error was %s\n",
1940 domain->name, nt_errstr(result) ));
1943 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1944 "schannel.\n", domain->name ));
1946 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1947 SEC_RIGHTS_MAXIMUM_ALLOWED,
1948 &conn->sam_connect_handle);
1949 if (NT_STATUS_IS_OK(result)) {
1952 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1953 "for domain %s, error was %s. Trying anonymous\n",
1954 domain->name, nt_errstr(result) ));
1955 cli_rpc_pipe_close(conn->samr_pipe);
1959 /* Finally fall back to anonymous. */
1960 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1963 if (conn->samr_pipe == NULL) {
1964 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1968 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1969 SEC_RIGHTS_MAXIMUM_ALLOWED,
1970 &conn->sam_connect_handle);
1971 if (!NT_STATUS_IS_OK(result)) {
1972 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1973 "for domain %s Error was %s\n",
1974 domain->name, nt_errstr(result) ));
1979 result = rpccli_samr_open_domain(conn->samr_pipe,
1981 &conn->sam_connect_handle,
1982 SEC_RIGHTS_MAXIMUM_ALLOWED,
1984 &conn->sam_domain_handle);
1988 if (!NT_STATUS_IS_OK(result)) {
1989 invalidate_cm_connection(conn);
1993 *cli = conn->samr_pipe;
1994 *sam_handle = conn->sam_domain_handle;
1998 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1999 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
2001 struct winbindd_cm_conn *conn;
2002 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2004 struct dcinfo *p_dcinfo;
2006 result = init_dc_connection(domain);
2007 if (!NT_STATUS_IS_OK(result))
2010 conn = &domain->conn;
2012 if (conn->lsa_pipe != NULL) {
2016 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2017 if ((conn->cli->user_name[0] == '\0') ||
2018 (conn->cli->domain[0] == '\0') ||
2019 (conn_pwd[0] == '\0')) {
2020 DEBUG(10, ("cm_connect_lsa: No no user available for "
2021 "domain %s, trying schannel\n", conn->cli->domain));
2025 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2026 * authenticated LSA pipe with sign & seal. */
2027 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
2028 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2029 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
2031 if (conn->lsa_pipe == NULL) {
2032 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2033 "domain %s using NTLMSSP authenticated pipe: user "
2034 "%s\\%s. Error was %s. Trying schannel.\n",
2035 domain->name, conn->cli->domain,
2036 conn->cli->user_name, nt_errstr(result)));
2040 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2041 "NTLMSSP authenticated pipe: user %s\\%s\n",
2042 domain->name, conn->cli->domain, conn->cli->user_name ));
2044 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2045 SEC_RIGHTS_MAXIMUM_ALLOWED,
2047 if (NT_STATUS_IS_OK(result)) {
2051 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2054 cli_rpc_pipe_close(conn->lsa_pipe);
2058 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2060 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2061 /* If this call fails - conn->cli can now be NULL ! */
2062 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2063 "for domain %s, trying anon\n", domain->name));
2066 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
2067 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2068 domain->name, p_dcinfo, &result);
2070 if (conn->lsa_pipe == NULL) {
2071 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2072 "domain %s using schannel. Error was %s\n",
2073 domain->name, nt_errstr(result) ));
2076 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2077 "schannel.\n", domain->name ));
2079 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2080 SEC_RIGHTS_MAXIMUM_ALLOWED,
2082 if (NT_STATUS_IS_OK(result)) {
2086 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2089 cli_rpc_pipe_close(conn->lsa_pipe);
2093 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
2095 if (conn->lsa_pipe == NULL) {
2096 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2100 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2101 SEC_RIGHTS_MAXIMUM_ALLOWED,
2104 if (!NT_STATUS_IS_OK(result)) {
2105 invalidate_cm_connection(conn);
2109 *cli = conn->lsa_pipe;
2110 *lsa_policy = conn->lsa_policy;
2114 /****************************************************************************
2115 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2116 session key stored in conn->netlogon_pipe->dc->sess_key.
2117 ****************************************************************************/
2119 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2120 struct rpc_pipe_client **cli)
2122 struct winbindd_cm_conn *conn;
2125 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
2127 uint32 sec_chan_type;
2128 const char *account_name;
2129 struct rpc_pipe_client *netlogon_pipe = NULL;
2133 result = init_dc_connection(domain);
2134 if (!NT_STATUS_IS_OK(result)) {
2138 conn = &domain->conn;
2140 if (conn->netlogon_pipe != NULL) {
2141 *cli = conn->netlogon_pipe;
2142 return NT_STATUS_OK;
2145 if (domain->primary && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
2146 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2149 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
2151 if (netlogon_pipe == NULL) {
2155 if ( !domain->primary ) {
2156 /* Clear the schannel request bit and drop down */
2157 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2161 if (lp_client_schannel() != False) {
2162 neg_flags |= NETLOGON_NEG_SCHANNEL;
2165 /* if we are a DC and this is a trusted domain, then we need to use our
2166 domain name in the net_req_auth2() request */
2169 && !strequal(domain->name, lp_workgroup())
2170 && lp_allow_trusted_domains() )
2172 account_name = lp_workgroup();
2174 account_name = domain->primary ?
2175 global_myname() : domain->name;
2178 if (account_name == NULL) {
2179 cli_rpc_pipe_close(netlogon_pipe);
2180 return NT_STATUS_NO_MEMORY;
2183 result = rpccli_netlogon_setup_creds(
2185 domain->dcname, /* server name. */
2186 domain->name, /* domain name */
2187 global_myname(), /* client name */
2188 account_name, /* machine account */
2189 mach_pwd, /* machine password */
2190 sec_chan_type, /* from get_trust_pw */
2193 if (!NT_STATUS_IS_OK(result)) {
2194 cli_rpc_pipe_close(netlogon_pipe);
2198 if ((lp_client_schannel() == True) &&
2199 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2200 DEBUG(3, ("Server did not offer schannel\n"));
2201 cli_rpc_pipe_close(netlogon_pipe);
2202 return NT_STATUS_ACCESS_DENIED;
2206 if ((lp_client_schannel() == False) ||
2207 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2208 /* We're done - just keep the existing connection to NETLOGON
2210 conn->netlogon_pipe = netlogon_pipe;
2211 *cli = conn->netlogon_pipe;
2212 return NT_STATUS_OK;
2215 /* Using the credentials from the first pipe, open a signed and sealed
2216 second netlogon pipe. The session key is stored in the schannel
2217 part of the new pipe auth struct.
2220 conn->netlogon_pipe =
2221 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2223 PIPE_AUTH_LEVEL_PRIVACY,
2228 /* We can now close the initial netlogon pipe. */
2229 cli_rpc_pipe_close(netlogon_pipe);
2231 if (conn->netlogon_pipe == NULL) {
2232 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2233 "was %s\n", nt_errstr(result)));
2235 /* make sure we return something besides OK */
2236 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2239 *cli = conn->netlogon_pipe;
2240 return NT_STATUS_OK;