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