s3:winbindd: regain tickets for all ccache entries, when we go online
[kai/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
64 #undef DBGC_CLASS
65 #define DBGC_CLASS DBGC_WINBIND
66
67 struct dc_name_ip {
68         fstring name;
69         struct sockaddr_storage ss;
70 };
71
72 extern struct winbindd_methods reconnect_methods;
73 extern bool override_logfile;
74
75 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
76 static void set_dc_type_and_flags( struct winbindd_domain *domain );
77 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
78                     struct dc_name_ip **dcs, int *num_dcs);
79
80 /****************************************************************
81  Child failed to find DC's. Reschedule check.
82 ****************************************************************/
83
84 static void msg_failed_to_go_online(struct messaging_context *msg,
85                                     void *private_data,
86                                     uint32_t msg_type,
87                                     struct server_id server_id,
88                                     DATA_BLOB *data)
89 {
90         struct winbindd_domain *domain;
91         const char *domainname = (const char *)data->data;
92
93         if (data->data == NULL || data->length == 0) {
94                 return;
95         }
96
97         DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
98
99         for (domain = domain_list(); domain; domain = domain->next) {
100                 if (domain->internal) {
101                         continue;
102                 }
103
104                 if (strequal(domain->name, domainname)) {
105                         if (domain->online) {
106                                 /* We're already online, ignore. */
107                                 DEBUG(5,("msg_fail_to_go_online: domain %s "
108                                         "already online.\n", domainname));
109                                 continue;
110                         }
111
112                         /* Reschedule the online check. */
113                         set_domain_offline(domain);
114                         break;
115                 }
116         }
117 }
118
119 /****************************************************************
120  Actually cause a reconnect from a message.
121 ****************************************************************/
122
123 static void msg_try_to_go_online(struct messaging_context *msg,
124                                  void *private_data,
125                                  uint32_t msg_type,
126                                  struct server_id server_id,
127                                  DATA_BLOB *data)
128 {
129         struct winbindd_domain *domain;
130         const char *domainname = (const char *)data->data;
131
132         if (data->data == NULL || data->length == 0) {
133                 return;
134         }
135
136         DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
137
138         for (domain = domain_list(); domain; domain = domain->next) {
139                 if (domain->internal) {
140                         continue;
141                 }
142
143                 if (strequal(domain->name, domainname)) {
144
145                         if (domain->online) {
146                                 /* We're already online, ignore. */
147                                 DEBUG(5,("msg_try_to_go_online: domain %s "
148                                         "already online.\n", domainname));
149                                 continue;
150                         }
151
152                         /* This call takes care of setting the online
153                            flag to true if we connected, or re-adding
154                            the offline handler if false. Bypasses online
155                            check so always does network calls. */
156
157                         init_dc_connection_network(domain);
158                         break;
159                 }
160         }
161 }
162
163 /****************************************************************
164  Fork a child to try and contact a DC. Do this as contacting a
165  DC requires blocking lookups and we don't want to block our
166  parent.
167 ****************************************************************/
168
169 static bool fork_child_dc_connect(struct winbindd_domain *domain)
170 {
171         struct dc_name_ip *dcs = NULL;
172         int num_dcs = 0;
173         TALLOC_CTX *mem_ctx = NULL;
174         pid_t parent_pid = sys_getpid();
175
176         /* Stop zombies */
177         CatchChild();
178
179         if (domain->dc_probe_pid != (pid_t)-1) {
180                 /*
181                  * We might already have a DC probe
182                  * child working, check.
183                  */
184                 if (process_exists_by_pid(domain->dc_probe_pid)) {
185                         DEBUG(10,("fork_child_dc_connect: pid %u already "
186                                 "checking for DC's.\n",
187                                 (unsigned int)domain->dc_probe_pid));
188                         return true;
189                 }
190                 domain->dc_probe_pid = (pid_t)-1;
191         }
192
193         domain->dc_probe_pid = sys_fork();
194
195         if (domain->dc_probe_pid == (pid_t)-1) {
196                 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
197                 return False;
198         }
199
200         if (domain->dc_probe_pid != (pid_t)0) {
201                 /* Parent */
202                 messaging_register(winbind_messaging_context(), NULL,
203                                    MSG_WINBIND_TRY_TO_GO_ONLINE,
204                                    msg_try_to_go_online);
205                 messaging_register(winbind_messaging_context(), NULL,
206                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
207                                    msg_failed_to_go_online);
208                 return True;
209         }
210
211         /* Child. */
212
213         /* Leave messages blocked - we will never process one. */
214
215         if (!reinit_after_fork(winbind_messaging_context(),
216                                winbind_event_context(), true)) {
217                 DEBUG(0,("reinit_after_fork() failed\n"));
218                 messaging_send_buf(winbind_messaging_context(),
219                                    pid_to_procid(parent_pid),
220                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
221                                    (uint8 *)domain->name,
222                                    strlen(domain->name)+1);
223                 _exit(0);
224         }
225
226         close_conns_after_fork();
227
228         if (!override_logfile) {
229                 char *lfile;
230                 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) > 0) {
231                         lp_set_logfile(lfile);
232                         SAFE_FREE(lfile);
233                         reopen_logs();
234                 }
235         }
236
237         mem_ctx = talloc_init("fork_child_dc_connect");
238         if (!mem_ctx) {
239                 DEBUG(0,("talloc_init failed.\n"));
240                 messaging_send_buf(winbind_messaging_context(),
241                                    pid_to_procid(parent_pid),
242                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
243                                    (uint8 *)domain->name,
244                                    strlen(domain->name)+1);
245                 _exit(0);
246         }
247
248         if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
249                 /* Still offline ? Can't find DC's. */
250                 messaging_send_buf(winbind_messaging_context(),
251                                    pid_to_procid(parent_pid),
252                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
253                                    (uint8 *)domain->name,
254                                    strlen(domain->name)+1);
255                 _exit(0);
256         }
257
258         /* We got a DC. Send a message to our parent to get it to
259            try and do the same. */
260
261         messaging_send_buf(winbind_messaging_context(),
262                            pid_to_procid(parent_pid),
263                            MSG_WINBIND_TRY_TO_GO_ONLINE,
264                            (uint8 *)domain->name,
265                            strlen(domain->name)+1);
266         _exit(0);
267 }
268
269 /****************************************************************
270  Handler triggered if we're offline to try and detect a DC.
271 ****************************************************************/
272
273 static void check_domain_online_handler(struct event_context *ctx,
274                                         struct timed_event *te,
275                                         const struct timeval *now,
276                                         void *private_data)
277 {
278         struct winbindd_domain *domain =
279                 (struct winbindd_domain *)private_data;
280
281         DEBUG(10,("check_domain_online_handler: called for domain "
282                   "%s (online = %s)\n", domain->name, 
283                   domain->online ? "True" : "False" ));
284
285         TALLOC_FREE(domain->check_online_event);
286
287         /* Are we still in "startup" mode ? */
288
289         if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
290                 /* No longer in "startup" mode. */
291                 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
292                         domain->name ));
293                 domain->startup = False;
294         }
295
296         /* We've been told to stay offline, so stay
297            that way. */
298
299         if (get_global_winbindd_state_offline()) {
300                 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
301                         domain->name ));
302                 return;
303         }
304
305         /* Fork a child to test if it can contact a DC. 
306            If it can then send ourselves a message to
307            cause a reconnect. */
308
309         fork_child_dc_connect(domain);
310 }
311
312 /****************************************************************
313  If we're still offline setup the timeout check.
314 ****************************************************************/
315
316 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
317 {
318         int wbr = lp_winbind_reconnect_delay();
319
320         if (domain->startup) {
321                 domain->check_online_timeout = 10;
322         } else if (domain->check_online_timeout < wbr) {
323                 domain->check_online_timeout = wbr;
324         }
325 }
326
327 /****************************************************************
328  Set domain offline and also add handler to put us back online
329  if we detect a DC.
330 ****************************************************************/
331
332 void set_domain_offline(struct winbindd_domain *domain)
333 {
334         DEBUG(10,("set_domain_offline: called for domain %s\n",
335                 domain->name ));
336
337         TALLOC_FREE(domain->check_online_event);
338
339         if (domain->internal) {
340                 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
341                         domain->name ));
342                 return;
343         }
344
345         domain->online = False;
346
347         /* Offline domains are always initialized. They're
348            re-initialized when they go back online. */
349
350         domain->initialized = True;
351
352         /* We only add the timeout handler that checks and
353            allows us to go back online when we've not
354            been told to remain offline. */
355
356         if (get_global_winbindd_state_offline()) {
357                 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
358                         domain->name ));
359                 return;
360         }
361
362         /* If we're in statup mode, check again in 10 seconds, not in
363            lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
364
365         calc_new_online_timeout_check(domain);
366
367         domain->check_online_event = event_add_timed(winbind_event_context(),
368                                                 NULL,
369                                                 timeval_current_ofs(domain->check_online_timeout,0),
370                                                 "check_domain_online_handler",
371                                                 check_domain_online_handler,
372                                                 domain);
373
374         /* The above *has* to succeed for winbindd to work. */
375         if (!domain->check_online_event) {
376                 smb_panic("set_domain_offline: failed to add online handler");
377         }
378
379         DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
380                 domain->name ));
381
382         /* Send an offline message to the idmap child when our
383            primary domain goes offline */
384
385         if ( domain->primary ) {
386                 struct winbindd_child *idmap = idmap_child();
387
388                 if ( idmap->pid != 0 ) {
389                         messaging_send_buf(winbind_messaging_context(),
390                                            pid_to_procid(idmap->pid), 
391                                            MSG_WINBIND_OFFLINE, 
392                                            (uint8 *)domain->name, 
393                                            strlen(domain->name)+1);
394                 }                       
395         }
396
397         return; 
398 }
399
400 /****************************************************************
401  Set domain online - if allowed.
402 ****************************************************************/
403
404 static void set_domain_online(struct winbindd_domain *domain)
405 {
406         DEBUG(10,("set_domain_online: called for domain %s\n",
407                 domain->name ));
408
409         if (domain->internal) {
410                 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
411                         domain->name ));
412                 return;
413         }
414
415         if (get_global_winbindd_state_offline()) {
416                 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
417                         domain->name ));
418                 return;
419         }
420
421         winbindd_set_locator_kdc_envs(domain);
422
423         /* If we are waiting to get a krb5 ticket, trigger immediately. */
424         ccache_regain_all_now();
425
426         /* Ok, we're out of any startup mode now... */
427         domain->startup = False;
428
429         if (domain->online == False) {
430                 /* We were offline - now we're online. We default to
431                    using the MS-RPC backend if we started offline,
432                    and if we're going online for the first time we
433                    should really re-initialize the backends and the
434                    checks to see if we're talking to an AD or NT domain.
435                 */
436
437                 domain->initialized = False;
438
439                 /* 'reconnect_methods' is the MS-RPC backend. */
440                 if (domain->backend == &reconnect_methods) {
441                         domain->backend = NULL;
442                 }
443         }
444
445         /* Ensure we have no online timeout checks. */
446         domain->check_online_timeout = 0;
447         TALLOC_FREE(domain->check_online_event);
448
449         /* Ensure we ignore any pending child messages. */
450         messaging_deregister(winbind_messaging_context(),
451                              MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
452         messaging_deregister(winbind_messaging_context(),
453                              MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
454
455         domain->online = True;
456
457         /* Send an online message to the idmap child when our
458            primary domain comes online */
459
460         if ( domain->primary ) {
461                 struct winbindd_child *idmap = idmap_child();
462
463                 if ( idmap->pid != 0 ) {
464                         messaging_send_buf(winbind_messaging_context(),
465                                            pid_to_procid(idmap->pid), 
466                                            MSG_WINBIND_ONLINE, 
467                                            (uint8 *)domain->name, 
468                                            strlen(domain->name)+1);
469                 }                       
470         }
471
472         return; 
473 }
474
475 /****************************************************************
476  Requested to set a domain online.
477 ****************************************************************/
478
479 void set_domain_online_request(struct winbindd_domain *domain)
480 {
481         struct timeval tev;
482
483         DEBUG(10,("set_domain_online_request: called for domain %s\n",
484                 domain->name ));
485
486         if (get_global_winbindd_state_offline()) {
487                 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
488                         domain->name ));
489                 return;
490         }
491
492         /* We've been told it's safe to go online and
493            try and connect to a DC. But I don't believe it
494            because network manager seems to lie.
495            Wait at least 5 seconds. Heuristics suck... */
496
497
498         GetTimeOfDay(&tev);
499
500         /* Go into "startup" mode again. */
501         domain->startup_time = tev.tv_sec;
502         domain->startup = True;
503
504         tev.tv_sec += 5;
505
506         if (!domain->check_online_event) {
507                 /* If we've come from being globally offline we
508                    don't have a check online event handler set.
509                    We need to add one now we're trying to go
510                    back online. */
511
512                 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
513                         domain->name ));
514         }
515
516         TALLOC_FREE(domain->check_online_event);
517
518         domain->check_online_event = event_add_timed(winbind_event_context(),
519                                                      NULL,
520                                                      tev,
521                                                      "check_domain_online_handler",
522                                                      check_domain_online_handler,
523                                                      domain);
524
525         /* The above *has* to succeed for winbindd to work. */
526         if (!domain->check_online_event) {
527                 smb_panic("set_domain_online_request: failed to add online handler");
528         }
529 }
530
531 /****************************************************************
532  Add -ve connection cache entries for domain and realm.
533 ****************************************************************/
534
535 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
536                                         const char *server,
537                                         NTSTATUS result)
538 {
539         add_failed_connection_entry(domain->name, server, result);
540         /* If this was the saf name for the last thing we talked to,
541            remove it. */
542         saf_delete(domain->name);
543         if (*domain->alt_name) {
544                 add_failed_connection_entry(domain->alt_name, server, result);
545                 saf_delete(domain->alt_name);
546         }
547         winbindd_unset_locator_kdc_env(domain);
548 }
549
550 /* Choose between anonymous or authenticated connections.  We need to use
551    an authenticated connection if DCs have the RestrictAnonymous registry
552    entry set > 0, or the "Additional restrictions for anonymous
553    connections" set in the win2k Local Security Policy. 
554
555    Caller to free() result in domain, username, password
556 */
557
558 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
559 {
560         *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
561         *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
562         *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
563
564         if (*username && **username) {
565
566                 if (!*domain || !**domain)
567                         *domain = smb_xstrdup(lp_workgroup());
568
569                 if (!*password || !**password)
570                         *password = smb_xstrdup("");
571
572                 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n", 
573                           *domain, *username));
574
575         } else {
576                 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
577                 *username = smb_xstrdup("");
578                 *domain = smb_xstrdup("");
579                 *password = smb_xstrdup("");
580         }
581 }
582
583 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
584                                      fstring dcname,
585                                      struct sockaddr_storage *dc_ss)
586 {
587         struct winbindd_domain *our_domain = NULL;
588         struct rpc_pipe_client *netlogon_pipe = NULL;
589         NTSTATUS result;
590         WERROR werr;
591         TALLOC_CTX *mem_ctx;
592         unsigned int orig_timeout;
593         const char *tmp = NULL;
594         const char *p;
595
596         /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
597          * moment.... */
598
599         if (IS_DC) {
600                 return False;
601         }
602
603         if (domain->primary) {
604                 return False;
605         }
606
607         our_domain = find_our_domain();
608
609         if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
610                 return False;
611         }
612
613         result = cm_connect_netlogon(our_domain, &netlogon_pipe);
614         if (!NT_STATUS_IS_OK(result)) {
615                 talloc_destroy(mem_ctx);
616                 return False;
617         }
618
619         /* This call can take a long time - allow the server to time out.
620            35 seconds should do it. */
621
622         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
623
624         if (our_domain->active_directory) {
625                 struct netr_DsRGetDCNameInfo *domain_info = NULL;
626
627                 result = rpccli_netr_DsRGetDCName(netlogon_pipe,
628                                                   mem_ctx,
629                                                   our_domain->dcname,
630                                                   domain->name,
631                                                   NULL,
632                                                   NULL,
633                                                   DS_RETURN_DNS_NAME,
634                                                   &domain_info,
635                                                   &werr);
636                 if (W_ERROR_IS_OK(werr)) {
637                         tmp = talloc_strdup(
638                                 mem_ctx, domain_info->dc_unc);
639                         if (tmp == NULL) {
640                                 DEBUG(0, ("talloc_strdup failed\n"));
641                                 talloc_destroy(mem_ctx);
642                                 return false;
643                         }
644                         if (strlen(domain->alt_name) == 0) {
645                                 fstrcpy(domain->alt_name,
646                                         domain_info->domain_name);
647                         }
648                         if (strlen(domain->forest_name) == 0) {
649                                 fstrcpy(domain->forest_name,
650                                         domain_info->forest_name);
651                         }
652                 }
653         } else {
654                 result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
655                                                   our_domain->dcname,
656                                                   domain->name,
657                                                   &tmp,
658                                                   &werr);
659         }
660
661         /* And restore our original timeout. */
662         rpccli_set_timeout(netlogon_pipe, orig_timeout);
663
664         if (!NT_STATUS_IS_OK(result)) {
665                 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
666                         nt_errstr(result)));
667                 talloc_destroy(mem_ctx);
668                 return false;
669         }
670
671         if (!W_ERROR_IS_OK(werr)) {
672                 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
673                            win_errstr(werr)));
674                 talloc_destroy(mem_ctx);
675                 return false;
676         }
677
678         /* rpccli_netr_GetAnyDCName gives us a name with \\ */
679         p = strip_hostname(tmp);
680
681         fstrcpy(dcname, p);
682
683         talloc_destroy(mem_ctx);
684
685         DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
686
687         if (!resolve_name(dcname, dc_ss, 0x20)) {
688                 return False;
689         }
690
691         return True;
692 }
693
694 /**
695  * Helper function to assemble trust password and account name
696  */
697 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
698                                 char **machine_password,
699                                 char **machine_account,
700                                 char **machine_krb5_principal)
701 {
702         const char *account_name;
703         const char *name = NULL;
704
705         /* If we are a DC and this is not our own domain */
706
707         if (IS_DC) {
708                 name = domain->name;
709         } else {
710                 struct winbindd_domain *our_domain = find_our_domain();
711
712                 if (!our_domain)
713                         return NT_STATUS_INVALID_SERVER_STATE;          
714
715                 name = our_domain->name;                
716         }       
717
718         if (!get_trust_pw_clear(name, machine_password,
719                                 &account_name, NULL))
720         {
721                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
722         }
723
724         if ((machine_account != NULL) &&
725             (asprintf(machine_account, "%s$", account_name) == -1))
726         {
727                 return NT_STATUS_NO_MEMORY;
728         }
729
730         /* For now assume our machine account only exists in our domain */
731
732         if (machine_krb5_principal != NULL)
733         {
734                 struct winbindd_domain *our_domain = find_our_domain();
735
736                 if (!our_domain) {
737                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;                       
738                 }
739
740                 if (asprintf(machine_krb5_principal, "%s$@%s",
741                              account_name, our_domain->alt_name) == -1)
742                 {
743                         return NT_STATUS_NO_MEMORY;
744                 }
745
746                 strupper_m(*machine_krb5_principal);
747         }
748
749         return NT_STATUS_OK;
750 }
751
752 /************************************************************************
753  Given a fd with a just-connected TCP connection to a DC, open a connection
754  to the pipe.
755 ************************************************************************/
756
757 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
758                                       const int sockfd,
759                                       const char *controller,
760                                       struct cli_state **cli,
761                                       bool *retry)
762 {
763         char *machine_password = NULL;
764         char *machine_krb5_principal = NULL;
765         char *machine_account = NULL;
766         char *ipc_username = NULL;
767         char *ipc_domain = NULL;
768         char *ipc_password = NULL;
769
770         struct named_mutex *mutex;
771
772         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
773
774         struct sockaddr peeraddr;
775         socklen_t peeraddr_len;
776
777         struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
778
779         DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
780                 controller, domain->name ));
781
782         *retry = True;
783
784         mutex = grab_named_mutex(talloc_tos(), controller,
785                                  WINBIND_SERVER_MUTEX_WAIT_TIME);
786         if (mutex == NULL) {
787                 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
788                          controller));
789                 result = NT_STATUS_POSSIBLE_DEADLOCK;
790                 goto done;
791         }
792
793         if ((*cli = cli_initialise()) == NULL) {
794                 DEBUG(1, ("Could not cli_initialize\n"));
795                 result = NT_STATUS_NO_MEMORY;
796                 goto done;
797         }
798
799         (*cli)->timeout = 10000;        /* 10 seconds */
800         (*cli)->fd = sockfd;
801         fstrcpy((*cli)->desthost, controller);
802         (*cli)->use_kerberos = True;
803
804         peeraddr_len = sizeof(peeraddr);
805
806         if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
807             (peeraddr_len != sizeof(struct sockaddr_in)) ||
808             (peeraddr_in->sin_family != PF_INET))
809         {
810                 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
811                 result = NT_STATUS_UNSUCCESSFUL;
812                 goto done;
813         }
814
815         if (ntohs(peeraddr_in->sin_port) == 139) {
816                 struct nmb_name calling;
817                 struct nmb_name called;
818
819                 make_nmb_name(&calling, global_myname(), 0x0);
820                 make_nmb_name(&called, "*SMBSERVER", 0x20);
821
822                 if (!cli_session_request(*cli, &calling, &called)) {
823                         DEBUG(8, ("cli_session_request failed for %s\n",
824                                   controller));
825                         result = NT_STATUS_UNSUCCESSFUL;
826                         goto done;
827                 }
828         }
829
830         cli_setup_signing_state(*cli, Undefined);
831
832         result = cli_negprot(*cli);
833
834         if (!NT_STATUS_IS_OK(result)) {
835                 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
836                 goto done;
837         }
838
839         if (!is_dc_trusted_domain_situation(domain->name) &&
840             (*cli)->protocol >= PROTOCOL_NT1 &&
841             (*cli)->capabilities & CAP_EXTENDED_SECURITY)
842         {
843                 ADS_STATUS ads_status;
844
845                 result = get_trust_creds(domain, &machine_password,
846                                          &machine_account,
847                                          &machine_krb5_principal);
848                 if (!NT_STATUS_IS_OK(result)) {
849                         goto anon_fallback;
850                 }
851
852                 if (lp_security() == SEC_ADS) {
853
854                         /* Try a krb5 session */
855
856                         (*cli)->use_kerberos = True;
857                         DEBUG(5, ("connecting to %s from %s with kerberos principal "
858                                   "[%s] and realm [%s]\n", controller, global_myname(),
859                                   machine_krb5_principal, domain->alt_name));
860
861                         winbindd_set_locator_kdc_envs(domain);
862
863                         ads_status = cli_session_setup_spnego(*cli,
864                                                               machine_krb5_principal, 
865                                                               machine_password,
866                                                               lp_workgroup(),
867                                                               domain->name);
868
869                         if (!ADS_ERR_OK(ads_status)) {
870                                 DEBUG(4,("failed kerberos session setup with %s\n",
871                                          ads_errstr(ads_status)));
872                         }
873
874                         result = ads_ntstatus(ads_status);
875                         if (NT_STATUS_IS_OK(result)) {
876                                 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
877                                 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
878                                 goto session_setup_done;
879                         }
880                 }
881
882                 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
883                 (*cli)->use_kerberos = False;
884
885                 DEBUG(5, ("connecting to %s from %s with username "
886                           "[%s]\\[%s]\n",  controller, global_myname(),
887                           lp_workgroup(), machine_account));
888
889                 ads_status = cli_session_setup_spnego(*cli,
890                                                       machine_account, 
891                                                       machine_password, 
892                                                       lp_workgroup(),
893                                                       NULL);
894                 if (!ADS_ERR_OK(ads_status)) {
895                         DEBUG(4, ("authenticated session setup failed with %s\n",
896                                 ads_errstr(ads_status)));
897                 }
898
899                 result = ads_ntstatus(ads_status);
900                 if (NT_STATUS_IS_OK(result)) {
901                         /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
902                         cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
903                         goto session_setup_done;
904                 }
905         }
906
907         /* Fall back to non-kerberos session setup with auth_user */
908
909         (*cli)->use_kerberos = False;
910
911         cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
912
913         if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
914             (strlen(ipc_username) > 0)) {
915
916                 /* Only try authenticated if we have a username */
917
918                 DEBUG(5, ("connecting to %s from %s with username "
919                           "[%s]\\[%s]\n",  controller, global_myname(),
920                           ipc_domain, ipc_username));
921
922                 if (NT_STATUS_IS_OK(cli_session_setup(
923                                             *cli, ipc_username,
924                                             ipc_password, strlen(ipc_password)+1,
925                                             ipc_password, strlen(ipc_password)+1,
926                                             ipc_domain))) {
927                         /* Successful logon with given username. */
928                         cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
929                         goto session_setup_done;
930                 } else {
931                         DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
932                                 ipc_domain, ipc_username ));
933                 }
934         }
935
936  anon_fallback:
937
938         /* Fall back to anonymous connection, this might fail later */
939         DEBUG(10,("cm_prepare_connection: falling back to anonymous "
940                 "connection for DC %s\n",
941                 controller ));
942
943         if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
944                                               NULL, 0, ""))) {
945                 DEBUG(5, ("Connected anonymously\n"));
946                 cli_init_creds(*cli, "", "", "");
947                 goto session_setup_done;
948         }
949
950         result = cli_nt_error(*cli);
951
952         if (NT_STATUS_IS_OK(result))
953                 result = NT_STATUS_UNSUCCESSFUL;
954
955         /* We can't session setup */
956
957         goto done;
958
959  session_setup_done:
960
961         /* cache the server name for later connections */
962
963         saf_store( domain->name, (*cli)->desthost );
964         if (domain->alt_name && (*cli)->use_kerberos) {
965                 saf_store( domain->alt_name, (*cli)->desthost );
966         }
967
968         winbindd_set_locator_kdc_envs(domain);
969
970         if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
971
972                 result = cli_nt_error(*cli);
973
974                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
975
976                 if (NT_STATUS_IS_OK(result))
977                         result = NT_STATUS_UNSUCCESSFUL;
978
979                 goto done;
980         }
981
982         TALLOC_FREE(mutex);
983         *retry = False;
984
985         /* set the domain if empty; needed for schannel connections */
986         if ( !*(*cli)->domain ) {
987                 fstrcpy( (*cli)->domain, domain->name );
988         }
989
990         result = NT_STATUS_OK;
991
992  done:
993         TALLOC_FREE(mutex);
994         SAFE_FREE(machine_account);
995         SAFE_FREE(machine_password);
996         SAFE_FREE(machine_krb5_principal);
997         SAFE_FREE(ipc_username);
998         SAFE_FREE(ipc_domain);
999         SAFE_FREE(ipc_password);
1000
1001         if (!NT_STATUS_IS_OK(result)) {
1002                 winbind_add_failed_connection_entry(domain, controller, result);
1003                 if ((*cli) != NULL) {
1004                         cli_shutdown(*cli);
1005                         *cli = NULL;
1006                 }
1007         }
1008
1009         return result;
1010 }
1011
1012 /*******************************************************************
1013  Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1014  array.
1015
1016  Keeps the list unique by not adding duplicate entries.
1017
1018  @param[in] mem_ctx talloc memory context to allocate from
1019  @param[in] domain_name domain of the DC
1020  @param[in] dcname name of the DC to add to the list
1021  @param[in] pss Internet address and port pair to add to the list
1022  @param[in,out] dcs array of dc_name_ip structures to add to
1023  @param[in,out] num_dcs number of dcs returned in the dcs array
1024  @return true if the list was added to, false otherwise
1025 *******************************************************************/
1026
1027 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1028                               const char *dcname, struct sockaddr_storage *pss,
1029                               struct dc_name_ip **dcs, int *num)
1030 {
1031         int i = 0;
1032
1033         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1034                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1035                 return False;
1036         }
1037
1038         /* Make sure there's no duplicates in the list */
1039         for (i=0; i<*num; i++)
1040                 if (sockaddr_equal((struct sockaddr *)&(*dcs)[i].ss, (struct sockaddr *)pss))
1041                         return False;
1042
1043         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1044
1045         if (*dcs == NULL)
1046                 return False;
1047
1048         fstrcpy((*dcs)[*num].name, dcname);
1049         (*dcs)[*num].ss = *pss;
1050         *num += 1;
1051         return True;
1052 }
1053
1054 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1055                                   struct sockaddr_storage *pss, uint16 port,
1056                                   struct sockaddr_storage **addrs, int *num)
1057 {
1058         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1059
1060         if (*addrs == NULL) {
1061                 *num = 0;
1062                 return False;
1063         }
1064
1065         (*addrs)[*num] = *pss;
1066         set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1067
1068         *num += 1;
1069         return True;
1070 }
1071
1072 /*******************************************************************
1073  convert an ip to a name
1074 *******************************************************************/
1075
1076 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1077                 const struct winbindd_domain *domain,
1078                 struct sockaddr_storage *pss,
1079                 fstring name )
1080 {
1081         struct ip_service ip_list;
1082         uint32_t nt_version = NETLOGON_NT_VERSION_1;
1083
1084         ip_list.ss = *pss;
1085         ip_list.port = 0;
1086
1087 #ifdef WITH_ADS
1088         /* For active directory servers, try to get the ldap server name.
1089            None of these failures should be considered critical for now */
1090
1091         if (lp_security() == SEC_ADS) {
1092                 ADS_STRUCT *ads;
1093                 ADS_STATUS ads_status;
1094                 char addr[INET6_ADDRSTRLEN];
1095
1096                 print_sockaddr(addr, sizeof(addr), pss);
1097
1098                 ads = ads_init(domain->alt_name, domain->name, addr);
1099                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1100
1101                 ads_status = ads_connect(ads);
1102                 if (ADS_ERR_OK(ads_status)) {
1103                         /* We got a cldap packet. */
1104                         fstrcpy(name, ads->config.ldap_server_name);
1105                         namecache_store(name, 0x20, 1, &ip_list);
1106
1107                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1108
1109                         if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1110                                 if (ads_closest_dc(ads)) {
1111                                         char *sitename = sitename_fetch(ads->config.realm);
1112
1113                                         /* We're going to use this KDC for this realm/domain.
1114                                            If we are using sites, then force the krb5 libs
1115                                            to use this KDC. */
1116
1117                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1118                                                                         domain->name,
1119                                                                         sitename,
1120                                                                         pss);
1121
1122                                         SAFE_FREE(sitename);
1123                                 } else {
1124                                         /* use an off site KDC */
1125                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1126                                                                         domain->name,
1127                                                                         NULL,
1128                                                                         pss);
1129                                 }
1130                                 winbindd_set_locator_kdc_envs(domain);
1131
1132                                 /* Ensure we contact this DC also. */
1133                                 saf_store( domain->name, name);
1134                                 saf_store( domain->alt_name, name);
1135                         }
1136
1137                         ads_destroy( &ads );
1138                         return True;
1139                 }
1140
1141                 ads_destroy( &ads );
1142         }
1143 #endif
1144
1145         /* try GETDC requests next */
1146
1147         if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1148                                pss, domain->name, &domain->sid,
1149                                nt_version)) {
1150                 const char *dc_name = NULL;
1151                 int i;
1152                 smb_msleep(100);
1153                 for (i=0; i<5; i++) {
1154                         if (receive_getdc_response(mem_ctx, pss, domain->name,
1155                                                    &nt_version,
1156                                                    &dc_name, NULL)) {
1157                                 fstrcpy(name, dc_name);
1158                                 namecache_store(name, 0x20, 1, &ip_list);
1159                                 return True;
1160                         }
1161                         smb_msleep(500);
1162                 }
1163         }
1164
1165         /* try node status request */
1166
1167         if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1168                 namecache_store(name, 0x20, 1, &ip_list);
1169                 return True;
1170         }
1171         return False;
1172 }
1173
1174 /*******************************************************************
1175  Retrieve a list of IP addresses for domain controllers.
1176
1177  The array is sorted in the preferred connection order.
1178
1179  @param[in] mem_ctx talloc memory context to allocate from
1180  @param[in] domain domain to retrieve DCs for
1181  @param[out] dcs array of dcs that will be returned
1182  @param[out] num_dcs number of dcs returned in the dcs array
1183  @return always true
1184 *******************************************************************/
1185
1186 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1187                     struct dc_name_ip **dcs, int *num_dcs)
1188 {
1189         fstring dcname;
1190         struct  sockaddr_storage ss;
1191         struct  ip_service *ip_list = NULL;
1192         int     iplist_size = 0;
1193         int     i;
1194         bool    is_our_domain;
1195         enum security_types sec = (enum security_types)lp_security();
1196
1197         is_our_domain = strequal(domain->name, lp_workgroup());
1198
1199         /* If not our domain, get the preferred DC, by asking our primary DC */
1200         if ( !is_our_domain
1201                 && get_dc_name_via_netlogon(domain, dcname, &ss)
1202                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1203                        num_dcs) )
1204         {
1205                 char addr[INET6_ADDRSTRLEN];
1206                 print_sockaddr(addr, sizeof(addr), &ss);
1207                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1208                            dcname, addr));
1209                 return True;
1210         }
1211
1212         if (sec == SEC_ADS) {
1213                 char *sitename = NULL;
1214
1215                 /* We need to make sure we know the local site before
1216                    doing any DNS queries, as this will restrict the
1217                    get_sorted_dc_list() call below to only fetching
1218                    DNS records for the correct site. */
1219
1220                 /* Find any DC to get the site record.
1221                    We deliberately don't care about the
1222                    return here. */
1223
1224                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1225
1226                 sitename = sitename_fetch(domain->alt_name);
1227                 if (sitename) {
1228
1229                         /* Do the site-specific AD dns lookup first. */
1230                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1231                                &iplist_size, True);
1232
1233                         /* Add ips to the DC array.  We don't look up the name
1234                            of the DC in this function, but we fill in the char*
1235                            of the ip now to make the failed connection cache
1236                            work */
1237                         for ( i=0; i<iplist_size; i++ ) {
1238                                 char addr[INET6_ADDRSTRLEN];
1239                                 print_sockaddr(addr, sizeof(addr),
1240                                                 &ip_list[i].ss);
1241                                 add_one_dc_unique(mem_ctx,
1242                                                 domain->name,
1243                                                 addr,
1244                                                 &ip_list[i].ss,
1245                                                 dcs,
1246                                                 num_dcs);
1247                         }
1248
1249                         SAFE_FREE(ip_list);
1250                         SAFE_FREE(sitename);
1251                         iplist_size = 0;
1252                 }
1253
1254                 /* Now we add DCs from the main AD DNS lookup. */
1255                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1256                         &iplist_size, True);
1257
1258                 for ( i=0; i<iplist_size; i++ ) {
1259                         char addr[INET6_ADDRSTRLEN];
1260                         print_sockaddr(addr, sizeof(addr),
1261                                         &ip_list[i].ss);
1262                         add_one_dc_unique(mem_ctx,
1263                                         domain->name,
1264                                         addr,
1265                                         &ip_list[i].ss,
1266                                         dcs,
1267                                         num_dcs);
1268                 }
1269
1270                 SAFE_FREE(ip_list);
1271                 iplist_size = 0;
1272         }
1273
1274         /* Try standard netbios queries if no ADS */
1275         if (*num_dcs == 0) {
1276                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1277                        False);
1278
1279                 for ( i=0; i<iplist_size; i++ ) {
1280                         char addr[INET6_ADDRSTRLEN];
1281                         print_sockaddr(addr, sizeof(addr),
1282                                         &ip_list[i].ss);
1283                         add_one_dc_unique(mem_ctx,
1284                                         domain->name,
1285                                         addr,
1286                                         &ip_list[i].ss,
1287                                         dcs,
1288                                         num_dcs);
1289                 }
1290
1291                 SAFE_FREE(ip_list);
1292                 iplist_size = 0;
1293         }
1294
1295         return True;
1296 }
1297
1298 /*******************************************************************
1299  Find and make a connection to a DC in the given domain.
1300
1301  @param[in] mem_ctx talloc memory context to allocate from
1302  @param[in] domain domain to find a dc in
1303  @param[out] dcname NetBIOS or FQDN of DC that's connected to
1304  @param[out] pss DC Internet address and port
1305  @param[out] fd fd of the open socket connected to the newly found dc
1306  @return true when a DC connection is made, false otherwise
1307 *******************************************************************/
1308
1309 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1310                         struct winbindd_domain *domain,
1311                         fstring dcname, struct sockaddr_storage *pss, int *fd)
1312 {
1313         struct dc_name_ip *dcs = NULL;
1314         int num_dcs = 0;
1315
1316         const char **dcnames = NULL;
1317         int num_dcnames = 0;
1318
1319         struct sockaddr_storage *addrs = NULL;
1320         int num_addrs = 0;
1321
1322         int i, fd_index;
1323
1324         *fd = -1;
1325
1326  again:
1327         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1328                 return False;
1329
1330         for (i=0; i<num_dcs; i++) {
1331
1332                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1333                                     &dcnames, &num_dcnames)) {
1334                         return False;
1335                 }
1336                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1337                                       &addrs, &num_addrs)) {
1338                         return False;
1339                 }
1340
1341                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1342                                     &dcnames, &num_dcnames)) {
1343                         return False;
1344                 }
1345                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1346                                       &addrs, &num_addrs)) {
1347                         return False;
1348                 }
1349         }
1350
1351         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1352                 return False;
1353
1354         if ((addrs == NULL) || (dcnames == NULL))
1355                 return False;
1356
1357         /* 5 second timeout. */
1358         if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1359                 for (i=0; i<num_dcs; i++) {
1360                         char ab[INET6_ADDRSTRLEN];
1361                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1362                         DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1363                                 "domain %s address %s. Error was %s\n",
1364                                 domain->name, ab, strerror(errno) ));
1365                         winbind_add_failed_connection_entry(domain,
1366                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1367                 }
1368                 return False;
1369         }
1370
1371         *pss = addrs[fd_index];
1372
1373         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1374                 /* Ok, we've got a name for the DC */
1375                 fstrcpy(dcname, dcnames[fd_index]);
1376                 return True;
1377         }
1378
1379         /* Try to figure out the name */
1380         if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1381                 return True;
1382         }
1383
1384         /* We can not continue without the DC's name */
1385         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1386                                     NT_STATUS_UNSUCCESSFUL);
1387
1388         /* Throw away all arrays as we're doing this again. */
1389         TALLOC_FREE(dcs);
1390         num_dcs = 0;
1391
1392         TALLOC_FREE(dcnames);
1393         num_dcnames = 0;
1394
1395         TALLOC_FREE(addrs);
1396         num_addrs = 0;
1397
1398         close(*fd);
1399         *fd = -1;
1400
1401         goto again;
1402 }
1403
1404 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1405                                    struct winbindd_cm_conn *new_conn)
1406 {
1407         TALLOC_CTX *mem_ctx;
1408         NTSTATUS result;
1409         char *saf_servername = saf_fetch( domain->name );
1410         int retries;
1411
1412         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1413                 SAFE_FREE(saf_servername);
1414                 set_domain_offline(domain);
1415                 return NT_STATUS_NO_MEMORY;
1416         }
1417
1418         /* we have to check the server affinity cache here since 
1419            later we selecte a DC based on response time and not preference */
1420
1421         /* Check the negative connection cache
1422            before talking to it. It going down may have
1423            triggered the reconnection. */
1424
1425         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1426
1427                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1428                         saf_servername, domain->name ));
1429
1430                 /* convert an ip address to a name */
1431                 if (is_ipaddress( saf_servername ) ) {
1432                         fstring saf_name;
1433                         struct sockaddr_storage ss;
1434
1435                         if (!interpret_string_addr(&ss, saf_servername,
1436                                                 AI_NUMERICHOST)) {
1437                                 return NT_STATUS_UNSUCCESSFUL;
1438                         }
1439                         if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1440                                 fstrcpy( domain->dcname, saf_name );
1441                         } else {
1442                                 winbind_add_failed_connection_entry(
1443                                         domain, saf_servername,
1444                                         NT_STATUS_UNSUCCESSFUL);
1445                         }
1446                 } else {
1447                         fstrcpy( domain->dcname, saf_servername );
1448                 }
1449
1450                 SAFE_FREE( saf_servername );
1451         }
1452
1453         for (retries = 0; retries < 3; retries++) {
1454                 int fd = -1;
1455                 bool retry = False;
1456
1457                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1458
1459                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1460                         domain->dcname, domain->name ));
1461
1462                 if (*domain->dcname 
1463                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1464                         && (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
1465                 {
1466                         struct sockaddr_storage *addrs = NULL;
1467                         int num_addrs = 0;
1468                         int dummy = 0;
1469
1470                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1471                                 set_domain_offline(domain);
1472                                 talloc_destroy(mem_ctx);
1473                                 return NT_STATUS_NO_MEMORY;
1474                         }
1475                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1476                                 set_domain_offline(domain);
1477                                 talloc_destroy(mem_ctx);
1478                                 return NT_STATUS_NO_MEMORY;
1479                         }
1480
1481                         /* 5 second timeout. */
1482                         if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1483                                 fd = -1;
1484                         }
1485                 }
1486
1487                 if ((fd == -1) 
1488                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1489                 {
1490                         /* This is the one place where we will
1491                            set the global winbindd offline state
1492                            to true, if a "WINBINDD_OFFLINE" entry
1493                            is found in the winbindd cache. */
1494                         set_global_winbindd_state_offline();
1495                         break;
1496                 }
1497
1498                 new_conn->cli = NULL;
1499
1500                 result = cm_prepare_connection(domain, fd, domain->dcname,
1501                         &new_conn->cli, &retry);
1502
1503                 if (!retry)
1504                         break;
1505         }
1506
1507         if (NT_STATUS_IS_OK(result)) {
1508
1509                 winbindd_set_locator_kdc_envs(domain);
1510
1511                 if (domain->online == False) {
1512                         /* We're changing state from offline to online. */
1513                         set_global_winbindd_state_online();
1514                 }
1515                 set_domain_online(domain);
1516         } else {
1517                 /* Ensure we setup the retry handler. */
1518                 set_domain_offline(domain);
1519         }
1520
1521         talloc_destroy(mem_ctx);
1522         return result;
1523 }
1524
1525 /* Close down all open pipes on a connection. */
1526
1527 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1528 {
1529         /* We're closing down a possibly dead
1530            connection. Don't have impossibly long (10s) timeouts. */
1531
1532         if (conn->cli) {
1533                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1534         }
1535
1536         if (conn->samr_pipe != NULL) {
1537                 TALLOC_FREE(conn->samr_pipe);
1538                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1539                 if (conn->cli) {
1540                         cli_set_timeout(conn->cli, 500);
1541                 }
1542         }
1543
1544         if (conn->lsa_pipe != NULL) {
1545                 TALLOC_FREE(conn->lsa_pipe);
1546                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1547                 if (conn->cli) {
1548                         cli_set_timeout(conn->cli, 500);
1549                 }
1550         }
1551
1552         if (conn->netlogon_pipe != NULL) {
1553                 TALLOC_FREE(conn->netlogon_pipe);
1554                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1555                 if (conn->cli) {
1556                         cli_set_timeout(conn->cli, 500);
1557                 }
1558         }
1559
1560         if (conn->cli) {
1561                 cli_shutdown(conn->cli);
1562         }
1563
1564         conn->cli = NULL;
1565 }
1566
1567 void close_conns_after_fork(void)
1568 {
1569         struct winbindd_domain *domain;
1570
1571         for (domain = domain_list(); domain; domain = domain->next) {
1572                 if (domain->conn.cli == NULL)
1573                         continue;
1574
1575                 if (domain->conn.cli->fd == -1)
1576                         continue;
1577
1578                 close(domain->conn.cli->fd);
1579                 domain->conn.cli->fd = -1;
1580         }
1581 }
1582
1583 static bool connection_ok(struct winbindd_domain *domain)
1584 {
1585         if (domain->conn.cli == NULL) {
1586                 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1587                           "cli!\n", domain->dcname, domain->name));
1588                 return False;
1589         }
1590
1591         if (!domain->conn.cli->initialised) {
1592                 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1593                           "initialised!\n", domain->dcname, domain->name));
1594                 return False;
1595         }
1596
1597         if (domain->conn.cli->fd == -1) {
1598                 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1599                           "never started (fd == -1)\n", 
1600                           domain->dcname, domain->name));
1601                 return False;
1602         }
1603
1604         if (domain->online == False) {
1605                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1606                 return False;
1607         }
1608
1609         return True;
1610 }
1611
1612 /* Initialize a new connection up to the RPC BIND.
1613    Bypass online status check so always does network calls. */
1614
1615 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1616 {
1617         NTSTATUS result;
1618
1619         /* Internal connections never use the network. */
1620         if (domain->internal) {
1621                 domain->initialized = True;
1622                 return NT_STATUS_OK;
1623         }
1624
1625         if (connection_ok(domain)) {
1626                 if (!domain->initialized) {
1627                         set_dc_type_and_flags(domain);
1628                 }
1629                 return NT_STATUS_OK;
1630         }
1631
1632         invalidate_cm_connection(&domain->conn);
1633
1634         result = cm_open_connection(domain, &domain->conn);
1635
1636         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1637                 set_dc_type_and_flags(domain);
1638         }
1639
1640         return result;
1641 }
1642
1643 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1644 {
1645         if (domain->initialized && !domain->online) {
1646                 /* We check for online status elsewhere. */
1647                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1648         }
1649
1650         return init_dc_connection_network(domain);
1651 }
1652
1653 /******************************************************************************
1654  Set the trust flags (direction and forest location) for a domain
1655 ******************************************************************************/
1656
1657 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1658 {
1659         struct winbindd_domain *our_domain;
1660         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1661         struct netr_DomainTrustList trusts;
1662         int i;
1663         uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1664                         NETR_TRUST_FLAG_OUTBOUND |
1665                         NETR_TRUST_FLAG_INBOUND);
1666         struct rpc_pipe_client *cli;
1667         TALLOC_CTX *mem_ctx = NULL;
1668
1669         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1670
1671         /* Our primary domain doesn't need to worry about trust flags.
1672            Force it to go through the network setup */
1673         if ( domain->primary ) {                
1674                 return False;           
1675         }
1676
1677         our_domain = find_our_domain();
1678
1679         if ( !connection_ok(our_domain) ) {
1680                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1681                 return False;
1682         }
1683
1684         /* This won't work unless our domain is AD */
1685
1686         if ( !our_domain->active_directory ) {
1687                 return False;
1688         }
1689
1690         /* Use DsEnumerateDomainTrusts to get us the trust direction
1691            and type */
1692
1693         result = cm_connect_netlogon(our_domain, &cli);
1694
1695         if (!NT_STATUS_IS_OK(result)) {
1696                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1697                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1698                           domain->name, nt_errstr(result)));
1699                 return False;
1700         }
1701
1702         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1703                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1704                 return False;
1705         }       
1706
1707         result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1708                                                       cli->desthost,
1709                                                       flags,
1710                                                       &trusts,
1711                                                       NULL);
1712         if (!NT_STATUS_IS_OK(result)) {
1713                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1714                         "failed to query trusted domain list: %s\n",
1715                         nt_errstr(result)));
1716                 talloc_destroy(mem_ctx);
1717                 return false;
1718         }
1719
1720         /* Now find the domain name and get the flags */
1721
1722         for ( i=0; i<trusts.count; i++ ) {
1723                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1724                         domain->domain_flags          = trusts.array[i].trust_flags;
1725                         domain->domain_type           = trusts.array[i].trust_type;
1726                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
1727
1728                         if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1729                                 domain->active_directory = True;
1730
1731                         /* This flag is only set if the domain is *our* 
1732                            primary domain and the primary domain is in
1733                            native mode */
1734
1735                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1736
1737                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1738                                   "native mode.\n", domain->name, 
1739                                   domain->native_mode ? "" : "NOT "));
1740
1741                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1742                                  "running active directory.\n", domain->name, 
1743                                  domain->active_directory ? "" : "NOT "));
1744
1745
1746                         domain->initialized = True;
1747
1748                         if ( !winbindd_can_contact_domain( domain) )
1749                                 domain->internal = True;
1750
1751                         break;
1752                 }               
1753         }
1754
1755         talloc_destroy( mem_ctx );
1756
1757         return domain->initialized;     
1758 }
1759
1760 /******************************************************************************
1761  We can 'sense' certain things about the DC by it's replies to certain
1762  questions.
1763
1764  This tells us if this particular remote server is Active Directory, and if it
1765  is native mode.
1766 ******************************************************************************/
1767
1768 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1769 {
1770         NTSTATUS                result;
1771         WERROR werr;
1772         TALLOC_CTX              *mem_ctx = NULL;
1773         struct rpc_pipe_client  *cli;
1774         POLICY_HND pol;
1775         union dssetup_DsRoleInfo info;
1776         union lsa_PolicyInformation *lsa_info = NULL;
1777
1778         if (!connection_ok(domain)) {
1779                 return;
1780         }
1781
1782         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1783                               domain->name);
1784         if (!mem_ctx) {
1785                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1786                 return;
1787         }
1788
1789         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1790
1791         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1792                                           &ndr_table_dssetup.syntax_id,
1793                                           &cli);
1794
1795         if (!NT_STATUS_IS_OK(result)) {
1796                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1797                           "PI_DSSETUP on domain %s: (%s)\n",
1798                           domain->name, nt_errstr(result)));
1799
1800                 /* if this is just a non-AD domain we need to continue
1801                  * identifying so that we can in the end return with
1802                  * domain->initialized = True - gd */
1803
1804                 goto no_dssetup;
1805         }
1806
1807         result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1808                                                                   DS_ROLE_BASIC_INFORMATION,
1809                                                                   &info,
1810                                                                   &werr);
1811         TALLOC_FREE(cli);
1812
1813         if (!NT_STATUS_IS_OK(result)) {
1814                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1815                           "on domain %s failed: (%s)\n",
1816                           domain->name, nt_errstr(result)));
1817
1818                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1819                  * every opcode on the DSSETUP pipe, continue with
1820                  * no_dssetup mode here as well to get domain->initialized
1821                  * set - gd */
1822
1823                 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1824                         goto no_dssetup;
1825                 }
1826
1827                 TALLOC_FREE(mem_ctx);
1828                 return;
1829         }
1830
1831         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1832             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1833                 domain->native_mode = True;
1834         } else {
1835                 domain->native_mode = False;
1836         }
1837
1838 no_dssetup:
1839         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1840                                           &ndr_table_lsarpc.syntax_id, &cli);
1841
1842         if (!NT_STATUS_IS_OK(result)) {
1843                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1844                           "PI_LSARPC on domain %s: (%s)\n",
1845                           domain->name, nt_errstr(result)));
1846                 TALLOC_FREE(cli);
1847                 TALLOC_FREE(mem_ctx);
1848                 return;
1849         }
1850
1851         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
1852                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1853
1854         if (NT_STATUS_IS_OK(result)) {
1855                 /* This particular query is exactly what Win2k clients use 
1856                    to determine that the DC is active directory */
1857                 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1858                                                      &pol,
1859                                                      LSA_POLICY_INFO_DNS,
1860                                                      &lsa_info);
1861         }
1862
1863         if (NT_STATUS_IS_OK(result)) {
1864                 domain->active_directory = True;
1865
1866                 if (lsa_info->dns.name.string) {
1867                         fstrcpy(domain->name, lsa_info->dns.name.string);
1868                 }
1869
1870                 if (lsa_info->dns.dns_domain.string) {
1871                         fstrcpy(domain->alt_name,
1872                                 lsa_info->dns.dns_domain.string);
1873                 }
1874
1875                 /* See if we can set some domain trust flags about
1876                    ourself */
1877
1878                 if (lsa_info->dns.dns_forest.string) {
1879                         fstrcpy(domain->forest_name,
1880                                 lsa_info->dns.dns_forest.string);
1881
1882                         if (strequal(domain->forest_name, domain->alt_name)) {
1883                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1884                         }
1885                 }
1886
1887                 if (lsa_info->dns.sid) {
1888                         sid_copy(&domain->sid, lsa_info->dns.sid);
1889                 }
1890         } else {
1891                 domain->active_directory = False;
1892
1893                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
1894                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
1895                                                 &pol);
1896
1897                 if (!NT_STATUS_IS_OK(result)) {
1898                         goto done;
1899                 }
1900
1901                 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1902                                                     &pol,
1903                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1904                                                     &lsa_info);
1905
1906                 if (NT_STATUS_IS_OK(result)) {
1907
1908                         if (lsa_info->account_domain.name.string) {
1909                                 fstrcpy(domain->name,
1910                                         lsa_info->account_domain.name.string);
1911                         }
1912
1913                         if (lsa_info->account_domain.sid) {
1914                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1915                         }
1916                 }
1917         }
1918 done:
1919
1920         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1921                   domain->name, domain->native_mode ? "" : "NOT "));
1922
1923         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1924                   domain->name, domain->active_directory ? "" : "NOT "));
1925
1926         TALLOC_FREE(cli);
1927
1928         TALLOC_FREE(mem_ctx);
1929
1930         domain->initialized = True;
1931 }
1932
1933 /**********************************************************************
1934  Set the domain_flags (trust attributes, domain operating modes, etc... 
1935 ***********************************************************************/
1936
1937 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1938 {
1939         /* we always have to contact our primary domain */
1940
1941         if ( domain->primary ) {
1942                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1943                           "primary domain\n"));
1944                 set_dc_type_and_flags_connect( domain );
1945                 return;         
1946         }
1947
1948         /* Use our DC to get the information if possible */
1949
1950         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1951                 /* Otherwise, fallback to contacting the 
1952                    domain directly */
1953                 set_dc_type_and_flags_connect( domain );
1954         }
1955
1956         return;
1957 }
1958
1959
1960
1961 /**********************************************************************
1962 ***********************************************************************/
1963
1964 static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1965                                    struct dcinfo **ppdc)
1966 {
1967         NTSTATUS result;
1968         struct rpc_pipe_client *netlogon_pipe;
1969
1970         if (lp_client_schannel() == False) {
1971                 return False;
1972         }
1973
1974         result = cm_connect_netlogon(domain, &netlogon_pipe);
1975         if (!NT_STATUS_IS_OK(result)) {
1976                 return False;
1977         }
1978
1979         /* Return a pointer to the struct dcinfo from the
1980            netlogon pipe. */
1981
1982         if (!domain->conn.netlogon_pipe->dc) {
1983                 return false;
1984         }
1985
1986         *ppdc = domain->conn.netlogon_pipe->dc;
1987         return True;
1988 }
1989
1990 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1991                         struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1992 {
1993         struct winbindd_cm_conn *conn;
1994         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1995         fstring conn_pwd;
1996         struct dcinfo *p_dcinfo;
1997         char *machine_password = NULL;
1998         char *machine_account = NULL;
1999         char *domain_name = NULL;
2000
2001         result = init_dc_connection(domain);
2002         if (!NT_STATUS_IS_OK(result)) {
2003                 return result;
2004         }
2005
2006         conn = &domain->conn;
2007
2008         if (conn->samr_pipe != NULL) {
2009                 goto done;
2010         }
2011
2012
2013         /*
2014          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2015          * sign and sealed pipe using the machine account password by
2016          * preference. If we can't - try schannel, if that fails, try
2017          * anonymous.
2018          */
2019
2020         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2021         if ((conn->cli->user_name[0] == '\0') ||
2022             (conn->cli->domain[0] == '\0') || 
2023             (conn_pwd[0] == '\0'))
2024         {
2025                 result = get_trust_creds(domain, &machine_password,
2026                                          &machine_account, NULL);
2027                 if (!NT_STATUS_IS_OK(result)) {
2028                         DEBUG(10, ("cm_connect_sam: No no user available for "
2029                                    "domain %s, trying schannel\n", conn->cli->domain));
2030                         goto schannel;
2031                 }
2032                 domain_name = domain->name;
2033         } else {
2034                 machine_password = SMB_STRDUP(conn_pwd);                
2035                 machine_account = SMB_STRDUP(conn->cli->user_name);
2036                 domain_name = conn->cli->domain;
2037         }
2038
2039         if (!machine_password || !machine_account) {
2040                 result = NT_STATUS_NO_MEMORY;
2041                 goto done;
2042         }
2043
2044         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2045            authenticated SAMR pipe with sign & seal. */
2046         result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2047                                                   &ndr_table_samr.syntax_id,
2048                                                   PIPE_AUTH_LEVEL_PRIVACY,
2049                                                   domain_name,
2050                                                   machine_account,
2051                                                   machine_password,
2052                                                   &conn->samr_pipe);
2053
2054         if (!NT_STATUS_IS_OK(result)) {
2055                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2056                           "pipe for domain %s using NTLMSSP "
2057                           "authenticated pipe: user %s\\%s. Error was "
2058                           "%s\n", domain->name, domain_name,
2059                           machine_account, nt_errstr(result)));
2060                 goto schannel;
2061         }
2062
2063         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2064                   "domain %s using NTLMSSP authenticated "
2065                   "pipe: user %s\\%s\n", domain->name,
2066                   domain_name, machine_account));
2067
2068         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2069                                       conn->samr_pipe->desthost,
2070                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2071                                       &conn->sam_connect_handle);
2072         if (NT_STATUS_IS_OK(result)) {
2073                 goto open_domain;
2074         }
2075         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2076                   "failed for domain %s, error was %s. Trying schannel\n",
2077                   domain->name, nt_errstr(result) ));
2078         TALLOC_FREE(conn->samr_pipe);
2079
2080  schannel:
2081
2082         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2083
2084         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2085                 /* If this call fails - conn->cli can now be NULL ! */
2086                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2087                            "for domain %s, trying anon\n", domain->name));
2088                 goto anonymous;
2089         }
2090         result = cli_rpc_pipe_open_schannel_with_key
2091                 (conn->cli, &ndr_table_samr.syntax_id, PIPE_AUTH_LEVEL_PRIVACY,
2092                  domain->name, p_dcinfo, &conn->samr_pipe);
2093
2094         if (!NT_STATUS_IS_OK(result)) {
2095                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2096                           "domain %s using schannel. Error was %s\n",
2097                           domain->name, nt_errstr(result) ));
2098                 goto anonymous;
2099         }
2100         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2101                   "schannel.\n", domain->name ));
2102
2103         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2104                                       conn->samr_pipe->desthost,
2105                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2106                                       &conn->sam_connect_handle);
2107         if (NT_STATUS_IS_OK(result)) {
2108                 goto open_domain;
2109         }
2110         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2111                   "for domain %s, error was %s. Trying anonymous\n",
2112                   domain->name, nt_errstr(result) ));
2113         TALLOC_FREE(conn->samr_pipe);
2114
2115  anonymous:
2116
2117         /* Finally fall back to anonymous. */
2118         result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2119                                           &conn->samr_pipe);
2120
2121         if (!NT_STATUS_IS_OK(result)) {
2122                 goto done;
2123         }
2124
2125         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2126                                       conn->samr_pipe->desthost,
2127                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2128                                       &conn->sam_connect_handle);
2129         if (!NT_STATUS_IS_OK(result)) {
2130                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2131                           "for domain %s Error was %s\n",
2132                           domain->name, nt_errstr(result) ));
2133                 goto done;
2134         }
2135
2136  open_domain:
2137         result = rpccli_samr_OpenDomain(conn->samr_pipe,
2138                                         mem_ctx,
2139                                         &conn->sam_connect_handle,
2140                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2141                                         &domain->sid,
2142                                         &conn->sam_domain_handle);
2143
2144  done:
2145
2146         if (!NT_STATUS_IS_OK(result)) {
2147                 invalidate_cm_connection(conn);
2148                 return result;
2149         }
2150
2151         *cli = conn->samr_pipe;
2152         *sam_handle = conn->sam_domain_handle;
2153         SAFE_FREE(machine_password);
2154         SAFE_FREE(machine_account);
2155         return result;
2156 }
2157
2158 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2159                         struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
2160 {
2161         struct winbindd_cm_conn *conn;
2162         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2163         fstring conn_pwd;
2164         struct dcinfo *p_dcinfo;
2165
2166         result = init_dc_connection(domain);
2167         if (!NT_STATUS_IS_OK(result))
2168                 return result;
2169
2170         conn = &domain->conn;
2171
2172         if (conn->lsa_pipe != NULL) {
2173                 goto done;
2174         }
2175
2176         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2177         if ((conn->cli->user_name[0] == '\0') ||
2178             (conn->cli->domain[0] == '\0') || 
2179             (conn_pwd[0] == '\0')) {
2180                 DEBUG(10, ("cm_connect_lsa: No no user available for "
2181                            "domain %s, trying schannel\n", conn->cli->domain));
2182                 goto schannel;
2183         }
2184
2185         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2186          * authenticated LSA pipe with sign & seal. */
2187         result = cli_rpc_pipe_open_spnego_ntlmssp
2188                 (conn->cli, &ndr_table_lsarpc.syntax_id,
2189                  PIPE_AUTH_LEVEL_PRIVACY,
2190                  conn->cli->domain, conn->cli->user_name, conn_pwd,
2191                  &conn->lsa_pipe);
2192
2193         if (!NT_STATUS_IS_OK(result)) {
2194                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2195                           "domain %s using NTLMSSP authenticated pipe: user "
2196                           "%s\\%s. Error was %s. Trying schannel.\n",
2197                           domain->name, conn->cli->domain,
2198                           conn->cli->user_name, nt_errstr(result)));
2199                 goto schannel;
2200         }
2201
2202         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2203                   "NTLMSSP authenticated pipe: user %s\\%s\n",
2204                   domain->name, conn->cli->domain, conn->cli->user_name ));
2205
2206         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2207                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2208                                         &conn->lsa_policy);
2209         if (NT_STATUS_IS_OK(result)) {
2210                 goto done;
2211         }
2212
2213         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2214                   "schannel\n"));
2215
2216         TALLOC_FREE(conn->lsa_pipe);
2217
2218  schannel:
2219
2220         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2221
2222         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2223                 /* If this call fails - conn->cli can now be NULL ! */
2224                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2225                            "for domain %s, trying anon\n", domain->name));
2226                 goto anonymous;
2227         }
2228         result = cli_rpc_pipe_open_schannel_with_key
2229                 (conn->cli, &ndr_table_lsarpc.syntax_id,
2230                  PIPE_AUTH_LEVEL_PRIVACY,
2231                  domain->name, p_dcinfo, &conn->lsa_pipe);
2232
2233         if (!NT_STATUS_IS_OK(result)) {
2234                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2235                           "domain %s using schannel. Error was %s\n",
2236                           domain->name, nt_errstr(result) ));
2237                 goto anonymous;
2238         }
2239         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2240                   "schannel.\n", domain->name ));
2241
2242         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2243                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2244                                         &conn->lsa_policy);
2245         if (NT_STATUS_IS_OK(result)) {
2246                 goto done;
2247         }
2248
2249         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2250                   "anonymous\n"));
2251
2252         TALLOC_FREE(conn->lsa_pipe);
2253
2254  anonymous:
2255
2256         result = cli_rpc_pipe_open_noauth(conn->cli,
2257                                           &ndr_table_lsarpc.syntax_id,
2258                                           &conn->lsa_pipe);
2259         if (!NT_STATUS_IS_OK(result)) {
2260                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2261                 goto done;
2262         }
2263
2264         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2265                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2266                                         &conn->lsa_policy);
2267  done:
2268         if (!NT_STATUS_IS_OK(result)) {
2269                 invalidate_cm_connection(conn);
2270                 return result;
2271         }
2272
2273         *cli = conn->lsa_pipe;
2274         *lsa_policy = conn->lsa_policy;
2275         return result;
2276 }
2277
2278 /****************************************************************************
2279  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2280  session key stored in conn->netlogon_pipe->dc->sess_key.
2281 ****************************************************************************/
2282
2283 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2284                              struct rpc_pipe_client **cli)
2285 {
2286         struct winbindd_cm_conn *conn;
2287         NTSTATUS result;
2288
2289         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2290         uint8  mach_pwd[16];
2291         uint32  sec_chan_type;
2292         const char *account_name;
2293         struct rpc_pipe_client *netlogon_pipe = NULL;
2294
2295         *cli = NULL;
2296
2297         result = init_dc_connection(domain);
2298         if (!NT_STATUS_IS_OK(result)) {
2299                 return result;
2300         }
2301
2302         conn = &domain->conn;
2303
2304         if (conn->netlogon_pipe != NULL) {
2305                 *cli = conn->netlogon_pipe;
2306                 return NT_STATUS_OK;
2307         }
2308
2309         result = cli_rpc_pipe_open_noauth(conn->cli,
2310                                           &ndr_table_netlogon.syntax_id,
2311                                           &netlogon_pipe);
2312         if (!NT_STATUS_IS_OK(result)) {
2313                 return result;
2314         }
2315
2316         if ((!IS_DC) && (!domain->primary)) {
2317                 /* Clear the schannel request bit and drop down */
2318                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2319                 goto no_schannel;
2320         }
2321
2322         if (lp_client_schannel() != False) {
2323                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2324         }
2325
2326         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2327                                &sec_chan_type))
2328         {
2329                 TALLOC_FREE(netlogon_pipe);
2330                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2331         }
2332
2333         result = rpccli_netlogon_setup_creds(
2334                  netlogon_pipe,
2335                  domain->dcname, /* server name. */
2336                  domain->name,   /* domain name */
2337                  global_myname(), /* client name */
2338                  account_name,   /* machine account */
2339                  mach_pwd,       /* machine password */
2340                  sec_chan_type,  /* from get_trust_pw */
2341                  &neg_flags);
2342
2343         if (!NT_STATUS_IS_OK(result)) {
2344                 TALLOC_FREE(netlogon_pipe);
2345                 return result;
2346         }
2347
2348         if ((lp_client_schannel() == True) &&
2349                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2350                 DEBUG(3, ("Server did not offer schannel\n"));
2351                 TALLOC_FREE(netlogon_pipe);
2352                 return NT_STATUS_ACCESS_DENIED;
2353         }
2354
2355  no_schannel:
2356         if ((lp_client_schannel() == False) ||
2357                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2358                 /*
2359                  * NetSamLogonEx only works for schannel
2360                  */
2361                 domain->can_do_samlogon_ex = False;
2362
2363                 /* We're done - just keep the existing connection to NETLOGON
2364                  * open */
2365                 conn->netlogon_pipe = netlogon_pipe;
2366                 *cli = conn->netlogon_pipe;
2367                 return NT_STATUS_OK;
2368         }
2369
2370         /* Using the credentials from the first pipe, open a signed and sealed
2371            second netlogon pipe. The session key is stored in the schannel
2372            part of the new pipe auth struct.
2373         */
2374
2375         result = cli_rpc_pipe_open_schannel_with_key(
2376                 conn->cli, &ndr_table_netlogon.syntax_id,
2377                 PIPE_AUTH_LEVEL_PRIVACY, domain->name, netlogon_pipe->dc,
2378                 &conn->netlogon_pipe);
2379
2380         /* We can now close the initial netlogon pipe. */
2381         TALLOC_FREE(netlogon_pipe);
2382
2383         if (!NT_STATUS_IS_OK(result)) {
2384                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2385                           "was %s\n", nt_errstr(result)));
2386
2387                 /* make sure we return something besides OK */
2388                 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2389         }
2390
2391         /*
2392          * Try NetSamLogonEx for AD domains
2393          */
2394         domain->can_do_samlogon_ex = domain->active_directory;
2395
2396         *cli = conn->netlogon_pipe;
2397         return NT_STATUS_OK;
2398 }