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