r19784: smbd compiles (still a few warning which are actual bugs)
[Samba.git] / source / nsswitch / winbindd_cm.c
blob0be7093c6412d465e0a18503e48cf574ebfbb411
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 if (domain->internal) {
126 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
127 domain->name ));
128 return;
131 domain->online = False;
133 /* We only add the timeout handler that checks and
134 allows us to go back online when we've not
135 been told to remain offline. */
137 if (get_global_winbindd_state_offline()) {
138 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
139 domain->name ));
140 return;
143 /* If we're in statup mode, check again in 10 seconds, not in
144 lp_winbind_cache_time() seconds (which is 5 mins by default). */
146 domain->check_online_event = add_timed_event( NULL,
147 domain->startup ?
148 timeval_current_ofs(10,0) :
149 timeval_current_ofs(lp_winbind_cache_time(), 0),
150 "check_domain_online_handler",
151 check_domain_online_handler,
152 domain);
154 /* The above *has* to succeed for winbindd to work. */
155 if (!domain->check_online_event) {
156 smb_panic("set_domain_offline: failed to add online handler.\n");
159 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
160 domain->name ));
163 /****************************************************************
164 Set domain online - if allowed.
165 ****************************************************************/
167 static void set_domain_online(struct winbindd_domain *domain)
169 extern struct winbindd_methods reconnect_methods;
170 struct timeval now;
172 DEBUG(10,("set_domain_online: called for domain %s\n",
173 domain->name ));
175 if (domain->internal) {
176 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
177 domain->name ));
178 return;
181 if (get_global_winbindd_state_offline()) {
182 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
183 domain->name ));
184 return;
187 /* If we are waiting to get a krb5 ticket, trigger immediately. */
188 GetTimeOfDay(&now);
189 set_event_dispatch_time("krb5_ticket_gain_handler", now);
191 /* Ok, we're out of any startup mode now... */
192 domain->startup = False;
194 if (domain->online == False) {
195 /* We were offline - now we're online. We default to
196 using the MS-RPC backend if we started offline,
197 and if we're going online for the first time we
198 should really re-initialize the backends and the
199 checks to see if we're talking to an AD or NT domain.
202 domain->initialized = False;
204 /* 'reconnect_methods' is the MS-RPC backend. */
205 if (domain->backend == &reconnect_methods) {
206 domain->backend = NULL;
210 domain->online = True;
213 /****************************************************************
214 Requested to set a domain online.
215 ****************************************************************/
217 void set_domain_online_request(struct winbindd_domain *domain)
219 DEBUG(10,("set_domain_online_request: called for domain %s\n",
220 domain->name ));
222 if (get_global_winbindd_state_offline()) {
223 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
224 domain->name ));
225 return;
228 /* We've been told it's safe to go online and
229 try and connect to a DC. But I don't believe it
230 because network manager seems to lie.
231 Wait at least 5 seconds. Heuristics suck... */
233 if (!domain->check_online_event) {
234 DEBUG(5,("set_domain_online_request: no check_domain_online_handler "
235 "registered. Were we online (%d) ?\n", (int)domain->online ));
236 } else {
237 struct timeval tev;
239 GetTimeOfDay(&tev);
241 /* Go into "startup" mode again. */
242 domain->startup_time = tev.tv_sec;
243 domain->startup = True;
245 tev.tv_sec += 5;
246 set_event_dispatch_time("check_domain_online_handler", tev);
250 /****************************************************************
251 Add -ve connection cache entries for domain and realm.
252 ****************************************************************/
254 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
255 const char *server,
256 NTSTATUS result)
258 add_failed_connection_entry(domain->name, server, result);
259 /* If this was the saf name for the last thing we talked to,
260 remove it. */
261 saf_delete(domain->name);
262 if (*domain->alt_name) {
263 add_failed_connection_entry(domain->alt_name, server, result);
264 saf_delete(domain->alt_name);
268 /* Choose between anonymous or authenticated connections. We need to use
269 an authenticated connection if DCs have the RestrictAnonymous registry
270 entry set > 0, or the "Additional restrictions for anonymous
271 connections" set in the win2k Local Security Policy.
273 Caller to free() result in domain, username, password
276 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
278 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
279 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
280 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
282 if (*username && **username) {
284 if (!*domain || !**domain)
285 *domain = smb_xstrdup(lp_workgroup());
287 if (!*password || !**password)
288 *password = smb_xstrdup("");
290 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
291 *domain, *username));
293 } else {
294 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
295 *username = smb_xstrdup("");
296 *domain = smb_xstrdup("");
297 *password = smb_xstrdup("");
301 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
302 fstring dcname, struct in_addr *dc_ip)
304 struct winbindd_domain *our_domain = NULL;
305 struct rpc_pipe_client *netlogon_pipe = NULL;
306 NTSTATUS result;
307 WERROR werr;
308 TALLOC_CTX *mem_ctx;
309 unsigned int orig_timeout;
310 fstring tmp;
311 char *p;
313 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
314 * moment.... */
316 if (IS_DC) {
317 return False;
320 if (domain->primary) {
321 return False;
324 our_domain = find_our_domain();
326 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
327 return False;
330 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
331 if (!NT_STATUS_IS_OK(result)) {
332 return False;
335 /* This call can take a long time - allow the server to time out.
336 35 seconds should do it. */
338 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
340 werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
341 domain->name, tmp);
343 /* And restore our original timeout. */
344 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
346 talloc_destroy(mem_ctx);
348 if (!W_ERROR_IS_OK(werr)) {
349 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
350 dos_errstr(werr)));
351 return False;
354 /* cli_netlogon_getdcname gives us a name with \\ */
355 p = tmp;
356 if (*p == '\\') {
357 p+=1;
359 if (*p == '\\') {
360 p+=1;
363 fstrcpy(dcname, p);
365 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
367 if (!resolve_name(dcname, dc_ip, 0x20)) {
368 return False;
371 return True;
374 /************************************************************************
375 Given a fd with a just-connected TCP connection to a DC, open a connection
376 to the pipe.
377 ************************************************************************/
379 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
380 const int sockfd,
381 const char *controller,
382 struct cli_state **cli,
383 BOOL *retry)
385 char *machine_password, *machine_krb5_principal, *machine_account;
386 char *ipc_username, *ipc_domain, *ipc_password;
388 BOOL got_mutex;
390 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
392 struct sockaddr peeraddr;
393 socklen_t peeraddr_len;
395 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
397 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
398 controller, domain->name ));
400 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
401 NULL);
403 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
404 SAFE_FREE(machine_password);
405 return NT_STATUS_NO_MEMORY;
408 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
409 lp_realm()) == -1) {
410 SAFE_FREE(machine_account);
411 SAFE_FREE(machine_password);
412 return NT_STATUS_NO_MEMORY;
415 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
417 *retry = True;
419 got_mutex = secrets_named_mutex(controller,
420 WINBIND_SERVER_MUTEX_WAIT_TIME);
422 if (!got_mutex) {
423 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
424 controller));
425 result = NT_STATUS_POSSIBLE_DEADLOCK;
426 goto done;
429 if ((*cli = cli_initialise(NULL)) == NULL) {
430 DEBUG(1, ("Could not cli_initialize\n"));
431 result = NT_STATUS_NO_MEMORY;
432 goto done;
435 (*cli)->timeout = 10000; /* 10 seconds */
436 (*cli)->fd = sockfd;
437 fstrcpy((*cli)->desthost, controller);
438 (*cli)->use_kerberos = True;
440 peeraddr_len = sizeof(peeraddr);
442 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
443 (peeraddr_len != sizeof(struct sockaddr_in)) ||
444 (peeraddr_in->sin_family != PF_INET))
446 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
447 result = NT_STATUS_UNSUCCESSFUL;
448 goto done;
451 if (ntohs(peeraddr_in->sin_port) == 139) {
452 struct nmb_name calling;
453 struct nmb_name called;
455 make_nmb_name(&calling, global_myname(), 0x0);
456 make_nmb_name(&called, "*SMBSERVER", 0x20);
458 if (!cli_session_request(*cli, &calling, &called)) {
459 DEBUG(8, ("cli_session_request failed for %s\n",
460 controller));
461 result = NT_STATUS_UNSUCCESSFUL;
462 goto done;
466 cli_setup_signing_state(*cli, Undefined);
468 if (!cli_negprot(*cli)) {
469 DEBUG(1, ("cli_negprot failed\n"));
470 result = NT_STATUS_UNSUCCESSFUL;
471 goto done;
474 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
475 ADS_STATUS ads_status;
477 if (lp_security() == SEC_ADS) {
479 /* Try a krb5 session */
481 (*cli)->use_kerberos = True;
482 DEBUG(5, ("connecting to %s from %s with kerberos principal "
483 "[%s]\n", controller, global_myname(),
484 machine_krb5_principal));
486 ads_status = cli_session_setup_spnego(*cli,
487 machine_krb5_principal,
488 machine_password,
489 lp_workgroup());
491 if (!ADS_ERR_OK(ads_status)) {
492 DEBUG(4,("failed kerberos session setup with %s\n",
493 ads_errstr(ads_status)));
496 result = ads_ntstatus(ads_status);
497 if (NT_STATUS_IS_OK(result)) {
498 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
499 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
500 goto session_setup_done;
504 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
505 (*cli)->use_kerberos = False;
507 DEBUG(5, ("connecting to %s from %s with username "
508 "[%s]\\[%s]\n", controller, global_myname(),
509 lp_workgroup(), machine_account));
511 ads_status = cli_session_setup_spnego(*cli,
512 machine_account,
513 machine_password,
514 lp_workgroup());
515 if (!ADS_ERR_OK(ads_status)) {
516 DEBUG(4, ("authenticated session setup failed with %s\n",
517 ads_errstr(ads_status)));
520 result = ads_ntstatus(ads_status);
521 if (NT_STATUS_IS_OK(result)) {
522 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
523 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
524 goto session_setup_done;
528 /* Fall back to non-kerberos session setup */
530 (*cli)->use_kerberos = False;
532 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
533 (strlen(ipc_username) > 0)) {
535 /* Only try authenticated if we have a username */
537 DEBUG(5, ("connecting to %s from %s with username "
538 "[%s]\\[%s]\n", controller, global_myname(),
539 ipc_domain, ipc_username));
541 if (cli_session_setup(*cli, ipc_username,
542 ipc_password, strlen(ipc_password)+1,
543 ipc_password, strlen(ipc_password)+1,
544 ipc_domain)) {
545 /* Successful logon with given username. */
546 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
547 goto session_setup_done;
548 } else {
549 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
550 ipc_domain, ipc_username ));
554 /* Fall back to anonymous connection, this might fail later */
556 if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
557 DEBUG(5, ("Connected anonymously\n"));
558 cli_init_creds(*cli, "", "", "");
559 goto session_setup_done;
562 result = cli_nt_error(*cli);
564 if (NT_STATUS_IS_OK(result))
565 result = NT_STATUS_UNSUCCESSFUL;
567 /* We can't session setup */
569 goto done;
571 session_setup_done:
573 /* cache the server name for later connections */
575 saf_store( domain->name, (*cli)->desthost );
576 if (domain->alt_name && (*cli)->use_kerberos) {
577 saf_store( domain->alt_name, (*cli)->desthost );
580 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
582 result = cli_nt_error(*cli);
584 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
586 if (NT_STATUS_IS_OK(result))
587 result = NT_STATUS_UNSUCCESSFUL;
589 goto done;
592 secrets_named_mutex_release(controller);
593 got_mutex = False;
594 *retry = False;
596 /* set the domain if empty; needed for schannel connections */
597 if ( !*(*cli)->domain ) {
598 fstrcpy( (*cli)->domain, domain->name );
601 result = NT_STATUS_OK;
603 done:
604 if (got_mutex) {
605 secrets_named_mutex_release(controller);
608 SAFE_FREE(machine_account);
609 SAFE_FREE(machine_password);
610 SAFE_FREE(machine_krb5_principal);
611 SAFE_FREE(ipc_username);
612 SAFE_FREE(ipc_domain);
613 SAFE_FREE(ipc_password);
615 if (!NT_STATUS_IS_OK(result)) {
616 winbind_add_failed_connection_entry(domain, controller, result);
617 if ((*cli) != NULL) {
618 cli_shutdown(*cli);
619 *cli = NULL;
623 return result;
626 struct dc_name_ip {
627 fstring name;
628 struct in_addr ip;
631 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
632 const char *dcname, struct in_addr ip,
633 struct dc_name_ip **dcs, int *num)
635 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
636 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
637 return False;
640 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
642 if (*dcs == NULL)
643 return False;
645 fstrcpy((*dcs)[*num].name, dcname);
646 (*dcs)[*num].ip = ip;
647 *num += 1;
648 return True;
651 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
652 struct in_addr ip, uint16 port,
653 struct sockaddr_in **addrs, int *num)
655 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
657 if (*addrs == NULL)
658 return False;
660 (*addrs)[*num].sin_family = PF_INET;
661 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
662 (*addrs)[*num].sin_port = htons(port);
664 *num += 1;
665 return True;
668 static void mailslot_name(struct in_addr dc_ip, fstring name)
670 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
673 static BOOL send_getdc_request(struct in_addr dc_ip,
674 const char *domain_name,
675 const DOM_SID *sid)
677 pstring outbuf;
678 char *p;
679 fstring my_acct_name;
680 fstring my_mailslot;
682 mailslot_name(dc_ip, my_mailslot);
684 memset(outbuf, '\0', sizeof(outbuf));
686 p = outbuf;
688 SCVAL(p, 0, SAMLOGON);
689 p++;
691 SCVAL(p, 0, 0); /* Count pointer ... */
692 p++;
694 SIVAL(p, 0, 0); /* The sender's token ... */
695 p += 2;
697 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
698 fstr_sprintf(my_acct_name, "%s$", global_myname());
699 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
701 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
702 p += strlen(my_mailslot)+1;
704 SIVAL(p, 0, 0x80);
705 p+=4;
707 SIVAL(p, 0, sid_size(sid));
708 p+=4;
710 p = ALIGN4(p, outbuf);
712 sid_linearize(p, sid_size(sid), sid);
713 p += sid_size(sid);
715 SIVAL(p, 0, 1);
716 SSVAL(p, 4, 0xffff);
717 SSVAL(p, 6, 0xffff);
718 p+=8;
720 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
721 outbuf, PTR_DIFF(p, outbuf),
722 global_myname(), 0, domain_name, 0x1c,
723 dc_ip);
726 static BOOL receive_getdc_response(struct in_addr dc_ip,
727 const char *domain_name,
728 fstring dc_name)
730 struct packet_struct *packet;
731 fstring my_mailslot;
732 char *buf, *p;
733 fstring dcname, user, domain;
734 int len;
736 mailslot_name(dc_ip, my_mailslot);
738 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
740 if (packet == NULL) {
741 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
742 return False;
745 DEBUG(5, ("Received packet for %s\n", my_mailslot));
747 buf = packet->packet.dgram.data;
748 len = packet->packet.dgram.datasize;
750 if (len < 70) {
751 /* 70 is a completely arbitrary value to make sure
752 the SVAL below does not read uninitialized memory */
753 DEBUG(3, ("GetDC got short response\n"));
754 return False;
757 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
758 p = buf+SVAL(buf, smb_vwv10);
760 if (CVAL(p,0) != SAMLOGON_R) {
761 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
762 return False;
765 p+=2;
766 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
767 STR_TERMINATE|STR_NOALIGN);
768 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
769 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
770 STR_TERMINATE|STR_NOALIGN);
771 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
772 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
773 STR_TERMINATE|STR_NOALIGN);
774 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
776 if (!strequal(domain, domain_name)) {
777 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
778 domain_name, domain));
779 return False;
782 p = dcname;
783 if (*p == '\\') p += 1;
784 if (*p == '\\') p += 1;
786 fstrcpy(dc_name, p);
788 DEBUG(10, ("GetDC gave name %s for domain %s\n",
789 dc_name, domain));
791 return True;
794 /*******************************************************************
795 convert an ip to a name
796 *******************************************************************/
798 static BOOL dcip_to_name( const char *domainname, const char *realm,
799 const DOM_SID *sid, struct in_addr ip, fstring name )
801 struct ip_service ip_list;
803 ip_list.ip = ip;
804 ip_list.port = 0;
806 #ifdef WITH_ADS
807 /* For active directory servers, try to get the ldap server name.
808 None of these failures should be considered critical for now */
810 if (lp_security() == SEC_ADS) {
811 ADS_STRUCT *ads;
813 ads = ads_init(realm, domainname, NULL);
814 ads->auth.flags |= ADS_AUTH_NO_BIND;
816 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
817 /* We got a cldap packet. */
818 fstrcpy(name, ads->config.ldap_server_name);
819 namecache_store(name, 0x20, 1, &ip_list);
821 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
823 if ((ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
824 /* We're going to use this KDC for this realm/domain.
825 If we are using sites, then force the krb5 libs
826 to use this KDC. */
828 create_local_private_krb5_conf_for_domain(realm,
829 domainname,
830 ip);
832 /* Ensure we contact this DC also. */
833 saf_store( domainname, name);
834 saf_store( realm, name);
837 ads_destroy( &ads );
838 return True;
841 ads_destroy( &ads );
843 #endif
845 /* try GETDC requests next */
847 if (send_getdc_request(ip, domainname, sid)) {
848 int i;
849 smb_msleep(100);
850 for (i=0; i<5; i++) {
851 if (receive_getdc_response(ip, domainname, name)) {
852 namecache_store(name, 0x20, 1, &ip_list);
853 return True;
855 smb_msleep(500);
859 /* try node status request */
861 if ( name_status_find(domainname, 0x1c, 0x20, ip, name) ) {
862 namecache_store(name, 0x20, 1, &ip_list);
863 return True;
865 return False;
868 /*******************************************************************
869 Retreive a list of IP address for domain controllers. Fill in
870 the dcs[] with results.
871 *******************************************************************/
873 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
874 struct dc_name_ip **dcs, int *num_dcs)
876 fstring dcname;
877 struct in_addr ip;
878 struct ip_service *ip_list = NULL;
879 int iplist_size = 0;
880 int i;
881 BOOL is_our_domain;
882 enum security_types sec = (enum security_types)lp_security();
884 is_our_domain = strequal(domain->name, lp_workgroup());
886 if ( !is_our_domain
887 && get_dc_name_via_netlogon(domain, dcname, &ip)
888 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
890 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
891 dcname, inet_ntoa(ip)));
892 return True;
895 if (sec == SEC_ADS) {
896 /* We need to make sure we know the local site before
897 doing any DNS queries, as this will restrict the
898 get_sorted_dc_list() call below to only fetching
899 DNS records for the correct site. */
901 /* Find any DC to get the site record.
902 We deliberately don't care about the
903 return here. */
904 get_dc_name(domain->name, lp_realm(), dcname, &ip);
906 /* Now do the site-specific AD dns lookup. */
907 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
910 /* try standard netbios queries if no ADS */
912 if (iplist_size==0)
913 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
915 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
917 /* now add to the dc array. We'll wait until the last minute
918 to look up the name of the DC. But we fill in the char* for
919 the ip now in to make the failed connection cache work */
921 for ( i=0; i<iplist_size; i++ ) {
922 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
923 ip_list[i].ip, dcs, num_dcs);
926 SAFE_FREE( ip_list );
928 return True;
931 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
932 const struct winbindd_domain *domain,
933 fstring dcname, struct sockaddr_in *addr, int *fd)
935 struct dc_name_ip *dcs = NULL;
936 int num_dcs = 0;
938 const char **dcnames = NULL;
939 int num_dcnames = 0;
941 struct sockaddr_in *addrs = NULL;
942 int num_addrs = 0;
944 int i, fd_index;
946 again:
947 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
948 return False;
950 for (i=0; i<num_dcs; i++) {
952 add_string_to_array(mem_ctx, dcs[i].name,
953 &dcnames, &num_dcnames);
954 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
955 &addrs, &num_addrs);
957 add_string_to_array(mem_ctx, dcs[i].name,
958 &dcnames, &num_dcnames);
959 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
960 &addrs, &num_addrs);
963 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
964 return False;
966 if ((addrs == NULL) || (dcnames == NULL))
967 return False;
969 /* 5 second timeout. */
970 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
972 for (i=0; i<num_dcs; i++) {
973 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
974 "domain %s address %s. Error was %s\n",
975 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
976 winbind_add_failed_connection_entry(domain,
977 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
979 return False;
982 *addr = addrs[fd_index];
984 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
985 /* Ok, we've got a name for the DC */
986 fstrcpy(dcname, dcnames[fd_index]);
987 return True;
990 /* Try to figure out the name */
991 if (dcip_to_name( domain->name, domain->alt_name, &domain->sid,
992 addr->sin_addr, dcname )) {
993 return True;
996 /* We can not continue without the DC's name */
997 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
998 NT_STATUS_UNSUCCESSFUL);
999 goto again;
1002 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1003 struct winbindd_cm_conn *new_conn)
1005 TALLOC_CTX *mem_ctx;
1006 NTSTATUS result;
1007 char *saf_servername = saf_fetch( domain->name );
1008 int retries;
1010 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1011 SAFE_FREE(saf_servername);
1012 set_domain_offline(domain);
1013 return NT_STATUS_NO_MEMORY;
1016 /* we have to check the server affinity cache here since
1017 later we selecte a DC based on response time and not preference */
1019 /* Check the negative connection cache
1020 before talking to it. It going down may have
1021 triggered the reconnection. */
1023 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1025 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1026 saf_servername, domain->name ));
1028 /* convert an ip address to a name */
1029 if ( is_ipaddress( saf_servername ) ) {
1030 fstring saf_name;
1031 struct in_addr ip;
1033 ip = *interpret_addr2( saf_servername );
1034 if (dcip_to_name( domain->name, domain->alt_name,
1035 &domain->sid, ip, saf_name )) {
1036 fstrcpy( domain->dcname, saf_name );
1037 } else {
1038 winbind_add_failed_connection_entry(
1039 domain, saf_servername,
1040 NT_STATUS_UNSUCCESSFUL);
1042 } else {
1043 fstrcpy( domain->dcname, saf_servername );
1046 SAFE_FREE( saf_servername );
1049 for (retries = 0; retries < 3; retries++) {
1051 int fd = -1;
1052 BOOL retry = False;
1054 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1056 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1057 domain->dcname, domain->name ));
1059 if (*domain->dcname
1060 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1061 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1063 struct sockaddr_in *addrs = NULL;
1064 int num_addrs = 0;
1065 int dummy = 0;
1067 add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs);
1068 add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs);
1070 /* 5 second timeout. */
1071 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1072 fd = -1;
1076 if ((fd == -1)
1077 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1079 /* This is the one place where we will
1080 set the global winbindd offline state
1081 to true, if a "WINBINDD_OFFLINE" entry
1082 is found in the winbindd cache. */
1083 set_global_winbindd_state_offline();
1084 break;
1087 new_conn->cli = NULL;
1089 result = cm_prepare_connection(domain, fd, domain->dcname,
1090 &new_conn->cli, &retry);
1092 if (!retry)
1093 break;
1096 if (NT_STATUS_IS_OK(result)) {
1097 if (domain->online == False) {
1098 /* We're changing state from offline to online. */
1099 set_global_winbindd_state_online();
1101 set_domain_online(domain);
1102 } else {
1103 /* Ensure we setup the retry handler. */
1104 set_domain_offline(domain);
1107 talloc_destroy(mem_ctx);
1108 return result;
1111 /* Close down all open pipes on a connection. */
1113 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1115 /* We're closing down a possibly dead
1116 connection. Don't have impossibly long (10s) timeouts. */
1118 if (conn->cli) {
1119 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1122 if (conn->samr_pipe != NULL) {
1123 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1124 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1125 if (conn->cli) {
1126 cli_set_timeout(conn->cli, 500);
1129 conn->samr_pipe = NULL;
1132 if (conn->lsa_pipe != NULL) {
1133 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1134 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1135 if (conn->cli) {
1136 cli_set_timeout(conn->cli, 500);
1139 conn->lsa_pipe = NULL;
1142 if (conn->netlogon_pipe != NULL) {
1143 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1144 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1145 if (conn->cli) {
1146 cli_set_timeout(conn->cli, 500);
1149 conn->netlogon_pipe = NULL;
1152 if (conn->cli) {
1153 cli_shutdown(conn->cli);
1156 conn->cli = NULL;
1159 void close_conns_after_fork(void)
1161 struct winbindd_domain *domain;
1163 for (domain = domain_list(); domain; domain = domain->next) {
1164 if (domain->conn.cli == NULL)
1165 continue;
1167 if (domain->conn.cli->fd == -1)
1168 continue;
1170 close(domain->conn.cli->fd);
1171 domain->conn.cli->fd = -1;
1175 static BOOL connection_ok(struct winbindd_domain *domain)
1177 if (domain->conn.cli == NULL) {
1178 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1179 "cli!\n", domain->dcname, domain->name));
1180 return False;
1183 if (!domain->conn.cli->initialised) {
1184 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1185 "initialised!\n", domain->dcname, domain->name));
1186 return False;
1189 if (domain->conn.cli->fd == -1) {
1190 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1191 "never started (fd == -1)\n",
1192 domain->dcname, domain->name));
1193 return False;
1196 if (domain->online == False) {
1197 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1198 return False;
1201 return True;
1204 /* Initialize a new connection up to the RPC BIND. */
1206 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1208 NTSTATUS result;
1210 /* Internal connections never use the network. */
1211 if (domain->internal) {
1212 domain->initialized = True;
1213 return NT_STATUS_OK;
1216 if (connection_ok(domain)) {
1217 if (!domain->initialized) {
1218 set_dc_type_and_flags(domain);
1220 return NT_STATUS_OK;
1223 invalidate_cm_connection(&domain->conn);
1225 result = cm_open_connection(domain, &domain->conn);
1227 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1228 set_dc_type_and_flags(domain);
1231 return result;
1234 /******************************************************************************
1235 We can 'sense' certain things about the DC by it's replies to certain
1236 questions.
1238 This tells us if this particular remote server is Active Directory, and if it
1239 is native mode.
1240 ******************************************************************************/
1242 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1244 NTSTATUS result;
1245 DS_DOMINFO_CTR ctr;
1246 TALLOC_CTX *mem_ctx = NULL;
1247 struct rpc_pipe_client *cli;
1248 POLICY_HND pol;
1250 char *domain_name = NULL;
1251 char *dns_name = NULL;
1252 DOM_SID *dom_sid = NULL;
1254 ZERO_STRUCT( ctr );
1256 if (!connection_ok(domain)) {
1257 return;
1260 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1262 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1263 &result);
1265 if (cli == NULL) {
1266 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1267 "PI_LSARPC_DS on domain %s: (%s)\n",
1268 domain->name, nt_errstr(result)));
1269 return;
1272 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1273 DsRolePrimaryDomainInfoBasic,
1274 &ctr);
1275 cli_rpc_pipe_close(cli);
1277 if (!NT_STATUS_IS_OK(result)) {
1278 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1279 "on domain %s failed: (%s)\n",
1280 domain->name, nt_errstr(result)));
1281 return;
1284 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1285 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1286 domain->native_mode = True;
1287 } else {
1288 domain->native_mode = False;
1291 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1293 if (cli == NULL) {
1294 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1295 "PI_LSARPC on domain %s: (%s)\n",
1296 domain->name, nt_errstr(result)));
1297 cli_rpc_pipe_close(cli);
1298 return;
1301 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1302 domain->name);
1303 if (!mem_ctx) {
1304 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1305 cli_rpc_pipe_close(cli);
1306 return;
1309 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1310 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1312 if (NT_STATUS_IS_OK(result)) {
1313 /* This particular query is exactly what Win2k clients use
1314 to determine that the DC is active directory */
1315 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1316 12, &domain_name,
1317 &dns_name, NULL,
1318 NULL, &dom_sid);
1321 if (NT_STATUS_IS_OK(result)) {
1322 domain->active_directory = True;
1324 if (domain_name)
1325 fstrcpy(domain->name, domain_name);
1327 if (dns_name)
1328 fstrcpy(domain->alt_name, dns_name);
1330 if (dom_sid)
1331 sid_copy(&domain->sid, dom_sid);
1332 } else {
1333 domain->active_directory = False;
1335 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1336 SEC_RIGHTS_MAXIMUM_ALLOWED,
1337 &pol);
1339 if (!NT_STATUS_IS_OK(result))
1340 goto done;
1342 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1343 &pol, 5, &domain_name,
1344 &dom_sid);
1346 if (NT_STATUS_IS_OK(result)) {
1347 if (domain_name)
1348 fstrcpy(domain->name, domain_name);
1350 if (dom_sid)
1351 sid_copy(&domain->sid, dom_sid);
1354 done:
1356 DEBUG(5, ("set_dc_type_and_flags: domain %s is %snative mode.\n",
1357 domain->name, domain->native_mode ? "" : "NOT "));
1359 DEBUG(5,("set_dc_type_and_flags: domain %s is %sactive directory.\n",
1360 domain->name, domain->active_directory ? "" : "NOT "));
1362 cli_rpc_pipe_close(cli);
1364 talloc_destroy(mem_ctx);
1366 domain->initialized = True;
1369 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1370 struct dcinfo **ppdc)
1372 NTSTATUS result;
1373 struct rpc_pipe_client *netlogon_pipe;
1375 if (lp_client_schannel() == False) {
1376 return False;
1379 result = cm_connect_netlogon(domain, &netlogon_pipe);
1380 if (!NT_STATUS_IS_OK(result)) {
1381 return False;
1384 /* Return a pointer to the struct dcinfo from the
1385 netlogon pipe. */
1387 *ppdc = domain->conn.netlogon_pipe->dc;
1388 return True;
1391 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1392 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1394 struct winbindd_cm_conn *conn;
1395 NTSTATUS result;
1396 fstring conn_pwd;
1397 struct dcinfo *p_dcinfo;
1399 result = init_dc_connection(domain);
1400 if (!NT_STATUS_IS_OK(result)) {
1401 return result;
1404 conn = &domain->conn;
1406 if (conn->samr_pipe != NULL) {
1407 goto done;
1411 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1412 * sign and sealed pipe using the machine account password by
1413 * preference. If we can't - try schannel, if that fails, try
1414 * anonymous.
1417 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1418 if ((conn->cli->user_name[0] == '\0') ||
1419 (conn->cli->domain[0] == '\0') ||
1420 (conn_pwd[0] == '\0')) {
1421 DEBUG(10, ("cm_connect_sam: No no user available for "
1422 "domain %s, trying schannel\n", conn->cli->domain));
1423 goto schannel;
1426 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1427 authenticated SAMR pipe with sign & seal. */
1428 conn->samr_pipe =
1429 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1430 PIPE_AUTH_LEVEL_PRIVACY,
1431 conn->cli->domain,
1432 conn->cli->user_name,
1433 conn_pwd, &result);
1435 if (conn->samr_pipe == NULL) {
1436 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1437 "pipe for domain %s using NTLMSSP "
1438 "authenticated pipe: user %s\\%s. Error was "
1439 "%s\n", domain->name, conn->cli->domain,
1440 conn->cli->user_name, nt_errstr(result)));
1441 goto schannel;
1444 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1445 "domain %s using NTLMSSP authenticated "
1446 "pipe: user %s\\%s\n", domain->name,
1447 conn->cli->domain, conn->cli->user_name ));
1449 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1450 SEC_RIGHTS_MAXIMUM_ALLOWED,
1451 &conn->sam_connect_handle);
1452 if (NT_STATUS_IS_OK(result)) {
1453 goto open_domain;
1455 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1456 "failed for domain %s, error was %s. Trying schannel\n",
1457 domain->name, nt_errstr(result) ));
1458 cli_rpc_pipe_close(conn->samr_pipe);
1460 schannel:
1462 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1464 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1465 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1466 "for domain %s, trying anon\n", conn->cli->domain));
1467 goto anonymous;
1469 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1470 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1471 domain->name, p_dcinfo, &result);
1473 if (conn->samr_pipe == NULL) {
1474 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1475 "domain %s using schannel. Error was %s\n",
1476 domain->name, nt_errstr(result) ));
1477 goto anonymous;
1479 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1480 "schannel.\n", domain->name ));
1482 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1483 SEC_RIGHTS_MAXIMUM_ALLOWED,
1484 &conn->sam_connect_handle);
1485 if (NT_STATUS_IS_OK(result)) {
1486 goto open_domain;
1488 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1489 "for domain %s, error was %s. Trying anonymous\n",
1490 domain->name, nt_errstr(result) ));
1491 cli_rpc_pipe_close(conn->samr_pipe);
1493 anonymous:
1495 /* Finally fall back to anonymous. */
1496 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1497 &result);
1499 if (conn->samr_pipe == NULL) {
1500 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1501 goto done;
1504 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1505 SEC_RIGHTS_MAXIMUM_ALLOWED,
1506 &conn->sam_connect_handle);
1507 if (!NT_STATUS_IS_OK(result)) {
1508 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1509 "for domain %s Error was %s\n",
1510 domain->name, nt_errstr(result) ));
1511 goto done;
1514 open_domain:
1515 result = rpccli_samr_open_domain(conn->samr_pipe,
1516 mem_ctx,
1517 &conn->sam_connect_handle,
1518 SEC_RIGHTS_MAXIMUM_ALLOWED,
1519 &domain->sid,
1520 &conn->sam_domain_handle);
1522 done:
1524 if (!NT_STATUS_IS_OK(result)) {
1525 invalidate_cm_connection(conn);
1526 return result;
1529 *cli = conn->samr_pipe;
1530 *sam_handle = conn->sam_domain_handle;
1531 return result;
1534 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1535 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1537 struct winbindd_cm_conn *conn;
1538 NTSTATUS result;
1539 fstring conn_pwd;
1540 struct dcinfo *p_dcinfo;
1542 result = init_dc_connection(domain);
1543 if (!NT_STATUS_IS_OK(result))
1544 return result;
1546 conn = &domain->conn;
1548 if (conn->lsa_pipe != NULL) {
1549 goto done;
1552 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1553 if ((conn->cli->user_name[0] == '\0') ||
1554 (conn->cli->domain[0] == '\0') ||
1555 (conn_pwd[0] == '\0')) {
1556 DEBUG(10, ("cm_connect_lsa: No no user available for "
1557 "domain %s, trying schannel\n", conn->cli->domain));
1558 goto schannel;
1561 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1562 * authenticated LSA pipe with sign & seal. */
1563 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1564 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1565 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1567 if (conn->lsa_pipe == NULL) {
1568 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1569 "domain %s using NTLMSSP authenticated pipe: user "
1570 "%s\\%s. Error was %s. Trying schannel.\n",
1571 domain->name, conn->cli->domain,
1572 conn->cli->user_name, nt_errstr(result)));
1573 goto schannel;
1576 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1577 "NTLMSSP authenticated pipe: user %s\\%s\n",
1578 domain->name, conn->cli->domain, conn->cli->user_name ));
1580 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1581 SEC_RIGHTS_MAXIMUM_ALLOWED,
1582 &conn->lsa_policy);
1583 if (NT_STATUS_IS_OK(result)) {
1584 goto done;
1587 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1588 "schannel\n"));
1590 cli_rpc_pipe_close(conn->lsa_pipe);
1592 schannel:
1594 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1596 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1597 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1598 "for domain %s, trying anon\n", conn->cli->domain));
1599 goto anonymous;
1601 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1602 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1603 domain->name, p_dcinfo, &result);
1605 if (conn->lsa_pipe == NULL) {
1606 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1607 "domain %s using schannel. Error was %s\n",
1608 domain->name, nt_errstr(result) ));
1609 goto anonymous;
1611 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1612 "schannel.\n", domain->name ));
1614 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1615 SEC_RIGHTS_MAXIMUM_ALLOWED,
1616 &conn->lsa_policy);
1617 if (NT_STATUS_IS_OK(result)) {
1618 goto done;
1621 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1622 "anonymous\n"));
1624 cli_rpc_pipe_close(conn->lsa_pipe);
1626 anonymous:
1628 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1629 &result);
1630 if (conn->lsa_pipe == NULL) {
1631 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1632 goto done;
1635 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1636 SEC_RIGHTS_MAXIMUM_ALLOWED,
1637 &conn->lsa_policy);
1638 done:
1639 if (!NT_STATUS_IS_OK(result)) {
1640 invalidate_cm_connection(conn);
1641 return NT_STATUS_UNSUCCESSFUL;
1644 *cli = conn->lsa_pipe;
1645 *lsa_policy = conn->lsa_policy;
1646 return result;
1649 /****************************************************************************
1650 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1651 session key stored in conn->netlogon_pipe->dc->sess_key.
1652 ****************************************************************************/
1654 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1655 struct rpc_pipe_client **cli)
1657 struct winbindd_cm_conn *conn;
1658 NTSTATUS result;
1660 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1661 uint8 mach_pwd[16];
1662 uint32 sec_chan_type;
1663 const char *account_name;
1664 struct rpc_pipe_client *netlogon_pipe = NULL;
1666 *cli = NULL;
1668 result = init_dc_connection(domain);
1669 if (!NT_STATUS_IS_OK(result)) {
1670 return result;
1673 conn = &domain->conn;
1675 if (conn->netlogon_pipe != NULL) {
1676 *cli = conn->netlogon_pipe;
1677 return NT_STATUS_OK;
1680 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1681 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1684 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1685 &result);
1686 if (netlogon_pipe == NULL) {
1687 return result;
1690 if (lp_client_schannel() != False) {
1691 neg_flags |= NETLOGON_NEG_SCHANNEL;
1694 /* if we are a DC and this is a trusted domain, then we need to use our
1695 domain name in the net_req_auth2() request */
1697 if ( IS_DC
1698 && !strequal(domain->name, lp_workgroup())
1699 && lp_allow_trusted_domains() )
1701 account_name = lp_workgroup();
1702 } else {
1703 account_name = domain->primary ?
1704 global_myname() : domain->name;
1707 if (account_name == NULL) {
1708 cli_rpc_pipe_close(netlogon_pipe);
1709 return NT_STATUS_NO_MEMORY;
1712 result = rpccli_netlogon_setup_creds(
1713 netlogon_pipe,
1714 domain->dcname, /* server name. */
1715 domain->name, /* domain name */
1716 global_myname(), /* client name */
1717 account_name, /* machine account */
1718 mach_pwd, /* machine password */
1719 sec_chan_type, /* from get_trust_pw */
1720 &neg_flags);
1722 if (!NT_STATUS_IS_OK(result)) {
1723 cli_rpc_pipe_close(netlogon_pipe);
1724 return result;
1727 if ((lp_client_schannel() == True) &&
1728 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1729 DEBUG(3, ("Server did not offer schannel\n"));
1730 cli_rpc_pipe_close(netlogon_pipe);
1731 return NT_STATUS_ACCESS_DENIED;
1734 if ((lp_client_schannel() == False) ||
1735 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1736 /* We're done - just keep the existing connection to NETLOGON
1737 * open */
1738 conn->netlogon_pipe = netlogon_pipe;
1739 *cli = conn->netlogon_pipe;
1740 return NT_STATUS_OK;
1743 /* Using the credentials from the first pipe, open a signed and sealed
1744 second netlogon pipe. The session key is stored in the schannel
1745 part of the new pipe auth struct.
1748 conn->netlogon_pipe =
1749 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1750 PI_NETLOGON,
1751 PIPE_AUTH_LEVEL_PRIVACY,
1752 domain->name,
1753 netlogon_pipe->dc,
1754 &result);
1756 /* We can now close the initial netlogon pipe. */
1757 cli_rpc_pipe_close(netlogon_pipe);
1759 if (conn->netlogon_pipe == NULL) {
1760 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1761 "was %s\n", nt_errstr(result)));
1763 /* make sure we return something besides OK */
1764 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
1767 *cli = conn->netlogon_pipe;
1768 return NT_STATUS_OK;