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