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