Followup patch for BUG: https://bugzilla.samba.org/show_bug.cgi?id=10082
[mat/samba.git] / source3 / winbindd / winbindd_cm.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon connection manager
5
6    Copyright (C) Tim Potter                2001
7    Copyright (C) Andrew Bartlett           2002
8    Copyright (C) Gerald (Jerry) Carter     2003-2005.
9    Copyright (C) Volker Lendecke           2004-2005
10    Copyright (C) Jeremy Allison            2006
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 /*
27    We need to manage connections to domain controllers without having to
28    mess up the main winbindd code with other issues.  The aim of the
29    connection manager is to:
30
31        - make connections to domain controllers and cache them
32        - re-establish connections when networks or servers go down
33        - centralise the policy on connection timeouts, domain controller
34          selection etc
35        - manage re-entrancy for when winbindd becomes able to handle
36          multiple outstanding rpc requests
37
38    Why not have connection management as part of the rpc layer like tng?
39    Good question.  This code may morph into libsmb/rpc_cache.c or something
40    like that but at the moment it's simply staying as part of winbind.  I
41    think the TNG architecture of forcing every user of the rpc layer to use
42    the connection caching system is a bad idea.  It should be an optional
43    method of using the routines.
44
45    The TNG design is quite good but I disagree with some aspects of the
46    implementation. -tpot
47
48  */
49
50 /*
51    TODO:
52
53      - I'm pretty annoyed by all the make_nmb_name() stuff.  It should be
54        moved down into another function.
55
56      - Take care when destroying cli_structs as they can be shared between
57        various sam handles.
58
59  */
60
61 #include "includes.h"
62 #include "winbindd.h"
63 #include "../libcli/auth/libcli_auth.h"
64 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
65 #include "rpc_client/cli_pipe.h"
66 #include "rpc_client/cli_netlogon.h"
67 #include "../librpc/gen_ndr/ndr_samr_c.h"
68 #include "../librpc/gen_ndr/ndr_lsa_c.h"
69 #include "rpc_client/cli_lsarpc.h"
70 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
71 #include "libads/sitename_cache.h"
72 #include "libsmb/libsmb.h"
73 #include "libsmb/clidgram.h"
74 #include "ads.h"
75 #include "secrets.h"
76 #include "../libcli/security/security.h"
77 #include "passdb.h"
78 #include "messages.h"
79 #include "auth/gensec/gensec.h"
80 #include "../libcli/smb/smbXcli_base.h"
81 #include "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         fstring nbtname;
1131
1132         ip_list.ss = *pss;
1133         ip_list.port = 0;
1134
1135 #ifdef HAVE_ADS
1136         /* For active directory servers, try to get the ldap server name.
1137            None of these failures should be considered critical for now */
1138
1139         if (lp_security() == SEC_ADS) {
1140                 ADS_STRUCT *ads;
1141                 ADS_STATUS ads_status;
1142                 char addr[INET6_ADDRSTRLEN];
1143
1144                 print_sockaddr(addr, sizeof(addr), pss);
1145
1146                 ads = ads_init(domain->alt_name, domain->name, addr);
1147                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1148
1149                 ads_status = ads_connect(ads);
1150                 if (ADS_ERR_OK(ads_status)) {
1151                         /* We got a cldap packet. */
1152                         *name = talloc_strdup(mem_ctx,
1153                                              ads->config.ldap_server_name);
1154                         if (*name == NULL) {
1155                                 return false;
1156                         }
1157                         namecache_store(*name, 0x20, 1, &ip_list);
1158
1159                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1160
1161                         if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1162                                 if (ads_closest_dc(ads)) {
1163                                         char *sitename = sitename_fetch(ads->config.realm);
1164
1165                                         /* We're going to use this KDC for this realm/domain.
1166                                            If we are using sites, then force the krb5 libs
1167                                            to use this KDC. */
1168
1169                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1170                                                                         domain->name,
1171                                                                         sitename,
1172                                                                         pss,
1173                                                                         *name);
1174
1175                                         SAFE_FREE(sitename);
1176                                 } else {
1177                                         /* use an off site KDC */
1178                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1179                                                                         domain->name,
1180                                                                         NULL,
1181                                                                         pss,
1182                                                                         *name);
1183                                 }
1184                                 winbindd_set_locator_kdc_envs(domain);
1185
1186                                 /* Ensure we contact this DC also. */
1187                                 saf_store(domain->name, *name);
1188                                 saf_store(domain->alt_name, *name);
1189                         }
1190
1191                         ads_destroy( &ads );
1192                         return True;
1193                 }
1194
1195                 ads_destroy( &ads );
1196                 return false;
1197         }
1198 #endif
1199
1200         status = nbt_getdc(winbind_messaging_context(), 10, pss, domain->name,
1201                            &domain->sid, nt_version, mem_ctx, &nt_version,
1202                            &dc_name, NULL);
1203         if (NT_STATUS_IS_OK(status)) {
1204                 *name = talloc_strdup(mem_ctx, dc_name);
1205                 if (*name == NULL) {
1206                         return false;
1207                 }
1208                 namecache_store(*name, 0x20, 1, &ip_list);
1209                 return True;
1210         }
1211
1212         /* try node status request */
1213
1214         if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) {
1215                 namecache_store(nbtname, 0x20, 1, &ip_list);
1216
1217                 if (name != NULL) {
1218                         *name = talloc_strdup(mem_ctx, nbtname);
1219                         if (*name == NULL) {
1220                                 return false;
1221                         }
1222                 }
1223
1224                 return true;
1225         }
1226         return False;
1227 }
1228
1229 /*******************************************************************
1230  Retrieve a list of IP addresses for domain controllers.
1231
1232  The array is sorted in the preferred connection order.
1233
1234  @param[in] mem_ctx talloc memory context to allocate from
1235  @param[in] domain domain to retrieve DCs for
1236  @param[out] dcs array of dcs that will be returned
1237  @param[out] num_dcs number of dcs returned in the dcs array
1238  @return always true
1239 *******************************************************************/
1240
1241 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1242                     struct dc_name_ip **dcs, int *num_dcs)
1243 {
1244         fstring dcname;
1245         struct  sockaddr_storage ss;
1246         struct  ip_service *ip_list = NULL;
1247         int     iplist_size = 0;
1248         int     i;
1249         bool    is_our_domain;
1250         enum security_types sec = (enum security_types)lp_security();
1251
1252         is_our_domain = strequal(domain->name, lp_workgroup());
1253
1254         /* If not our domain, get the preferred DC, by asking our primary DC */
1255         if ( !is_our_domain
1256                 && get_dc_name_via_netlogon(domain, dcname, &ss)
1257                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1258                        num_dcs) )
1259         {
1260                 char addr[INET6_ADDRSTRLEN];
1261                 print_sockaddr(addr, sizeof(addr), &ss);
1262                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1263                            dcname, addr));
1264                 return True;
1265         }
1266
1267         if (sec == SEC_ADS) {
1268                 char *sitename = NULL;
1269
1270                 /* We need to make sure we know the local site before
1271                    doing any DNS queries, as this will restrict the
1272                    get_sorted_dc_list() call below to only fetching
1273                    DNS records for the correct site. */
1274
1275                 /* Find any DC to get the site record.
1276                    We deliberately don't care about the
1277                    return here. */
1278
1279                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1280
1281                 sitename = sitename_fetch(domain->alt_name);
1282                 if (sitename) {
1283
1284                         /* Do the site-specific AD dns lookup first. */
1285                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1286                                &iplist_size, True);
1287
1288                         /* Add ips to the DC array.  We don't look up the name
1289                            of the DC in this function, but we fill in the char*
1290                            of the ip now to make the failed connection cache
1291                            work */
1292                         for ( i=0; i<iplist_size; i++ ) {
1293                                 char addr[INET6_ADDRSTRLEN];
1294                                 print_sockaddr(addr, sizeof(addr),
1295                                                 &ip_list[i].ss);
1296                                 add_one_dc_unique(mem_ctx,
1297                                                 domain->name,
1298                                                 addr,
1299                                                 &ip_list[i].ss,
1300                                                 dcs,
1301                                                 num_dcs);
1302                         }
1303
1304                         SAFE_FREE(ip_list);
1305                         SAFE_FREE(sitename);
1306                         iplist_size = 0;
1307                 }
1308
1309                 /* Now we add DCs from the main AD DNS lookup. */
1310                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1311                         &iplist_size, True);
1312
1313                 for ( i=0; i<iplist_size; i++ ) {
1314                         char addr[INET6_ADDRSTRLEN];
1315                         print_sockaddr(addr, sizeof(addr),
1316                                         &ip_list[i].ss);
1317                         add_one_dc_unique(mem_ctx,
1318                                         domain->name,
1319                                         addr,
1320                                         &ip_list[i].ss,
1321                                         dcs,
1322                                         num_dcs);
1323                 }
1324
1325                 SAFE_FREE(ip_list);
1326                 iplist_size = 0;
1327         }
1328
1329         /* Try standard netbios queries if no ADS and fall back to DNS queries
1330          * if alt_name is available */
1331         if (*num_dcs == 0) {
1332                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1333                        false);
1334                 if (iplist_size == 0) {
1335                         if (domain->alt_name != NULL) {
1336                                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1337                                        &iplist_size, true);
1338                         }
1339                 }
1340
1341                 for ( i=0; i<iplist_size; i++ ) {
1342                         char addr[INET6_ADDRSTRLEN];
1343                         print_sockaddr(addr, sizeof(addr),
1344                                         &ip_list[i].ss);
1345                         add_one_dc_unique(mem_ctx,
1346                                         domain->name,
1347                                         addr,
1348                                         &ip_list[i].ss,
1349                                         dcs,
1350                                         num_dcs);
1351                 }
1352
1353                 SAFE_FREE(ip_list);
1354                 iplist_size = 0;
1355         }
1356
1357         return True;
1358 }
1359
1360 /*******************************************************************
1361  Find and make a connection to a DC in the given domain.
1362
1363  @param[in] mem_ctx talloc memory context to allocate from
1364  @param[in] domain domain to find a dc in
1365  @param[out] dcname NetBIOS or FQDN of DC that's connected to
1366  @param[out] pss DC Internet address and port
1367  @param[out] fd fd of the open socket connected to the newly found dc
1368  @return true when a DC connection is made, false otherwise
1369 *******************************************************************/
1370
1371 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1372                         struct winbindd_domain *domain,
1373                         char **dcname, struct sockaddr_storage *pss, int *fd)
1374 {
1375         struct dc_name_ip *dcs = NULL;
1376         int num_dcs = 0;
1377
1378         const char **dcnames = NULL;
1379         int num_dcnames = 0;
1380
1381         struct sockaddr_storage *addrs = NULL;
1382         int num_addrs = 0;
1383
1384         int i;
1385         size_t fd_index;
1386
1387         NTSTATUS status;
1388
1389         *fd = -1;
1390
1391  again:
1392         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1393                 return False;
1394
1395         for (i=0; i<num_dcs; i++) {
1396
1397                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1398                                     &dcnames, &num_dcnames)) {
1399                         return False;
1400                 }
1401                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1402                                       &addrs, &num_addrs)) {
1403                         return False;
1404                 }
1405         }
1406
1407         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1408                 return False;
1409
1410         if ((addrs == NULL) || (dcnames == NULL))
1411                 return False;
1412
1413         status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1414                                      num_addrs, 0, 10, fd, &fd_index, NULL);
1415         if (!NT_STATUS_IS_OK(status)) {
1416                 for (i=0; i<num_dcs; i++) {
1417                         char ab[INET6_ADDRSTRLEN];
1418                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1419                         DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1420                                 "domain %s address %s. Error was %s\n",
1421                                    domain->name, ab, nt_errstr(status) ));
1422                         winbind_add_failed_connection_entry(domain,
1423                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1424                 }
1425                 return False;
1426         }
1427
1428         *pss = addrs[fd_index];
1429
1430         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1431                 /* Ok, we've got a name for the DC */
1432                 *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]);
1433                 if (*dcname == NULL) {
1434                         return false;
1435                 }
1436                 return true;
1437         }
1438
1439         /* Try to figure out the name */
1440         if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1441                 return True;
1442         }
1443
1444         /* We can not continue without the DC's name */
1445         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1446                                     NT_STATUS_UNSUCCESSFUL);
1447
1448         /* Throw away all arrays as we're doing this again. */
1449         TALLOC_FREE(dcs);
1450         num_dcs = 0;
1451
1452         TALLOC_FREE(dcnames);
1453         num_dcnames = 0;
1454
1455         TALLOC_FREE(addrs);
1456         num_addrs = 0;
1457
1458         close(*fd);
1459         *fd = -1;
1460
1461         goto again;
1462 }
1463
1464 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1465 {
1466         return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1467                                           domain_name);
1468 }
1469
1470 static void store_current_dc_in_gencache(const char *domain_name,
1471                                          const char *dc_name,
1472                                          struct cli_state *cli)
1473 {
1474         char addr[INET6_ADDRSTRLEN];
1475         char *key = NULL;
1476         char *value = NULL;
1477
1478         if (!cli_state_is_connected(cli)) {
1479                 return;
1480         }
1481
1482         print_sockaddr(addr, sizeof(addr),
1483                        smbXcli_conn_remote_sockaddr(cli->conn));
1484
1485         key = current_dc_key(talloc_tos(), domain_name);
1486         if (key == NULL) {
1487                 goto done;
1488         }
1489
1490         value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1491         if (value == NULL) {
1492                 goto done;
1493         }
1494
1495         gencache_set(key, value, 0x7fffffff);
1496 done:
1497         TALLOC_FREE(value);
1498         TALLOC_FREE(key);
1499 }
1500
1501 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1502                                     const char *domain_name,
1503                                     char **p_dc_name, char **p_dc_ip)
1504 {
1505         char *key, *value, *p;
1506         bool ret = false;
1507         char *dc_name = NULL;
1508         char *dc_ip = NULL;
1509
1510         key = current_dc_key(talloc_tos(), domain_name);
1511         if (key == NULL) {
1512                 goto done;
1513         }
1514         if (!gencache_get(key, &value, NULL)) {
1515                 goto done;
1516         }
1517         p = strchr(value, ' ');
1518         if (p == NULL) {
1519                 goto done;
1520         }
1521         dc_ip = talloc_strndup(mem_ctx, value, p - value);
1522         if (dc_ip == NULL) {
1523                 goto done;
1524         }
1525         dc_name = talloc_strdup(mem_ctx, p+1);
1526         if (dc_name == NULL) {
1527                 goto done;
1528         }
1529
1530         if (p_dc_ip != NULL) {
1531                 *p_dc_ip = dc_ip;
1532                 dc_ip = NULL;
1533         }
1534         if (p_dc_name != NULL) {
1535                 *p_dc_name = dc_name;
1536                 dc_name = NULL;
1537         }
1538         ret = true;
1539 done:
1540         TALLOC_FREE(dc_name);
1541         TALLOC_FREE(dc_ip);
1542         TALLOC_FREE(key);
1543         return ret;
1544 }
1545
1546 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1547                                    struct winbindd_cm_conn *new_conn)
1548 {
1549         TALLOC_CTX *mem_ctx;
1550         NTSTATUS result;
1551         char *saf_servername = saf_fetch( domain->name );
1552         int retries;
1553
1554         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1555                 SAFE_FREE(saf_servername);
1556                 set_domain_offline(domain);
1557                 return NT_STATUS_NO_MEMORY;
1558         }
1559
1560         /* we have to check the server affinity cache here since 
1561            later we select a DC based on response time and not preference */
1562
1563         /* Check the negative connection cache
1564            before talking to it. It going down may have
1565            triggered the reconnection. */
1566
1567         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1568
1569                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1570                         saf_servername, domain->name ));
1571
1572                 /* convert an ip address to a name */
1573                 if (is_ipaddress( saf_servername ) ) {
1574                         char *dcname = NULL;
1575                         struct sockaddr_storage ss;
1576
1577                         if (!interpret_string_addr(&ss, saf_servername,
1578                                                 AI_NUMERICHOST)) {
1579                                 return NT_STATUS_UNSUCCESSFUL;
1580                         }
1581                         if (dcip_to_name(mem_ctx, domain, &ss, &dcname)) {
1582                                 domain->dcname = talloc_strdup(domain,
1583                                                                dcname);
1584                                 if (domain->dcname == NULL) {
1585                                         SAFE_FREE(saf_servername);
1586                                         return NT_STATUS_NO_MEMORY;
1587                                 }
1588                         } else {
1589                                 winbind_add_failed_connection_entry(
1590                                         domain, saf_servername,
1591                                         NT_STATUS_UNSUCCESSFUL);
1592                         }
1593                 } else {
1594                         domain->dcname = talloc_strdup(domain, saf_servername);
1595                         if (domain->dcname == NULL) {
1596                                 SAFE_FREE(saf_servername);
1597                                 return NT_STATUS_NO_MEMORY;
1598                         }
1599                 }
1600
1601                 SAFE_FREE( saf_servername );
1602         }
1603
1604         for (retries = 0; retries < 3; retries++) {
1605                 int fd = -1;
1606                 bool retry = False;
1607                 char *dcname = NULL;
1608
1609                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1610
1611                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1612                         domain->dcname ? domain->dcname : "", domain->name ));
1613
1614                 if (domain->dcname != NULL
1615                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1616                         && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1617                 {
1618                         NTSTATUS status;
1619
1620                         status = smbsock_connect(&domain->dcaddr, 0,
1621                                                  NULL, -1, NULL, -1,
1622                                                  &fd, NULL, 10);
1623                         if (!NT_STATUS_IS_OK(status)) {
1624                                 fd = -1;
1625                         }
1626                 }
1627
1628                 if ((fd == -1) &&
1629                     !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd))
1630                 {
1631                         /* This is the one place where we will
1632                            set the global winbindd offline state
1633                            to true, if a "WINBINDD_OFFLINE" entry
1634                            is found in the winbindd cache. */
1635                         set_global_winbindd_state_offline();
1636                         break;
1637                 }
1638                 if (dcname != NULL) {
1639                         talloc_free(domain->dcname);
1640
1641                         domain->dcname = talloc_move(domain, &dcname);
1642                         if (domain->dcname == NULL) {
1643                                 result = NT_STATUS_NO_MEMORY;
1644                                 break;
1645                         }
1646                 }
1647
1648                 new_conn->cli = NULL;
1649
1650                 result = cm_prepare_connection(domain, fd, domain->dcname,
1651                         &new_conn->cli, &retry);
1652                 if (!NT_STATUS_IS_OK(result)) {
1653                         /* Don't leak the smb connection socket */
1654                         close(fd);
1655                 }
1656
1657                 if (!retry)
1658                         break;
1659         }
1660
1661         if (NT_STATUS_IS_OK(result)) {
1662
1663                 winbindd_set_locator_kdc_envs(domain);
1664
1665                 if (domain->online == False) {
1666                         /* We're changing state from offline to online. */
1667                         set_global_winbindd_state_online();
1668                 }
1669                 set_domain_online(domain);
1670
1671                 /*
1672                  * Much as I hate global state, this seems to be the point
1673                  * where we can be certain that we have a proper connection to
1674                  * a DC. wbinfo --dc-info needs that information, store it in
1675                  * gencache with a looong timeout. This will need revisiting
1676                  * once we start to connect to multiple DCs, wbcDcInfo is
1677                  * already prepared for that.
1678                  */
1679                 store_current_dc_in_gencache(domain->name, domain->dcname,
1680                                              new_conn->cli);
1681         } else {
1682                 /* Ensure we setup the retry handler. */
1683                 set_domain_offline(domain);
1684         }
1685
1686         talloc_destroy(mem_ctx);
1687         return result;
1688 }
1689
1690 /* Close down all open pipes on a connection. */
1691
1692 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1693 {
1694         NTSTATUS result;
1695
1696         /* We're closing down a possibly dead
1697            connection. Don't have impossibly long (10s) timeouts. */
1698
1699         if (conn->cli) {
1700                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1701         }
1702
1703         if (conn->samr_pipe != NULL) {
1704                 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1705                         dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1706                                           talloc_tos(),
1707                                           &conn->sam_connect_handle,
1708                                           &result);
1709                 }
1710                 TALLOC_FREE(conn->samr_pipe);
1711                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1712                 if (conn->cli) {
1713                         cli_set_timeout(conn->cli, 500);
1714                 }
1715         }
1716
1717         if (conn->lsa_pipe != NULL) {
1718                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1719                         dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1720                                          talloc_tos(),
1721                                          &conn->lsa_policy,
1722                                          &result);
1723                 }
1724                 TALLOC_FREE(conn->lsa_pipe);
1725                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1726                 if (conn->cli) {
1727                         cli_set_timeout(conn->cli, 500);
1728                 }
1729         }
1730
1731         if (conn->lsa_pipe_tcp != NULL) {
1732                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1733                         dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1734                                          talloc_tos(),
1735                                          &conn->lsa_policy,
1736                                          &result);
1737                 }
1738                 TALLOC_FREE(conn->lsa_pipe_tcp);
1739                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1740                 if (conn->cli) {
1741                         cli_set_timeout(conn->cli, 500);
1742                 }
1743         }
1744
1745         if (conn->netlogon_pipe != NULL) {
1746                 TALLOC_FREE(conn->netlogon_pipe);
1747                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1748                 if (conn->cli) {
1749                         cli_set_timeout(conn->cli, 500);
1750                 }
1751         }
1752
1753         if (conn->cli) {
1754                 cli_shutdown(conn->cli);
1755         }
1756
1757         conn->cli = NULL;
1758 }
1759
1760 void close_conns_after_fork(void)
1761 {
1762         struct winbindd_domain *domain;
1763         struct winbindd_cli_state *cli_state;
1764
1765         for (domain = domain_list(); domain; domain = domain->next) {
1766                 /*
1767                  * first close the low level SMB TCP connection
1768                  * so that we don't generate any SMBclose
1769                  * requests in invalidate_cm_connection()
1770                  */
1771                 if (cli_state_is_connected(domain->conn.cli)) {
1772                         smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
1773                 }
1774
1775                 invalidate_cm_connection(&domain->conn);
1776         }
1777
1778         for (cli_state = winbindd_client_list();
1779              cli_state != NULL;
1780              cli_state = cli_state->next) {
1781                 if (cli_state->sock >= 0) {
1782                         close(cli_state->sock);
1783                         cli_state->sock = -1;
1784                 }
1785         }
1786 }
1787
1788 static bool connection_ok(struct winbindd_domain *domain)
1789 {
1790         bool ok;
1791
1792         ok = cli_state_is_connected(domain->conn.cli);
1793         if (!ok) {
1794                 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1795                           domain->dcname, domain->name));
1796                 return False;
1797         }
1798
1799         if (domain->online == False) {
1800                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1801                 return False;
1802         }
1803
1804         return True;
1805 }
1806
1807 /* Initialize a new connection up to the RPC BIND.
1808    Bypass online status check so always does network calls. */
1809
1810 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1811 {
1812         NTSTATUS result;
1813
1814         /* Internal connections never use the network. */
1815         if (domain->internal) {
1816                 domain->initialized = True;
1817                 return NT_STATUS_OK;
1818         }
1819
1820         if (connection_ok(domain)) {
1821                 if (!domain->initialized) {
1822                         set_dc_type_and_flags(domain);
1823                 }
1824                 return NT_STATUS_OK;
1825         }
1826
1827         invalidate_cm_connection(&domain->conn);
1828
1829         result = cm_open_connection(domain, &domain->conn);
1830
1831         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1832                 set_dc_type_and_flags(domain);
1833         }
1834
1835         return result;
1836 }
1837
1838 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1839 {
1840         if (domain->internal) {
1841                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1842         }
1843
1844         if (domain->initialized && !domain->online) {
1845                 /* We check for online status elsewhere. */
1846                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1847         }
1848
1849         return init_dc_connection_network(domain);
1850 }
1851
1852 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1853 {
1854         NTSTATUS status;
1855
1856         status = init_dc_connection(domain);
1857         if (!NT_STATUS_IS_OK(status)) {
1858                 return status;
1859         }
1860
1861         if (!domain->internal && domain->conn.cli == NULL) {
1862                 /* happens for trusted domains without inbound trust */
1863                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1864         }
1865
1866         return NT_STATUS_OK;
1867 }
1868
1869 /******************************************************************************
1870  Set the trust flags (direction and forest location) for a domain
1871 ******************************************************************************/
1872
1873 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1874 {
1875         struct winbindd_domain *our_domain;
1876         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1877         WERROR werr;
1878         struct netr_DomainTrustList trusts;
1879         int i;
1880         uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1881                         NETR_TRUST_FLAG_OUTBOUND |
1882                         NETR_TRUST_FLAG_INBOUND);
1883         struct rpc_pipe_client *cli;
1884         TALLOC_CTX *mem_ctx = NULL;
1885         struct dcerpc_binding_handle *b;
1886
1887         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1888
1889         /* Our primary domain doesn't need to worry about trust flags.
1890            Force it to go through the network setup */
1891         if ( domain->primary ) {                
1892                 return False;           
1893         }
1894
1895         our_domain = find_our_domain();
1896
1897         if ( !connection_ok(our_domain) ) {
1898                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1899                 return False;
1900         }
1901
1902         /* This won't work unless our domain is AD */
1903
1904         if ( !our_domain->active_directory ) {
1905                 return False;
1906         }
1907
1908         /* Use DsEnumerateDomainTrusts to get us the trust direction
1909            and type */
1910
1911         result = cm_connect_netlogon(our_domain, &cli);
1912
1913         if (!NT_STATUS_IS_OK(result)) {
1914                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1915                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1916                           domain->name, nt_errstr(result)));
1917                 return False;
1918         }
1919
1920         b = cli->binding_handle;
1921
1922         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1923                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1924                 return False;
1925         }       
1926
1927         result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1928                                                       cli->desthost,
1929                                                       flags,
1930                                                       &trusts,
1931                                                       &werr);
1932         if (!NT_STATUS_IS_OK(result)) {
1933                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1934                         "failed to query trusted domain list: %s\n",
1935                         nt_errstr(result)));
1936                 talloc_destroy(mem_ctx);
1937                 return false;
1938         }
1939         if (!W_ERROR_IS_OK(werr)) {
1940                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1941                         "failed to query trusted domain list: %s\n",
1942                         win_errstr(werr)));
1943                 talloc_destroy(mem_ctx);
1944                 return false;
1945         }
1946
1947         /* Now find the domain name and get the flags */
1948
1949         for ( i=0; i<trusts.count; i++ ) {
1950                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1951                         domain->domain_flags          = trusts.array[i].trust_flags;
1952                         domain->domain_type           = trusts.array[i].trust_type;
1953                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
1954
1955                         if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1956                                 domain->active_directory = True;
1957
1958                         /* This flag is only set if the domain is *our* 
1959                            primary domain and the primary domain is in
1960                            native mode */
1961
1962                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1963
1964                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1965                                   "native mode.\n", domain->name, 
1966                                   domain->native_mode ? "" : "NOT "));
1967
1968                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1969                                  "running active directory.\n", domain->name, 
1970                                  domain->active_directory ? "" : "NOT "));
1971
1972                         domain->can_do_ncacn_ip_tcp = domain->active_directory;
1973                         domain->can_do_validation6 = domain->active_directory;
1974
1975                         domain->initialized = True;
1976
1977                         break;
1978                 }               
1979         }
1980
1981         talloc_destroy( mem_ctx );
1982
1983         return domain->initialized;     
1984 }
1985
1986 /******************************************************************************
1987  We can 'sense' certain things about the DC by it's replies to certain
1988  questions.
1989
1990  This tells us if this particular remote server is Active Directory, and if it
1991  is native mode.
1992 ******************************************************************************/
1993
1994 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1995 {
1996         NTSTATUS status, result;
1997         WERROR werr;
1998         TALLOC_CTX              *mem_ctx = NULL;
1999         struct rpc_pipe_client  *cli = NULL;
2000         struct policy_handle pol;
2001         union dssetup_DsRoleInfo info;
2002         union lsa_PolicyInformation *lsa_info = NULL;
2003
2004         if (!connection_ok(domain)) {
2005                 return;
2006         }
2007
2008         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2009                               domain->name);
2010         if (!mem_ctx) {
2011                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2012                 return;
2013         }
2014
2015         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2016
2017         status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2018                                           &ndr_table_dssetup,
2019                                           &cli);
2020
2021         if (!NT_STATUS_IS_OK(status)) {
2022                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2023                           "PI_DSSETUP on domain %s: (%s)\n",
2024                           domain->name, nt_errstr(status)));
2025
2026                 /* if this is just a non-AD domain we need to continue
2027                  * identifying so that we can in the end return with
2028                  * domain->initialized = True - gd */
2029
2030                 goto no_dssetup;
2031         }
2032
2033         status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2034                                                                   DS_ROLE_BASIC_INFORMATION,
2035                                                                   &info,
2036                                                                   &werr);
2037         TALLOC_FREE(cli);
2038
2039         if (NT_STATUS_IS_OK(status)) {
2040                 result = werror_to_ntstatus(werr);
2041         }
2042         if (!NT_STATUS_IS_OK(status)) {
2043                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2044                           "on domain %s failed: (%s)\n",
2045                           domain->name, nt_errstr(status)));
2046
2047                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2048                  * every opcode on the DSSETUP pipe, continue with
2049                  * no_dssetup mode here as well to get domain->initialized
2050                  * set - gd */
2051
2052                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2053                         goto no_dssetup;
2054                 }
2055
2056                 TALLOC_FREE(mem_ctx);
2057                 return;
2058         }
2059
2060         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2061             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2062                 domain->native_mode = True;
2063         } else {
2064                 domain->native_mode = False;
2065         }
2066
2067 no_dssetup:
2068         status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2069                                           &ndr_table_lsarpc, &cli);
2070
2071         if (!NT_STATUS_IS_OK(status)) {
2072                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2073                           "PI_LSARPC on domain %s: (%s)\n",
2074                           domain->name, nt_errstr(status)));
2075                 TALLOC_FREE(cli);
2076                 TALLOC_FREE(mem_ctx);
2077                 return;
2078         }
2079
2080         status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2081                                          SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2082
2083         if (NT_STATUS_IS_OK(status)) {
2084                 /* This particular query is exactly what Win2k clients use 
2085                    to determine that the DC is active directory */
2086                 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2087                                                      &pol,
2088                                                      LSA_POLICY_INFO_DNS,
2089                                                      &lsa_info,
2090                                                      &result);
2091         }
2092
2093         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2094                 domain->active_directory = True;
2095
2096                 if (lsa_info->dns.name.string) {
2097                         talloc_free(domain->name);
2098                         domain->name = talloc_strdup(domain,
2099                                                      lsa_info->dns.name.string);
2100                         if (domain->name == NULL) {
2101                                 goto done;
2102                         }
2103                 }
2104
2105                 if (lsa_info->dns.dns_domain.string) {
2106                         talloc_free(domain->alt_name);
2107                         domain->alt_name =
2108                                 talloc_strdup(domain,
2109                                               lsa_info->dns.dns_domain.string);
2110                         if (domain->alt_name == NULL) {
2111                                 goto done;
2112                         }
2113                 }
2114
2115                 /* See if we can set some domain trust flags about
2116                    ourself */
2117
2118                 if (lsa_info->dns.dns_forest.string) {
2119                         talloc_free(domain->forest_name);
2120                         domain->forest_name =
2121                                 talloc_strdup(domain,
2122                                               lsa_info->dns.dns_forest.string);
2123                         if (domain->forest_name == NULL) {
2124                                 goto done;
2125                         }
2126
2127                         if (strequal(domain->forest_name, domain->alt_name)) {
2128                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2129                         }
2130                 }
2131
2132                 if (lsa_info->dns.sid) {
2133                         sid_copy(&domain->sid, lsa_info->dns.sid);
2134                 }
2135         } else {
2136                 domain->active_directory = False;
2137
2138                 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2139                                                 SEC_FLAG_MAXIMUM_ALLOWED,
2140                                                 &pol);
2141
2142                 if (!NT_STATUS_IS_OK(status)) {
2143                         goto done;
2144                 }
2145
2146                 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2147                                                     &pol,
2148                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2149                                                     &lsa_info,
2150                                                     &result);
2151                 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2152
2153                         if (lsa_info->account_domain.name.string) {
2154                                 talloc_free(domain->name);
2155                                 domain->name =
2156                                         talloc_strdup(domain,
2157                                                       lsa_info->account_domain.name.string);
2158                         }
2159
2160                         if (lsa_info->account_domain.sid) {
2161                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2162                         }
2163                 }
2164         }
2165 done:
2166
2167         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2168                   domain->name, domain->native_mode ? "" : "NOT "));
2169
2170         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2171                   domain->name, domain->active_directory ? "" : "NOT "));
2172
2173         domain->can_do_ncacn_ip_tcp = domain->active_directory;
2174         domain->can_do_validation6 = domain->active_directory;
2175
2176         TALLOC_FREE(cli);
2177
2178         TALLOC_FREE(mem_ctx);
2179
2180         domain->initialized = True;
2181 }
2182
2183 /**********************************************************************
2184  Set the domain_flags (trust attributes, domain operating modes, etc... 
2185 ***********************************************************************/
2186
2187 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2188 {
2189         /* we always have to contact our primary domain */
2190
2191         if ( domain->primary ) {
2192                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2193                           "primary domain\n"));
2194                 set_dc_type_and_flags_connect( domain );
2195                 return;         
2196         }
2197
2198         /* Use our DC to get the information if possible */
2199
2200         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2201                 /* Otherwise, fallback to contacting the 
2202                    domain directly */
2203                 set_dc_type_and_flags_connect( domain );
2204         }
2205
2206         return;
2207 }
2208
2209
2210
2211 /**********************************************************************
2212 ***********************************************************************/
2213
2214 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2215                                    struct netlogon_creds_CredentialState **ppdc)
2216 {
2217         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2218         struct rpc_pipe_client *netlogon_pipe;
2219
2220         if (lp_client_schannel() == False) {
2221                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2222         }
2223
2224         result = cm_connect_netlogon(domain, &netlogon_pipe);
2225         if (!NT_STATUS_IS_OK(result)) {
2226                 return result;
2227         }
2228
2229         /* Return a pointer to the struct netlogon_creds_CredentialState from the
2230            netlogon pipe. */
2231
2232         if (!domain->conn.netlogon_pipe->dc) {
2233                 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2234         }
2235
2236         *ppdc = domain->conn.netlogon_pipe->dc;
2237         return NT_STATUS_OK;
2238 }
2239
2240 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2241                         struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2242 {
2243         struct winbindd_cm_conn *conn;
2244         NTSTATUS status, result;
2245         struct netlogon_creds_CredentialState *p_creds;
2246         char *machine_password = NULL;
2247         char *machine_account = NULL;
2248         const char *domain_name = NULL;
2249
2250         if (sid_check_is_our_sam(&domain->sid)) {
2251                 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2252         }
2253
2254         status = init_dc_connection_rpc(domain);
2255         if (!NT_STATUS_IS_OK(status)) {
2256                 return status;
2257         }
2258
2259         conn = &domain->conn;
2260
2261         if (rpccli_is_connected(conn->samr_pipe)) {
2262                 goto done;
2263         }
2264
2265         TALLOC_FREE(conn->samr_pipe);
2266
2267         /*
2268          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2269          * sign and sealed pipe using the machine account password by
2270          * preference. If we can't - try schannel, if that fails, try
2271          * anonymous.
2272          */
2273
2274         if ((conn->cli->user_name[0] == '\0') ||
2275             (conn->cli->domain[0] == '\0') || 
2276             (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2277         {
2278                 status = get_trust_creds(domain, &machine_password,
2279                                          &machine_account, NULL);
2280                 if (!NT_STATUS_IS_OK(status)) {
2281                         DEBUG(10, ("cm_connect_sam: No no user available for "
2282                                    "domain %s, trying schannel\n", conn->cli->domain));
2283                         goto schannel;
2284                 }
2285                 domain_name = domain->name;
2286         } else {
2287                 machine_password = SMB_STRDUP(conn->cli->password);
2288                 machine_account = SMB_STRDUP(conn->cli->user_name);
2289                 domain_name = conn->cli->domain;
2290         }
2291
2292         if (!machine_password || !machine_account) {
2293                 status = NT_STATUS_NO_MEMORY;
2294                 goto done;
2295         }
2296
2297         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2298            authenticated SAMR pipe with sign & seal. */
2299         status = cli_rpc_pipe_open_spnego(conn->cli,
2300                                           &ndr_table_samr,
2301                                           NCACN_NP,
2302                                           GENSEC_OID_NTLMSSP,
2303                                           DCERPC_AUTH_LEVEL_PRIVACY,
2304                                           smbXcli_conn_remote_name(conn->cli->conn),
2305                                           domain_name,
2306                                           machine_account,
2307                                           machine_password,
2308                                           &conn->samr_pipe);
2309
2310         if (!NT_STATUS_IS_OK(status)) {
2311                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2312                           "pipe for domain %s using NTLMSSP "
2313                           "authenticated pipe: user %s\\%s. Error was "
2314                           "%s\n", domain->name, domain_name,
2315                           machine_account, nt_errstr(status)));
2316                 goto schannel;
2317         }
2318
2319         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2320                   "domain %s using NTLMSSP authenticated "
2321                   "pipe: user %s\\%s\n", domain->name,
2322                   domain_name, machine_account));
2323
2324         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2325                                       conn->samr_pipe->desthost,
2326                                       SEC_FLAG_MAXIMUM_ALLOWED,
2327                                       &conn->sam_connect_handle,
2328                                       &result);
2329         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2330                 goto open_domain;
2331         }
2332         if (NT_STATUS_IS_OK(status)) {
2333                 status = result;
2334         }
2335
2336         DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2337                   "failed for domain %s, error was %s. Trying schannel\n",
2338                   domain->name, nt_errstr(status) ));
2339         TALLOC_FREE(conn->samr_pipe);
2340
2341  schannel:
2342
2343         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2344
2345         status = cm_get_schannel_creds(domain, &p_creds);
2346         if (!NT_STATUS_IS_OK(status)) {
2347                 /* If this call fails - conn->cli can now be NULL ! */
2348                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2349                            "for domain %s (error %s), trying anon\n",
2350                         domain->name,
2351                         nt_errstr(status) ));
2352                 goto anonymous;
2353         }
2354         status = cli_rpc_pipe_open_schannel_with_key
2355                 (conn->cli, &ndr_table_samr, NCACN_NP,
2356                  DCERPC_AUTH_LEVEL_PRIVACY,
2357                  domain->name, &p_creds, &conn->samr_pipe);
2358
2359         if (!NT_STATUS_IS_OK(status)) {
2360                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2361                           "domain %s using schannel. Error was %s\n",
2362                           domain->name, nt_errstr(status) ));
2363                 goto anonymous;
2364         }
2365         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2366                   "schannel.\n", domain->name ));
2367
2368         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2369                                       conn->samr_pipe->desthost,
2370                                       SEC_FLAG_MAXIMUM_ALLOWED,
2371                                       &conn->sam_connect_handle,
2372                                       &result);
2373         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2374                 goto open_domain;
2375         }
2376         if (NT_STATUS_IS_OK(status)) {
2377                 status = result;
2378         }
2379         DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2380                   "for domain %s, error was %s. Trying anonymous\n",
2381                   domain->name, nt_errstr(status) ));
2382         TALLOC_FREE(conn->samr_pipe);
2383
2384  anonymous:
2385
2386         /* Finally fall back to anonymous. */
2387         status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2388                                           &conn->samr_pipe);
2389
2390         if (!NT_STATUS_IS_OK(status)) {
2391                 goto done;
2392         }
2393
2394         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2395                                       conn->samr_pipe->desthost,
2396                                       SEC_FLAG_MAXIMUM_ALLOWED,
2397                                       &conn->sam_connect_handle,
2398                                       &result);
2399         if (!NT_STATUS_IS_OK(status)) {
2400                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2401                           "for domain %s Error was %s\n",
2402                           domain->name, nt_errstr(status) ));
2403                 goto done;
2404         }
2405         if (!NT_STATUS_IS_OK(result)) {
2406                 status = result;
2407                 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2408                           "for domain %s Error was %s\n",
2409                           domain->name, nt_errstr(result)));
2410                 goto done;
2411         }
2412
2413  open_domain:
2414         status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2415                                         mem_ctx,
2416                                         &conn->sam_connect_handle,
2417                                         SEC_FLAG_MAXIMUM_ALLOWED,
2418                                         &domain->sid,
2419                                         &conn->sam_domain_handle,
2420                                         &result);
2421         if (!NT_STATUS_IS_OK(status)) {
2422                 goto done;
2423         }
2424
2425         status = result;
2426  done:
2427
2428         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2429                 /*
2430                  * if we got access denied, we might just have no access rights
2431                  * to talk to the remote samr server server (e.g. when we are a
2432                  * PDC and we are connecting a w2k8 pdc via an interdomain
2433                  * trust). In that case do not invalidate the whole connection
2434                  * stack
2435                  */
2436                 TALLOC_FREE(conn->samr_pipe);
2437                 ZERO_STRUCT(conn->sam_domain_handle);
2438                 return status;
2439         } else if (!NT_STATUS_IS_OK(status)) {
2440                 invalidate_cm_connection(conn);
2441                 return status;
2442         }
2443
2444         *cli = conn->samr_pipe;
2445         *sam_handle = conn->sam_domain_handle;
2446         SAFE_FREE(machine_password);
2447         SAFE_FREE(machine_account);
2448         return status;
2449 }
2450
2451 /**********************************************************************
2452  open an schanneld ncacn_ip_tcp connection to LSA
2453 ***********************************************************************/
2454
2455 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2456                             TALLOC_CTX *mem_ctx,
2457                             struct rpc_pipe_client **cli)
2458 {
2459         struct winbindd_cm_conn *conn;
2460         struct netlogon_creds_CredentialState *creds;
2461         NTSTATUS status;
2462
2463         DEBUG(10,("cm_connect_lsa_tcp\n"));
2464
2465         status = init_dc_connection_rpc(domain);
2466         if (!NT_STATUS_IS_OK(status)) {
2467                 return status;
2468         }
2469
2470         conn = &domain->conn;
2471
2472         if (conn->lsa_pipe_tcp &&
2473             conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2474             conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2475             rpccli_is_connected(conn->lsa_pipe_tcp)) {
2476                 goto done;
2477         }
2478
2479         TALLOC_FREE(conn->lsa_pipe_tcp);
2480
2481         status = cm_get_schannel_creds(domain, &creds);
2482         if (!NT_STATUS_IS_OK(status)) {
2483                 goto done;
2484         }
2485
2486         status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2487                                                      &ndr_table_lsarpc,
2488                                                      NCACN_IP_TCP,
2489                                                      DCERPC_AUTH_LEVEL_PRIVACY,
2490                                                      domain->name,
2491                                                      &creds,
2492                                                      &conn->lsa_pipe_tcp);
2493         if (!NT_STATUS_IS_OK(status)) {
2494                 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2495                         nt_errstr(status)));
2496                 goto done;
2497         }
2498
2499  done:
2500         if (!NT_STATUS_IS_OK(status)) {
2501                 TALLOC_FREE(conn->lsa_pipe_tcp);
2502                 return status;
2503         }
2504
2505         *cli = conn->lsa_pipe_tcp;
2506
2507         return status;
2508 }
2509
2510 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2511                         struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2512 {
2513         struct winbindd_cm_conn *conn;
2514         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2515         struct netlogon_creds_CredentialState *p_creds;
2516
2517         result = init_dc_connection_rpc(domain);
2518         if (!NT_STATUS_IS_OK(result))
2519                 return result;
2520
2521         conn = &domain->conn;
2522
2523         if (rpccli_is_connected(conn->lsa_pipe)) {
2524                 goto done;
2525         }
2526
2527         TALLOC_FREE(conn->lsa_pipe);
2528
2529         if ((conn->cli->user_name[0] == '\0') ||
2530             (conn->cli->domain[0] == '\0') || 
2531             (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2532                 DEBUG(10, ("cm_connect_lsa: No no user available for "
2533                            "domain %s, trying schannel\n", conn->cli->domain));
2534                 goto schannel;
2535         }
2536
2537         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2538          * authenticated LSA pipe with sign & seal. */
2539         result = cli_rpc_pipe_open_spnego
2540                 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2541                  GENSEC_OID_NTLMSSP,
2542                  DCERPC_AUTH_LEVEL_PRIVACY,
2543                  smbXcli_conn_remote_name(conn->cli->conn),
2544                  conn->cli->domain, conn->cli->user_name, conn->cli->password,
2545                  &conn->lsa_pipe);
2546
2547         if (!NT_STATUS_IS_OK(result)) {
2548                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2549                           "domain %s using NTLMSSP authenticated pipe: user "
2550                           "%s\\%s. Error was %s. Trying schannel.\n",
2551                           domain->name, conn->cli->domain,
2552                           conn->cli->user_name, nt_errstr(result)));
2553                 goto schannel;
2554         }
2555
2556         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2557                   "NTLMSSP authenticated pipe: user %s\\%s\n",
2558                   domain->name, conn->cli->domain, conn->cli->user_name ));
2559
2560         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2561                                         SEC_FLAG_MAXIMUM_ALLOWED,
2562                                         &conn->lsa_policy);
2563         if (NT_STATUS_IS_OK(result)) {
2564                 goto done;
2565         }
2566
2567         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2568                   "schannel\n"));
2569
2570         TALLOC_FREE(conn->lsa_pipe);
2571
2572  schannel:
2573
2574         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2575
2576         result = cm_get_schannel_creds(domain, &p_creds);
2577         if (!NT_STATUS_IS_OK(result)) {
2578                 /* If this call fails - conn->cli can now be NULL ! */
2579                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2580                            "for domain %s (error %s), trying anon\n",
2581                         domain->name,
2582                         nt_errstr(result) ));
2583                 goto anonymous;
2584         }
2585         result = cli_rpc_pipe_open_schannel_with_key
2586                 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2587                  DCERPC_AUTH_LEVEL_PRIVACY,
2588                  domain->name, &p_creds, &conn->lsa_pipe);
2589
2590         if (!NT_STATUS_IS_OK(result)) {
2591                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2592                           "domain %s using schannel. Error was %s\n",
2593                           domain->name, nt_errstr(result) ));
2594                 goto anonymous;
2595         }
2596         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2597                   "schannel.\n", domain->name ));
2598
2599         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2600                                         SEC_FLAG_MAXIMUM_ALLOWED,
2601                                         &conn->lsa_policy);
2602         if (NT_STATUS_IS_OK(result)) {
2603                 goto done;
2604         }
2605
2606         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2607                   "anonymous\n"));
2608
2609         TALLOC_FREE(conn->lsa_pipe);
2610
2611  anonymous:
2612
2613         result = cli_rpc_pipe_open_noauth(conn->cli,
2614                                           &ndr_table_lsarpc,
2615                                           &conn->lsa_pipe);
2616         if (!NT_STATUS_IS_OK(result)) {
2617                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2618                 goto done;
2619         }
2620
2621         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2622                                         SEC_FLAG_MAXIMUM_ALLOWED,
2623                                         &conn->lsa_policy);
2624  done:
2625         if (!NT_STATUS_IS_OK(result)) {
2626                 invalidate_cm_connection(conn);
2627                 return result;
2628         }
2629
2630         *cli = conn->lsa_pipe;
2631         *lsa_policy = conn->lsa_policy;
2632         return result;
2633 }
2634
2635 /****************************************************************************
2636 Open a LSA connection to a DC, suiteable for LSA lookup calls.
2637 ****************************************************************************/
2638
2639 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
2640                          TALLOC_CTX *mem_ctx,
2641                          struct rpc_pipe_client **cli,
2642                          struct policy_handle *lsa_policy)
2643 {
2644         NTSTATUS status;
2645
2646         if (domain->can_do_ncacn_ip_tcp) {
2647                 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
2648                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
2649                     NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
2650                     NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
2651                         invalidate_cm_connection(&domain->conn);
2652                         status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
2653                 }
2654                 if (NT_STATUS_IS_OK(status)) {
2655                         return status;
2656                 }
2657
2658                 /*
2659                  * we tried twice to connect via ncan_ip_tcp and schannel and
2660                  * failed - maybe it is a trusted domain we can't connect to ?
2661                  * do not try tcp next time - gd
2662                  */
2663                 domain->can_do_ncacn_ip_tcp = false;
2664         }
2665
2666         status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
2667
2668         return status;
2669 }
2670
2671 /****************************************************************************
2672  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2673  session key stored in conn->netlogon_pipe->dc->sess_key.
2674 ****************************************************************************/
2675
2676 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2677                              struct rpc_pipe_client **cli)
2678 {
2679         struct winbindd_cm_conn *conn;
2680         NTSTATUS result;
2681
2682         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
2683         uint8_t  mach_pwd[16];
2684         enum netr_SchannelType sec_chan_type;
2685         const char *account_name;
2686         struct rpc_pipe_client *netlogon_pipe = NULL;
2687
2688         *cli = NULL;
2689
2690         result = init_dc_connection_rpc(domain);
2691         if (!NT_STATUS_IS_OK(result)) {
2692                 return result;
2693         }
2694
2695         conn = &domain->conn;
2696
2697         if (rpccli_is_connected(conn->netlogon_pipe)) {
2698                 *cli = conn->netlogon_pipe;
2699                 return NT_STATUS_OK;
2700         }
2701
2702         TALLOC_FREE(conn->netlogon_pipe);
2703
2704         result = cli_rpc_pipe_open_noauth(conn->cli,
2705                                           &ndr_table_netlogon,
2706                                           &netlogon_pipe);
2707         if (!NT_STATUS_IS_OK(result)) {
2708                 return result;
2709         }
2710
2711         if ((!IS_DC) && (!domain->primary)) {
2712                 /* Clear the schannel request bit and drop down */
2713                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2714                 goto no_schannel;
2715         }
2716
2717         if (lp_client_schannel() != False) {
2718                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2719         }
2720
2721         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2722                                &sec_chan_type))
2723         {
2724                 TALLOC_FREE(netlogon_pipe);
2725                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2726         }
2727
2728         result = rpccli_netlogon_setup_creds(
2729                  netlogon_pipe,
2730                  domain->dcname, /* server name. */
2731                  domain->name,   /* domain name */
2732                  lp_netbios_name(), /* client name */
2733                  account_name,   /* machine account */
2734                  mach_pwd,       /* machine password */
2735                  sec_chan_type,  /* from get_trust_pw */
2736                  &neg_flags);
2737
2738         if (!NT_STATUS_IS_OK(result)) {
2739                 TALLOC_FREE(netlogon_pipe);
2740                 return result;
2741         }
2742
2743         if ((lp_client_schannel() == True) &&
2744                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2745                 DEBUG(3, ("Server did not offer schannel\n"));
2746                 TALLOC_FREE(netlogon_pipe);
2747                 return NT_STATUS_ACCESS_DENIED;
2748         }
2749
2750  no_schannel:
2751         if ((lp_client_schannel() == False) ||
2752                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2753                 /*
2754                  * NetSamLogonEx only works for schannel
2755                  */
2756                 domain->can_do_samlogon_ex = False;
2757
2758                 /* We're done - just keep the existing connection to NETLOGON
2759                  * open */
2760                 conn->netlogon_pipe = netlogon_pipe;
2761                 *cli = conn->netlogon_pipe;
2762                 return NT_STATUS_OK;
2763         }
2764
2765         /* Using the credentials from the first pipe, open a signed and sealed
2766            second netlogon pipe. The session key is stored in the schannel
2767            part of the new pipe auth struct.
2768         */
2769
2770         result = cli_rpc_pipe_open_schannel_with_key(
2771                 conn->cli, &ndr_table_netlogon, NCACN_NP,
2772                 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2773                 &conn->netlogon_pipe);
2774
2775         /* We can now close the initial netlogon pipe. */
2776         TALLOC_FREE(netlogon_pipe);
2777
2778         if (!NT_STATUS_IS_OK(result)) {
2779                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2780                           "was %s\n", nt_errstr(result)));
2781
2782                 invalidate_cm_connection(conn);
2783                 return result;
2784         }
2785
2786         /*
2787          * Always try netr_LogonSamLogonEx. We will fall back for NT4
2788          * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2789          * supported). We used to only try SamLogonEx for AD, but
2790          * Samba DCs can also do it. And because we don't distinguish
2791          * between Samba and NT4, always try it once.
2792          */
2793         domain->can_do_samlogon_ex = true;
2794
2795         *cli = conn->netlogon_pipe;
2796         return NT_STATUS_OK;
2797 }
2798
2799 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2800                             void *private_data,
2801                             uint32_t msg_type,
2802                             struct server_id server_id,
2803                             DATA_BLOB *data)
2804 {
2805         struct winbindd_domain *domain;
2806         char *freeit = NULL;
2807         char *addr;
2808
2809         if ((data == NULL)
2810             || (data->data == NULL)
2811             || (data->length == 0)
2812             || (data->data[data->length-1] != '\0')) {
2813                 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2814                           "string\n"));
2815                 return;
2816         }
2817
2818         addr = (char *)data->data;
2819         DEBUG(10, ("IP %s dropped\n", addr));
2820
2821         if (!is_ipaddress(addr)) {
2822                 char *slash;
2823                 /*
2824                  * Some code sends us ip addresses with the /netmask
2825                  * suffix
2826                  */
2827                 slash = strchr(addr, '/');
2828                 if (slash == NULL) {
2829                         DEBUG(1, ("invalid msg_ip_dropped message: %s",
2830                                   addr));
2831                         return;
2832                 }
2833                 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2834                 if (freeit == NULL) {
2835                         DEBUG(1, ("talloc failed\n"));
2836                         return;
2837                 }
2838                 addr = freeit;
2839                 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2840         }
2841
2842         for (domain = domain_list(); domain != NULL; domain = domain->next) {
2843                 char sockaddr[INET6_ADDRSTRLEN];
2844
2845                 if (!cli_state_is_connected(domain->conn.cli)) {
2846                         continue;
2847                 }
2848
2849                 print_sockaddr(sockaddr, sizeof(sockaddr),
2850                                smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
2851
2852                 if (strequal(sockaddr, addr)) {
2853                         smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
2854                 }
2855         }
2856         TALLOC_FREE(freeit);
2857 }