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