libsmb: Give namequery.c its own header
[garming/samba-autobuild/.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         status = nbt_getdc(server_messaging_context(), 10, pss, domain->name,
1470                            &domain->sid, nt_version, mem_ctx, &nt_version,
1471                            &dc_name, NULL);
1472         if (NT_STATUS_IS_OK(status)) {
1473                 *name = talloc_strdup(mem_ctx, dc_name);
1474                 if (*name == NULL) {
1475                         return false;
1476                 }
1477                 namecache_store(*name, 0x20, 1, &ip_list);
1478                 return True;
1479         }
1480
1481         /* try node status request */
1482
1483         if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1484                 namecache_store(nbtname, 0x20, 1, &ip_list);
1485
1486                 if (name != NULL) {
1487                         *name = talloc_strdup(mem_ctx, nbtname);
1488                         if (*name == NULL) {
1489                                 return false;
1490                         }
1491                 }
1492
1493                 return true;
1494         }
1495         return False;
1496 }
1497
1498 /*******************************************************************
1499  Retrieve a list of IP addresses for domain controllers.
1500
1501  The array is sorted in the preferred connection order.
1502
1503  @param[in] mem_ctx talloc memory context to allocate from
1504  @param[in] domain domain to retrieve DCs for
1505  @param[out] dcs array of dcs that will be returned
1506  @param[out] num_dcs number of dcs returned in the dcs array
1507  @return always true
1508 *******************************************************************/
1509
1510 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1511                     struct dc_name_ip **dcs, int *num_dcs,
1512                     uint32_t request_flags)
1513 {
1514         fstring dcname;
1515         struct  sockaddr_storage ss;
1516         struct  ip_service *ip_list = NULL;
1517         int     iplist_size = 0;
1518         int     i;
1519         bool    is_our_domain;
1520         enum security_types sec = (enum security_types)lp_security();
1521
1522         is_our_domain = strequal(domain->name, lp_workgroup());
1523
1524         /* If not our domain, get the preferred DC, by asking our primary DC */
1525         if ( !is_our_domain
1526                 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1527                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1528                        num_dcs) )
1529         {
1530                 char addr[INET6_ADDRSTRLEN];
1531                 print_sockaddr(addr, sizeof(addr), &ss);
1532                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1533                            dcname, addr));
1534                 return True;
1535         }
1536
1537         if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1538                 char *sitename = NULL;
1539
1540                 /* We need to make sure we know the local site before
1541                    doing any DNS queries, as this will restrict the
1542                    get_sorted_dc_list() call below to only fetching
1543                    DNS records for the correct site. */
1544
1545                 /* Find any DC to get the site record.
1546                    We deliberately don't care about the
1547                    return here. */
1548
1549                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1550
1551                 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1552                 if (sitename) {
1553
1554                         /* Do the site-specific AD dns lookup first. */
1555                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1556                                &iplist_size, True);
1557
1558                         /* Add ips to the DC array.  We don't look up the name
1559                            of the DC in this function, but we fill in the char*
1560                            of the ip now to make the failed connection cache
1561                            work */
1562                         for ( i=0; i<iplist_size; i++ ) {
1563                                 char addr[INET6_ADDRSTRLEN];
1564                                 print_sockaddr(addr, sizeof(addr),
1565                                                 &ip_list[i].ss);
1566                                 add_one_dc_unique(mem_ctx,
1567                                                 domain->name,
1568                                                 addr,
1569                                                 &ip_list[i].ss,
1570                                                 dcs,
1571                                                 num_dcs);
1572                         }
1573
1574                         SAFE_FREE(ip_list);
1575                         TALLOC_FREE(sitename);
1576                         iplist_size = 0;
1577                 }
1578
1579                 /* Now we add DCs from the main AD DNS lookup. */
1580                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1581                         &iplist_size, True);
1582
1583                 for ( i=0; i<iplist_size; i++ ) {
1584                         char addr[INET6_ADDRSTRLEN];
1585                         print_sockaddr(addr, sizeof(addr),
1586                                         &ip_list[i].ss);
1587                         add_one_dc_unique(mem_ctx,
1588                                         domain->name,
1589                                         addr,
1590                                         &ip_list[i].ss,
1591                                         dcs,
1592                                         num_dcs);
1593                 }
1594
1595                 SAFE_FREE(ip_list);
1596                 iplist_size = 0;
1597         }
1598
1599         /* Try standard netbios queries if no ADS and fall back to DNS queries
1600          * if alt_name is available */
1601         if (*num_dcs == 0) {
1602                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1603                        false);
1604                 if (iplist_size == 0) {
1605                         if (domain->alt_name != NULL) {
1606                                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1607                                        &iplist_size, true);
1608                         }
1609                 }
1610
1611                 for ( i=0; i<iplist_size; i++ ) {
1612                         char addr[INET6_ADDRSTRLEN];
1613                         print_sockaddr(addr, sizeof(addr),
1614                                         &ip_list[i].ss);
1615                         add_one_dc_unique(mem_ctx,
1616                                         domain->name,
1617                                         addr,
1618                                         &ip_list[i].ss,
1619                                         dcs,
1620                                         num_dcs);
1621                 }
1622
1623                 SAFE_FREE(ip_list);
1624                 iplist_size = 0;
1625         }
1626
1627         return True;
1628 }
1629
1630 /*******************************************************************
1631  Find and make a connection to a DC in the given domain.
1632
1633  @param[in] mem_ctx talloc memory context to allocate from
1634  @param[in] domain domain to find a dc in
1635  @param[out] dcname NetBIOS or FQDN of DC that's connected to
1636  @param[out] pss DC Internet address and port
1637  @param[out] fd fd of the open socket connected to the newly found dc
1638  @return true when a DC connection is made, false otherwise
1639 *******************************************************************/
1640
1641 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1642                         struct winbindd_domain *domain,
1643                         char **dcname, struct sockaddr_storage *pss, int *fd,
1644                         uint32_t request_flags)
1645 {
1646         struct dc_name_ip *dcs = NULL;
1647         int num_dcs = 0;
1648
1649         const char **dcnames = NULL;
1650         size_t num_dcnames = 0;
1651
1652         struct sockaddr_storage *addrs = NULL;
1653         int num_addrs = 0;
1654
1655         int i;
1656         size_t fd_index;
1657
1658         NTSTATUS status;
1659
1660         *fd = -1;
1661
1662  again:
1663         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1664                 return False;
1665
1666         for (i=0; i<num_dcs; i++) {
1667
1668                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1669                                     &dcnames, &num_dcnames)) {
1670                         return False;
1671                 }
1672                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1673                                       &addrs, &num_addrs)) {
1674                         return False;
1675                 }
1676         }
1677
1678         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1679                 return False;
1680
1681         if ((addrs == NULL) || (dcnames == NULL))
1682                 return False;
1683
1684         status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1685                                      num_addrs, 0, 10, fd, &fd_index, NULL);
1686         if (!NT_STATUS_IS_OK(status)) {
1687                 for (i=0; i<num_dcs; i++) {
1688                         char ab[INET6_ADDRSTRLEN];
1689                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1690                         DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1691                                 "domain %s address %s. Error was %s\n",
1692                                    domain->name, ab, nt_errstr(status) ));
1693                         winbind_add_failed_connection_entry(domain,
1694                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1695                 }
1696                 return False;
1697         }
1698
1699         *pss = addrs[fd_index];
1700
1701         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1702                 /* Ok, we've got a name for the DC */
1703                 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1704                 if (*dcname == NULL) {
1705                         return false;
1706                 }
1707                 return true;
1708         }
1709
1710         /* Try to figure out the name */
1711         if (dcip_check_name(mem_ctx, domain, pss, dcname, request_flags)) {
1712                 return True;
1713         }
1714
1715         /* We can not continue without the DC's name */
1716         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1717                                     NT_STATUS_UNSUCCESSFUL);
1718
1719         /* Throw away all arrays as we're doing this again. */
1720         TALLOC_FREE(dcs);
1721         num_dcs = 0;
1722
1723         TALLOC_FREE(dcnames);
1724         num_dcnames = 0;
1725
1726         TALLOC_FREE(addrs);
1727         num_addrs = 0;
1728
1729         close(*fd);
1730         *fd = -1;
1731
1732         goto again;
1733 }
1734
1735 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1736 {
1737         return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1738                                           domain_name);
1739 }
1740
1741 static void store_current_dc_in_gencache(const char *domain_name,
1742                                          const char *dc_name,
1743                                          struct cli_state *cli)
1744 {
1745         char addr[INET6_ADDRSTRLEN];
1746         char *key = NULL;
1747         char *value = NULL;
1748
1749         if (!cli_state_is_connected(cli)) {
1750                 return;
1751         }
1752
1753         print_sockaddr(addr, sizeof(addr),
1754                        smbXcli_conn_remote_sockaddr(cli->conn));
1755
1756         key = current_dc_key(talloc_tos(), domain_name);
1757         if (key == NULL) {
1758                 goto done;
1759         }
1760
1761         value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1762         if (value == NULL) {
1763                 goto done;
1764         }
1765
1766         gencache_set(key, value, 0x7fffffff);
1767 done:
1768         TALLOC_FREE(value);
1769         TALLOC_FREE(key);
1770 }
1771
1772 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1773                                     const char *domain_name,
1774                                     char **p_dc_name, char **p_dc_ip)
1775 {
1776         char *key, *p;
1777         char *value = NULL;
1778         bool ret = false;
1779         char *dc_name = NULL;
1780         char *dc_ip = NULL;
1781
1782         key = current_dc_key(talloc_tos(), domain_name);
1783         if (key == NULL) {
1784                 goto done;
1785         }
1786         if (!gencache_get(key, mem_ctx, &value, NULL)) {
1787                 goto done;
1788         }
1789         p = strchr(value, ' ');
1790         if (p == NULL) {
1791                 goto done;
1792         }
1793         dc_ip = talloc_strndup(mem_ctx, value, p - value);
1794         if (dc_ip == NULL) {
1795                 goto done;
1796         }
1797         dc_name = talloc_strdup(mem_ctx, p+1);
1798         if (dc_name == NULL) {
1799                 goto done;
1800         }
1801
1802         if (p_dc_ip != NULL) {
1803                 *p_dc_ip = dc_ip;
1804                 dc_ip = NULL;
1805         }
1806         if (p_dc_name != NULL) {
1807                 *p_dc_name = dc_name;
1808                 dc_name = NULL;
1809         }
1810         ret = true;
1811 done:
1812         TALLOC_FREE(dc_name);
1813         TALLOC_FREE(dc_ip);
1814         TALLOC_FREE(key);
1815         TALLOC_FREE(value);
1816         return ret;
1817 }
1818
1819 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1820                                const struct ndr_interface_table *table,
1821                                struct rpc_pipe_client **ret_pipe)
1822 {
1823         struct rpc_pipe_client *cli = NULL;
1824         const struct auth_session_info *session_info;
1825         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1826
1827
1828         session_info = get_session_info_system();
1829         SMB_ASSERT(session_info != NULL);
1830
1831         /* create a connection to the specified pipe */
1832         if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1833                 status = rpc_pipe_open_interface(mem_ctx,
1834                                                  table,
1835                                                  session_info,
1836                                                  NULL,
1837                                                  NULL,
1838                                                  server_messaging_context(),
1839                                                  &cli);
1840         } else {
1841                 status = rpc_pipe_open_internal(mem_ctx,
1842                                                 table,
1843                                                 session_info,
1844                                                 NULL,
1845                                                 NULL,
1846                                                 server_messaging_context(),
1847                                                 &cli);
1848         }
1849         if (!NT_STATUS_IS_OK(status)) {
1850                 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1851                           table->name, nt_errstr(status)));
1852                 return status;
1853         }
1854
1855         if (ret_pipe) {
1856                 *ret_pipe = cli;
1857         }
1858
1859         return NT_STATUS_OK;
1860 }
1861
1862 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1863                                    struct winbindd_cm_conn *new_conn,
1864                                    bool need_rw_dc)
1865 {
1866         TALLOC_CTX *mem_ctx;
1867         NTSTATUS result;
1868         char *saf_servername;
1869         int retries;
1870         uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1871
1872         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1873                 set_domain_offline(domain);
1874                 return NT_STATUS_NO_MEMORY;
1875         }
1876
1877         saf_servername = saf_fetch(mem_ctx, domain->name );
1878
1879         /* we have to check the server affinity cache here since 
1880            later we select a DC based on response time and not preference */
1881
1882         /* Check the negative connection cache
1883            before talking to it. It going down may have
1884            triggered the reconnection. */
1885
1886         if (saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, saf_servername))) {
1887                 struct sockaddr_storage ss;
1888                 char *dcname = NULL;
1889                 bool resolved = true;
1890
1891                 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1892                            saf_servername, domain->name));
1893
1894                 /* convert an ip address to a name */
1895                 if (is_ipaddress(saf_servername)) {
1896                         if (!interpret_string_addr(&ss, saf_servername,
1897                                                    AI_NUMERICHOST)) {
1898                                 TALLOC_FREE(mem_ctx);
1899                                 return NT_STATUS_UNSUCCESSFUL;
1900                         }
1901                 } else {
1902                         if (!resolve_name(saf_servername, &ss, 0x20, true)) {
1903                                 resolved = false;
1904                         }
1905                 }
1906
1907                 if (resolved && dcip_check_name(mem_ctx, domain, &ss, &dcname, request_flags)) {
1908                         domain->dcname = talloc_strdup(domain,
1909                                                        dcname);
1910                         if (domain->dcname == NULL) {
1911                                 TALLOC_FREE(mem_ctx);
1912                                 return NT_STATUS_NO_MEMORY;
1913                         }
1914
1915                         domain->dcaddr = ss;
1916                 } else {
1917                         winbind_add_failed_connection_entry(domain, saf_servername,
1918                                                             NT_STATUS_UNSUCCESSFUL);
1919                 }
1920         }
1921
1922         for (retries = 0; retries < 3; retries++) {
1923                 int fd = -1;
1924                 bool retry = False;
1925                 char *dcname = NULL;
1926
1927                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1928
1929                 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1930                            domain->dcname ? domain->dcname : "", domain->name));
1931
1932                 if (domain->dcname != NULL &&
1933                     NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
1934                                                               domain->dcname)))
1935                 {
1936                         NTSTATUS status;
1937
1938                         status = smbsock_connect(&domain->dcaddr, 0,
1939                                                  NULL, -1, NULL, -1,
1940                                                  &fd, NULL, 10);
1941                         if (!NT_STATUS_IS_OK(status)) {
1942                                 fd = -1;
1943                         }
1944                 }
1945
1946                 if ((fd == -1) &&
1947                     !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd, request_flags))
1948                 {
1949                         /* This is the one place where we will
1950                            set the global winbindd offline state
1951                            to true, if a "WINBINDD_OFFLINE" entry
1952                            is found in the winbindd cache. */
1953                         set_global_winbindd_state_offline();
1954                         break;
1955                 }
1956                 if (dcname != NULL) {
1957                         talloc_free(domain->dcname);
1958
1959                         domain->dcname = talloc_move(domain, &dcname);
1960                         if (domain->dcname == NULL) {
1961                                 result = NT_STATUS_NO_MEMORY;
1962                                 break;
1963                         }
1964                 }
1965
1966                 new_conn->cli = NULL;
1967
1968                 result = cm_prepare_connection(domain, fd, domain->dcname,
1969                         &new_conn->cli, &retry);
1970                 if (!NT_STATUS_IS_OK(result)) {
1971                         /* Don't leak the smb connection socket */
1972                         close(fd);
1973                 }
1974
1975                 if (!retry)
1976                         break;
1977         }
1978
1979         if (NT_STATUS_IS_OK(result)) {
1980                 bool seal_pipes = true;
1981
1982                 winbindd_set_locator_kdc_envs(domain);
1983
1984                 if (domain->online == False) {
1985                         /* We're changing state from offline to online. */
1986                         set_global_winbindd_state_online();
1987                 }
1988                 set_domain_online(domain);
1989
1990                 /*
1991                  * Much as I hate global state, this seems to be the point
1992                  * where we can be certain that we have a proper connection to
1993                  * a DC. wbinfo --dc-info needs that information, store it in
1994                  * gencache with a looong timeout. This will need revisiting
1995                  * once we start to connect to multiple DCs, wbcDcInfo is
1996                  * already prepared for that.
1997                  */
1998                 store_current_dc_in_gencache(domain->name, domain->dcname,
1999                                              new_conn->cli);
2000
2001                 seal_pipes = lp_winbind_sealed_pipes();
2002                 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
2003                                           domain->name,
2004                                           seal_pipes);
2005
2006                 if (seal_pipes) {
2007                         new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2008                 } else {
2009                         new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
2010                 }
2011         } else {
2012                 /* Ensure we setup the retry handler. */
2013                 set_domain_offline(domain);
2014         }
2015
2016         talloc_destroy(mem_ctx);
2017         return result;
2018 }
2019
2020 /* Close down all open pipes on a connection. */
2021
2022 void invalidate_cm_connection(struct winbindd_domain *domain)
2023 {
2024         NTSTATUS result;
2025         struct winbindd_cm_conn *conn = &domain->conn;
2026
2027         /* We're closing down a possibly dead
2028            connection. Don't have impossibly long (10s) timeouts. */
2029
2030         if (conn->cli) {
2031                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
2032         }
2033
2034         if (conn->samr_pipe != NULL) {
2035                 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
2036                         dcerpc_samr_Close(conn->samr_pipe->binding_handle,
2037                                           talloc_tos(),
2038                                           &conn->sam_connect_handle,
2039                                           &result);
2040                 }
2041                 TALLOC_FREE(conn->samr_pipe);
2042                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2043                 if (conn->cli) {
2044                         cli_set_timeout(conn->cli, 500);
2045                 }
2046         }
2047
2048         if (conn->lsa_pipe != NULL) {
2049                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2050                         dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
2051                                          talloc_tos(),
2052                                          &conn->lsa_policy,
2053                                          &result);
2054                 }
2055                 TALLOC_FREE(conn->lsa_pipe);
2056                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2057                 if (conn->cli) {
2058                         cli_set_timeout(conn->cli, 500);
2059                 }
2060         }
2061
2062         if (conn->lsa_pipe_tcp != NULL) {
2063                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2064                         dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
2065                                          talloc_tos(),
2066                                          &conn->lsa_policy,
2067                                          &result);
2068                 }
2069                 TALLOC_FREE(conn->lsa_pipe_tcp);
2070                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2071                 if (conn->cli) {
2072                         cli_set_timeout(conn->cli, 500);
2073                 }
2074         }
2075
2076         if (conn->netlogon_pipe != NULL) {
2077                 TALLOC_FREE(conn->netlogon_pipe);
2078                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2079                 if (conn->cli) {
2080                         cli_set_timeout(conn->cli, 500);
2081                 }
2082         }
2083
2084         conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2085         TALLOC_FREE(conn->netlogon_creds_ctx);
2086
2087         if (conn->cli) {
2088                 cli_shutdown(conn->cli);
2089         }
2090
2091         conn->cli = NULL;
2092 }
2093
2094 void close_conns_after_fork(void)
2095 {
2096         struct winbindd_domain *domain;
2097         struct winbindd_cli_state *cli_state;
2098
2099         for (domain = domain_list(); domain; domain = domain->next) {
2100                 /*
2101                  * first close the low level SMB TCP connection
2102                  * so that we don't generate any SMBclose
2103                  * requests in invalidate_cm_connection()
2104                  */
2105                 if (cli_state_is_connected(domain->conn.cli)) {
2106                         smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2107                 }
2108
2109                 invalidate_cm_connection(domain);
2110         }
2111
2112         for (cli_state = winbindd_client_list();
2113              cli_state != NULL;
2114              cli_state = cli_state->next) {
2115                 if (cli_state->sock >= 0) {
2116                         close(cli_state->sock);
2117                         cli_state->sock = -1;
2118                 }
2119         }
2120 }
2121
2122 static bool connection_ok(struct winbindd_domain *domain)
2123 {
2124         bool ok;
2125
2126         ok = cli_state_is_connected(domain->conn.cli);
2127         if (!ok) {
2128                 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
2129                           domain->dcname, domain->name));
2130                 return False;
2131         }
2132
2133         if (domain->online == False) {
2134                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
2135                 return False;
2136         }
2137
2138         return True;
2139 }
2140
2141 /* Initialize a new connection up to the RPC BIND.
2142    Bypass online status check so always does network calls. */
2143
2144 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
2145 {
2146         NTSTATUS result;
2147         bool skip_connection = domain->internal;
2148         if (need_rw_dc && domain->rodc) {
2149                 skip_connection = false;
2150         }
2151
2152         /* Internal connections never use the network. */
2153         if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2154                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2155         }
2156
2157         /* Still ask the internal LSA and SAMR server about the local domain */
2158         if (skip_connection || connection_ok(domain)) {
2159                 if (!domain->initialized) {
2160                         set_dc_type_and_flags(domain);
2161                 }
2162                 return NT_STATUS_OK;
2163         }
2164
2165         invalidate_cm_connection(domain);
2166
2167         if (!domain->primary && !domain->initialized) {
2168                 /*
2169                  * Before we connect to a trust, work out if it is an
2170                  * AD domain by asking our own domain.
2171                  */
2172                 set_dc_type_and_flags_trustinfo(domain);
2173         }
2174
2175         result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2176
2177         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2178                 set_dc_type_and_flags(domain);
2179         }
2180
2181         return result;
2182 }
2183
2184 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2185 {
2186         if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2187                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2188         }
2189
2190         if (domain->initialized && !domain->online) {
2191                 /* We check for online status elsewhere. */
2192                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2193         }
2194
2195         return init_dc_connection_network(domain, need_rw_dc);
2196 }
2197
2198 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2199 {
2200         NTSTATUS status;
2201
2202         status = init_dc_connection(domain, need_rw_dc);
2203         if (!NT_STATUS_IS_OK(status)) {
2204                 return status;
2205         }
2206
2207         if (!domain->internal && domain->conn.cli == NULL) {
2208                 /* happens for trusted domains without inbound trust */
2209                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2210         }
2211
2212         return NT_STATUS_OK;
2213 }
2214
2215 /******************************************************************************
2216  Set the trust flags (direction and forest location) for a domain
2217 ******************************************************************************/
2218
2219 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2220 {
2221         struct winbindd_domain *our_domain;
2222         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2223         WERROR werr;
2224         struct netr_DomainTrustList trusts;
2225         int i;
2226         uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2227                         NETR_TRUST_FLAG_OUTBOUND |
2228                         NETR_TRUST_FLAG_INBOUND);
2229         struct rpc_pipe_client *cli;
2230         TALLOC_CTX *mem_ctx = NULL;
2231         struct dcerpc_binding_handle *b;
2232
2233         if (IS_DC) {
2234                 /*
2235                  * On a DC we loaded all trusts
2236                  * from configuration and never learn
2237                  * new domains.
2238                  */
2239                 return true;
2240         }
2241
2242         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2243
2244         /* Our primary domain doesn't need to worry about trust flags.
2245            Force it to go through the network setup */
2246         if ( domain->primary ) {                
2247                 return False;           
2248         }
2249
2250         mem_ctx = talloc_stackframe();
2251         our_domain = find_our_domain();
2252         if (our_domain->internal) {
2253                 result = init_dc_connection(our_domain, false);
2254                 if (!NT_STATUS_IS_OK(result)) {
2255                         DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2256                                  "Not able to make a connection to our domain: %s\n",
2257                                   nt_errstr(result)));
2258                         TALLOC_FREE(mem_ctx);
2259                         return false;
2260                 }
2261         }
2262
2263         /* This won't work unless our domain is AD */
2264         if ( !our_domain->active_directory ) {
2265                 TALLOC_FREE(mem_ctx);
2266                 return False;
2267         }
2268
2269         if (our_domain->internal) {
2270                 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2271         } else if (!connection_ok(our_domain)) {
2272                 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2273                          "No connection to our domain!\n"));
2274                 TALLOC_FREE(mem_ctx);
2275                 return False;
2276         } else {
2277                 result = cm_connect_netlogon(our_domain, &cli);
2278         }
2279
2280         if (!NT_STATUS_IS_OK(result)) {
2281                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2282                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
2283                           domain->name, nt_errstr(result)));
2284                 TALLOC_FREE(mem_ctx);
2285                 return False;
2286         }
2287         b = cli->binding_handle;
2288
2289         /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2290         result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2291                                                       cli->desthost,
2292                                                       flags,
2293                                                       &trusts,
2294                                                       &werr);
2295         if (!NT_STATUS_IS_OK(result)) {
2296                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2297                         "failed to query trusted domain list: %s\n",
2298                         nt_errstr(result)));
2299                 TALLOC_FREE(mem_ctx);
2300                 return false;
2301         }
2302         if (!W_ERROR_IS_OK(werr)) {
2303                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2304                         "failed to query trusted domain list: %s\n",
2305                         win_errstr(werr)));
2306                 TALLOC_FREE(mem_ctx);
2307                 return false;
2308         }
2309
2310         /* Now find the domain name and get the flags */
2311
2312         for ( i=0; i<trusts.count; i++ ) {
2313                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2314                         domain->domain_flags          = trusts.array[i].trust_flags;
2315                         domain->domain_type           = trusts.array[i].trust_type;
2316                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
2317
2318                         if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2319                                 domain->active_directory = True;
2320
2321                         /* This flag is only set if the domain is *our* 
2322                            primary domain and the primary domain is in
2323                            native mode */
2324
2325                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2326
2327                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2328                                   "native mode.\n", domain->name, 
2329                                   domain->native_mode ? "" : "NOT "));
2330
2331                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2332                                  "running active directory.\n", domain->name, 
2333                                  domain->active_directory ? "" : "NOT "));
2334
2335                         domain->can_do_ncacn_ip_tcp = domain->active_directory;
2336
2337                         domain->initialized = True;
2338
2339                         break;
2340                 }               
2341         }
2342
2343         TALLOC_FREE(mem_ctx);
2344
2345         return domain->initialized;     
2346 }
2347
2348 /******************************************************************************
2349  We can 'sense' certain things about the DC by it's replies to certain
2350  questions.
2351
2352  This tells us if this particular remote server is Active Directory, and if it
2353  is native mode.
2354 ******************************************************************************/
2355
2356 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2357 {
2358         NTSTATUS status, result;
2359         WERROR werr;
2360         TALLOC_CTX              *mem_ctx = NULL;
2361         struct rpc_pipe_client  *cli = NULL;
2362         struct policy_handle pol;
2363         union dssetup_DsRoleInfo info;
2364         union lsa_PolicyInformation *lsa_info = NULL;
2365
2366         if (!domain->internal && !connection_ok(domain)) {
2367                 return;
2368         }
2369
2370         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2371                               domain->name);
2372         if (!mem_ctx) {
2373                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2374                 return;
2375         }
2376
2377         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2378
2379         if (domain->internal) {
2380                 status = wb_open_internal_pipe(mem_ctx,
2381                                                &ndr_table_dssetup,
2382                                                &cli);
2383         } else {
2384                 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2385                                                   &ndr_table_dssetup,
2386                                                   &cli);
2387         }
2388
2389         if (!NT_STATUS_IS_OK(status)) {
2390                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2391                           "PI_DSSETUP on domain %s: (%s)\n",
2392                           domain->name, nt_errstr(status)));
2393
2394                 /* if this is just a non-AD domain we need to continue
2395                  * identifying so that we can in the end return with
2396                  * domain->initialized = True - gd */
2397
2398                 goto no_dssetup;
2399         }
2400
2401         status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2402                                                                   DS_ROLE_BASIC_INFORMATION,
2403                                                                   &info,
2404                                                                   &werr);
2405         TALLOC_FREE(cli);
2406
2407         if (NT_STATUS_IS_OK(status)) {
2408                 result = werror_to_ntstatus(werr);
2409         }
2410         if (!NT_STATUS_IS_OK(status)) {
2411                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2412                           "on domain %s failed: (%s)\n",
2413                           domain->name, nt_errstr(status)));
2414
2415                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2416                  * every opcode on the DSSETUP pipe, continue with
2417                  * no_dssetup mode here as well to get domain->initialized
2418                  * set - gd */
2419
2420                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2421                         goto no_dssetup;
2422                 }
2423
2424                 TALLOC_FREE(mem_ctx);
2425                 return;
2426         }
2427
2428         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2429             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2430                 domain->native_mode = True;
2431         } else {
2432                 domain->native_mode = False;
2433         }
2434
2435 no_dssetup:
2436         if (domain->internal) {
2437                 status = wb_open_internal_pipe(mem_ctx,
2438                                                &ndr_table_lsarpc,
2439                                                &cli);
2440         } else {
2441                 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2442                                                   &ndr_table_lsarpc, &cli);
2443         }
2444         if (!NT_STATUS_IS_OK(status)) {
2445                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2446                           "PI_LSARPC on domain %s: (%s)\n",
2447                           domain->name, nt_errstr(status)));
2448                 TALLOC_FREE(cli);
2449                 TALLOC_FREE(mem_ctx);
2450                 return;
2451         }
2452
2453         status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2454                                          SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2455
2456         if (NT_STATUS_IS_OK(status)) {
2457                 /* This particular query is exactly what Win2k clients use 
2458                    to determine that the DC is active directory */
2459                 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2460                                                      &pol,
2461                                                      LSA_POLICY_INFO_DNS,
2462                                                      &lsa_info,
2463                                                      &result);
2464         }
2465
2466         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2467                 domain->active_directory = True;
2468
2469                 if (lsa_info->dns.name.string) {
2470                         if (!strequal(domain->name, lsa_info->dns.name.string))
2471                         {
2472                                 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2473                                           "for domain %s claimed it was a DC "
2474                                           "for domain %s, refusing to "
2475                                           "initialize\n",
2476                                           domain->name,
2477                                           lsa_info->dns.name.string));
2478                                 TALLOC_FREE(cli);
2479                                 TALLOC_FREE(mem_ctx);
2480                                 return;
2481                         }
2482                         talloc_free(domain->name);
2483                         domain->name = talloc_strdup(domain,
2484                                                      lsa_info->dns.name.string);
2485                         if (domain->name == NULL) {
2486                                 goto done;
2487                         }
2488                 }
2489
2490                 if (lsa_info->dns.dns_domain.string) {
2491                         if (domain->alt_name != NULL &&
2492                             !strequal(domain->alt_name,
2493                                       lsa_info->dns.dns_domain.string))
2494                         {
2495                                 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2496                                           "for domain %s (%s) claimed it was "
2497                                           "a DC for domain %s, refusing to "
2498                                           "initialize\n",
2499                                           domain->alt_name, domain->name,
2500                                           lsa_info->dns.dns_domain.string));
2501                                 TALLOC_FREE(cli);
2502                                 TALLOC_FREE(mem_ctx);
2503                                 return;
2504                         }
2505                         talloc_free(domain->alt_name);
2506                         domain->alt_name =
2507                                 talloc_strdup(domain,
2508                                               lsa_info->dns.dns_domain.string);
2509                         if (domain->alt_name == NULL) {
2510                                 goto done;
2511                         }
2512                 }
2513
2514                 /* See if we can set some domain trust flags about
2515                    ourself */
2516
2517                 if (lsa_info->dns.dns_forest.string) {
2518                         talloc_free(domain->forest_name);
2519                         domain->forest_name =
2520                                 talloc_strdup(domain,
2521                                               lsa_info->dns.dns_forest.string);
2522                         if (domain->forest_name == NULL) {
2523                                 goto done;
2524                         }
2525
2526                         if (strequal(domain->forest_name, domain->alt_name)) {
2527                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2528                         }
2529                 }
2530
2531                 if (lsa_info->dns.sid) {
2532                         if (!is_null_sid(&domain->sid) &&
2533                             !dom_sid_equal(&domain->sid,
2534                                            lsa_info->dns.sid))
2535                         {
2536                                 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2537                                           "for domain %s (%s) claimed it was "
2538                                           "a DC for domain %s, refusing to "
2539                                           "initialize\n",
2540                                           dom_sid_string(talloc_tos(),
2541                                                          &domain->sid),
2542                                           domain->name,
2543                                           dom_sid_string(talloc_tos(),
2544                                                          lsa_info->dns.sid)));
2545                                 TALLOC_FREE(cli);
2546                                 TALLOC_FREE(mem_ctx);
2547                                 return;
2548                         }
2549                         sid_copy(&domain->sid, lsa_info->dns.sid);
2550                 }
2551         } else {
2552                 domain->active_directory = False;
2553
2554                 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2555                                                 SEC_FLAG_MAXIMUM_ALLOWED,
2556                                                 &pol);
2557
2558                 if (!NT_STATUS_IS_OK(status)) {
2559                         goto done;
2560                 }
2561
2562                 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2563                                                     &pol,
2564                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2565                                                     &lsa_info,
2566                                                     &result);
2567                 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2568
2569                         if (lsa_info->account_domain.name.string) {
2570                                 if (!strequal(domain->name,
2571                                         lsa_info->account_domain.name.string))
2572                                 {
2573                                         DEBUG(1,
2574                                               ("set_dc_type_and_flags_connect: "
2575                                                "DC for domain %s claimed it was"
2576                                                " a DC for domain %s, refusing "
2577                                                "to initialize\n", domain->name,
2578                                                lsa_info->
2579                                                 account_domain.name.string));
2580                                         TALLOC_FREE(cli);
2581                                         TALLOC_FREE(mem_ctx);
2582                                         return;
2583                                 }
2584                                 talloc_free(domain->name);
2585                                 domain->name =
2586                                         talloc_strdup(domain,
2587                                                       lsa_info->account_domain.name.string);
2588                         }
2589
2590                         if (lsa_info->account_domain.sid) {
2591                                 if (!is_null_sid(&domain->sid) &&
2592                                     !dom_sid_equal(&domain->sid,
2593                                                 lsa_info->account_domain.sid))
2594                                 {
2595                                         DEBUG(1,
2596                                               ("set_dc_type_and_flags_connect: "
2597                                                "DC for domain %s (%s) claimed "
2598                                                "it was a DC for domain %s, "
2599                                                "refusing to initialize\n",
2600                                                dom_sid_string(talloc_tos(),
2601                                                               &domain->sid),
2602                                                domain->name,
2603                                                dom_sid_string(talloc_tos(),
2604                                                 lsa_info->account_domain.sid)));
2605                                         TALLOC_FREE(cli);
2606                                         TALLOC_FREE(mem_ctx);
2607                                         return;
2608                                 }
2609                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2610                         }
2611                 }
2612         }
2613 done:
2614
2615         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2616                   domain->name, domain->native_mode ? "" : "NOT "));
2617
2618         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2619                   domain->name, domain->active_directory ? "" : "NOT "));
2620
2621         domain->can_do_ncacn_ip_tcp = domain->active_directory;
2622
2623         TALLOC_FREE(cli);
2624
2625         TALLOC_FREE(mem_ctx);
2626
2627         domain->initialized = True;
2628 }
2629
2630 /**********************************************************************
2631  Set the domain_flags (trust attributes, domain operating modes, etc... 
2632 ***********************************************************************/
2633
2634 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2635 {
2636         if (IS_DC) {
2637                 /*
2638                  * On a DC we loaded all trusts
2639                  * from configuration and never learn
2640                  * new domains.
2641                  */
2642                 return;
2643         }
2644
2645         /* we always have to contact our primary domain */
2646
2647         if ( domain->primary || domain->internal) {
2648                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2649                           "primary or internal domain\n"));
2650                 set_dc_type_and_flags_connect( domain );
2651                 return;         
2652         }
2653
2654         /* Use our DC to get the information if possible */
2655
2656         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2657                 /* Otherwise, fallback to contacting the 
2658                    domain directly */
2659                 set_dc_type_and_flags_connect( domain );
2660         }
2661
2662         return;
2663 }
2664
2665
2666
2667 /**********************************************************************
2668 ***********************************************************************/
2669
2670 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2671                                    struct netlogon_creds_cli_context **ppdc)
2672 {
2673         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2674         struct rpc_pipe_client *netlogon_pipe;
2675
2676         *ppdc = NULL;
2677
2678         if ((!IS_DC) && (!domain->primary)) {
2679                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2680         }
2681
2682         if (domain->conn.netlogon_creds_ctx != NULL) {
2683                 *ppdc = domain->conn.netlogon_creds_ctx;
2684                 return NT_STATUS_OK;
2685         }
2686
2687         result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2688         if (!NT_STATUS_IS_OK(result)) {
2689                 return result;
2690         }
2691
2692         return NT_STATUS_OK;
2693 }
2694
2695 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2696                         bool need_rw_dc,
2697                         struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2698 {
2699         struct winbindd_cm_conn *conn;
2700         NTSTATUS status, result;
2701         struct netlogon_creds_cli_context *p_creds;
2702         struct cli_credentials *creds = NULL;
2703         bool retry = false; /* allow one retry attempt for expired session */
2704
2705         if (sid_check_is_our_sam(&domain->sid)) {
2706                 if (domain->rodc == false || need_rw_dc == false) {
2707                         return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2708                 }
2709         }
2710
2711         if (IS_AD_DC) {
2712                 /*
2713                  * In theory we should not use SAMR within
2714                  * winbindd at all, but that's a larger task to
2715                  * remove this and avoid breaking existing
2716                  * setups.
2717                  *
2718                  * At least as AD DC we have the restriction
2719                  * to avoid SAMR against trusted domains,
2720                  * as there're no existing setups.
2721                  */
2722                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
2723         }
2724
2725 retry:
2726         status = init_dc_connection_rpc(domain, need_rw_dc);
2727         if (!NT_STATUS_IS_OK(status)) {
2728                 return status;
2729         }
2730
2731         conn = &domain->conn;
2732
2733         if (rpccli_is_connected(conn->samr_pipe)) {
2734                 goto done;
2735         }
2736
2737         TALLOC_FREE(conn->samr_pipe);
2738
2739         /*
2740          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2741          * sign and sealed pipe using the machine account password by
2742          * preference. If we can't - try schannel, if that fails, try
2743          * anonymous.
2744          */
2745
2746         result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2747         if (!NT_STATUS_IS_OK(result)) {
2748                 DEBUG(10, ("cm_connect_sam: No user available for "
2749                            "domain %s, trying schannel\n", domain->name));
2750                 goto schannel;
2751         }
2752
2753         if (cli_credentials_is_anonymous(creds)) {
2754                 goto anonymous;
2755         }
2756
2757         /*
2758          * We have an authenticated connection. Use a SPNEGO
2759          * authenticated SAMR pipe with sign & seal.
2760          */
2761         status = cli_rpc_pipe_open_with_creds(conn->cli,
2762                                               &ndr_table_samr,
2763                                               NCACN_NP,
2764                                               DCERPC_AUTH_TYPE_SPNEGO,
2765                                               conn->auth_level,
2766                                               smbXcli_conn_remote_name(conn->cli->conn),
2767                                               creds,
2768                                               &conn->samr_pipe);
2769
2770         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2771             && !retry) {
2772                 invalidate_cm_connection(domain);
2773                 retry = true;
2774                 goto retry;
2775         }
2776
2777         if (!NT_STATUS_IS_OK(status)) {
2778                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2779                           "pipe for domain %s using NTLMSSP "
2780                           "authenticated pipe: user %s. Error was "
2781                           "%s\n", domain->name,
2782                           cli_credentials_get_unparsed_name(creds, talloc_tos()),
2783                           nt_errstr(status)));
2784                 goto schannel;
2785         }
2786
2787         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2788                   "domain %s using NTLMSSP authenticated "
2789                   "pipe: user %s\n", domain->name,
2790                   cli_credentials_get_unparsed_name(creds, talloc_tos())));
2791
2792         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2793                                       conn->samr_pipe->desthost,
2794                                       SEC_FLAG_MAXIMUM_ALLOWED,
2795                                       &conn->sam_connect_handle,
2796                                       &result);
2797
2798         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2799                 invalidate_cm_connection(domain);
2800                 TALLOC_FREE(conn->samr_pipe);
2801                 retry = true;
2802                 goto retry;
2803         }
2804
2805         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2806                 goto open_domain;
2807         }
2808         if (NT_STATUS_IS_OK(status)) {
2809                 status = result;
2810         }
2811
2812         DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2813                   "failed for domain %s, error was %s. Trying schannel\n",
2814                   domain->name, nt_errstr(status) ));
2815         TALLOC_FREE(conn->samr_pipe);
2816
2817  schannel:
2818
2819         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2820
2821         status = cm_get_schannel_creds(domain, &p_creds);
2822         if (!NT_STATUS_IS_OK(status)) {
2823                 /* If this call fails - conn->cli can now be NULL ! */
2824                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2825                            "for domain %s (error %s), trying anon\n",
2826                         domain->name,
2827                         nt_errstr(status) ));
2828                 goto anonymous;
2829         }
2830         TALLOC_FREE(creds);
2831         status = cli_rpc_pipe_open_schannel_with_creds(
2832                 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2833                 &conn->samr_pipe);
2834
2835         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2836             && !retry) {
2837                 invalidate_cm_connection(domain);
2838                 retry = true;
2839                 goto retry;
2840         }
2841
2842         if (!NT_STATUS_IS_OK(status)) {
2843                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2844                           "domain %s using schannel. Error was %s\n",
2845                           domain->name, nt_errstr(status) ));
2846                 goto anonymous;
2847         }
2848         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2849                   "schannel.\n", domain->name ));
2850
2851         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2852                                       conn->samr_pipe->desthost,
2853                                       SEC_FLAG_MAXIMUM_ALLOWED,
2854                                       &conn->sam_connect_handle,
2855                                       &result);
2856
2857         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2858                 invalidate_cm_connection(domain);
2859                 TALLOC_FREE(conn->samr_pipe);
2860                 retry = true;
2861                 goto retry;
2862         }
2863
2864         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2865                 goto open_domain;
2866         }
2867         if (NT_STATUS_IS_OK(status)) {
2868                 status = result;
2869         }
2870         DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2871                   "for domain %s, error was %s. Trying anonymous\n",
2872                   domain->name, nt_errstr(status) ));
2873         TALLOC_FREE(conn->samr_pipe);
2874
2875  anonymous:
2876
2877         /* Finally fall back to anonymous. */
2878         if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
2879                 status = NT_STATUS_DOWNGRADE_DETECTED;
2880                 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2881                           "without connection level security, "
2882                           "must set 'winbind sealed pipes = false' and "
2883                           "'require strong key = false' to proceed: %s\n",
2884                           domain->name, nt_errstr(status)));
2885                 goto done;
2886         }
2887         status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2888                                           &conn->samr_pipe);
2889
2890         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2891             && !retry) {
2892                 invalidate_cm_connection(domain);
2893                 retry = true;
2894                 goto retry;
2895         }
2896
2897         if (!NT_STATUS_IS_OK(status)) {
2898                 goto done;
2899         }
2900
2901         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2902                                       conn->samr_pipe->desthost,
2903                                       SEC_FLAG_MAXIMUM_ALLOWED,
2904                                       &conn->sam_connect_handle,
2905                                       &result);
2906
2907         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2908                 invalidate_cm_connection(domain);
2909                 TALLOC_FREE(conn->samr_pipe);
2910                 retry = true;
2911                 goto retry;
2912         }
2913
2914         if (!NT_STATUS_IS_OK(status)) {
2915                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2916                           "for domain %s Error was %s\n",
2917                           domain->name, nt_errstr(status) ));
2918                 goto done;
2919         }
2920         if (!NT_STATUS_IS_OK(result)) {
2921                 status = result;
2922                 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2923                           "for domain %s Error was %s\n",
2924                           domain->name, nt_errstr(result)));
2925                 goto done;
2926         }
2927
2928  open_domain:
2929         status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2930                                         mem_ctx,
2931                                         &conn->sam_connect_handle,
2932                                         SEC_FLAG_MAXIMUM_ALLOWED,
2933                                         &domain->sid,
2934                                         &conn->sam_domain_handle,
2935                                         &result);
2936         if (!NT_STATUS_IS_OK(status)) {
2937                 goto done;
2938         }
2939
2940         status = result;
2941  done:
2942
2943         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2944                 /*
2945                  * if we got access denied, we might just have no access rights
2946                  * to talk to the remote samr server server (e.g. when we are a
2947                  * PDC and we are connecting a w2k8 pdc via an interdomain
2948                  * trust). In that case do not invalidate the whole connection
2949                  * stack
2950                  */
2951                 TALLOC_FREE(conn->samr_pipe);
2952                 ZERO_STRUCT(conn->sam_domain_handle);
2953                 return status;
2954         } else if (!NT_STATUS_IS_OK(status)) {
2955                 invalidate_cm_connection(domain);
2956                 return status;
2957         }
2958
2959         *cli = conn->samr_pipe;
2960         *sam_handle = conn->sam_domain_handle;
2961         return status;
2962 }
2963
2964 /**********************************************************************
2965  open an schanneld ncacn_ip_tcp connection to LSA
2966 ***********************************************************************/
2967
2968 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2969                                    TALLOC_CTX *mem_ctx,
2970                                    struct rpc_pipe_client **cli)
2971 {
2972         struct winbindd_cm_conn *conn;
2973         struct netlogon_creds_cli_context *p_creds = NULL;
2974         NTSTATUS status;
2975
2976         DEBUG(10,("cm_connect_lsa_tcp\n"));
2977
2978         status = init_dc_connection_rpc(domain, false);
2979         if (!NT_STATUS_IS_OK(status)) {
2980                 return status;
2981         }
2982
2983         conn = &domain->conn;
2984
2985         /*
2986          * rpccli_is_connected handles more error cases
2987          */
2988         if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2989             conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2990             conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2991                 goto done;
2992         }
2993
2994         TALLOC_FREE(conn->lsa_pipe_tcp);
2995
2996         status = cm_get_schannel_creds(domain, &p_creds);
2997         if (!NT_STATUS_IS_OK(status)) {
2998                 goto done;
2999         }
3000
3001         status = cli_rpc_pipe_open_schannel_with_creds(conn->cli,
3002                                                        &ndr_table_lsarpc,
3003                                                        NCACN_IP_TCP,
3004                                                        p_creds,
3005                                                        &conn->lsa_pipe_tcp);
3006         if (!NT_STATUS_IS_OK(status)) {
3007                 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
3008                         nt_errstr(status)));
3009                 goto done;
3010         }
3011
3012  done:
3013         if (!NT_STATUS_IS_OK(status)) {
3014                 TALLOC_FREE(conn->lsa_pipe_tcp);
3015                 return status;
3016         }
3017
3018         *cli = conn->lsa_pipe_tcp;
3019
3020         return status;
3021 }
3022
3023 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
3024                         struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
3025 {
3026         struct winbindd_cm_conn *conn;
3027         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
3028         struct netlogon_creds_cli_context *p_creds;
3029         struct cli_credentials *creds = NULL;
3030         bool retry = false; /* allow one retry attempt for expired session */
3031
3032 retry:
3033         result = init_dc_connection_rpc(domain, false);
3034         if (!NT_STATUS_IS_OK(result))
3035                 return result;
3036
3037         conn = &domain->conn;
3038
3039         if (rpccli_is_connected(conn->lsa_pipe)) {
3040                 goto done;
3041         }
3042
3043         TALLOC_FREE(conn->lsa_pipe);
3044
3045         if (IS_AD_DC) {
3046                 /*
3047                  * Make sure we only use schannel as AD DC.
3048                  */
3049                 goto schannel;
3050         }
3051
3052         result = get_trust_credentials(domain, talloc_tos(), false, &creds);
3053         if (!NT_STATUS_IS_OK(result)) {
3054                 DEBUG(10, ("cm_connect_lsa: No user available for "
3055                            "domain %s, trying schannel\n", domain->name));
3056                 goto schannel;
3057         }
3058
3059         if (cli_credentials_is_anonymous(creds)) {
3060                 goto anonymous;
3061         }
3062
3063         /*
3064          * We have an authenticated connection. Use a SPNEGO
3065          * authenticated LSA pipe with sign & seal.
3066          */
3067         result = cli_rpc_pipe_open_with_creds
3068                 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
3069                  DCERPC_AUTH_TYPE_SPNEGO,
3070                  conn->auth_level,
3071                  smbXcli_conn_remote_name(conn->cli->conn),
3072                  creds,
3073                  &conn->lsa_pipe);
3074
3075         if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3076             && !retry) {
3077                 invalidate_cm_connection(domain);
3078                 retry = true;
3079                 goto retry;
3080         }
3081
3082         if (!NT_STATUS_IS_OK(result)) {
3083                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3084                           "domain %s using NTLMSSP authenticated pipe: user "
3085                           "%s. Error was %s. Trying schannel.\n",
3086                           domain->name,
3087                           cli_credentials_get_unparsed_name(creds, talloc_tos()),
3088                           nt_errstr(result)));
3089                 goto schannel;
3090         }
3091
3092         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3093                   "NTLMSSP authenticated pipe: user %s\n",
3094                   domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3095
3096         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3097                                         SEC_FLAG_MAXIMUM_ALLOWED,
3098                                         &conn->lsa_policy);
3099         if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3100                 invalidate_cm_connection(domain);
3101                 TALLOC_FREE(conn->lsa_pipe);
3102                 retry = true;
3103                 goto retry;
3104         }
3105
3106         if (NT_STATUS_IS_OK(result)) {
3107                 goto done;
3108         }
3109
3110         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3111                   "schannel\n"));
3112
3113         TALLOC_FREE(conn->lsa_pipe);
3114
3115  schannel:
3116
3117         /* Fall back to schannel if it's a W2K pre-SP1 box. */
3118
3119         result = cm_get_schannel_creds(domain, &p_creds);
3120         if (!NT_STATUS_IS_OK(result)) {
3121                 /* If this call fails - conn->cli can now be NULL ! */
3122                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3123                            "for domain %s (error %s), trying anon\n",
3124                         domain->name,
3125                         nt_errstr(result) ));
3126                 goto anonymous;
3127         }
3128
3129         TALLOC_FREE(creds);
3130         result = cli_rpc_pipe_open_schannel_with_creds(
3131                 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3132                 &conn->lsa_pipe);
3133
3134         if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3135             && !retry) {
3136                 invalidate_cm_connection(domain);
3137                 retry = true;
3138                 goto retry;
3139         }
3140
3141         if (!NT_STATUS_IS_OK(result)) {
3142                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3143                           "domain %s using schannel. Error was %s\n",
3144                           domain->name, nt_errstr(result) ));
3145                 goto anonymous;
3146         }
3147         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3148                   "schannel.\n", domain->name ));
3149
3150         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3151                                         SEC_FLAG_MAXIMUM_ALLOWED,
3152                                         &conn->lsa_policy);
3153
3154         if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3155                 invalidate_cm_connection(domain);
3156                 TALLOC_FREE(conn->lsa_pipe);
3157                 retry = true;
3158                 goto retry;
3159         }
3160
3161         if (NT_STATUS_IS_OK(result)) {
3162                 goto done;
3163         }
3164
3165         if (IS_AD_DC) {
3166                 /*
3167                  * Make sure we only use schannel as AD DC.
3168                  */
3169                 goto done;
3170         }
3171
3172         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3173                   "anonymous\n"));
3174
3175         TALLOC_FREE(conn->lsa_pipe);
3176
3177  anonymous:
3178
3179         if (IS_AD_DC) {
3180                 /*
3181                  * Make sure we only use schannel as AD DC.
3182                  */
3183                 goto done;
3184         }
3185
3186         if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3187                 result = NT_STATUS_DOWNGRADE_DETECTED;
3188                 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3189                           "without connection level security, "
3190                           "must set 'winbind sealed pipes = false' and "
3191                           "'require strong key = false' to proceed: %s\n",
3192                           domain->name, nt_errstr(result)));
3193                 goto done;
3194         }
3195
3196         result = cli_rpc_pipe_open_noauth(conn->cli,
3197                                           &ndr_table_lsarpc,
3198                                           &conn->lsa_pipe);
3199
3200         if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3201             && !retry) {
3202                 invalidate_cm_connection(domain);
3203                 retry = true;
3204                 goto retry;
3205         }
3206
3207         if (!NT_STATUS_IS_OK(result)) {
3208                 goto done;
3209         }
3210
3211         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3212                                         SEC_FLAG_MAXIMUM_ALLOWED,
3213                                         &conn->lsa_policy);
3214
3215         if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3216                 invalidate_cm_connection(domain);
3217                 TALLOC_FREE(conn->lsa_pipe);
3218                 retry = true;
3219                 goto retry;
3220         }
3221
3222  done:
3223         if (!NT_STATUS_IS_OK(result)) {
3224                 invalidate_cm_connection(domain);
3225                 return result;
3226         }
3227
3228         *cli = conn->lsa_pipe;
3229         *lsa_policy = conn->lsa_policy;
3230         return result;
3231 }
3232
3233 /****************************************************************************
3234 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3235 ****************************************************************************/
3236
3237 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3238                          TALLOC_CTX *mem_ctx,
3239                          struct rpc_pipe_client **cli,
3240                          struct policy_handle *lsa_policy)
3241 {
3242         NTSTATUS status;
3243
3244         if (domain->can_do_ncacn_ip_tcp) {
3245                 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3246                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3247                     NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3248                     NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3249                         invalidate_cm_connection(domain);
3250                         status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3251                 }
3252                 if (NT_STATUS_IS_OK(status)) {
3253                         return status;
3254                 }
3255
3256                 /*
3257                  * we tried twice to connect via ncan_ip_tcp and schannel and
3258                  * failed - maybe it is a trusted domain we can't connect to ?
3259                  * do not try tcp next time - gd
3260                  *
3261                  * This also prevents NETLOGON over TCP
3262                  */
3263                 domain->can_do_ncacn_ip_tcp = false;
3264         }
3265
3266         status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3267
3268         return status;
3269 }
3270
3271 /****************************************************************************
3272  Open the netlogon pipe to this DC.
3273 ****************************************************************************/
3274
3275 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3276                                               enum dcerpc_transport_t transport,
3277                                               struct rpc_pipe_client **cli)
3278 {
3279         struct messaging_context *msg_ctx = server_messaging_context();
3280         struct winbindd_cm_conn *conn;
3281         NTSTATUS result;
3282         enum netr_SchannelType sec_chan_type;
3283         struct cli_credentials *creds = NULL;
3284
3285         *cli = NULL;
3286
3287         if (IS_AD_DC) {
3288                 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3289                         /*
3290                          * Make sure we don't even try to
3291                          * connect to a foreign domain
3292                          * without a direct outbound trust.
3293                          */
3294                         return NT_STATUS_NO_TRUST_LSA_SECRET;
3295                 }
3296         }
3297
3298         result = init_dc_connection_rpc(domain, domain->rodc);
3299         if (!NT_STATUS_IS_OK(result)) {
3300                 return result;
3301         }
3302
3303         conn = &domain->conn;
3304
3305         if (rpccli_is_connected(conn->netlogon_pipe)) {
3306                 *cli = conn->netlogon_pipe;
3307                 return NT_STATUS_OK;
3308         }
3309
3310         TALLOC_FREE(conn->netlogon_pipe);
3311         TALLOC_FREE(conn->netlogon_creds_ctx);
3312
3313         result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3314         if (!NT_STATUS_IS_OK(result)) {
3315                 DBG_DEBUG("No user available for domain %s when trying "
3316                           "schannel\n", domain->name);
3317                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3318         }
3319
3320         if (cli_credentials_is_anonymous(creds)) {
3321                 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3322                             "unable to make get NETLOGON credentials\n",
3323                             domain->name);
3324                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3325         }
3326
3327         sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3328         if (sec_chan_type == SEC_CHAN_NULL) {
3329                 if (transport == NCACN_IP_TCP) {
3330                         DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3331                                    "for %s, deny NCACN_IP_TCP and let the "
3332                                    "caller fallback to NCACN_NP.\n",
3333                                    domain->name);
3334                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3335                 }
3336
3337                 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3338                            "fallback to noauth on NCACN_NP.\n",
3339                            domain->name);
3340
3341                 result = cli_rpc_pipe_open_noauth_transport(
3342                         conn->cli,
3343                         transport,
3344                         &ndr_table_netlogon,
3345                         &conn->netlogon_pipe);
3346                 if (!NT_STATUS_IS_OK(result)) {
3347                         invalidate_cm_connection(domain);
3348                         return result;
3349                 }
3350
3351                 *cli = conn->netlogon_pipe;
3352                 return NT_STATUS_OK;
3353         }
3354
3355         result = rpccli_create_netlogon_creds_ctx(creds,
3356                                                   domain->dcname,
3357                                                   msg_ctx,
3358                                                   domain,
3359                                                   &conn->netlogon_creds_ctx);
3360         if (!NT_STATUS_IS_OK(result)) {
3361                 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3362                           "unable to create NETLOGON credentials: %s\n",
3363                           domain->name, nt_errstr(result)));
3364                 return result;
3365         }
3366
3367         result = rpccli_connect_netlogon(
3368                 conn->cli, transport,
3369                 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3370                 &conn->netlogon_pipe);
3371         conn->netlogon_force_reauth = false;
3372         if (!NT_STATUS_IS_OK(result)) {
3373                 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3374                           nt_errstr(result));
3375                 return result;
3376         }
3377
3378         *cli = conn->netlogon_pipe;
3379         return NT_STATUS_OK;
3380 }
3381
3382 /****************************************************************************
3383 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3384 ****************************************************************************/
3385
3386 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3387                              struct rpc_pipe_client **cli)
3388 {
3389         NTSTATUS status;
3390
3391         status = init_dc_connection_rpc(domain, domain->rodc);
3392         if (!NT_STATUS_IS_OK(status)) {
3393                 return status;
3394         }
3395
3396         if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3397                 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3398                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3399                     NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3400                     NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3401                         invalidate_cm_connection(domain);
3402                         status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3403                 }
3404                 if (NT_STATUS_IS_OK(status)) {
3405                         return status;
3406                 }
3407
3408                 /*
3409                  * we tried twice to connect via ncan_ip_tcp and schannel and
3410                  * failed - maybe it is a trusted domain we can't connect to ?
3411                  * do not try tcp next time - gd
3412                  *
3413                  * This also prevents LSA over TCP
3414                  */
3415                 domain->can_do_ncacn_ip_tcp = false;
3416         }
3417
3418         status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3419         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3420                 /*
3421                  * SMB2 session expired, needs reauthentication. Drop
3422                  * connection and retry.
3423                  */
3424                 invalidate_cm_connection(domain);
3425                 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3426         }
3427
3428         return status;
3429 }
3430
3431 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3432                                     struct rpc_pipe_client **cli,
3433                                     struct netlogon_creds_cli_context **ppdc)
3434 {
3435         NTSTATUS status;
3436
3437         if (domain->secure_channel_type == SEC_CHAN_NULL) {
3438                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3439         }
3440
3441         status = cm_connect_netlogon(domain, cli);
3442         if (!NT_STATUS_IS_OK(status)) {
3443                 return status;
3444         }
3445
3446         if (domain->conn.netlogon_creds_ctx == NULL) {
3447                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3448         }
3449
3450         *ppdc = domain->conn.netlogon_creds_ctx;
3451         return NT_STATUS_OK;
3452 }
3453
3454 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3455                             void *private_data,
3456                             uint32_t msg_type,
3457                             struct server_id server_id,
3458                             DATA_BLOB *data)
3459 {
3460         struct winbindd_domain *domain;
3461         char *freeit = NULL;
3462         char *addr;
3463
3464         if ((data == NULL)
3465             || (data->data == NULL)
3466             || (data->length == 0)
3467             || (data->data[data->length-1] != '\0')) {
3468                 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3469                           "string\n"));
3470                 return;
3471         }
3472
3473         addr = (char *)data->data;
3474         DEBUG(10, ("IP %s dropped\n", addr));
3475
3476         if (!is_ipaddress(addr)) {
3477                 char *slash;
3478                 /*
3479                  * Some code sends us ip addresses with the /netmask
3480                  * suffix
3481                  */
3482                 slash = strchr(addr, '/');
3483                 if (slash == NULL) {
3484                         DEBUG(1, ("invalid msg_ip_dropped message: %s",
3485                                   addr));
3486                         return;
3487                 }
3488                 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3489                 if (freeit == NULL) {
3490                         DEBUG(1, ("talloc failed\n"));
3491                         return;
3492                 }
3493                 addr = freeit;
3494                 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3495         }
3496
3497         for (domain = domain_list(); domain != NULL; domain = domain->next) {
3498                 char sockaddr[INET6_ADDRSTRLEN];
3499
3500                 if (!cli_state_is_connected(domain->conn.cli)) {
3501                         continue;
3502                 }
3503
3504                 print_sockaddr(sockaddr, sizeof(sockaddr),
3505                                smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3506
3507                 if (strequal(sockaddr, addr)) {
3508                         smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3509                 }
3510         }
3511         TALLOC_FREE(freeit);
3512 }
3513
3514 void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx,
3515                                void *private_data,
3516                                uint32_t msg_type,
3517                                struct server_id server_id,
3518                                DATA_BLOB *data)
3519 {
3520         struct winbindd_domain *domain;
3521
3522         for (domain = domain_list(); domain; domain = domain->next) {
3523                 if (domain->internal) {
3524                         continue;
3525                 }
3526                 invalidate_cm_connection(domain);
3527         }
3528 }