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