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