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