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