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