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