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