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