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(int msg_type, struct process_id src,
86 void *buf, size_t len, void *private_data)
88 struct winbindd_domain *domain;
89 const char *domainname = (const char *)buf;
91 if (buf == NULL || len == 0) {
95 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
97 for (domain = domain_list(); domain; domain = domain->next) {
98 if (domain->internal) {
102 if (strequal(domain->name, domainname)) {
103 if (domain->online) {
104 /* We're already online, ignore. */
105 DEBUG(5,("msg_fail_to_go_online: domain %s "
106 "already online.\n", domainname));
110 /* Reschedule the online check. */
111 set_domain_offline(domain);
117 /****************************************************************
118 Actually cause a reconnect from a message.
119 ****************************************************************/
121 static void msg_try_to_go_online(int msg_type, struct process_id src,
122 void *buf, size_t len, void *private_data)
124 struct winbindd_domain *domain;
125 const char *domainname = (const char *)buf;
127 if (buf == NULL || len == 0) {
131 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
133 for (domain = domain_list(); domain; domain = domain->next) {
134 if (domain->internal) {
138 if (strequal(domain->name, domainname)) {
140 if (domain->online) {
141 /* We're already online, ignore. */
142 DEBUG(5,("msg_try_to_go_online: domain %s "
143 "already online.\n", domainname));
147 /* This call takes care of setting the online
148 flag to true if we connected, or re-adding
149 the offline handler if false. Bypasses online
150 check so always does network calls. */
152 init_dc_connection_network(domain);
158 /****************************************************************
159 Fork a child to try and contact a DC. Do this as contacting a
160 DC requires blocking lookups and we don't want to block our
162 ****************************************************************/
164 static BOOL fork_child_dc_connect(struct winbindd_domain *domain)
166 struct dc_name_ip *dcs = NULL;
168 TALLOC_CTX *mem_ctx = NULL;
170 pid_t parent_pid = sys_getpid();
177 child_pid = sys_fork();
179 if (child_pid == -1) {
180 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
185 if (child_pid != 0) {
187 message_register(MSG_WINBIND_TRY_TO_GO_ONLINE,
188 msg_try_to_go_online, NULL);
189 message_register(MSG_WINBIND_FAILED_TO_GO_ONLINE,
190 msg_failed_to_go_online, NULL);
197 /* Leave messages blocked - we will never process one. */
199 /* tdb needs special fork handling */
200 if (tdb_reopen_all(1) == -1) {
201 DEBUG(0,("tdb_reopen_all failed.\n"));
205 close_conns_after_fork();
207 if (!override_logfile) {
209 pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
210 lp_set_logfile(logfile);
214 mem_ctx = talloc_init("fork_child_dc_connect");
216 DEBUG(0,("talloc_init failed.\n"));
220 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
221 /* Still offline ? Can't find DC's. */
222 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE,
224 strlen(domain->name)+1, False);
228 /* We got a DC. Send a message to our parent to get it to
229 try and do the same. */
231 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE,
233 strlen(domain->name)+1, False);
237 /****************************************************************
238 Handler triggered if we're offline to try and detect a DC.
239 ****************************************************************/
241 static void check_domain_online_handler(struct event_context *ctx,
242 struct timed_event *te,
243 const struct timeval *now,
246 struct winbindd_domain *domain =
247 (struct winbindd_domain *)private_data;
249 DEBUG(10,("check_domain_online_handler: called for domain "
250 "%s (online = %s)\n", domain->name,
251 domain->online ? "True" : "False" ));
253 if (domain->check_online_event) {
254 TALLOC_FREE(domain->check_online_event);
257 /* Are we still in "startup" mode ? */
259 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
260 /* No longer in "startup" mode. */
261 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
263 domain->startup = False;
266 /* We've been told to stay offline, so stay
269 if (get_global_winbindd_state_offline()) {
270 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
275 /* Fork a child to test if it can contact a DC.
276 If it can then send ourselves a message to
277 cause a reconnect. */
279 fork_child_dc_connect(domain);
282 /****************************************************************
283 If we're still offline setup the timeout check.
284 ****************************************************************/
286 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
288 int wbc = lp_winbind_cache_time();
290 if (domain->startup) {
291 domain->check_online_timeout = 10;
292 } else if (domain->check_online_timeout < wbc) {
293 domain->check_online_timeout = wbc;
297 /****************************************************************
298 Set domain offline and also add handler to put us back online
300 ****************************************************************/
302 void set_domain_offline(struct winbindd_domain *domain)
304 DEBUG(10,("set_domain_offline: called for domain %s\n",
307 if (domain->check_online_event) {
308 TALLOC_FREE(domain->check_online_event);
311 if (domain->internal) {
312 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
317 domain->online = False;
319 /* Offline domains are always initialized. They're
320 re-initialized when they go back online. */
322 domain->initialized = True;
324 /* We only add the timeout handler that checks and
325 allows us to go back online when we've not
326 been told to remain offline. */
328 if (get_global_winbindd_state_offline()) {
329 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
334 /* If we're in statup mode, check again in 10 seconds, not in
335 lp_winbind_cache_time() seconds (which is 5 mins by default). */
337 calc_new_online_timeout_check(domain);
339 domain->check_online_event = event_add_timed(winbind_event_context(),
341 timeval_current_ofs(domain->check_online_timeout,0),
342 "check_domain_online_handler",
343 check_domain_online_handler,
346 /* The above *has* to succeed for winbindd to work. */
347 if (!domain->check_online_event) {
348 smb_panic("set_domain_offline: failed to add online handler.\n");
351 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
354 /* Send an offline message to the idmap child when our
355 primary domain goes offline */
357 if ( domain->primary ) {
358 struct winbindd_child *idmap = idmap_child();
360 if ( idmap->pid != 0 ) {
361 message_send_pid(pid_to_procid(idmap->pid),
364 strlen(domain->name)+1,
372 /****************************************************************
373 Set domain online - if allowed.
374 ****************************************************************/
376 static void set_domain_online(struct winbindd_domain *domain)
380 DEBUG(10,("set_domain_online: called for domain %s\n",
383 if (domain->internal) {
384 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
389 if (get_global_winbindd_state_offline()) {
390 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
395 /* If we are waiting to get a krb5 ticket, trigger immediately. */
397 set_event_dispatch_time(winbind_event_context(),
398 "krb5_ticket_gain_handler", now);
400 /* Ok, we're out of any startup mode now... */
401 domain->startup = False;
403 if (domain->online == False) {
404 /* We were offline - now we're online. We default to
405 using the MS-RPC backend if we started offline,
406 and if we're going online for the first time we
407 should really re-initialize the backends and the
408 checks to see if we're talking to an AD or NT domain.
411 domain->initialized = False;
413 /* 'reconnect_methods' is the MS-RPC backend. */
414 if (domain->backend == &reconnect_methods) {
415 domain->backend = NULL;
419 /* Ensure we have no online timeout checks. */
420 domain->check_online_timeout = 0;
421 if (domain->check_online_event) {
422 TALLOC_FREE(domain->check_online_event);
425 /* Ensure we ignore any pending child messages. */
426 message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
427 message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
429 domain->online = True;
431 /* Send an online message to the idmap child when our
432 primary domain comes online */
434 if ( domain->primary ) {
435 struct winbindd_child *idmap = idmap_child();
437 if ( idmap->pid != 0 ) {
438 message_send_pid(pid_to_procid(idmap->pid),
441 strlen(domain->name)+1,
449 /****************************************************************
450 Requested to set a domain online.
451 ****************************************************************/
453 void set_domain_online_request(struct winbindd_domain *domain)
457 DEBUG(10,("set_domain_online_request: called for domain %s\n",
460 if (get_global_winbindd_state_offline()) {
461 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
466 /* We've been told it's safe to go online and
467 try and connect to a DC. But I don't believe it
468 because network manager seems to lie.
469 Wait at least 5 seconds. Heuristics suck... */
471 if (!domain->check_online_event) {
472 /* If we've come from being globally offline we
473 don't have a check online event handler set.
474 We need to add one now we're trying to go
477 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
480 domain->check_online_event = event_add_timed(winbind_event_context(),
482 timeval_current_ofs(5, 0),
483 "check_domain_online_handler",
484 check_domain_online_handler,
487 /* The above *has* to succeed for winbindd to work. */
488 if (!domain->check_online_event) {
489 smb_panic("set_domain_online_request: failed to add online handler.\n");
495 /* Go into "startup" mode again. */
496 domain->startup_time = tev.tv_sec;
497 domain->startup = True;
501 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
504 /****************************************************************
505 Add -ve connection cache entries for domain and realm.
506 ****************************************************************/
508 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
512 add_failed_connection_entry(domain->name, server, result);
513 /* If this was the saf name for the last thing we talked to,
515 saf_delete(domain->name);
516 if (*domain->alt_name) {
517 add_failed_connection_entry(domain->alt_name, server, result);
518 saf_delete(domain->alt_name);
522 /* Choose between anonymous or authenticated connections. We need to use
523 an authenticated connection if DCs have the RestrictAnonymous registry
524 entry set > 0, or the "Additional restrictions for anonymous
525 connections" set in the win2k Local Security Policy.
527 Caller to free() result in domain, username, password
530 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
532 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
533 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
534 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
536 if (*username && **username) {
538 if (!*domain || !**domain)
539 *domain = smb_xstrdup(lp_workgroup());
541 if (!*password || !**password)
542 *password = smb_xstrdup("");
544 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
545 *domain, *username));
548 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
549 *username = smb_xstrdup("");
550 *domain = smb_xstrdup("");
551 *password = smb_xstrdup("");
555 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
556 fstring dcname, struct in_addr *dc_ip)
558 struct winbindd_domain *our_domain = NULL;
559 struct rpc_pipe_client *netlogon_pipe = NULL;
563 unsigned int orig_timeout;
567 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
574 if (domain->primary) {
578 our_domain = find_our_domain();
580 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
584 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
585 if (!NT_STATUS_IS_OK(result)) {
586 talloc_destroy(mem_ctx);
590 /* This call can take a long time - allow the server to time out.
591 35 seconds should do it. */
593 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
595 werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
598 /* And restore our original timeout. */
599 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
601 talloc_destroy(mem_ctx);
603 if (!W_ERROR_IS_OK(werr)) {
604 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
609 /* cli_netlogon_getdcname gives us a name with \\ */
620 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
622 if (!resolve_name(dcname, dc_ip, 0x20)) {
629 /************************************************************************
630 Given a fd with a just-connected TCP connection to a DC, open a connection
632 ************************************************************************/
634 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
636 const char *controller,
637 struct cli_state **cli,
640 char *machine_password, *machine_krb5_principal, *machine_account;
641 char *ipc_username, *ipc_domain, *ipc_password;
645 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
647 struct sockaddr peeraddr;
648 socklen_t peeraddr_len;
650 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
652 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
653 controller, domain->name ));
655 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
658 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
659 SAFE_FREE(machine_password);
660 return NT_STATUS_NO_MEMORY;
663 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
665 SAFE_FREE(machine_account);
666 SAFE_FREE(machine_password);
667 return NT_STATUS_NO_MEMORY;
670 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
674 got_mutex = secrets_named_mutex(controller,
675 WINBIND_SERVER_MUTEX_WAIT_TIME);
678 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
680 result = NT_STATUS_POSSIBLE_DEADLOCK;
684 if ((*cli = cli_initialise()) == NULL) {
685 DEBUG(1, ("Could not cli_initialize\n"));
686 result = NT_STATUS_NO_MEMORY;
690 (*cli)->timeout = 10000; /* 10 seconds */
692 fstrcpy((*cli)->desthost, controller);
693 (*cli)->use_kerberos = True;
695 peeraddr_len = sizeof(peeraddr);
697 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
698 (peeraddr_len != sizeof(struct sockaddr_in)) ||
699 (peeraddr_in->sin_family != PF_INET))
701 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
702 result = NT_STATUS_UNSUCCESSFUL;
706 if (ntohs(peeraddr_in->sin_port) == 139) {
707 struct nmb_name calling;
708 struct nmb_name called;
710 make_nmb_name(&calling, global_myname(), 0x0);
711 make_nmb_name(&called, "*SMBSERVER", 0x20);
713 if (!cli_session_request(*cli, &calling, &called)) {
714 DEBUG(8, ("cli_session_request failed for %s\n",
716 result = NT_STATUS_UNSUCCESSFUL;
721 cli_setup_signing_state(*cli, Undefined);
723 if (!cli_negprot(*cli)) {
724 DEBUG(1, ("cli_negprot failed\n"));
725 result = NT_STATUS_UNSUCCESSFUL;
729 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
730 ADS_STATUS ads_status;
732 if (lp_security() == SEC_ADS) {
734 /* Try a krb5 session */
736 (*cli)->use_kerberos = True;
737 DEBUG(5, ("connecting to %s from %s with kerberos principal "
738 "[%s]\n", controller, global_myname(),
739 machine_krb5_principal));
741 ads_status = cli_session_setup_spnego(*cli,
742 machine_krb5_principal,
746 if (!ADS_ERR_OK(ads_status)) {
747 DEBUG(4,("failed kerberos session setup with %s\n",
748 ads_errstr(ads_status)));
751 result = ads_ntstatus(ads_status);
752 if (NT_STATUS_IS_OK(result)) {
753 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
754 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
755 goto session_setup_done;
759 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
760 (*cli)->use_kerberos = False;
762 DEBUG(5, ("connecting to %s from %s with username "
763 "[%s]\\[%s]\n", controller, global_myname(),
764 lp_workgroup(), machine_account));
766 ads_status = cli_session_setup_spnego(*cli,
770 if (!ADS_ERR_OK(ads_status)) {
771 DEBUG(4, ("authenticated session setup failed with %s\n",
772 ads_errstr(ads_status)));
775 result = ads_ntstatus(ads_status);
776 if (NT_STATUS_IS_OK(result)) {
777 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
778 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
779 goto session_setup_done;
783 /* Fall back to non-kerberos session setup */
785 (*cli)->use_kerberos = False;
787 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
788 (strlen(ipc_username) > 0)) {
790 /* Only try authenticated if we have a username */
792 DEBUG(5, ("connecting to %s from %s with username "
793 "[%s]\\[%s]\n", controller, global_myname(),
794 ipc_domain, ipc_username));
796 if (NT_STATUS_IS_OK(cli_session_setup(
798 ipc_password, strlen(ipc_password)+1,
799 ipc_password, strlen(ipc_password)+1,
801 /* Successful logon with given username. */
802 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
803 goto session_setup_done;
805 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
806 ipc_domain, ipc_username ));
810 /* Fall back to anonymous connection, this might fail later */
812 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
814 DEBUG(5, ("Connected anonymously\n"));
815 cli_init_creds(*cli, "", "", "");
816 goto session_setup_done;
819 result = cli_nt_error(*cli);
821 if (NT_STATUS_IS_OK(result))
822 result = NT_STATUS_UNSUCCESSFUL;
824 /* We can't session setup */
830 /* cache the server name for later connections */
832 saf_store( domain->name, (*cli)->desthost );
833 if (domain->alt_name && (*cli)->use_kerberos) {
834 saf_store( domain->alt_name, (*cli)->desthost );
837 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
839 result = cli_nt_error(*cli);
841 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
843 if (NT_STATUS_IS_OK(result))
844 result = NT_STATUS_UNSUCCESSFUL;
849 secrets_named_mutex_release(controller);
853 /* set the domain if empty; needed for schannel connections */
854 if ( !*(*cli)->domain ) {
855 fstrcpy( (*cli)->domain, domain->name );
858 result = NT_STATUS_OK;
862 secrets_named_mutex_release(controller);
865 SAFE_FREE(machine_account);
866 SAFE_FREE(machine_password);
867 SAFE_FREE(machine_krb5_principal);
868 SAFE_FREE(ipc_username);
869 SAFE_FREE(ipc_domain);
870 SAFE_FREE(ipc_password);
872 if (!NT_STATUS_IS_OK(result)) {
873 winbind_add_failed_connection_entry(domain, controller, result);
874 if ((*cli) != NULL) {
883 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
884 const char *dcname, struct in_addr ip,
885 struct dc_name_ip **dcs, int *num)
887 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
888 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
892 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
897 fstrcpy((*dcs)[*num].name, dcname);
898 (*dcs)[*num].ip = ip;
903 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
904 struct in_addr ip, uint16 port,
905 struct sockaddr_in **addrs, int *num)
907 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
909 if (*addrs == NULL) {
914 (*addrs)[*num].sin_family = PF_INET;
915 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
916 (*addrs)[*num].sin_port = htons(port);
922 static void mailslot_name(struct in_addr dc_ip, fstring name)
924 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
927 static BOOL send_getdc_request(struct in_addr dc_ip,
928 const char *domain_name,
933 fstring my_acct_name;
936 mailslot_name(dc_ip, my_mailslot);
938 memset(outbuf, '\0', sizeof(outbuf));
942 SCVAL(p, 0, SAMLOGON);
945 SCVAL(p, 0, 0); /* Count pointer ... */
948 SIVAL(p, 0, 0); /* The sender's token ... */
951 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
952 fstr_sprintf(my_acct_name, "%s$", global_myname());
953 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
955 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
956 p += strlen(my_mailslot)+1;
961 SIVAL(p, 0, sid_size(sid));
964 p = ALIGN4(p, outbuf);
966 sid_linearize(p, sid_size(sid), sid);
974 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
975 outbuf, PTR_DIFF(p, outbuf),
976 global_myname(), 0, domain_name, 0x1c,
980 static BOOL receive_getdc_response(struct in_addr dc_ip,
981 const char *domain_name,
984 struct packet_struct *packet;
987 fstring dcname, user, domain;
990 mailslot_name(dc_ip, my_mailslot);
992 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
994 if (packet == NULL) {
995 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
999 DEBUG(5, ("Received packet for %s\n", my_mailslot));
1001 buf = packet->packet.dgram.data;
1002 len = packet->packet.dgram.datasize;
1005 /* 70 is a completely arbitrary value to make sure
1006 the SVAL below does not read uninitialized memory */
1007 DEBUG(3, ("GetDC got short response\n"));
1011 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
1012 p = buf+SVAL(buf, smb_vwv10);
1014 if (CVAL(p,0) != SAMLOGON_R) {
1015 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
1020 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1021 STR_TERMINATE|STR_NOALIGN);
1022 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1023 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1024 STR_TERMINATE|STR_NOALIGN);
1025 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1026 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
1027 STR_TERMINATE|STR_NOALIGN);
1028 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
1030 if (!strequal(domain, domain_name)) {
1031 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
1032 domain_name, domain));
1037 if (*p == '\\') p += 1;
1038 if (*p == '\\') p += 1;
1040 fstrcpy(dc_name, p);
1042 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1048 /*******************************************************************
1049 convert an ip to a name
1050 *******************************************************************/
1052 static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1054 struct ip_service ip_list;
1060 /* For active directory servers, try to get the ldap server name.
1061 None of these failures should be considered critical for now */
1063 if (lp_security() == SEC_ADS) {
1066 ads = ads_init(domain->alt_name, domain->name, NULL);
1067 ads->auth.flags |= ADS_AUTH_NO_BIND;
1069 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1070 /* We got a cldap packet. */
1071 fstrcpy(name, ads->config.ldap_server_name);
1072 namecache_store(name, 0x20, 1, &ip_list);
1074 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1076 if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
1077 char *sitename = sitename_fetch(ads->config.realm);
1079 /* We're going to use this KDC for this realm/domain.
1080 If we are using sites, then force the krb5 libs
1083 create_local_private_krb5_conf_for_domain(domain->alt_name,
1088 SAFE_FREE(sitename);
1089 /* Ensure we contact this DC also. */
1090 saf_store( domain->name, name);
1091 saf_store( domain->alt_name, name);
1094 ads_destroy( &ads );
1098 ads_destroy( &ads );
1102 /* try GETDC requests next */
1104 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1107 for (i=0; i<5; i++) {
1108 if (receive_getdc_response(ip, domain->name, name)) {
1109 namecache_store(name, 0x20, 1, &ip_list);
1116 /* try node status request */
1118 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1119 namecache_store(name, 0x20, 1, &ip_list);
1125 /*******************************************************************
1126 Retreive a list of IP address for domain controllers. Fill in
1127 the dcs[] with results.
1128 *******************************************************************/
1130 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1131 struct dc_name_ip **dcs, int *num_dcs)
1135 struct ip_service *ip_list = NULL;
1136 int iplist_size = 0;
1139 enum security_types sec = (enum security_types)lp_security();
1141 is_our_domain = strequal(domain->name, lp_workgroup());
1144 && get_dc_name_via_netlogon(domain, dcname, &ip)
1145 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1147 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1148 dcname, inet_ntoa(ip)));
1152 if (sec == SEC_ADS) {
1153 char *sitename = NULL;
1155 /* We need to make sure we know the local site before
1156 doing any DNS queries, as this will restrict the
1157 get_sorted_dc_list() call below to only fetching
1158 DNS records for the correct site. */
1160 /* Find any DC to get the site record.
1161 We deliberately don't care about the
1164 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
1166 sitename = sitename_fetch(domain->alt_name);
1169 /* Do the site-specific AD dns lookup first. */
1170 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1172 for ( i=0; i<iplist_size; i++ ) {
1173 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1174 ip_list[i].ip, dcs, num_dcs);
1178 SAFE_FREE(sitename);
1182 /* Now we add DCs from the main AD dns lookup. */
1183 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1185 for ( i=0; i<iplist_size; i++ ) {
1186 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1187 ip_list[i].ip, dcs, num_dcs);
1191 /* try standard netbios queries if no ADS */
1193 if (iplist_size==0) {
1194 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1197 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1199 /* now add to the dc array. We'll wait until the last minute
1200 to look up the name of the DC. But we fill in the char* for
1201 the ip now in to make the failed connection cache work */
1203 for ( i=0; i<iplist_size; i++ ) {
1204 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1205 ip_list[i].ip, dcs, num_dcs);
1208 SAFE_FREE( ip_list );
1213 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1214 const struct winbindd_domain *domain,
1215 fstring dcname, struct sockaddr_in *addr, int *fd)
1217 struct dc_name_ip *dcs = NULL;
1220 const char **dcnames = NULL;
1221 int num_dcnames = 0;
1223 struct sockaddr_in *addrs = NULL;
1229 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1232 for (i=0; i<num_dcs; i++) {
1234 if (!add_string_to_array(mem_ctx, dcs[i].name,
1235 &dcnames, &num_dcnames)) {
1238 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1239 &addrs, &num_addrs)) {
1243 if (!add_string_to_array(mem_ctx, dcs[i].name,
1244 &dcnames, &num_dcnames)) {
1247 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1248 &addrs, &num_addrs)) {
1253 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1256 if ((addrs == NULL) || (dcnames == NULL))
1259 /* 5 second timeout. */
1260 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1262 for (i=0; i<num_dcs; i++) {
1263 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1264 "domain %s address %s. Error was %s\n",
1265 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1266 winbind_add_failed_connection_entry(domain,
1267 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1272 *addr = addrs[fd_index];
1274 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1275 /* Ok, we've got a name for the DC */
1276 fstrcpy(dcname, dcnames[fd_index]);
1280 /* Try to figure out the name */
1281 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1285 /* We can not continue without the DC's name */
1286 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1287 NT_STATUS_UNSUCCESSFUL);
1291 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1292 struct winbindd_cm_conn *new_conn)
1294 TALLOC_CTX *mem_ctx;
1296 char *saf_servername = saf_fetch( domain->name );
1299 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1300 SAFE_FREE(saf_servername);
1301 set_domain_offline(domain);
1302 return NT_STATUS_NO_MEMORY;
1305 /* we have to check the server affinity cache here since
1306 later we selecte a DC based on response time and not preference */
1308 /* Check the negative connection cache
1309 before talking to it. It going down may have
1310 triggered the reconnection. */
1312 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1314 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1315 saf_servername, domain->name ));
1317 /* convert an ip address to a name */
1318 if ( is_ipaddress( saf_servername ) ) {
1322 ip = *interpret_addr2( saf_servername );
1323 if (dcip_to_name( domain, ip, saf_name )) {
1324 fstrcpy( domain->dcname, saf_name );
1326 winbind_add_failed_connection_entry(
1327 domain, saf_servername,
1328 NT_STATUS_UNSUCCESSFUL);
1331 fstrcpy( domain->dcname, saf_servername );
1334 SAFE_FREE( saf_servername );
1337 for (retries = 0; retries < 3; retries++) {
1342 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1344 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1345 domain->dcname, domain->name ));
1348 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1349 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1351 struct sockaddr_in *addrs = NULL;
1355 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1356 set_domain_offline(domain);
1357 talloc_destroy(mem_ctx);
1358 return NT_STATUS_NO_MEMORY;
1360 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1361 set_domain_offline(domain);
1362 talloc_destroy(mem_ctx);
1363 return NT_STATUS_NO_MEMORY;
1366 /* 5 second timeout. */
1367 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1373 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1375 /* This is the one place where we will
1376 set the global winbindd offline state
1377 to true, if a "WINBINDD_OFFLINE" entry
1378 is found in the winbindd cache. */
1379 set_global_winbindd_state_offline();
1383 new_conn->cli = NULL;
1385 result = cm_prepare_connection(domain, fd, domain->dcname,
1386 &new_conn->cli, &retry);
1392 if (NT_STATUS_IS_OK(result)) {
1393 if (domain->online == False) {
1394 /* We're changing state from offline to online. */
1395 set_global_winbindd_state_online();
1397 set_domain_online(domain);
1399 /* Ensure we setup the retry handler. */
1400 set_domain_offline(domain);
1403 talloc_destroy(mem_ctx);
1407 /* Close down all open pipes on a connection. */
1409 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1411 /* We're closing down a possibly dead
1412 connection. Don't have impossibly long (10s) timeouts. */
1415 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1418 if (conn->samr_pipe != NULL) {
1419 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1420 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1422 cli_set_timeout(conn->cli, 500);
1425 conn->samr_pipe = NULL;
1428 if (conn->lsa_pipe != NULL) {
1429 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1430 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1432 cli_set_timeout(conn->cli, 500);
1435 conn->lsa_pipe = NULL;
1438 if (conn->netlogon_pipe != NULL) {
1439 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1440 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1442 cli_set_timeout(conn->cli, 500);
1445 conn->netlogon_pipe = NULL;
1449 cli_shutdown(conn->cli);
1455 void close_conns_after_fork(void)
1457 struct winbindd_domain *domain;
1459 for (domain = domain_list(); domain; domain = domain->next) {
1460 if (domain->conn.cli == NULL)
1463 if (domain->conn.cli->fd == -1)
1466 close(domain->conn.cli->fd);
1467 domain->conn.cli->fd = -1;
1471 static BOOL connection_ok(struct winbindd_domain *domain)
1473 if (domain->conn.cli == NULL) {
1474 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1475 "cli!\n", domain->dcname, domain->name));
1479 if (!domain->conn.cli->initialised) {
1480 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1481 "initialised!\n", domain->dcname, domain->name));
1485 if (domain->conn.cli->fd == -1) {
1486 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1487 "never started (fd == -1)\n",
1488 domain->dcname, domain->name));
1492 if (domain->online == False) {
1493 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1500 /* Initialize a new connection up to the RPC BIND.
1501 Bypass online status check so always does network calls. */
1503 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1507 /* Internal connections never use the network. */
1508 if (domain->internal) {
1509 domain->initialized = True;
1510 return NT_STATUS_OK;
1513 if (connection_ok(domain)) {
1514 if (!domain->initialized) {
1515 set_dc_type_and_flags(domain);
1517 return NT_STATUS_OK;
1520 invalidate_cm_connection(&domain->conn);
1522 result = cm_open_connection(domain, &domain->conn);
1524 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1525 set_dc_type_and_flags(domain);
1531 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1533 if (domain->initialized && !domain->online) {
1534 /* We check for online status elsewhere. */
1535 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1538 return init_dc_connection_network(domain);
1541 /******************************************************************************
1542 Set the trust flags (direction and forest location) for a domain
1543 ******************************************************************************/
1545 static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1547 struct winbindd_domain *our_domain;
1548 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1549 struct ds_domain_trust *domains = NULL;
1552 uint32 flags = (DS_DOMAIN_IN_FOREST |
1553 DS_DOMAIN_DIRECT_OUTBOUND |
1554 DS_DOMAIN_DIRECT_INBOUND);
1555 struct rpc_pipe_client *cli;
1556 TALLOC_CTX *mem_ctx = NULL;
1558 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1560 /* Our primary domain doesn't need to worry about trust flags.
1561 Force it to go through the network setup */
1562 if ( domain->primary ) {
1566 our_domain = find_our_domain();
1568 if ( !connection_ok(our_domain) ) {
1569 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));
1573 /* This won't work unless our domain is AD */
1575 if ( !our_domain->active_directory ) {
1579 /* Use DsEnumerateDomainTrusts to get us the trust direction
1582 result = cm_connect_netlogon(our_domain, &cli);
1584 if (!NT_STATUS_IS_OK(result)) {
1585 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1586 "a connection to %s for PIPE_NETLOGON (%s)\n",
1587 domain->name, nt_errstr(result)));
1591 if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1592 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1596 result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
1599 (unsigned int *)&count);
1601 /* Now find the domain name and get the flags */
1603 for ( i=0; i<count; i++ ) {
1604 if ( strequal( domain->name, domains[i].netbios_domain ) ) {
1605 domain->domain_flags = domains[i].flags;
1606 domain->domain_type = domains[i].trust_type;
1607 domain->domain_trust_attribs = domains[i].trust_attributes;
1609 if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
1610 domain->active_directory = True;
1612 /* This flag is only set if the domain is *our*
1613 primary domain and the primary domain is in
1616 domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
1618 DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1619 "native mode.\n", domain->name,
1620 domain->native_mode ? "" : "NOT "));
1622 DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1623 "running active directory.\n", domain->name,
1624 domain->active_directory ? "" : "NOT "));
1627 domain->initialized = True;
1629 if ( !winbindd_can_contact_domain( domain) )
1630 domain->internal = True;
1636 talloc_destroy( mem_ctx );
1638 return domain->initialized;
1641 /******************************************************************************
1642 We can 'sense' certain things about the DC by it's replies to certain
1645 This tells us if this particular remote server is Active Directory, and if it
1647 ******************************************************************************/
1649 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1653 TALLOC_CTX *mem_ctx = NULL;
1654 struct rpc_pipe_client *cli;
1657 char *domain_name = NULL;
1658 char *dns_name = NULL;
1659 char *forest_name = NULL;
1660 DOM_SID *dom_sid = NULL;
1664 if (!connection_ok(domain)) {
1668 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1670 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1674 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1675 "PI_LSARPC_DS on domain %s: (%s)\n",
1676 domain->name, nt_errstr(result)));
1678 /* if this is just a non-AD domain we need to continue
1679 * identifying so that we can in the end return with
1680 * domain->initialized = True - gd */
1685 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1686 DsRolePrimaryDomainInfoBasic,
1688 cli_rpc_pipe_close(cli);
1690 if (!NT_STATUS_IS_OK(result)) {
1691 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1692 "on domain %s failed: (%s)\n",
1693 domain->name, nt_errstr(result)));
1697 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1698 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1699 domain->native_mode = True;
1701 domain->native_mode = False;
1705 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1708 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1709 "PI_LSARPC on domain %s: (%s)\n",
1710 domain->name, nt_errstr(result)));
1711 cli_rpc_pipe_close(cli);
1715 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1718 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1719 cli_rpc_pipe_close(cli);
1723 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1724 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1726 if (NT_STATUS_IS_OK(result)) {
1727 /* This particular query is exactly what Win2k clients use
1728 to determine that the DC is active directory */
1729 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1731 &dns_name, &forest_name,
1735 if (NT_STATUS_IS_OK(result)) {
1736 domain->active_directory = True;
1739 fstrcpy(domain->name, domain_name);
1742 fstrcpy(domain->alt_name, dns_name);
1745 fstrcpy(domain->forest_name, forest_name);
1748 sid_copy(&domain->sid, dom_sid);
1750 domain->active_directory = False;
1752 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1753 SEC_RIGHTS_MAXIMUM_ALLOWED,
1756 if (!NT_STATUS_IS_OK(result))
1759 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1760 &pol, 5, &domain_name,
1763 if (NT_STATUS_IS_OK(result)) {
1765 fstrcpy(domain->name, domain_name);
1768 sid_copy(&domain->sid, dom_sid);
1773 DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1774 domain->name, domain->native_mode ? "" : "NOT "));
1776 DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1777 domain->name, domain->active_directory ? "" : "NOT "));
1779 cli_rpc_pipe_close(cli);
1781 talloc_destroy(mem_ctx);
1783 domain->initialized = True;
1786 /**********************************************************************
1787 Set the domain_flags (trust attributes, domain operating modes, etc...
1788 ***********************************************************************/
1790 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1792 /* we always have to contact our primary domain */
1794 if ( domain->primary ) {
1795 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1796 "primary domain\n"));
1797 set_dc_type_and_flags_connect( domain );
1801 /* Use our DC to get the information if possible */
1803 if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1804 /* Otherwise, fallback to contacting the
1806 set_dc_type_and_flags_connect( domain );
1814 /**********************************************************************
1815 ***********************************************************************/
1817 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1818 struct dcinfo **ppdc)
1821 struct rpc_pipe_client *netlogon_pipe;
1823 if (lp_client_schannel() == False) {
1827 result = cm_connect_netlogon(domain, &netlogon_pipe);
1828 if (!NT_STATUS_IS_OK(result)) {
1832 /* Return a pointer to the struct dcinfo from the
1835 *ppdc = domain->conn.netlogon_pipe->dc;
1839 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1840 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1842 struct winbindd_cm_conn *conn;
1843 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1845 struct dcinfo *p_dcinfo;
1847 result = init_dc_connection(domain);
1848 if (!NT_STATUS_IS_OK(result)) {
1852 conn = &domain->conn;
1854 if (conn->samr_pipe != NULL) {
1859 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1860 * sign and sealed pipe using the machine account password by
1861 * preference. If we can't - try schannel, if that fails, try
1865 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1866 if ((conn->cli->user_name[0] == '\0') ||
1867 (conn->cli->domain[0] == '\0') ||
1868 (conn_pwd[0] == '\0')) {
1869 DEBUG(10, ("cm_connect_sam: No no user available for "
1870 "domain %s, trying schannel\n", conn->cli->domain));
1874 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1875 authenticated SAMR pipe with sign & seal. */
1877 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1878 PIPE_AUTH_LEVEL_PRIVACY,
1880 conn->cli->user_name,
1883 if (conn->samr_pipe == NULL) {
1884 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1885 "pipe for domain %s using NTLMSSP "
1886 "authenticated pipe: user %s\\%s. Error was "
1887 "%s\n", domain->name, conn->cli->domain,
1888 conn->cli->user_name, nt_errstr(result)));
1892 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1893 "domain %s using NTLMSSP authenticated "
1894 "pipe: user %s\\%s\n", domain->name,
1895 conn->cli->domain, conn->cli->user_name ));
1897 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1898 SEC_RIGHTS_MAXIMUM_ALLOWED,
1899 &conn->sam_connect_handle);
1900 if (NT_STATUS_IS_OK(result)) {
1903 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1904 "failed for domain %s, error was %s. Trying schannel\n",
1905 domain->name, nt_errstr(result) ));
1906 cli_rpc_pipe_close(conn->samr_pipe);
1910 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1912 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1913 /* If this call fails - conn->cli can now be NULL ! */
1914 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1915 "for domain %s, trying anon\n", domain->name));
1918 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1919 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1920 domain->name, p_dcinfo, &result);
1922 if (conn->samr_pipe == NULL) {
1923 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1924 "domain %s using schannel. Error was %s\n",
1925 domain->name, nt_errstr(result) ));
1928 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1929 "schannel.\n", domain->name ));
1931 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1932 SEC_RIGHTS_MAXIMUM_ALLOWED,
1933 &conn->sam_connect_handle);
1934 if (NT_STATUS_IS_OK(result)) {
1937 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1938 "for domain %s, error was %s. Trying anonymous\n",
1939 domain->name, nt_errstr(result) ));
1940 cli_rpc_pipe_close(conn->samr_pipe);
1944 /* Finally fall back to anonymous. */
1945 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1948 if (conn->samr_pipe == NULL) {
1949 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1953 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1954 SEC_RIGHTS_MAXIMUM_ALLOWED,
1955 &conn->sam_connect_handle);
1956 if (!NT_STATUS_IS_OK(result)) {
1957 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1958 "for domain %s Error was %s\n",
1959 domain->name, nt_errstr(result) ));
1964 result = rpccli_samr_open_domain(conn->samr_pipe,
1966 &conn->sam_connect_handle,
1967 SEC_RIGHTS_MAXIMUM_ALLOWED,
1969 &conn->sam_domain_handle);
1973 if (!NT_STATUS_IS_OK(result)) {
1974 invalidate_cm_connection(conn);
1978 *cli = conn->samr_pipe;
1979 *sam_handle = conn->sam_domain_handle;
1983 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1984 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1986 struct winbindd_cm_conn *conn;
1987 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1989 struct dcinfo *p_dcinfo;
1991 result = init_dc_connection(domain);
1992 if (!NT_STATUS_IS_OK(result))
1995 conn = &domain->conn;
1997 if (conn->lsa_pipe != NULL) {
2001 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2002 if ((conn->cli->user_name[0] == '\0') ||
2003 (conn->cli->domain[0] == '\0') ||
2004 (conn_pwd[0] == '\0')) {
2005 DEBUG(10, ("cm_connect_lsa: No no user available for "
2006 "domain %s, trying schannel\n", conn->cli->domain));
2010 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2011 * authenticated LSA pipe with sign & seal. */
2012 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
2013 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2014 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
2016 if (conn->lsa_pipe == NULL) {
2017 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2018 "domain %s using NTLMSSP authenticated pipe: user "
2019 "%s\\%s. Error was %s. Trying schannel.\n",
2020 domain->name, conn->cli->domain,
2021 conn->cli->user_name, nt_errstr(result)));
2025 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2026 "NTLMSSP authenticated pipe: user %s\\%s\n",
2027 domain->name, conn->cli->domain, conn->cli->user_name ));
2029 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2030 SEC_RIGHTS_MAXIMUM_ALLOWED,
2032 if (NT_STATUS_IS_OK(result)) {
2036 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2039 cli_rpc_pipe_close(conn->lsa_pipe);
2043 /* Fall back to schannel if it's a W2K pre-SP1 box. */
2045 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2046 /* If this call fails - conn->cli can now be NULL ! */
2047 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2048 "for domain %s, trying anon\n", domain->name));
2051 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
2052 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
2053 domain->name, p_dcinfo, &result);
2055 if (conn->lsa_pipe == NULL) {
2056 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2057 "domain %s using schannel. Error was %s\n",
2058 domain->name, nt_errstr(result) ));
2061 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2062 "schannel.\n", domain->name ));
2064 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2065 SEC_RIGHTS_MAXIMUM_ALLOWED,
2067 if (NT_STATUS_IS_OK(result)) {
2071 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2074 cli_rpc_pipe_close(conn->lsa_pipe);
2078 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
2080 if (conn->lsa_pipe == NULL) {
2081 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2085 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2086 SEC_RIGHTS_MAXIMUM_ALLOWED,
2089 if (!NT_STATUS_IS_OK(result)) {
2090 invalidate_cm_connection(conn);
2094 *cli = conn->lsa_pipe;
2095 *lsa_policy = conn->lsa_policy;
2099 /****************************************************************************
2100 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2101 session key stored in conn->netlogon_pipe->dc->sess_key.
2102 ****************************************************************************/
2104 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2105 struct rpc_pipe_client **cli)
2107 struct winbindd_cm_conn *conn;
2110 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
2112 uint32 sec_chan_type;
2113 const char *account_name;
2114 struct rpc_pipe_client *netlogon_pipe = NULL;
2118 result = init_dc_connection(domain);
2119 if (!NT_STATUS_IS_OK(result)) {
2123 conn = &domain->conn;
2125 if (conn->netlogon_pipe != NULL) {
2126 *cli = conn->netlogon_pipe;
2127 return NT_STATUS_OK;
2130 if (domain->primary && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
2131 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2134 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
2136 if (netlogon_pipe == NULL) {
2140 if ( !domain->primary ) {
2141 /* Clear the schannel request bit and drop down */
2142 neg_flags &= ~NETLOGON_NEG_SCHANNEL;
2146 if (lp_client_schannel() != False) {
2147 neg_flags |= NETLOGON_NEG_SCHANNEL;
2150 /* if we are a DC and this is a trusted domain, then we need to use our
2151 domain name in the net_req_auth2() request */
2154 && !strequal(domain->name, lp_workgroup())
2155 && lp_allow_trusted_domains() )
2157 account_name = lp_workgroup();
2159 account_name = domain->primary ?
2160 global_myname() : domain->name;
2163 if (account_name == NULL) {
2164 cli_rpc_pipe_close(netlogon_pipe);
2165 return NT_STATUS_NO_MEMORY;
2168 result = rpccli_netlogon_setup_creds(
2170 domain->dcname, /* server name. */
2171 domain->name, /* domain name */
2172 global_myname(), /* client name */
2173 account_name, /* machine account */
2174 mach_pwd, /* machine password */
2175 sec_chan_type, /* from get_trust_pw */
2178 if (!NT_STATUS_IS_OK(result)) {
2179 cli_rpc_pipe_close(netlogon_pipe);
2183 if ((lp_client_schannel() == True) &&
2184 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2185 DEBUG(3, ("Server did not offer schannel\n"));
2186 cli_rpc_pipe_close(netlogon_pipe);
2187 return NT_STATUS_ACCESS_DENIED;
2191 if ((lp_client_schannel() == False) ||
2192 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2193 /* We're done - just keep the existing connection to NETLOGON
2195 conn->netlogon_pipe = netlogon_pipe;
2196 *cli = conn->netlogon_pipe;
2197 return NT_STATUS_OK;
2200 /* Using the credentials from the first pipe, open a signed and sealed
2201 second netlogon pipe. The session key is stored in the schannel
2202 part of the new pipe auth struct.
2205 conn->netlogon_pipe =
2206 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2208 PIPE_AUTH_LEVEL_PRIVACY,
2213 /* We can now close the initial netlogon pipe. */
2214 cli_rpc_pipe_close(netlogon_pipe);
2216 if (conn->netlogon_pipe == NULL) {
2217 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2218 "was %s\n", nt_errstr(result)));
2220 /* make sure we return something besides OK */
2221 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2224 *cli = conn->netlogon_pipe;
2225 return NT_STATUS_OK;