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