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