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