source: trunk/server/source3/winbindd/winbindd_cm.c

Last change on this file was 920, checked in by Silvan Scherrer, 9 years ago

Samba Server: apply latest security patches to trunk

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