Rework Samba3 to use new libcli/auth code (partial)
[kai/samba.git] / source3 / winbindd / winbindd_cm.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon connection manager
5
6    Copyright (C) Tim Potter                2001
7    Copyright (C) Andrew Bartlett           2002
8    Copyright (C) Gerald (Jerry) Carter     2003-2005.
9    Copyright (C) Volker Lendecke           2004-2005
10    Copyright (C) Jeremy Allison            2006
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 /*
27    We need to manage connections to domain controllers without having to
28    mess up the main winbindd code with other issues.  The aim of the
29    connection manager is to:
30
31        - make connections to domain controllers and cache them
32        - re-establish connections when networks or servers go down
33        - centralise the policy on connection timeouts, domain controller
34          selection etc
35        - manage re-entrancy for when winbindd becomes able to handle
36          multiple outstanding rpc requests
37
38    Why not have connection management as part of the rpc layer like tng?
39    Good question.  This code may morph into libsmb/rpc_cache.c or something
40    like that but at the moment it's simply staying as part of winbind.  I
41    think the TNG architecture of forcing every user of the rpc layer to use
42    the connection caching system is a bad idea.  It should be an optional
43    method of using the routines.
44
45    The TNG design is quite good but I disagree with some aspects of the
46    implementation. -tpot
47
48  */
49
50 /*
51    TODO:
52
53      - I'm pretty annoyed by all the make_nmb_name() stuff.  It should be
54        moved down into another function.
55
56      - Take care when destroying cli_structs as they can be shared between
57        various sam handles.
58
59  */
60
61 #include "includes.h"
62 #include "winbindd.h"
63 #include "../libcli/auth/libcli_auth.h"
64
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 = (struct sockaddr_in *)&peeraddr;
773
774         DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
775                 controller, domain->name ));
776
777         *retry = True;
778
779         mutex = grab_named_mutex(talloc_tos(), controller,
780                                  WINBIND_SERVER_MUTEX_WAIT_TIME);
781         if (mutex == NULL) {
782                 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
783                          controller));
784                 result = NT_STATUS_POSSIBLE_DEADLOCK;
785                 goto done;
786         }
787
788         if ((*cli = cli_initialise()) == NULL) {
789                 DEBUG(1, ("Could not cli_initialize\n"));
790                 result = NT_STATUS_NO_MEMORY;
791                 goto done;
792         }
793
794         (*cli)->timeout = 10000;        /* 10 seconds */
795         (*cli)->fd = sockfd;
796         fstrcpy((*cli)->desthost, controller);
797         (*cli)->use_kerberos = True;
798
799         peeraddr_len = sizeof(peeraddr);
800
801         if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
802             (peeraddr_len != sizeof(struct sockaddr_in)) ||
803             (peeraddr_in->sin_family != PF_INET))
804         {
805                 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
806                 result = NT_STATUS_UNSUCCESSFUL;
807                 goto done;
808         }
809
810         if (ntohs(peeraddr_in->sin_port) == 139) {
811                 struct nmb_name calling;
812                 struct nmb_name called;
813
814                 make_nmb_name(&calling, global_myname(), 0x0);
815                 make_nmb_name(&called, "*SMBSERVER", 0x20);
816
817                 if (!cli_session_request(*cli, &calling, &called)) {
818                         DEBUG(8, ("cli_session_request failed for %s\n",
819                                   controller));
820                         result = NT_STATUS_UNSUCCESSFUL;
821                         goto done;
822                 }
823         }
824
825         result = cli_negprot(*cli);
826
827         if (!NT_STATUS_IS_OK(result)) {
828                 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
829                 goto done;
830         }
831
832         if (!is_dc_trusted_domain_situation(domain->name) &&
833             (*cli)->protocol >= PROTOCOL_NT1 &&
834             (*cli)->capabilities & CAP_EXTENDED_SECURITY)
835         {
836                 ADS_STATUS ads_status;
837
838                 result = get_trust_creds(domain, &machine_password,
839                                          &machine_account,
840                                          &machine_krb5_principal);
841                 if (!NT_STATUS_IS_OK(result)) {
842                         goto anon_fallback;
843                 }
844
845                 if (lp_security() == SEC_ADS) {
846
847                         /* Try a krb5 session */
848
849                         (*cli)->use_kerberos = True;
850                         DEBUG(5, ("connecting to %s from %s with kerberos principal "
851                                   "[%s] and realm [%s]\n", controller, global_myname(),
852                                   machine_krb5_principal, domain->alt_name));
853
854                         winbindd_set_locator_kdc_envs(domain);
855
856                         ads_status = cli_session_setup_spnego(*cli,
857                                                               machine_krb5_principal, 
858                                                               machine_password,
859                                                               lp_workgroup(),
860                                                               domain->name);
861
862                         if (!ADS_ERR_OK(ads_status)) {
863                                 DEBUG(4,("failed kerberos session setup with %s\n",
864                                          ads_errstr(ads_status)));
865                         }
866
867                         result = ads_ntstatus(ads_status);
868                         if (NT_STATUS_IS_OK(result)) {
869                                 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
870                                 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
871                                 if (!NT_STATUS_IS_OK(result)) {
872                                         goto done;
873                                 }
874                                 goto session_setup_done;
875                         }
876                 }
877
878                 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
879                 (*cli)->use_kerberos = False;
880
881                 DEBUG(5, ("connecting to %s from %s with username "
882                           "[%s]\\[%s]\n",  controller, global_myname(),
883                           lp_workgroup(), machine_account));
884
885                 ads_status = cli_session_setup_spnego(*cli,
886                                                       machine_account, 
887                                                       machine_password, 
888                                                       lp_workgroup(),
889                                                       NULL);
890                 if (!ADS_ERR_OK(ads_status)) {
891                         DEBUG(4, ("authenticated session setup failed with %s\n",
892                                 ads_errstr(ads_status)));
893                 }
894
895                 result = ads_ntstatus(ads_status);
896                 if (NT_STATUS_IS_OK(result)) {
897                         /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
898                         result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
899                         if (!NT_STATUS_IS_OK(result)) {
900                                 goto done;
901                         }
902                         goto session_setup_done;
903                 }
904         }
905
906         /* Fall back to non-kerberos session setup with auth_user */
907
908         (*cli)->use_kerberos = False;
909
910         cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
911
912         if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
913             (strlen(ipc_username) > 0)) {
914
915                 /* Only try authenticated if we have a username */
916
917                 DEBUG(5, ("connecting to %s from %s with username "
918                           "[%s]\\[%s]\n",  controller, global_myname(),
919                           ipc_domain, ipc_username));
920
921                 if (NT_STATUS_IS_OK(cli_session_setup(
922                                             *cli, ipc_username,
923                                             ipc_password, strlen(ipc_password)+1,
924                                             ipc_password, strlen(ipc_password)+1,
925                                             ipc_domain))) {
926                         /* Successful logon with given username. */
927                         result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
928                         if (!NT_STATUS_IS_OK(result)) {
929                                 goto done;
930                         }
931                         goto session_setup_done;
932                 } else {
933                         DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
934                                 ipc_domain, ipc_username ));
935                 }
936         }
937
938  anon_fallback:
939
940         /* Fall back to anonymous connection, this might fail later */
941         DEBUG(10,("cm_prepare_connection: falling back to anonymous "
942                 "connection for DC %s\n",
943                 controller ));
944
945         if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
946                                               NULL, 0, ""))) {
947                 DEBUG(5, ("Connected anonymously\n"));
948                 result = cli_init_creds(*cli, "", "", "");
949                 if (!NT_STATUS_IS_OK(result)) {
950                         goto done;
951                 }
952                 goto session_setup_done;
953         }
954
955         result = cli_nt_error(*cli);
956
957         if (NT_STATUS_IS_OK(result))
958                 result = NT_STATUS_UNSUCCESSFUL;
959
960         /* We can't session setup */
961
962         goto done;
963
964  session_setup_done:
965
966         /* cache the server name for later connections */
967
968         saf_store( domain->name, (*cli)->desthost );
969         if (domain->alt_name && (*cli)->use_kerberos) {
970                 saf_store( domain->alt_name, (*cli)->desthost );
971         }
972
973         winbindd_set_locator_kdc_envs(domain);
974
975         result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
976
977         if (!NT_STATUS_IS_OK(result)) {
978                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
979                 goto done;
980         }
981
982         TALLOC_FREE(mutex);
983         *retry = False;
984
985         /* set the domain if empty; needed for schannel connections */
986         if ( !(*cli)->domain[0] ) {
987                 result = cli_set_domain((*cli), domain->name);
988                 if (!NT_STATUS_IS_OK(result)) {
989                         return result;
990                 }
991         }
992
993         result = NT_STATUS_OK;
994
995  done:
996         TALLOC_FREE(mutex);
997         SAFE_FREE(machine_account);
998         SAFE_FREE(machine_password);
999         SAFE_FREE(machine_krb5_principal);
1000         SAFE_FREE(ipc_username);
1001         SAFE_FREE(ipc_domain);
1002         SAFE_FREE(ipc_password);
1003
1004         if (!NT_STATUS_IS_OK(result)) {
1005                 winbind_add_failed_connection_entry(domain, controller, result);
1006                 if ((*cli) != NULL) {
1007                         cli_shutdown(*cli);
1008                         *cli = NULL;
1009                 }
1010         }
1011
1012         return result;
1013 }
1014
1015 /*******************************************************************
1016  Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1017  array.
1018
1019  Keeps the list unique by not adding duplicate entries.
1020
1021  @param[in] mem_ctx talloc memory context to allocate from
1022  @param[in] domain_name domain of the DC
1023  @param[in] dcname name of the DC to add to the list
1024  @param[in] pss Internet address and port pair to add to the list
1025  @param[in,out] dcs array of dc_name_ip structures to add to
1026  @param[in,out] num_dcs number of dcs returned in the dcs array
1027  @return true if the list was added to, false otherwise
1028 *******************************************************************/
1029
1030 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1031                               const char *dcname, struct sockaddr_storage *pss,
1032                               struct dc_name_ip **dcs, int *num)
1033 {
1034         int i = 0;
1035
1036         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1037                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1038                 return False;
1039         }
1040
1041         /* Make sure there's no duplicates in the list */
1042         for (i=0; i<*num; i++)
1043                 if (sockaddr_equal((struct sockaddr *)&(*dcs)[i].ss, (struct sockaddr *)pss))
1044                         return False;
1045
1046         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1047
1048         if (*dcs == NULL)
1049                 return False;
1050
1051         fstrcpy((*dcs)[*num].name, dcname);
1052         (*dcs)[*num].ss = *pss;
1053         *num += 1;
1054         return True;
1055 }
1056
1057 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1058                                   struct sockaddr_storage *pss, uint16 port,
1059                                   struct sockaddr_storage **addrs, int *num)
1060 {
1061         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1062
1063         if (*addrs == NULL) {
1064                 *num = 0;
1065                 return False;
1066         }
1067
1068         (*addrs)[*num] = *pss;
1069         set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1070
1071         *num += 1;
1072         return True;
1073 }
1074
1075 /*******************************************************************
1076  convert an ip to a name
1077 *******************************************************************/
1078
1079 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1080                 const struct winbindd_domain *domain,
1081                 struct sockaddr_storage *pss,
1082                 fstring name )
1083 {
1084         struct ip_service ip_list;
1085         uint32_t nt_version = NETLOGON_NT_VERSION_1;
1086
1087         ip_list.ss = *pss;
1088         ip_list.port = 0;
1089
1090 #ifdef WITH_ADS
1091         /* For active directory servers, try to get the ldap server name.
1092            None of these failures should be considered critical for now */
1093
1094         if (lp_security() == SEC_ADS) {
1095                 ADS_STRUCT *ads;
1096                 ADS_STATUS ads_status;
1097                 char addr[INET6_ADDRSTRLEN];
1098
1099                 print_sockaddr(addr, sizeof(addr), pss);
1100
1101                 ads = ads_init(domain->alt_name, domain->name, addr);
1102                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1103
1104                 ads_status = ads_connect(ads);
1105                 if (ADS_ERR_OK(ads_status)) {
1106                         /* We got a cldap packet. */
1107                         fstrcpy(name, ads->config.ldap_server_name);
1108                         namecache_store(name, 0x20, 1, &ip_list);
1109
1110                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1111
1112                         if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1113                                 if (ads_closest_dc(ads)) {
1114                                         char *sitename = sitename_fetch(ads->config.realm);
1115
1116                                         /* We're going to use this KDC for this realm/domain.
1117                                            If we are using sites, then force the krb5 libs
1118                                            to use this KDC. */
1119
1120                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1121                                                                         domain->name,
1122                                                                         sitename,
1123                                                                         pss);
1124
1125                                         SAFE_FREE(sitename);
1126                                 } else {
1127                                         /* use an off site KDC */
1128                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1129                                                                         domain->name,
1130                                                                         NULL,
1131                                                                         pss);
1132                                 }
1133                                 winbindd_set_locator_kdc_envs(domain);
1134
1135                                 /* Ensure we contact this DC also. */
1136                                 saf_store( domain->name, name);
1137                                 saf_store( domain->alt_name, name);
1138                         }
1139
1140                         ads_destroy( &ads );
1141                         return True;
1142                 }
1143
1144                 ads_destroy( &ads );
1145         }
1146 #endif
1147
1148         /* try GETDC requests next */
1149
1150         if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1151                                pss, domain->name, &domain->sid,
1152                                nt_version)) {
1153                 const char *dc_name = NULL;
1154                 int i;
1155                 smb_msleep(100);
1156                 for (i=0; i<5; i++) {
1157                         if (receive_getdc_response(mem_ctx, pss, domain->name,
1158                                                    &nt_version,
1159                                                    &dc_name, NULL)) {
1160                                 fstrcpy(name, dc_name);
1161                                 namecache_store(name, 0x20, 1, &ip_list);
1162                                 return True;
1163                         }
1164                         smb_msleep(500);
1165                 }
1166         }
1167
1168         /* try node status request */
1169
1170         if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1171                 namecache_store(name, 0x20, 1, &ip_list);
1172                 return True;
1173         }
1174         return False;
1175 }
1176
1177 /*******************************************************************
1178  Retrieve a list of IP addresses for domain controllers.
1179
1180  The array is sorted in the preferred connection order.
1181
1182  @param[in] mem_ctx talloc memory context to allocate from
1183  @param[in] domain domain to retrieve DCs for
1184  @param[out] dcs array of dcs that will be returned
1185  @param[out] num_dcs number of dcs returned in the dcs array
1186  @return always true
1187 *******************************************************************/
1188
1189 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1190                     struct dc_name_ip **dcs, int *num_dcs)
1191 {
1192         fstring dcname;
1193         struct  sockaddr_storage ss;
1194         struct  ip_service *ip_list = NULL;
1195         int     iplist_size = 0;
1196         int     i;
1197         bool    is_our_domain;
1198         enum security_types sec = (enum security_types)lp_security();
1199
1200         is_our_domain = strequal(domain->name, lp_workgroup());
1201
1202         /* If not our domain, get the preferred DC, by asking our primary DC */
1203         if ( !is_our_domain
1204                 && get_dc_name_via_netlogon(domain, dcname, &ss)
1205                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1206                        num_dcs) )
1207         {
1208                 char addr[INET6_ADDRSTRLEN];
1209                 print_sockaddr(addr, sizeof(addr), &ss);
1210                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1211                            dcname, addr));
1212                 return True;
1213         }
1214
1215         if (sec == SEC_ADS) {
1216                 char *sitename = NULL;
1217
1218                 /* We need to make sure we know the local site before
1219                    doing any DNS queries, as this will restrict the
1220                    get_sorted_dc_list() call below to only fetching
1221                    DNS records for the correct site. */
1222
1223                 /* Find any DC to get the site record.
1224                    We deliberately don't care about the
1225                    return here. */
1226
1227                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1228
1229                 sitename = sitename_fetch(domain->alt_name);
1230                 if (sitename) {
1231
1232                         /* Do the site-specific AD dns lookup first. */
1233                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1234                                &iplist_size, True);
1235
1236                         /* Add ips to the DC array.  We don't look up the name
1237                            of the DC in this function, but we fill in the char*
1238                            of the ip now to make the failed connection cache
1239                            work */
1240                         for ( i=0; i<iplist_size; i++ ) {
1241                                 char addr[INET6_ADDRSTRLEN];
1242                                 print_sockaddr(addr, sizeof(addr),
1243                                                 &ip_list[i].ss);
1244                                 add_one_dc_unique(mem_ctx,
1245                                                 domain->name,
1246                                                 addr,
1247                                                 &ip_list[i].ss,
1248                                                 dcs,
1249                                                 num_dcs);
1250                         }
1251
1252                         SAFE_FREE(ip_list);
1253                         SAFE_FREE(sitename);
1254                         iplist_size = 0;
1255                 }
1256
1257                 /* Now we add DCs from the main AD DNS lookup. */
1258                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1259                         &iplist_size, True);
1260
1261                 for ( i=0; i<iplist_size; i++ ) {
1262                         char addr[INET6_ADDRSTRLEN];
1263                         print_sockaddr(addr, sizeof(addr),
1264                                         &ip_list[i].ss);
1265                         add_one_dc_unique(mem_ctx,
1266                                         domain->name,
1267                                         addr,
1268                                         &ip_list[i].ss,
1269                                         dcs,
1270                                         num_dcs);
1271                 }
1272
1273                 SAFE_FREE(ip_list);
1274                 iplist_size = 0;
1275         }
1276
1277         /* Try standard netbios queries if no ADS */
1278         if (*num_dcs == 0) {
1279                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1280                        False);
1281
1282                 for ( i=0; i<iplist_size; i++ ) {
1283                         char addr[INET6_ADDRSTRLEN];
1284                         print_sockaddr(addr, sizeof(addr),
1285                                         &ip_list[i].ss);
1286                         add_one_dc_unique(mem_ctx,
1287                                         domain->name,
1288                                         addr,
1289                                         &ip_list[i].ss,
1290                                         dcs,
1291                                         num_dcs);
1292                 }
1293
1294                 SAFE_FREE(ip_list);
1295                 iplist_size = 0;
1296         }
1297
1298         return True;
1299 }
1300
1301 /*******************************************************************
1302  Find and make a connection to a DC in the given domain.
1303
1304  @param[in] mem_ctx talloc memory context to allocate from
1305  @param[in] domain domain to find a dc in
1306  @param[out] dcname NetBIOS or FQDN of DC that's connected to
1307  @param[out] pss DC Internet address and port
1308  @param[out] fd fd of the open socket connected to the newly found dc
1309  @return true when a DC connection is made, false otherwise
1310 *******************************************************************/
1311
1312 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1313                         struct winbindd_domain *domain,
1314                         fstring dcname, struct sockaddr_storage *pss, int *fd)
1315 {
1316         struct dc_name_ip *dcs = NULL;
1317         int num_dcs = 0;
1318
1319         const char **dcnames = NULL;
1320         int num_dcnames = 0;
1321
1322         struct sockaddr_storage *addrs = NULL;
1323         int num_addrs = 0;
1324
1325         int i, fd_index;
1326
1327         *fd = -1;
1328
1329  again:
1330         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1331                 return False;
1332
1333         for (i=0; i<num_dcs; i++) {
1334
1335                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1336                                     &dcnames, &num_dcnames)) {
1337                         return False;
1338                 }
1339                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1340                                       &addrs, &num_addrs)) {
1341                         return False;
1342                 }
1343
1344                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1345                                     &dcnames, &num_dcnames)) {
1346                         return False;
1347                 }
1348                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1349                                       &addrs, &num_addrs)) {
1350                         return False;
1351                 }
1352         }
1353
1354         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1355                 return False;
1356
1357         if ((addrs == NULL) || (dcnames == NULL))
1358                 return False;
1359
1360         /* 5 second timeout. */
1361         if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1362                 for (i=0; i<num_dcs; i++) {
1363                         char ab[INET6_ADDRSTRLEN];
1364                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1365                         DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1366                                 "domain %s address %s. Error was %s\n",
1367                                 domain->name, ab, strerror(errno) ));
1368                         winbind_add_failed_connection_entry(domain,
1369                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1370                 }
1371                 return False;
1372         }
1373
1374         *pss = addrs[fd_index];
1375
1376         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1377                 /* Ok, we've got a name for the DC */
1378                 fstrcpy(dcname, dcnames[fd_index]);
1379                 return True;
1380         }
1381
1382         /* Try to figure out the name */
1383         if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1384                 return True;
1385         }
1386
1387         /* We can not continue without the DC's name */
1388         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1389                                     NT_STATUS_UNSUCCESSFUL);
1390
1391         /* Throw away all arrays as we're doing this again. */
1392         TALLOC_FREE(dcs);
1393         num_dcs = 0;
1394
1395         TALLOC_FREE(dcnames);
1396         num_dcnames = 0;
1397
1398         TALLOC_FREE(addrs);
1399         num_addrs = 0;
1400
1401         close(*fd);
1402         *fd = -1;
1403
1404         goto again;
1405 }
1406
1407 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1408                                    struct winbindd_cm_conn *new_conn)
1409 {
1410         TALLOC_CTX *mem_ctx;
1411         NTSTATUS result;
1412         char *saf_servername = saf_fetch( domain->name );
1413         int retries;
1414
1415         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1416                 SAFE_FREE(saf_servername);
1417                 set_domain_offline(domain);
1418                 return NT_STATUS_NO_MEMORY;
1419         }
1420
1421         /* we have to check the server affinity cache here since 
1422            later we selecte a DC based on response time and not preference */
1423
1424         /* Check the negative connection cache
1425            before talking to it. It going down may have
1426            triggered the reconnection. */
1427
1428         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1429
1430                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1431                         saf_servername, domain->name ));
1432
1433                 /* convert an ip address to a name */
1434                 if (is_ipaddress( saf_servername ) ) {
1435                         fstring saf_name;
1436                         struct sockaddr_storage ss;
1437
1438                         if (!interpret_string_addr(&ss, saf_servername,
1439                                                 AI_NUMERICHOST)) {
1440                                 return NT_STATUS_UNSUCCESSFUL;
1441                         }
1442                         if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1443                                 fstrcpy( domain->dcname, saf_name );
1444                         } else {
1445                                 winbind_add_failed_connection_entry(
1446                                         domain, saf_servername,
1447                                         NT_STATUS_UNSUCCESSFUL);
1448                         }
1449                 } else {
1450                         fstrcpy( domain->dcname, saf_servername );
1451                 }
1452
1453                 SAFE_FREE( saf_servername );
1454         }
1455
1456         for (retries = 0; retries < 3; retries++) {
1457                 int fd = -1;
1458                 bool retry = False;
1459
1460                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1461
1462                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1463                         domain->dcname, domain->name ));
1464
1465                 if (*domain->dcname 
1466                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1467                         && (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
1468                 {
1469                         struct sockaddr_storage *addrs = NULL;
1470                         int num_addrs = 0;
1471                         int dummy = 0;
1472
1473                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1474                                 set_domain_offline(domain);
1475                                 talloc_destroy(mem_ctx);
1476                                 return NT_STATUS_NO_MEMORY;
1477                         }
1478                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1479                                 set_domain_offline(domain);
1480                                 talloc_destroy(mem_ctx);
1481                                 return NT_STATUS_NO_MEMORY;
1482                         }
1483
1484                         /* 5 second timeout. */
1485                         if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1486                                 fd = -1;
1487                         }
1488                 }
1489
1490                 if ((fd == -1) 
1491                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1492                 {
1493                         /* This is the one place where we will
1494                            set the global winbindd offline state
1495                            to true, if a "WINBINDD_OFFLINE" entry
1496                            is found in the winbindd cache. */
1497                         set_global_winbindd_state_offline();
1498                         break;
1499                 }
1500
1501                 new_conn->cli = NULL;
1502
1503                 result = cm_prepare_connection(domain, fd, domain->dcname,
1504                         &new_conn->cli, &retry);
1505
1506                 if (!retry)
1507                         break;
1508         }
1509
1510         if (NT_STATUS_IS_OK(result)) {
1511
1512                 winbindd_set_locator_kdc_envs(domain);
1513
1514                 if (domain->online == False) {
1515                         /* We're changing state from offline to online. */
1516                         set_global_winbindd_state_online();
1517                 }
1518                 set_domain_online(domain);
1519         } else {
1520                 /* Ensure we setup the retry handler. */
1521                 set_domain_offline(domain);
1522         }
1523
1524         talloc_destroy(mem_ctx);
1525         return result;
1526 }
1527
1528 /* Close down all open pipes on a connection. */
1529
1530 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1531 {
1532         /* We're closing down a possibly dead
1533            connection. Don't have impossibly long (10s) timeouts. */
1534
1535         if (conn->cli) {
1536                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1537         }
1538
1539         if (conn->samr_pipe != NULL) {
1540                 TALLOC_FREE(conn->samr_pipe);
1541                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1542                 if (conn->cli) {
1543                         cli_set_timeout(conn->cli, 500);
1544                 }
1545         }
1546
1547         if (conn->lsa_pipe != NULL) {
1548                 TALLOC_FREE(conn->lsa_pipe);
1549                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1550                 if (conn->cli) {
1551                         cli_set_timeout(conn->cli, 500);
1552                 }
1553         }
1554
1555         if (conn->netlogon_pipe != NULL) {
1556                 TALLOC_FREE(conn->netlogon_pipe);
1557                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1558                 if (conn->cli) {
1559                         cli_set_timeout(conn->cli, 500);
1560                 }
1561         }
1562
1563         if (conn->cli) {
1564                 cli_shutdown(conn->cli);
1565         }
1566
1567         conn->cli = NULL;
1568 }
1569
1570 void close_conns_after_fork(void)
1571 {
1572         struct winbindd_domain *domain;
1573
1574         for (domain = domain_list(); domain; domain = domain->next) {
1575                 if (domain->conn.cli == NULL)
1576                         continue;
1577
1578                 if (domain->conn.cli->fd == -1)
1579                         continue;
1580
1581                 close(domain->conn.cli->fd);
1582                 domain->conn.cli->fd = -1;
1583         }
1584 }
1585
1586 static bool connection_ok(struct winbindd_domain *domain)
1587 {
1588         if (domain->conn.cli == NULL) {
1589                 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1590                           "cli!\n", domain->dcname, domain->name));
1591                 return False;
1592         }
1593
1594         if (!domain->conn.cli->initialised) {
1595                 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1596                           "initialised!\n", domain->dcname, domain->name));
1597                 return False;
1598         }
1599
1600         if (domain->conn.cli->fd == -1) {
1601                 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1602                           "never started (fd == -1)\n", 
1603                           domain->dcname, domain->name));
1604                 return False;
1605         }
1606
1607         if (domain->online == False) {
1608                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1609                 return False;
1610         }
1611
1612         return True;
1613 }
1614
1615 /* Initialize a new connection up to the RPC BIND.
1616    Bypass online status check so always does network calls. */
1617
1618 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1619 {
1620         NTSTATUS result;
1621
1622         /* Internal connections never use the network. */
1623         if (domain->internal) {
1624                 domain->initialized = True;
1625                 return NT_STATUS_OK;
1626         }
1627
1628         if (connection_ok(domain)) {
1629                 if (!domain->initialized) {
1630                         set_dc_type_and_flags(domain);
1631                 }
1632                 return NT_STATUS_OK;
1633         }
1634
1635         invalidate_cm_connection(&domain->conn);
1636
1637         result = cm_open_connection(domain, &domain->conn);
1638
1639         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1640                 set_dc_type_and_flags(domain);
1641         }
1642
1643         return result;
1644 }
1645
1646 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1647 {
1648         if (domain->initialized && !domain->online) {
1649                 /* We check for online status elsewhere. */
1650                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1651         }
1652
1653         return init_dc_connection_network(domain);
1654 }
1655
1656 /******************************************************************************
1657  Set the trust flags (direction and forest location) for a domain
1658 ******************************************************************************/
1659
1660 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1661 {
1662         struct winbindd_domain *our_domain;
1663         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1664         struct netr_DomainTrustList trusts;
1665         int i;
1666         uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1667                         NETR_TRUST_FLAG_OUTBOUND |
1668                         NETR_TRUST_FLAG_INBOUND);
1669         struct rpc_pipe_client *cli;
1670         TALLOC_CTX *mem_ctx = NULL;
1671
1672         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1673
1674         /* Our primary domain doesn't need to worry about trust flags.
1675            Force it to go through the network setup */
1676         if ( domain->primary ) {                
1677                 return False;           
1678         }
1679
1680         our_domain = find_our_domain();
1681
1682         if ( !connection_ok(our_domain) ) {
1683                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1684                 return False;
1685         }
1686
1687         /* This won't work unless our domain is AD */
1688
1689         if ( !our_domain->active_directory ) {
1690                 return False;
1691         }
1692
1693         /* Use DsEnumerateDomainTrusts to get us the trust direction
1694            and type */
1695
1696         result = cm_connect_netlogon(our_domain, &cli);
1697
1698         if (!NT_STATUS_IS_OK(result)) {
1699                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1700                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1701                           domain->name, nt_errstr(result)));
1702                 return False;
1703         }
1704
1705         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1706                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1707                 return False;
1708         }       
1709
1710         result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1711                                                       cli->desthost,
1712                                                       flags,
1713                                                       &trusts,
1714                                                       NULL);
1715         if (!NT_STATUS_IS_OK(result)) {
1716                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1717                         "failed to query trusted domain list: %s\n",
1718                         nt_errstr(result)));
1719                 talloc_destroy(mem_ctx);
1720                 return false;
1721         }
1722
1723         /* Now find the domain name and get the flags */
1724
1725         for ( i=0; i<trusts.count; i++ ) {
1726                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1727                         domain->domain_flags          = trusts.array[i].trust_flags;
1728                         domain->domain_type           = trusts.array[i].trust_type;
1729                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
1730
1731                         if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1732                                 domain->active_directory = True;
1733
1734                         /* This flag is only set if the domain is *our* 
1735                            primary domain and the primary domain is in
1736                            native mode */
1737
1738                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1739
1740                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1741                                   "native mode.\n", domain->name, 
1742                                   domain->native_mode ? "" : "NOT "));
1743
1744                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1745                                  "running active directory.\n", domain->name, 
1746                                  domain->active_directory ? "" : "NOT "));
1747
1748
1749                         domain->initialized = True;
1750
1751                         if ( !winbindd_can_contact_domain( domain) )
1752                                 domain->internal = True;
1753
1754                         break;
1755                 }               
1756         }
1757
1758         talloc_destroy( mem_ctx );
1759
1760         return domain->initialized;     
1761 }
1762
1763 /******************************************************************************
1764  We can 'sense' certain things about the DC by it's replies to certain
1765  questions.
1766
1767  This tells us if this particular remote server is Active Directory, and if it
1768  is native mode.
1769 ******************************************************************************/
1770
1771 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1772 {
1773         NTSTATUS                result;
1774         WERROR werr;
1775         TALLOC_CTX              *mem_ctx = NULL;
1776         struct rpc_pipe_client  *cli = NULL;
1777         struct policy_handle pol;
1778         union dssetup_DsRoleInfo info;
1779         union lsa_PolicyInformation *lsa_info = NULL;
1780
1781         if (!connection_ok(domain)) {
1782                 return;
1783         }
1784
1785         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1786                               domain->name);
1787         if (!mem_ctx) {
1788                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1789                 return;
1790         }
1791
1792         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1793
1794         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1795                                           &ndr_table_dssetup.syntax_id,
1796                                           &cli);
1797
1798         if (!NT_STATUS_IS_OK(result)) {
1799                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1800                           "PI_DSSETUP on domain %s: (%s)\n",
1801                           domain->name, nt_errstr(result)));
1802
1803                 /* if this is just a non-AD domain we need to continue
1804                  * identifying so that we can in the end return with
1805                  * domain->initialized = True - gd */
1806
1807                 goto no_dssetup;
1808         }
1809
1810         result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1811                                                                   DS_ROLE_BASIC_INFORMATION,
1812                                                                   &info,
1813                                                                   &werr);
1814         TALLOC_FREE(cli);
1815
1816         if (!NT_STATUS_IS_OK(result)) {
1817                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1818                           "on domain %s failed: (%s)\n",
1819                           domain->name, nt_errstr(result)));
1820
1821                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1822                  * every opcode on the DSSETUP pipe, continue with
1823                  * no_dssetup mode here as well to get domain->initialized
1824                  * set - gd */
1825
1826                 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1827                         goto no_dssetup;
1828                 }
1829
1830                 TALLOC_FREE(mem_ctx);
1831                 return;
1832         }
1833
1834         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1835             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1836                 domain->native_mode = True;
1837         } else {
1838                 domain->native_mode = False;
1839         }
1840
1841 no_dssetup:
1842         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1843                                           &ndr_table_lsarpc.syntax_id, &cli);
1844
1845         if (!NT_STATUS_IS_OK(result)) {
1846                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1847                           "PI_LSARPC on domain %s: (%s)\n",
1848                           domain->name, nt_errstr(result)));
1849                 TALLOC_FREE(cli);
1850                 TALLOC_FREE(mem_ctx);
1851                 return;
1852         }
1853
1854         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
1855                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1856
1857         if (NT_STATUS_IS_OK(result)) {
1858                 /* This particular query is exactly what Win2k clients use 
1859                    to determine that the DC is active directory */
1860                 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1861                                                      &pol,
1862                                                      LSA_POLICY_INFO_DNS,
1863                                                      &lsa_info);
1864         }
1865
1866         if (NT_STATUS_IS_OK(result)) {
1867                 domain->active_directory = True;
1868
1869                 if (lsa_info->dns.name.string) {
1870                         fstrcpy(domain->name, lsa_info->dns.name.string);
1871                 }
1872
1873                 if (lsa_info->dns.dns_domain.string) {
1874                         fstrcpy(domain->alt_name,
1875                                 lsa_info->dns.dns_domain.string);
1876                 }
1877
1878                 /* See if we can set some domain trust flags about
1879                    ourself */
1880
1881                 if (lsa_info->dns.dns_forest.string) {
1882                         fstrcpy(domain->forest_name,
1883                                 lsa_info->dns.dns_forest.string);
1884
1885                         if (strequal(domain->forest_name, domain->alt_name)) {
1886                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1887                         }
1888                 }
1889
1890                 if (lsa_info->dns.sid) {
1891                         sid_copy(&domain->sid, lsa_info->dns.sid);
1892                 }
1893         } else {
1894                 domain->active_directory = False;
1895
1896                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
1897                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
1898                                                 &pol);
1899
1900                 if (!NT_STATUS_IS_OK(result)) {
1901                         goto done;
1902                 }
1903
1904                 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1905                                                     &pol,
1906                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1907                                                     &lsa_info);
1908
1909                 if (NT_STATUS_IS_OK(result)) {
1910
1911                         if (lsa_info->account_domain.name.string) {
1912                                 fstrcpy(domain->name,
1913                                         lsa_info->account_domain.name.string);
1914                         }
1915
1916                         if (lsa_info->account_domain.sid) {
1917                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1918                         }
1919                 }
1920         }
1921 done:
1922
1923         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1924                   domain->name, domain->native_mode ? "" : "NOT "));
1925
1926         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1927                   domain->name, domain->active_directory ? "" : "NOT "));
1928
1929         TALLOC_FREE(cli);
1930
1931         TALLOC_FREE(mem_ctx);
1932
1933         domain->initialized = True;
1934 }
1935
1936 /**********************************************************************
1937  Set the domain_flags (trust attributes, domain operating modes, etc... 
1938 ***********************************************************************/
1939
1940 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1941 {
1942         /* we always have to contact our primary domain */
1943
1944         if ( domain->primary ) {
1945                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1946                           "primary domain\n"));
1947                 set_dc_type_and_flags_connect( domain );
1948                 return;         
1949         }
1950
1951         /* Use our DC to get the information if possible */
1952
1953         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1954                 /* Otherwise, fallback to contacting the 
1955                    domain directly */
1956                 set_dc_type_and_flags_connect( domain );
1957         }
1958
1959         return;
1960 }
1961
1962
1963
1964 /**********************************************************************
1965 ***********************************************************************/
1966
1967 static bool cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1968                                    struct dcinfo **ppdc)
1969 {
1970         NTSTATUS result;
1971         struct rpc_pipe_client *netlogon_pipe;
1972
1973         if (lp_client_schannel() == False) {
1974                 return False;
1975         }
1976
1977         result = cm_connect_netlogon(domain, &netlogon_pipe);
1978         if (!NT_STATUS_IS_OK(result)) {
1979                 return False;
1980         }
1981
1982         /* Return a pointer to the struct dcinfo from the
1983            netlogon pipe. */
1984
1985         if (!domain->conn.netlogon_pipe->dc) {
1986                 return false;
1987         }
1988
1989         *ppdc = domain->conn.netlogon_pipe->dc;
1990         return True;
1991 }
1992
1993 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1994                         struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
1995 {
1996         struct winbindd_cm_conn *conn;
1997         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1998         struct dcinfo *p_dcinfo;
1999         char *machine_password = NULL;
2000         char *machine_account = NULL;
2001         char *domain_name = NULL;
2002
2003         result = init_dc_connection(domain);
2004         if (!NT_STATUS_IS_OK(result)) {
2005                 return result;
2006         }
2007
2008         conn = &domain->conn;
2009
2010         if (conn->samr_pipe != NULL) {
2011                 goto done;
2012         }
2013
2014
2015         /*
2016          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2017          * sign and sealed pipe using the machine account password by
2018          * preference. If we can't - try schannel, if that fails, try
2019          * anonymous.
2020          */
2021
2022         if ((conn->cli->user_name[0] == '\0') ||
2023             (conn->cli->domain[0] == '\0') || 
2024             (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2025         {
2026                 result = get_trust_creds(domain, &machine_password,
2027                                          &machine_account, NULL);
2028                 if (!NT_STATUS_IS_OK(result)) {
2029                         DEBUG(10, ("cm_connect_sam: No no user available for "
2030                                    "domain %s, trying schannel\n", conn->cli->domain));
2031                         goto schannel;
2032                 }
2033                 domain_name = domain->name;
2034         } else {
2035                 machine_password = SMB_STRDUP(conn->cli->password);
2036                 machine_account = SMB_STRDUP(conn->cli->user_name);
2037                 domain_name = conn->cli->domain;
2038         }
2039
2040         if (!machine_password || !machine_account) {
2041                 result = NT_STATUS_NO_MEMORY;
2042                 goto done;
2043         }
2044
2045         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2046            authenticated SAMR pipe with sign & seal. */
2047         result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2048                                                   &ndr_table_samr.syntax_id,
2049                                                   PIPE_AUTH_LEVEL_PRIVACY,
2050                                                   domain_name,
2051                                                   machine_account,
2052                                                   machine_password,
2053                                                   &conn->samr_pipe);
2054
2055         if (!NT_STATUS_IS_OK(result)) {
2056                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2057                           "pipe for domain %s using NTLMSSP "
2058                           "authenticated pipe: user %s\\%s. Error was "
2059                           "%s\n", domain->name, domain_name,
2060                           machine_account, nt_errstr(result)));
2061                 goto schannel;
2062         }
2063
2064         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2065                   "domain %s using NTLMSSP authenticated "
2066                   "pipe: user %s\\%s\n", domain->name,
2067                   domain_name, machine_account));
2068
2069         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2070                                       conn->samr_pipe->desthost,
2071                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2072                                       &conn->sam_connect_handle);
2073         if (NT_STATUS_IS_OK(result)) {
2074                 goto open_domain;
2075         }
2076         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2077                   "failed for domain %s, error was %s. Trying schannel\n",
2078                   domain->name, nt_errstr(result) ));
2079         TALLOC_FREE(conn->samr_pipe);
2080
2081  schannel:
2082
2083         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2084
2085         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2086                 /* If this call fails - conn->cli can now be NULL ! */
2087                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2088                            "for domain %s, trying anon\n", domain->name));
2089                 goto anonymous;
2090         }
2091         result = cli_rpc_pipe_open_schannel_with_key
2092                 (conn->cli, &ndr_table_samr.syntax_id, PIPE_AUTH_LEVEL_PRIVACY,
2093                  domain->name, p_dcinfo, &conn->samr_pipe);
2094
2095         if (!NT_STATUS_IS_OK(result)) {
2096                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2097                           "domain %s using schannel. Error was %s\n",
2098                           domain->name, nt_errstr(result) ));
2099                 goto anonymous;
2100         }
2101         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2102                   "schannel.\n", domain->name ));
2103
2104         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2105                                       conn->samr_pipe->desthost,
2106                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2107                                       &conn->sam_connect_handle);
2108         if (NT_STATUS_IS_OK(result)) {
2109                 goto open_domain;
2110         }
2111         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2112                   "for domain %s, error was %s. Trying anonymous\n",
2113                   domain->name, nt_errstr(result) ));
2114         TALLOC_FREE(conn->samr_pipe);
2115
2116  anonymous:
2117
2118         /* Finally fall back to anonymous. */
2119         result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2120                                           &conn->samr_pipe);
2121
2122         if (!NT_STATUS_IS_OK(result)) {
2123                 goto done;
2124         }
2125
2126         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2127                                       conn->samr_pipe->desthost,
2128                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
2129                                       &conn->sam_connect_handle);
2130         if (!NT_STATUS_IS_OK(result)) {
2131                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2132                           "for domain %s Error was %s\n",
2133                           domain->name, nt_errstr(result) ));
2134                 goto done;
2135         }
2136
2137  open_domain:
2138         result = rpccli_samr_OpenDomain(conn->samr_pipe,
2139                                         mem_ctx,
2140                                         &conn->sam_connect_handle,
2141                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2142                                         &domain->sid,
2143                                         &conn->sam_domain_handle);
2144
2145  done:
2146
2147         if (!NT_STATUS_IS_OK(result)) {
2148                 invalidate_cm_connection(conn);
2149                 return result;
2150         }
2151
2152         *cli = conn->samr_pipe;
2153         *sam_handle = conn->sam_domain_handle;
2154         SAFE_FREE(machine_password);
2155         SAFE_FREE(machine_account);
2156         return result;
2157 }
2158
2159 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2160                         struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2161 {
2162         struct winbindd_cm_conn *conn;
2163         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2164         struct dcinfo *p_dcinfo;
2165
2166         result = init_dc_connection(domain);
2167         if (!NT_STATUS_IS_OK(result))
2168                 return result;
2169
2170         conn = &domain->conn;
2171
2172         if (conn->lsa_pipe != NULL) {
2173                 goto done;
2174         }
2175
2176         if ((conn->cli->user_name[0] == '\0') ||
2177             (conn->cli->domain[0] == '\0') || 
2178             (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2179                 DEBUG(10, ("cm_connect_lsa: No no user available for "
2180                            "domain %s, trying schannel\n", conn->cli->domain));
2181                 goto schannel;
2182         }
2183
2184         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2185          * authenticated LSA pipe with sign & seal. */
2186         result = cli_rpc_pipe_open_spnego_ntlmssp
2187                 (conn->cli, &ndr_table_lsarpc.syntax_id,
2188                  PIPE_AUTH_LEVEL_PRIVACY,
2189                  conn->cli->domain, conn->cli->user_name, conn->cli->password,
2190                  &conn->lsa_pipe);
2191
2192         if (!NT_STATUS_IS_OK(result)) {
2193                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2194                           "domain %s using NTLMSSP authenticated pipe: user "
2195                           "%s\\%s. Error was %s. Trying schannel.\n",
2196                           domain->name, conn->cli->domain,
2197                           conn->cli->user_name, nt_errstr(result)));
2198                 goto schannel;
2199         }
2200
2201         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2202                   "NTLMSSP authenticated pipe: user %s\\%s\n",
2203                   domain->name, conn->cli->domain, conn->cli->user_name ));
2204
2205         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2206                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2207                                         &conn->lsa_policy);
2208         if (NT_STATUS_IS_OK(result)) {
2209                 goto done;
2210         }
2211
2212         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2213                   "schannel\n"));
2214
2215         TALLOC_FREE(conn->lsa_pipe);
2216
2217  schannel:
2218
2219         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2220
2221         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
2222                 /* If this call fails - conn->cli can now be NULL ! */
2223                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2224                            "for domain %s, trying anon\n", domain->name));
2225                 goto anonymous;
2226         }
2227         result = cli_rpc_pipe_open_schannel_with_key
2228                 (conn->cli, &ndr_table_lsarpc.syntax_id,
2229                  PIPE_AUTH_LEVEL_PRIVACY,
2230                  domain->name, p_dcinfo, &conn->lsa_pipe);
2231
2232         if (!NT_STATUS_IS_OK(result)) {
2233                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2234                           "domain %s using schannel. Error was %s\n",
2235                           domain->name, nt_errstr(result) ));
2236                 goto anonymous;
2237         }
2238         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2239                   "schannel.\n", domain->name ));
2240
2241         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2242                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2243                                         &conn->lsa_policy);
2244         if (NT_STATUS_IS_OK(result)) {
2245                 goto done;
2246         }
2247
2248         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2249                   "anonymous\n"));
2250
2251         TALLOC_FREE(conn->lsa_pipe);
2252
2253  anonymous:
2254
2255         result = cli_rpc_pipe_open_noauth(conn->cli,
2256                                           &ndr_table_lsarpc.syntax_id,
2257                                           &conn->lsa_pipe);
2258         if (!NT_STATUS_IS_OK(result)) {
2259                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2260                 goto done;
2261         }
2262
2263         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2264                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
2265                                         &conn->lsa_policy);
2266  done:
2267         if (!NT_STATUS_IS_OK(result)) {
2268                 invalidate_cm_connection(conn);
2269                 return result;
2270         }
2271
2272         *cli = conn->lsa_pipe;
2273         *lsa_policy = conn->lsa_policy;
2274         return result;
2275 }
2276
2277 /****************************************************************************
2278  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2279  session key stored in conn->netlogon_pipe->dc->sess_key.
2280 ****************************************************************************/
2281
2282 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2283                              struct rpc_pipe_client **cli)
2284 {
2285         struct winbindd_cm_conn *conn;
2286         NTSTATUS result;
2287
2288         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2289         uint8  mach_pwd[16];
2290         uint32  sec_chan_type;
2291         const char *account_name;
2292         struct rpc_pipe_client *netlogon_pipe = NULL;
2293
2294         *cli = NULL;
2295
2296         result = init_dc_connection(domain);
2297         if (!NT_STATUS_IS_OK(result)) {
2298                 return result;
2299         }
2300
2301         conn = &domain->conn;
2302
2303         if (conn->netlogon_pipe != NULL) {
2304                 *cli = conn->netlogon_pipe;
2305                 return NT_STATUS_OK;
2306         }
2307
2308         result = cli_rpc_pipe_open_noauth(conn->cli,
2309                                           &ndr_table_netlogon.syntax_id,
2310                                           &netlogon_pipe);
2311         if (!NT_STATUS_IS_OK(result)) {
2312                 return result;
2313         }
2314
2315         if ((!IS_DC) && (!domain->primary)) {
2316                 /* Clear the schannel request bit and drop down */
2317                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2318                 goto no_schannel;
2319         }
2320
2321         if (lp_client_schannel() != False) {
2322                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2323         }
2324
2325         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2326                                &sec_chan_type))
2327         {
2328                 TALLOC_FREE(netlogon_pipe);
2329                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2330         }
2331
2332         result = rpccli_netlogon_setup_creds(
2333                  netlogon_pipe,
2334                  domain->dcname, /* server name. */
2335                  domain->name,   /* domain name */
2336                  global_myname(), /* client name */
2337                  account_name,   /* machine account */
2338                  mach_pwd,       /* machine password */
2339                  sec_chan_type,  /* from get_trust_pw */
2340                  &neg_flags);
2341
2342         if (!NT_STATUS_IS_OK(result)) {
2343                 TALLOC_FREE(netlogon_pipe);
2344                 return result;
2345         }
2346
2347         if ((lp_client_schannel() == True) &&
2348                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2349                 DEBUG(3, ("Server did not offer schannel\n"));
2350                 TALLOC_FREE(netlogon_pipe);
2351                 return NT_STATUS_ACCESS_DENIED;
2352         }
2353
2354  no_schannel:
2355         if ((lp_client_schannel() == False) ||
2356                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2357                 /*
2358                  * NetSamLogonEx only works for schannel
2359                  */
2360                 domain->can_do_samlogon_ex = False;
2361
2362                 /* We're done - just keep the existing connection to NETLOGON
2363                  * open */
2364                 conn->netlogon_pipe = netlogon_pipe;
2365                 *cli = conn->netlogon_pipe;
2366                 return NT_STATUS_OK;
2367         }
2368
2369         /* Using the credentials from the first pipe, open a signed and sealed
2370            second netlogon pipe. The session key is stored in the schannel
2371            part of the new pipe auth struct.
2372         */
2373
2374         result = cli_rpc_pipe_open_schannel_with_key(
2375                 conn->cli, &ndr_table_netlogon.syntax_id,
2376                 PIPE_AUTH_LEVEL_PRIVACY, domain->name, netlogon_pipe->dc,
2377                 &conn->netlogon_pipe);
2378
2379         /* We can now close the initial netlogon pipe. */
2380         TALLOC_FREE(netlogon_pipe);
2381
2382         if (!NT_STATUS_IS_OK(result)) {
2383                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2384                           "was %s\n", nt_errstr(result)));
2385
2386                 /* make sure we return something besides OK */
2387                 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2388         }
2389
2390         /*
2391          * Try NetSamLogonEx for AD domains
2392          */
2393         domain->can_do_samlogon_ex = domain->active_directory;
2394
2395         *cli = conn->netlogon_pipe;
2396         return NT_STATUS_OK;
2397 }