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