s3:winbindd: make sure we don't try rpc requests against unaccessable domains
[ira/wip.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) {
1636                 domain->initialized = True;
1637                 return NT_STATUS_OK;
1638         }
1639
1640         if (!winbindd_can_contact_domain(domain)) {
1641                 invalidate_cm_connection(&domain->conn);
1642                 domain->initialized = True;
1643                 return NT_STATUS_OK;
1644         }
1645
1646         if (connection_ok(domain)) {
1647                 if (!domain->initialized) {
1648                         set_dc_type_and_flags(domain);
1649                 }
1650                 return NT_STATUS_OK;
1651         }
1652
1653         invalidate_cm_connection(&domain->conn);
1654
1655         result = cm_open_connection(domain, &domain->conn);
1656
1657         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1658                 set_dc_type_and_flags(domain);
1659         }
1660
1661         return result;
1662 }
1663
1664 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1665 {
1666         if (domain->initialized && !domain->online) {
1667                 /* We check for online status elsewhere. */
1668                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1669         }
1670
1671         return init_dc_connection_network(domain);
1672 }
1673
1674 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1675 {
1676         NTSTATUS status;
1677
1678         status = init_dc_connection(domain);
1679         if (!NT_STATUS_IS_OK(status)) {
1680                 return status;
1681         }
1682
1683         if (!domain->internal && domain->conn.cli == NULL) {
1684                 /* happens for trusted domains without inbound trust */
1685                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1686         }
1687
1688         return NT_STATUS_OK;
1689 }
1690
1691 /******************************************************************************
1692  Set the trust flags (direction and forest location) for a domain
1693 ******************************************************************************/
1694
1695 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1696 {
1697         struct winbindd_domain *our_domain;
1698         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1699         struct netr_DomainTrustList trusts;
1700         int i;
1701         uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1702                         NETR_TRUST_FLAG_OUTBOUND |
1703                         NETR_TRUST_FLAG_INBOUND);
1704         struct rpc_pipe_client *cli;
1705         TALLOC_CTX *mem_ctx = NULL;
1706
1707         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1708
1709         /* Our primary domain doesn't need to worry about trust flags.
1710            Force it to go through the network setup */
1711         if ( domain->primary ) {                
1712                 return False;           
1713         }
1714
1715         our_domain = find_our_domain();
1716
1717         if ( !connection_ok(our_domain) ) {
1718                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1719                 return False;
1720         }
1721
1722         /* This won't work unless our domain is AD */
1723
1724         if ( !our_domain->active_directory ) {
1725                 return False;
1726         }
1727
1728         /* Use DsEnumerateDomainTrusts to get us the trust direction
1729            and type */
1730
1731         result = cm_connect_netlogon(our_domain, &cli);
1732
1733         if (!NT_STATUS_IS_OK(result)) {
1734                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1735                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1736                           domain->name, nt_errstr(result)));
1737                 return False;
1738         }
1739
1740         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1741                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1742                 return False;
1743         }       
1744
1745         result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1746                                                       cli->desthost,
1747                                                       flags,
1748                                                       &trusts,
1749                                                       NULL);
1750         if (!NT_STATUS_IS_OK(result)) {
1751                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1752                         "failed to query trusted domain list: %s\n",
1753                         nt_errstr(result)));
1754                 talloc_destroy(mem_ctx);
1755                 return false;
1756         }
1757
1758         /* Now find the domain name and get the flags */
1759
1760         for ( i=0; i<trusts.count; i++ ) {
1761                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1762                         domain->domain_flags          = trusts.array[i].trust_flags;
1763                         domain->domain_type           = trusts.array[i].trust_type;
1764                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
1765
1766                         if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1767                                 domain->active_directory = True;
1768
1769                         /* This flag is only set if the domain is *our* 
1770                            primary domain and the primary domain is in
1771                            native mode */
1772
1773                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1774
1775                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1776                                   "native mode.\n", domain->name, 
1777                                   domain->native_mode ? "" : "NOT "));
1778
1779                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1780                                  "running active directory.\n", domain->name, 
1781                                  domain->active_directory ? "" : "NOT "));
1782
1783
1784                         domain->initialized = True;
1785
1786                         break;
1787                 }               
1788         }
1789
1790         talloc_destroy( mem_ctx );
1791
1792         return domain->initialized;     
1793 }
1794
1795 /******************************************************************************
1796  We can 'sense' certain things about the DC by it's replies to certain
1797  questions.
1798
1799  This tells us if this particular remote server is Active Directory, and if it
1800  is native mode.
1801 ******************************************************************************/
1802
1803 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1804 {
1805         NTSTATUS                result;
1806         WERROR werr;
1807         TALLOC_CTX              *mem_ctx = NULL;
1808         struct rpc_pipe_client  *cli = NULL;
1809         struct policy_handle pol;
1810         union dssetup_DsRoleInfo info;
1811         union lsa_PolicyInformation *lsa_info = NULL;
1812
1813         if (!connection_ok(domain)) {
1814                 return;
1815         }
1816
1817         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1818                               domain->name);
1819         if (!mem_ctx) {
1820                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1821                 return;
1822         }
1823
1824         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1825
1826         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1827                                           &ndr_table_dssetup.syntax_id,
1828                                           &cli);
1829
1830         if (!NT_STATUS_IS_OK(result)) {
1831                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1832                           "PI_DSSETUP on domain %s: (%s)\n",
1833                           domain->name, nt_errstr(result)));
1834
1835                 /* if this is just a non-AD domain we need to continue
1836                  * identifying so that we can in the end return with
1837                  * domain->initialized = True - gd */
1838
1839                 goto no_dssetup;
1840         }
1841
1842         result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1843                                                                   DS_ROLE_BASIC_INFORMATION,
1844                                                                   &info,
1845                                                                   &werr);
1846         TALLOC_FREE(cli);
1847
1848         if (!NT_STATUS_IS_OK(result)) {
1849                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1850                           "on domain %s failed: (%s)\n",
1851                           domain->name, nt_errstr(result)));
1852
1853                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1854                  * every opcode on the DSSETUP pipe, continue with
1855                  * no_dssetup mode here as well to get domain->initialized
1856                  * set - gd */
1857
1858                 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1859                         goto no_dssetup;
1860                 }
1861
1862                 TALLOC_FREE(mem_ctx);
1863                 return;
1864         }
1865
1866         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1867             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1868                 domain->native_mode = True;
1869         } else {
1870                 domain->native_mode = False;
1871         }
1872
1873 no_dssetup:
1874         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1875                                           &ndr_table_lsarpc.syntax_id, &cli);
1876
1877         if (!NT_STATUS_IS_OK(result)) {
1878                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1879                           "PI_LSARPC on domain %s: (%s)\n",
1880                           domain->name, nt_errstr(result)));
1881                 TALLOC_FREE(cli);
1882                 TALLOC_FREE(mem_ctx);
1883                 return;
1884         }
1885
1886         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
1887                                          SEC_FLAG_MAXIMUM_ALLOWED, &pol);
1888
1889         if (NT_STATUS_IS_OK(result)) {
1890                 /* This particular query is exactly what Win2k clients use 
1891                    to determine that the DC is active directory */
1892                 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1893                                                      &pol,
1894                                                      LSA_POLICY_INFO_DNS,
1895                                                      &lsa_info);
1896         }
1897
1898         if (NT_STATUS_IS_OK(result)) {
1899                 domain->active_directory = True;
1900
1901                 if (lsa_info->dns.name.string) {
1902                         fstrcpy(domain->name, lsa_info->dns.name.string);
1903                 }
1904
1905                 if (lsa_info->dns.dns_domain.string) {
1906                         fstrcpy(domain->alt_name,
1907                                 lsa_info->dns.dns_domain.string);
1908                 }
1909
1910                 /* See if we can set some domain trust flags about
1911                    ourself */
1912
1913                 if (lsa_info->dns.dns_forest.string) {
1914                         fstrcpy(domain->forest_name,
1915                                 lsa_info->dns.dns_forest.string);
1916
1917                         if (strequal(domain->forest_name, domain->alt_name)) {
1918                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1919                         }
1920                 }
1921
1922                 if (lsa_info->dns.sid) {
1923                         sid_copy(&domain->sid, lsa_info->dns.sid);
1924                 }
1925         } else {
1926                 domain->active_directory = False;
1927
1928                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
1929                                                 SEC_FLAG_MAXIMUM_ALLOWED,
1930                                                 &pol);
1931
1932                 if (!NT_STATUS_IS_OK(result)) {
1933                         goto done;
1934                 }
1935
1936                 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1937                                                     &pol,
1938                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1939                                                     &lsa_info);
1940
1941                 if (NT_STATUS_IS_OK(result)) {
1942
1943                         if (lsa_info->account_domain.name.string) {
1944                                 fstrcpy(domain->name,
1945                                         lsa_info->account_domain.name.string);
1946                         }
1947
1948                         if (lsa_info->account_domain.sid) {
1949                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1950                         }
1951                 }
1952         }
1953 done:
1954
1955         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1956                   domain->name, domain->native_mode ? "" : "NOT "));
1957
1958         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1959                   domain->name, domain->active_directory ? "" : "NOT "));
1960
1961         domain->can_do_ncacn_ip_tcp = domain->active_directory;
1962
1963         TALLOC_FREE(cli);
1964
1965         TALLOC_FREE(mem_ctx);
1966
1967         domain->initialized = True;
1968 }
1969
1970 /**********************************************************************
1971  Set the domain_flags (trust attributes, domain operating modes, etc... 
1972 ***********************************************************************/
1973
1974 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1975 {
1976         /* we always have to contact our primary domain */
1977
1978         if ( domain->primary ) {
1979                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1980                           "primary domain\n"));
1981                 set_dc_type_and_flags_connect( domain );
1982                 return;         
1983         }
1984
1985         /* Use our DC to get the information if possible */
1986
1987         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1988                 /* Otherwise, fallback to contacting the 
1989                    domain directly */
1990                 set_dc_type_and_flags_connect( domain );
1991         }
1992
1993         return;
1994 }
1995
1996
1997
1998 /**********************************************************************
1999 ***********************************************************************/
2000
2001 static bool cm_get_schannel_creds(struct winbindd_domain *domain,
2002                                    struct netlogon_creds_CredentialState **ppdc)
2003 {
2004         NTSTATUS result;
2005         struct rpc_pipe_client *netlogon_pipe;
2006
2007         if (lp_client_schannel() == False) {
2008                 return False;
2009         }
2010
2011         result = cm_connect_netlogon(domain, &netlogon_pipe);
2012         if (!NT_STATUS_IS_OK(result)) {
2013                 return False;
2014         }
2015
2016         /* Return a pointer to the struct netlogon_creds_CredentialState from the
2017            netlogon pipe. */
2018
2019         if (!domain->conn.netlogon_pipe->dc) {
2020                 return false;
2021         }
2022
2023         *ppdc = domain->conn.netlogon_pipe->dc;
2024         return True;
2025 }
2026
2027 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2028                         struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2029 {
2030         struct winbindd_cm_conn *conn;
2031         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2032         struct netlogon_creds_CredentialState *p_creds;
2033         char *machine_password = NULL;
2034         char *machine_account = NULL;
2035         char *domain_name = NULL;
2036
2037         result = init_dc_connection_rpc(domain);
2038         if (!NT_STATUS_IS_OK(result)) {
2039                 return result;
2040         }
2041
2042         conn = &domain->conn;
2043
2044         if (rpccli_is_connected(conn->samr_pipe)) {
2045                 goto done;
2046         }
2047
2048         TALLOC_FREE(conn->samr_pipe);
2049
2050         /*
2051          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2052          * sign and sealed pipe using the machine account password by
2053          * preference. If we can't - try schannel, if that fails, try
2054          * anonymous.
2055          */
2056
2057         if ((conn->cli->user_name[0] == '\0') ||
2058             (conn->cli->domain[0] == '\0') || 
2059             (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2060         {
2061                 result = get_trust_creds(domain, &machine_password,
2062                                          &machine_account, NULL);
2063                 if (!NT_STATUS_IS_OK(result)) {
2064                         DEBUG(10, ("cm_connect_sam: No no user available for "
2065                                    "domain %s, trying schannel\n", conn->cli->domain));
2066                         goto schannel;
2067                 }
2068                 domain_name = domain->name;
2069         } else {
2070                 machine_password = SMB_STRDUP(conn->cli->password);
2071                 machine_account = SMB_STRDUP(conn->cli->user_name);
2072                 domain_name = conn->cli->domain;
2073         }
2074
2075         if (!machine_password || !machine_account) {
2076                 result = NT_STATUS_NO_MEMORY;
2077                 goto done;
2078         }
2079
2080         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2081            authenticated SAMR pipe with sign & seal. */
2082         result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2083                                                   &ndr_table_samr.syntax_id,
2084                                                   NCACN_NP,
2085                                                   DCERPC_AUTH_LEVEL_PRIVACY,
2086                                                   domain_name,
2087                                                   machine_account,
2088                                                   machine_password,
2089                                                   &conn->samr_pipe);
2090
2091         if (!NT_STATUS_IS_OK(result)) {
2092                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2093                           "pipe for domain %s using NTLMSSP "
2094                           "authenticated pipe: user %s\\%s. Error was "
2095                           "%s\n", domain->name, domain_name,
2096                           machine_account, nt_errstr(result)));
2097                 goto schannel;
2098         }
2099
2100         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2101                   "domain %s using NTLMSSP authenticated "
2102                   "pipe: user %s\\%s\n", domain->name,
2103                   domain_name, machine_account));
2104
2105         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2106                                       conn->samr_pipe->desthost,
2107                                       SEC_FLAG_MAXIMUM_ALLOWED,
2108                                       &conn->sam_connect_handle);
2109         if (NT_STATUS_IS_OK(result)) {
2110                 goto open_domain;
2111         }
2112         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2113                   "failed for domain %s, error was %s. Trying schannel\n",
2114                   domain->name, nt_errstr(result) ));
2115         TALLOC_FREE(conn->samr_pipe);
2116
2117  schannel:
2118
2119         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2120
2121         if (!cm_get_schannel_creds(domain, &p_creds)) {
2122                 /* If this call fails - conn->cli can now be NULL ! */
2123                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2124                            "for domain %s, trying anon\n", domain->name));
2125                 goto anonymous;
2126         }
2127         result = cli_rpc_pipe_open_schannel_with_key
2128                 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2129                  DCERPC_AUTH_LEVEL_PRIVACY,
2130                  domain->name, &p_creds, &conn->samr_pipe);
2131
2132         if (!NT_STATUS_IS_OK(result)) {
2133                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2134                           "domain %s using schannel. Error was %s\n",
2135                           domain->name, nt_errstr(result) ));
2136                 goto anonymous;
2137         }
2138         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2139                   "schannel.\n", domain->name ));
2140
2141         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2142                                       conn->samr_pipe->desthost,
2143                                       SEC_FLAG_MAXIMUM_ALLOWED,
2144                                       &conn->sam_connect_handle);
2145         if (NT_STATUS_IS_OK(result)) {
2146                 goto open_domain;
2147         }
2148         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2149                   "for domain %s, error was %s. Trying anonymous\n",
2150                   domain->name, nt_errstr(result) ));
2151         TALLOC_FREE(conn->samr_pipe);
2152
2153  anonymous:
2154
2155         /* Finally fall back to anonymous. */
2156         result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2157                                           &conn->samr_pipe);
2158
2159         if (!NT_STATUS_IS_OK(result)) {
2160                 goto done;
2161         }
2162
2163         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2164                                       conn->samr_pipe->desthost,
2165                                       SEC_FLAG_MAXIMUM_ALLOWED,
2166                                       &conn->sam_connect_handle);
2167         if (!NT_STATUS_IS_OK(result)) {
2168                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2169                           "for domain %s Error was %s\n",
2170                           domain->name, nt_errstr(result) ));
2171                 goto done;
2172         }
2173
2174  open_domain:
2175         result = rpccli_samr_OpenDomain(conn->samr_pipe,
2176                                         mem_ctx,
2177                                         &conn->sam_connect_handle,
2178                                         SEC_FLAG_MAXIMUM_ALLOWED,
2179                                         &domain->sid,
2180                                         &conn->sam_domain_handle);
2181
2182  done:
2183
2184         if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
2185                 /*
2186                  * if we got access denied, we might just have no access rights
2187                  * to talk to the remote samr server server (e.g. when we are a
2188                  * PDC and we are connecting a w2k8 pdc via an interdomain
2189                  * trust). In that case do not invalidate the whole connection
2190                  * stack
2191                  */
2192                 TALLOC_FREE(conn->samr_pipe);
2193                 ZERO_STRUCT(conn->sam_domain_handle);
2194                 return result;
2195         } else if (!NT_STATUS_IS_OK(result)) {
2196                 invalidate_cm_connection(conn);
2197                 return result;
2198         }
2199
2200         *cli = conn->samr_pipe;
2201         *sam_handle = conn->sam_domain_handle;
2202         SAFE_FREE(machine_password);
2203         SAFE_FREE(machine_account);
2204         return result;
2205 }
2206
2207 /**********************************************************************
2208  open an schanneld ncacn_ip_tcp connection to LSA
2209 ***********************************************************************/
2210
2211 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2212                             TALLOC_CTX *mem_ctx,
2213                             struct rpc_pipe_client **cli)
2214 {
2215         struct winbindd_cm_conn *conn;
2216         NTSTATUS status;
2217
2218         DEBUG(10,("cm_connect_lsa_tcp\n"));
2219
2220         status = init_dc_connection_rpc(domain);
2221         if (!NT_STATUS_IS_OK(status)) {
2222                 return status;
2223         }
2224
2225         conn = &domain->conn;
2226
2227         if (conn->lsa_pipe_tcp &&
2228             conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2229             conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2230             rpccli_is_connected(conn->lsa_pipe_tcp)) {
2231                 goto done;
2232         }
2233
2234         TALLOC_FREE(conn->lsa_pipe_tcp);
2235
2236         status = cli_rpc_pipe_open_schannel(conn->cli,
2237                                             &ndr_table_lsarpc.syntax_id,
2238                                             NCACN_IP_TCP,
2239                                             DCERPC_AUTH_LEVEL_PRIVACY,
2240                                             domain->name,
2241                                             &conn->lsa_pipe_tcp);
2242         if (!NT_STATUS_IS_OK(status)) {
2243                 DEBUG(10,("cli_rpc_pipe_open_schannel failed: %s\n",
2244                         nt_errstr(status)));
2245                 goto done;
2246         }
2247
2248  done:
2249         if (!NT_STATUS_IS_OK(status)) {
2250                 TALLOC_FREE(conn->lsa_pipe_tcp);
2251                 return status;
2252         }
2253
2254         *cli = conn->lsa_pipe_tcp;
2255
2256         return status;
2257 }
2258
2259 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2260                         struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2261 {
2262         struct winbindd_cm_conn *conn;
2263         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2264         struct netlogon_creds_CredentialState *p_creds;
2265
2266         result = init_dc_connection_rpc(domain);
2267         if (!NT_STATUS_IS_OK(result))
2268                 return result;
2269
2270         conn = &domain->conn;
2271
2272         if (rpccli_is_connected(conn->lsa_pipe)) {
2273                 goto done;
2274         }
2275
2276         TALLOC_FREE(conn->lsa_pipe);
2277
2278         if ((conn->cli->user_name[0] == '\0') ||
2279             (conn->cli->domain[0] == '\0') || 
2280             (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2281                 DEBUG(10, ("cm_connect_lsa: No no user available for "
2282                            "domain %s, trying schannel\n", conn->cli->domain));
2283                 goto schannel;
2284         }
2285
2286         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2287          * authenticated LSA pipe with sign & seal. */
2288         result = cli_rpc_pipe_open_spnego_ntlmssp
2289                 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2290                  DCERPC_AUTH_LEVEL_PRIVACY,
2291                  conn->cli->domain, conn->cli->user_name, conn->cli->password,
2292                  &conn->lsa_pipe);
2293
2294         if (!NT_STATUS_IS_OK(result)) {
2295                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2296                           "domain %s using NTLMSSP authenticated pipe: user "
2297                           "%s\\%s. Error was %s. Trying schannel.\n",
2298                           domain->name, conn->cli->domain,
2299                           conn->cli->user_name, nt_errstr(result)));
2300                 goto schannel;
2301         }
2302
2303         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2304                   "NTLMSSP authenticated pipe: user %s\\%s\n",
2305                   domain->name, conn->cli->domain, conn->cli->user_name ));
2306
2307         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2308                                         SEC_FLAG_MAXIMUM_ALLOWED,
2309                                         &conn->lsa_policy);
2310         if (NT_STATUS_IS_OK(result)) {
2311                 goto done;
2312         }
2313
2314         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2315                   "schannel\n"));
2316
2317         TALLOC_FREE(conn->lsa_pipe);
2318
2319  schannel:
2320
2321         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2322
2323         if (!cm_get_schannel_creds(domain, &p_creds)) {
2324                 /* If this call fails - conn->cli can now be NULL ! */
2325                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2326                            "for domain %s, trying anon\n", domain->name));
2327                 goto anonymous;
2328         }
2329         result = cli_rpc_pipe_open_schannel_with_key
2330                 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2331                  DCERPC_AUTH_LEVEL_PRIVACY,
2332                  domain->name, &p_creds, &conn->lsa_pipe);
2333
2334         if (!NT_STATUS_IS_OK(result)) {
2335                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2336                           "domain %s using schannel. Error was %s\n",
2337                           domain->name, nt_errstr(result) ));
2338                 goto anonymous;
2339         }
2340         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2341                   "schannel.\n", domain->name ));
2342
2343         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2344                                         SEC_FLAG_MAXIMUM_ALLOWED,
2345                                         &conn->lsa_policy);
2346         if (NT_STATUS_IS_OK(result)) {
2347                 goto done;
2348         }
2349
2350         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2351                   "anonymous\n"));
2352
2353         TALLOC_FREE(conn->lsa_pipe);
2354
2355  anonymous:
2356
2357         result = cli_rpc_pipe_open_noauth(conn->cli,
2358                                           &ndr_table_lsarpc.syntax_id,
2359                                           &conn->lsa_pipe);
2360         if (!NT_STATUS_IS_OK(result)) {
2361                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2362                 goto done;
2363         }
2364
2365         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2366                                         SEC_FLAG_MAXIMUM_ALLOWED,
2367                                         &conn->lsa_policy);
2368  done:
2369         if (!NT_STATUS_IS_OK(result)) {
2370                 invalidate_cm_connection(conn);
2371                 return result;
2372         }
2373
2374         *cli = conn->lsa_pipe;
2375         *lsa_policy = conn->lsa_policy;
2376         return result;
2377 }
2378
2379 /****************************************************************************
2380  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2381  session key stored in conn->netlogon_pipe->dc->sess_key.
2382 ****************************************************************************/
2383
2384 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2385                              struct rpc_pipe_client **cli)
2386 {
2387         struct winbindd_cm_conn *conn;
2388         NTSTATUS result;
2389
2390         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2391         uint8  mach_pwd[16];
2392         enum netr_SchannelType sec_chan_type;
2393         const char *account_name;
2394         struct rpc_pipe_client *netlogon_pipe = NULL;
2395
2396         *cli = NULL;
2397
2398         result = init_dc_connection_rpc(domain);
2399         if (!NT_STATUS_IS_OK(result)) {
2400                 return result;
2401         }
2402
2403         conn = &domain->conn;
2404
2405         if (rpccli_is_connected(conn->netlogon_pipe)) {
2406                 *cli = conn->netlogon_pipe;
2407                 return NT_STATUS_OK;
2408         }
2409
2410         TALLOC_FREE(conn->netlogon_pipe);
2411
2412         result = cli_rpc_pipe_open_noauth(conn->cli,
2413                                           &ndr_table_netlogon.syntax_id,
2414                                           &netlogon_pipe);
2415         if (!NT_STATUS_IS_OK(result)) {
2416                 return result;
2417         }
2418
2419         if ((!IS_DC) && (!domain->primary)) {
2420                 /* Clear the schannel request bit and drop down */
2421                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2422                 goto no_schannel;
2423         }
2424
2425         if (lp_client_schannel() != False) {
2426                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2427         }
2428
2429         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2430                                &sec_chan_type))
2431         {
2432                 TALLOC_FREE(netlogon_pipe);
2433                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2434         }
2435
2436         result = rpccli_netlogon_setup_creds(
2437                  netlogon_pipe,
2438                  domain->dcname, /* server name. */
2439                  domain->name,   /* domain name */
2440                  global_myname(), /* client name */
2441                  account_name,   /* machine account */
2442                  mach_pwd,       /* machine password */
2443                  sec_chan_type,  /* from get_trust_pw */
2444                  &neg_flags);
2445
2446         if (!NT_STATUS_IS_OK(result)) {
2447                 TALLOC_FREE(netlogon_pipe);
2448                 return result;
2449         }
2450
2451         if ((lp_client_schannel() == True) &&
2452                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2453                 DEBUG(3, ("Server did not offer schannel\n"));
2454                 TALLOC_FREE(netlogon_pipe);
2455                 return NT_STATUS_ACCESS_DENIED;
2456         }
2457
2458  no_schannel:
2459         if ((lp_client_schannel() == False) ||
2460                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2461                 /*
2462                  * NetSamLogonEx only works for schannel
2463                  */
2464                 domain->can_do_samlogon_ex = False;
2465
2466                 /* We're done - just keep the existing connection to NETLOGON
2467                  * open */
2468                 conn->netlogon_pipe = netlogon_pipe;
2469                 *cli = conn->netlogon_pipe;
2470                 return NT_STATUS_OK;
2471         }
2472
2473         /* Using the credentials from the first pipe, open a signed and sealed
2474            second netlogon pipe. The session key is stored in the schannel
2475            part of the new pipe auth struct.
2476         */
2477
2478         result = cli_rpc_pipe_open_schannel_with_key(
2479                 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2480                 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2481                 &conn->netlogon_pipe);
2482
2483         /* We can now close the initial netlogon pipe. */
2484         TALLOC_FREE(netlogon_pipe);
2485
2486         if (!NT_STATUS_IS_OK(result)) {
2487                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2488                           "was %s\n", nt_errstr(result)));
2489
2490                 invalidate_cm_connection(conn);
2491                 return result;
2492         }
2493
2494         /*
2495          * Always try netr_LogonSamLogonEx. We will fall back for NT4
2496          * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2497          * supported). We used to only try SamLogonEx for AD, but
2498          * Samba DCs can also do it. And because we don't distinguish
2499          * between Samba and NT4, always try it once.
2500          */
2501         domain->can_do_samlogon_ex = true;
2502
2503         *cli = conn->netlogon_pipe;
2504         return NT_STATUS_OK;
2505 }