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