source: trunk-3.0/source/nsswitch/winbindd_cm.c@ 101

Last change on this file since 101 was 71, checked in by Paul Smedley, 18 years ago

Update source to 3.0.26a

File size: 56.0 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Winbind daemon connection manager
5
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
11
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.
16
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.
21
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.
25*/
26
27/*
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:
31
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
38
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.
45
46 The TNG design is quite good but I disagree with some aspects of the
47 implementation. -tpot
48
49 */
50
51/*
52 TODO:
53
54 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
55 moved down into another function.
56
57 - Take care when destroying cli_structs as they can be shared between
58 various sam handles.
59
60 */
61
62#include "includes.h"
63#include "winbindd.h"
64
65#undef DBGC_CLASS
66#define DBGC_CLASS DBGC_WINBIND
67
68struct dc_name_ip {
69 fstring name;
70 struct in_addr ip;
71};
72
73extern struct winbindd_methods reconnect_methods;
74extern BOOL override_logfile;
75
76static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
77static void set_dc_type_and_flags( struct winbindd_domain *domain );
78static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
79 struct dc_name_ip **dcs, int *num_dcs);
80
81/****************************************************************
82 Child failed to find DC's. Reschedule check.
83****************************************************************/
84
85static void msg_failed_to_go_online(int msg_type, struct process_id src,
86 void *buf, size_t len, void *private_data)
87{
88 struct winbindd_domain *domain;
89 const char *domainname = (const char *)buf;
90
91 if (buf == NULL || len == 0) {
92 return;
93 }
94
95 DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
96
97 for (domain = domain_list(); domain; domain = domain->next) {
98 if (domain->internal) {
99 continue;
100 }
101
102 if (strequal(domain->name, domainname)) {
103 if (domain->online) {
104 /* We're already online, ignore. */
105 DEBUG(5,("msg_fail_to_go_online: domain %s "
106 "already online.\n", domainname));
107 continue;
108 }
109
110 /* Reschedule the online check. */
111 set_domain_offline(domain);
112 break;
113 }
114 }
115}
116
117/****************************************************************
118 Actually cause a reconnect from a message.
119****************************************************************/
120
121static void msg_try_to_go_online(int msg_type, struct process_id src,
122 void *buf, size_t len, void *private_data)
123{
124 struct winbindd_domain *domain;
125 const char *domainname = (const char *)buf;
126
127 if (buf == NULL || len == 0) {
128 return;
129 }
130
131 DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
132
133 for (domain = domain_list(); domain; domain = domain->next) {
134 if (domain->internal) {
135 continue;
136 }
137
138 if (strequal(domain->name, domainname)) {
139
140 if (domain->online) {
141 /* We're already online, ignore. */
142 DEBUG(5,("msg_try_to_go_online: domain %s "
143 "already online.\n", domainname));
144 continue;
145 }
146
147 /* This call takes care of setting the online
148 flag to true if we connected, or re-adding
149 the offline handler if false. Bypasses online
150 check so always does network calls. */
151
152 init_dc_connection_network(domain);
153 break;
154 }
155 }
156}
157
158/****************************************************************
159 Fork a child to try and contact a DC. Do this as contacting a
160 DC requires blocking lookups and we don't want to block our
161 parent.
162****************************************************************/
163
164static BOOL fork_child_dc_connect(struct winbindd_domain *domain)
165{
166 struct dc_name_ip *dcs = NULL;
167 int num_dcs = 0;
168 TALLOC_CTX *mem_ctx = NULL;
169 pid_t child_pid;
170 pid_t parent_pid = sys_getpid();
171
172 /* Stop zombies */
173 CatchChild();
174
175 message_block();
176
177 child_pid = sys_fork();
178
179 if (child_pid == -1) {
180 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
181 message_unblock();
182 return False;
183 }
184
185 if (child_pid != 0) {
186 /* Parent */
187 message_register(MSG_WINBIND_TRY_TO_GO_ONLINE,
188 msg_try_to_go_online, NULL);
189 message_register(MSG_WINBIND_FAILED_TO_GO_ONLINE,
190 msg_failed_to_go_online, NULL);
191 message_unblock();
192 return True;
193 }
194
195 /* Child. */
196
197 /* Leave messages blocked - we will never process one. */
198
199 /* tdb needs special fork handling */
200 if (tdb_reopen_all(1) == -1) {
201 DEBUG(0,("tdb_reopen_all failed.\n"));
202 _exit(0);
203 }
204
205 close_conns_after_fork();
206
207 if (!override_logfile) {
208 pstring logfile;
209 pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
210 lp_set_logfile(logfile);
211 reopen_logs();
212 }
213
214 mem_ctx = talloc_init("fork_child_dc_connect");
215 if (!mem_ctx) {
216 DEBUG(0,("talloc_init failed.\n"));
217 _exit(0);
218 }
219
220 if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
221 /* Still offline ? Can't find DC's. */
222 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE,
223 domain->name,
224 strlen(domain->name)+1, False);
225 _exit(0);
226 }
227
228 /* We got a DC. Send a message to our parent to get it to
229 try and do the same. */
230
231 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE,
232 domain->name,
233 strlen(domain->name)+1, False);
234 _exit(0);
235}
236
237/****************************************************************
238 Handler triggered if we're offline to try and detect a DC.
239****************************************************************/
240
241static void check_domain_online_handler(struct event_context *ctx,
242 struct timed_event *te,
243 const struct timeval *now,
244 void *private_data)
245{
246 struct winbindd_domain *domain =
247 (struct winbindd_domain *)private_data;
248
249 DEBUG(10,("check_domain_online_handler: called for domain %s\n",
250 domain->name ));
251
252 TALLOC_FREE(domain->check_online_event);
253
254 /* Are we still in "startup" mode ? */
255
256 if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
257 /* No longer in "startup" mode. */
258 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
259 domain->name ));
260 domain->startup = False;
261 }
262
263 /* We've been told to stay offline, so stay
264 that way. */
265
266 if (get_global_winbindd_state_offline()) {
267 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
268 domain->name ));
269 return;
270 }
271
272 /* Fork a child to test if it can contact a DC.
273 If it can then send ourselves a message to
274 cause a reconnect. */
275
276 fork_child_dc_connect(domain);
277}
278
279/****************************************************************
280 If we're still offline setup the timeout check.
281****************************************************************/
282
283static void calc_new_online_timeout_check(struct winbindd_domain *domain)
284{
285 int wbc = lp_winbind_cache_time();
286
287 if (domain->startup) {
288 domain->check_online_timeout = 10;
289 } else if (domain->check_online_timeout < wbc) {
290 domain->check_online_timeout = wbc;
291 }
292}
293
294/****************************************************************
295 Set domain offline and also add handler to put us back online
296 if we detect a DC.
297****************************************************************/
298
299void set_domain_offline(struct winbindd_domain *domain)
300{
301 DEBUG(10,("set_domain_offline: called for domain %s\n",
302 domain->name ));
303
304 TALLOC_FREE(domain->check_online_event);
305
306 if (domain->internal) {
307 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
308 domain->name ));
309 return;
310 }
311
312 domain->online = False;
313
314 /* Offline domains are always initialized. They're
315 re-initialized when they go back online. */
316
317 domain->initialized = True;
318
319 /* We only add the timeout handler that checks and
320 allows us to go back online when we've not
321 been told to remain offline. */
322
323 if (get_global_winbindd_state_offline()) {
324 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
325 domain->name ));
326 return;
327 }
328
329 /* If we're in statup mode, check again in 10 seconds, not in
330 lp_winbind_cache_time() seconds (which is 5 mins by default). */
331
332 calc_new_online_timeout_check(domain);
333
334 domain->check_online_event = event_add_timed(winbind_event_context(),
335 NULL,
336 timeval_current_ofs(domain->check_online_timeout,0),
337 "check_domain_online_handler",
338 check_domain_online_handler,
339 domain);
340
341 /* The above *has* to succeed for winbindd to work. */
342 if (!domain->check_online_event) {
343 smb_panic("set_domain_offline: failed to add online handler.\n");
344 }
345
346 DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
347 domain->name ));
348}
349
350/****************************************************************
351 Set domain online - if allowed.
352****************************************************************/
353
354static void set_domain_online(struct winbindd_domain *domain)
355{
356 struct timeval now;
357
358 DEBUG(10,("set_domain_online: called for domain %s\n",
359 domain->name ));
360
361 if (domain->internal) {
362 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
363 domain->name ));
364 return;
365 }
366
367 if (get_global_winbindd_state_offline()) {
368 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
369 domain->name ));
370 return;
371 }
372
373 /* If we are waiting to get a krb5 ticket, trigger immediately. */
374 GetTimeOfDay(&now);
375 set_event_dispatch_time(winbind_event_context(),
376 "krb5_ticket_gain_handler", now);
377
378 /* Ok, we're out of any startup mode now... */
379 domain->startup = False;
380
381 if (domain->online == False) {
382 /* We were offline - now we're online. We default to
383 using the MS-RPC backend if we started offline,
384 and if we're going online for the first time we
385 should really re-initialize the backends and the
386 checks to see if we're talking to an AD or NT domain.
387 */
388
389 domain->initialized = False;
390
391 /* 'reconnect_methods' is the MS-RPC backend. */
392 if (domain->backend == &reconnect_methods) {
393 domain->backend = NULL;
394 }
395 }
396
397 /* Ensure we have no online timeout checks. */
398 domain->check_online_timeout = 0;
399 TALLOC_FREE(domain->check_online_event);
400
401 /* Ensure we ignore any pending child messages. */
402 message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
403 message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
404
405 domain->online = True;
406}
407
408/****************************************************************
409 Requested to set a domain online.
410****************************************************************/
411
412void set_domain_online_request(struct winbindd_domain *domain)
413{
414 struct timeval tev;
415
416 DEBUG(10,("set_domain_online_request: called for domain %s\n",
417 domain->name ));
418
419 if (get_global_winbindd_state_offline()) {
420 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
421 domain->name ));
422 return;
423 }
424
425 /* We've been told it's safe to go online and
426 try and connect to a DC. But I don't believe it
427 because network manager seems to lie.
428 Wait at least 5 seconds. Heuristics suck... */
429
430 if (!domain->check_online_event) {
431 /* If we've come from being globally offline we
432 don't have a check online event handler set.
433 We need to add one now we're trying to go
434 back online. */
435
436 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
437 domain->name ));
438
439 domain->check_online_event = event_add_timed(winbind_event_context(),
440 NULL,
441 timeval_current_ofs(5, 0),
442 "check_domain_online_handler",
443 check_domain_online_handler,
444 domain);
445
446 /* The above *has* to succeed for winbindd to work. */
447 if (!domain->check_online_event) {
448 smb_panic("set_domain_online_request: failed to add online handler.\n");
449 }
450 }
451
452 GetTimeOfDay(&tev);
453
454 /* Go into "startup" mode again. */
455 domain->startup_time = tev.tv_sec;
456 domain->startup = True;
457
458 tev.tv_sec += 5;
459
460 set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
461}
462
463/****************************************************************
464 Add -ve connection cache entries for domain and realm.
465****************************************************************/
466
467void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
468 const char *server,
469 NTSTATUS result)
470{
471 add_failed_connection_entry(domain->name, server, result);
472 /* If this was the saf name for the last thing we talked to,
473 remove it. */
474 saf_delete(domain->name);
475 if (*domain->alt_name) {
476 add_failed_connection_entry(domain->alt_name, server, result);
477 saf_delete(domain->alt_name);
478 }
479}
480
481/* Choose between anonymous or authenticated connections. We need to use
482 an authenticated connection if DCs have the RestrictAnonymous registry
483 entry set > 0, or the "Additional restrictions for anonymous
484 connections" set in the win2k Local Security Policy.
485
486 Caller to free() result in domain, username, password
487*/
488
489static void cm_get_ipc_userpass(char **username, char **domain, char **password)
490{
491 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
492 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
493 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
494
495 if (*username && **username) {
496
497 if (!*domain || !**domain)
498 *domain = smb_xstrdup(lp_workgroup());
499
500 if (!*password || !**password)
501 *password = smb_xstrdup("");
502
503 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
504 *domain, *username));
505
506 } else {
507 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
508 *username = smb_xstrdup("");
509 *domain = smb_xstrdup("");
510 *password = smb_xstrdup("");
511 }
512}
513
514static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
515 fstring dcname, struct in_addr *dc_ip)
516{
517 struct winbindd_domain *our_domain = NULL;
518 struct rpc_pipe_client *netlogon_pipe = NULL;
519 NTSTATUS result;
520 WERROR werr;
521 TALLOC_CTX *mem_ctx;
522 unsigned int orig_timeout;
523 fstring tmp;
524 char *p;
525
526 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
527 * moment.... */
528
529 if (IS_DC) {
530 return False;
531 }
532
533 if (domain->primary) {
534 return False;
535 }
536
537 our_domain = find_our_domain();
538
539 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
540 return False;
541 }
542
543 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
544 if (!NT_STATUS_IS_OK(result)) {
545 talloc_destroy(mem_ctx);
546 return False;
547 }
548
549 /* This call can take a long time - allow the server to time out.
550 35 seconds should do it. */
551
552 orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
553
554 werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
555 domain->name, tmp);
556
557 /* And restore our original timeout. */
558 cli_set_timeout(netlogon_pipe->cli, orig_timeout);
559
560 talloc_destroy(mem_ctx);
561
562 if (!W_ERROR_IS_OK(werr)) {
563 DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
564 dos_errstr(werr)));
565 return False;
566 }
567
568 /* cli_netlogon_getanydcname gives us a name with \\ */
569 p = tmp;
570 if (*p == '\\') {
571 p+=1;
572 }
573 if (*p == '\\') {
574 p+=1;
575 }
576
577 fstrcpy(dcname, p);
578
579 DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
580
581 if (!resolve_name(dcname, dc_ip, 0x20)) {
582 return False;
583 }
584
585 return True;
586}
587
588/************************************************************************
589 Given a fd with a just-connected TCP connection to a DC, open a connection
590 to the pipe.
591************************************************************************/
592
593static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
594 const int sockfd,
595 const char *controller,
596 struct cli_state **cli,
597 BOOL *retry)
598{
599 char *machine_password, *machine_krb5_principal, *machine_account;
600 char *ipc_username, *ipc_domain, *ipc_password;
601
602 BOOL got_mutex;
603
604 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
605
606 struct sockaddr peeraddr;
607 socklen_t peeraddr_len;
608
609 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
610
611 DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
612 controller, domain->name ));
613
614 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
615 NULL);
616
617 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
618 SAFE_FREE(machine_password);
619 return NT_STATUS_NO_MEMORY;
620 }
621
622 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
623 lp_realm()) == -1) {
624 SAFE_FREE(machine_account);
625 SAFE_FREE(machine_password);
626 return NT_STATUS_NO_MEMORY;
627 }
628
629 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
630
631 *retry = True;
632
633 got_mutex = secrets_named_mutex(controller,
634 WINBIND_SERVER_MUTEX_WAIT_TIME);
635
636 if (!got_mutex) {
637 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
638 controller));
639 result = NT_STATUS_POSSIBLE_DEADLOCK;
640 goto done;
641 }
642
643 if ((*cli = cli_initialise()) == NULL) {
644 DEBUG(1, ("Could not cli_initialize\n"));
645 result = NT_STATUS_NO_MEMORY;
646 goto done;
647 }
648
649 (*cli)->timeout = 10000; /* 10 seconds */
650 (*cli)->fd = sockfd;
651 fstrcpy((*cli)->desthost, controller);
652 (*cli)->use_kerberos = True;
653
654 peeraddr_len = sizeof(peeraddr);
655
656 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
657 (peeraddr_len != sizeof(struct sockaddr_in)) ||
658 (peeraddr_in->sin_family != PF_INET))
659 {
660 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
661 result = NT_STATUS_UNSUCCESSFUL;
662 goto done;
663 }
664
665 if (ntohs(peeraddr_in->sin_port) == 139) {
666 struct nmb_name calling;
667 struct nmb_name called;
668
669 make_nmb_name(&calling, global_myname(), 0x0);
670 make_nmb_name(&called, "*SMBSERVER", 0x20);
671
672 if (!cli_session_request(*cli, &calling, &called)) {
673 DEBUG(8, ("cli_session_request failed for %s\n",
674 controller));
675 result = NT_STATUS_UNSUCCESSFUL;
676 goto done;
677 }
678 }
679
680 cli_setup_signing_state(*cli, Undefined);
681
682 if (!cli_negprot(*cli)) {
683 DEBUG(1, ("cli_negprot failed\n"));
684 result = NT_STATUS_UNSUCCESSFUL;
685 goto done;
686 }
687
688 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
689 ADS_STATUS ads_status;
690
691 if (lp_security() == SEC_ADS) {
692
693 /* Try a krb5 session */
694
695 (*cli)->use_kerberos = True;
696 DEBUG(5, ("connecting to %s from %s with kerberos principal "
697 "[%s]\n", controller, global_myname(),
698 machine_krb5_principal));
699
700 ads_status = cli_session_setup_spnego(*cli,
701 machine_krb5_principal,
702 machine_password,
703 lp_workgroup());
704
705 if (!ADS_ERR_OK(ads_status)) {
706 DEBUG(4,("failed kerberos session setup with %s\n",
707 ads_errstr(ads_status)));
708 }
709
710 result = ads_ntstatus(ads_status);
711 if (NT_STATUS_IS_OK(result)) {
712 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
713 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
714 goto session_setup_done;
715 }
716 }
717
718 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
719 (*cli)->use_kerberos = False;
720
721 DEBUG(5, ("connecting to %s from %s with username "
722 "[%s]\\[%s]\n", controller, global_myname(),
723 lp_workgroup(), machine_account));
724
725 ads_status = cli_session_setup_spnego(*cli,
726 machine_account,
727 machine_password,
728 lp_workgroup());
729 if (!ADS_ERR_OK(ads_status)) {
730 DEBUG(4, ("authenticated session setup failed with %s\n",
731 ads_errstr(ads_status)));
732 }
733
734 result = ads_ntstatus(ads_status);
735 if (NT_STATUS_IS_OK(result)) {
736 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
737 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
738 goto session_setup_done;
739 }
740 }
741
742 /* Fall back to non-kerberos session setup */
743
744 (*cli)->use_kerberos = False;
745
746 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
747 (strlen(ipc_username) > 0)) {
748
749 /* Only try authenticated if we have a username */
750
751 DEBUG(5, ("connecting to %s from %s with username "
752 "[%s]\\[%s]\n", controller, global_myname(),
753 ipc_domain, ipc_username));
754
755 if (NT_STATUS_IS_OK(cli_session_setup(
756 *cli, ipc_username,
757 ipc_password, strlen(ipc_password)+1,
758 ipc_password, strlen(ipc_password)+1,
759 ipc_domain))) {
760 /* Successful logon with given username. */
761 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
762 goto session_setup_done;
763 } else {
764 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
765 ipc_domain, ipc_username ));
766 }
767 }
768
769 /* Fall back to anonymous connection, this might fail later */
770
771 if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
772 NULL, 0, ""))) {
773 DEBUG(5, ("Connected anonymously\n"));
774 cli_init_creds(*cli, "", "", "");
775 goto session_setup_done;
776 }
777
778 result = cli_nt_error(*cli);
779
780 if (NT_STATUS_IS_OK(result))
781 result = NT_STATUS_UNSUCCESSFUL;
782
783 /* We can't session setup */
784
785 goto done;
786
787 session_setup_done:
788
789 /* cache the server name for later connections */
790
791 saf_store( domain->name, (*cli)->desthost );
792 if (domain->alt_name && (*cli)->use_kerberos) {
793 saf_store( domain->alt_name, (*cli)->desthost );
794 }
795
796 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
797
798 result = cli_nt_error(*cli);
799
800 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
801
802 if (NT_STATUS_IS_OK(result))
803 result = NT_STATUS_UNSUCCESSFUL;
804
805 goto done;
806 }
807
808 secrets_named_mutex_release(controller);
809 got_mutex = False;
810 *retry = False;
811
812 /* set the domain if empty; needed for schannel connections */
813 if ( !*(*cli)->domain ) {
814 fstrcpy( (*cli)->domain, domain->name );
815 }
816
817 result = NT_STATUS_OK;
818
819 done:
820 if (got_mutex) {
821 secrets_named_mutex_release(controller);
822 }
823
824 SAFE_FREE(machine_account);
825 SAFE_FREE(machine_password);
826 SAFE_FREE(machine_krb5_principal);
827 SAFE_FREE(ipc_username);
828 SAFE_FREE(ipc_domain);
829 SAFE_FREE(ipc_password);
830
831 if (!NT_STATUS_IS_OK(result)) {
832 winbind_add_failed_connection_entry(domain, controller, result);
833 if ((*cli) != NULL) {
834 cli_shutdown(*cli);
835 *cli = NULL;
836 }
837 }
838
839 return result;
840}
841
842static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
843 const char *dcname, struct in_addr ip,
844 struct dc_name_ip **dcs, int *num)
845{
846 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
847 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
848 return False;
849 }
850
851 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
852
853 if (*dcs == NULL)
854 return False;
855
856 fstrcpy((*dcs)[*num].name, dcname);
857 (*dcs)[*num].ip = ip;
858 *num += 1;
859 return True;
860}
861
862static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
863 struct in_addr ip, uint16 port,
864 struct sockaddr_in **addrs, int *num)
865{
866 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
867
868 if (*addrs == NULL) {
869 *num = 0;
870 return False;
871 }
872
873 (*addrs)[*num].sin_family = PF_INET;
874 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
875 (*addrs)[*num].sin_port = htons(port);
876
877 *num += 1;
878 return True;
879}
880
881static void mailslot_name(struct in_addr dc_ip, fstring name)
882{
883 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
884}
885
886static BOOL send_getdc_request(struct in_addr dc_ip,
887 const char *domain_name,
888 const DOM_SID *sid)
889{
890 pstring outbuf;
891 char *p;
892 fstring my_acct_name;
893 fstring my_mailslot;
894
895 mailslot_name(dc_ip, my_mailslot);
896
897 memset(outbuf, '\0', sizeof(outbuf));
898
899 p = outbuf;
900
901 SCVAL(p, 0, SAMLOGON);
902 p++;
903
904 SCVAL(p, 0, 0); /* Count pointer ... */
905 p++;
906
907 SIVAL(p, 0, 0); /* The sender's token ... */
908 p += 2;
909
910 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
911 fstr_sprintf(my_acct_name, "%s$", global_myname());
912 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
913
914 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
915 p += strlen(my_mailslot)+1;
916
917 SIVAL(p, 0, 0x80);
918 p+=4;
919
920 SIVAL(p, 0, sid_size(sid));
921 p+=4;
922
923 p = ALIGN4(p, outbuf);
924
925 sid_linearize(p, sid_size(sid), sid);
926 p += sid_size(sid);
927
928 SIVAL(p, 0, 1);
929 SSVAL(p, 4, 0xffff);
930 SSVAL(p, 6, 0xffff);
931 p+=8;
932
933 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
934 outbuf, PTR_DIFF(p, outbuf),
935 global_myname(), 0, domain_name, 0x1c,
936 dc_ip);
937}
938
939static BOOL receive_getdc_response(struct in_addr dc_ip,
940 const char *domain_name,
941 fstring dc_name)
942{
943 struct packet_struct *packet;
944 fstring my_mailslot;
945 char *buf, *p;
946 fstring dcname, user, domain;
947 int len;
948
949 mailslot_name(dc_ip, my_mailslot);
950
951 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
952
953 if (packet == NULL) {
954 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
955 return False;
956 }
957
958 DEBUG(5, ("Received packet for %s\n", my_mailslot));
959
960 buf = packet->packet.dgram.data;
961 len = packet->packet.dgram.datasize;
962
963 if (len < 70) {
964 /* 70 is a completely arbitrary value to make sure
965 the SVAL below does not read uninitialized memory */
966 DEBUG(3, ("GetDC got short response\n"));
967 return False;
968 }
969
970 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
971 p = buf+SVAL(buf, smb_vwv10);
972
973 if (CVAL(p,0) != SAMLOGON_R) {
974 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
975 return False;
976 }
977
978 p+=2;
979 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
980 STR_TERMINATE|STR_NOALIGN);
981 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
982 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
983 STR_TERMINATE|STR_NOALIGN);
984 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
985 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
986 STR_TERMINATE|STR_NOALIGN);
987 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
988
989 if (!strequal(domain, domain_name)) {
990 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
991 domain_name, domain));
992 return False;
993 }
994
995 p = dcname;
996 if (*p == '\\') p += 1;
997 if (*p == '\\') p += 1;
998
999 fstrcpy(dc_name, p);
1000
1001 DEBUG(10, ("GetDC gave name %s for domain %s\n",
1002 dc_name, domain));
1003
1004 return True;
1005}
1006
1007/*******************************************************************
1008 convert an ip to a name
1009*******************************************************************/
1010
1011static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
1012{
1013 struct ip_service ip_list;
1014
1015 ip_list.ip = ip;
1016 ip_list.port = 0;
1017
1018#ifdef WITH_ADS
1019 /* For active directory servers, try to get the ldap server name.
1020 None of these failures should be considered critical for now */
1021
1022 if (lp_security() == SEC_ADS) {
1023 ADS_STRUCT *ads;
1024
1025 ads = ads_init(domain->alt_name, domain->name, NULL);
1026 ads->auth.flags |= ADS_AUTH_NO_BIND;
1027
1028 if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
1029 /* We got a cldap packet. */
1030 fstrcpy(name, ads->config.ldap_server_name);
1031 namecache_store(name, 0x20, 1, &ip_list);
1032
1033 DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1034
1035 if (domain->primary && (ads->config.flags & ADS_KDC)) {
1036 if (ads_closest_dc(ads)) {
1037 char *sitename = sitename_fetch(ads->config.realm);
1038
1039 /* We're going to use this KDC for this realm/domain.
1040 If we are using sites, then force the krb5 libs
1041 to use this KDC. */
1042
1043 create_local_private_krb5_conf_for_domain(domain->alt_name,
1044 domain->name,
1045 sitename,
1046 ip);
1047
1048 SAFE_FREE(sitename);
1049 } else {
1050 /* use an off site KDC */
1051 create_local_private_krb5_conf_for_domain(domain->alt_name,
1052 domain->name,
1053 NULL,
1054 ip);
1055 }
1056 /* Ensure we contact this DC also. */
1057 saf_store( domain->name, name);
1058 saf_store( domain->alt_name, name);
1059 }
1060
1061 ads_destroy( &ads );
1062 return True;
1063 }
1064
1065 ads_destroy( &ads );
1066 }
1067#endif
1068
1069 /* try GETDC requests next */
1070
1071 if (send_getdc_request(ip, domain->name, &domain->sid)) {
1072 int i;
1073 smb_msleep(100);
1074 for (i=0; i<5; i++) {
1075 if (receive_getdc_response(ip, domain->name, name)) {
1076 namecache_store(name, 0x20, 1, &ip_list);
1077 return True;
1078 }
1079 smb_msleep(500);
1080 }
1081 }
1082
1083 /* try node status request */
1084
1085 if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
1086 namecache_store(name, 0x20, 1, &ip_list);
1087 return True;
1088 }
1089 return False;
1090}
1091
1092/*******************************************************************
1093 Retreive a list of IP address for domain controllers. Fill in
1094 the dcs[] with results.
1095*******************************************************************/
1096
1097static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
1098 struct dc_name_ip **dcs, int *num_dcs)
1099{
1100 fstring dcname;
1101 struct in_addr ip;
1102 struct ip_service *ip_list = NULL;
1103 int iplist_size = 0;
1104 int i;
1105 BOOL is_our_domain;
1106 enum security_types sec = (enum security_types)lp_security();
1107
1108 is_our_domain = strequal(domain->name, lp_workgroup());
1109
1110 if ( !is_our_domain
1111 && get_dc_name_via_netlogon(domain, dcname, &ip)
1112 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
1113 {
1114 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1115 dcname, inet_ntoa(ip)));
1116 return True;
1117 }
1118
1119 if (sec == SEC_ADS) {
1120 char *sitename = NULL;
1121
1122 /* We need to make sure we know the local site before
1123 doing any DNS queries, as this will restrict the
1124 get_sorted_dc_list() call below to only fetching
1125 DNS records for the correct site. */
1126
1127 /* Find any DC to get the site record.
1128 We deliberately don't care about the
1129 return here. */
1130
1131 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
1132
1133 sitename = sitename_fetch(domain->alt_name);
1134 if (sitename) {
1135
1136 /* Do the site-specific AD dns lookup first. */
1137 get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
1138
1139 for ( i=0; i<iplist_size; i++ ) {
1140 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1141 ip_list[i].ip, dcs, num_dcs);
1142 }
1143
1144 SAFE_FREE(ip_list);
1145 SAFE_FREE(sitename);
1146 iplist_size = 0;
1147 }
1148
1149 /* Now we add DCs from the main AD dns lookup. */
1150 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
1151
1152 for ( i=0; i<iplist_size; i++ ) {
1153 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1154 ip_list[i].ip, dcs, num_dcs);
1155 }
1156 }
1157
1158 /* try standard netbios queries if no ADS */
1159
1160 if (iplist_size==0) {
1161 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
1162 }
1163
1164 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
1165
1166 /* now add to the dc array. We'll wait until the last minute
1167 to look up the name of the DC. But we fill in the char* for
1168 the ip now in to make the failed connection cache work */
1169
1170 for ( i=0; i<iplist_size; i++ ) {
1171 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
1172 ip_list[i].ip, dcs, num_dcs);
1173 }
1174
1175 SAFE_FREE( ip_list );
1176
1177 return True;
1178}
1179
1180static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
1181 const struct winbindd_domain *domain,
1182 fstring dcname, struct sockaddr_in *addr, int *fd)
1183{
1184 struct dc_name_ip *dcs = NULL;
1185 int num_dcs = 0;
1186
1187 const char **dcnames = NULL;
1188 int num_dcnames = 0;
1189
1190 struct sockaddr_in *addrs = NULL;
1191 int num_addrs = 0;
1192
1193 int i, fd_index;
1194
1195 again:
1196 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1197 return False;
1198
1199 for (i=0; i<num_dcs; i++) {
1200
1201 if (!add_string_to_array(mem_ctx, dcs[i].name,
1202 &dcnames, &num_dcnames)) {
1203 return False;
1204 }
1205 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
1206 &addrs, &num_addrs)) {
1207 return False;
1208 }
1209
1210 if (!add_string_to_array(mem_ctx, dcs[i].name,
1211 &dcnames, &num_dcnames)) {
1212 return False;
1213 }
1214 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
1215 &addrs, &num_addrs)) {
1216 return False;
1217 }
1218 }
1219
1220 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1221 return False;
1222
1223 if ((addrs == NULL) || (dcnames == NULL))
1224 return False;
1225
1226 /* 5 second timeout. */
1227 if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
1228 {
1229 for (i=0; i<num_dcs; i++) {
1230 DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1231 "domain %s address %s. Error was %s\n",
1232 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
1233 winbind_add_failed_connection_entry(domain,
1234 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1235 }
1236 return False;
1237 }
1238
1239 *addr = addrs[fd_index];
1240
1241 if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1242 /* Ok, we've got a name for the DC */
1243 fstrcpy(dcname, dcnames[fd_index]);
1244 return True;
1245 }
1246
1247 /* Try to figure out the name */
1248 if (dcip_to_name( domain, addr->sin_addr, dcname )) {
1249 return True;
1250 }
1251
1252 /* We can not continue without the DC's name */
1253 winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1254 NT_STATUS_UNSUCCESSFUL);
1255 goto again;
1256}
1257
1258static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1259 struct winbindd_cm_conn *new_conn)
1260{
1261 TALLOC_CTX *mem_ctx;
1262 NTSTATUS result;
1263 char *saf_servername = saf_fetch( domain->name );
1264 int retries;
1265
1266 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1267 SAFE_FREE(saf_servername);
1268 set_domain_offline(domain);
1269 return NT_STATUS_NO_MEMORY;
1270 }
1271
1272 /* we have to check the server affinity cache here since
1273 later we selecte a DC based on response time and not preference */
1274
1275 /* Check the negative connection cache
1276 before talking to it. It going down may have
1277 triggered the reconnection. */
1278
1279 if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1280
1281 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1282 saf_servername, domain->name ));
1283
1284 /* convert an ip address to a name */
1285 if ( is_ipaddress( saf_servername ) ) {
1286 fstring saf_name;
1287 struct in_addr ip;
1288
1289 ip = *interpret_addr2( saf_servername );
1290 if (dcip_to_name( domain, ip, saf_name )) {
1291 fstrcpy( domain->dcname, saf_name );
1292 } else {
1293 winbind_add_failed_connection_entry(
1294 domain, saf_servername,
1295 NT_STATUS_UNSUCCESSFUL);
1296 }
1297 } else {
1298 fstrcpy( domain->dcname, saf_servername );
1299 }
1300
1301 SAFE_FREE( saf_servername );
1302 }
1303
1304 for (retries = 0; retries < 3; retries++) {
1305
1306 int fd = -1;
1307 BOOL retry = False;
1308
1309 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1310
1311 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1312 domain->dcname, domain->name ));
1313
1314 if (*domain->dcname
1315 && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1316 && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1317 {
1318 struct sockaddr_in *addrs = NULL;
1319 int num_addrs = 0;
1320 int dummy = 0;
1321
1322 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
1323 set_domain_offline(domain);
1324 talloc_destroy(mem_ctx);
1325 return NT_STATUS_NO_MEMORY;
1326 }
1327 if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
1328 set_domain_offline(domain);
1329 talloc_destroy(mem_ctx);
1330 return NT_STATUS_NO_MEMORY;
1331 }
1332
1333 /* 5 second timeout. */
1334 if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1335 fd = -1;
1336 }
1337 }
1338
1339 if ((fd == -1)
1340 && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1341 {
1342 /* This is the one place where we will
1343 set the global winbindd offline state
1344 to true, if a "WINBINDD_OFFLINE" entry
1345 is found in the winbindd cache. */
1346 set_global_winbindd_state_offline();
1347 break;
1348 }
1349
1350 new_conn->cli = NULL;
1351
1352 result = cm_prepare_connection(domain, fd, domain->dcname,
1353 &new_conn->cli, &retry);
1354
1355 if (!retry)
1356 break;
1357 }
1358
1359 if (NT_STATUS_IS_OK(result)) {
1360 if (domain->online == False) {
1361 /* We're changing state from offline to online. */
1362 set_global_winbindd_state_online();
1363 }
1364 set_domain_online(domain);
1365 } else {
1366 /* Ensure we setup the retry handler. */
1367 set_domain_offline(domain);
1368 }
1369
1370 talloc_destroy(mem_ctx);
1371 return result;
1372}
1373
1374/* Close down all open pipes on a connection. */
1375
1376void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1377{
1378 /* We're closing down a possibly dead
1379 connection. Don't have impossibly long (10s) timeouts. */
1380
1381 if (conn->cli) {
1382 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1383 }
1384
1385 if (conn->samr_pipe != NULL) {
1386 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1387 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1388 if (conn->cli) {
1389 cli_set_timeout(conn->cli, 500);
1390 }
1391 }
1392 conn->samr_pipe = NULL;
1393 }
1394
1395 if (conn->lsa_pipe != NULL) {
1396 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1397 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1398 if (conn->cli) {
1399 cli_set_timeout(conn->cli, 500);
1400 }
1401 }
1402 conn->lsa_pipe = NULL;
1403 }
1404
1405 if (conn->netlogon_pipe != NULL) {
1406 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1407 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1408 if (conn->cli) {
1409 cli_set_timeout(conn->cli, 500);
1410 }
1411 }
1412 conn->netlogon_pipe = NULL;
1413 }
1414
1415 if (conn->cli) {
1416 cli_shutdown(conn->cli);
1417 }
1418
1419 conn->cli = NULL;
1420}
1421
1422void close_conns_after_fork(void)
1423{
1424 struct winbindd_domain *domain;
1425
1426 for (domain = domain_list(); domain; domain = domain->next) {
1427 if (domain->conn.cli == NULL)
1428 continue;
1429
1430 if (domain->conn.cli->fd == -1)
1431 continue;
1432
1433 close(domain->conn.cli->fd);
1434 domain->conn.cli->fd = -1;
1435 }
1436}
1437
1438static BOOL connection_ok(struct winbindd_domain *domain)
1439{
1440 if (domain->conn.cli == NULL) {
1441 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1442 "cli!\n", domain->dcname, domain->name));
1443 return False;
1444 }
1445
1446 if (!domain->conn.cli->initialised) {
1447 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1448 "initialised!\n", domain->dcname, domain->name));
1449 return False;
1450 }
1451
1452 if (domain->conn.cli->fd == -1) {
1453 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1454 "never started (fd == -1)\n",
1455 domain->dcname, domain->name));
1456 return False;
1457 }
1458
1459 if (domain->online == False) {
1460 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1461 return False;
1462 }
1463
1464 return True;
1465}
1466
1467/* Initialize a new connection up to the RPC BIND.
1468 Bypass online status check so always does network calls. */
1469
1470static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1471{
1472 NTSTATUS result;
1473
1474 /* Internal connections never use the network. */
1475 if (domain->internal) {
1476 domain->initialized = True;
1477 return NT_STATUS_OK;
1478 }
1479
1480 if (connection_ok(domain)) {
1481 if (!domain->initialized) {
1482 set_dc_type_and_flags(domain);
1483 }
1484 return NT_STATUS_OK;
1485 }
1486
1487 invalidate_cm_connection(&domain->conn);
1488
1489 result = cm_open_connection(domain, &domain->conn);
1490
1491 if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1492 set_dc_type_and_flags(domain);
1493 }
1494
1495 return result;
1496}
1497
1498NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1499{
1500 if (domain->initialized && !domain->online) {
1501 /* We check for online status elsewhere. */
1502 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1503 }
1504
1505 return init_dc_connection_network(domain);
1506}
1507
1508/******************************************************************************
1509 We can 'sense' certain things about the DC by it's replies to certain
1510 questions.
1511
1512 This tells us if this particular remote server is Active Directory, and if it
1513 is native mode.
1514******************************************************************************/
1515
1516static void set_dc_type_and_flags( struct winbindd_domain *domain )
1517{
1518 NTSTATUS result;
1519 DS_DOMINFO_CTR ctr;
1520 TALLOC_CTX *mem_ctx = NULL;
1521 struct rpc_pipe_client *cli;
1522 POLICY_HND pol;
1523
1524 char *domain_name = NULL;
1525 char *dns_name = NULL;
1526 char *forest_name = NULL;
1527 DOM_SID *dom_sid = NULL;
1528
1529 ZERO_STRUCT( ctr );
1530
1531 if (!connection_ok(domain)) {
1532 return;
1533 }
1534
1535 DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1536
1537 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1538 &result);
1539
1540 if (cli == NULL) {
1541 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1542 "PI_LSARPC_DS on domain %s: (%s)\n",
1543 domain->name, nt_errstr(result)));
1544
1545 /* if this is just a non-AD domain we need to continue
1546 * identifying so that we can in the end return with
1547 * domain->initialized = True - gd */
1548
1549 goto no_lsarpc_ds;
1550 }
1551
1552 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1553 DsRolePrimaryDomainInfoBasic,
1554 &ctr);
1555 cli_rpc_pipe_close(cli);
1556
1557 if (!NT_STATUS_IS_OK(result)) {
1558 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1559 "on domain %s failed: (%s)\n",
1560 domain->name, nt_errstr(result)));
1561
1562 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1563 * every opcode on the LSARPC_DS pipe, continue with
1564 * no_lsarpc_ds mode here as well to get domain->initialized
1565 * set - gd */
1566
1567 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1568 goto no_lsarpc_ds;
1569 }
1570
1571 return;
1572 }
1573
1574 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1575 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1576 domain->native_mode = True;
1577 } else {
1578 domain->native_mode = False;
1579 }
1580
1581no_lsarpc_ds:
1582 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1583
1584 if (cli == NULL) {
1585 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1586 "PI_LSARPC on domain %s: (%s)\n",
1587 domain->name, nt_errstr(result)));
1588 cli_rpc_pipe_close(cli);
1589 return;
1590 }
1591
1592 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1593 domain->name);
1594 if (!mem_ctx) {
1595 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1596 cli_rpc_pipe_close(cli);
1597 return;
1598 }
1599
1600 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
1601 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1602
1603 if (NT_STATUS_IS_OK(result)) {
1604 /* This particular query is exactly what Win2k clients use
1605 to determine that the DC is active directory */
1606 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1607 12, &domain_name,
1608 &dns_name, &forest_name,
1609 NULL, &dom_sid);
1610 }
1611
1612 if (NT_STATUS_IS_OK(result)) {
1613 domain->active_directory = True;
1614
1615 if (domain_name)
1616 fstrcpy(domain->name, domain_name);
1617
1618 if (dns_name)
1619 fstrcpy(domain->alt_name, dns_name);
1620
1621 if ( forest_name )
1622 fstrcpy(domain->forest_name, forest_name);
1623
1624 if (dom_sid)
1625 sid_copy(&domain->sid, dom_sid);
1626 } else {
1627 domain->active_directory = False;
1628
1629 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
1630 SEC_RIGHTS_MAXIMUM_ALLOWED,
1631 &pol);
1632
1633 if (!NT_STATUS_IS_OK(result))
1634 goto done;
1635
1636 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
1637 &pol, 5, &domain_name,
1638 &dom_sid);
1639
1640 if (NT_STATUS_IS_OK(result)) {
1641 if (domain_name)
1642 fstrcpy(domain->name, domain_name);
1643
1644 if (dom_sid)
1645 sid_copy(&domain->sid, dom_sid);
1646 }
1647 }
1648done:
1649
1650 DEBUG(5, ("set_dc_type_and_flags: domain %s is %sin native mode.\n",
1651 domain->name, domain->native_mode ? "" : "NOT "));
1652
1653 DEBUG(5,("set_dc_type_and_flags: domain %s is %srunning active directory.\n",
1654 domain->name, domain->active_directory ? "" : "NOT "));
1655
1656 cli_rpc_pipe_close(cli);
1657
1658 talloc_destroy(mem_ctx);
1659
1660 domain->initialized = True;
1661}
1662
1663static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1664 struct dcinfo **ppdc)
1665{
1666 NTSTATUS result;
1667 struct rpc_pipe_client *netlogon_pipe;
1668
1669 if (lp_client_schannel() == False) {
1670 return False;
1671 }
1672
1673 result = cm_connect_netlogon(domain, &netlogon_pipe);
1674 if (!NT_STATUS_IS_OK(result)) {
1675 return False;
1676 }
1677
1678 /* Return a pointer to the struct dcinfo from the
1679 netlogon pipe. */
1680
1681 *ppdc = domain->conn.netlogon_pipe->dc;
1682 return True;
1683}
1684
1685NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1686 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1687{
1688 struct winbindd_cm_conn *conn;
1689 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1690 fstring conn_pwd;
1691 struct dcinfo *p_dcinfo;
1692
1693 result = init_dc_connection(domain);
1694 if (!NT_STATUS_IS_OK(result)) {
1695 return result;
1696 }
1697
1698 conn = &domain->conn;
1699
1700 if (conn->samr_pipe != NULL) {
1701 goto done;
1702 }
1703
1704 /*
1705 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1706 * sign and sealed pipe using the machine account password by
1707 * preference. If we can't - try schannel, if that fails, try
1708 * anonymous.
1709 */
1710
1711 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1712 if ((conn->cli->user_name[0] == '\0') ||
1713 (conn->cli->domain[0] == '\0') ||
1714 (conn_pwd[0] == '\0')) {
1715 DEBUG(10, ("cm_connect_sam: No no user available for "
1716 "domain %s, trying schannel\n", conn->cli->domain));
1717 goto schannel;
1718 }
1719
1720 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1721 authenticated SAMR pipe with sign & seal. */
1722 conn->samr_pipe =
1723 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1724 PIPE_AUTH_LEVEL_PRIVACY,
1725 conn->cli->domain,
1726 conn->cli->user_name,
1727 conn_pwd, &result);
1728
1729 if (conn->samr_pipe == NULL) {
1730 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1731 "pipe for domain %s using NTLMSSP "
1732 "authenticated pipe: user %s\\%s. Error was "
1733 "%s\n", domain->name, conn->cli->domain,
1734 conn->cli->user_name, nt_errstr(result)));
1735 goto schannel;
1736 }
1737
1738 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1739 "domain %s using NTLMSSP authenticated "
1740 "pipe: user %s\\%s\n", domain->name,
1741 conn->cli->domain, conn->cli->user_name ));
1742
1743 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1744 SEC_RIGHTS_MAXIMUM_ALLOWED,
1745 &conn->sam_connect_handle);
1746 if (NT_STATUS_IS_OK(result)) {
1747 goto open_domain;
1748 }
1749 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1750 "failed for domain %s, error was %s. Trying schannel\n",
1751 domain->name, nt_errstr(result) ));
1752 cli_rpc_pipe_close(conn->samr_pipe);
1753
1754 schannel:
1755
1756 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1757
1758 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1759 /* If this call fails - conn->cli can now be NULL ! */
1760 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1761 "for domain %s, trying anon\n", domain->name));
1762 goto anonymous;
1763 }
1764 conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1765 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1766 domain->name, p_dcinfo, &result);
1767
1768 if (conn->samr_pipe == NULL) {
1769 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1770 "domain %s using schannel. Error was %s\n",
1771 domain->name, nt_errstr(result) ));
1772 goto anonymous;
1773 }
1774 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1775 "schannel.\n", domain->name ));
1776
1777 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1778 SEC_RIGHTS_MAXIMUM_ALLOWED,
1779 &conn->sam_connect_handle);
1780 if (NT_STATUS_IS_OK(result)) {
1781 goto open_domain;
1782 }
1783 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1784 "for domain %s, error was %s. Trying anonymous\n",
1785 domain->name, nt_errstr(result) ));
1786 cli_rpc_pipe_close(conn->samr_pipe);
1787
1788 anonymous:
1789
1790 /* Finally fall back to anonymous. */
1791 conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1792 &result);
1793
1794 if (conn->samr_pipe == NULL) {
1795 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1796 goto done;
1797 }
1798
1799 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1800 SEC_RIGHTS_MAXIMUM_ALLOWED,
1801 &conn->sam_connect_handle);
1802 if (!NT_STATUS_IS_OK(result)) {
1803 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1804 "for domain %s Error was %s\n",
1805 domain->name, nt_errstr(result) ));
1806 goto done;
1807 }
1808
1809 open_domain:
1810 result = rpccli_samr_open_domain(conn->samr_pipe,
1811 mem_ctx,
1812 &conn->sam_connect_handle,
1813 SEC_RIGHTS_MAXIMUM_ALLOWED,
1814 &domain->sid,
1815 &conn->sam_domain_handle);
1816
1817 done:
1818
1819 if (!NT_STATUS_IS_OK(result)) {
1820 invalidate_cm_connection(conn);
1821 return result;
1822 }
1823
1824 *cli = conn->samr_pipe;
1825 *sam_handle = conn->sam_domain_handle;
1826 return result;
1827}
1828
1829NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1830 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1831{
1832 struct winbindd_cm_conn *conn;
1833 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1834 fstring conn_pwd;
1835 struct dcinfo *p_dcinfo;
1836
1837 result = init_dc_connection(domain);
1838 if (!NT_STATUS_IS_OK(result))
1839 return result;
1840
1841 conn = &domain->conn;
1842
1843 if (conn->lsa_pipe != NULL) {
1844 goto done;
1845 }
1846
1847 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1848 if ((conn->cli->user_name[0] == '\0') ||
1849 (conn->cli->domain[0] == '\0') ||
1850 (conn_pwd[0] == '\0')) {
1851 DEBUG(10, ("cm_connect_lsa: No no user available for "
1852 "domain %s, trying schannel\n", conn->cli->domain));
1853 goto schannel;
1854 }
1855
1856 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1857 * authenticated LSA pipe with sign & seal. */
1858 conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1859 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1860 conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1861
1862 if (conn->lsa_pipe == NULL) {
1863 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1864 "domain %s using NTLMSSP authenticated pipe: user "
1865 "%s\\%s. Error was %s. Trying schannel.\n",
1866 domain->name, conn->cli->domain,
1867 conn->cli->user_name, nt_errstr(result)));
1868 goto schannel;
1869 }
1870
1871 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1872 "NTLMSSP authenticated pipe: user %s\\%s\n",
1873 domain->name, conn->cli->domain, conn->cli->user_name ));
1874
1875 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1876 SEC_RIGHTS_MAXIMUM_ALLOWED,
1877 &conn->lsa_policy);
1878 if (NT_STATUS_IS_OK(result)) {
1879 goto done;
1880 }
1881
1882 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1883 "schannel\n"));
1884
1885 cli_rpc_pipe_close(conn->lsa_pipe);
1886
1887 schannel:
1888
1889 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1890
1891 if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1892 /* If this call fails - conn->cli can now be NULL ! */
1893 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1894 "for domain %s, trying anon\n", domain->name));
1895 goto anonymous;
1896 }
1897 conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1898 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1899 domain->name, p_dcinfo, &result);
1900
1901 if (conn->lsa_pipe == NULL) {
1902 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1903 "domain %s using schannel. Error was %s\n",
1904 domain->name, nt_errstr(result) ));
1905 goto anonymous;
1906 }
1907 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1908 "schannel.\n", domain->name ));
1909
1910 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1911 SEC_RIGHTS_MAXIMUM_ALLOWED,
1912 &conn->lsa_policy);
1913 if (NT_STATUS_IS_OK(result)) {
1914 goto done;
1915 }
1916
1917 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1918 "anonymous\n"));
1919
1920 cli_rpc_pipe_close(conn->lsa_pipe);
1921
1922 anonymous:
1923
1924 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1925 &result);
1926 if (conn->lsa_pipe == NULL) {
1927 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1928 goto done;
1929 }
1930
1931 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1932 SEC_RIGHTS_MAXIMUM_ALLOWED,
1933 &conn->lsa_policy);
1934 done:
1935 if (!NT_STATUS_IS_OK(result)) {
1936 invalidate_cm_connection(conn);
1937 return result;
1938 }
1939
1940 *cli = conn->lsa_pipe;
1941 *lsa_policy = conn->lsa_policy;
1942 return result;
1943}
1944
1945/****************************************************************************
1946 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1947 session key stored in conn->netlogon_pipe->dc->sess_key.
1948****************************************************************************/
1949
1950NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1951 struct rpc_pipe_client **cli)
1952{
1953 struct winbindd_cm_conn *conn;
1954 NTSTATUS result;
1955
1956 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1957 uint8 mach_pwd[16];
1958 uint32 sec_chan_type;
1959 const char *account_name;
1960 struct rpc_pipe_client *netlogon_pipe = NULL;
1961
1962 *cli = NULL;
1963
1964 result = init_dc_connection(domain);
1965 if (!NT_STATUS_IS_OK(result)) {
1966 return result;
1967 }
1968
1969 conn = &domain->conn;
1970
1971 if (conn->netlogon_pipe != NULL) {
1972 *cli = conn->netlogon_pipe;
1973 return NT_STATUS_OK;
1974 }
1975
1976 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1977 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1978 }
1979
1980 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1981 &result);
1982 if (netlogon_pipe == NULL) {
1983 return result;
1984 }
1985
1986 if (lp_client_schannel() != False) {
1987 neg_flags |= NETLOGON_NEG_SCHANNEL;
1988 }
1989
1990 /* if we are a DC and this is a trusted domain, then we need to use our
1991 domain name in the net_req_auth2() request */
1992
1993 if ( IS_DC
1994 && !strequal(domain->name, lp_workgroup())
1995 && lp_allow_trusted_domains() )
1996 {
1997 account_name = lp_workgroup();
1998 } else {
1999 account_name = domain->primary ?
2000 global_myname() : domain->name;
2001 }
2002
2003 if (account_name == NULL) {
2004 cli_rpc_pipe_close(netlogon_pipe);
2005 return NT_STATUS_NO_MEMORY;
2006 }
2007
2008 result = rpccli_netlogon_setup_creds(
2009 netlogon_pipe,
2010 domain->dcname, /* server name. */
2011 domain->name, /* domain name */
2012 global_myname(), /* client name */
2013 account_name, /* machine account */
2014 mach_pwd, /* machine password */
2015 sec_chan_type, /* from get_trust_pw */
2016 &neg_flags);
2017
2018 if (!NT_STATUS_IS_OK(result)) {
2019 cli_rpc_pipe_close(netlogon_pipe);
2020 return result;
2021 }
2022
2023 if ((lp_client_schannel() == True) &&
2024 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2025 DEBUG(3, ("Server did not offer schannel\n"));
2026 cli_rpc_pipe_close(netlogon_pipe);
2027 return NT_STATUS_ACCESS_DENIED;
2028 }
2029
2030 if ((lp_client_schannel() == False) ||
2031 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2032 /* We're done - just keep the existing connection to NETLOGON
2033 * open */
2034 conn->netlogon_pipe = netlogon_pipe;
2035 *cli = conn->netlogon_pipe;
2036 return NT_STATUS_OK;
2037 }
2038
2039 /* Using the credentials from the first pipe, open a signed and sealed
2040 second netlogon pipe. The session key is stored in the schannel
2041 part of the new pipe auth struct.
2042 */
2043
2044 conn->netlogon_pipe =
2045 cli_rpc_pipe_open_schannel_with_key(conn->cli,
2046 PI_NETLOGON,
2047 PIPE_AUTH_LEVEL_PRIVACY,
2048 domain->name,
2049 netlogon_pipe->dc,
2050 &result);
2051
2052 /* We can now close the initial netlogon pipe. */
2053 cli_rpc_pipe_close(netlogon_pipe);
2054
2055 if (conn->netlogon_pipe == NULL) {
2056 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2057 "was %s\n", nt_errstr(result)));
2058
2059 /* make sure we return something besides OK */
2060 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2061 }
2062
2063 *cli = conn->netlogon_pipe;
2064 return NT_STATUS_OK;
2065}
Note: See TracBrowser for help on using the repository browser.