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