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