source: branches/samba-3.2.x/source/winbindd/winbindd_cm.c

Last change on this file was 233, checked in by Herwig Bauernfeind, 16 years ago

Update 3.2 branch to 3.2.9

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