source: vendor/3.5.2/source3/winbindd/winbindd_cm.c

Last change on this file was 427, checked in by Silvan Scherrer, 16 years ago

Samba 3.5.x: update to 3.5.2

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