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