r20090: Fix a class of bugs found by James Peach. Ensure
[Samba/nascimento.git] / source3 / nsswitch / winbindd_cm.c
blob2c341d5efa8d057d2507179d77216c41b3baf8da
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
10 Copyright (C) Jeremy Allison 2006
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 We need to manage connections to domain controllers without having to
29 mess up the main winbindd code with other issues. The aim of the
30 connection manager is to:
32 - make connections to domain controllers and cache them
33 - re-establish connections when networks or servers go down
34 - centralise the policy on connection timeouts, domain controller
35 selection etc
36 - manage re-entrancy for when winbindd becomes able to handle
37 multiple outstanding rpc requests
39 Why not have connection management as part of the rpc layer like tng?
40 Good question. This code may morph into libsmb/rpc_cache.c or something
41 like that but at the moment it's simply staying as part of winbind. I
42 think the TNG architecture of forcing every user of the rpc layer to use
43 the connection caching system is a bad idea. It should be an optional
44 method of using the routines.
46 The TNG design is quite good but I disagree with some aspects of the
47 implementation. -tpot
52 TODO:
54 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
55 moved down into another function.
57 - Take care when destroying cli_structs as they can be shared between
58 various sam handles.
62 #include "includes.h"
63 #include "winbindd.h"
65 #undef DBGC_CLASS
66 #define DBGC_CLASS DBGC_WINBIND
68 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
69 static void set_dc_type_and_flags( struct winbindd_domain *domain );
71 /****************************************************************
72 If we're still offline, exponentially increase the timeout check.
73 ****************************************************************/
75 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
77 int wbc = lp_winbind_cache_time();
79 if (domain->startup) {
80 domain->check_online_timeout = 10;
81 } else if (domain->check_online_timeout < wbc) {
82 domain->check_online_timeout = wbc;
83 } else {
84 uint32 new_to = domain->check_online_timeout * 3;
85 if (new_to > (3*60*60)) {
86 new_to = 3*60*60; /* 3 hours. */
88 domain->check_online_timeout = new_to;
92 /****************************************************************
93 Handler triggered if we're offline to try and detect a DC.
94 ****************************************************************/
96 static void check_domain_online_handler(struct timed_event *te,
97 const struct timeval *now,
98 void *private_data)
100 struct winbindd_domain *domain =
101 (struct winbindd_domain *)private_data;
103 DEBUG(10,("check_domain_online_handler: called for domain %s\n",
104 domain->name ));
106 if (domain->check_online_event) {
107 TALLOC_FREE(domain->check_online_event);
110 /* Are we still in "startup" mode ? */
112 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
113 /* No longer in "startup" mode. */
114 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
115 domain->name ));
116 domain->startup = False;
119 /* We've been told to stay offline, so stay
120 that way. */
122 if (get_global_winbindd_state_offline()) {
123 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
124 domain->name ));
125 return;
128 /* This call takes care of setting the online
129 flag to true if we connected, or re-adding
130 the offline handler if false. Bypasses online
131 check so always does network calls. */
133 init_dc_connection_network(domain);
136 /****************************************************************
137 Set domain offline and also add handler to put us back online
138 if we detect a DC.
139 ****************************************************************/
141 void set_domain_offline(struct winbindd_domain *domain)
143 DEBUG(10,("set_domain_offline: called for domain %s\n",
144 domain->name ));
146 if (domain->check_online_event) {
147 TALLOC_FREE(domain->check_online_event);
150 if (domain->internal) {
151 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
152 domain->name ));
153 return;
156 domain->online = False;
158 /* Offline domains are always initialized. They're
159 re-initialized when they go back online. */
161 domain->initialized = True;
163 /* We only add the timeout handler that checks and
164 allows us to go back online when we've not
165 been told to remain offline. */
167 if (get_global_winbindd_state_offline()) {
168 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
169 domain->name ));
170 return;
173 /* If we're in statup mode, check again in 10 seconds, not in
174 lp_winbind_cache_time() seconds (which is 5 mins by default). */
176 calc_new_online_timeout_check(domain);
178 domain->check_online_event = add_timed_event( NULL,
179 timeval_current_ofs(domain->check_online_timeout,0),
180 "check_domain_online_handler",
181 check_domain_online_handler,
182 domain);
184 /* The above *has* to succeed for winbindd to work. */
185 if (!domain->check_online_event) {
186 smb_panic("set_domain_offline: failed to add online handler.\n");
189 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
190 domain->name ));
193 /****************************************************************
194 Set domain online - if allowed.
195 ****************************************************************/
197 static void set_domain_online(struct winbindd_domain *domain)
199 extern struct winbindd_methods reconnect_methods;
200 struct timeval now;
202 DEBUG(10,("set_domain_online: called for domain %s\n",
203 domain->name ));
205 if (domain->internal) {
206 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
207 domain->name ));
208 return;
211 if (get_global_winbindd_state_offline()) {
212 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
213 domain->name ));
214 return;
217 /* If we are waiting to get a krb5 ticket, trigger immediately. */
218 GetTimeOfDay(&now);
219 set_event_dispatch_time("krb5_ticket_gain_handler", now);
221 /* Ok, we're out of any startup mode now... */
222 domain->startup = False;
224 if (domain->online == False) {
225 /* We were offline - now we're online. We default to
226 using the MS-RPC backend if we started offline,
227 and if we're going online for the first time we
228 should really re-initialize the backends and the
229 checks to see if we're talking to an AD or NT domain.
232 domain->initialized = False;
234 /* 'reconnect_methods' is the MS-RPC backend. */
235 if (domain->backend == &reconnect_methods) {
236 domain->backend = NULL;
240 /* Ensure we have no online timeout checks. */
241 domain->check_online_timeout = 0;
242 if (domain->check_online_event) {
243 TALLOC_FREE(domain->check_online_event);
246 domain->online = True;
249 /****************************************************************
250 Requested to set a domain online.
251 ****************************************************************/
253 void set_domain_online_request(struct winbindd_domain *domain)
255 DEBUG(10,("set_domain_online_request: called for domain %s\n",
256 domain->name ));
258 if (get_global_winbindd_state_offline()) {
259 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
260 domain->name ));
261 return;
264 /* We've been told it's safe to go online and
265 try and connect to a DC. But I don't believe it
266 because network manager seems to lie.
267 Wait at least 5 seconds. Heuristics suck... */
269 if (!domain->check_online_event) {
270 DEBUG(5,("set_domain_online_request: no check_domain_online_handler "
271 "registered. Were we online (%d) ?\n", (int)domain->online ));
272 } else {
273 struct timeval tev;
275 GetTimeOfDay(&tev);
277 /* Go into "startup" mode again. */
278 domain->startup_time = tev.tv_sec;
279 domain->startup = True;
281 tev.tv_sec += 5;
282 set_event_dispatch_time("check_domain_online_handler", tev);
286 /****************************************************************
287 Add -ve connection cache entries for domain and realm.
288 ****************************************************************/
290 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
291 const char *server,
292 NTSTATUS result)
294 add_failed_connection_entry(domain->name, server, result);
295 /* If this was the saf name for the last thing we talked to,
296 remove it. */
297 saf_delete(domain->name);
298 if (*domain->alt_name) {
299 add_failed_connection_entry(domain->alt_name, server, result);
300 saf_delete(domain->alt_name);
304 /* Choose between anonymous or authenticated connections. We need to use
305 an authenticated connection if DCs have the RestrictAnonymous registry
306 entry set > 0, or the "Additional restrictions for anonymous
307 connections" set in the win2k Local Security Policy.
309 Caller to free() result in domain, username, password
312 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
314 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
315 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
316 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
318 if (*username && **username) {
320 if (!*domain || !**domain)
321 *domain = smb_xstrdup(lp_workgroup());
323 if (!*password || !**password)
324 *password = smb_xstrdup("");
326 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
327 *domain, *username));
329 } else {
330 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
331 *username = smb_xstrdup("");
332 *domain = smb_xstrdup("");
333 *password = smb_xstrdup("");
337 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
338 fstring dcname, struct in_addr *dc_ip)
340 struct winbindd_domain *our_domain = NULL;
341 struct rpc_pipe_client *netlogon_pipe = NULL;
342 NTSTATUS result;
343 WERROR werr;
344 TALLOC_CTX *mem_ctx;
345 unsigned int orig_timeout;
346 fstring tmp;
347 char *p;
349 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
350 * moment.... */
352 if (IS_DC) {
353 return False;
356 if (domain->primary) {
357 return False;
360 our_domain = find_our_domain();
362 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
363 return False;
366 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
367 if (!NT_STATUS_IS_OK(result)) {
368 return False;
371 /* This call can take a long time - allow the server to time out.
372 35 seconds should do it. */
374 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
376 werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
377 domain->name, tmp);
379 /* And restore our original timeout. */
380 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
382 talloc_destroy(mem_ctx);
384 if (!W_ERROR_IS_OK(werr)) {
385 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
386 dos_errstr(werr)));
387 return False;
390 /* cli_netlogon_getdcname gives us a name with \\ */
391 p = tmp;
392 if (*p == '\\') {
393 p+=1;
395 if (*p == '\\') {
396 p+=1;
399 fstrcpy(dcname, p);
401 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
403 if (!resolve_name(dcname, dc_ip, 0x20)) {
404 return False;
407 return True;
410 /************************************************************************
411 Given a fd with a just-connected TCP connection to a DC, open a connection
412 to the pipe.
413 ************************************************************************/
415 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
416 const int sockfd,
417 const char *controller,
418 struct cli_state **cli,
419 BOOL *retry)
421 char *machine_password, *machine_krb5_principal, *machine_account;
422 char *ipc_username, *ipc_domain, *ipc_password;
424 BOOL got_mutex;
426 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
428 struct sockaddr peeraddr;
429 socklen_t peeraddr_len;
431 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
433 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
434 controller, domain->name ));
436 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
437 NULL);
439 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
440 SAFE_FREE(machine_password);
441 return NT_STATUS_NO_MEMORY;
444 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
445 lp_realm()) == -1) {
446 SAFE_FREE(machine_account);
447 SAFE_FREE(machine_password);
448 return NT_STATUS_NO_MEMORY;
451 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
453 *retry = True;
455 got_mutex = secrets_named_mutex(controller,
456 WINBIND_SERVER_MUTEX_WAIT_TIME);
458 if (!got_mutex) {
459 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
460 controller));
461 result = NT_STATUS_POSSIBLE_DEADLOCK;
462 goto done;
465 if ((*cli = cli_initialise()) == NULL) {
466 DEBUG(1, ("Could not cli_initialize\n"));
467 result = NT_STATUS_NO_MEMORY;
468 goto done;
471 (*cli)->timeout = 10000; /* 10 seconds */
472 (*cli)->fd = sockfd;
473 fstrcpy((*cli)->desthost, controller);
474 (*cli)->use_kerberos = True;
476 peeraddr_len = sizeof(peeraddr);
478 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
479 (peeraddr_len != sizeof(struct sockaddr_in)) ||
480 (peeraddr_in->sin_family != PF_INET))
482 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
483 result = NT_STATUS_UNSUCCESSFUL;
484 goto done;
487 if (ntohs(peeraddr_in->sin_port) == 139) {
488 struct nmb_name calling;
489 struct nmb_name called;
491 make_nmb_name(&calling, global_myname(), 0x0);
492 make_nmb_name(&called, "*SMBSERVER", 0x20);
494 if (!cli_session_request(*cli, &calling, &called)) {
495 DEBUG(8, ("cli_session_request failed for %s\n",
496 controller));
497 result = NT_STATUS_UNSUCCESSFUL;
498 goto done;
502 cli_setup_signing_state(*cli, Undefined);
504 if (!cli_negprot(*cli)) {
505 DEBUG(1, ("cli_negprot failed\n"));
506 result = NT_STATUS_UNSUCCESSFUL;
507 goto done;
510 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
511 ADS_STATUS ads_status;
513 if (lp_security() == SEC_ADS) {
515 /* Try a krb5 session */
517 (*cli)->use_kerberos = True;
518 DEBUG(5, ("connecting to %s from %s with kerberos principal "
519 "[%s]\n", controller, global_myname(),
520 machine_krb5_principal));
522 ads_status = cli_session_setup_spnego(*cli,
523 machine_krb5_principal,
524 machine_password,
525 lp_workgroup());
527 if (!ADS_ERR_OK(ads_status)) {
528 DEBUG(4,("failed kerberos session setup with %s\n",
529 ads_errstr(ads_status)));
532 result = ads_ntstatus(ads_status);
533 if (NT_STATUS_IS_OK(result)) {
534 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
535 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
536 goto session_setup_done;
540 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
541 (*cli)->use_kerberos = False;
543 DEBUG(5, ("connecting to %s from %s with username "
544 "[%s]\\[%s]\n", controller, global_myname(),
545 lp_workgroup(), machine_account));
547 ads_status = cli_session_setup_spnego(*cli,
548 machine_account,
549 machine_password,
550 lp_workgroup());
551 if (!ADS_ERR_OK(ads_status)) {
552 DEBUG(4, ("authenticated session setup failed with %s\n",
553 ads_errstr(ads_status)));
556 result = ads_ntstatus(ads_status);
557 if (NT_STATUS_IS_OK(result)) {
558 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
559 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
560 goto session_setup_done;
564 /* Fall back to non-kerberos session setup */
566 (*cli)->use_kerberos = False;
568 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
569 (strlen(ipc_username) > 0)) {
571 /* Only try authenticated if we have a username */
573 DEBUG(5, ("connecting to %s from %s with username "
574 "[%s]\\[%s]\n", controller, global_myname(),
575 ipc_domain, ipc_username));
577 if (NT_STATUS_IS_OK(cli_session_setup(
578 *cli, ipc_username,
579 ipc_password, strlen(ipc_password)+1,
580 ipc_password, strlen(ipc_password)+1,
581 ipc_domain))) {
582 /* Successful logon with given username. */
583 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
584 goto session_setup_done;
585 } else {
586 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
587 ipc_domain, ipc_username ));
591 /* Fall back to anonymous connection, this might fail later */
593 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
594 NULL, 0, ""))) {
595 DEBUG(5, ("Connected anonymously\n"));
596 cli_init_creds(*cli, "", "", "");
597 goto session_setup_done;
600 result = cli_nt_error(*cli);
602 if (NT_STATUS_IS_OK(result))
603 result = NT_STATUS_UNSUCCESSFUL;
605 /* We can't session setup */
607 goto done;
609 session_setup_done:
611 /* cache the server name for later connections */
613 saf_store( domain->name, (*cli)->desthost );
614 if (domain->alt_name && (*cli)->use_kerberos) {
615 saf_store( domain->alt_name, (*cli)->desthost );
618 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
620 result = cli_nt_error(*cli);
622 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
624 if (NT_STATUS_IS_OK(result))
625 result = NT_STATUS_UNSUCCESSFUL;
627 goto done;
630 secrets_named_mutex_release(controller);
631 got_mutex = False;
632 *retry = False;
634 /* set the domain if empty; needed for schannel connections */
635 if ( !*(*cli)->domain ) {
636 fstrcpy( (*cli)->domain, domain->name );
639 result = NT_STATUS_OK;
641 done:
642 if (got_mutex) {
643 secrets_named_mutex_release(controller);
646 SAFE_FREE(machine_account);
647 SAFE_FREE(machine_password);
648 SAFE_FREE(machine_krb5_principal);
649 SAFE_FREE(ipc_username);
650 SAFE_FREE(ipc_domain);
651 SAFE_FREE(ipc_password);
653 if (!NT_STATUS_IS_OK(result)) {
654 winbind_add_failed_connection_entry(domain, controller, result);
655 if ((*cli) != NULL) {
656 cli_shutdown(*cli);
657 *cli = NULL;
661 return result;
664 struct dc_name_ip {
665 fstring name;
666 struct in_addr ip;
669 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
670 const char *dcname, struct in_addr ip,
671 struct dc_name_ip **dcs, int *num)
673 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
674 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
675 return False;
678 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
680 if (*dcs == NULL)
681 return False;
683 fstrcpy((*dcs)[*num].name, dcname);
684 (*dcs)[*num].ip = ip;
685 *num += 1;
686 return True;
689 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
690 struct in_addr ip, uint16 port,
691 struct sockaddr_in **addrs, int *num)
693 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
695 if (*addrs == NULL) {
696 *num = 0;
697 return False;
700 (*addrs)[*num].sin_family = PF_INET;
701 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
702 (*addrs)[*num].sin_port = htons(port);
704 *num += 1;
705 return True;
708 static void mailslot_name(struct in_addr dc_ip, fstring name)
710 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
713 static BOOL send_getdc_request(struct in_addr dc_ip,
714 const char *domain_name,
715 const DOM_SID *sid)
717 pstring outbuf;
718 char *p;
719 fstring my_acct_name;
720 fstring my_mailslot;
722 mailslot_name(dc_ip, my_mailslot);
724 memset(outbuf, '\0', sizeof(outbuf));
726 p = outbuf;
728 SCVAL(p, 0, SAMLOGON);
729 p++;
731 SCVAL(p, 0, 0); /* Count pointer ... */
732 p++;
734 SIVAL(p, 0, 0); /* The sender's token ... */
735 p += 2;
737 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
738 fstr_sprintf(my_acct_name, "%s$", global_myname());
739 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
741 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
742 p += strlen(my_mailslot)+1;
744 SIVAL(p, 0, 0x80);
745 p+=4;
747 SIVAL(p, 0, sid_size(sid));
748 p+=4;
750 p = ALIGN4(p, outbuf);
752 sid_linearize(p, sid_size(sid), sid);
753 p += sid_size(sid);
755 SIVAL(p, 0, 1);
756 SSVAL(p, 4, 0xffff);
757 SSVAL(p, 6, 0xffff);
758 p+=8;
760 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
761 outbuf, PTR_DIFF(p, outbuf),
762 global_myname(), 0, domain_name, 0x1c,
763 dc_ip);
766 static BOOL receive_getdc_response(struct in_addr dc_ip,
767 const char *domain_name,
768 fstring dc_name)
770 struct packet_struct *packet;
771 fstring my_mailslot;
772 char *buf, *p;
773 fstring dcname, user, domain;
774 int len;
776 mailslot_name(dc_ip, my_mailslot);
778 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
780 if (packet == NULL) {
781 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
782 return False;
785 DEBUG(5, ("Received packet for %s\n", my_mailslot));
787 buf = packet->packet.dgram.data;
788 len = packet->packet.dgram.datasize;
790 if (len < 70) {
791 /* 70 is a completely arbitrary value to make sure
792 the SVAL below does not read uninitialized memory */
793 DEBUG(3, ("GetDC got short response\n"));
794 return False;
797 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
798 p = buf+SVAL(buf, smb_vwv10);
800 if (CVAL(p,0) != SAMLOGON_R) {
801 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
802 return False;
805 p+=2;
806 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
807 STR_TERMINATE|STR_NOALIGN);
808 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
809 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
810 STR_TERMINATE|STR_NOALIGN);
811 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
812 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
813 STR_TERMINATE|STR_NOALIGN);
814 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
816 if (!strequal(domain, domain_name)) {
817 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
818 domain_name, domain));
819 return False;
822 p = dcname;
823 if (*p == '\\') p += 1;
824 if (*p == '\\') p += 1;
826 fstrcpy(dc_name, p);
828 DEBUG(10, ("GetDC gave name %s for domain %s\n",
829 dc_name, domain));
831 return True;
834 /*******************************************************************
835 convert an ip to a name
836 *******************************************************************/
838 static BOOL dcip_to_name( const char *domainname, const char *realm,
839 const DOM_SID *sid, struct in_addr ip, fstring name )
841 struct ip_service ip_list;
843 ip_list.ip = ip;
844 ip_list.port = 0;
846 #ifdef WITH_ADS
847 /* For active directory servers, try to get the ldap server name.
848 None of these failures should be considered critical for now */
850 if (lp_security() == SEC_ADS) {
851 ADS_STRUCT *ads;
853 ads = ads_init(realm, domainname, NULL);
854 ads->auth.flags |= ADS_AUTH_NO_BIND;
856 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
857 /* We got a cldap packet. */
858 fstrcpy(name, ads->config.ldap_server_name);
859 namecache_store(name, 0x20, 1, &ip_list);
861 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
863 if ((ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
864 /* We're going to use this KDC for this realm/domain.
865 If we are using sites, then force the krb5 libs
866 to use this KDC. */
868 create_local_private_krb5_conf_for_domain(realm,
869 domainname,
870 ip);
872 /* Ensure we contact this DC also. */
873 saf_store( domainname, name);
874 saf_store( realm, name);
877 ads_destroy( &ads );
878 return True;
881 ads_destroy( &ads );
883 #endif
885 /* try GETDC requests next */
887 if (send_getdc_request(ip, domainname, sid)) {
888 int i;
889 smb_msleep(100);
890 for (i=0; i<5; i++) {
891 if (receive_getdc_response(ip, domainname, name)) {
892 namecache_store(name, 0x20, 1, &ip_list);
893 return True;
895 smb_msleep(500);
899 /* try node status request */
901 if ( name_status_find(domainname, 0x1c, 0x20, ip, name) ) {
902 namecache_store(name, 0x20, 1, &ip_list);
903 return True;
905 return False;
908 /*******************************************************************
909 Retreive a list of IP address for domain controllers. Fill in
910 the dcs[] with results.
911 *******************************************************************/
913 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
914 struct dc_name_ip **dcs, int *num_dcs)
916 fstring dcname;
917 struct in_addr ip;
918 struct ip_service *ip_list = NULL;
919 int iplist_size = 0;
920 int i;
921 BOOL is_our_domain;
922 enum security_types sec = (enum security_types)lp_security();
924 is_our_domain = strequal(domain->name, lp_workgroup());
926 if ( !is_our_domain
927 && get_dc_name_via_netlogon(domain, dcname, &ip)
928 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
930 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
931 dcname, inet_ntoa(ip)));
932 return True;
935 if (sec == SEC_ADS) {
936 /* We need to make sure we know the local site before
937 doing any DNS queries, as this will restrict the
938 get_sorted_dc_list() call below to only fetching
939 DNS records for the correct site. */
941 /* Find any DC to get the site record.
942 We deliberately don't care about the
943 return here. */
944 get_dc_name(domain->name, lp_realm(), dcname, &ip);
946 /* Now do the site-specific AD dns lookup. */
947 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
950 /* try standard netbios queries if no ADS */
952 if (iplist_size==0)
953 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
955 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
957 /* now add to the dc array. We'll wait until the last minute
958 to look up the name of the DC. But we fill in the char* for
959 the ip now in to make the failed connection cache work */
961 for ( i=0; i<iplist_size; i++ ) {
962 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
963 ip_list[i].ip, dcs, num_dcs);
966 SAFE_FREE( ip_list );
968 return True;
971 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
972 const struct winbindd_domain *domain,
973 fstring dcname, struct sockaddr_in *addr, int *fd)
975 struct dc_name_ip *dcs = NULL;
976 int num_dcs = 0;
978 const char **dcnames = NULL;
979 int num_dcnames = 0;
981 struct sockaddr_in *addrs = NULL;
982 int num_addrs = 0;
984 int i, fd_index;
986 again:
987 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
988 return False;
990 for (i=0; i<num_dcs; i++) {
992 if (!add_string_to_array(mem_ctx, dcs[i].name,
993 &dcnames, &num_dcnames)) {
994 return False;
996 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
997 &addrs, &num_addrs)) {
998 return False;
1001 if (!add_string_to_array(mem_ctx, dcs[i].name,
1002 &dcnames, &num_dcnames)) {
1003 return False;
1005 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1006 &addrs, &num_addrs)) {
1007 return False;
1011 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1012 return False;
1014 if ((addrs == NULL) || (dcnames == NULL))
1015 return False;
1017 /* 5 second timeout. */
1018 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1020 for (i=0; i<num_dcs; i++) {
1021 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1022 "domain %s address %s. Error was %s\n",
1023 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1024 winbind_add_failed_connection_entry(domain,
1025 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1027 return False;
1030 *addr = addrs[fd_index];
1032 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1033 /* Ok, we've got a name for the DC */
1034 fstrcpy(dcname, dcnames[fd_index]);
1035 return True;
1038 /* Try to figure out the name */
1039 if (dcip_to_name( domain->name, domain->alt_name, &domain->sid,
1040 addr->sin_addr, dcname )) {
1041 return True;
1044 /* We can not continue without the DC's name */
1045 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1046 NT_STATUS_UNSUCCESSFUL);
1047 goto again;
1050 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1051 struct winbindd_cm_conn *new_conn)
1053 TALLOC_CTX *mem_ctx;
1054 NTSTATUS result;
1055 char *saf_servername = saf_fetch( domain->name );
1056 int retries;
1058 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1059 SAFE_FREE(saf_servername);
1060 set_domain_offline(domain);
1061 return NT_STATUS_NO_MEMORY;
1064 /* we have to check the server affinity cache here since
1065 later we selecte a DC based on response time and not preference */
1067 /* Check the negative connection cache
1068 before talking to it. It going down may have
1069 triggered the reconnection. */
1071 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1073 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1074 saf_servername, domain->name ));
1076 /* convert an ip address to a name */
1077 if ( is_ipaddress( saf_servername ) ) {
1078 fstring saf_name;
1079 struct in_addr ip;
1081 ip = *interpret_addr2( saf_servername );
1082 if (dcip_to_name( domain->name, domain->alt_name,
1083 &domain->sid, ip, saf_name )) {
1084 fstrcpy( domain->dcname, saf_name );
1085 } else {
1086 winbind_add_failed_connection_entry(
1087 domain, saf_servername,
1088 NT_STATUS_UNSUCCESSFUL);
1090 } else {
1091 fstrcpy( domain->dcname, saf_servername );
1094 SAFE_FREE( saf_servername );
1097 for (retries = 0; retries < 3; retries++) {
1099 int fd = -1;
1100 BOOL retry = False;
1102 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1104 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1105 domain->dcname, domain->name ));
1107 if (*domain->dcname
1108 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1109 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1111 struct sockaddr_in *addrs = NULL;
1112 int num_addrs = 0;
1113 int dummy = 0;
1115 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1116 set_domain_offline(domain);
1117 return NT_STATUS_NO_MEMORY;
1119 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1120 set_domain_offline(domain);
1121 return NT_STATUS_NO_MEMORY;
1124 /* 5 second timeout. */
1125 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1126 fd = -1;
1130 if ((fd == -1)
1131 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1133 /* This is the one place where we will
1134 set the global winbindd offline state
1135 to true, if a "WINBINDD_OFFLINE" entry
1136 is found in the winbindd cache. */
1137 set_global_winbindd_state_offline();
1138 break;
1141 new_conn->cli = NULL;
1143 result = cm_prepare_connection(domain, fd, domain->dcname,
1144 &new_conn->cli, &retry);
1146 if (!retry)
1147 break;
1150 if (NT_STATUS_IS_OK(result)) {
1151 if (domain->online == False) {
1152 /* We're changing state from offline to online. */
1153 set_global_winbindd_state_online();
1155 set_domain_online(domain);
1156 } else {
1157 /* Ensure we setup the retry handler. */
1158 set_domain_offline(domain);
1161 talloc_destroy(mem_ctx);
1162 return result;
1165 /* Close down all open pipes on a connection. */
1167 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1169 /* We're closing down a possibly dead
1170 connection. Don't have impossibly long (10s) timeouts. */
1172 if (conn->cli) {
1173 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1176 if (conn->samr_pipe != NULL) {
1177 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1178 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1179 if (conn->cli) {
1180 cli_set_timeout(conn->cli, 500);
1183 conn->samr_pipe = NULL;
1186 if (conn->lsa_pipe != NULL) {
1187 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1188 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1189 if (conn->cli) {
1190 cli_set_timeout(conn->cli, 500);
1193 conn->lsa_pipe = NULL;
1196 if (conn->netlogon_pipe != NULL) {
1197 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1198 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1199 if (conn->cli) {
1200 cli_set_timeout(conn->cli, 500);
1203 conn->netlogon_pipe = NULL;
1206 if (conn->cli) {
1207 cli_shutdown(conn->cli);
1210 conn->cli = NULL;
1213 void close_conns_after_fork(void)
1215 struct winbindd_domain *domain;
1217 for (domain = domain_list(); domain; domain = domain->next) {
1218 if (domain->conn.cli == NULL)
1219 continue;
1221 if (domain->conn.cli->fd == -1)
1222 continue;
1224 close(domain->conn.cli->fd);
1225 domain->conn.cli->fd = -1;
1229 static BOOL connection_ok(struct winbindd_domain *domain)
1231 if (domain->conn.cli == NULL) {
1232 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1233 "cli!\n", domain->dcname, domain->name));
1234 return False;
1237 if (!domain->conn.cli->initialised) {
1238 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1239 "initialised!\n", domain->dcname, domain->name));
1240 return False;
1243 if (domain->conn.cli->fd == -1) {
1244 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1245 "never started (fd == -1)\n",
1246 domain->dcname, domain->name));
1247 return False;
1250 if (domain->online == False) {
1251 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1252 return False;
1255 return True;
1258 /* Initialize a new connection up to the RPC BIND.
1259 Bypass online status check so always does network calls. */
1261 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1263 NTSTATUS result;
1265 /* Internal connections never use the network. */
1266 if (domain->internal) {
1267 domain->initialized = True;
1268 return NT_STATUS_OK;
1271 if (connection_ok(domain)) {
1272 if (!domain->initialized) {
1273 set_dc_type_and_flags(domain);
1275 return NT_STATUS_OK;
1278 invalidate_cm_connection(&domain->conn);
1280 result = cm_open_connection(domain, &domain->conn);
1282 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1283 set_dc_type_and_flags(domain);
1286 return result;
1289 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1291 if (domain->initialized && !domain->online) {
1292 /* We check for online status elsewhere. */
1293 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1296 return init_dc_connection_network(domain);
1299 /******************************************************************************
1300 We can 'sense' certain things about the DC by it's replies to certain
1301 questions.
1303 This tells us if this particular remote server is Active Directory, and if it
1304 is native mode.
1305 ******************************************************************************/
1307 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1309 NTSTATUS result;
1310 DS_DOMINFO_CTR ctr;
1311 TALLOC_CTX *mem_ctx = NULL;
1312 struct rpc_pipe_client *cli;
1313 POLICY_HND pol;
1315 char *domain_name = NULL;
1316 char *dns_name = NULL;
1317 DOM_SID *dom_sid = NULL;
1319 ZERO_STRUCT( ctr );
1321 if (!connection_ok(domain)) {
1322 return;
1325 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1327 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1328 &result);
1330 if (cli == NULL) {
1331 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1332 "PI_LSARPC_DS on domain %s: (%s)\n",
1333 domain->name, nt_errstr(result)));
1334 return;
1337 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1338 DsRolePrimaryDomainInfoBasic,
1339 &ctr);
1340 cli_rpc_pipe_close(cli);
1342 if (!NT_STATUS_IS_OK(result)) {
1343 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1344 "on domain %s failed: (%s)\n",
1345 domain->name, nt_errstr(result)));
1346 return;
1349 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1350 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1351 domain->native_mode = True;
1352 } else {
1353 domain->native_mode = False;
1356 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1358 if (cli == NULL) {
1359 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1360 "PI_LSARPC on domain %s: (%s)\n",
1361 domain->name, nt_errstr(result)));
1362 cli_rpc_pipe_close(cli);
1363 return;
1366 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1367 domain->name);
1368 if (!mem_ctx) {
1369 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1370 cli_rpc_pipe_close(cli);
1371 return;
1374 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1375 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1377 if (NT_STATUS_IS_OK(result)) {
1378 /* This particular query is exactly what Win2k clients use
1379 to determine that the DC is active directory */
1380 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1381 12, &domain_name,
1382 &dns_name, NULL,
1383 NULL, &dom_sid);
1386 if (NT_STATUS_IS_OK(result)) {
1387 domain->active_directory = True;
1389 if (domain_name)
1390 fstrcpy(domain->name, domain_name);
1392 if (dns_name)
1393 fstrcpy(domain->alt_name, dns_name);
1395 if (dom_sid)
1396 sid_copy(&domain->sid, dom_sid);
1397 } else {
1398 domain->active_directory = False;
1400 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1401 SEC_RIGHTS_MAXIMUM_ALLOWED,
1402 &pol);
1404 if (!NT_STATUS_IS_OK(result))
1405 goto done;
1407 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1408 &pol, 5, &domain_name,
1409 &dom_sid);
1411 if (NT_STATUS_IS_OK(result)) {
1412 if (domain_name)
1413 fstrcpy(domain->name, domain_name);
1415 if (dom_sid)
1416 sid_copy(&domain->sid, dom_sid);
1419 done:
1421 DEBUG(5, ("set_dc_type_and_flags: domain %s is %snative mode.\n",
1422 domain->name, domain->native_mode ? "" : "NOT "));
1424 DEBUG(5,("set_dc_type_and_flags: domain %s is %sactive directory.\n",
1425 domain->name, domain->active_directory ? "" : "NOT "));
1427 cli_rpc_pipe_close(cli);
1429 talloc_destroy(mem_ctx);
1431 domain->initialized = True;
1434 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1435 struct dcinfo **ppdc)
1437 NTSTATUS result;
1438 struct rpc_pipe_client *netlogon_pipe;
1440 if (lp_client_schannel() == False) {
1441 return False;
1444 result = cm_connect_netlogon(domain, &netlogon_pipe);
1445 if (!NT_STATUS_IS_OK(result)) {
1446 return False;
1449 /* Return a pointer to the struct dcinfo from the
1450 netlogon pipe. */
1452 *ppdc = domain->conn.netlogon_pipe->dc;
1453 return True;
1456 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1457 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1459 struct winbindd_cm_conn *conn;
1460 NTSTATUS result;
1461 fstring conn_pwd;
1462 struct dcinfo *p_dcinfo;
1464 result = init_dc_connection(domain);
1465 if (!NT_STATUS_IS_OK(result)) {
1466 return result;
1469 conn = &domain->conn;
1471 if (conn->samr_pipe != NULL) {
1472 goto done;
1476 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1477 * sign and sealed pipe using the machine account password by
1478 * preference. If we can't - try schannel, if that fails, try
1479 * anonymous.
1482 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1483 if ((conn->cli->user_name[0] == '\0') ||
1484 (conn->cli->domain[0] == '\0') ||
1485 (conn_pwd[0] == '\0')) {
1486 DEBUG(10, ("cm_connect_sam: No no user available for "
1487 "domain %s, trying schannel\n", conn->cli->domain));
1488 goto schannel;
1491 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1492 authenticated SAMR pipe with sign & seal. */
1493 conn->samr_pipe =
1494 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1495 PIPE_AUTH_LEVEL_PRIVACY,
1496 conn->cli->domain,
1497 conn->cli->user_name,
1498 conn_pwd, &result);
1500 if (conn->samr_pipe == NULL) {
1501 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1502 "pipe for domain %s using NTLMSSP "
1503 "authenticated pipe: user %s\\%s. Error was "
1504 "%s\n", domain->name, conn->cli->domain,
1505 conn->cli->user_name, nt_errstr(result)));
1506 goto schannel;
1509 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1510 "domain %s using NTLMSSP authenticated "
1511 "pipe: user %s\\%s\n", domain->name,
1512 conn->cli->domain, conn->cli->user_name ));
1514 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1515 SEC_RIGHTS_MAXIMUM_ALLOWED,
1516 &conn->sam_connect_handle);
1517 if (NT_STATUS_IS_OK(result)) {
1518 goto open_domain;
1520 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1521 "failed for domain %s, error was %s. Trying schannel\n",
1522 domain->name, nt_errstr(result) ));
1523 cli_rpc_pipe_close(conn->samr_pipe);
1525 schannel:
1527 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1529 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1530 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1531 "for domain %s, trying anon\n", conn->cli->domain));
1532 goto anonymous;
1534 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1535 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1536 domain->name, p_dcinfo, &result);
1538 if (conn->samr_pipe == NULL) {
1539 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1540 "domain %s using schannel. Error was %s\n",
1541 domain->name, nt_errstr(result) ));
1542 goto anonymous;
1544 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1545 "schannel.\n", domain->name ));
1547 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1548 SEC_RIGHTS_MAXIMUM_ALLOWED,
1549 &conn->sam_connect_handle);
1550 if (NT_STATUS_IS_OK(result)) {
1551 goto open_domain;
1553 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1554 "for domain %s, error was %s. Trying anonymous\n",
1555 domain->name, nt_errstr(result) ));
1556 cli_rpc_pipe_close(conn->samr_pipe);
1558 anonymous:
1560 /* Finally fall back to anonymous. */
1561 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1562 &result);
1564 if (conn->samr_pipe == NULL) {
1565 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1566 goto done;
1569 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1570 SEC_RIGHTS_MAXIMUM_ALLOWED,
1571 &conn->sam_connect_handle);
1572 if (!NT_STATUS_IS_OK(result)) {
1573 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1574 "for domain %s Error was %s\n",
1575 domain->name, nt_errstr(result) ));
1576 goto done;
1579 open_domain:
1580 result = rpccli_samr_open_domain(conn->samr_pipe,
1581 mem_ctx,
1582 &conn->sam_connect_handle,
1583 SEC_RIGHTS_MAXIMUM_ALLOWED,
1584 &domain->sid,
1585 &conn->sam_domain_handle);
1587 done:
1589 if (!NT_STATUS_IS_OK(result)) {
1590 invalidate_cm_connection(conn);
1591 return result;
1594 *cli = conn->samr_pipe;
1595 *sam_handle = conn->sam_domain_handle;
1596 return result;
1599 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1600 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1602 struct winbindd_cm_conn *conn;
1603 NTSTATUS result;
1604 fstring conn_pwd;
1605 struct dcinfo *p_dcinfo;
1607 result = init_dc_connection(domain);
1608 if (!NT_STATUS_IS_OK(result))
1609 return result;
1611 conn = &domain->conn;
1613 if (conn->lsa_pipe != NULL) {
1614 goto done;
1617 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1618 if ((conn->cli->user_name[0] == '\0') ||
1619 (conn->cli->domain[0] == '\0') ||
1620 (conn_pwd[0] == '\0')) {
1621 DEBUG(10, ("cm_connect_lsa: No no user available for "
1622 "domain %s, trying schannel\n", conn->cli->domain));
1623 goto schannel;
1626 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1627 * authenticated LSA pipe with sign & seal. */
1628 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1629 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1630 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1632 if (conn->lsa_pipe == NULL) {
1633 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1634 "domain %s using NTLMSSP authenticated pipe: user "
1635 "%s\\%s. Error was %s. Trying schannel.\n",
1636 domain->name, conn->cli->domain,
1637 conn->cli->user_name, nt_errstr(result)));
1638 goto schannel;
1641 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1642 "NTLMSSP authenticated pipe: user %s\\%s\n",
1643 domain->name, conn->cli->domain, conn->cli->user_name ));
1645 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1646 SEC_RIGHTS_MAXIMUM_ALLOWED,
1647 &conn->lsa_policy);
1648 if (NT_STATUS_IS_OK(result)) {
1649 goto done;
1652 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1653 "schannel\n"));
1655 cli_rpc_pipe_close(conn->lsa_pipe);
1657 schannel:
1659 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1661 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1662 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1663 "for domain %s, trying anon\n", conn->cli->domain));
1664 goto anonymous;
1666 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1667 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1668 domain->name, p_dcinfo, &result);
1670 if (conn->lsa_pipe == NULL) {
1671 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1672 "domain %s using schannel. Error was %s\n",
1673 domain->name, nt_errstr(result) ));
1674 goto anonymous;
1676 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1677 "schannel.\n", domain->name ));
1679 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1680 SEC_RIGHTS_MAXIMUM_ALLOWED,
1681 &conn->lsa_policy);
1682 if (NT_STATUS_IS_OK(result)) {
1683 goto done;
1686 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1687 "anonymous\n"));
1689 cli_rpc_pipe_close(conn->lsa_pipe);
1691 anonymous:
1693 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1694 &result);
1695 if (conn->lsa_pipe == NULL) {
1696 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1697 goto done;
1700 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1701 SEC_RIGHTS_MAXIMUM_ALLOWED,
1702 &conn->lsa_policy);
1703 done:
1704 if (!NT_STATUS_IS_OK(result)) {
1705 invalidate_cm_connection(conn);
1706 return NT_STATUS_UNSUCCESSFUL;
1709 *cli = conn->lsa_pipe;
1710 *lsa_policy = conn->lsa_policy;
1711 return result;
1714 /****************************************************************************
1715 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1716 session key stored in conn->netlogon_pipe->dc->sess_key.
1717 ****************************************************************************/
1719 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1720 struct rpc_pipe_client **cli)
1722 struct winbindd_cm_conn *conn;
1723 NTSTATUS result;
1725 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1726 uint8 mach_pwd[16];
1727 uint32 sec_chan_type;
1728 const char *account_name;
1729 struct rpc_pipe_client *netlogon_pipe = NULL;
1731 *cli = NULL;
1733 result = init_dc_connection(domain);
1734 if (!NT_STATUS_IS_OK(result)) {
1735 return result;
1738 conn = &domain->conn;
1740 if (conn->netlogon_pipe != NULL) {
1741 *cli = conn->netlogon_pipe;
1742 return NT_STATUS_OK;
1745 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1746 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1749 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1750 &result);
1751 if (netlogon_pipe == NULL) {
1752 return result;
1755 if (lp_client_schannel() != False) {
1756 neg_flags |= NETLOGON_NEG_SCHANNEL;
1759 /* if we are a DC and this is a trusted domain, then we need to use our
1760 domain name in the net_req_auth2() request */
1762 if ( IS_DC
1763 && !strequal(domain->name, lp_workgroup())
1764 && lp_allow_trusted_domains() )
1766 account_name = lp_workgroup();
1767 } else {
1768 account_name = domain->primary ?
1769 global_myname() : domain->name;
1772 if (account_name == NULL) {
1773 cli_rpc_pipe_close(netlogon_pipe);
1774 return NT_STATUS_NO_MEMORY;
1777 result = rpccli_netlogon_setup_creds(
1778 netlogon_pipe,
1779 domain->dcname, /* server name. */
1780 domain->name, /* domain name */
1781 global_myname(), /* client name */
1782 account_name, /* machine account */
1783 mach_pwd, /* machine password */
1784 sec_chan_type, /* from get_trust_pw */
1785 &neg_flags);
1787 if (!NT_STATUS_IS_OK(result)) {
1788 cli_rpc_pipe_close(netlogon_pipe);
1789 return result;
1792 if ((lp_client_schannel() == True) &&
1793 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1794 DEBUG(3, ("Server did not offer schannel\n"));
1795 cli_rpc_pipe_close(netlogon_pipe);
1796 return NT_STATUS_ACCESS_DENIED;
1799 if ((lp_client_schannel() == False) ||
1800 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1801 /* We're done - just keep the existing connection to NETLOGON
1802 * open */
1803 conn->netlogon_pipe = netlogon_pipe;
1804 *cli = conn->netlogon_pipe;
1805 return NT_STATUS_OK;
1808 /* Using the credentials from the first pipe, open a signed and sealed
1809 second netlogon pipe. The session key is stored in the schannel
1810 part of the new pipe auth struct.
1813 conn->netlogon_pipe =
1814 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1815 PI_NETLOGON,
1816 PIPE_AUTH_LEVEL_PRIVACY,
1817 domain->name,
1818 netlogon_pipe->dc,
1819 &result);
1821 /* We can now close the initial netlogon pipe. */
1822 cli_rpc_pipe_close(netlogon_pipe);
1824 if (conn->netlogon_pipe == NULL) {
1825 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1826 "was %s\n", nt_errstr(result)));
1828 /* make sure we return something besides OK */
1829 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
1832 *cli = conn->netlogon_pipe;
1833 return NT_STATUS_OK;