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