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