r19148: Finish last nights patch - make offline
[Samba.git] / source / nsswitch / winbindd_cm.c
blobb947ce75ec8563bc584235d890753c8a1c255906
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
8 Copyright (C) Gerald (Jerry) Carter 2003-2005.
9 Copyright (C) Volker Lendecke 2004-2005
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 We need to manage connections to domain controllers without having to
28 mess up the main winbindd code with other issues. The aim of the
29 connection manager is to:
31 - make connections to domain controllers and cache them
32 - re-establish connections when networks or servers go down
33 - centralise the policy on connection timeouts, domain controller
34 selection etc
35 - manage re-entrancy for when winbindd becomes able to handle
36 multiple outstanding rpc requests
38 Why not have connection management as part of the rpc layer like tng?
39 Good question. This code may morph into libsmb/rpc_cache.c or something
40 like that but at the moment it's simply staying as part of winbind. I
41 think the TNG architecture of forcing every user of the rpc layer to use
42 the connection caching system is a bad idea. It should be an optional
43 method of using the routines.
45 The TNG design is quite good but I disagree with some aspects of the
46 implementation. -tpot
51 TODO:
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
57 various sam handles.
61 #include "includes.h"
62 #include "winbindd.h"
64 #undef DBGC_CLASS
65 #define DBGC_CLASS DBGC_WINBIND
67 static void set_dc_type_and_flags( struct winbindd_domain *domain );
69 /****************************************************************
70 Handler triggered if we're offline to try and detect a DC.
71 ****************************************************************/
73 static void check_domain_online_handler(struct timed_event *te,
74 const struct timeval *now,
75 void *private_data)
77 struct winbindd_domain *domain =
78 (struct winbindd_domain *)private_data;
80 DEBUG(10,("check_domain_online_handler: called for domain %s\n",
81 domain->name ));
83 if (domain->check_online_event) {
84 TALLOC_FREE(domain->check_online_event);
87 /* Are we still in "startup" mode ? */
89 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
90 /* No longer in "startup" mode. */
91 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
92 domain->name ));
93 domain->startup = False;
96 /* We've been told to stay offline, so stay
97 that way. */
99 if (get_global_winbindd_state_offline()) {
100 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
101 domain->name ));
102 return;
105 /* This call takes care of setting the online
106 flag to true if we connected, or re-adding
107 the offline handler if false. */
108 init_dc_connection(domain);
111 /****************************************************************
112 Set domain offline and also add handler to put us back online
113 if we detect a DC.
114 ****************************************************************/
116 void set_domain_offline(struct winbindd_domain *domain)
118 DEBUG(10,("set_domain_offline: called for domain %s\n",
119 domain->name ));
121 if (domain->check_online_event) {
122 TALLOC_FREE(domain->check_online_event);
125 domain->online = False;
127 /* We only add the timeout handler that checks and
128 allows us to go back online when we've not
129 been told to remain offline. */
131 if (get_global_winbindd_state_offline()) {
132 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
133 domain->name ));
134 return;
137 /* If we're in statup mode, check again in 10 seconds, not in
138 lp_winbind_cache_time() seconds (which is 5 mins by default). */
140 domain->check_online_event = add_timed_event( NULL,
141 domain->startup ?
142 timeval_current_ofs(10,0) :
143 timeval_current_ofs(lp_winbind_cache_time(), 0),
144 "check_domain_online_handler",
145 check_domain_online_handler,
146 domain);
148 /* The above *has* to succeed for winbindd to work. */
149 if (!domain->check_online_event) {
150 smb_panic("set_domain_offline: failed to add online handler.\n");
153 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
154 domain->name ));
157 /****************************************************************
158 Set domain online - if allowed.
159 ****************************************************************/
161 static void set_domain_online(struct winbindd_domain *domain)
163 extern struct winbindd_methods reconnect_methods;
164 struct timeval now;
166 DEBUG(10,("set_domain_online: called for domain %s\n",
167 domain->name ));
169 if (get_global_winbindd_state_offline()) {
170 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
171 domain->name ));
172 return;
175 /* If we are waiting to get a krb5 ticket, trigger immediately. */
176 GetTimeOfDay(&now);
177 set_event_dispatch_time("krb5_ticket_gain_handler", now);
179 /* Ok, we're out of any startup mode now... */
180 domain->startup = False;
182 if (domain->online == False) {
183 /* We were offline - now we're online. We default to
184 using the MS-RPC backend if we started offline,
185 and if we're going online for the first time we
186 should really re-initialize the backends and the
187 checks to see if we're talking to an AD or NT domain.
190 domain->initialized = False;
192 /* 'reconnect_methods' is the MS-RPC backend. */
193 if (domain->backend == &reconnect_methods) {
194 domain->backend = NULL;
198 domain->online = True;
201 /****************************************************************
202 Requested to set a domain online.
203 ****************************************************************/
205 void set_domain_online_request(struct winbindd_domain *domain)
207 DEBUG(10,("set_domain_online_request: called for domain %s\n",
208 domain->name ));
210 if (get_global_winbindd_state_offline()) {
211 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
212 domain->name ));
213 return;
216 /* We've been told it's safe to go online and
217 try and connect to a DC. But I don't believe it
218 because network manager seems to lie.
219 Wait at least 5 seconds. Heuristics suck... */
221 if (!domain->check_online_event) {
222 DEBUG(5,("set_domain_online_request: no check_domain_online_handler "
223 "registered. Were we online (%d) ?\n", (int)domain->online ));
224 } else {
225 struct timeval tev;
227 GetTimeOfDay(&tev);
229 /* Go into "startup" mode again. */
230 domain->startup_time = tev.tv_sec;
231 domain->startup = True;
233 tev.tv_sec += 5;
234 set_event_dispatch_time("check_domain_online_handler", tev);
238 /****************************************************************
239 Add -ve connection cache entries for domain and realm.
240 ****************************************************************/
242 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
243 const char *server,
244 NTSTATUS result)
246 add_failed_connection_entry(domain->name, server, result);
247 /* If this was the saf name for the last thing we talked to,
248 remove it. */
249 saf_delete(domain->name, server);
250 if (*domain->alt_name) {
251 add_failed_connection_entry(domain->alt_name, server, result);
252 saf_delete(domain->alt_name, server);
256 /* Choose between anonymous or authenticated connections. We need to use
257 an authenticated connection if DCs have the RestrictAnonymous registry
258 entry set > 0, or the "Additional restrictions for anonymous
259 connections" set in the win2k Local Security Policy.
261 Caller to free() result in domain, username, password
264 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
266 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
267 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
268 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
270 if (*username && **username) {
272 if (!*domain || !**domain)
273 *domain = smb_xstrdup(lp_workgroup());
275 if (!*password || !**password)
276 *password = smb_xstrdup("");
278 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
279 *domain, *username));
281 } else {
282 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
283 *username = smb_xstrdup("");
284 *domain = smb_xstrdup("");
285 *password = smb_xstrdup("");
289 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
290 fstring dcname, struct in_addr *dc_ip)
292 struct winbindd_domain *our_domain = NULL;
293 struct rpc_pipe_client *netlogon_pipe = NULL;
294 NTSTATUS result;
295 WERROR werr;
296 TALLOC_CTX *mem_ctx;
298 fstring tmp;
299 char *p;
301 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
302 * moment.... */
304 if (IS_DC) {
305 return False;
308 if (domain->primary) {
309 return False;
312 our_domain = find_our_domain();
314 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
315 return False;
318 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
319 if (!NT_STATUS_IS_OK(result)) {
320 return False;
323 werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
324 domain->name, tmp);
326 talloc_destroy(mem_ctx);
328 if (!W_ERROR_IS_OK(werr)) {
329 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
330 dos_errstr(werr)));
331 return False;
334 /* cli_netlogon_getdcname gives us a name with \\ */
335 p = tmp;
336 if (*p == '\\') {
337 p+=1;
339 if (*p == '\\') {
340 p+=1;
343 fstrcpy(dcname, p);
345 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
347 if (!resolve_name(dcname, dc_ip, 0x20)) {
348 return False;
351 return True;
354 /************************************************************************
355 Given a fd with a just-connected TCP connection to a DC, open a connection
356 to the pipe.
357 ************************************************************************/
359 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
360 const int sockfd,
361 const char *controller,
362 struct cli_state **cli,
363 BOOL *retry)
365 char *machine_password, *machine_krb5_principal, *machine_account;
366 char *ipc_username, *ipc_domain, *ipc_password;
368 BOOL got_mutex;
370 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
372 struct sockaddr peeraddr;
373 socklen_t peeraddr_len;
375 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
377 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
378 controller, domain->name ));
380 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
381 NULL);
383 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
384 SAFE_FREE(machine_password);
385 return NT_STATUS_NO_MEMORY;
388 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
389 lp_realm()) == -1) {
390 SAFE_FREE(machine_account);
391 SAFE_FREE(machine_password);
392 return NT_STATUS_NO_MEMORY;
395 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
397 *retry = True;
399 got_mutex = secrets_named_mutex(controller,
400 WINBIND_SERVER_MUTEX_WAIT_TIME);
402 if (!got_mutex) {
403 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
404 controller));
405 result = NT_STATUS_POSSIBLE_DEADLOCK;
406 goto done;
409 if ((*cli = cli_initialise()) == NULL) {
410 DEBUG(1, ("Could not cli_initialize\n"));
411 result = NT_STATUS_NO_MEMORY;
412 goto done;
415 (*cli)->timeout = 10000; /* 10 seconds */
416 (*cli)->fd = sockfd;
417 fstrcpy((*cli)->desthost, controller);
418 (*cli)->use_kerberos = True;
420 peeraddr_len = sizeof(peeraddr);
422 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
423 (peeraddr_len != sizeof(struct sockaddr_in)) ||
424 (peeraddr_in->sin_family != PF_INET))
426 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
427 result = NT_STATUS_UNSUCCESSFUL;
428 goto done;
431 if (ntohs(peeraddr_in->sin_port) == 139) {
432 struct nmb_name calling;
433 struct nmb_name called;
435 make_nmb_name(&calling, global_myname(), 0x0);
436 make_nmb_name(&called, "*SMBSERVER", 0x20);
438 if (!cli_session_request(*cli, &calling, &called)) {
439 DEBUG(8, ("cli_session_request failed for %s\n",
440 controller));
441 result = NT_STATUS_UNSUCCESSFUL;
442 goto done;
446 cli_setup_signing_state(*cli, Undefined);
448 if (!cli_negprot(*cli)) {
449 DEBUG(1, ("cli_negprot failed\n"));
450 result = NT_STATUS_UNSUCCESSFUL;
451 goto done;
454 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
455 ADS_STATUS ads_status;
457 if (lp_security() == SEC_ADS) {
459 /* Try a krb5 session */
461 (*cli)->use_kerberos = True;
462 DEBUG(5, ("connecting to %s from %s with kerberos principal "
463 "[%s]\n", controller, global_myname(),
464 machine_krb5_principal));
466 ads_status = cli_session_setup_spnego(*cli,
467 machine_krb5_principal,
468 machine_password,
469 lp_workgroup());
471 if (!ADS_ERR_OK(ads_status)) {
472 DEBUG(4,("failed kerberos session setup with %s\n",
473 ads_errstr(ads_status)));
476 result = ads_ntstatus(ads_status);
477 if (NT_STATUS_IS_OK(result)) {
478 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
479 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
480 goto session_setup_done;
484 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
485 (*cli)->use_kerberos = False;
487 DEBUG(5, ("connecting to %s from %s with username "
488 "[%s]\\[%s]\n", controller, global_myname(),
489 lp_workgroup(), machine_account));
491 ads_status = cli_session_setup_spnego(*cli,
492 machine_account,
493 machine_password,
494 lp_workgroup());
495 if (!ADS_ERR_OK(ads_status)) {
496 DEBUG(4, ("authenticated session setup failed with %s\n",
497 ads_errstr(ads_status)));
500 result = ads_ntstatus(ads_status);
501 if (NT_STATUS_IS_OK(result)) {
502 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
503 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
504 goto session_setup_done;
508 /* Fall back to non-kerberos session setup */
510 (*cli)->use_kerberos = False;
512 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
513 (strlen(ipc_username) > 0)) {
515 /* Only try authenticated if we have a username */
517 DEBUG(5, ("connecting to %s from %s with username "
518 "[%s]\\[%s]\n", controller, global_myname(),
519 ipc_domain, ipc_username));
521 if (NT_STATUS_IS_OK(cli_session_setup(
522 *cli, ipc_username,
523 ipc_password, strlen(ipc_password)+1,
524 ipc_password, strlen(ipc_password)+1,
525 ipc_domain))) {
526 /* Successful logon with given username. */
527 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
528 goto session_setup_done;
529 } else {
530 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
531 ipc_domain, ipc_username ));
535 /* Fall back to anonymous connection, this might fail later */
537 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
538 NULL, 0, ""))) {
539 DEBUG(5, ("Connected anonymously\n"));
540 cli_init_creds(*cli, "", "", "");
541 goto session_setup_done;
544 result = cli_nt_error(*cli);
546 if (NT_STATUS_IS_OK(result))
547 result = NT_STATUS_UNSUCCESSFUL;
549 /* We can't session setup */
551 goto done;
553 session_setup_done:
555 /* cache the server name for later connections */
557 saf_store( domain->name, (*cli)->desthost );
558 if (domain->alt_name && (*cli)->use_kerberos) {
559 saf_store( domain->alt_name, (*cli)->desthost );
562 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
564 result = cli_nt_error(*cli);
566 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
568 if (NT_STATUS_IS_OK(result))
569 result = NT_STATUS_UNSUCCESSFUL;
571 goto done;
574 secrets_named_mutex_release(controller);
575 got_mutex = False;
576 *retry = False;
578 /* set the domain if empty; needed for schannel connections */
579 if ( !*(*cli)->domain ) {
580 fstrcpy( (*cli)->domain, domain->name );
583 result = NT_STATUS_OK;
585 done:
586 if (got_mutex) {
587 secrets_named_mutex_release(controller);
590 SAFE_FREE(machine_account);
591 SAFE_FREE(machine_password);
592 SAFE_FREE(machine_krb5_principal);
593 SAFE_FREE(ipc_username);
594 SAFE_FREE(ipc_domain);
595 SAFE_FREE(ipc_password);
597 if (!NT_STATUS_IS_OK(result)) {
598 winbind_add_failed_connection_entry(domain, controller, result);
599 if ((*cli) != NULL) {
600 cli_shutdown(*cli);
601 *cli = NULL;
605 return result;
608 struct dc_name_ip {
609 fstring name;
610 struct in_addr ip;
613 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
614 const char *dcname, struct in_addr ip,
615 struct dc_name_ip **dcs, int *num)
617 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
618 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
619 return False;
622 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
624 if (*dcs == NULL)
625 return False;
627 fstrcpy((*dcs)[*num].name, dcname);
628 (*dcs)[*num].ip = ip;
629 *num += 1;
630 return True;
633 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
634 struct in_addr ip, uint16 port,
635 struct sockaddr_in **addrs, int *num)
637 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
639 if (*addrs == NULL)
640 return False;
642 (*addrs)[*num].sin_family = PF_INET;
643 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
644 (*addrs)[*num].sin_port = htons(port);
646 *num += 1;
647 return True;
650 static void mailslot_name(struct in_addr dc_ip, fstring name)
652 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
655 static BOOL send_getdc_request(struct in_addr dc_ip,
656 const char *domain_name,
657 const DOM_SID *sid)
659 pstring outbuf;
660 char *p;
661 fstring my_acct_name;
662 fstring my_mailslot;
664 mailslot_name(dc_ip, my_mailslot);
666 memset(outbuf, '\0', sizeof(outbuf));
668 p = outbuf;
670 SCVAL(p, 0, SAMLOGON);
671 p++;
673 SCVAL(p, 0, 0); /* Count pointer ... */
674 p++;
676 SIVAL(p, 0, 0); /* The sender's token ... */
677 p += 2;
679 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
680 fstr_sprintf(my_acct_name, "%s$", global_myname());
681 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
683 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
684 p += strlen(my_mailslot)+1;
686 SIVAL(p, 0, 0x80);
687 p+=4;
689 SIVAL(p, 0, sid_size(sid));
690 p+=4;
692 p = ALIGN4(p, outbuf);
694 sid_linearize(p, sid_size(sid), sid);
695 p += sid_size(sid);
697 SIVAL(p, 0, 1);
698 SSVAL(p, 4, 0xffff);
699 SSVAL(p, 6, 0xffff);
700 p+=8;
702 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
703 outbuf, PTR_DIFF(p, outbuf),
704 global_myname(), 0, domain_name, 0x1c,
705 dc_ip);
708 static BOOL receive_getdc_response(struct in_addr dc_ip,
709 const char *domain_name,
710 fstring dc_name)
712 struct packet_struct *packet;
713 fstring my_mailslot;
714 char *buf, *p;
715 fstring dcname, user, domain;
716 int len;
718 mailslot_name(dc_ip, my_mailslot);
720 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
722 if (packet == NULL) {
723 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
724 return False;
727 DEBUG(5, ("Received packet for %s\n", my_mailslot));
729 buf = packet->packet.dgram.data;
730 len = packet->packet.dgram.datasize;
732 if (len < 70) {
733 /* 70 is a completely arbitrary value to make sure
734 the SVAL below does not read uninitialized memory */
735 DEBUG(3, ("GetDC got short response\n"));
736 return False;
739 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
740 p = buf+SVAL(buf, smb_vwv10);
742 if (CVAL(p,0) != SAMLOGON_R) {
743 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
744 return False;
747 p+=2;
748 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
749 STR_TERMINATE|STR_NOALIGN);
750 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
751 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
752 STR_TERMINATE|STR_NOALIGN);
753 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
754 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
755 STR_TERMINATE|STR_NOALIGN);
756 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
758 if (!strequal(domain, domain_name)) {
759 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
760 domain_name, domain));
761 return False;
764 p = dcname;
765 if (*p == '\\') p += 1;
766 if (*p == '\\') p += 1;
768 fstrcpy(dc_name, p);
770 DEBUG(10, ("GetDC gave name %s for domain %s\n",
771 dc_name, domain));
773 return True;
776 /*******************************************************************
777 convert an ip to a name
778 *******************************************************************/
780 static BOOL dcip_to_name( const char *domainname, const char *realm,
781 const DOM_SID *sid, struct in_addr ip, fstring name )
783 struct ip_service ip_list;
785 ip_list.ip = ip;
786 ip_list.port = 0;
788 #ifdef WITH_ADS
789 /* For active directory servers, try to get the ldap server name.
790 None of these failures should be considered critical for now */
792 if (lp_security() == SEC_ADS) {
793 ADS_STRUCT *ads;
795 ads = ads_init(realm, domainname, NULL);
796 ads->auth.flags |= ADS_AUTH_NO_BIND;
798 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
799 /* We got a cldap packet. */
800 fstrcpy(name, ads->config.ldap_server_name);
801 namecache_store(name, 0x20, 1, &ip_list);
803 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
805 if ((ads->config.flags & ADS_KDC) && ads_sitename_match(ads)) {
806 /* We're going to use this KDC for this realm/domain.
807 If we are using sites, then force the krb5 libs
808 to use this KDC. */
810 create_local_private_krb5_conf_for_domain(realm,
811 domainname,
812 ip);
814 /* Ensure we contact this DC also. */
815 saf_store( domainname, name);
816 saf_store( realm, name);
819 ads_destroy( &ads );
820 return True;
823 ads_destroy( &ads );
825 #endif
827 /* try GETDC requests next */
829 if (send_getdc_request(ip, domainname, sid)) {
830 int i;
831 smb_msleep(100);
832 for (i=0; i<5; i++) {
833 if (receive_getdc_response(ip, domainname, name)) {
834 namecache_store(name, 0x20, 1, &ip_list);
835 return True;
837 smb_msleep(500);
841 /* try node status request */
843 if ( name_status_find(domainname, 0x1c, 0x20, ip, name) ) {
844 namecache_store(name, 0x20, 1, &ip_list);
845 return True;
847 return False;
850 /*******************************************************************
851 Retreive a list of IP address for domain controllers. Fill in
852 the dcs[] with results.
853 *******************************************************************/
855 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
856 struct dc_name_ip **dcs, int *num_dcs)
858 fstring dcname;
859 struct in_addr ip;
860 struct ip_service *ip_list = NULL;
861 int iplist_size = 0;
862 int i;
863 BOOL is_our_domain;
864 enum security_types sec = (enum security_types)lp_security();
866 is_our_domain = strequal(domain->name, lp_workgroup());
868 if ( !is_our_domain
869 && get_dc_name_via_netlogon(domain, dcname, &ip)
870 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
872 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
873 dcname, inet_ntoa(ip)));
874 return True;
877 if (sec == SEC_ADS) {
878 /* We need to make sure we know the local site before
879 doing any DNS queries, as this will restrict the
880 get_sorted_dc_list() call below to only fetching
881 DNS records for the correct site. */
883 /* Find any DC to get the site record.
884 We deliberately don't care about the
885 return here. */
886 get_dc_name(domain->name, lp_realm(), dcname, &ip);
888 /* Now do the site-specific AD dns lookup. */
889 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
892 /* try standard netbios queries if no ADS */
894 if (iplist_size==0)
895 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
897 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
899 /* now add to the dc array. We'll wait until the last minute
900 to look up the name of the DC. But we fill in the char* for
901 the ip now in to make the failed connection cache work */
903 for ( i=0; i<iplist_size; i++ ) {
904 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
905 ip_list[i].ip, dcs, num_dcs);
908 SAFE_FREE( ip_list );
910 return True;
913 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
914 const struct winbindd_domain *domain,
915 fstring dcname, struct sockaddr_in *addr, int *fd)
917 struct dc_name_ip *dcs = NULL;
918 int num_dcs = 0;
920 const char **dcnames = NULL;
921 int num_dcnames = 0;
923 struct sockaddr_in *addrs = NULL;
924 int num_addrs = 0;
926 int i, fd_index;
928 again:
929 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
930 return False;
932 for (i=0; i<num_dcs; i++) {
934 add_string_to_array(mem_ctx, dcs[i].name,
935 &dcnames, &num_dcnames);
936 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
937 &addrs, &num_addrs);
939 add_string_to_array(mem_ctx, dcs[i].name,
940 &dcnames, &num_dcnames);
941 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
942 &addrs, &num_addrs);
945 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
946 return False;
948 if ((addrs == NULL) || (dcnames == NULL))
949 return False;
951 /* 5 second timeout. */
952 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
954 for (i=0; i<num_dcs; i++) {
955 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
956 "domain %s address %s. Error was %s\n",
957 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
958 winbind_add_failed_connection_entry(domain,
959 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
961 return False;
964 *addr = addrs[fd_index];
966 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
967 /* Ok, we've got a name for the DC */
968 fstrcpy(dcname, dcnames[fd_index]);
969 return True;
972 /* Try to figure out the name */
973 if (dcip_to_name( domain->name, domain->alt_name, &domain->sid,
974 addr->sin_addr, dcname )) {
975 return True;
978 /* We can not continue without the DC's name */
979 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
980 NT_STATUS_UNSUCCESSFUL);
981 goto again;
984 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
985 struct winbindd_cm_conn *new_conn)
987 TALLOC_CTX *mem_ctx;
988 NTSTATUS result;
989 char *saf_servername = saf_fetch( domain->name );
990 int retries;
992 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
993 SAFE_FREE(saf_servername);
994 set_domain_offline(domain);
995 return NT_STATUS_NO_MEMORY;
998 /* we have to check the server affinity cache here since
999 later we selecte a DC based on response time and not preference */
1001 /* Check the negative connection cache
1002 before talking to it. It going down may have
1003 triggered the reconnection. */
1005 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1007 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1008 saf_servername, domain->name ));
1010 /* convert an ip address to a name */
1011 if ( is_ipaddress( saf_servername ) ) {
1012 fstring saf_name;
1013 struct in_addr ip;
1015 ip = *interpret_addr2( saf_servername );
1016 if (dcip_to_name( domain->name, domain->alt_name,
1017 &domain->sid, ip, saf_name )) {
1018 fstrcpy( domain->dcname, saf_name );
1019 } else {
1020 winbind_add_failed_connection_entry(
1021 domain, saf_servername,
1022 NT_STATUS_UNSUCCESSFUL);
1024 } else {
1025 fstrcpy( domain->dcname, saf_servername );
1028 SAFE_FREE( saf_servername );
1031 for (retries = 0; retries < 3; retries++) {
1033 int fd = -1;
1034 BOOL retry = False;
1036 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1038 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1039 domain->dcname, domain->name ));
1041 if (*domain->dcname
1042 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1043 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1045 struct sockaddr_in *addrs = NULL;
1046 int num_addrs = 0;
1047 int dummy = 0;
1049 add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs);
1050 add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs);
1052 /* 5 second timeout. */
1053 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1054 fd = -1;
1058 if ((fd == -1)
1059 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1061 /* This is the one place where we will
1062 set the global winbindd offline state
1063 to true, if a "WINBINDD_OFFLINE" entry
1064 is found in the winbindd cache. */
1065 set_global_winbindd_state_offline();
1066 break;
1069 new_conn->cli = NULL;
1071 result = cm_prepare_connection(domain, fd, domain->dcname,
1072 &new_conn->cli, &retry);
1074 if (!retry)
1075 break;
1078 if (NT_STATUS_IS_OK(result)) {
1079 if (domain->online == False) {
1080 /* We're changing state from offline to online. */
1081 set_global_winbindd_state_online();
1083 set_domain_online(domain);
1084 } else {
1085 /* Ensure we setup the retry handler. */
1086 set_domain_offline(domain);
1089 talloc_destroy(mem_ctx);
1090 return result;
1093 /* Close down all open pipes on a connection. */
1095 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1097 /* We're closing down a possibly dead
1098 connection. Don't have impossibly long (10s) timeouts. */
1100 if (conn->cli) {
1101 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1104 if (conn->samr_pipe != NULL) {
1105 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1106 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1107 if (conn->cli) {
1108 cli_set_timeout(conn->cli, 500);
1111 conn->samr_pipe = NULL;
1114 if (conn->lsa_pipe != NULL) {
1115 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1116 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1117 if (conn->cli) {
1118 cli_set_timeout(conn->cli, 500);
1121 conn->lsa_pipe = NULL;
1124 if (conn->netlogon_pipe != NULL) {
1125 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1126 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1127 if (conn->cli) {
1128 cli_set_timeout(conn->cli, 500);
1131 conn->netlogon_pipe = NULL;
1134 if (conn->cli) {
1135 cli_shutdown(conn->cli);
1138 conn->cli = NULL;
1141 void close_conns_after_fork(void)
1143 struct winbindd_domain *domain;
1145 for (domain = domain_list(); domain; domain = domain->next) {
1146 if (domain->conn.cli == NULL)
1147 continue;
1149 if (domain->conn.cli->fd == -1)
1150 continue;
1152 close(domain->conn.cli->fd);
1153 domain->conn.cli->fd = -1;
1157 static BOOL connection_ok(struct winbindd_domain *domain)
1159 if (domain->conn.cli == NULL) {
1160 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1161 "cli!\n", domain->dcname, domain->name));
1162 return False;
1165 if (!domain->conn.cli->initialised) {
1166 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1167 "initialised!\n", domain->dcname, domain->name));
1168 return False;
1171 if (domain->conn.cli->fd == -1) {
1172 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1173 "never started (fd == -1)\n",
1174 domain->dcname, domain->name));
1175 return False;
1178 if (domain->online == False) {
1179 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1180 return False;
1183 return True;
1186 /* Initialize a new connection up to the RPC BIND. */
1188 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1190 NTSTATUS result;
1192 if (connection_ok(domain)) {
1193 if (!domain->initialized) {
1194 set_dc_type_and_flags(domain);
1196 return NT_STATUS_OK;
1199 invalidate_cm_connection(&domain->conn);
1201 result = cm_open_connection(domain, &domain->conn);
1203 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1204 set_dc_type_and_flags(domain);
1207 return result;
1210 /******************************************************************************
1211 We can 'sense' certain things about the DC by it's replies to certain
1212 questions.
1214 This tells us if this particular remote server is Active Directory, and if it
1215 is native mode.
1216 ******************************************************************************/
1218 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1220 NTSTATUS result;
1221 DS_DOMINFO_CTR ctr;
1222 TALLOC_CTX *mem_ctx = NULL;
1223 struct rpc_pipe_client *cli;
1224 POLICY_HND pol;
1226 char *domain_name = NULL;
1227 char *dns_name = NULL;
1228 DOM_SID *dom_sid = NULL;
1230 ZERO_STRUCT( ctr );
1232 if (domain->internal) {
1233 domain->initialized = True;
1234 return;
1237 if (!connection_ok(domain)) {
1238 return;
1241 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1243 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1244 &result);
1246 if (cli == NULL) {
1247 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1248 "PI_LSARPC_DS on domain %s: (%s)\n",
1249 domain->name, nt_errstr(result)));
1250 return;
1253 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1254 DsRolePrimaryDomainInfoBasic,
1255 &ctr);
1256 cli_rpc_pipe_close(cli);
1258 if (!NT_STATUS_IS_OK(result)) {
1259 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1260 "on domain %s failed: (%s)\n",
1261 domain->name, nt_errstr(result)));
1262 return;
1265 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1266 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1267 domain->native_mode = True;
1268 } else {
1269 domain->native_mode = False;
1272 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1274 if (cli == NULL) {
1275 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1276 "PI_LSARPC on domain %s: (%s)\n",
1277 domain->name, nt_errstr(result)));
1278 cli_rpc_pipe_close(cli);
1279 return;
1282 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1283 domain->name);
1284 if (!mem_ctx) {
1285 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1286 cli_rpc_pipe_close(cli);
1287 return;
1290 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1291 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1293 if (NT_STATUS_IS_OK(result)) {
1294 /* This particular query is exactly what Win2k clients use
1295 to determine that the DC is active directory */
1296 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1297 12, &domain_name,
1298 &dns_name, NULL,
1299 NULL, &dom_sid);
1302 if (NT_STATUS_IS_OK(result)) {
1303 domain->active_directory = True;
1305 if (domain_name)
1306 fstrcpy(domain->name, domain_name);
1308 if (dns_name)
1309 fstrcpy(domain->alt_name, dns_name);
1311 if (dom_sid)
1312 sid_copy(&domain->sid, dom_sid);
1313 } else {
1314 domain->active_directory = False;
1316 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1317 SEC_RIGHTS_MAXIMUM_ALLOWED,
1318 &pol);
1320 if (!NT_STATUS_IS_OK(result))
1321 goto done;
1323 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1324 &pol, 5, &domain_name,
1325 &dom_sid);
1327 if (NT_STATUS_IS_OK(result)) {
1328 if (domain_name)
1329 fstrcpy(domain->name, domain_name);
1331 if (dom_sid)
1332 sid_copy(&domain->sid, dom_sid);
1335 done:
1337 DEBUG(5, ("set_dc_type_and_flags: domain %s is %snative mode.\n",
1338 domain->name, domain->native_mode ? "" : "NOT "));
1340 DEBUG(5,("set_dc_type_and_flags: domain %s is %sactive directory.\n",
1341 domain->name, domain->active_directory ? "" : "NOT "));
1343 cli_rpc_pipe_close(cli);
1345 talloc_destroy(mem_ctx);
1347 domain->initialized = True;
1350 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1351 struct dcinfo **ppdc)
1353 NTSTATUS result;
1354 struct rpc_pipe_client *netlogon_pipe;
1356 if (lp_client_schannel() == False) {
1357 return False;
1360 result = cm_connect_netlogon(domain, &netlogon_pipe);
1361 if (!NT_STATUS_IS_OK(result)) {
1362 return False;
1365 /* Return a pointer to the struct dcinfo from the
1366 netlogon pipe. */
1368 *ppdc = domain->conn.netlogon_pipe->dc;
1369 return True;
1372 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1373 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1375 struct winbindd_cm_conn *conn;
1376 NTSTATUS result;
1377 fstring conn_pwd;
1378 struct dcinfo *p_dcinfo;
1380 result = init_dc_connection(domain);
1381 if (!NT_STATUS_IS_OK(result)) {
1382 return result;
1385 conn = &domain->conn;
1387 if (conn->samr_pipe != NULL) {
1388 goto done;
1392 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1393 * sign and sealed pipe using the machine account password by
1394 * preference. If we can't - try schannel, if that fails, try
1395 * anonymous.
1398 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1399 if ((conn->cli->user_name[0] == '\0') ||
1400 (conn->cli->domain[0] == '\0') ||
1401 (conn_pwd[0] == '\0')) {
1402 DEBUG(10, ("cm_connect_sam: No no user available for "
1403 "domain %s, trying schannel\n", conn->cli->domain));
1404 goto schannel;
1407 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1408 authenticated SAMR pipe with sign & seal. */
1409 conn->samr_pipe =
1410 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1411 PIPE_AUTH_LEVEL_PRIVACY,
1412 conn->cli->domain,
1413 conn->cli->user_name,
1414 conn_pwd, &result);
1416 if (conn->samr_pipe == NULL) {
1417 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1418 "pipe for domain %s using NTLMSSP "
1419 "authenticated pipe: user %s\\%s. Error was "
1420 "%s\n", domain->name, conn->cli->domain,
1421 conn->cli->user_name, nt_errstr(result)));
1422 goto schannel;
1425 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1426 "domain %s using NTLMSSP authenticated "
1427 "pipe: user %s\\%s\n", domain->name,
1428 conn->cli->domain, conn->cli->user_name ));
1430 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1431 SEC_RIGHTS_MAXIMUM_ALLOWED,
1432 &conn->sam_connect_handle);
1433 if (NT_STATUS_IS_OK(result)) {
1434 goto open_domain;
1436 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1437 "failed for domain %s, error was %s. Trying schannel\n",
1438 domain->name, nt_errstr(result) ));
1439 cli_rpc_pipe_close(conn->samr_pipe);
1441 schannel:
1443 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1445 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1446 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1447 "for domain %s, trying anon\n", conn->cli->domain));
1448 goto anonymous;
1450 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1451 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1452 domain->name, p_dcinfo, &result);
1454 if (conn->samr_pipe == NULL) {
1455 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1456 "domain %s using schannel. Error was %s\n",
1457 domain->name, nt_errstr(result) ));
1458 goto anonymous;
1460 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1461 "schannel.\n", domain->name ));
1463 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1464 SEC_RIGHTS_MAXIMUM_ALLOWED,
1465 &conn->sam_connect_handle);
1466 if (NT_STATUS_IS_OK(result)) {
1467 goto open_domain;
1469 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1470 "for domain %s, error was %s. Trying anonymous\n",
1471 domain->name, nt_errstr(result) ));
1472 cli_rpc_pipe_close(conn->samr_pipe);
1474 anonymous:
1476 /* Finally fall back to anonymous. */
1477 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1478 &result);
1480 if (conn->samr_pipe == NULL) {
1481 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1482 goto done;
1485 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1486 SEC_RIGHTS_MAXIMUM_ALLOWED,
1487 &conn->sam_connect_handle);
1488 if (!NT_STATUS_IS_OK(result)) {
1489 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1490 "for domain %s Error was %s\n",
1491 domain->name, nt_errstr(result) ));
1492 goto done;
1495 open_domain:
1496 result = rpccli_samr_open_domain(conn->samr_pipe,
1497 mem_ctx,
1498 &conn->sam_connect_handle,
1499 SEC_RIGHTS_MAXIMUM_ALLOWED,
1500 &domain->sid,
1501 &conn->sam_domain_handle);
1503 done:
1505 if (!NT_STATUS_IS_OK(result)) {
1506 invalidate_cm_connection(conn);
1507 return result;
1510 *cli = conn->samr_pipe;
1511 *sam_handle = conn->sam_domain_handle;
1512 return result;
1515 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1516 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1518 struct winbindd_cm_conn *conn;
1519 NTSTATUS result;
1520 fstring conn_pwd;
1521 struct dcinfo *p_dcinfo;
1523 result = init_dc_connection(domain);
1524 if (!NT_STATUS_IS_OK(result))
1525 return result;
1527 conn = &domain->conn;
1529 if (conn->lsa_pipe != NULL) {
1530 goto done;
1533 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1534 if ((conn->cli->user_name[0] == '\0') ||
1535 (conn->cli->domain[0] == '\0') ||
1536 (conn_pwd[0] == '\0')) {
1537 DEBUG(10, ("cm_connect_lsa: No no user available for "
1538 "domain %s, trying schannel\n", conn->cli->domain));
1539 goto schannel;
1542 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1543 * authenticated LSA pipe with sign & seal. */
1544 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1545 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1546 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1548 if (conn->lsa_pipe == NULL) {
1549 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1550 "domain %s using NTLMSSP authenticated pipe: user "
1551 "%s\\%s. Error was %s. Trying schannel.\n",
1552 domain->name, conn->cli->domain,
1553 conn->cli->user_name, nt_errstr(result)));
1554 goto schannel;
1557 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1558 "NTLMSSP authenticated pipe: user %s\\%s\n",
1559 domain->name, conn->cli->domain, conn->cli->user_name ));
1561 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1562 SEC_RIGHTS_MAXIMUM_ALLOWED,
1563 &conn->lsa_policy);
1564 if (NT_STATUS_IS_OK(result)) {
1565 goto done;
1568 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1569 "schannel\n"));
1571 cli_rpc_pipe_close(conn->lsa_pipe);
1573 schannel:
1575 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1577 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1578 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1579 "for domain %s, trying anon\n", conn->cli->domain));
1580 goto anonymous;
1582 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1583 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1584 domain->name, p_dcinfo, &result);
1586 if (conn->lsa_pipe == NULL) {
1587 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1588 "domain %s using schannel. Error was %s\n",
1589 domain->name, nt_errstr(result) ));
1590 goto anonymous;
1592 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1593 "schannel.\n", domain->name ));
1595 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1596 SEC_RIGHTS_MAXIMUM_ALLOWED,
1597 &conn->lsa_policy);
1598 if (NT_STATUS_IS_OK(result)) {
1599 goto done;
1602 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1603 "anonymous\n"));
1605 cli_rpc_pipe_close(conn->lsa_pipe);
1607 anonymous:
1609 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1610 &result);
1611 if (conn->lsa_pipe == NULL) {
1612 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1613 goto done;
1616 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1617 SEC_RIGHTS_MAXIMUM_ALLOWED,
1618 &conn->lsa_policy);
1619 done:
1620 if (!NT_STATUS_IS_OK(result)) {
1621 invalidate_cm_connection(conn);
1622 return NT_STATUS_UNSUCCESSFUL;
1625 *cli = conn->lsa_pipe;
1626 *lsa_policy = conn->lsa_policy;
1627 return result;
1630 /****************************************************************************
1631 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1632 session key stored in conn->netlogon_pipe->dc->sess_key.
1633 ****************************************************************************/
1635 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1636 struct rpc_pipe_client **cli)
1638 struct winbindd_cm_conn *conn;
1639 NTSTATUS result;
1641 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1642 uint8 mach_pwd[16];
1643 uint32 sec_chan_type;
1644 const char *account_name;
1645 struct rpc_pipe_client *netlogon_pipe = NULL;
1647 *cli = NULL;
1649 result = init_dc_connection(domain);
1650 if (!NT_STATUS_IS_OK(result)) {
1651 return result;
1654 conn = &domain->conn;
1656 if (conn->netlogon_pipe != NULL) {
1657 *cli = conn->netlogon_pipe;
1658 return NT_STATUS_OK;
1661 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1662 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1665 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1666 &result);
1667 if (netlogon_pipe == NULL) {
1668 return result;
1671 if (lp_client_schannel() != False) {
1672 neg_flags |= NETLOGON_NEG_SCHANNEL;
1675 /* if we are a DC and this is a trusted domain, then we need to use our
1676 domain name in the net_req_auth2() request */
1678 if ( IS_DC
1679 && !strequal(domain->name, lp_workgroup())
1680 && lp_allow_trusted_domains() )
1682 account_name = lp_workgroup();
1683 } else {
1684 account_name = domain->primary ?
1685 global_myname() : domain->name;
1688 if (account_name == NULL) {
1689 cli_rpc_pipe_close(netlogon_pipe);
1690 return NT_STATUS_NO_MEMORY;
1693 result = rpccli_netlogon_setup_creds(
1694 netlogon_pipe,
1695 domain->dcname, /* server name. */
1696 domain->name, /* domain name */
1697 global_myname(), /* client name */
1698 account_name, /* machine account */
1699 mach_pwd, /* machine password */
1700 sec_chan_type, /* from get_trust_pw */
1701 &neg_flags);
1703 if (!NT_STATUS_IS_OK(result)) {
1704 cli_rpc_pipe_close(netlogon_pipe);
1705 return result;
1708 if ((lp_client_schannel() == True) &&
1709 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1710 DEBUG(3, ("Server did not offer schannel\n"));
1711 cli_rpc_pipe_close(netlogon_pipe);
1712 return NT_STATUS_ACCESS_DENIED;
1715 if ((lp_client_schannel() == False) ||
1716 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1717 /* We're done - just keep the existing connection to NETLOGON
1718 * open */
1719 conn->netlogon_pipe = netlogon_pipe;
1720 *cli = conn->netlogon_pipe;
1721 return NT_STATUS_OK;
1724 /* Using the credentials from the first pipe, open a signed and sealed
1725 second netlogon pipe. The session key is stored in the schannel
1726 part of the new pipe auth struct.
1729 conn->netlogon_pipe =
1730 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1731 PI_NETLOGON,
1732 PIPE_AUTH_LEVEL_PRIVACY,
1733 domain->name,
1734 netlogon_pipe->dc,
1735 &result);
1737 /* We can now close the initial netlogon pipe. */
1738 cli_rpc_pipe_close(netlogon_pipe);
1740 if (conn->netlogon_pipe == NULL) {
1741 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1742 "was %s\n", nt_errstr(result)));
1744 /* make sure we return something besides OK */
1745 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
1748 *cli = conn->netlogon_pipe;
1749 return NT_STATUS_OK;