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