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