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