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