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