7a53f19ffd4ee94ced4f3a717277043d66b3a063
[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         result = cli_negprot(*cli);
825
826         if (!NT_STATUS_IS_OK(result)) {
827                 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
828                 goto done;
829         }
830
831         if (!is_dc_trusted_domain_situation(domain->name) &&
832             (*cli)->protocol >= PROTOCOL_NT1 &&
833             (*cli)->capabilities & CAP_EXTENDED_SECURITY)
834         {
835                 ADS_STATUS ads_status;
836
837                 result = get_trust_creds(domain, &machine_password,
838                                          &machine_account,
839                                          &machine_krb5_principal);
840                 if (!NT_STATUS_IS_OK(result)) {
841                         goto anon_fallback;
842                 }
843
844                 if (lp_security() == SEC_ADS) {
845
846                         /* Try a krb5 session */
847
848                         (*cli)->use_kerberos = True;
849                         DEBUG(5, ("connecting to %s from %s with kerberos principal "
850                                   "[%s] and realm [%s]\n", controller, global_myname(),
851                                   machine_krb5_principal, domain->alt_name));
852
853                         winbindd_set_locator_kdc_envs(domain);
854
855                         ads_status = cli_session_setup_spnego(*cli,
856                                                               machine_krb5_principal, 
857                                                               machine_password,
858                                                               lp_workgroup(),
859                                                               domain->name);
860
861                         if (!ADS_ERR_OK(ads_status)) {
862                                 DEBUG(4,("failed kerberos session setup with %s\n",
863                                          ads_errstr(ads_status)));
864                         }
865
866                         result = ads_ntstatus(ads_status);
867                         if (NT_STATUS_IS_OK(result)) {
868                                 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
869                                 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
870                                 goto session_setup_done;
871                         }
872                 }
873
874                 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
875                 (*cli)->use_kerberos = False;
876
877                 DEBUG(5, ("connecting to %s from %s with username "
878                           "[%s]\\[%s]\n",  controller, global_myname(),
879                           lp_workgroup(), machine_account));
880
881                 ads_status = cli_session_setup_spnego(*cli,
882                                                       machine_account, 
883                                                       machine_password, 
884                                                       lp_workgroup(),
885                                                       NULL);
886                 if (!ADS_ERR_OK(ads_status)) {
887                         DEBUG(4, ("authenticated session setup failed with %s\n",
888                                 ads_errstr(ads_status)));
889                 }
890
891                 result = ads_ntstatus(ads_status);
892                 if (NT_STATUS_IS_OK(result)) {
893                         /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
894                         cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
895                         goto session_setup_done;
896                 }
897         }
898
899         /* Fall back to non-kerberos session setup with auth_user */
900
901         (*cli)->use_kerberos = False;
902
903         cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
904
905         if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
906             (strlen(ipc_username) > 0)) {
907
908                 /* Only try authenticated if we have a username */
909
910                 DEBUG(5, ("connecting to %s from %s with username "
911                           "[%s]\\[%s]\n",  controller, global_myname(),
912                           ipc_domain, ipc_username));
913
914                 if (NT_STATUS_IS_OK(cli_session_setup(
915                                             *cli, ipc_username,
916                                             ipc_password, strlen(ipc_password)+1,
917                                             ipc_password, strlen(ipc_password)+1,
918                                             ipc_domain))) {
919                         /* Successful logon with given username. */
920                         cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
921                         goto session_setup_done;
922                 } else {
923                         DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
924                                 ipc_domain, ipc_username ));
925                 }
926         }
927
928  anon_fallback:
929
930         /* Fall back to anonymous connection, this might fail later */
931         DEBUG(10,("cm_prepare_connection: falling back to anonymous "
932                 "connection for DC %s\n",
933                 controller ));
934
935         if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
936                                               NULL, 0, ""))) {
937                 DEBUG(5, ("Connected anonymously\n"));
938                 cli_init_creds(*cli, "", "", "");
939                 goto session_setup_done;
940         }
941
942         result = cli_nt_error(*cli);
943
944         if (NT_STATUS_IS_OK(result))
945                 result = NT_STATUS_UNSUCCESSFUL;
946
947         /* We can't session setup */
948
949         goto done;
950
951  session_setup_done:
952
953         /* cache the server name for later connections */
954
955         saf_store( domain->name, (*cli)->desthost );
956         if (domain->alt_name && (*cli)->use_kerberos) {
957                 saf_store( domain->alt_name, (*cli)->desthost );
958         }
959
960         winbindd_set_locator_kdc_envs(domain);
961
962         result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
963
964         if (!NT_STATUS_IS_OK(result)) {
965                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
966                 goto done;
967         }
968
969         TALLOC_FREE(mutex);
970         *retry = False;
971
972         /* set the domain if empty; needed for schannel connections */
973         if ( !*(*cli)->domain ) {
974                 fstrcpy( (*cli)->domain, domain->name );
975         }
976
977         result = NT_STATUS_OK;
978
979  done:
980         TALLOC_FREE(mutex);
981         SAFE_FREE(machine_account);
982         SAFE_FREE(machine_password);
983         SAFE_FREE(machine_krb5_principal);
984         SAFE_FREE(ipc_username);
985         SAFE_FREE(ipc_domain);
986         SAFE_FREE(ipc_password);
987
988         if (!NT_STATUS_IS_OK(result)) {
989                 winbind_add_failed_connection_entry(domain, controller, result);
990                 if ((*cli) != NULL) {
991                         cli_shutdown(*cli);
992                         *cli = NULL;
993                 }
994         }
995
996         return result;
997 }
998
999 /*******************************************************************
1000  Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1001  array.
1002
1003  Keeps the list unique by not adding duplicate entries.
1004
1005  @param[in] mem_ctx talloc memory context to allocate from
1006  @param[in] domain_name domain of the DC
1007  @param[in] dcname name of the DC to add to the list
1008  @param[in] pss Internet address and port pair to add to the list
1009  @param[in,out] dcs array of dc_name_ip structures to add to
1010  @param[in,out] num_dcs number of dcs returned in the dcs array
1011  @return true if the list was added to, false otherwise
1012 *******************************************************************/
1013
1014 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1015                               const char *dcname, struct sockaddr_storage *pss,
1016                               struct dc_name_ip **dcs, int *num)
1017 {
1018         int i = 0;
1019
1020         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1021                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1022                 return False;
1023         }
1024
1025         /* Make sure there's no duplicates in the list */
1026         for (i=0; i<*num; i++)
1027                 if (sockaddr_equal((struct sockaddr *)&(*dcs)[i].ss, (struct sockaddr *)pss))
1028                         return False;
1029
1030         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1031
1032         if (*dcs == NULL)
1033                 return False;
1034
1035         fstrcpy((*dcs)[*num].name, dcname);
1036         (*dcs)[*num].ss = *pss;
1037         *num += 1;
1038         return True;
1039 }
1040
1041 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1042                                   struct sockaddr_storage *pss, uint16 port,
1043                                   struct sockaddr_storage **addrs, int *num)
1044 {
1045         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1046
1047         if (*addrs == NULL) {
1048                 *num = 0;
1049                 return False;
1050         }
1051
1052         (*addrs)[*num] = *pss;
1053         set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1054
1055         *num += 1;
1056         return True;
1057 }
1058
1059 /*******************************************************************
1060  convert an ip to a name
1061 *******************************************************************/
1062
1063 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1064                 const struct winbindd_domain *domain,
1065                 struct sockaddr_storage *pss,
1066                 fstring name )
1067 {
1068         struct ip_service ip_list;
1069         uint32_t nt_version = NETLOGON_NT_VERSION_1;
1070
1071         ip_list.ss = *pss;
1072         ip_list.port = 0;
1073
1074 #ifdef WITH_ADS
1075         /* For active directory servers, try to get the ldap server name.
1076            None of these failures should be considered critical for now */
1077
1078         if (lp_security() == SEC_ADS) {
1079                 ADS_STRUCT *ads;
1080                 ADS_STATUS ads_status;
1081                 char addr[INET6_ADDRSTRLEN];
1082
1083                 print_sockaddr(addr, sizeof(addr), pss);
1084
1085                 ads = ads_init(domain->alt_name, domain->name, addr);
1086                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1087
1088                 ads_status = ads_connect(ads);
1089                 if (ADS_ERR_OK(ads_status)) {
1090                         /* We got a cldap packet. */
1091                         fstrcpy(name, ads->config.ldap_server_name);
1092                         namecache_store(name, 0x20, 1, &ip_list);
1093
1094                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1095
1096                         if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1097                                 if (ads_closest_dc(ads)) {
1098                                         char *sitename = sitename_fetch(ads->config.realm);
1099
1100                                         /* We're going to use this KDC for this realm/domain.
1101                                            If we are using sites, then force the krb5 libs
1102                                            to use this KDC. */
1103
1104                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1105                                                                         domain->name,
1106                                                                         sitename,
1107                                                                         pss);
1108
1109                                         SAFE_FREE(sitename);
1110                                 } else {
1111                                         /* use an off site KDC */
1112                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1113                                                                         domain->name,
1114                                                                         NULL,
1115                                                                         pss);
1116                                 }
1117                                 winbindd_set_locator_kdc_envs(domain);
1118
1119                                 /* Ensure we contact this DC also. */
1120                                 saf_store( domain->name, name);
1121                                 saf_store( domain->alt_name, name);
1122                         }
1123
1124                         ads_destroy( &ads );
1125                         return True;
1126                 }
1127
1128                 ads_destroy( &ads );
1129         }
1130 #endif
1131
1132         /* try GETDC requests next */
1133
1134         if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1135                                pss, domain->name, &domain->sid,
1136                                nt_version)) {
1137                 const char *dc_name = NULL;
1138                 int i;
1139                 smb_msleep(100);
1140                 for (i=0; i<5; i++) {
1141                         if (receive_getdc_response(mem_ctx, pss, domain->name,
1142                                                    &nt_version,
1143                                                    &dc_name, NULL)) {
1144                                 fstrcpy(name, dc_name);
1145                                 namecache_store(name, 0x20, 1, &ip_list);
1146                                 return True;
1147                         }
1148                         smb_msleep(500);
1149                 }
1150         }
1151
1152         /* try node status request */
1153
1154         if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1155                 namecache_store(name, 0x20, 1, &ip_list);
1156                 return True;
1157         }
1158         return False;
1159 }
1160
1161 /*******************************************************************
1162  Retrieve a list of IP addresses for domain controllers.
1163
1164  The array is sorted in the preferred connection order.
1165
1166  @param[in] mem_ctx talloc memory context to allocate from
1167  @param[in] domain domain to retrieve DCs for
1168  @param[out] dcs array of dcs that will be returned
1169  @param[out] num_dcs number of dcs returned in the dcs array
1170  @return always true
1171 *******************************************************************/
1172
1173 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1174                     struct dc_name_ip **dcs, int *num_dcs)
1175 {
1176         fstring dcname;
1177         struct  sockaddr_storage ss;
1178         struct  ip_service *ip_list = NULL;
1179         int     iplist_size = 0;
1180         int     i;
1181         bool    is_our_domain;
1182         enum security_types sec = (enum security_types)lp_security();
1183
1184         is_our_domain = strequal(domain->name, lp_workgroup());
1185
1186         /* If not our domain, get the preferred DC, by asking our primary DC */
1187         if ( !is_our_domain
1188                 && get_dc_name_via_netlogon(domain, dcname, &ss)
1189                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1190                        num_dcs) )
1191         {
1192                 char addr[INET6_ADDRSTRLEN];
1193                 print_sockaddr(addr, sizeof(addr), &ss);
1194                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1195                            dcname, addr));
1196                 return True;
1197         }
1198
1199         if (sec == SEC_ADS) {
1200                 char *sitename = NULL;
1201
1202                 /* We need to make sure we know the local site before
1203                    doing any DNS queries, as this will restrict the
1204                    get_sorted_dc_list() call below to only fetching
1205                    DNS records for the correct site. */
1206
1207                 /* Find any DC to get the site record.
1208                    We deliberately don't care about the
1209                    return here. */
1210
1211                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1212
1213                 sitename = sitename_fetch(domain->alt_name);
1214                 if (sitename) {
1215
1216                         /* Do the site-specific AD dns lookup first. */
1217                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1218                                &iplist_size, True);
1219
1220                         /* Add ips to the DC array.  We don't look up the name
1221                            of the DC in this function, but we fill in the char*
1222                            of the ip now to make the failed connection cache
1223                            work */
1224                         for ( i=0; i<iplist_size; i++ ) {
1225                                 char addr[INET6_ADDRSTRLEN];
1226                                 print_sockaddr(addr, sizeof(addr),
1227                                                 &ip_list[i].ss);
1228                                 add_one_dc_unique(mem_ctx,
1229                                                 domain->name,
1230                                                 addr,
1231                                                 &ip_list[i].ss,
1232                                                 dcs,
1233                                                 num_dcs);
1234                         }
1235
1236                         SAFE_FREE(ip_list);
1237                         SAFE_FREE(sitename);
1238                         iplist_size = 0;
1239                 }
1240
1241                 /* Now we add DCs from the main AD DNS lookup. */
1242                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1243                         &iplist_size, True);
1244
1245                 for ( i=0; i<iplist_size; i++ ) {
1246                         char addr[INET6_ADDRSTRLEN];
1247                         print_sockaddr(addr, sizeof(addr),
1248                                         &ip_list[i].ss);
1249                         add_one_dc_unique(mem_ctx,
1250                                         domain->name,
1251                                         addr,
1252                                         &ip_list[i].ss,
1253                                         dcs,
1254                                         num_dcs);
1255                 }
1256
1257                 SAFE_FREE(ip_list);
1258                 iplist_size = 0;
1259         }
1260
1261         /* Try standard netbios queries if no ADS */
1262         if (*num_dcs == 0) {
1263                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1264                        False);
1265
1266                 for ( i=0; i<iplist_size; i++ ) {
1267                         char addr[INET6_ADDRSTRLEN];
1268                         print_sockaddr(addr, sizeof(addr),
1269                                         &ip_list[i].ss);
1270                         add_one_dc_unique(mem_ctx,
1271                                         domain->name,
1272                                         addr,
1273                                         &ip_list[i].ss,
1274                                         dcs,
1275                                         num_dcs);
1276                 }
1277
1278                 SAFE_FREE(ip_list);
1279                 iplist_size = 0;
1280         }
1281
1282         return True;
1283 }
1284
1285 /*******************************************************************
1286  Find and make a connection to a DC in the given domain.
1287
1288  @param[in] mem_ctx talloc memory context to allocate from
1289  @param[in] domain domain to find a dc in
1290  @param[out] dcname NetBIOS or FQDN of DC that's connected to
1291  @param[out] pss DC Internet address and port
1292  @param[out] fd fd of the open socket connected to the newly found dc
1293  @return true when a DC connection is made, false otherwise
1294 *******************************************************************/
1295
1296 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1297                         struct winbindd_domain *domain,
1298                         fstring dcname, struct sockaddr_storage *pss, int *fd)
1299 {
1300         struct dc_name_ip *dcs = NULL;
1301         int num_dcs = 0;
1302
1303         const char **dcnames = NULL;
1304         int num_dcnames = 0;
1305
1306         struct sockaddr_storage *addrs = NULL;
1307         int num_addrs = 0;
1308
1309         int i, fd_index;
1310
1311         *fd = -1;
1312
1313  again:
1314         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1315                 return False;
1316
1317         for (i=0; i<num_dcs; i++) {
1318
1319                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1320                                     &dcnames, &num_dcnames)) {
1321                         return False;
1322                 }
1323                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1324                                       &addrs, &num_addrs)) {
1325                         return False;
1326                 }
1327
1328                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1329                                     &dcnames, &num_dcnames)) {
1330                         return False;
1331                 }
1332                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1333                                       &addrs, &num_addrs)) {
1334                         return False;
1335                 }
1336         }
1337
1338         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1339                 return False;
1340
1341         if ((addrs == NULL) || (dcnames == NULL))
1342                 return False;
1343
1344         /* 5 second timeout. */
1345         if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1346                 for (i=0; i<num_dcs; i++) {
1347                         char ab[INET6_ADDRSTRLEN];
1348                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1349                         DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1350                                 "domain %s address %s. Error was %s\n",
1351                                 domain->name, ab, strerror(errno) ));
1352                         winbind_add_failed_connection_entry(domain,
1353                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1354                 }
1355                 return False;
1356         }
1357
1358         *pss = addrs[fd_index];
1359
1360         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1361                 /* Ok, we've got a name for the DC */
1362                 fstrcpy(dcname, dcnames[fd_index]);
1363                 return True;
1364         }
1365
1366         /* Try to figure out the name */
1367         if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1368                 return True;
1369         }
1370
1371         /* We can not continue without the DC's name */
1372         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1373                                     NT_STATUS_UNSUCCESSFUL);
1374
1375         /* Throw away all arrays as we're doing this again. */
1376         TALLOC_FREE(dcs);
1377         num_dcs = 0;
1378
1379         TALLOC_FREE(dcnames);
1380         num_dcnames = 0;
1381
1382         TALLOC_FREE(addrs);
1383         num_addrs = 0;
1384
1385         close(*fd);
1386         *fd = -1;
1387
1388         goto again;
1389 }
1390
1391 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1392                                    struct winbindd_cm_conn *new_conn)
1393 {
1394         TALLOC_CTX *mem_ctx;
1395         NTSTATUS result;
1396         char *saf_servername = saf_fetch( domain->name );
1397         int retries;
1398
1399         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1400                 SAFE_FREE(saf_servername);
1401                 set_domain_offline(domain);
1402                 return NT_STATUS_NO_MEMORY;
1403         }
1404
1405         /* we have to check the server affinity cache here since 
1406            later we selecte a DC based on response time and not preference */
1407
1408         /* Check the negative connection cache
1409            before talking to it. It going down may have
1410            triggered the reconnection. */
1411
1412         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1413
1414                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1415                         saf_servername, domain->name ));
1416
1417                 /* convert an ip address to a name */
1418                 if (is_ipaddress( saf_servername ) ) {
1419                         fstring saf_name;
1420                         struct sockaddr_storage ss;
1421
1422                         if (!interpret_string_addr(&ss, saf_servername,
1423                                                 AI_NUMERICHOST)) {
1424                                 return NT_STATUS_UNSUCCESSFUL;
1425                         }
1426                         if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1427                                 fstrcpy( domain->dcname, saf_name );
1428                         } else {
1429                                 winbind_add_failed_connection_entry(
1430                                         domain, saf_servername,
1431                                         NT_STATUS_UNSUCCESSFUL);
1432                         }
1433                 } else {
1434                         fstrcpy( domain->dcname, saf_servername );
1435                 }
1436
1437                 SAFE_FREE( saf_servername );
1438         }
1439
1440         for (retries = 0; retries < 3; retries++) {
1441                 int fd = -1;
1442                 bool retry = False;
1443
1444                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1445
1446                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1447                         domain->dcname, domain->name ));
1448
1449                 if (*domain->dcname 
1450                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1451                         && (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
1452                 {
1453                         struct sockaddr_storage *addrs = NULL;
1454                         int num_addrs = 0;
1455                         int dummy = 0;
1456
1457                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1458                                 set_domain_offline(domain);
1459                                 talloc_destroy(mem_ctx);
1460                                 return NT_STATUS_NO_MEMORY;
1461                         }
1462                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1463                                 set_domain_offline(domain);
1464                                 talloc_destroy(mem_ctx);
1465                                 return NT_STATUS_NO_MEMORY;
1466                         }
1467
1468                         /* 5 second timeout. */
1469                         if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1470                                 fd = -1;
1471                         }
1472                 }
1473
1474                 if ((fd == -1) 
1475                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1476                 {
1477                         /* This is the one place where we will
1478                            set the global winbindd offline state
1479                            to true, if a "WINBINDD_OFFLINE" entry
1480                            is found in the winbindd cache. */
1481                         set_global_winbindd_state_offline();
1482                         break;
1483                 }
1484
1485                 new_conn->cli = NULL;
1486
1487                 result = cm_prepare_connection(domain, fd, domain->dcname,
1488                         &new_conn->cli, &retry);
1489
1490                 if (!retry)
1491                         break;
1492         }
1493
1494         if (NT_STATUS_IS_OK(result)) {
1495
1496                 winbindd_set_locator_kdc_envs(domain);
1497
1498                 if (domain->online == False) {
1499                         /* We're changing state from offline to online. */
1500                         set_global_winbindd_state_online();
1501                 }
1502                 set_domain_online(domain);
1503         } else {
1504                 /* Ensure we setup the retry handler. */
1505                 set_domain_offline(domain);
1506         }
1507
1508         talloc_destroy(mem_ctx);
1509         return result;
1510 }
1511
1512 /* Close down all open pipes on a connection. */
1513
1514 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1515 {
1516         /* We're closing down a possibly dead
1517            connection. Don't have impossibly long (10s) timeouts. */
1518
1519         if (conn->cli) {
1520                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1521         }
1522
1523         if (conn->samr_pipe != NULL) {
1524                 TALLOC_FREE(conn->samr_pipe);
1525                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1526                 if (conn->cli) {
1527                         cli_set_timeout(conn->cli, 500);
1528                 }
1529         }
1530
1531         if (conn->lsa_pipe != NULL) {
1532                 TALLOC_FREE(conn->lsa_pipe);
1533                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1534                 if (conn->cli) {
1535                         cli_set_timeout(conn->cli, 500);
1536                 }
1537         }
1538
1539         if (conn->netlogon_pipe != NULL) {
1540                 TALLOC_FREE(conn->netlogon_pipe);
1541                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1542                 if (conn->cli) {
1543                         cli_set_timeout(conn->cli, 500);
1544                 }
1545         }
1546
1547         if (conn->cli) {
1548                 cli_shutdown(conn->cli);
1549         }
1550
1551         conn->cli = NULL;
1552 }
1553
1554 void close_conns_after_fork(void)
1555 {
1556         struct winbindd_domain *domain;
1557
1558         for (domain = domain_list(); domain; domain = domain->next) {
1559                 if (domain->conn.cli == NULL)
1560                         continue;
1561
1562                 if (domain->conn.cli->fd == -1)
1563                         continue;
1564
1565                 close(domain->conn.cli->fd);
1566                 domain->conn.cli->fd = -1;
1567         }
1568 }
1569
1570 static bool connection_ok(struct winbindd_domain *domain)
1571 {
1572         if (domain->conn.cli == NULL) {
1573                 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1574                           "cli!\n", domain->dcname, domain->name));
1575                 return False;
1576         }
1577
1578         if (!domain->conn.cli->initialised) {
1579                 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1580                           "initialised!\n", domain->dcname, domain->name));
1581                 return False;
1582         }
1583
1584         if (domain->conn.cli->fd == -1) {
1585                 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1586                           "never started (fd == -1)\n", 
1587                           domain->dcname, domain->name));
1588                 return False;
1589         }
1590
1591         if (domain->online == False) {
1592                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1593                 return False;
1594         }
1595
1596         return True;
1597 }
1598
1599 /* Initialize a new connection up to the RPC BIND.
1600    Bypass online status check so always does network calls. */
1601
1602 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1603 {
1604         NTSTATUS result;
1605
1606         /* Internal connections never use the network. */
1607         if (domain->internal) {
1608                 domain->initialized = True;
1609                 return NT_STATUS_OK;
1610         }
1611
1612         if (connection_ok(domain)) {
1613                 if (!domain->initialized) {
1614                         set_dc_type_and_flags(domain);
1615                 }
1616                 return NT_STATUS_OK;
1617         }
1618
1619         invalidate_cm_connection(&domain->conn);
1620
1621         result = cm_open_connection(domain, &domain->conn);
1622
1623         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1624                 set_dc_type_and_flags(domain);
1625         }
1626
1627         return result;
1628 }
1629
1630 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1631 {
1632         if (domain->initialized && !domain->online) {
1633                 /* We check for online status elsewhere. */
1634                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1635         }
1636
1637         return init_dc_connection_network(domain);
1638 }
1639
1640 /******************************************************************************
1641  Set the trust flags (direction and forest location) for a domain
1642 ******************************************************************************/
1643
1644 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1645 {
1646         struct winbindd_domain *our_domain;
1647         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1648         struct netr_DomainTrustList trusts;
1649         int i;
1650         uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1651                         NETR_TRUST_FLAG_OUTBOUND |
1652                         NETR_TRUST_FLAG_INBOUND);
1653         struct rpc_pipe_client *cli;
1654         TALLOC_CTX *mem_ctx = NULL;
1655
1656         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1657
1658         /* Our primary domain doesn't need to worry about trust flags.
1659            Force it to go through the network setup */
1660         if ( domain->primary ) {                
1661                 return False;           
1662         }
1663
1664         our_domain = find_our_domain();
1665
1666         if ( !connection_ok(our_domain) ) {
1667                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1668                 return False;
1669         }
1670
1671         /* This won't work unless our domain is AD */
1672
1673         if ( !our_domain->active_directory ) {
1674                 return False;
1675         }
1676
1677         /* Use DsEnumerateDomainTrusts to get us the trust direction
1678            and type */
1679
1680         result = cm_connect_netlogon(our_domain, &cli);
1681
1682         if (!NT_STATUS_IS_OK(result)) {
1683                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1684                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1685                           domain->name, nt_errstr(result)));
1686                 return False;
1687         }
1688
1689         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1690                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1691                 return False;
1692         }       
1693
1694         result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1695                                                       cli->desthost,
1696                                                       flags,
1697                                                       &trusts,
1698                                                       NULL);
1699         if (!NT_STATUS_IS_OK(result)) {
1700                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1701                         "failed to query trusted domain list: %s\n",
1702                         nt_errstr(result)));
1703                 talloc_destroy(mem_ctx);
1704                 return false;
1705         }
1706
1707         /* Now find the domain name and get the flags */
1708
1709         for ( i=0; i<trusts.count; i++ ) {
1710                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1711                         domain->domain_flags          = trusts.array[i].trust_flags;
1712                         domain->domain_type           = trusts.array[i].trust_type;
1713                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
1714
1715                         if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1716                                 domain->active_directory = True;
1717
1718                         /* This flag is only set if the domain is *our* 
1719                            primary domain and the primary domain is in
1720                            native mode */
1721
1722                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1723
1724                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1725                                   "native mode.\n", domain->name, 
1726                                   domain->native_mode ? "" : "NOT "));
1727
1728                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1729                                  "running active directory.\n", domain->name, 
1730                                  domain->active_directory ? "" : "NOT "));
1731
1732
1733                         domain->initialized = True;
1734
1735                         if ( !winbindd_can_contact_domain( domain) )
1736                                 domain->internal = True;
1737
1738                         break;
1739                 }               
1740         }
1741
1742         talloc_destroy( mem_ctx );
1743
1744         return domain->initialized;     
1745 }
1746
1747 /******************************************************************************
1748  We can 'sense' certain things about the DC by it's replies to certain
1749  questions.
1750
1751  This tells us if this particular remote server is Active Directory, and if it
1752  is native mode.
1753 ******************************************************************************/
1754
1755 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1756 {
1757         NTSTATUS                result;
1758         WERROR werr;
1759         TALLOC_CTX              *mem_ctx = NULL;
1760         struct rpc_pipe_client  *cli;
1761         POLICY_HND pol;
1762         union dssetup_DsRoleInfo info;
1763         union lsa_PolicyInformation *lsa_info = NULL;
1764
1765         if (!connection_ok(domain)) {
1766                 return;
1767         }
1768
1769         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1770                               domain->name);
1771         if (!mem_ctx) {
1772                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1773                 return;
1774         }
1775
1776         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1777
1778         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1779                                           &ndr_table_dssetup.syntax_id,
1780                                           &cli);
1781
1782         if (!NT_STATUS_IS_OK(result)) {
1783                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1784                           "PI_DSSETUP on domain %s: (%s)\n",
1785                           domain->name, nt_errstr(result)));
1786
1787                 /* if this is just a non-AD domain we need to continue
1788                  * identifying so that we can in the end return with
1789                  * domain->initialized = True - gd */
1790
1791                 goto no_dssetup;
1792         }
1793
1794         result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1795                                                                   DS_ROLE_BASIC_INFORMATION,
1796                                                                   &info,
1797                                                                   &werr);
1798         TALLOC_FREE(cli);
1799
1800         if (!NT_STATUS_IS_OK(result)) {
1801                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1802                           "on domain %s failed: (%s)\n",
1803                           domain->name, nt_errstr(result)));
1804
1805                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1806                  * every opcode on the DSSETUP pipe, continue with
1807                  * no_dssetup mode here as well to get domain->initialized
1808                  * set - gd */
1809
1810                 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1811                         goto no_dssetup;
1812                 }
1813
1814                 TALLOC_FREE(mem_ctx);
1815                 return;
1816         }
1817
1818         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1819             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1820                 domain->native_mode = True;
1821         } else {
1822                 domain->native_mode = False;
1823         }
1824
1825 no_dssetup:
1826         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1827                                           &ndr_table_lsarpc.syntax_id, &cli);
1828
1829         if (!NT_STATUS_IS_OK(result)) {
1830                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1831                           "PI_LSARPC on domain %s: (%s)\n",
1832                           domain->name, nt_errstr(result)));
1833                 TALLOC_FREE(cli);
1834                 TALLOC_FREE(mem_ctx);
1835                 return;
1836         }
1837
1838         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
1839                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1840
1841         if (NT_STATUS_IS_OK(result)) {
1842                 /* This particular query is exactly what Win2k clients use 
1843                    to determine that the DC is active directory */
1844                 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1845                                                      &pol,
1846                                                      LSA_POLICY_INFO_DNS,
1847                                                      &lsa_info);
1848         }
1849
1850         if (NT_STATUS_IS_OK(result)) {
1851                 domain->active_directory = True;
1852
1853                 if (lsa_info->dns.name.string) {
1854                         fstrcpy(domain->name, lsa_info->dns.name.string);
1855                 }
1856
1857                 if (lsa_info->dns.dns_domain.string) {
1858                         fstrcpy(domain->alt_name,
1859                                 lsa_info->dns.dns_domain.string);
1860                 }
1861
1862                 /* See if we can set some domain trust flags about
1863                    ourself */
1864
1865                 if (lsa_info->dns.dns_forest.string) {
1866                         fstrcpy(domain->forest_name,
1867                                 lsa_info->dns.dns_forest.string);
1868
1869                         if (strequal(domain->forest_name, domain->alt_name)) {
1870                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1871                         }
1872                 }
1873
1874                 if (lsa_info->dns.sid) {
1875                         sid_copy(&domain->sid, lsa_info->dns.sid);
1876                 }
1877         } else {
1878                 domain->active_directory = False;
1879
1880                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
1881                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
1882                                                 &pol);
1883
1884                 if (!NT_STATUS_IS_OK(result)) {
1885                         goto done;
1886                 }
1887
1888                 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1889                                                     &pol,
1890                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1891                                                     &lsa_info);
1892
1893                 if (NT_STATUS_IS_OK(result)) {
1894
1895                         if (lsa_info->account_domain.name.string) {
1896                                 fstrcpy(domain->name,
1897                                         lsa_info->account_domain.name.string);
1898                         }
1899
1900                         if (lsa_info->account_domain.sid) {
1901                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1902                         }
1903                 }
1904         }
1905 done:
1906
1907         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1908                   domain->name, domain->native_mode ? "" : "NOT "));
1909
1910         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1911                   domain->name, domain->active_directory ? "" : "NOT "));
1912
1913         TALLOC_FREE(cli);
1914
1915         TALLOC_FREE(mem_ctx);
1916
1917         domain->initialized = True;
1918 }
1919
1920 /**********************************************************************
1921  Set the domain_flags (trust attributes, domain operating modes, etc... 
1922 ***********************************************************************/
1923
1924 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1925 {
1926         /* we always have to contact our primary domain */
1927
1928         if ( domain->primary ) {
1929                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1930                           "primary domain\n"));
1931                 set_dc_type_and_flags_connect( domain );
1932                 return;         
1933         }
1934
1935         /* Use our DC to get the information if possible */
1936
1937         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1938                 /* Otherwise, fallback to contacting the 
1939                    domain directly */
1940                 set_dc_type_and_flags_connect( domain );
1941         }
1942
1943         return;
1944 }
1945
1946
1947
1948 /**********************************************************************
1949 ***********************************************************************/
1950
1951 static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1952                                    struct dcinfo **ppdc)
1953 {
1954         NTSTATUS result;
1955         struct rpc_pipe_client *netlogon_pipe;
1956
1957         if (lp_client_schannel() == False) {
1958                 return False;
1959         }
1960
1961         result = cm_connect_netlogon(domain, &netlogon_pipe);
1962         if (!NT_STATUS_IS_OK(result)) {
1963                 return False;
1964         }
1965
1966         /* Return a pointer to the struct dcinfo from the
1967            netlogon pipe. */
1968
1969         if (!domain->conn.netlogon_pipe->dc) {
1970                 return false;
1971         }
1972
1973         *ppdc = domain->conn.netlogon_pipe->dc;
1974         return True;
1975 }
1976
1977 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1978                         struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1979 {
1980         struct winbindd_cm_conn *conn;
1981         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1982         fstring conn_pwd;
1983         struct dcinfo *p_dcinfo;
1984         char *machine_password = NULL;
1985         char *machine_account = NULL;
1986         char *domain_name = NULL;
1987
1988         result = init_dc_connection(domain);
1989         if (!NT_STATUS_IS_OK(result)) {
1990                 return result;
1991         }
1992
1993         conn = &domain->conn;
1994
1995         if (conn->samr_pipe != NULL) {
1996                 goto done;
1997         }
1998
1999
2000         /*
2001          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2002          * sign and sealed pipe using the machine account password by
2003          * preference. If we can't - try schannel, if that fails, try
2004          * anonymous.
2005          */
2006
2007         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2008         if ((conn->cli->user_name[0] == '\0') ||
2009             (conn->cli->domain[0] == '\0') || 
2010             (conn_pwd[0] == '\0'))
2011         {
2012                 result = get_trust_creds(domain, &machine_password,
2013                                          &machine_account, NULL);
2014                 if (!NT_STATUS_IS_OK(result)) {
2015                         DEBUG(10, ("cm_connect_sam: No no user available for "
2016                                    "domain %s, trying schannel\n", conn->cli->domain));
2017                         goto schannel;
2018                 }
2019                 domain_name = domain->name;
2020         } else {
2021                 machine_password = SMB_STRDUP(conn_pwd);                
2022                 machine_account = SMB_STRDUP(conn->cli->user_name);
2023                 domain_name = conn->cli->domain;
2024         }
2025
2026         if (!machine_password || !machine_account) {
2027                 result = NT_STATUS_NO_MEMORY;
2028                 goto done;
2029         }
2030
2031         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2032            authenticated SAMR pipe with sign & seal. */
2033         result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2034                                                   &ndr_table_samr.syntax_id,
2035                                                   PIPE_AUTH_LEVEL_PRIVACY,
2036                                                   domain_name,
2037                                                   machine_account,
2038                                                   machine_password,
2039                                                   &conn->samr_pipe);
2040
2041         if (!NT_STATUS_IS_OK(result)) {
2042                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2043                           "pipe for domain %s using NTLMSSP "
2044                           "authenticated pipe: user %s\\%s. Error was "
2045                           "%s\n", domain->name, domain_name,
2046                           machine_account, nt_errstr(result)));
2047                 goto schannel;
2048         }
2049
2050         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2051                   "domain %s using NTLMSSP authenticated "
2052                   "pipe: user %s\\%s\n", domain->name,
2053                   domain_name, machine_account));
2054
2055         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2056                                       conn->samr_pipe->desthost,
2057                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2058                                       &conn->sam_connect_handle);
2059         if (NT_STATUS_IS_OK(result)) {
2060                 goto open_domain;
2061         }
2062         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2063                   "failed for domain %s, error was %s. Trying schannel\n",
2064                   domain->name, nt_errstr(result) ));
2065         TALLOC_FREE(conn->samr_pipe);
2066
2067  schannel:
2068
2069         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2070
2071         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2072                 /* If this call fails - conn->cli can now be NULL ! */
2073                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2074                            "for domain %s, trying anon\n", domain->name));
2075                 goto anonymous;
2076         }
2077         result = cli_rpc_pipe_open_schannel_with_key
2078                 (conn->cli, &ndr_table_samr.syntax_id, PIPE_AUTH_LEVEL_PRIVACY,
2079                  domain->name, p_dcinfo, &conn->samr_pipe);
2080
2081         if (!NT_STATUS_IS_OK(result)) {
2082                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2083                           "domain %s using schannel. Error was %s\n",
2084                           domain->name, nt_errstr(result) ));
2085                 goto anonymous;
2086         }
2087         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2088                   "schannel.\n", domain->name ));
2089
2090         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2091                                       conn->samr_pipe->desthost,
2092                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2093                                       &conn->sam_connect_handle);
2094         if (NT_STATUS_IS_OK(result)) {
2095                 goto open_domain;
2096         }
2097         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2098                   "for domain %s, error was %s. Trying anonymous\n",
2099                   domain->name, nt_errstr(result) ));
2100         TALLOC_FREE(conn->samr_pipe);
2101
2102  anonymous:
2103
2104         /* Finally fall back to anonymous. */
2105         result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2106                                           &conn->samr_pipe);
2107
2108         if (!NT_STATUS_IS_OK(result)) {
2109                 goto done;
2110         }
2111
2112         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2113                                       conn->samr_pipe->desthost,
2114                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2115                                       &conn->sam_connect_handle);
2116         if (!NT_STATUS_IS_OK(result)) {
2117                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2118                           "for domain %s Error was %s\n",
2119                           domain->name, nt_errstr(result) ));
2120                 goto done;
2121         }
2122
2123  open_domain:
2124         result = rpccli_samr_OpenDomain(conn->samr_pipe,
2125                                         mem_ctx,
2126                                         &conn->sam_connect_handle,
2127                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2128                                         &domain->sid,
2129                                         &conn->sam_domain_handle);
2130
2131  done:
2132
2133         if (!NT_STATUS_IS_OK(result)) {
2134                 invalidate_cm_connection(conn);
2135                 return result;
2136         }
2137
2138         *cli = conn->samr_pipe;
2139         *sam_handle = conn->sam_domain_handle;
2140         SAFE_FREE(machine_password);
2141         SAFE_FREE(machine_account);
2142         return result;
2143 }
2144
2145 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2146                         struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
2147 {
2148         struct winbindd_cm_conn *conn;
2149         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2150         fstring conn_pwd;
2151         struct dcinfo *p_dcinfo;
2152
2153         result = init_dc_connection(domain);
2154         if (!NT_STATUS_IS_OK(result))
2155                 return result;
2156
2157         conn = &domain->conn;
2158
2159         if (conn->lsa_pipe != NULL) {
2160                 goto done;
2161         }
2162
2163         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
2164         if ((conn->cli->user_name[0] == '\0') ||
2165             (conn->cli->domain[0] == '\0') || 
2166             (conn_pwd[0] == '\0')) {
2167                 DEBUG(10, ("cm_connect_lsa: No no user available for "
2168                            "domain %s, trying schannel\n", conn->cli->domain));
2169                 goto schannel;
2170         }
2171
2172         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2173          * authenticated LSA pipe with sign & seal. */
2174         result = cli_rpc_pipe_open_spnego_ntlmssp
2175                 (conn->cli, &ndr_table_lsarpc.syntax_id,
2176                  PIPE_AUTH_LEVEL_PRIVACY,
2177                  conn->cli->domain, conn->cli->user_name, conn_pwd,
2178                  &conn->lsa_pipe);
2179
2180         if (!NT_STATUS_IS_OK(result)) {
2181                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2182                           "domain %s using NTLMSSP authenticated pipe: user "
2183                           "%s\\%s. Error was %s. Trying schannel.\n",
2184                           domain->name, conn->cli->domain,
2185                           conn->cli->user_name, nt_errstr(result)));
2186                 goto schannel;
2187         }
2188
2189         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2190                   "NTLMSSP authenticated pipe: user %s\\%s\n",
2191                   domain->name, conn->cli->domain, conn->cli->user_name ));
2192
2193         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2194                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2195                                         &conn->lsa_policy);
2196         if (NT_STATUS_IS_OK(result)) {
2197                 goto done;
2198         }
2199
2200         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2201                   "schannel\n"));
2202
2203         TALLOC_FREE(conn->lsa_pipe);
2204
2205  schannel:
2206
2207         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2208
2209         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2210                 /* If this call fails - conn->cli can now be NULL ! */
2211                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2212                            "for domain %s, trying anon\n", domain->name));
2213                 goto anonymous;
2214         }
2215         result = cli_rpc_pipe_open_schannel_with_key
2216                 (conn->cli, &ndr_table_lsarpc.syntax_id,
2217                  PIPE_AUTH_LEVEL_PRIVACY,
2218                  domain->name, p_dcinfo, &conn->lsa_pipe);
2219
2220         if (!NT_STATUS_IS_OK(result)) {
2221                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2222                           "domain %s using schannel. Error was %s\n",
2223                           domain->name, nt_errstr(result) ));
2224                 goto anonymous;
2225         }
2226         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2227                   "schannel.\n", domain->name ));
2228
2229         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2230                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2231                                         &conn->lsa_policy);
2232         if (NT_STATUS_IS_OK(result)) {
2233                 goto done;
2234         }
2235
2236         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2237                   "anonymous\n"));
2238
2239         TALLOC_FREE(conn->lsa_pipe);
2240
2241  anonymous:
2242
2243         result = cli_rpc_pipe_open_noauth(conn->cli,
2244                                           &ndr_table_lsarpc.syntax_id,
2245                                           &conn->lsa_pipe);
2246         if (!NT_STATUS_IS_OK(result)) {
2247                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2248                 goto done;
2249         }
2250
2251         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2252                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2253                                         &conn->lsa_policy);
2254  done:
2255         if (!NT_STATUS_IS_OK(result)) {
2256                 invalidate_cm_connection(conn);
2257                 return result;
2258         }
2259
2260         *cli = conn->lsa_pipe;
2261         *lsa_policy = conn->lsa_policy;
2262         return result;
2263 }
2264
2265 /****************************************************************************
2266  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2267  session key stored in conn->netlogon_pipe->dc->sess_key.
2268 ****************************************************************************/
2269
2270 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2271                              struct rpc_pipe_client **cli)
2272 {
2273         struct winbindd_cm_conn *conn;
2274         NTSTATUS result;
2275
2276         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2277         uint8  mach_pwd[16];
2278         uint32  sec_chan_type;
2279         const char *account_name;
2280         struct rpc_pipe_client *netlogon_pipe = NULL;
2281
2282         *cli = NULL;
2283
2284         result = init_dc_connection(domain);
2285         if (!NT_STATUS_IS_OK(result)) {
2286                 return result;
2287         }
2288
2289         conn = &domain->conn;
2290
2291         if (conn->netlogon_pipe != NULL) {
2292                 *cli = conn->netlogon_pipe;
2293                 return NT_STATUS_OK;
2294         }
2295
2296         result = cli_rpc_pipe_open_noauth(conn->cli,
2297                                           &ndr_table_netlogon.syntax_id,
2298                                           &netlogon_pipe);
2299         if (!NT_STATUS_IS_OK(result)) {
2300                 return result;
2301         }
2302
2303         if ((!IS_DC) && (!domain->primary)) {
2304                 /* Clear the schannel request bit and drop down */
2305                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2306                 goto no_schannel;
2307         }
2308
2309         if (lp_client_schannel() != False) {
2310                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2311         }
2312
2313         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2314                                &sec_chan_type))
2315         {
2316                 TALLOC_FREE(netlogon_pipe);
2317                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2318         }
2319
2320         result = rpccli_netlogon_setup_creds(
2321                  netlogon_pipe,
2322                  domain->dcname, /* server name. */
2323                  domain->name,   /* domain name */
2324                  global_myname(), /* client name */
2325                  account_name,   /* machine account */
2326                  mach_pwd,       /* machine password */
2327                  sec_chan_type,  /* from get_trust_pw */
2328                  &neg_flags);
2329
2330         if (!NT_STATUS_IS_OK(result)) {
2331                 TALLOC_FREE(netlogon_pipe);
2332                 return result;
2333         }
2334
2335         if ((lp_client_schannel() == True) &&
2336                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2337                 DEBUG(3, ("Server did not offer schannel\n"));
2338                 TALLOC_FREE(netlogon_pipe);
2339                 return NT_STATUS_ACCESS_DENIED;
2340         }
2341
2342  no_schannel:
2343         if ((lp_client_schannel() == False) ||
2344                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2345                 /*
2346                  * NetSamLogonEx only works for schannel
2347                  */
2348                 domain->can_do_samlogon_ex = False;
2349
2350                 /* We're done - just keep the existing connection to NETLOGON
2351                  * open */
2352                 conn->netlogon_pipe = netlogon_pipe;
2353                 *cli = conn->netlogon_pipe;
2354                 return NT_STATUS_OK;
2355         }
2356
2357         /* Using the credentials from the first pipe, open a signed and sealed
2358            second netlogon pipe. The session key is stored in the schannel
2359            part of the new pipe auth struct.
2360         */
2361
2362         result = cli_rpc_pipe_open_schannel_with_key(
2363                 conn->cli, &ndr_table_netlogon.syntax_id,
2364                 PIPE_AUTH_LEVEL_PRIVACY, domain->name, netlogon_pipe->dc,
2365                 &conn->netlogon_pipe);
2366
2367         /* We can now close the initial netlogon pipe. */
2368         TALLOC_FREE(netlogon_pipe);
2369
2370         if (!NT_STATUS_IS_OK(result)) {
2371                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2372                           "was %s\n", nt_errstr(result)));
2373
2374                 /* make sure we return something besides OK */
2375                 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2376         }
2377
2378         /*
2379          * Try NetSamLogonEx for AD domains
2380          */
2381         domain->can_do_samlogon_ex = domain->active_directory;
2382
2383         *cli = conn->netlogon_pipe;
2384         return NT_STATUS_OK;
2385 }