rpc_client3: Avoid "cli_credentials" in cli_rpc_pipe_open_schannel_with_creds
[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, controller,
1034                                 smb_sign_client_connections, flags);
1035         if (*cli == NULL) {
1036                 close(sockfd);
1037                 DEBUG(1, ("Could not cli_initialize\n"));
1038                 result = NT_STATUS_NO_MEMORY;
1039                 goto done;
1040         }
1041
1042         cli_set_timeout(*cli, 10000); /* 10 seconds */
1043
1044         set_socket_options(sockfd, lp_socket_options());
1045
1046         result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
1047                                  lp_client_ipc_min_protocol(),
1048                                  lp_client_ipc_max_protocol());
1049
1050         if (!NT_STATUS_IS_OK(result)) {
1051                 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
1052                 goto done;
1053         }
1054
1055         if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
1056             smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
1057                 try_ipc_auth = true;
1058         } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1059                 try_ipc_auth = true;
1060         } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1061                 /*
1062                  * If we are forcing on SMB signing, then we must
1063                  * require authentication unless this is a one-way
1064                  * trust, and we have no stored user/password
1065                  */
1066                 try_ipc_auth = true;
1067         }
1068
1069         if (try_ipc_auth) {
1070                 result = get_trust_credentials(domain, talloc_tos(), false, &creds);
1071                 if (!NT_STATUS_IS_OK(result)) {
1072                         DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
1073                                   domain->name, nt_errstr(result)));
1074                         goto done;
1075                 }
1076         } else {
1077                 /*
1078                  * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
1079                  * would try and authentication with our machine
1080                  * account password and fail.  This is very rare in
1081                  * the modern world however
1082                  */
1083                 creds = cli_credentials_init_anon(talloc_tos());
1084                 if (creds == NULL) {
1085                         result = NT_STATUS_NO_MEMORY;
1086                         DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
1087                                   domain->name, nt_errstr(result)));
1088                         goto done;
1089                 }
1090         }
1091
1092         machine_principal = cli_credentials_get_principal(creds,
1093                                                         talloc_tos());
1094         machine_realm = cli_credentials_get_realm(creds);
1095         machine_account = cli_credentials_get_username(creds);
1096         machine_domain = cli_credentials_get_domain(creds);
1097
1098         DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
1099                   "[%s] and realm [%s]\n",
1100                   controller, domain->name, domain->alt_name,
1101                   machine_domain, machine_account,
1102                   machine_principal, machine_realm));
1103
1104         if (cli_credentials_is_anonymous(creds)) {
1105                 goto anon_fallback;
1106         }
1107
1108         winbindd_set_locator_kdc_envs(domain);
1109
1110         result = cli_session_setup_creds(*cli, creds);
1111         if (NT_STATUS_IS_OK(result)) {
1112                 goto session_setup_done;
1113         }
1114
1115         DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1116                   controller,
1117                   cli_credentials_get_unparsed_name(creds, talloc_tos()),
1118                   nt_errstr(result)));
1119
1120         /*
1121          * If we are not going to validiate the conneciton
1122          * with SMB signing, then allow us to fall back to
1123          * anonymous
1124          */
1125         if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1126             || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1127             || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1128             || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1129             || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1130         {
1131                 if (!cm_is_ipc_credentials(creds)) {
1132                         goto ipc_fallback;
1133                 }
1134
1135                 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1136                         goto done;
1137                 }
1138
1139                 goto anon_fallback;
1140         }
1141
1142         goto done;
1143
1144  ipc_fallback:
1145         TALLOC_FREE(creds);
1146         tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
1147         if (!NT_STATUS_IS_OK(tmp_status)) {
1148                 result = tmp_status;
1149                 goto done;
1150         }
1151
1152         if (cli_credentials_is_anonymous(creds)) {
1153                 goto anon_fallback;
1154         }
1155
1156         machine_account = cli_credentials_get_username(creds);
1157         machine_domain = cli_credentials_get_domain(creds);
1158
1159         DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
1160                   "[%s]\\[%s]\n",  controller, lp_netbios_name(),
1161                   machine_domain, machine_account));
1162
1163         result = cli_session_setup_creds(*cli, creds);
1164         if (NT_STATUS_IS_OK(result)) {
1165                 goto session_setup_done;
1166         }
1167
1168         DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
1169                   controller,
1170                   cli_credentials_get_unparsed_name(creds, talloc_tos()),
1171                   nt_errstr(result)));
1172
1173         /*
1174          * If we are not going to validiate the conneciton
1175          * with SMB signing, then allow us to fall back to
1176          * anonymous
1177          */
1178         if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
1179             || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
1180             || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
1181             || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
1182             || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
1183         {
1184                 goto anon_fallback;
1185         }
1186
1187         goto done;
1188
1189  anon_fallback:
1190         TALLOC_FREE(creds);
1191
1192         if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
1193                 goto done;
1194         }
1195
1196         /* Fall back to anonymous connection, this might fail later */
1197         DEBUG(5,("cm_prepare_connection: falling back to anonymous "
1198                 "connection for DC %s\n",
1199                 controller ));
1200
1201         result = cli_session_setup_anon(*cli);
1202         if (NT_STATUS_IS_OK(result)) {
1203                 DEBUG(5, ("Connected anonymously\n"));
1204                 goto session_setup_done;
1205         }
1206
1207         DEBUG(1, ("anonymous session setup to %s failed with %s\n",
1208                   controller, nt_errstr(result)));
1209
1210         /* We can't session setup */
1211         goto done;
1212
1213  session_setup_done:
1214         TALLOC_FREE(creds);
1215
1216         /*
1217          * This should be a short term hack until
1218          * dynamic re-authentication is implemented.
1219          *
1220          * See Bug 9175 - winbindd doesn't recover from
1221          * NT_STATUS_NETWORK_SESSION_EXPIRED
1222          */
1223         if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1224                 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1225         }
1226
1227         result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
1228         if (!NT_STATUS_IS_OK(result)) {
1229                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1230                 goto done;
1231         }
1232         tcon_status = result;
1233
1234         /* cache the server name for later connections */
1235
1236         saf_store(domain->name, controller);
1237         if (domain->alt_name) {
1238                 saf_store(domain->alt_name, controller);
1239         }
1240
1241         winbindd_set_locator_kdc_envs(domain);
1242
1243         TALLOC_FREE(mutex);
1244         *retry = False;
1245
1246         result = NT_STATUS_OK;
1247
1248  done:
1249         TALLOC_FREE(mutex);
1250         TALLOC_FREE(creds);
1251
1252         if (NT_STATUS_IS_OK(result)) {
1253                 result = tcon_status;
1254         }
1255
1256         if (!NT_STATUS_IS_OK(result)) {
1257                 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1258                           controller, nt_errstr(result)));
1259                 winbind_add_failed_connection_entry(domain, controller, result);
1260                 if ((*cli) != NULL) {
1261                         cli_shutdown(*cli);
1262                         *cli = NULL;
1263                 }
1264         }
1265
1266         return result;
1267 }
1268
1269 /*******************************************************************
1270  Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1271  array.
1272
1273  Keeps the list unique by not adding duplicate entries.
1274
1275  @param[in] mem_ctx talloc memory context to allocate from
1276  @param[in] domain_name domain of the DC
1277  @param[in] dcname name of the DC to add to the list
1278  @param[in] pss Internet address and port pair to add to the list
1279  @param[in,out] dcs array of dc_name_ip structures to add to
1280  @param[in,out] num_dcs number of dcs returned in the dcs array
1281  @return true if the list was added to, false otherwise
1282 *******************************************************************/
1283
1284 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1285                               const char *dcname, struct sockaddr_storage *pss,
1286                               struct dc_name_ip **dcs, int *num)
1287 {
1288         int i = 0;
1289
1290         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1291                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1292                 return False;
1293         }
1294
1295         /* Make sure there's no duplicates in the list */
1296         for (i=0; i<*num; i++)
1297                 if (sockaddr_equal(
1298                             (struct sockaddr *)(void *)&(*dcs)[i].ss,
1299                             (struct sockaddr *)(void *)pss))
1300                         return False;
1301
1302         *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1303
1304         if (*dcs == NULL)
1305                 return False;
1306
1307         fstrcpy((*dcs)[*num].name, dcname);
1308         (*dcs)[*num].ss = *pss;
1309         *num += 1;
1310         return True;
1311 }
1312
1313 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1314                                   struct sockaddr_storage *pss, uint16_t port,
1315                                   struct sockaddr_storage **addrs, int *num)
1316 {
1317         *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1318
1319         if (*addrs == NULL) {
1320                 *num = 0;
1321                 return False;
1322         }
1323
1324         (*addrs)[*num] = *pss;
1325         set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1326
1327         *num += 1;
1328         return True;
1329 }
1330
1331 /*******************************************************************
1332  convert an ip to a name
1333  For an AD Domain, it checks the requirements of the request flags.
1334 *******************************************************************/
1335
1336 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1337                             const struct winbindd_domain *domain,
1338                             struct sockaddr_storage *pss,
1339                             char **name, uint32_t request_flags)
1340 {
1341         struct ip_service ip_list;
1342         uint32_t nt_version = NETLOGON_NT_VERSION_1;
1343         NTSTATUS status;
1344         const char *dc_name;
1345         fstring nbtname;
1346 #ifdef HAVE_ADS
1347         bool is_ad_domain = false;
1348 #endif
1349         ip_list.ss = *pss;
1350         ip_list.port = 0;
1351
1352 #ifdef HAVE_ADS
1353         /* For active directory servers, try to get the ldap server name.
1354            None of these failures should be considered critical for now */
1355
1356         if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1357                 is_ad_domain = true;
1358         } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1359                 is_ad_domain = domain->active_directory;
1360         }
1361
1362         if (is_ad_domain) {
1363                 ADS_STRUCT *ads;
1364                 ADS_STATUS ads_status;
1365                 char addr[INET6_ADDRSTRLEN];
1366
1367                 print_sockaddr(addr, sizeof(addr), pss);
1368
1369                 ads = ads_init(domain->alt_name, domain->name, addr);
1370                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1371                 ads->config.flags |= request_flags;
1372                 ads->server.no_fallback = true;
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                                    bool need_rw_dc)
1819 {
1820         TALLOC_CTX *mem_ctx;
1821         NTSTATUS result;
1822         char *saf_servername;
1823         int retries;
1824         uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1825
1826         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1827                 set_domain_offline(domain);
1828                 return NT_STATUS_NO_MEMORY;
1829         }
1830
1831         saf_servername = saf_fetch(mem_ctx, domain->name );
1832
1833         /* we have to check the server affinity cache here since 
1834            later we select a DC based on response time and not preference */
1835
1836         /* Check the negative connection cache
1837            before talking to it. It going down may have
1838            triggered the reconnection. */
1839
1840         if (saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, saf_servername))) {
1841                 struct sockaddr_storage ss;
1842                 char *dcname = NULL;
1843                 bool resolved = true;
1844
1845                 DEBUG(10, ("cm_open_connection: saf_servername is '%s' for domain %s\n",
1846                            saf_servername, domain->name));
1847
1848                 /* convert an ip address to a name */
1849                 if (is_ipaddress(saf_servername)) {
1850                         if (!interpret_string_addr(&ss, saf_servername,
1851                                                    AI_NUMERICHOST)) {
1852                                 TALLOC_FREE(mem_ctx);
1853                                 return NT_STATUS_UNSUCCESSFUL;
1854                         }
1855                 } else {
1856                         if (!resolve_name(saf_servername, &ss, 0x20, true)) {
1857                                 resolved = false;
1858                         }
1859                 }
1860
1861                 if (resolved && dcip_check_name(mem_ctx, domain, &ss, &dcname, request_flags)) {
1862                         domain->dcname = talloc_strdup(domain,
1863                                                        dcname);
1864                         if (domain->dcname == NULL) {
1865                                 TALLOC_FREE(mem_ctx);
1866                                 return NT_STATUS_NO_MEMORY;
1867                         }
1868
1869                         domain->dcaddr = ss;
1870                 } else {
1871                         winbind_add_failed_connection_entry(domain, saf_servername,
1872                                                             NT_STATUS_UNSUCCESSFUL);
1873                 }
1874         }
1875
1876         for (retries = 0; retries < 3; retries++) {
1877                 int fd = -1;
1878                 bool retry = False;
1879                 char *dcname = NULL;
1880
1881                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1882
1883                 DEBUG(10, ("cm_open_connection: dcname is '%s' for domain %s\n",
1884                            domain->dcname ? domain->dcname : "", domain->name));
1885
1886                 if (domain->dcname != NULL &&
1887                     NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
1888                                                               domain->dcname)))
1889                 {
1890                         NTSTATUS status;
1891
1892                         status = smbsock_connect(&domain->dcaddr, 0,
1893                                                  NULL, -1, NULL, -1,
1894                                                  &fd, NULL, 10);
1895                         if (!NT_STATUS_IS_OK(status)) {
1896                                 fd = -1;
1897                         }
1898                 }
1899
1900                 if ((fd == -1) &&
1901                     !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd, request_flags))
1902                 {
1903                         /* This is the one place where we will
1904                            set the global winbindd offline state
1905                            to true, if a "WINBINDD_OFFLINE" entry
1906                            is found in the winbindd cache. */
1907                         set_global_winbindd_state_offline();
1908                         break;
1909                 }
1910                 if (dcname != NULL) {
1911                         talloc_free(domain->dcname);
1912
1913                         domain->dcname = talloc_move(domain, &dcname);
1914                         if (domain->dcname == NULL) {
1915                                 result = NT_STATUS_NO_MEMORY;
1916                                 break;
1917                         }
1918                 }
1919
1920                 new_conn->cli = NULL;
1921
1922                 result = cm_prepare_connection(domain, fd, domain->dcname,
1923                         &new_conn->cli, &retry);
1924                 if (!NT_STATUS_IS_OK(result)) {
1925                         /* Don't leak the smb connection socket */
1926                         close(fd);
1927                 }
1928
1929                 if (!retry)
1930                         break;
1931         }
1932
1933         if (NT_STATUS_IS_OK(result)) {
1934                 bool seal_pipes = true;
1935
1936                 winbindd_set_locator_kdc_envs(domain);
1937
1938                 if (domain->online == False) {
1939                         /* We're changing state from offline to online. */
1940                         set_global_winbindd_state_online();
1941                 }
1942                 set_domain_online(domain);
1943
1944                 /*
1945                  * Much as I hate global state, this seems to be the point
1946                  * where we can be certain that we have a proper connection to
1947                  * a DC. wbinfo --dc-info needs that information, store it in
1948                  * gencache with a looong timeout. This will need revisiting
1949                  * once we start to connect to multiple DCs, wbcDcInfo is
1950                  * already prepared for that.
1951                  */
1952                 store_current_dc_in_gencache(domain->name, domain->dcname,
1953                                              new_conn->cli);
1954
1955                 seal_pipes = lp_winbind_sealed_pipes();
1956                 seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1957                                           domain->name,
1958                                           seal_pipes);
1959
1960                 if (seal_pipes) {
1961                         new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1962                 } else {
1963                         new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1964                 }
1965         } else {
1966                 /* Ensure we setup the retry handler. */
1967                 set_domain_offline(domain);
1968         }
1969
1970         talloc_destroy(mem_ctx);
1971         return result;
1972 }
1973
1974 /* Close down all open pipes on a connection. */
1975
1976 void invalidate_cm_connection(struct winbindd_domain *domain)
1977 {
1978         NTSTATUS result;
1979         struct winbindd_cm_conn *conn = &domain->conn;
1980
1981         /* We're closing down a possibly dead
1982            connection. Don't have impossibly long (10s) timeouts. */
1983
1984         if (conn->cli) {
1985                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1986         }
1987
1988         if (conn->samr_pipe != NULL) {
1989                 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1990                         dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1991                                           talloc_tos(),
1992                                           &conn->sam_connect_handle,
1993                                           &result);
1994                 }
1995                 TALLOC_FREE(conn->samr_pipe);
1996                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1997                 if (conn->cli) {
1998                         cli_set_timeout(conn->cli, 500);
1999                 }
2000         }
2001
2002         if (conn->lsa_pipe != NULL) {
2003                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2004                         dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
2005                                          talloc_tos(),
2006                                          &conn->lsa_policy,
2007                                          &result);
2008                 }
2009                 TALLOC_FREE(conn->lsa_pipe);
2010                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2011                 if (conn->cli) {
2012                         cli_set_timeout(conn->cli, 500);
2013                 }
2014         }
2015
2016         if (conn->lsa_pipe_tcp != NULL) {
2017                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
2018                         dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
2019                                          talloc_tos(),
2020                                          &conn->lsa_policy,
2021                                          &result);
2022                 }
2023                 TALLOC_FREE(conn->lsa_pipe_tcp);
2024                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2025                 if (conn->cli) {
2026                         cli_set_timeout(conn->cli, 500);
2027                 }
2028         }
2029
2030         if (conn->netlogon_pipe != NULL) {
2031                 TALLOC_FREE(conn->netlogon_pipe);
2032                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
2033                 if (conn->cli) {
2034                         cli_set_timeout(conn->cli, 500);
2035                 }
2036         }
2037
2038         conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2039         conn->netlogon_force_reauth = false;
2040         conn->netlogon_flags = 0;
2041         TALLOC_FREE(conn->netlogon_creds_ctx);
2042
2043         if (conn->cli) {
2044                 cli_shutdown(conn->cli);
2045         }
2046
2047         conn->cli = NULL;
2048 }
2049
2050 void close_conns_after_fork(void)
2051 {
2052         struct winbindd_domain *domain;
2053         struct winbindd_cli_state *cli_state;
2054
2055         for (domain = domain_list(); domain; domain = domain->next) {
2056                 /*
2057                  * first close the low level SMB TCP connection
2058                  * so that we don't generate any SMBclose
2059                  * requests in invalidate_cm_connection()
2060                  */
2061                 if (cli_state_is_connected(domain->conn.cli)) {
2062                         smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2063                 }
2064
2065                 invalidate_cm_connection(domain);
2066         }
2067
2068         for (cli_state = winbindd_client_list();
2069              cli_state != NULL;
2070              cli_state = cli_state->next) {
2071                 if (cli_state->sock >= 0) {
2072                         close(cli_state->sock);
2073                         cli_state->sock = -1;
2074                 }
2075         }
2076 }
2077
2078 static bool connection_ok(struct winbindd_domain *domain)
2079 {
2080         bool ok;
2081
2082         ok = cli_state_is_connected(domain->conn.cli);
2083         if (!ok) {
2084                 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
2085                           domain->dcname, domain->name));
2086                 return False;
2087         }
2088
2089         if (domain->online == False) {
2090                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
2091                 return False;
2092         }
2093
2094         return True;
2095 }
2096
2097 /* Initialize a new connection up to the RPC BIND.
2098    Bypass online status check so always does network calls. */
2099
2100 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
2101 {
2102         NTSTATUS result;
2103         bool skip_connection = domain->internal;
2104         if (need_rw_dc && domain->rodc) {
2105                 skip_connection = false;
2106         }
2107
2108         /* Internal connections never use the network. */
2109         if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2110                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2111         }
2112
2113         /* Still ask the internal LSA and SAMR server about the local domain */
2114         if (skip_connection || connection_ok(domain)) {
2115                 if (!domain->initialized) {
2116                         set_dc_type_and_flags(domain);
2117                 }
2118                 return NT_STATUS_OK;
2119         }
2120
2121         invalidate_cm_connection(domain);
2122
2123         if (!domain->primary && !domain->initialized) {
2124                 /*
2125                  * Before we connect to a trust, work out if it is an
2126                  * AD domain by asking our own domain.
2127                  */
2128                 set_dc_type_and_flags_trustinfo(domain);
2129         }
2130
2131         result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2132
2133         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2134                 set_dc_type_and_flags(domain);
2135         }
2136
2137         return result;
2138 }
2139
2140 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2141 {
2142         if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2143                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2144         }
2145
2146         if (domain->initialized && !domain->online) {
2147                 /* We check for online status elsewhere. */
2148                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2149         }
2150
2151         return init_dc_connection_network(domain, need_rw_dc);
2152 }
2153
2154 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2155 {
2156         NTSTATUS status;
2157
2158         status = init_dc_connection(domain, need_rw_dc);
2159         if (!NT_STATUS_IS_OK(status)) {
2160                 return status;
2161         }
2162
2163         if (!domain->internal && domain->conn.cli == NULL) {
2164                 /* happens for trusted domains without inbound trust */
2165                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2166         }
2167
2168         return NT_STATUS_OK;
2169 }
2170
2171 /******************************************************************************
2172  Set the trust flags (direction and forest location) for a domain
2173 ******************************************************************************/
2174
2175 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2176 {
2177         struct winbindd_domain *our_domain;
2178         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2179         WERROR werr;
2180         struct netr_DomainTrustList trusts;
2181         int i;
2182         uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2183                         NETR_TRUST_FLAG_OUTBOUND |
2184                         NETR_TRUST_FLAG_INBOUND);
2185         struct rpc_pipe_client *cli;
2186         TALLOC_CTX *mem_ctx = NULL;
2187         struct dcerpc_binding_handle *b;
2188
2189         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2190
2191         /* Our primary domain doesn't need to worry about trust flags.
2192            Force it to go through the network setup */
2193         if ( domain->primary ) {                
2194                 return False;           
2195         }
2196
2197         mem_ctx = talloc_stackframe();
2198         our_domain = find_our_domain();
2199         if (our_domain->internal) {
2200                 result = init_dc_connection(our_domain, false);
2201                 if (!NT_STATUS_IS_OK(result)) {
2202                         DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2203                                  "Not able to make a connection to our domain: %s\n",
2204                                   nt_errstr(result)));
2205                         TALLOC_FREE(mem_ctx);
2206                         return false;
2207                 }
2208         }
2209
2210         /* This won't work unless our domain is AD */
2211         if ( !our_domain->active_directory ) {
2212                 TALLOC_FREE(mem_ctx);
2213                 return False;
2214         }
2215
2216         if (our_domain->internal) {
2217                 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2218         } else if (!connection_ok(our_domain)) {
2219                 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2220                          "No connection to our domain!\n"));
2221                 TALLOC_FREE(mem_ctx);
2222                 return False;
2223         } else {
2224                 result = cm_connect_netlogon(our_domain, &cli);
2225         }
2226
2227         if (!NT_STATUS_IS_OK(result)) {
2228                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2229                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
2230                           domain->name, nt_errstr(result)));
2231                 TALLOC_FREE(mem_ctx);
2232                 return False;
2233         }
2234         b = cli->binding_handle;
2235
2236         /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2237         result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2238                                                       cli->desthost,
2239                                                       flags,
2240                                                       &trusts,
2241                                                       &werr);
2242         if (!NT_STATUS_IS_OK(result)) {
2243                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2244                         "failed to query trusted domain list: %s\n",
2245                         nt_errstr(result)));
2246                 TALLOC_FREE(mem_ctx);
2247                 return false;
2248         }
2249         if (!W_ERROR_IS_OK(werr)) {
2250                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2251                         "failed to query trusted domain list: %s\n",
2252                         win_errstr(werr)));
2253                 TALLOC_FREE(mem_ctx);
2254                 return false;
2255         }
2256
2257         /* Now find the domain name and get the flags */
2258
2259         for ( i=0; i<trusts.count; i++ ) {
2260                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2261                         domain->domain_flags          = trusts.array[i].trust_flags;
2262                         domain->domain_type           = trusts.array[i].trust_type;
2263                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
2264
2265                         if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2266                                 domain->active_directory = True;
2267
2268                         /* This flag is only set if the domain is *our* 
2269                            primary domain and the primary domain is in
2270                            native mode */
2271
2272                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2273
2274                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2275                                   "native mode.\n", domain->name, 
2276                                   domain->native_mode ? "" : "NOT "));
2277
2278                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2279                                  "running active directory.\n", domain->name, 
2280                                  domain->active_directory ? "" : "NOT "));
2281
2282                         domain->can_do_ncacn_ip_tcp = domain->active_directory;
2283
2284                         domain->initialized = True;
2285
2286                         break;
2287                 }               
2288         }
2289
2290         TALLOC_FREE(mem_ctx);
2291
2292         return domain->initialized;     
2293 }
2294
2295 /******************************************************************************
2296  We can 'sense' certain things about the DC by it's replies to certain
2297  questions.
2298
2299  This tells us if this particular remote server is Active Directory, and if it
2300  is native mode.
2301 ******************************************************************************/
2302
2303 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2304 {
2305         NTSTATUS status, result;
2306         WERROR werr;
2307         TALLOC_CTX              *mem_ctx = NULL;
2308         struct rpc_pipe_client  *cli = NULL;
2309         struct policy_handle pol;
2310         union dssetup_DsRoleInfo info;
2311         union lsa_PolicyInformation *lsa_info = NULL;
2312
2313         if (!domain->internal && !connection_ok(domain)) {
2314                 return;
2315         }
2316
2317         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2318                               domain->name);
2319         if (!mem_ctx) {
2320                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2321                 return;
2322         }
2323
2324         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2325
2326         if (domain->internal) {
2327                 status = wb_open_internal_pipe(mem_ctx,
2328                                                &ndr_table_dssetup,
2329                                                &cli);
2330         } else {
2331                 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2332                                                   &ndr_table_dssetup,
2333                                                   &cli);
2334         }
2335
2336         if (!NT_STATUS_IS_OK(status)) {
2337                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2338                           "PI_DSSETUP on domain %s: (%s)\n",
2339                           domain->name, nt_errstr(status)));
2340
2341                 /* if this is just a non-AD domain we need to continue
2342                  * identifying so that we can in the end return with
2343                  * domain->initialized = True - gd */
2344
2345                 goto no_dssetup;
2346         }
2347
2348         status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2349                                                                   DS_ROLE_BASIC_INFORMATION,
2350                                                                   &info,
2351                                                                   &werr);
2352         TALLOC_FREE(cli);
2353
2354         if (NT_STATUS_IS_OK(status)) {
2355                 result = werror_to_ntstatus(werr);
2356         }
2357         if (!NT_STATUS_IS_OK(status)) {
2358                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2359                           "on domain %s failed: (%s)\n",
2360                           domain->name, nt_errstr(status)));
2361
2362                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2363                  * every opcode on the DSSETUP pipe, continue with
2364                  * no_dssetup mode here as well to get domain->initialized
2365                  * set - gd */
2366
2367                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2368                         goto no_dssetup;
2369                 }
2370
2371                 TALLOC_FREE(mem_ctx);
2372                 return;
2373         }
2374
2375         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2376             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2377                 domain->native_mode = True;
2378         } else {
2379                 domain->native_mode = False;
2380         }
2381
2382 no_dssetup:
2383         if (domain->internal) {
2384                 status = wb_open_internal_pipe(mem_ctx,
2385                                                &ndr_table_lsarpc,
2386                                                &cli);
2387         } else {
2388                 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2389                                                   &ndr_table_lsarpc, &cli);
2390         }
2391         if (!NT_STATUS_IS_OK(status)) {
2392                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2393                           "PI_LSARPC on domain %s: (%s)\n",
2394                           domain->name, nt_errstr(status)));
2395                 TALLOC_FREE(cli);
2396                 TALLOC_FREE(mem_ctx);
2397                 return;
2398         }
2399
2400         status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2401                                          SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2402
2403         if (NT_STATUS_IS_OK(status)) {
2404                 /* This particular query is exactly what Win2k clients use 
2405                    to determine that the DC is active directory */
2406                 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2407                                                      &pol,
2408                                                      LSA_POLICY_INFO_DNS,
2409                                                      &lsa_info,
2410                                                      &result);
2411         }
2412
2413         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2414                 domain->active_directory = True;
2415
2416                 if (lsa_info->dns.name.string) {
2417                         if (!strequal(domain->name, lsa_info->dns.name.string))
2418                         {
2419                                 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2420                                           "for domain %s claimed it was a DC "
2421                                           "for domain %s, refusing to "
2422                                           "initialize\n",
2423                                           domain->name,
2424                                           lsa_info->dns.name.string));
2425                                 TALLOC_FREE(cli);
2426                                 TALLOC_FREE(mem_ctx);
2427                                 return;
2428                         }
2429                         talloc_free(domain->name);
2430                         domain->name = talloc_strdup(domain,
2431                                                      lsa_info->dns.name.string);
2432                         if (domain->name == NULL) {
2433                                 goto done;
2434                         }
2435                 }
2436
2437                 if (lsa_info->dns.dns_domain.string) {
2438                         if (domain->alt_name != NULL &&
2439                             !strequal(domain->alt_name,
2440                                       lsa_info->dns.dns_domain.string))
2441                         {
2442                                 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2443                                           "for domain %s (%s) claimed it was "
2444                                           "a DC for domain %s, refusing to "
2445                                           "initialize\n",
2446                                           domain->alt_name, domain->name,
2447                                           lsa_info->dns.dns_domain.string));
2448                                 TALLOC_FREE(cli);
2449                                 TALLOC_FREE(mem_ctx);
2450                                 return;
2451                         }
2452                         talloc_free(domain->alt_name);
2453                         domain->alt_name =
2454                                 talloc_strdup(domain,
2455                                               lsa_info->dns.dns_domain.string);
2456                         if (domain->alt_name == NULL) {
2457                                 goto done;
2458                         }
2459                 }
2460
2461                 /* See if we can set some domain trust flags about
2462                    ourself */
2463
2464                 if (lsa_info->dns.dns_forest.string) {
2465                         talloc_free(domain->forest_name);
2466                         domain->forest_name =
2467                                 talloc_strdup(domain,
2468                                               lsa_info->dns.dns_forest.string);
2469                         if (domain->forest_name == NULL) {
2470                                 goto done;
2471                         }
2472
2473                         if (strequal(domain->forest_name, domain->alt_name)) {
2474                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2475                         }
2476                 }
2477
2478                 if (lsa_info->dns.sid) {
2479                         if (!is_null_sid(&domain->sid) &&
2480                             !dom_sid_equal(&domain->sid,
2481                                            lsa_info->dns.sid))
2482                         {
2483                                 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2484                                           "for domain %s (%s) claimed it was "
2485                                           "a DC for domain %s, refusing to "
2486                                           "initialize\n",
2487                                           dom_sid_string(talloc_tos(),
2488                                                          &domain->sid),
2489                                           domain->name,
2490                                           dom_sid_string(talloc_tos(),
2491                                                          lsa_info->dns.sid)));
2492                                 TALLOC_FREE(cli);
2493                                 TALLOC_FREE(mem_ctx);
2494                                 return;
2495                         }
2496                         sid_copy(&domain->sid, lsa_info->dns.sid);
2497                 }
2498         } else {
2499                 domain->active_directory = False;
2500
2501                 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2502                                                 SEC_FLAG_MAXIMUM_ALLOWED,
2503                                                 &pol);
2504
2505                 if (!NT_STATUS_IS_OK(status)) {
2506                         goto done;
2507                 }
2508
2509                 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2510                                                     &pol,
2511                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2512                                                     &lsa_info,
2513                                                     &result);
2514                 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2515
2516                         if (lsa_info->account_domain.name.string) {
2517                                 if (!strequal(domain->name,
2518                                         lsa_info->account_domain.name.string))
2519                                 {
2520                                         DEBUG(1,
2521                                               ("set_dc_type_and_flags_connect: "
2522                                                "DC for domain %s claimed it was"
2523                                                " a DC for domain %s, refusing "
2524                                                "to initialize\n", domain->name,
2525                                                lsa_info->
2526                                                 account_domain.name.string));
2527                                         TALLOC_FREE(cli);
2528                                         TALLOC_FREE(mem_ctx);
2529                                         return;
2530                                 }
2531                                 talloc_free(domain->name);
2532                                 domain->name =
2533                                         talloc_strdup(domain,
2534                                                       lsa_info->account_domain.name.string);
2535                         }
2536
2537                         if (lsa_info->account_domain.sid) {
2538                                 if (!is_null_sid(&domain->sid) &&
2539                                     !dom_sid_equal(&domain->sid,
2540                                                 lsa_info->account_domain.sid))
2541                                 {
2542                                         DEBUG(1,
2543                                               ("set_dc_type_and_flags_connect: "
2544                                                "DC for domain %s (%s) claimed "
2545                                                "it was a DC for domain %s, "
2546                                                "refusing to initialize\n",
2547                                                dom_sid_string(talloc_tos(),
2548                                                               &domain->sid),
2549                                                domain->name,
2550                                                dom_sid_string(talloc_tos(),
2551                                                 lsa_info->account_domain.sid)));
2552                                         TALLOC_FREE(cli);
2553                                         TALLOC_FREE(mem_ctx);
2554                                         return;
2555                                 }
2556                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2557                         }
2558                 }
2559         }
2560 done:
2561
2562         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2563                   domain->name, domain->native_mode ? "" : "NOT "));
2564
2565         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2566                   domain->name, domain->active_directory ? "" : "NOT "));
2567
2568         domain->can_do_ncacn_ip_tcp = domain->active_directory;
2569
2570         TALLOC_FREE(cli);
2571
2572         TALLOC_FREE(mem_ctx);
2573
2574         domain->initialized = True;
2575 }
2576
2577 /**********************************************************************
2578  Set the domain_flags (trust attributes, domain operating modes, etc... 
2579 ***********************************************************************/
2580
2581 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2582 {
2583         /* we always have to contact our primary domain */
2584
2585         if ( domain->primary || domain->internal) {
2586                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2587                           "primary or internal domain\n"));
2588                 set_dc_type_and_flags_connect( domain );
2589                 return;         
2590         }
2591
2592         /* Use our DC to get the information if possible */
2593
2594         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2595                 /* Otherwise, fallback to contacting the 
2596                    domain directly */
2597                 set_dc_type_and_flags_connect( domain );
2598         }
2599
2600         return;
2601 }
2602
2603
2604
2605 /**********************************************************************
2606 ***********************************************************************/
2607
2608 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2609                                    struct netlogon_creds_cli_context **ppdc)
2610 {
2611         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2612         struct rpc_pipe_client *netlogon_pipe;
2613
2614         *ppdc = NULL;
2615
2616         if ((!IS_DC) && (!domain->primary)) {
2617                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2618         }
2619
2620         if (domain->conn.netlogon_creds_ctx != NULL) {
2621                 if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
2622                         return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2623                 }
2624                 *ppdc = domain->conn.netlogon_creds_ctx;
2625                 return NT_STATUS_OK;
2626         }
2627
2628         result = cm_connect_netlogon(domain, &netlogon_pipe);
2629         if (!NT_STATUS_IS_OK(result)) {
2630                 return result;
2631         }
2632
2633         if (domain->conn.netlogon_creds_ctx == NULL) {
2634                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2635         }
2636
2637         if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
2638                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2639         }
2640
2641         *ppdc = domain->conn.netlogon_creds_ctx;
2642         return NT_STATUS_OK;
2643 }
2644
2645 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2646                         bool need_rw_dc,
2647                         struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2648 {
2649         struct winbindd_cm_conn *conn;
2650         NTSTATUS status, result;
2651         struct netlogon_creds_cli_context *p_creds;
2652         struct cli_credentials *creds = NULL;
2653         bool retry = false; /* allow one retry attempt for expired session */
2654
2655         if (sid_check_is_our_sam(&domain->sid)) {
2656                 if (domain->rodc == false || need_rw_dc == false) {
2657                         return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2658                 }
2659         }
2660
2661 retry:
2662         status = init_dc_connection_rpc(domain, need_rw_dc);
2663         if (!NT_STATUS_IS_OK(status)) {
2664                 return status;
2665         }
2666
2667         conn = &domain->conn;
2668
2669         if (rpccli_is_connected(conn->samr_pipe)) {
2670                 goto done;
2671         }
2672
2673         TALLOC_FREE(conn->samr_pipe);
2674
2675         /*
2676          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2677          * sign and sealed pipe using the machine account password by
2678          * preference. If we can't - try schannel, if that fails, try
2679          * anonymous.
2680          */
2681
2682         result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2683         if (!NT_STATUS_IS_OK(result)) {
2684                 DEBUG(10, ("cm_connect_sam: No user available for "
2685                            "domain %s, trying schannel\n", domain->name));
2686                 goto schannel;
2687         }
2688
2689         if (cli_credentials_is_anonymous(creds)) {
2690                 goto anonymous;
2691         }
2692
2693         /*
2694          * We have an authenticated connection. Use a SPNEGO
2695          * authenticated SAMR pipe with sign & seal.
2696          */
2697         status = cli_rpc_pipe_open_with_creds(conn->cli,
2698                                               &ndr_table_samr,
2699                                               NCACN_NP,
2700                                               DCERPC_AUTH_TYPE_SPNEGO,
2701                                               conn->auth_level,
2702                                               smbXcli_conn_remote_name(conn->cli->conn),
2703                                               creds,
2704                                               &conn->samr_pipe);
2705
2706         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2707             && !retry) {
2708                 invalidate_cm_connection(domain);
2709                 retry = true;
2710                 goto retry;
2711         }
2712
2713         if (!NT_STATUS_IS_OK(status)) {
2714                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2715                           "pipe for domain %s using NTLMSSP "
2716                           "authenticated pipe: user %s. Error was "
2717                           "%s\n", domain->name,
2718                           cli_credentials_get_unparsed_name(creds, talloc_tos()),
2719                           nt_errstr(status)));
2720                 goto schannel;
2721         }
2722
2723         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2724                   "domain %s using NTLMSSP authenticated "
2725                   "pipe: user %s\n", domain->name,
2726                   cli_credentials_get_unparsed_name(creds, talloc_tos())));
2727
2728         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2729                                       conn->samr_pipe->desthost,
2730                                       SEC_FLAG_MAXIMUM_ALLOWED,
2731                                       &conn->sam_connect_handle,
2732                                       &result);
2733
2734         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2735                 invalidate_cm_connection(domain);
2736                 TALLOC_FREE(conn->samr_pipe);
2737                 retry = true;
2738                 goto retry;
2739         }
2740
2741         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2742                 goto open_domain;
2743         }
2744         if (NT_STATUS_IS_OK(status)) {
2745                 status = result;
2746         }
2747
2748         DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2749                   "failed for domain %s, error was %s. Trying schannel\n",
2750                   domain->name, nt_errstr(status) ));
2751         TALLOC_FREE(conn->samr_pipe);
2752
2753  schannel:
2754
2755         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2756
2757         status = cm_get_schannel_creds(domain, &p_creds);
2758         if (!NT_STATUS_IS_OK(status)) {
2759                 /* If this call fails - conn->cli can now be NULL ! */
2760                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2761                            "for domain %s (error %s), trying anon\n",
2762                         domain->name,
2763                         nt_errstr(status) ));
2764                 goto anonymous;
2765         }
2766         TALLOC_FREE(creds);
2767         result = get_trust_credentials(domain, talloc_tos(), true, &creds);
2768         if (!NT_STATUS_IS_OK(result)) {
2769                 DEBUG(10, ("cm_connect_sam: No user available for "
2770                            "domain %s (error %s), trying anon\n", domain->name,
2771                            nt_errstr(result)));
2772                 goto anonymous;
2773         }
2774         status = cli_rpc_pipe_open_schannel_with_creds(
2775                 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2776                 &conn->samr_pipe);
2777
2778         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2779             && !retry) {
2780                 invalidate_cm_connection(domain);
2781                 retry = true;
2782                 goto retry;
2783         }
2784
2785         if (!NT_STATUS_IS_OK(status)) {
2786                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2787                           "domain %s using schannel. Error was %s\n",
2788                           domain->name, nt_errstr(status) ));
2789                 goto anonymous;
2790         }
2791         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2792                   "schannel.\n", domain->name ));
2793
2794         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2795                                       conn->samr_pipe->desthost,
2796                                       SEC_FLAG_MAXIMUM_ALLOWED,
2797                                       &conn->sam_connect_handle,
2798                                       &result);
2799
2800         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2801                 invalidate_cm_connection(domain);
2802                 TALLOC_FREE(conn->samr_pipe);
2803                 retry = true;
2804                 goto retry;
2805         }
2806
2807         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2808                 goto open_domain;
2809         }
2810         if (NT_STATUS_IS_OK(status)) {
2811                 status = result;
2812         }
2813         DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2814                   "for domain %s, error was %s. Trying anonymous\n",
2815                   domain->name, nt_errstr(status) ));
2816         TALLOC_FREE(conn->samr_pipe);
2817
2818  anonymous:
2819
2820         /* Finally fall back to anonymous. */
2821         if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
2822                 status = NT_STATUS_DOWNGRADE_DETECTED;
2823                 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2824                           "without connection level security, "
2825                           "must set 'winbind sealed pipes = false' and "
2826                           "'require strong key = false' to proceed: %s\n",
2827                           domain->name, nt_errstr(status)));
2828                 goto done;
2829         }
2830         status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2831                                           &conn->samr_pipe);
2832
2833         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2834             && !retry) {
2835                 invalidate_cm_connection(domain);
2836                 retry = true;
2837                 goto retry;
2838         }
2839
2840         if (!NT_STATUS_IS_OK(status)) {
2841                 goto done;
2842         }
2843
2844         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2845                                       conn->samr_pipe->desthost,
2846                                       SEC_FLAG_MAXIMUM_ALLOWED,
2847                                       &conn->sam_connect_handle,
2848                                       &result);
2849
2850         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2851                 invalidate_cm_connection(domain);
2852                 TALLOC_FREE(conn->samr_pipe);
2853                 retry = true;
2854                 goto retry;
2855         }
2856
2857         if (!NT_STATUS_IS_OK(status)) {
2858                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2859                           "for domain %s Error was %s\n",
2860                           domain->name, nt_errstr(status) ));
2861                 goto done;
2862         }
2863         if (!NT_STATUS_IS_OK(result)) {
2864                 status = result;
2865                 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2866                           "for domain %s Error was %s\n",
2867                           domain->name, nt_errstr(result)));
2868                 goto done;
2869         }
2870
2871  open_domain:
2872         status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2873                                         mem_ctx,
2874                                         &conn->sam_connect_handle,
2875                                         SEC_FLAG_MAXIMUM_ALLOWED,
2876                                         &domain->sid,
2877                                         &conn->sam_domain_handle,
2878                                         &result);
2879         if (!NT_STATUS_IS_OK(status)) {
2880                 goto done;
2881         }
2882
2883         status = result;
2884  done:
2885
2886         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2887                 /*
2888                  * if we got access denied, we might just have no access rights
2889                  * to talk to the remote samr server server (e.g. when we are a
2890                  * PDC and we are connecting a w2k8 pdc via an interdomain
2891                  * trust). In that case do not invalidate the whole connection
2892                  * stack
2893                  */
2894                 TALLOC_FREE(conn->samr_pipe);
2895                 ZERO_STRUCT(conn->sam_domain_handle);
2896                 return status;
2897         } else if (!NT_STATUS_IS_OK(status)) {
2898                 invalidate_cm_connection(domain);
2899                 return status;
2900         }
2901
2902         *cli = conn->samr_pipe;
2903         *sam_handle = conn->sam_domain_handle;
2904         return status;
2905 }
2906
2907 /**********************************************************************
2908  open an schanneld ncacn_ip_tcp connection to LSA
2909 ***********************************************************************/
2910
2911 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2912                                    TALLOC_CTX *mem_ctx,
2913                                    struct rpc_pipe_client **cli)
2914 {
2915         struct winbindd_cm_conn *conn;
2916         struct netlogon_creds_cli_context *p_creds = NULL;
2917         struct cli_credentials *creds = NULL;
2918         NTSTATUS status;
2919
2920         DEBUG(10,("cm_connect_lsa_tcp\n"));
2921
2922         status = init_dc_connection_rpc(domain, false);
2923         if (!NT_STATUS_IS_OK(status)) {
2924                 return status;
2925         }
2926
2927         conn = &domain->conn;
2928
2929         /*
2930          * rpccli_is_connected handles more error cases
2931          */
2932         if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2933             conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2934             conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2935                 goto done;
2936         }
2937
2938         TALLOC_FREE(conn->lsa_pipe_tcp);
2939
2940         status = cm_get_schannel_creds(domain, &p_creds);
2941         if (!NT_STATUS_IS_OK(status)) {
2942                 goto done;
2943         }
2944
2945         status = get_trust_credentials(domain, talloc_tos(), true, &creds);
2946         if (!NT_STATUS_IS_OK(status)) {
2947                 goto done;
2948         }
2949
2950         status = cli_rpc_pipe_open_schannel_with_creds(conn->cli,
2951                                                        &ndr_table_lsarpc,
2952                                                        NCACN_IP_TCP,
2953                                                        p_creds,
2954                                                        &conn->lsa_pipe_tcp);
2955         if (!NT_STATUS_IS_OK(status)) {
2956                 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2957                         nt_errstr(status)));
2958                 goto done;
2959         }
2960
2961  done:
2962         if (!NT_STATUS_IS_OK(status)) {
2963                 TALLOC_FREE(conn->lsa_pipe_tcp);
2964                 return status;
2965         }
2966
2967         *cli = conn->lsa_pipe_tcp;
2968
2969         return status;
2970 }
2971
2972 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2973                         struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2974 {
2975         struct winbindd_cm_conn *conn;
2976         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2977         struct netlogon_creds_cli_context *p_creds;
2978         struct cli_credentials *creds = NULL;
2979         bool retry = false; /* allow one retry attempt for expired session */
2980
2981 retry:
2982         result = init_dc_connection_rpc(domain, false);
2983         if (!NT_STATUS_IS_OK(result))
2984                 return result;
2985
2986         conn = &domain->conn;
2987
2988         if (rpccli_is_connected(conn->lsa_pipe)) {
2989                 goto done;
2990         }
2991
2992         TALLOC_FREE(conn->lsa_pipe);
2993
2994         result = get_trust_credentials(domain, talloc_tos(), false, &creds);
2995         if (!NT_STATUS_IS_OK(result)) {
2996                 DEBUG(10, ("cm_connect_lsa: No user available for "
2997                            "domain %s, trying schannel\n", domain->name));
2998                 goto schannel;
2999         }
3000
3001         if (cli_credentials_is_anonymous(creds)) {
3002                 goto anonymous;
3003         }
3004
3005         /*
3006          * We have an authenticated connection. Use a SPNEGO
3007          * authenticated LSA pipe with sign & seal.
3008          */
3009         result = cli_rpc_pipe_open_with_creds
3010                 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
3011                  DCERPC_AUTH_TYPE_SPNEGO,
3012                  conn->auth_level,
3013                  smbXcli_conn_remote_name(conn->cli->conn),
3014                  creds,
3015                  &conn->lsa_pipe);
3016
3017         if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3018             && !retry) {
3019                 invalidate_cm_connection(domain);
3020                 retry = true;
3021                 goto retry;
3022         }
3023
3024         if (!NT_STATUS_IS_OK(result)) {
3025                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3026                           "domain %s using NTLMSSP authenticated pipe: user "
3027                           "%s. Error was %s. Trying schannel.\n",
3028                           domain->name,
3029                           cli_credentials_get_unparsed_name(creds, talloc_tos()),
3030                           nt_errstr(result)));
3031                 goto schannel;
3032         }
3033
3034         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3035                   "NTLMSSP authenticated pipe: user %s\n",
3036                   domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3037
3038         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3039                                         SEC_FLAG_MAXIMUM_ALLOWED,
3040                                         &conn->lsa_policy);
3041         if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3042                 invalidate_cm_connection(domain);
3043                 TALLOC_FREE(conn->lsa_pipe);
3044                 retry = true;
3045                 goto retry;
3046         }
3047
3048         if (NT_STATUS_IS_OK(result)) {
3049                 goto done;
3050         }
3051
3052         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3053                   "schannel\n"));
3054
3055         TALLOC_FREE(conn->lsa_pipe);
3056
3057  schannel:
3058
3059         /* Fall back to schannel if it's a W2K pre-SP1 box. */
3060
3061         result = cm_get_schannel_creds(domain, &p_creds);
3062         if (!NT_STATUS_IS_OK(result)) {
3063                 /* If this call fails - conn->cli can now be NULL ! */
3064                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3065                            "for domain %s (error %s), trying anon\n",
3066                         domain->name,
3067                         nt_errstr(result) ));
3068                 goto anonymous;
3069         }
3070
3071         TALLOC_FREE(creds);
3072         result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3073         if (!NT_STATUS_IS_OK(result)) {
3074                 DEBUG(10, ("cm_connect_lsa: No user available for "
3075                            "domain %s (error %s), trying anon\n", domain->name,
3076                            nt_errstr(result)));
3077                 goto anonymous;
3078         }
3079         result = cli_rpc_pipe_open_schannel_with_creds(
3080                 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3081                 &conn->lsa_pipe);
3082
3083         if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3084             && !retry) {
3085                 invalidate_cm_connection(domain);
3086                 retry = true;
3087                 goto retry;
3088         }
3089
3090         if (!NT_STATUS_IS_OK(result)) {
3091                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3092                           "domain %s using schannel. Error was %s\n",
3093                           domain->name, nt_errstr(result) ));
3094                 goto anonymous;
3095         }
3096         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3097                   "schannel.\n", domain->name ));
3098
3099         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3100                                         SEC_FLAG_MAXIMUM_ALLOWED,
3101                                         &conn->lsa_policy);
3102
3103         if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3104                 invalidate_cm_connection(domain);
3105                 TALLOC_FREE(conn->lsa_pipe);
3106                 retry = true;
3107                 goto retry;
3108         }
3109
3110         if (NT_STATUS_IS_OK(result)) {
3111                 goto done;
3112         }
3113
3114         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3115                   "anonymous\n"));
3116
3117         TALLOC_FREE(conn->lsa_pipe);
3118
3119  anonymous:
3120
3121         if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3122                 result = NT_STATUS_DOWNGRADE_DETECTED;
3123                 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3124                           "without connection level security, "
3125                           "must set 'winbind sealed pipes = false' and "
3126                           "'require strong key = false' to proceed: %s\n",
3127                           domain->name, nt_errstr(result)));
3128                 goto done;
3129         }
3130
3131         result = cli_rpc_pipe_open_noauth(conn->cli,
3132                                           &ndr_table_lsarpc,
3133                                           &conn->lsa_pipe);
3134
3135         if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3136             && !retry) {
3137                 invalidate_cm_connection(domain);
3138                 retry = true;
3139                 goto retry;
3140         }
3141
3142         if (!NT_STATUS_IS_OK(result)) {
3143                 goto done;
3144         }
3145
3146         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3147                                         SEC_FLAG_MAXIMUM_ALLOWED,
3148                                         &conn->lsa_policy);
3149
3150         if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3151                 invalidate_cm_connection(domain);
3152                 TALLOC_FREE(conn->lsa_pipe);
3153                 retry = true;
3154                 goto retry;
3155         }
3156
3157  done:
3158         if (!NT_STATUS_IS_OK(result)) {
3159                 invalidate_cm_connection(domain);
3160                 return result;
3161         }
3162
3163         *cli = conn->lsa_pipe;
3164         *lsa_policy = conn->lsa_policy;
3165         return result;
3166 }
3167
3168 /****************************************************************************
3169 Open a LSA connection to a DC, suiteable for LSA lookup calls.
3170 ****************************************************************************/
3171
3172 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3173                          TALLOC_CTX *mem_ctx,
3174                          struct rpc_pipe_client **cli,
3175                          struct policy_handle *lsa_policy)
3176 {
3177         NTSTATUS status;
3178
3179         if (domain->can_do_ncacn_ip_tcp) {
3180                 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3181                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3182                     NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3183                     NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3184                         invalidate_cm_connection(domain);
3185                         status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3186                 }
3187                 if (NT_STATUS_IS_OK(status)) {
3188                         return status;
3189                 }
3190
3191                 /*
3192                  * we tried twice to connect via ncan_ip_tcp and schannel and
3193                  * failed - maybe it is a trusted domain we can't connect to ?
3194                  * do not try tcp next time - gd
3195                  *
3196                  * This also prevents NETLOGON over TCP
3197                  */
3198                 domain->can_do_ncacn_ip_tcp = false;
3199         }
3200
3201         status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3202
3203         return status;
3204 }
3205
3206 /****************************************************************************
3207  Open the netlogon pipe to this DC.
3208 ****************************************************************************/
3209
3210 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3211                                               enum dcerpc_transport_t transport,
3212                                               struct rpc_pipe_client **cli)
3213 {
3214         struct messaging_context *msg_ctx = winbind_messaging_context();
3215         struct winbindd_cm_conn *conn;
3216         NTSTATUS result;
3217         enum netr_SchannelType sec_chan_type;
3218         struct netlogon_creds_CredentialState *netlogon_creds = NULL;
3219         struct cli_credentials *creds = NULL;
3220
3221         *cli = NULL;
3222
3223         result = init_dc_connection_rpc(domain, domain->rodc);
3224         if (!NT_STATUS_IS_OK(result)) {
3225                 return result;
3226         }
3227
3228         conn = &domain->conn;
3229
3230         if (rpccli_is_connected(conn->netlogon_pipe)) {
3231                 *cli = conn->netlogon_pipe;
3232                 return NT_STATUS_OK;
3233         }
3234
3235         TALLOC_FREE(conn->netlogon_pipe);
3236         conn->netlogon_flags = 0;
3237         TALLOC_FREE(conn->netlogon_creds_ctx);
3238
3239         result = get_trust_credentials(domain, talloc_tos(), true, &creds);
3240         if (!NT_STATUS_IS_OK(result)) {
3241                 DBG_DEBUG("No user available for domain %s when trying "
3242                           "schannel\n", domain->name);
3243                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3244         }
3245
3246         if (cli_credentials_is_anonymous(creds)) {
3247                 DEBUG(1, ("get_trust_credential only gave anonymous for %s, unable to make get NETLOGON credentials\n",
3248                           domain->name));
3249                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3250         }
3251
3252         sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3253         if (sec_chan_type == SEC_CHAN_NULL) {
3254                 if (transport == NCACN_IP_TCP) {
3255                         DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3256                                    " deny NCACN_IP_TCP and let the caller fallback to NCACN_NP.\n",
3257                                    domain->name);
3258                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3259                 }
3260
3261                 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3262                            "fallback to noauth on NCACN_NP.\n",
3263                            domain->name);
3264
3265                 result = cli_rpc_pipe_open_noauth_transport(conn->cli,
3266                                                             transport,
3267                                                             &ndr_table_netlogon,
3268                                                             &conn->netlogon_pipe);
3269                 if (!NT_STATUS_IS_OK(result)) {
3270                         invalidate_cm_connection(domain);
3271                         return result;
3272                 }
3273
3274                 *cli = conn->netlogon_pipe;
3275                 return NT_STATUS_OK;
3276         }
3277
3278         result = rpccli_create_netlogon_creds_ctx(creds,
3279                                                   domain->dcname,
3280                                                   msg_ctx,
3281                                                   domain,
3282                                                   &conn->netlogon_creds_ctx);
3283         if (!NT_STATUS_IS_OK(result)) {
3284                 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3285                           "unable to create NETLOGON credentials: %s\n",
3286                           domain->name, nt_errstr(result)));
3287                 return result;
3288         }
3289
3290         result = rpccli_setup_netlogon_creds(conn->cli, transport,
3291                                              conn->netlogon_creds_ctx,
3292                                              conn->netlogon_force_reauth,
3293                                              creds);
3294         conn->netlogon_force_reauth = false;
3295         if (!NT_STATUS_IS_OK(result)) {
3296                 DEBUG(1, ("rpccli_setup_netlogon_creds failed for %s, "
3297                           "unable to setup NETLOGON credentials: %s\n",
3298                           domain->name, nt_errstr(result)));
3299                 return result;
3300         }
3301
3302         result = netlogon_creds_cli_get(conn->netlogon_creds_ctx,
3303                                         talloc_tos(),
3304                                         &netlogon_creds);
3305         if (!NT_STATUS_IS_OK(result)) {
3306                 DEBUG(1, ("netlogon_creds_cli_get failed for %s, "
3307                           "unable to get NETLOGON credentials: %s\n",
3308                           domain->name, nt_errstr(result)));
3309                 return result;
3310         }
3311         conn->netlogon_flags = netlogon_creds->negotiate_flags;
3312         TALLOC_FREE(netlogon_creds);
3313
3314         if (!(conn->netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
3315                 if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
3316                         result = NT_STATUS_DOWNGRADE_DETECTED;
3317                         DEBUG(1, ("Unwilling to make connection to domain %s"
3318                                   "without connection level security, "
3319                                   "must set 'winbind sealed pipes = false' and "
3320                                   "'require strong key = false' to proceed: %s\n",
3321                                   domain->name, nt_errstr(result)));
3322                         invalidate_cm_connection(domain);
3323                         return result;
3324                 }
3325                 result = cli_rpc_pipe_open_noauth_transport(conn->cli,
3326                                                             transport,
3327                                                             &ndr_table_netlogon,
3328                                                             &conn->netlogon_pipe);
3329                 if (!NT_STATUS_IS_OK(result)) {
3330                         invalidate_cm_connection(domain);
3331                         return result;
3332                 }
3333
3334                 *cli = conn->netlogon_pipe;
3335                 return NT_STATUS_OK;
3336         }
3337
3338         /* Using the credentials from the first pipe, open a signed and sealed
3339            second netlogon pipe. The session key is stored in the schannel
3340            part of the new pipe auth struct.
3341         */
3342
3343         result = cli_rpc_pipe_open_schannel_with_creds(
3344                 conn->cli, &ndr_table_netlogon, transport,
3345                 conn->netlogon_creds_ctx,
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 }