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