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