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