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