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