0f6a0a9ba1fb4212498dc2a31d4641ad1d2b67a8
[samba.git] / source3 / winbindd / winbindd_cm.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon connection manager
5
6    Copyright (C) Tim Potter                2001
7    Copyright (C) Andrew Bartlett           2002
8    Copyright (C) Gerald (Jerry) Carter     2003-2005.
9    Copyright (C) Volker Lendecke           2004-2005
10    Copyright (C) Jeremy Allison            2006
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 /*
27    We need to manage connections to domain controllers without having to
28    mess up the main winbindd code with other issues.  The aim of the
29    connection manager is to:
30
31        - make connections to domain controllers and cache them
32        - re-establish connections when networks or servers go down
33        - centralise the policy on connection timeouts, domain controller
34          selection etc
35        - manage re-entrancy for when winbindd becomes able to handle
36          multiple outstanding rpc requests
37
38    Why not have connection management as part of the rpc layer like tng?
39    Good question.  This code may morph into libsmb/rpc_cache.c or something
40    like that but at the moment it's simply staying as part of winbind.  I
41    think the TNG architecture of forcing every user of the rpc layer to use
42    the connection caching system is a bad idea.  It should be an optional
43    method of using the routines.
44
45    The TNG design is quite good but I disagree with some aspects of the
46    implementation. -tpot
47
48  */
49
50 /*
51    TODO:
52
53      - I'm pretty annoyed by all the make_nmb_name() stuff.  It should be
54        moved down into another function.
55
56      - Take care when destroying cli_structs as they can be shared between
57        various sam handles.
58
59  */
60
61 #include "includes.h"
62 #include "winbindd.h"
63 #include "../libcli/auth/libcli_auth.h"
64 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
65 #include "rpc_client/cli_pipe.h"
66 #include "rpc_client/cli_netlogon.h"
67 #include "../librpc/gen_ndr/ndr_samr_c.h"
68 #include "../librpc/gen_ndr/ndr_lsa_c.h"
69 #include "rpc_client/cli_lsarpc.h"
70 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
71 #include "libads/sitename_cache.h"
72 #include "libsmb/libsmb.h"
73 #include "libsmb/clidgram.h"
74 #include "ads.h"
75 #include "secrets.h"
76 #include "../libcli/security/security.h"
77 #include "passdb.h"
78 #include "messages.h"
79 #include "auth/gensec/gensec.h"
80 #include "../libcli/smb/smbXcli_base.h"
81 #include "libcli/auth/netlogon_creds_cli.h"
82 #include "auth.h"
83 #include "rpc_server/rpc_ncacn_np.h"
84 #include "auth/credentials/credentials.h"
85 #include "lib/param/param.h"
86
87 #undef DBGC_CLASS
88 #define DBGC_CLASS DBGC_WINBIND
89
90 struct dc_name_ip {
91         fstring name;
92         struct sockaddr_storage ss;
93 };
94
95 extern struct winbindd_methods reconnect_methods;
96 extern bool override_logfile;
97
98 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc);
99 static void set_dc_type_and_flags( struct winbindd_domain *domain );
100 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain );
101 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
102                     struct dc_name_ip **dcs, int *num_dcs,
103                     uint32_t request_flags);
104
105 /****************************************************************
106  Child failed to find DC's. Reschedule check.
107 ****************************************************************/
108
109 static void msg_failed_to_go_online(struct messaging_context *msg,
110                                     void *private_data,
111                                     uint32_t msg_type,
112                                     struct server_id server_id,
113                                     DATA_BLOB *data)
114 {
115         struct winbindd_domain *domain;
116         const char *domainname = (const char *)data->data;
117
118         if (data->data == NULL || data->length == 0) {
119                 return;
120         }
121
122         DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
123
124         for (domain = domain_list(); domain; domain = domain->next) {
125                 if (domain->internal) {
126                         continue;
127                 }
128
129                 if (strequal(domain->name, domainname)) {
130                         if (domain->online) {
131                                 /* We're already online, ignore. */
132                                 DEBUG(5,("msg_fail_to_go_online: domain %s "
133                                         "already online.\n", domainname));
134                                 continue;
135                         }
136
137                         /* Reschedule the online check. */
138                         set_domain_offline(domain);
139                         break;
140                 }
141         }
142 }
143
144 /****************************************************************
145  Actually cause a reconnect from a message.
146 ****************************************************************/
147
148 static void msg_try_to_go_online(struct messaging_context *msg,
149                                  void *private_data,
150                                  uint32_t msg_type,
151                                  struct server_id server_id,
152                                  DATA_BLOB *data)
153 {
154         struct winbindd_domain *domain;
155         const char *domainname = (const char *)data->data;
156
157         if (data->data == NULL || data->length == 0) {
158                 return;
159         }
160
161         DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
162
163         for (domain = domain_list(); domain; domain = domain->next) {
164                 if (domain->internal) {
165                         continue;
166                 }
167
168                 if (strequal(domain->name, domainname)) {
169
170                         if (domain->online) {
171                                 /* We're already online, ignore. */
172                                 DEBUG(5,("msg_try_to_go_online: domain %s "
173                                         "already online.\n", domainname));
174                                 continue;
175                         }
176
177                         /* This call takes care of setting the online
178                            flag to true if we connected, or re-adding
179                            the offline handler if false. Bypasses online
180                            check so always does network calls. */
181
182                         init_dc_connection_network(domain, true);
183                         break;
184                 }
185         }
186 }
187
188 /****************************************************************
189  Fork a child to try and contact a DC. Do this as contacting a
190  DC requires blocking lookups and we don't want to block our
191  parent.
192 ****************************************************************/
193
194 static bool fork_child_dc_connect(struct winbindd_domain *domain)
195 {
196         struct dc_name_ip *dcs = NULL;
197         int num_dcs = 0;
198         TALLOC_CTX *mem_ctx = NULL;
199         pid_t parent_pid = getpid();
200         char *lfile = NULL;
201         NTSTATUS status;
202         bool ok;
203
204         if (domain->dc_probe_pid != (pid_t)-1) {
205                 /*
206                  * We might already have a DC probe
207                  * child working, check.
208                  */
209                 if (process_exists_by_pid(domain->dc_probe_pid)) {
210                         DEBUG(10,("fork_child_dc_connect: pid %u already "
211                                 "checking for DC's.\n",
212                                 (unsigned int)domain->dc_probe_pid));
213                         return true;
214                 }
215                 domain->dc_probe_pid = (pid_t)-1;
216         }
217
218         domain->dc_probe_pid = fork();
219
220         if (domain->dc_probe_pid == (pid_t)-1) {
221                 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
222                 return False;
223         }
224
225         if (domain->dc_probe_pid != (pid_t)0) {
226                 /* Parent */
227                 messaging_register(server_messaging_context(), NULL,
228                                    MSG_WINBIND_TRY_TO_GO_ONLINE,
229                                    msg_try_to_go_online);
230                 messaging_register(server_messaging_context(), NULL,
231                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
232                                    msg_failed_to_go_online);
233                 return True;
234         }
235
236         /* Child. */
237
238         /* Leave messages blocked - we will never process one. */
239
240         if (!override_logfile) {
241                 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
242                         DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
243                         _exit(1);
244                 }
245         }
246
247         status = winbindd_reinit_after_fork(NULL, lfile);
248         if (!NT_STATUS_IS_OK(status)) {
249                 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
250                           nt_errstr(status)));
251                 messaging_send_buf(server_messaging_context(),
252                                    pid_to_procid(parent_pid),
253                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
254                                    (const uint8_t *)domain->name,
255                                    strlen(domain->name)+1);
256                 _exit(1);
257         }
258         SAFE_FREE(lfile);
259
260         setproctitle("dc-connect child");
261
262         mem_ctx = talloc_init("fork_child_dc_connect");
263         if (!mem_ctx) {
264                 DEBUG(0,("talloc_init failed.\n"));
265                 messaging_send_buf(server_messaging_context(),
266                                    pid_to_procid(parent_pid),
267                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
268                                    (const uint8_t *)domain->name,
269                                    strlen(domain->name)+1);
270                 _exit(1);
271         }
272
273         ok = get_dcs(mem_ctx, domain, &dcs, &num_dcs, 0);
274         TALLOC_FREE(mem_ctx);
275         if (!ok || (num_dcs == 0)) {
276                 /* Still offline ? Can't find DC's. */
277                 messaging_send_buf(server_messaging_context(),
278                                    pid_to_procid(parent_pid),
279                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
280                                    (const uint8_t *)domain->name,
281                                    strlen(domain->name)+1);
282                 _exit(0);
283         }
284
285         /* We got a DC. Send a message to our parent to get it to
286            try and do the same. */
287
288         messaging_send_buf(server_messaging_context(),
289                            pid_to_procid(parent_pid),
290                            MSG_WINBIND_TRY_TO_GO_ONLINE,
291                            (const uint8_t *)domain->name,
292                            strlen(domain->name)+1);
293         _exit(0);
294 }
295
296 /****************************************************************
297  Handler triggered if we're offline to try and detect a DC.
298 ****************************************************************/
299
300 static void check_domain_online_handler(struct tevent_context *ctx,
301                                         struct tevent_timer *te,
302                                         struct timeval now,
303                                         void *private_data)
304 {
305         struct winbindd_domain *domain =
306                 (struct winbindd_domain *)private_data;
307
308         DEBUG(10,("check_domain_online_handler: called for domain "
309                   "%s (online = %s)\n", domain->name, 
310                   domain->online ? "True" : "False" ));
311
312         TALLOC_FREE(domain->check_online_event);
313
314         /* Are we still in "startup" mode ? */
315
316         if (domain->startup && (time_mono(NULL) > domain->startup_time + 30)) {
317                 /* No longer in "startup" mode. */
318                 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
319                         domain->name ));
320                 domain->startup = False;
321         }
322
323         /* We've been told to stay offline, so stay
324            that way. */
325
326         if (get_global_winbindd_state_offline()) {
327                 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
328                         domain->name ));
329                 return;
330         }
331
332         /* Fork a child to test if it can contact a DC. 
333            If it can then send ourselves a message to
334            cause a reconnect. */
335
336         fork_child_dc_connect(domain);
337 }
338
339 /****************************************************************
340  If we're still offline setup the timeout check.
341 ****************************************************************/
342
343 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
344 {
345         int wbr = lp_winbind_reconnect_delay();
346
347         if (domain->startup) {
348                 domain->check_online_timeout = 10;
349         } else if (domain->check_online_timeout < wbr) {
350                 domain->check_online_timeout = wbr;
351         }
352 }
353
354 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
355                                 void *private_data,
356                                 uint32_t msg_type,
357                                 struct server_id server_id,
358                                 DATA_BLOB *data)
359 {
360         const char *domain_name = (const char *)data->data;
361         struct winbindd_domain *domain;
362
363         domain = find_domain_from_name_noinit(domain_name);
364         if (domain == NULL) {
365                 return;
366         }
367
368         domain->online = false;
369
370         DEBUG(10, ("Domain %s is marked as offline now.\n",
371                    domain_name));
372 }
373
374 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
375                                 void *private_data,
376                                 uint32_t msg_type,
377                                 struct server_id server_id,
378                                 DATA_BLOB *data)
379 {
380         const char *domain_name = (const char *)data->data;
381         struct winbindd_domain *domain;
382
383         domain = find_domain_from_name_noinit(domain_name);
384         if (domain == NULL) {
385                 return;
386         }
387
388         domain->online = true;
389
390         DEBUG(10, ("Domain %s is marked as online now.\n",
391                    domain_name));
392 }
393
394 /****************************************************************
395  Set domain offline and also add handler to put us back online
396  if we detect a DC.
397 ****************************************************************/
398
399 void set_domain_offline(struct winbindd_domain *domain)
400 {
401         pid_t parent_pid = getppid();
402
403         DEBUG(10,("set_domain_offline: called for domain %s\n",
404                 domain->name ));
405
406         TALLOC_FREE(domain->check_online_event);
407
408         if (domain->internal) {
409                 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
410                         domain->name ));
411                 return;
412         }
413
414         domain->online = False;
415
416         /* Offline domains are always initialized. They're
417            re-initialized when they go back online. */
418
419         domain->initialized = True;
420
421         /* We only add the timeout handler that checks and
422            allows us to go back online when we've not
423            been told to remain offline. */
424
425         if (get_global_winbindd_state_offline()) {
426                 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
427                         domain->name ));
428                 return;
429         }
430
431         /* If we're in startup mode, check again in 10 seconds, not in
432            lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
433
434         calc_new_online_timeout_check(domain);
435
436         domain->check_online_event = tevent_add_timer(server_event_context(),
437                                                 NULL,
438                                                 timeval_current_ofs(domain->check_online_timeout,0),
439                                                 check_domain_online_handler,
440                                                 domain);
441
442         /* The above *has* to succeed for winbindd to work. */
443         if (!domain->check_online_event) {
444                 smb_panic("set_domain_offline: failed to add online handler");
445         }
446
447         DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
448                 domain->name ));
449
450         /* Send a message to the parent that the domain is offline. */
451         if (parent_pid > 1 && !domain->internal) {
452                 messaging_send_buf(server_messaging_context(),
453                                    pid_to_procid(parent_pid),
454                                    MSG_WINBIND_DOMAIN_OFFLINE,
455                                    (uint8_t *)domain->name,
456                                    strlen(domain->name) + 1);
457         }
458
459         /* Send an offline message to the idmap child when our
460            primary domain goes offline */
461
462         if ( domain->primary ) {
463                 struct winbindd_child *idmap = idmap_child();
464
465                 if ( idmap->pid != 0 ) {
466                         messaging_send_buf(server_messaging_context(),
467                                            pid_to_procid(idmap->pid), 
468                                            MSG_WINBIND_OFFLINE, 
469                                            (const uint8_t *)domain->name,
470                                            strlen(domain->name)+1);
471                 }                       
472         }
473
474         return; 
475 }
476
477 /****************************************************************
478  Set domain online - if allowed.
479 ****************************************************************/
480
481 static void set_domain_online(struct winbindd_domain *domain)
482 {
483         pid_t parent_pid = getppid();
484
485         DEBUG(10,("set_domain_online: called for domain %s\n",
486                 domain->name ));
487
488         if (domain->internal) {
489                 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
490                         domain->name ));
491                 return;
492         }
493
494         if (get_global_winbindd_state_offline()) {
495                 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
496                         domain->name ));
497                 return;
498         }
499
500         winbindd_set_locator_kdc_envs(domain);
501
502         /* If we are waiting to get a krb5 ticket, trigger immediately. */
503         ccache_regain_all_now();
504
505         /* Ok, we're out of any startup mode now... */
506         domain->startup = False;
507
508         if (domain->online == False) {
509                 /* We were offline - now we're online. We default to
510                    using the MS-RPC backend if we started offline,
511                    and if we're going online for the first time we
512                    should really re-initialize the backends and the
513                    checks to see if we're talking to an AD or NT domain.
514                 */
515
516                 domain->initialized = False;
517
518                 /* 'reconnect_methods' is the MS-RPC backend. */
519                 if (domain->backend == &reconnect_methods) {
520                         domain->backend = NULL;
521                 }
522         }
523
524         /* Ensure we have no online timeout checks. */
525         domain->check_online_timeout = 0;
526         TALLOC_FREE(domain->check_online_event);
527
528         /* Ensure we ignore any pending child messages. */
529         messaging_deregister(server_messaging_context(),
530                              MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
531         messaging_deregister(server_messaging_context(),
532                              MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
533
534         domain->online = True;
535
536         /* Send a message to the parent that the domain is online. */
537         if (parent_pid > 1 && !domain->internal) {
538                 messaging_send_buf(server_messaging_context(),
539                                    pid_to_procid(parent_pid),
540                                    MSG_WINBIND_DOMAIN_ONLINE,
541                                    (uint8_t *)domain->name,
542                                    strlen(domain->name) + 1);
543         }
544
545         /* Send an online message to the idmap child when our
546            primary domain comes online */
547
548         if ( domain->primary ) {
549                 struct winbindd_child *idmap = idmap_child();
550
551                 if ( idmap->pid != 0 ) {
552                         messaging_send_buf(server_messaging_context(),
553                                            pid_to_procid(idmap->pid), 
554                                            MSG_WINBIND_ONLINE, 
555                                            (const uint8_t *)domain->name,
556                                            strlen(domain->name)+1);
557                 }                       
558         }
559
560         return; 
561 }
562
563 /****************************************************************
564  Requested to set a domain online.
565 ****************************************************************/
566
567 void set_domain_online_request(struct winbindd_domain *domain)
568 {
569         struct timeval tev;
570
571         DEBUG(10,("set_domain_online_request: called for domain %s\n",
572                 domain->name ));
573
574         if (get_global_winbindd_state_offline()) {
575                 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
576                         domain->name ));
577                 return;
578         }
579
580         if (domain->internal) {
581                 DEBUG(10, ("set_domain_online_request: Internal domains are "
582                            "always online\n"));
583                 return;
584         }
585
586         /* We've been told it's safe to go online and
587            try and connect to a DC. But I don't believe it
588            because network manager seems to lie.
589            Wait at least 5 seconds. Heuristics suck... */
590
591
592         GetTimeOfDay(&tev);
593
594         /* Go into "startup" mode again. */
595         domain->startup_time = time_mono(NULL);
596         domain->startup = True;
597
598         tev.tv_sec += 5;
599
600         if (!domain->check_online_event) {
601                 /* If we've come from being globally offline we
602                    don't have a check online event handler set.
603                    We need to add one now we're trying to go
604                    back online. */
605
606                 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
607                         domain->name ));
608         }
609
610         TALLOC_FREE(domain->check_online_event);
611
612         domain->check_online_event = tevent_add_timer(server_event_context(),
613                                                      NULL,
614                                                      tev,
615                                                      check_domain_online_handler,
616                                                      domain);
617
618         /* The above *has* to succeed for winbindd to work. */
619         if (!domain->check_online_event) {
620                 smb_panic("set_domain_online_request: failed to add online handler");
621         }
622 }
623
624 /****************************************************************
625  Add -ve connection cache entries for domain and realm.
626 ****************************************************************/
627
628 static void winbind_add_failed_connection_entry(
629         const struct winbindd_domain *domain,
630         const char *server,
631         NTSTATUS result)
632 {
633         add_failed_connection_entry(domain->name, server, result);
634         /* If this was the saf name for the last thing we talked to,
635            remove it. */
636         saf_delete(domain->name);
637         if (domain->alt_name != NULL) {
638                 add_failed_connection_entry(domain->alt_name, server, result);
639                 saf_delete(domain->alt_name);
640         }
641         winbindd_unset_locator_kdc_env(domain);
642 }
643
644 /* Choose between anonymous or authenticated connections.  We need to use
645    an authenticated connection if DCs have the RestrictAnonymous registry
646    entry set > 0, or the "Additional restrictions for anonymous
647    connections" set in the win2k Local Security Policy. 
648
649    Caller to free() result in domain, username, password
650 */
651
652 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
653 {
654         *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
655         *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
656         *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
657
658         if (*username && **username) {
659
660                 if (!*domain || !**domain)
661                         *domain = smb_xstrdup(lp_workgroup());
662
663                 if (!*password || !**password)
664                         *password = smb_xstrdup("");
665
666                 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n", 
667                           *domain, *username));
668
669         } else {
670                 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
671                 *username = smb_xstrdup("");
672                 *domain = smb_xstrdup("");
673                 *password = smb_xstrdup("");
674         }
675 }
676
677 static NTSTATUS cm_get_ipc_credentials(TALLOC_CTX *mem_ctx,
678                                        struct cli_credentials **_creds)
679 {
680
681         TALLOC_CTX *frame = talloc_stackframe();
682         NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
683         struct loadparm_context *lp_ctx;
684         char *username = NULL;
685         char *netbios_domain = NULL;
686         char *password = NULL;
687         struct cli_credentials *creds = NULL;
688         bool ok;
689
690         cm_get_ipc_userpass(&username, &netbios_domain, &password);
691
692         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
693         if (lp_ctx == NULL) {
694                 DEBUG(1, ("loadparm_init_s3 failed\n"));
695                 status = NT_STATUS_INTERNAL_ERROR;
696                 goto fail;
697         }
698
699         creds = cli_credentials_init(mem_ctx);
700         if (creds == NULL) {
701                 status = NT_STATUS_NO_MEMORY;
702                 goto fail;
703         }
704
705         cli_credentials_set_conf(creds, lp_ctx);
706         cli_credentials_set_kerberos_state(creds, CRED_DONT_USE_KERBEROS);
707
708         ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
709         if (!ok) {
710                 status = NT_STATUS_NO_MEMORY;
711                 goto fail;
712         }
713
714         ok = cli_credentials_set_username(creds, username, CRED_SPECIFIED);
715         if (!ok) {
716                 status = NT_STATUS_NO_MEMORY;
717                 goto fail;
718         }
719
720         ok = cli_credentials_set_password(creds, password, CRED_SPECIFIED);
721         if (!ok) {
722                 status = NT_STATUS_NO_MEMORY;
723                 goto fail;
724         }
725
726         *_creds = creds;
727         creds = NULL;
728         status = NT_STATUS_OK;
729  fail:
730         TALLOC_FREE(creds);
731         SAFE_FREE(username);
732         SAFE_FREE(netbios_domain);
733         SAFE_FREE(password);
734         TALLOC_FREE(frame);
735         return status;
736 }
737
738 static bool cm_is_ipc_credentials(struct cli_credentials *creds)
739 {
740         TALLOC_CTX *frame = talloc_stackframe();
741         char *ipc_account = NULL;
742         char *ipc_domain = NULL;
743         char *ipc_password = NULL;
744         const char *creds_account = NULL;
745         const char *creds_domain = NULL;
746         const char *creds_password = NULL;
747         bool ret = false;
748
749         cm_get_ipc_userpass(&ipc_account, &ipc_domain, &ipc_password);
750
751         creds_account = cli_credentials_get_username(creds);
752         creds_domain = cli_credentials_get_domain(creds);
753         creds_password = cli_credentials_get_password(creds);
754
755         if (!strequal(ipc_domain, creds_domain)) {
756                 goto done;
757         }
758
759         if (!strequal(ipc_account, creds_account)) {
760                 goto done;
761         }
762
763         if (!strcsequal(ipc_password, creds_password)) {
764                 goto done;
765         }
766
767         ret = true;
768  done:
769         SAFE_FREE(ipc_account);
770         SAFE_FREE(ipc_domain);
771         SAFE_FREE(ipc_password);
772         TALLOC_FREE(frame);
773         return ret;
774 }
775
776 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
777                                      fstring dcname,
778                                      struct sockaddr_storage *dc_ss,
779                                      uint32_t request_flags)
780 {
781         struct winbindd_domain *our_domain = NULL;
782         struct rpc_pipe_client *netlogon_pipe = NULL;
783         NTSTATUS result;
784         WERROR werr;
785         TALLOC_CTX *mem_ctx;
786         unsigned int orig_timeout;
787         const char *tmp = NULL;
788         const char *p;
789         struct dcerpc_binding_handle *b;
790
791         /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
792          * moment.... */
793
794         if (IS_DC) {
795                 return False;
796         }
797
798         if (domain->primary) {
799                 return False;
800         }
801
802         our_domain = find_our_domain();
803
804         if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
805                 return False;
806         }
807
808         result = cm_connect_netlogon(our_domain, &netlogon_pipe);
809         if (!NT_STATUS_IS_OK(result)) {
810                 talloc_destroy(mem_ctx);
811                 return False;
812         }
813
814         b = netlogon_pipe->binding_handle;
815
816         /* This call can take a long time - allow the server to time out.
817            35 seconds should do it. */
818
819         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
820
821         if (our_domain->active_directory) {
822                 struct netr_DsRGetDCNameInfo *domain_info = NULL;
823
824                 /*
825                  * TODO request flags are not respected in the server
826                  * (and in some cases, like REQUIRE_PDC, causes an error)
827                  */
828                 result = dcerpc_netr_DsRGetDCName(b,
829                                                   mem_ctx,
830                                                   our_domain->dcname,
831                                                   domain->name,
832                                                   NULL,
833                                                   NULL,
834                                                   request_flags|DS_RETURN_DNS_NAME,
835                                                   &domain_info,
836                                                   &werr);
837                 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
838                         tmp = talloc_strdup(
839                                 mem_ctx, domain_info->dc_unc);
840                         if (tmp == NULL) {
841                                 DEBUG(0, ("talloc_strdup failed\n"));
842                                 talloc_destroy(mem_ctx);
843                                 return false;
844                         }
845                         if (domain->alt_name == NULL) {
846                                 domain->alt_name = talloc_strdup(domain,
847                                                                  domain_info->domain_name);
848                                 if (domain->alt_name == NULL) {
849                                         DEBUG(0, ("talloc_strdup failed\n"));
850                                         talloc_destroy(mem_ctx);
851                                         return false;
852                                 }
853                         }
854                         if (domain->forest_name == NULL) {
855                                 domain->forest_name = talloc_strdup(domain,
856                                                                     domain_info->forest_name);
857                                 if (domain->forest_name == NULL) {
858                                         DEBUG(0, ("talloc_strdup failed\n"));
859                                         talloc_destroy(mem_ctx);
860                                         return false;
861                                 }
862                         }
863                 }
864         } else {
865                 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
866                                                   our_domain->dcname,
867                                                   domain->name,
868                                                   &tmp,
869                                                   &werr);
870         }
871
872         /* And restore our original timeout. */
873         rpccli_set_timeout(netlogon_pipe, orig_timeout);
874
875         if (!NT_STATUS_IS_OK(result)) {
876                 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
877                         nt_errstr(result)));
878                 talloc_destroy(mem_ctx);
879                 return false;
880         }
881
882         if (!W_ERROR_IS_OK(werr)) {
883                 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
884                            win_errstr(werr)));
885                 talloc_destroy(mem_ctx);
886                 return false;
887         }
888
889         /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
890         p = strip_hostname(tmp);
891
892         fstrcpy(dcname, p);
893
894         talloc_destroy(mem_ctx);
895
896         DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
897
898         if (!resolve_name(dcname, dc_ss, 0x20, true)) {
899                 return False;
900         }
901
902         return True;
903 }
904
905 /**
906  * Helper function to assemble trust password and account name
907  */
908 static NTSTATUS get_trust_credentials(struct winbindd_domain *domain,
909                                       TALLOC_CTX *mem_ctx,
910                                       bool netlogon,
911                                       struct cli_credentials **_creds)
912 {
913         const struct winbindd_domain *creds_domain = NULL;
914         struct cli_credentials *creds;
915         NTSTATUS status;
916         bool force_machine_account = false;
917
918         /* If we are a DC and this is not our own domain */
919
920         if (!domain->active_directory) {
921                 if (!netlogon) {
922                         /*
923                          * For non active directory domains
924                          * we can only use NTLMSSP for SMB.
925                          *
926                          * But the trust account is not allowed
927                          * to use SMB with NTLMSSP.
928                          */
929                         force_machine_account = true;
930                 }
931         }
932
933         if (IS_DC && !force_machine_account) {
934                 creds_domain = domain;
935         } else {
936                 creds_domain = find_our_domain();
937                 if (creds_domain == NULL) {
938                         return NT_STATUS_INVALID_SERVER_STATE;
939                 }
940         }
941
942         status = pdb_get_trust_credentials(creds_domain->name,
943                                            creds_domain->alt_name,
944                                            mem_ctx,
945                                            &creds);
946         if (!NT_STATUS_IS_OK(status)) {
947                 goto ipc_fallback;
948         }
949
950         if (creds_domain != domain) {
951                 /*
952                  * We can only use schannel against a direct trust
953                  */
954                 cli_credentials_set_secure_channel_type(creds,
955                                                         SEC_CHAN_NULL);
956         }
957
958         *_creds = creds;
959         return NT_STATUS_OK;
960
961  ipc_fallback:
962         if (netlogon) {
963                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
964         }
965
966         status = cm_get_ipc_credentials(mem_ctx, &creds);
967         if (!NT_STATUS_IS_OK(status)) {
968                 return status;
969         }
970
971         *_creds = creds;
972         return NT_STATUS_OK;
973 }
974
975 /************************************************************************
976  Given a fd with a just-connected TCP connection to a DC, open a connection
977  to the pipe.
978 ************************************************************************/
979
980 static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
981                                       const int sockfd,
982                                       const char *controller,
983                                       struct cli_state **cli,
984                                       bool *retry)
985 {
986         bool try_ipc_auth = false;
987         const char *machine_principal = NULL;
988         const char *machine_realm = NULL;
989         const char *machine_account = NULL;
990         const char *machine_domain = NULL;
991         int flags = 0;
992         struct cli_credentials *creds = NULL;
993
994         struct named_mutex *mutex;
995
996         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
997         NTSTATUS tmp_status;
998         NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
999
1000         enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
1001
1002         if (IS_AD_DC) {
1003                 if (domain->secure_channel_type == SEC_CHAN_NULL) {
1004                         /*
1005                          * Make sure we don't even try to
1006                          * connect to a foreign domain
1007                          * without a direct outbound trust.
1008                          */
1009                         return NT_STATUS_NO_TRUST_LSA_SECRET;
1010                 }
1011
1012                 /*
1013                  * As AD DC we only use netlogon and lsa
1014                  * using schannel over an anonymous transport
1015                  * (ncacn_ip_tcp or ncacn_np).
1016                  *
1017                  * Currently we always establish the SMB connection,
1018                  * even if we don't use it, because we later use ncacn_ip_tcp.
1019                  *
1020                  * As we won't use the SMB connection there's no
1021                  * need to try kerberos. And NT4 domains expect
1022                  * an anonymous IPC$ connection anyway.
1023                  */
1024                 smb_sign_client_connections = SMB_SIGNING_OFF;
1025         }
1026
1027         if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
1028                 /*
1029                  * If we are connecting to our own AD domain, require
1030                  * smb signing to disrupt MITM attacks
1031                  */
1032                 if (domain->primary && lp_security() == SEC_ADS) {
1033                         smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1034                 /*
1035                  * If we are in or are an AD domain and connecting to another
1036                  * AD domain in our forest
1037                  * then require smb signing to disrupt MITM attacks
1038                  */
1039                 } else if ((lp_security() == SEC_ADS)
1040                            && domain->active_directory
1041                            && (domain->domain_trust_attribs
1042                                & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
1043                         smb_sign_client_connections = SMB_SIGNING_REQUIRED;
1044                 }
1045         }
1046
1047         DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
1048                 controller, domain->name ));
1049
1050         *retry = True;
1051
1052         mutex = grab_named_mutex(talloc_tos(), controller,
1053                                  WINBIND_SERVER_MUTEX_WAIT_TIME);
1054         if (mutex == NULL) {
1055                 close(sockfd);
1056                 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
1057                          controller));
1058                 result = NT_STATUS_POSSIBLE_DEADLOCK;
1059                 goto done;
1060         }
1061
1062         *cli = cli_state_create(NULL, sockfd, controller,
1063                                 smb_sign_client_connections, flags);
1064         if (*cli == NULL) {
1065                 close(sockfd);
1066                 DEBUG(1, ("Could not cli_initialize\n"));
1067                 result = NT_STATUS_NO_MEMORY;
1068                 goto done;
1069         }
1070
1071         cli_set_timeout(*cli, 10000); /* 10 seconds */
1072
1073         set_socket_options(sockfd, lp_socket_options());
1074
1075         result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
1076                                  lp_client_ipc_min_protocol(),
1077                                  lp_client_ipc_max_protocol());
1078
1079         if (!NT_STATUS_IS_OK(result)) {
1080                 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
1081                 goto done;
1082         }
1083
1084         if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
1085             smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
1086                 try_ipc_auth = true;
1087         } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1088                 try_ipc_auth = true;
1089         } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1090                 /*
1091                  * If we are forcing on SMB signing, then we must
1092                  * require authentication unless this is a one-way
1093                  * trust, and we have no stored user/password
1094                  */
1095                 try_ipc_auth = true;
1096         }
1097
1098         if (IS_AD_DC) {
1099                 /*
1100                  * As AD DC we only use netlogon and lsa
1101                  * using schannel over an anonymous transport
1102                  * (ncacn_ip_tcp or ncacn_np).
1103                  *
1104                  * Currently we always establish the SMB connection,
1105                  * even if we don't use it, because we later use ncacn_ip_tcp.
1106                  *
1107                  * As we won't use the SMB connection there's no
1108                  * need to try kerberos. And NT4 domains expect
1109                  * an anonymous IPC$ connection anyway.
1110                  */
1111                 try_ipc_auth = false;
1112         }
1113
1114         if (try_ipc_auth) {
1115                 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
1116                 if (!NT_STATUS_IS_OK(result)) {
1117                         DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
1118                                   domain->name, nt_errstr(result)));
1119                         goto done;
1120                 }
1121         } else {
1122                 /*
1123                  * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
1124                  * would try and authentication with our machine
1125                  * account password and fail.  This is very rare in
1126                  * the modern world however
1127                  */
1128                 creds = cli_credentials_init_anon(talloc_tos());
1129                 if (creds == NULL) {
1130                         result = NT_STATUS_NO_MEMORY;
1131                         DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
1132                                   domain->name, nt_errstr(result)));
1133                         goto done;
1134                 }
1135         }
1136
1137         machine_principal = cli_credentials_get_principal(creds,
1138                                                         talloc_tos());
1139         machine_realm = cli_credentials_get_realm(creds);
1140         machine_account = cli_credentials_get_username(creds);
1141         machine_domain = cli_credentials_get_domain(creds);
1142
1143         DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
1144                   "[%s] and realm [%s]\n",
1145                   controller, domain->name, domain->alt_name,
1146                   machine_domain, machine_account,
1147                   machine_principal, machine_realm));
1148
1149         if (cli_credentials_is_anonymous(creds)) {
1150                 goto anon_fallback;
1151         }
1152
1153         winbindd_set_locator_kdc_envs(domain);
1154
1155         result = cli_session_setup_creds(*cli, creds);
1156         if (NT_STATUS_IS_OK(result)) {
1157                 goto session_setup_done;
1158         }
1159
1160         DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1161                   controller,
1162                   cli_credentials_get_unparsed_name(creds, talloc_tos()),
1163                   nt_errstr(result)));
1164
1165         /*
1166          * If we are not going to validiate the conneciton
1167          * with SMB signing, then allow us to fall back to
1168          * anonymous
1169          */
1170         if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1171             || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1172             || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1173             || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1174             || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1175         {
1176                 if (!cm_is_ipc_credentials(creds)) {
1177                         goto ipc_fallback;
1178                 }
1179
1180                 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1181                         goto done;
1182                 }
1183
1184                 goto anon_fallback;
1185         }
1186
1187         goto done;
1188
1189  ipc_fallback:
1190         TALLOC_FREE(creds);
1191         tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
1192         if (!NT_STATUS_IS_OK(tmp_status)) {
1193                 result = tmp_status;
1194                 goto done;
1195         }
1196
1197         if (cli_credentials_is_anonymous(creds)) {
1198                 goto anon_fallback;
1199         }
1200
1201         machine_account = cli_credentials_get_username(creds);
1202         machine_domain = cli_credentials_get_domain(creds);
1203
1204         DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
1205                   "[%s]\\[%s]\n",  controller, lp_netbios_name(),
1206                   machine_domain, machine_account));
1207
1208         result = cli_session_setup_creds(*cli, creds);
1209         if (NT_STATUS_IS_OK(result)) {
1210                 goto session_setup_done;
1211         }
1212
1213         DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1214                   controller,
1215                   cli_credentials_get_unparsed_name(creds, talloc_tos()),
1216                   nt_errstr(result)));
1217
1218         /*
1219          * If we are not going to validiate the conneciton
1220          * with SMB signing, then allow us to fall back to
1221          * anonymous
1222          */
1223         if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1224             || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1225             || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1226             || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1227             || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1228         {
1229                 goto anon_fallback;
1230         }
1231
1232         goto done;
1233
1234  anon_fallback:
1235         TALLOC_FREE(creds);
1236
1237         if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1238                 goto done;
1239         }
1240
1241         /* Fall back to anonymous connection, this might fail later */
1242         DEBUG(5,("cm_prepare_connection: falling back to anonymous "
1243                 "connection for DC %s\n",
1244                 controller ));
1245
1246         result = cli_session_setup_anon(*cli);
1247         if (NT_STATUS_IS_OK(result)) {
1248                 DEBUG(5, ("Connected anonymously\n"));
1249                 goto session_setup_done;
1250         }
1251
1252         DEBUG(1, ("anonymous session setup to %s failed with %s\n",
1253                   controller, nt_errstr(result)));
1254
1255         /* We can't session setup */
1256         goto done;
1257
1258  session_setup_done:
1259         TALLOC_FREE(creds);
1260
1261         /*
1262          * This should be a short term hack until
1263          * dynamic re-authentication is implemented.
1264          *
1265          * See Bug 9175 - winbindd doesn't recover from
1266          * NT_STATUS_NETWORK_SESSION_EXPIRED
1267          */
1268         if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1269                 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1270         }
1271
1272         result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
1273         if (!NT_STATUS_IS_OK(result)) {
1274                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1275                 goto done;
1276         }
1277         tcon_status = result;
1278
1279         /* cache the server name for later connections */
1280
1281         saf_store(domain->name, controller);
1282         if (domain->alt_name) {
1283                 saf_store(domain->alt_name, controller);
1284         }
1285
1286         winbindd_set_locator_kdc_envs(domain);
1287
1288         TALLOC_FREE(mutex);
1289         *retry = False;
1290
1291         result = NT_STATUS_OK;
1292
1293  done:
1294         TALLOC_FREE(mutex);
1295         TALLOC_FREE(creds);
1296
1297         if (NT_STATUS_IS_OK(result)) {
1298                 result = tcon_status;
1299         }
1300
1301         if (!NT_STATUS_IS_OK(result)) {
1302                 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1303                           controller, nt_errstr(result)));
1304                 winbind_add_failed_connection_entry(domain, controller, result);
1305                 if ((*cli) != NULL) {
1306                         cli_shutdown(*cli);
1307                         *cli = NULL;
1308                 }
1309         }
1310
1311         return result;
1312 }
1313
1314 /*******************************************************************
1315  Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1316  array.
1317
1318  Keeps the list unique by not adding duplicate entries.
1319
1320  @param[in] mem_ctx talloc memory context to allocate from
1321  @param[in] domain_name domain of the DC
1322  @param[in] dcname name of the DC to add to the list
1323  @param[in] pss Internet address and port pair to add to the list
1324  @param[in,out] dcs array of dc_name_ip structures to add to
1325  @param[in,out] num_dcs number of dcs returned in the dcs array
1326  @return true if the list was added to, false otherwise
1327 *******************************************************************/
1328
1329 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1330                               const char *dcname, struct sockaddr_storage *pss,
1331                               struct dc_name_ip **dcs, int *num)
1332 {
1333         int i = 0;
1334
1335         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1336                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1337                 return False;
1338         }
1339
1340         /* Make sure there's no duplicates in the list */
1341         for (i=0; i<*num; i++)
1342                 if (sockaddr_equal(
1343                             (struct sockaddr *)(void *)&(*dcs)[i].ss,
1344                             (struct sockaddr *)(void *)pss))
1345                         return False;
1346
1347         *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1348
1349         if (*dcs == NULL)
1350                 return False;
1351
1352         fstrcpy((*dcs)[*num].name, dcname);
1353         (*dcs)[*num].ss = *pss;
1354         *num += 1;
1355         return True;
1356 }
1357
1358 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1359                                   struct sockaddr_storage *pss, uint16_t port,
1360                                   struct sockaddr_storage **addrs, int *num)
1361 {
1362         *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1363
1364         if (*addrs == NULL) {
1365                 *num = 0;
1366                 return False;
1367         }
1368
1369         (*addrs)[*num] = *pss;
1370         set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1371
1372         *num += 1;
1373         return True;
1374 }
1375
1376 /*******************************************************************
1377  convert an ip to a name
1378  For an AD Domain, it checks the requirements of the request flags.
1379 *******************************************************************/
1380
1381 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1382                             const struct winbindd_domain *domain,
1383                             struct sockaddr_storage *pss,
1384                             char **name, uint32_t request_flags)
1385 {
1386         struct ip_service ip_list;
1387         uint32_t nt_version = NETLOGON_NT_VERSION_1;
1388         NTSTATUS status;
1389         const char *dc_name;
1390         fstring nbtname;
1391 #ifdef HAVE_ADS
1392         bool is_ad_domain = false;
1393 #endif
1394         ip_list.ss = *pss;
1395         ip_list.port = 0;
1396
1397 #ifdef HAVE_ADS
1398         /* For active directory servers, try to get the ldap server name.
1399            None of these failures should be considered critical for now */
1400
1401         if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1402                 is_ad_domain = true;
1403         } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1404                 is_ad_domain = domain->active_directory;
1405         }
1406
1407         if (is_ad_domain) {
1408                 ADS_STRUCT *ads;
1409                 ADS_STATUS ads_status;
1410                 char addr[INET6_ADDRSTRLEN];
1411
1412                 print_sockaddr(addr, sizeof(addr), pss);
1413
1414                 ads = ads_init(domain->alt_name, domain->name, addr);
1415                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1416                 ads->config.flags |= request_flags;
1417                 ads->server.no_fallback = true;
1418
1419                 ads_status = ads_connect(ads);
1420                 if (ADS_ERR_OK(ads_status)) {
1421                         /* We got a cldap packet. */
1422                         *name = talloc_strdup(mem_ctx,
1423                                              ads->config.ldap_server_name);
1424                         if (*name == NULL) {
1425                                 return false;
1426                         }
1427                         namecache_store(*name, 0x20, 1, &ip_list);
1428
1429                         DEBUG(10,("dcip_check_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1430
1431                         if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1432                                 if (ads_closest_dc(ads)) {
1433                                         char *sitename = sitename_fetch(mem_ctx, ads->config.realm);
1434
1435                                         /* We're going to use this KDC for this realm/domain.
1436                                            If we are using sites, then force the krb5 libs
1437                                            to use this KDC. */
1438
1439                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1440                                                                         domain->name,
1441                                                                         sitename,
1442                                                                         pss);
1443
1444                                         TALLOC_FREE(sitename);
1445                                 } else {
1446                                         /* use an off site KDC */
1447                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1448                                                                         domain->name,
1449                                                                         NULL,
1450                                                                         pss);
1451                                 }
1452                                 winbindd_set_locator_kdc_envs(domain);
1453
1454                                 /* Ensure we contact this DC also. */
1455                                 saf_store(domain->name, *name);
1456                                 saf_store(domain->alt_name, *name);
1457                         }
1458
1459                         ads_destroy( &ads );
1460                         return True;
1461                 }
1462
1463                 ads_destroy( &ads );
1464                 return false;
1465         }
1466 #endif
1467
1468         status = nbt_getdc(server_messaging_context(), 10, pss, domain->name,
1469                            &domain->sid, nt_version, mem_ctx, &nt_version,
1470                            &dc_name, NULL);
1471         if (NT_STATUS_IS_OK(status)) {
1472                 *name = talloc_strdup(mem_ctx, dc_name);
1473                 if (*name == NULL) {
1474                         return false;
1475                 }
1476                 namecache_store(*name, 0x20, 1, &ip_list);
1477                 return True;
1478         }
1479
1480         /* try node status request */
1481
1482         if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1483                 namecache_store(nbtname, 0x20, 1, &ip_list);
1484
1485                 if (name != NULL) {
1486                         *name = talloc_strdup(mem_ctx, nbtname);
1487                         if (*name == NULL) {
1488                                 return false;
1489                         }
1490                 }
1491
1492                 return true;
1493         }
1494         return False;
1495 }
1496
1497 /*******************************************************************
1498  Retrieve a list of IP addresses for domain controllers.
1499
1500  The array is sorted in the preferred connection order.
1501
1502  @param[in] mem_ctx talloc memory context to allocate from
1503  @param[in] domain domain to retrieve DCs for
1504  @param[out] dcs array of dcs that will be returned
1505  @param[out] num_dcs number of dcs returned in the dcs array
1506  @return always true
1507 *******************************************************************/
1508
1509 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1510                     struct dc_name_ip **dcs, int *num_dcs,
1511                     uint32_t request_flags)
1512 {
1513         fstring dcname;
1514         struct  sockaddr_storage ss;
1515         struct  ip_service *ip_list = NULL;
1516         int     iplist_size = 0;
1517         int     i;
1518         bool    is_our_domain;
1519         enum security_types sec = (enum security_types)lp_security();
1520
1521         is_our_domain = strequal(domain->name, lp_workgroup());
1522
1523         /* If not our domain, get the preferred DC, by asking our primary DC */
1524         if ( !is_our_domain
1525                 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1526                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1527                        num_dcs) )
1528         {
1529                 char addr[INET6_ADDRSTRLEN];
1530                 print_sockaddr(addr, sizeof(addr), &ss);
1531                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1532                            dcname, addr));
1533                 return True;
1534         }
1535
1536         if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1537                 char *sitename = NULL;
1538
1539                 /* We need to make sure we know the local site before
1540                    doing any DNS queries, as this will restrict the
1541                    get_sorted_dc_list() call below to only fetching
1542                    DNS records for the correct site. */
1543
1544                 /* Find any DC to get the site record.
1545                    We deliberately don't care about the
1546                    return here. */
1547
1548                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1549
1550                 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1551                 if (sitename) {
1552
1553                         /* Do the site-specific AD dns lookup first. */
1554                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1555                                &iplist_size, True);
1556
1557                         /* Add ips to the DC array.  We don't look up the name
1558                            of the DC in this function, but we fill in the char*
1559                            of the ip now to make the failed connection cache
1560                            work */
1561                         for ( i=0; i<iplist_size; i++ ) {
1562                                 char addr[INET6_ADDRSTRLEN];
1563                                 print_sockaddr(addr, sizeof(addr),
1564                                                 &ip_list[i].ss);
1565                                 add_one_dc_unique(mem_ctx,
1566                                                 domain->name,
1567                                                 addr,
1568                                                 &ip_list[i].ss,
1569                                                 dcs,
1570                                                 num_dcs);
1571                         }
1572
1573                         SAFE_FREE(ip_list);
1574                         TALLOC_FREE(sitename);
1575                         iplist_size = 0;
1576                 }
1577
1578                 /* Now we add DCs from the main AD DNS lookup. */
1579                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1580                         &iplist_size, True);
1581
1582                 for ( i=0; i<iplist_size; i++ ) {
1583                         char addr[INET6_ADDRSTRLEN];
1584                         print_sockaddr(addr, sizeof(addr),
1585                                         &ip_list[i].ss);
1586                         add_one_dc_unique(mem_ctx,
1587                                         domain->name,
1588                                         addr,
1589                                         &ip_list[i].ss,
1590                                         dcs,
1591                                         num_dcs);
1592                 }
1593
1594                 SAFE_FREE(ip_list);
1595                 iplist_size = 0;
1596         }
1597
1598         /* Try standard netbios queries if no ADS and fall back to DNS queries
1599          * if alt_name is available */
1600         if (*num_dcs == 0) {
1601                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1602                        false);
1603                 if (iplist_size == 0) {
1604                         if (domain->alt_name != NULL) {
1605                                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1606                                        &iplist_size, true);
1607                         }
1608                 }
1609
1610                 for ( i=0; i<iplist_size; i++ ) {
1611                         char addr[INET6_ADDRSTRLEN];
1612                         print_sockaddr(addr, sizeof(addr),
1613                                         &ip_list[i].ss);
1614                         add_one_dc_unique(mem_ctx,
1615                                         domain->name,
1616                                         addr,
1617                                         &ip_list[i].ss,
1618                                         dcs,
1619                                         num_dcs);
1620                 }
1621
1622                 SAFE_FREE(ip_list);
1623                 iplist_size = 0;
1624         }
1625
1626         return True;
1627 }
1628
1629 /*******************************************************************
1630  Find and make a connection to a DC in the given domain.
1631
1632  @param[in] mem_ctx talloc memory context to allocate from
1633  @param[in] domain domain to find a dc in
1634  @param[out] dcname NetBIOS or FQDN of DC that's connected to
1635  @param[out] pss DC Internet address and port
1636  @param[out] fd fd of the open socket connected to the newly found dc
1637  @return true when a DC connection is made, false otherwise
1638 *******************************************************************/
1639
1640 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1641                         struct winbindd_domain *domain,
1642                         char **dcname, struct sockaddr_storage *pss, int *fd,
1643                         uint32_t request_flags)
1644 {
1645         struct dc_name_ip *dcs = NULL;
1646         int num_dcs = 0;
1647
1648         const char **dcnames = NULL;
1649         size_t num_dcnames = 0;
1650
1651         struct sockaddr_storage *addrs = NULL;
1652         int num_addrs = 0;
1653
1654         int i;
1655         size_t fd_index;
1656
1657         NTSTATUS status;
1658
1659         *fd = -1;
1660
1661  again:
1662         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1663                 return False;
1664
1665         for (i=0; i<num_dcs; i++) {
1666
1667                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1668                                     &dcnames, &num_dcnames)) {
1669                         return False;
1670                 }
1671                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1672                                       &addrs, &num_addrs)) {
1673                         return False;
1674                 }
1675         }
1676
1677         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1678                 return False;
1679
1680         if ((addrs == NULL) || (dcnames == NULL))
1681                 return False;
1682
1683         status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1684                                      num_addrs, 0, 10, fd, &fd_index, NULL);
1685         if (!NT_STATUS_IS_OK(status)) {
1686                 for (i=0; i<num_dcs; i++) {
1687                         char ab[INET6_ADDRSTRLEN];
1688                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1689                         DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1690                                 "domain %s address %s. Error was %s\n",
1691                                    domain->name, ab, nt_errstr(status) ));
1692                         winbind_add_failed_connection_entry(domain,
1693                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1694                 }
1695                 return False;
1696         }
1697
1698         *pss = addrs[fd_index];
1699
1700         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1701                 /* Ok, we've got a name for the DC */
1702                 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1703                 if (*dcname == NULL) {
1704                         return false;
1705                 }
1706                 return true;
1707         }
1708
1709         /* Try to figure out the name */
1710         if (dcip_check_name(mem_ctx, domain, pss, dcname, request_flags)) {
1711                 return True;
1712         }
1713
1714         /* We can not continue without the DC's name */
1715         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1716                                     NT_STATUS_UNSUCCESSFUL);
1717
1718         /* Throw away all arrays as we're doing this again. */
1719         TALLOC_FREE(dcs);
1720         num_dcs = 0;
1721
1722         TALLOC_FREE(dcnames);
1723         num_dcnames = 0;
1724
1725         TALLOC_FREE(addrs);
1726         num_addrs = 0;
1727
1728         close(*fd);
1729         *fd = -1;
1730
1731         goto again;
1732 }
1733
1734 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1735 {
1736         return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1737                                           domain_name);
1738 }
1739
1740 static void store_current_dc_in_gencache(const char *domain_name,
1741                                          const char *dc_name,
1742                                          struct cli_state *cli)
1743 {
1744         char addr[INET6_ADDRSTRLEN];
1745         char *key = NULL;
1746         char *value = NULL;
1747
1748         if (!cli_state_is_connected(cli)) {
1749                 return;
1750         }
1751
1752         print_sockaddr(addr, sizeof(addr),
1753                        smbXcli_conn_remote_sockaddr(cli->conn));
1754
1755         key = current_dc_key(talloc_tos(), domain_name);
1756         if (key == NULL) {
1757                 goto done;
1758         }
1759
1760         value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1761         if (value == NULL) {
1762                 goto done;
1763         }
1764
1765         gencache_set(key, value, 0x7fffffff);
1766 done:
1767         TALLOC_FREE(value);
1768         TALLOC_FREE(key);
1769 }
1770
1771 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1772                                     const char *domain_name,
1773                                     char **p_dc_name, char **p_dc_ip)
1774 {
1775         char *key, *p;
1776         char *value = NULL;
1777         bool ret = false;
1778         char *dc_name = NULL;
1779         char *dc_ip = NULL;
1780
1781         key = current_dc_key(talloc_tos(), domain_name);
1782         if (key == NULL) {
1783                 goto done;
1784         }
1785         if (!gencache_get(key, mem_ctx, &value, NULL)) {
1786                 goto done;
1787         }
1788         p = strchr(value, ' ');
1789         if (p == NULL) {
1790                 goto done;
1791         }
1792         dc_ip = talloc_strndup(mem_ctx, value, p - value);
1793         if (dc_ip == NULL) {
1794                 goto done;
1795         }
1796         dc_name = talloc_strdup(mem_ctx, p+1);
1797         if (dc_name == NULL) {
1798                 goto done;
1799         }
1800
1801         if (p_dc_ip != NULL) {
1802                 *p_dc_ip = dc_ip;
1803                 dc_ip = NULL;
1804         }
1805         if (p_dc_name != NULL) {
1806                 *p_dc_name = dc_name;
1807                 dc_name = NULL;
1808         }
1809         ret = true;
1810 done:
1811         TALLOC_FREE(dc_name);
1812         TALLOC_FREE(dc_ip);
1813         TALLOC_FREE(key);
1814         TALLOC_FREE(value);
1815         return ret;
1816 }
1817
1818 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1819                                const struct ndr_interface_table *table,
1820                                struct rpc_pipe_client **ret_pipe)
1821 {
1822         struct rpc_pipe_client *cli = NULL;
1823         const struct auth_session_info *session_info;
1824         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1825
1826
1827         session_info = get_session_info_system();
1828         SMB_ASSERT(session_info != NULL);
1829
1830         /* create a connection to the specified pipe */
1831         if (lp_parm_bool(-1, "winbindd", "use external pipes", false)) {
1832                 status = rpc_pipe_open_interface(mem_ctx,
1833                                                  table,
1834                                                  session_info,
1835                                                  NULL,
1836                                                  NULL,
1837                                                  server_messaging_context(),
1838                                                  &cli);
1839         } else {
1840                 status = rpc_pipe_open_internal(mem_ctx,
1841                                                 table,
1842                                                 session_info,
1843                                                 NULL,
1844                                                 NULL,
1845                                                 server_messaging_context(),
1846                                                 &cli);
1847         }
1848         if (!NT_STATUS_IS_OK(status)) {
1849                 DEBUG(0, ("open_internal_pipe: Could not connect to %s pipe: %s\n",
1850                           table->name, nt_errstr(status)));
1851                 return status;
1852         }
1853
1854         if (ret_pipe) {
1855                 *ret_pipe = cli;
1856         }
1857
1858         return NT_STATUS_OK;
1859 }
1860
1861 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1862                                    struct winbindd_cm_conn *new_conn,
1863                                    bool need_rw_dc)
1864 {
1865         TALLOC_CTX *mem_ctx;
1866         NTSTATUS result;
1867         char *saf_servername;
1868         int retries;
1869         uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1870
1871         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1872                 set_domain_offline(domain);
1873                 return NT_STATUS_NO_MEMORY;
1874         }
1875
1876         saf_servername = saf_fetch(mem_ctx, domain->name );
1877
1878         /* we have to check the server affinity cache here since 
1879            later we select a DC based on response time and not preference */
1880
1881         /* Check the negative connection cache
1882            before talking to it. It going down may have
1883            triggered the reconnection. */
1884
1885         if (saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, saf_servername))) {
1886                 struct sockaddr_storage ss;
1887                 char *dcname = NULL;
1888                 bool resolved = true;
1889
1890                 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1891                            saf_servername, domain->name));
1892
1893                 /* convert an ip address to a name */
1894                 if (is_ipaddress(saf_servername)) {
1895                         if (!interpret_string_addr(&ss, saf_servername,
1896                                                    AI_NUMERICHOST)) {
1897                                 TALLOC_FREE(mem_ctx);
1898                                 return NT_STATUS_UNSUCCESSFUL;
1899                         }
1900                 } else {
1901                         if (!resolve_name(saf_servername, &ss, 0x20, true)) {
1902                                 resolved = false;
1903                         }
1904                 }
1905
1906                 if (resolved && dcip_check_name(mem_ctx, domain, &ss, &dcname, request_flags)) {
1907                         domain->dcname = talloc_strdup(domain,
1908                                                        dcname);
1909                         if (domain->dcname == NULL) {
1910                                 TALLOC_FREE(mem_ctx);
1911                                 return NT_STATUS_NO_MEMORY;
1912                         }
1913
1914                         domain->dcaddr = ss;
1915                 } else {
1916                         winbind_add_failed_connection_entry(domain, saf_servername,
1917                                                             NT_STATUS_UNSUCCESSFUL);
1918                 }
1919         }
1920
1921         for (retries = 0; retries < 3; retries++) {
1922                 int fd = -1;
1923                 bool retry = False;
1924                 char *dcname = NULL;
1925
1926                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1927
1928                 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1929                            domain->dcname ? domain->dcname : "", domain->name));
1930
1931                 if (domain->dcname != NULL &&
1932                     NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
1933                                                               domain->dcname)))
1934                 {
1935                         NTSTATUS status;
1936
1937                         status = smbsock_connect(&domain->dcaddr, 0,
1938                                                  NULL, -1, NULL, -1,
1939                                                  &fd, NULL, 10);
1940                         if (!NT_STATUS_IS_OK(status)) {
1941                                 fd = -1;
1942                         }
1943                 }
1944
1945                 if ((fd == -1) &&
1946                     !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd, request_flags))
1947                 {
1948                         /* This is the one place where we will
1949                            set the global winbindd offline state
1950                            to true, if a "WINBINDD_OFFLINE" entry
1951                            is found in the winbindd cache. */
1952                         set_global_winbindd_state_offline();
1953                         break;
1954                 }
1955                 if (dcname != NULL) {
1956                         talloc_free(domain->dcname);
1957
1958                         domain->dcname = talloc_move(domain, &dcname);
1959                         if (domain->dcname == NULL) {
1960                                 result = NT_STATUS_NO_MEMORY;
1961                                 break;
1962                         }
1963                 }
1964
1965                 new_conn->cli = NULL;
1966
1967                 result = cm_prepare_connection(domain, fd, domain->dcname,
1968                         &new_conn->cli, &retry);
1969                 if (!NT_STATUS_IS_OK(result)) {
1970                         /* Don't leak the smb connection socket */
1971                         close(fd);
1972                 }
1973
1974                 if (!retry)
1975                         break;
1976         }
1977
1978         if (NT_STATUS_IS_OK(result)) {
1979                 bool seal_pipes = true;
1980
1981                 winbindd_set_locator_kdc_envs(domain);
1982
1983                 if (domain->online == False) {
1984                         /* We're changing state from offline to online. */
1985                         set_global_winbindd_state_online();
1986                 }
1987                 set_domain_online(domain);
1988
1989                 /*
1990                  * Much as I hate global state, this seems to be the point
1991                  * where we can be certain that we have a proper connection to
1992                  * a DC. wbinfo --dc-info needs that information, store it in
1993                  * gencache with a looong timeout. This will need revisiting
1994                  * once we start to connect to multiple DCs, wbcDcInfo is
1995                  * already prepared for that.
1996                  */
1997                 store_current_dc_in_gencache(domain->name, domain->dcname,
1998                                              new_conn->cli);
1999
2000                 seal_pipes = lp_winbind_sealed_pipes();
2001                 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
2002                                           domain->name,
2003                                           seal_pipes);
2004
2005                 if (seal_pipes) {
2006                         new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2007                 } else {
2008                         new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
2009                 }
2010         } else {
2011                 /* Ensure we setup the retry handler. */
2012                 set_domain_offline(domain);
2013         }
2014
2015         talloc_destroy(mem_ctx);
2016         return result;
2017 }
2018
2019 /* Close down all open pipes on a connection. */
2020
2021 void invalidate_cm_connection(struct winbindd_domain *domain)
2022 {
2023         NTSTATUS result;
2024         struct winbindd_cm_conn *conn = &domain->conn;
2025
2026         /* We're closing down a possibly dead
2027            connection. Don't have impossibly long (10s) timeouts. */
2028
2029         if (conn->cli) {
2030                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
2031         }
2032
2033         if (conn->samr_pipe != NULL) {
2034                 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
2035                         dcerpc_samr_Close(conn->samr_pipe->binding_handle,
2036                                           talloc_tos(),
2037                                           &conn->sam_connect_handle,
2038                                           &result);
2039                 }
2040                 TALLOC_FREE(conn->samr_pipe);
2041                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2042                 if (conn->cli) {
2043                         cli_set_timeout(conn->cli, 500);
2044                 }
2045         }
2046
2047         if (conn->lsa_pipe != NULL) {
2048                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2049                         dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
2050                                          talloc_tos(),
2051                                          &conn->lsa_policy,
2052                                          &result);
2053                 }
2054                 TALLOC_FREE(conn->lsa_pipe);
2055                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2056                 if (conn->cli) {
2057                         cli_set_timeout(conn->cli, 500);
2058                 }
2059         }
2060
2061         if (conn->lsa_pipe_tcp != NULL) {
2062                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2063                         dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
2064                                          talloc_tos(),
2065                                          &conn->lsa_policy,
2066                                          &result);
2067                 }
2068                 TALLOC_FREE(conn->lsa_pipe_tcp);
2069                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2070                 if (conn->cli) {
2071                         cli_set_timeout(conn->cli, 500);
2072                 }
2073         }
2074
2075         if (conn->netlogon_pipe != NULL) {
2076                 TALLOC_FREE(conn->netlogon_pipe);
2077                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2078                 if (conn->cli) {
2079                         cli_set_timeout(conn->cli, 500);
2080                 }
2081         }
2082
2083         conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2084         conn->netlogon_force_reauth = false;
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         if (!NT_STATUS_IS_OK(result)) {
3372                 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3373                           nt_errstr(result));
3374                 return result;
3375         }
3376
3377         *cli = conn->netlogon_pipe;
3378         return NT_STATUS_OK;
3379 }
3380
3381 /****************************************************************************
3382 Open a NETLOGON connection to a DC, suiteable for SamLogon calls.
3383 ****************************************************************************/
3384
3385 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3386                              struct rpc_pipe_client **cli)
3387 {
3388         NTSTATUS status;
3389
3390         status = init_dc_connection_rpc(domain, domain->rodc);
3391         if (!NT_STATUS_IS_OK(status)) {
3392                 return status;
3393         }
3394
3395         if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3396                 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3397                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3398                     NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3399                     NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3400                         invalidate_cm_connection(domain);
3401                         status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3402                 }
3403                 if (NT_STATUS_IS_OK(status)) {
3404                         return status;
3405                 }
3406
3407                 /*
3408                  * we tried twice to connect via ncan_ip_tcp and schannel and
3409                  * failed - maybe it is a trusted domain we can't connect to ?
3410                  * do not try tcp next time - gd
3411                  *
3412                  * This also prevents LSA over TCP
3413                  */
3414                 domain->can_do_ncacn_ip_tcp = false;
3415         }
3416
3417         status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3418         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3419                 /*
3420                  * SMB2 session expired, needs reauthentication. Drop
3421                  * connection and retry.
3422                  */
3423                 invalidate_cm_connection(domain);
3424                 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3425         }
3426
3427         return status;
3428 }
3429
3430 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3431                                     struct rpc_pipe_client **cli,
3432                                     struct netlogon_creds_cli_context **ppdc)
3433 {
3434         NTSTATUS status;
3435
3436         if (domain->secure_channel_type == SEC_CHAN_NULL) {
3437                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3438         }
3439
3440         status = cm_connect_netlogon(domain, cli);
3441         if (!NT_STATUS_IS_OK(status)) {
3442                 return status;
3443         }
3444
3445         if (domain->conn.netlogon_creds_ctx == NULL) {
3446                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3447         }
3448
3449         *ppdc = domain->conn.netlogon_creds_ctx;
3450         return NT_STATUS_OK;
3451 }
3452
3453 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3454                             void *private_data,
3455                             uint32_t msg_type,
3456                             struct server_id server_id,
3457                             DATA_BLOB *data)
3458 {
3459         struct winbindd_domain *domain;
3460         char *freeit = NULL;
3461         char *addr;
3462
3463         if ((data == NULL)
3464             || (data->data == NULL)
3465             || (data->length == 0)
3466             || (data->data[data->length-1] != '\0')) {
3467                 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3468                           "string\n"));
3469                 return;
3470         }
3471
3472         addr = (char *)data->data;
3473         DEBUG(10, ("IP %s dropped\n", addr));
3474
3475         if (!is_ipaddress(addr)) {
3476                 char *slash;
3477                 /*
3478                  * Some code sends us ip addresses with the /netmask
3479                  * suffix
3480                  */
3481                 slash = strchr(addr, '/');
3482                 if (slash == NULL) {
3483                         DEBUG(1, ("invalid msg_ip_dropped message: %s",
3484                                   addr));
3485                         return;
3486                 }
3487                 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3488                 if (freeit == NULL) {
3489                         DEBUG(1, ("talloc failed\n"));
3490                         return;
3491                 }
3492                 addr = freeit;
3493                 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3494         }
3495
3496         for (domain = domain_list(); domain != NULL; domain = domain->next) {
3497                 char sockaddr[INET6_ADDRSTRLEN];
3498
3499                 if (!cli_state_is_connected(domain->conn.cli)) {
3500                         continue;
3501                 }
3502
3503                 print_sockaddr(sockaddr, sizeof(sockaddr),
3504                                smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3505
3506                 if (strequal(sockaddr, addr)) {
3507                         smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3508                 }
3509         }
3510         TALLOC_FREE(freeit);
3511 }
3512
3513 void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx,
3514                                void *private_data,
3515                                uint32_t msg_type,
3516                                struct server_id server_id,
3517                                DATA_BLOB *data)
3518 {
3519         struct winbindd_domain *domain;
3520
3521         for (domain = domain_list(); domain; domain = domain->next) {
3522                 if (domain->internal) {
3523                         continue;
3524                 }
3525                 invalidate_cm_connection(domain);
3526         }
3527 }