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