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