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