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