s3:winbindd_cm: don't invalidate the whole connection when just samr gave ACCCESS_DENIED
[gd/samba-autobuild/.git] / source3 / winbindd / winbindd_cm.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon connection manager
5
6    Copyright (C) Tim Potter                2001
7    Copyright (C) Andrew Bartlett           2002
8    Copyright (C) Gerald (Jerry) Carter     2003-2005.
9    Copyright (C) Volker Lendecke           2004-2005
10    Copyright (C) Jeremy Allison            2006
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 /*
27    We need to manage connections to domain controllers without having to
28    mess up the main winbindd code with other issues.  The aim of the
29    connection manager is to:
30
31        - make connections to domain controllers and cache them
32        - re-establish connections when networks or servers go down
33        - centralise the policy on connection timeouts, domain controller
34          selection etc
35        - manage re-entrancy for when winbindd becomes able to handle
36          multiple outstanding rpc requests
37
38    Why not have connection management as part of the rpc layer like tng?
39    Good question.  This code may morph into libsmb/rpc_cache.c or something
40    like that but at the moment it's simply staying as part of winbind.  I
41    think the TNG architecture of forcing every user of the rpc layer to use
42    the connection caching system is a bad idea.  It should be an optional
43    method of using the routines.
44
45    The TNG design is quite good but I disagree with some aspects of the
46    implementation. -tpot
47
48  */
49
50 /*
51    TODO:
52
53      - I'm pretty annoyed by all the make_nmb_name() stuff.  It should be
54        moved down into another function.
55
56      - Take care when destroying cli_structs as they can be shared between
57        various sam handles.
58
59  */
60
61 #include "includes.h"
62 #include "winbindd.h"
63 #include "../libcli/auth/libcli_auth.h"
64
65 #undef DBGC_CLASS
66 #define DBGC_CLASS DBGC_WINBIND
67
68 struct dc_name_ip {
69         fstring name;
70         struct sockaddr_storage ss;
71 };
72
73 extern struct winbindd_methods reconnect_methods;
74 extern bool override_logfile;
75
76 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
77 static void set_dc_type_and_flags( struct winbindd_domain *domain );
78 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
79                     struct dc_name_ip **dcs, int *num_dcs);
80
81 /****************************************************************
82  Child failed to find DC's. Reschedule check.
83 ****************************************************************/
84
85 static void msg_failed_to_go_online(struct messaging_context *msg,
86                                     void *private_data,
87                                     uint32_t msg_type,
88                                     struct server_id server_id,
89                                     DATA_BLOB *data)
90 {
91         struct winbindd_domain *domain;
92         const char *domainname = (const char *)data->data;
93
94         if (data->data == NULL || data->length == 0) {
95                 return;
96         }
97
98         DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
99
100         for (domain = domain_list(); domain; domain = domain->next) {
101                 if (domain->internal) {
102                         continue;
103                 }
104
105                 if (strequal(domain->name, domainname)) {
106                         if (domain->online) {
107                                 /* We're already online, ignore. */
108                                 DEBUG(5,("msg_fail_to_go_online: domain %s "
109                                         "already online.\n", domainname));
110                                 continue;
111                         }
112
113                         /* Reschedule the online check. */
114                         set_domain_offline(domain);
115                         break;
116                 }
117         }
118 }
119
120 /****************************************************************
121  Actually cause a reconnect from a message.
122 ****************************************************************/
123
124 static void msg_try_to_go_online(struct messaging_context *msg,
125                                  void *private_data,
126                                  uint32_t msg_type,
127                                  struct server_id server_id,
128                                  DATA_BLOB *data)
129 {
130         struct winbindd_domain *domain;
131         const char *domainname = (const char *)data->data;
132
133         if (data->data == NULL || data->length == 0) {
134                 return;
135         }
136
137         DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
138
139         for (domain = domain_list(); domain; domain = domain->next) {
140                 if (domain->internal) {
141                         continue;
142                 }
143
144                 if (strequal(domain->name, domainname)) {
145
146                         if (domain->online) {
147                                 /* We're already online, ignore. */
148                                 DEBUG(5,("msg_try_to_go_online: domain %s "
149                                         "already online.\n", domainname));
150                                 continue;
151                         }
152
153                         /* This call takes care of setting the online
154                            flag to true if we connected, or re-adding
155                            the offline handler if false. Bypasses online
156                            check so always does network calls. */
157
158                         init_dc_connection_network(domain);
159                         break;
160                 }
161         }
162 }
163
164 /****************************************************************
165  Fork a child to try and contact a DC. Do this as contacting a
166  DC requires blocking lookups and we don't want to block our
167  parent.
168 ****************************************************************/
169
170 static bool fork_child_dc_connect(struct winbindd_domain *domain)
171 {
172         struct dc_name_ip *dcs = NULL;
173         int num_dcs = 0;
174         TALLOC_CTX *mem_ctx = NULL;
175         pid_t parent_pid = sys_getpid();
176         char *lfile = NULL;
177
178         /* Stop zombies */
179         CatchChild();
180
181         if (domain->dc_probe_pid != (pid_t)-1) {
182                 /*
183                  * We might already have a DC probe
184                  * child working, check.
185                  */
186                 if (process_exists_by_pid(domain->dc_probe_pid)) {
187                         DEBUG(10,("fork_child_dc_connect: pid %u already "
188                                 "checking for DC's.\n",
189                                 (unsigned int)domain->dc_probe_pid));
190                         return true;
191                 }
192                 domain->dc_probe_pid = (pid_t)-1;
193         }
194
195         domain->dc_probe_pid = sys_fork();
196
197         if (domain->dc_probe_pid == (pid_t)-1) {
198                 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
199                 return False;
200         }
201
202         if (domain->dc_probe_pid != (pid_t)0) {
203                 /* Parent */
204                 messaging_register(winbind_messaging_context(), NULL,
205                                    MSG_WINBIND_TRY_TO_GO_ONLINE,
206                                    msg_try_to_go_online);
207                 messaging_register(winbind_messaging_context(), NULL,
208                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
209                                    msg_failed_to_go_online);
210                 return True;
211         }
212
213         /* Child. */
214
215         /* Leave messages blocked - we will never process one. */
216
217         if (!override_logfile) {
218                 if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
219                         DEBUG(0, ("fork_child_dc_connect: out of memory.\n"));
220                         _exit(1);
221                 }
222         }
223
224         if (!winbindd_reinit_after_fork(lfile)) {
225                 messaging_send_buf(winbind_messaging_context(),
226                                    pid_to_procid(parent_pid),
227                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
228                                    (uint8 *)domain->name,
229                                    strlen(domain->name)+1);
230                 _exit(1);
231         }
232         SAFE_FREE(lfile);
233
234         mem_ctx = talloc_init("fork_child_dc_connect");
235         if (!mem_ctx) {
236                 DEBUG(0,("talloc_init failed.\n"));
237                 messaging_send_buf(winbind_messaging_context(),
238                                    pid_to_procid(parent_pid),
239                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
240                                    (uint8 *)domain->name,
241                                    strlen(domain->name)+1);
242                 _exit(1);
243         }
244
245         if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
246                 /* Still offline ? Can't find DC's. */
247                 messaging_send_buf(winbind_messaging_context(),
248                                    pid_to_procid(parent_pid),
249                                    MSG_WINBIND_FAILED_TO_GO_ONLINE,
250                                    (uint8 *)domain->name,
251                                    strlen(domain->name)+1);
252                 _exit(0);
253         }
254
255         /* We got a DC. Send a message to our parent to get it to
256            try and do the same. */
257
258         messaging_send_buf(winbind_messaging_context(),
259                            pid_to_procid(parent_pid),
260                            MSG_WINBIND_TRY_TO_GO_ONLINE,
261                            (uint8 *)domain->name,
262                            strlen(domain->name)+1);
263         _exit(0);
264 }
265
266 /****************************************************************
267  Handler triggered if we're offline to try and detect a DC.
268 ****************************************************************/
269
270 static void check_domain_online_handler(struct event_context *ctx,
271                                         struct timed_event *te,
272                                         struct timeval now,
273                                         void *private_data)
274 {
275         struct winbindd_domain *domain =
276                 (struct winbindd_domain *)private_data;
277
278         DEBUG(10,("check_domain_online_handler: called for domain "
279                   "%s (online = %s)\n", domain->name, 
280                   domain->online ? "True" : "False" ));
281
282         TALLOC_FREE(domain->check_online_event);
283
284         /* Are we still in "startup" mode ? */
285
286         if (domain->startup && (now.tv_sec > domain->startup_time + 30)) {
287                 /* No longer in "startup" mode. */
288                 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
289                         domain->name ));
290                 domain->startup = False;
291         }
292
293         /* We've been told to stay offline, so stay
294            that way. */
295
296         if (get_global_winbindd_state_offline()) {
297                 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
298                         domain->name ));
299                 return;
300         }
301
302         /* Fork a child to test if it can contact a DC. 
303            If it can then send ourselves a message to
304            cause a reconnect. */
305
306         fork_child_dc_connect(domain);
307 }
308
309 /****************************************************************
310  If we're still offline setup the timeout check.
311 ****************************************************************/
312
313 static void calc_new_online_timeout_check(struct winbindd_domain *domain)
314 {
315         int wbr = lp_winbind_reconnect_delay();
316
317         if (domain->startup) {
318                 domain->check_online_timeout = 10;
319         } else if (domain->check_online_timeout < wbr) {
320                 domain->check_online_timeout = wbr;
321         }
322 }
323
324 /****************************************************************
325  Set domain offline and also add handler to put us back online
326  if we detect a DC.
327 ****************************************************************/
328
329 void set_domain_offline(struct winbindd_domain *domain)
330 {
331         DEBUG(10,("set_domain_offline: called for domain %s\n",
332                 domain->name ));
333
334         TALLOC_FREE(domain->check_online_event);
335
336         if (domain->internal) {
337                 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
338                         domain->name ));
339                 return;
340         }
341
342         domain->online = False;
343
344         /* Offline domains are always initialized. They're
345            re-initialized when they go back online. */
346
347         domain->initialized = True;
348
349         /* We only add the timeout handler that checks and
350            allows us to go back online when we've not
351            been told to remain offline. */
352
353         if (get_global_winbindd_state_offline()) {
354                 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
355                         domain->name ));
356                 return;
357         }
358
359         /* If we're in startup mode, check again in 10 seconds, not in
360            lp_winbind_reconnect_delay() seconds (which is 30 seconds by default). */
361
362         calc_new_online_timeout_check(domain);
363
364         domain->check_online_event = event_add_timed(winbind_event_context(),
365                                                 NULL,
366                                                 timeval_current_ofs(domain->check_online_timeout,0),
367                                                 check_domain_online_handler,
368                                                 domain);
369
370         /* The above *has* to succeed for winbindd to work. */
371         if (!domain->check_online_event) {
372                 smb_panic("set_domain_offline: failed to add online handler");
373         }
374
375         DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
376                 domain->name ));
377
378         /* Send an offline message to the idmap child when our
379            primary domain goes offline */
380
381         if ( domain->primary ) {
382                 struct winbindd_child *idmap = idmap_child();
383
384                 if ( idmap->pid != 0 ) {
385                         messaging_send_buf(winbind_messaging_context(),
386                                            pid_to_procid(idmap->pid), 
387                                            MSG_WINBIND_OFFLINE, 
388                                            (uint8 *)domain->name, 
389                                            strlen(domain->name)+1);
390                 }                       
391         }
392
393         return; 
394 }
395
396 /****************************************************************
397  Set domain online - if allowed.
398 ****************************************************************/
399
400 static void set_domain_online(struct winbindd_domain *domain)
401 {
402         DEBUG(10,("set_domain_online: called for domain %s\n",
403                 domain->name ));
404
405         if (domain->internal) {
406                 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
407                         domain->name ));
408                 return;
409         }
410
411         if (get_global_winbindd_state_offline()) {
412                 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
413                         domain->name ));
414                 return;
415         }
416
417         winbindd_set_locator_kdc_envs(domain);
418
419         /* If we are waiting to get a krb5 ticket, trigger immediately. */
420         ccache_regain_all_now();
421
422         /* Ok, we're out of any startup mode now... */
423         domain->startup = False;
424
425         if (domain->online == False) {
426                 /* We were offline - now we're online. We default to
427                    using the MS-RPC backend if we started offline,
428                    and if we're going online for the first time we
429                    should really re-initialize the backends and the
430                    checks to see if we're talking to an AD or NT domain.
431                 */
432
433                 domain->initialized = False;
434
435                 /* 'reconnect_methods' is the MS-RPC backend. */
436                 if (domain->backend == &reconnect_methods) {
437                         domain->backend = NULL;
438                 }
439         }
440
441         /* Ensure we have no online timeout checks. */
442         domain->check_online_timeout = 0;
443         TALLOC_FREE(domain->check_online_event);
444
445         /* Ensure we ignore any pending child messages. */
446         messaging_deregister(winbind_messaging_context(),
447                              MSG_WINBIND_TRY_TO_GO_ONLINE, NULL);
448         messaging_deregister(winbind_messaging_context(),
449                              MSG_WINBIND_FAILED_TO_GO_ONLINE, NULL);
450
451         domain->online = True;
452
453         /* Send an online message to the idmap child when our
454            primary domain comes online */
455
456         if ( domain->primary ) {
457                 struct winbindd_child *idmap = idmap_child();
458
459                 if ( idmap->pid != 0 ) {
460                         messaging_send_buf(winbind_messaging_context(),
461                                            pid_to_procid(idmap->pid), 
462                                            MSG_WINBIND_ONLINE, 
463                                            (uint8 *)domain->name, 
464                                            strlen(domain->name)+1);
465                 }                       
466         }
467
468         return; 
469 }
470
471 /****************************************************************
472  Requested to set a domain online.
473 ****************************************************************/
474
475 void set_domain_online_request(struct winbindd_domain *domain)
476 {
477         struct timeval tev;
478
479         DEBUG(10,("set_domain_online_request: called for domain %s\n",
480                 domain->name ));
481
482         if (get_global_winbindd_state_offline()) {
483                 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
484                         domain->name ));
485                 return;
486         }
487
488         if (domain->internal) {
489                 DEBUG(10, ("set_domain_online_request: Internal domains are "
490                            "always online\n"));
491                 return;
492         }
493
494         /* We've been told it's safe to go online and
495            try and connect to a DC. But I don't believe it
496            because network manager seems to lie.
497            Wait at least 5 seconds. Heuristics suck... */
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         if (!domain->check_online_event) {
509                 /* If we've come from being globally offline we
510                    don't have a check online event handler set.
511                    We need to add one now we're trying to go
512                    back online. */
513
514                 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
515                         domain->name ));
516         }
517
518         TALLOC_FREE(domain->check_online_event);
519
520         domain->check_online_event = event_add_timed(winbind_event_context(),
521                                                      NULL,
522                                                      tev,
523                                                      check_domain_online_handler,
524                                                      domain);
525
526         /* The above *has* to succeed for winbindd to work. */
527         if (!domain->check_online_event) {
528                 smb_panic("set_domain_online_request: failed to add online handler");
529         }
530 }
531
532 /****************************************************************
533  Add -ve connection cache entries for domain and realm.
534 ****************************************************************/
535
536 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
537                                         const char *server,
538                                         NTSTATUS result)
539 {
540         add_failed_connection_entry(domain->name, server, result);
541         /* If this was the saf name for the last thing we talked to,
542            remove it. */
543         saf_delete(domain->name);
544         if (*domain->alt_name) {
545                 add_failed_connection_entry(domain->alt_name, server, result);
546                 saf_delete(domain->alt_name);
547         }
548         winbindd_unset_locator_kdc_env(domain);
549 }
550
551 /* Choose between anonymous or authenticated connections.  We need to use
552    an authenticated connection if DCs have the RestrictAnonymous registry
553    entry set > 0, or the "Additional restrictions for anonymous
554    connections" set in the win2k Local Security Policy. 
555
556    Caller to free() result in domain, username, password
557 */
558
559 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
560 {
561         *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
562         *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
563         *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
564
565         if (*username && **username) {
566
567                 if (!*domain || !**domain)
568                         *domain = smb_xstrdup(lp_workgroup());
569
570                 if (!*password || !**password)
571                         *password = smb_xstrdup("");
572
573                 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n", 
574                           *domain, *username));
575
576         } else {
577                 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
578                 *username = smb_xstrdup("");
579                 *domain = smb_xstrdup("");
580                 *password = smb_xstrdup("");
581         }
582 }
583
584 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
585                                      fstring dcname,
586                                      struct sockaddr_storage *dc_ss)
587 {
588         struct winbindd_domain *our_domain = NULL;
589         struct rpc_pipe_client *netlogon_pipe = NULL;
590         NTSTATUS result;
591         WERROR werr;
592         TALLOC_CTX *mem_ctx;
593         unsigned int orig_timeout;
594         const char *tmp = NULL;
595         const char *p;
596
597         /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
598          * moment.... */
599
600         if (IS_DC) {
601                 return False;
602         }
603
604         if (domain->primary) {
605                 return False;
606         }
607
608         our_domain = find_our_domain();
609
610         if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
611                 return False;
612         }
613
614         result = cm_connect_netlogon(our_domain, &netlogon_pipe);
615         if (!NT_STATUS_IS_OK(result)) {
616                 talloc_destroy(mem_ctx);
617                 return False;
618         }
619
620         /* This call can take a long time - allow the server to time out.
621            35 seconds should do it. */
622
623         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
624
625         if (our_domain->active_directory) {
626                 struct netr_DsRGetDCNameInfo *domain_info = NULL;
627
628                 result = rpccli_netr_DsRGetDCName(netlogon_pipe,
629                                                   mem_ctx,
630                                                   our_domain->dcname,
631                                                   domain->name,
632                                                   NULL,
633                                                   NULL,
634                                                   DS_RETURN_DNS_NAME,
635                                                   &domain_info,
636                                                   &werr);
637                 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
638                         tmp = talloc_strdup(
639                                 mem_ctx, domain_info->dc_unc);
640                         if (tmp == NULL) {
641                                 DEBUG(0, ("talloc_strdup failed\n"));
642                                 talloc_destroy(mem_ctx);
643                                 return false;
644                         }
645                         if (strlen(domain->alt_name) == 0) {
646                                 fstrcpy(domain->alt_name,
647                                         domain_info->domain_name);
648                         }
649                         if (strlen(domain->forest_name) == 0) {
650                                 fstrcpy(domain->forest_name,
651                                         domain_info->forest_name);
652                         }
653                 }
654         } else {
655                 result = rpccli_netr_GetAnyDCName(netlogon_pipe, mem_ctx,
656                                                   our_domain->dcname,
657                                                   domain->name,
658                                                   &tmp,
659                                                   &werr);
660         }
661
662         /* And restore our original timeout. */
663         rpccli_set_timeout(netlogon_pipe, orig_timeout);
664
665         if (!NT_STATUS_IS_OK(result)) {
666                 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
667                         nt_errstr(result)));
668                 talloc_destroy(mem_ctx);
669                 return false;
670         }
671
672         if (!W_ERROR_IS_OK(werr)) {
673                 DEBUG(10,("rpccli_netr_GetAnyDCName failed: %s\n",
674                            win_errstr(werr)));
675                 talloc_destroy(mem_ctx);
676                 return false;
677         }
678
679         /* rpccli_netr_GetAnyDCName gives us a name with \\ */
680         p = strip_hostname(tmp);
681
682         fstrcpy(dcname, p);
683
684         talloc_destroy(mem_ctx);
685
686         DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname));
687
688         if (!resolve_name(dcname, dc_ss, 0x20, true)) {
689                 return False;
690         }
691
692         return True;
693 }
694
695 /**
696  * Helper function to assemble trust password and account name
697  */
698 static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
699                                 char **machine_password,
700                                 char **machine_account,
701                                 char **machine_krb5_principal)
702 {
703         const char *account_name;
704         const char *name = NULL;
705
706         /* If we are a DC and this is not our own domain */
707
708         if (IS_DC) {
709                 name = domain->name;
710         } else {
711                 struct winbindd_domain *our_domain = find_our_domain();
712
713                 if (!our_domain)
714                         return NT_STATUS_INVALID_SERVER_STATE;          
715
716                 name = our_domain->name;                
717         }       
718
719         if (!get_trust_pw_clear(name, machine_password,
720                                 &account_name, NULL))
721         {
722                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
723         }
724
725         if ((machine_account != NULL) &&
726             (asprintf(machine_account, "%s$", account_name) == -1))
727         {
728                 return NT_STATUS_NO_MEMORY;
729         }
730
731         /* For now assume our machine account only exists in our domain */
732
733         if (machine_krb5_principal != NULL)
734         {
735                 struct winbindd_domain *our_domain = find_our_domain();
736
737                 if (!our_domain) {
738                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;                       
739                 }
740
741                 if (asprintf(machine_krb5_principal, "%s$@%s",
742                              account_name, our_domain->alt_name) == -1)
743                 {
744                         return NT_STATUS_NO_MEMORY;
745                 }
746
747                 strupper_m(*machine_krb5_principal);
748         }
749
750         return NT_STATUS_OK;
751 }
752
753 /************************************************************************
754  Given a fd with a just-connected TCP connection to a DC, open a connection
755  to the pipe.
756 ************************************************************************/
757
758 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
759                                       const int sockfd,
760                                       const char *controller,
761                                       struct cli_state **cli,
762                                       bool *retry)
763 {
764         char *machine_password = NULL;
765         char *machine_krb5_principal = NULL;
766         char *machine_account = NULL;
767         char *ipc_username = NULL;
768         char *ipc_domain = NULL;
769         char *ipc_password = NULL;
770
771         struct named_mutex *mutex;
772
773         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
774
775         struct sockaddr peeraddr;
776         socklen_t peeraddr_len;
777
778         struct sockaddr_in *peeraddr_in =
779                 (struct sockaddr_in *)(void *)&peeraddr;
780
781         DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
782                 controller, domain->name ));
783
784         *retry = True;
785
786         mutex = grab_named_mutex(talloc_tos(), controller,
787                                  WINBIND_SERVER_MUTEX_WAIT_TIME);
788         if (mutex == NULL) {
789                 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
790                          controller));
791                 result = NT_STATUS_POSSIBLE_DEADLOCK;
792                 goto done;
793         }
794
795         if ((*cli = cli_initialise()) == NULL) {
796                 DEBUG(1, ("Could not cli_initialize\n"));
797                 result = NT_STATUS_NO_MEMORY;
798                 goto done;
799         }
800
801         (*cli)->timeout = 10000;        /* 10 seconds */
802         (*cli)->fd = sockfd;
803         fstrcpy((*cli)->desthost, controller);
804         (*cli)->use_kerberos = True;
805
806         peeraddr_len = sizeof(peeraddr);
807
808         if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
809             (peeraddr_len != sizeof(struct sockaddr_in)) ||
810             (peeraddr_in->sin_family != PF_INET))
811         {
812                 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
813                 result = NT_STATUS_UNSUCCESSFUL;
814                 goto done;
815         }
816
817         if (ntohs(peeraddr_in->sin_port) == 139) {
818                 struct nmb_name calling;
819                 struct nmb_name called;
820
821                 make_nmb_name(&calling, global_myname(), 0x0);
822                 make_nmb_name(&called, "*SMBSERVER", 0x20);
823
824                 if (!cli_session_request(*cli, &calling, &called)) {
825                         DEBUG(8, ("cli_session_request failed for %s\n",
826                                   controller));
827                         result = NT_STATUS_UNSUCCESSFUL;
828                         goto done;
829                 }
830         }
831
832         result = cli_negprot(*cli);
833
834         if (!NT_STATUS_IS_OK(result)) {
835                 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
836                 goto done;
837         }
838
839         if (!is_dc_trusted_domain_situation(domain->name) &&
840             (*cli)->protocol >= PROTOCOL_NT1 &&
841             (*cli)->capabilities & CAP_EXTENDED_SECURITY)
842         {
843                 ADS_STATUS ads_status;
844
845                 result = get_trust_creds(domain, &machine_password,
846                                          &machine_account,
847                                          &machine_krb5_principal);
848                 if (!NT_STATUS_IS_OK(result)) {
849                         goto anon_fallback;
850                 }
851
852                 if (lp_security() == SEC_ADS) {
853
854                         /* Try a krb5 session */
855
856                         (*cli)->use_kerberos = True;
857                         DEBUG(5, ("connecting to %s from %s with kerberos principal "
858                                   "[%s] and realm [%s]\n", controller, global_myname(),
859                                   machine_krb5_principal, domain->alt_name));
860
861                         winbindd_set_locator_kdc_envs(domain);
862
863                         ads_status = cli_session_setup_spnego(*cli,
864                                                               machine_krb5_principal, 
865                                                               machine_password,
866                                                               lp_workgroup(),
867                                                               domain->alt_name);
868
869                         if (!ADS_ERR_OK(ads_status)) {
870                                 DEBUG(4,("failed kerberos session setup with %s\n",
871                                          ads_errstr(ads_status)));
872                         }
873
874                         result = ads_ntstatus(ads_status);
875                         if (NT_STATUS_IS_OK(result)) {
876                                 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
877                                 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
878                                 if (!NT_STATUS_IS_OK(result)) {
879                                         goto done;
880                                 }
881                                 goto session_setup_done;
882                         }
883                 }
884
885                 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
886                 (*cli)->use_kerberos = False;
887
888                 DEBUG(5, ("connecting to %s from %s with username "
889                           "[%s]\\[%s]\n",  controller, global_myname(),
890                           lp_workgroup(), machine_account));
891
892                 ads_status = cli_session_setup_spnego(*cli,
893                                                       machine_account, 
894                                                       machine_password, 
895                                                       lp_workgroup(),
896                                                       NULL);
897                 if (!ADS_ERR_OK(ads_status)) {
898                         DEBUG(4, ("authenticated session setup failed with %s\n",
899                                 ads_errstr(ads_status)));
900                 }
901
902                 result = ads_ntstatus(ads_status);
903                 if (NT_STATUS_IS_OK(result)) {
904                         /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
905                         result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
906                         if (!NT_STATUS_IS_OK(result)) {
907                                 goto done;
908                         }
909                         goto session_setup_done;
910                 }
911         }
912
913         /* Fall back to non-kerberos session setup with auth_user */
914
915         (*cli)->use_kerberos = False;
916
917         cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
918
919         if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
920             (strlen(ipc_username) > 0)) {
921
922                 /* Only try authenticated if we have a username */
923
924                 DEBUG(5, ("connecting to %s from %s with username "
925                           "[%s]\\[%s]\n",  controller, global_myname(),
926                           ipc_domain, ipc_username));
927
928                 if (NT_STATUS_IS_OK(cli_session_setup(
929                                             *cli, ipc_username,
930                                             ipc_password, strlen(ipc_password)+1,
931                                             ipc_password, strlen(ipc_password)+1,
932                                             ipc_domain))) {
933                         /* Successful logon with given username. */
934                         result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
935                         if (!NT_STATUS_IS_OK(result)) {
936                                 goto done;
937                         }
938                         goto session_setup_done;
939                 } else {
940                         DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
941                                 ipc_domain, ipc_username ));
942                 }
943         }
944
945  anon_fallback:
946
947         /* Fall back to anonymous connection, this might fail later */
948         DEBUG(10,("cm_prepare_connection: falling back to anonymous "
949                 "connection for DC %s\n",
950                 controller ));
951
952         if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
953                                               NULL, 0, ""))) {
954                 DEBUG(5, ("Connected anonymously\n"));
955                 result = cli_init_creds(*cli, "", "", "");
956                 if (!NT_STATUS_IS_OK(result)) {
957                         goto done;
958                 }
959                 goto session_setup_done;
960         }
961
962         result = cli_nt_error(*cli);
963
964         if (NT_STATUS_IS_OK(result))
965                 result = NT_STATUS_UNSUCCESSFUL;
966
967         /* We can't session setup */
968
969         goto done;
970
971  session_setup_done:
972
973         /* cache the server name for later connections */
974
975         saf_store( domain->name, (*cli)->desthost );
976         if (domain->alt_name && (*cli)->use_kerberos) {
977                 saf_store( domain->alt_name, (*cli)->desthost );
978         }
979
980         winbindd_set_locator_kdc_envs(domain);
981
982         result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
983
984         if (!NT_STATUS_IS_OK(result)) {
985                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
986                 goto done;
987         }
988
989         TALLOC_FREE(mutex);
990         *retry = False;
991
992         /* set the domain if empty; needed for schannel connections */
993         if ( !(*cli)->domain[0] ) {
994                 result = cli_set_domain((*cli), domain->name);
995                 if (!NT_STATUS_IS_OK(result)) {
996                         return result;
997                 }
998         }
999
1000         result = NT_STATUS_OK;
1001
1002  done:
1003         TALLOC_FREE(mutex);
1004         SAFE_FREE(machine_account);
1005         SAFE_FREE(machine_password);
1006         SAFE_FREE(machine_krb5_principal);
1007         SAFE_FREE(ipc_username);
1008         SAFE_FREE(ipc_domain);
1009         SAFE_FREE(ipc_password);
1010
1011         if (!NT_STATUS_IS_OK(result)) {
1012                 winbind_add_failed_connection_entry(domain, controller, result);
1013                 if ((*cli) != NULL) {
1014                         cli_shutdown(*cli);
1015                         *cli = NULL;
1016                 }
1017         }
1018
1019         return result;
1020 }
1021
1022 /*******************************************************************
1023  Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1024  array.
1025
1026  Keeps the list unique by not adding duplicate entries.
1027
1028  @param[in] mem_ctx talloc memory context to allocate from
1029  @param[in] domain_name domain of the DC
1030  @param[in] dcname name of the DC to add to the list
1031  @param[in] pss Internet address and port pair to add to the list
1032  @param[in,out] dcs array of dc_name_ip structures to add to
1033  @param[in,out] num_dcs number of dcs returned in the dcs array
1034  @return true if the list was added to, false otherwise
1035 *******************************************************************/
1036
1037 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1038                               const char *dcname, struct sockaddr_storage *pss,
1039                               struct dc_name_ip **dcs, int *num)
1040 {
1041         int i = 0;
1042
1043         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1044                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1045                 return False;
1046         }
1047
1048         /* Make sure there's no duplicates in the list */
1049         for (i=0; i<*num; i++)
1050                 if (sockaddr_equal(
1051                             (struct sockaddr *)(void *)&(*dcs)[i].ss,
1052                             (struct sockaddr *)(void *)pss))
1053                         return False;
1054
1055         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1056
1057         if (*dcs == NULL)
1058                 return False;
1059
1060         fstrcpy((*dcs)[*num].name, dcname);
1061         (*dcs)[*num].ss = *pss;
1062         *num += 1;
1063         return True;
1064 }
1065
1066 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1067                                   struct sockaddr_storage *pss, uint16 port,
1068                                   struct sockaddr_storage **addrs, int *num)
1069 {
1070         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1071
1072         if (*addrs == NULL) {
1073                 *num = 0;
1074                 return False;
1075         }
1076
1077         (*addrs)[*num] = *pss;
1078         set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1079
1080         *num += 1;
1081         return True;
1082 }
1083
1084 /*******************************************************************
1085  convert an ip to a name
1086 *******************************************************************/
1087
1088 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1089                 const struct winbindd_domain *domain,
1090                 struct sockaddr_storage *pss,
1091                 fstring name )
1092 {
1093         struct ip_service ip_list;
1094         uint32_t nt_version = NETLOGON_NT_VERSION_1;
1095
1096         ip_list.ss = *pss;
1097         ip_list.port = 0;
1098
1099 #ifdef WITH_ADS
1100         /* For active directory servers, try to get the ldap server name.
1101            None of these failures should be considered critical for now */
1102
1103         if (lp_security() == SEC_ADS) {
1104                 ADS_STRUCT *ads;
1105                 ADS_STATUS ads_status;
1106                 char addr[INET6_ADDRSTRLEN];
1107
1108                 print_sockaddr(addr, sizeof(addr), pss);
1109
1110                 ads = ads_init(domain->alt_name, domain->name, addr);
1111                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1112
1113                 ads_status = ads_connect(ads);
1114                 if (ADS_ERR_OK(ads_status)) {
1115                         /* We got a cldap packet. */
1116                         fstrcpy(name, ads->config.ldap_server_name);
1117                         namecache_store(name, 0x20, 1, &ip_list);
1118
1119                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1120
1121                         if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1122                                 if (ads_closest_dc(ads)) {
1123                                         char *sitename = sitename_fetch(ads->config.realm);
1124
1125                                         /* We're going to use this KDC for this realm/domain.
1126                                            If we are using sites, then force the krb5 libs
1127                                            to use this KDC. */
1128
1129                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1130                                                                         domain->name,
1131                                                                         sitename,
1132                                                                         pss);
1133
1134                                         SAFE_FREE(sitename);
1135                                 } else {
1136                                         /* use an off site KDC */
1137                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1138                                                                         domain->name,
1139                                                                         NULL,
1140                                                                         pss);
1141                                 }
1142                                 winbindd_set_locator_kdc_envs(domain);
1143
1144                                 /* Ensure we contact this DC also. */
1145                                 saf_store( domain->name, name);
1146                                 saf_store( domain->alt_name, name);
1147                         }
1148
1149                         ads_destroy( &ads );
1150                         return True;
1151                 }
1152
1153                 ads_destroy( &ads );
1154         }
1155 #endif
1156
1157         /* try GETDC requests next */
1158
1159         if (send_getdc_request(mem_ctx, winbind_messaging_context(),
1160                                pss, domain->name, &domain->sid,
1161                                nt_version)) {
1162                 const char *dc_name = NULL;
1163                 int i;
1164                 smb_msleep(100);
1165                 for (i=0; i<5; i++) {
1166                         if (receive_getdc_response(mem_ctx, pss, domain->name,
1167                                                    &nt_version,
1168                                                    &dc_name, NULL)) {
1169                                 fstrcpy(name, dc_name);
1170                                 namecache_store(name, 0x20, 1, &ip_list);
1171                                 return True;
1172                         }
1173                         smb_msleep(500);
1174                 }
1175         }
1176
1177         /* try node status request */
1178
1179         if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1180                 namecache_store(name, 0x20, 1, &ip_list);
1181                 return True;
1182         }
1183         return False;
1184 }
1185
1186 /*******************************************************************
1187  Retrieve a list of IP addresses for domain controllers.
1188
1189  The array is sorted in the preferred connection order.
1190
1191  @param[in] mem_ctx talloc memory context to allocate from
1192  @param[in] domain domain to retrieve DCs for
1193  @param[out] dcs array of dcs that will be returned
1194  @param[out] num_dcs number of dcs returned in the dcs array
1195  @return always true
1196 *******************************************************************/
1197
1198 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1199                     struct dc_name_ip **dcs, int *num_dcs)
1200 {
1201         fstring dcname;
1202         struct  sockaddr_storage ss;
1203         struct  ip_service *ip_list = NULL;
1204         int     iplist_size = 0;
1205         int     i;
1206         bool    is_our_domain;
1207         enum security_types sec = (enum security_types)lp_security();
1208
1209         is_our_domain = strequal(domain->name, lp_workgroup());
1210
1211         /* If not our domain, get the preferred DC, by asking our primary DC */
1212         if ( !is_our_domain
1213                 && get_dc_name_via_netlogon(domain, dcname, &ss)
1214                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1215                        num_dcs) )
1216         {
1217                 char addr[INET6_ADDRSTRLEN];
1218                 print_sockaddr(addr, sizeof(addr), &ss);
1219                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1220                            dcname, addr));
1221                 return True;
1222         }
1223
1224         if (sec == SEC_ADS) {
1225                 char *sitename = NULL;
1226
1227                 /* We need to make sure we know the local site before
1228                    doing any DNS queries, as this will restrict the
1229                    get_sorted_dc_list() call below to only fetching
1230                    DNS records for the correct site. */
1231
1232                 /* Find any DC to get the site record.
1233                    We deliberately don't care about the
1234                    return here. */
1235
1236                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1237
1238                 sitename = sitename_fetch(domain->alt_name);
1239                 if (sitename) {
1240
1241                         /* Do the site-specific AD dns lookup first. */
1242                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1243                                &iplist_size, True);
1244
1245                         /* Add ips to the DC array.  We don't look up the name
1246                            of the DC in this function, but we fill in the char*
1247                            of the ip now to make the failed connection cache
1248                            work */
1249                         for ( i=0; i<iplist_size; i++ ) {
1250                                 char addr[INET6_ADDRSTRLEN];
1251                                 print_sockaddr(addr, sizeof(addr),
1252                                                 &ip_list[i].ss);
1253                                 add_one_dc_unique(mem_ctx,
1254                                                 domain->name,
1255                                                 addr,
1256                                                 &ip_list[i].ss,
1257                                                 dcs,
1258                                                 num_dcs);
1259                         }
1260
1261                         SAFE_FREE(ip_list);
1262                         SAFE_FREE(sitename);
1263                         iplist_size = 0;
1264                 }
1265
1266                 /* Now we add DCs from the main AD DNS lookup. */
1267                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1268                         &iplist_size, True);
1269
1270                 for ( i=0; i<iplist_size; i++ ) {
1271                         char addr[INET6_ADDRSTRLEN];
1272                         print_sockaddr(addr, sizeof(addr),
1273                                         &ip_list[i].ss);
1274                         add_one_dc_unique(mem_ctx,
1275                                         domain->name,
1276                                         addr,
1277                                         &ip_list[i].ss,
1278                                         dcs,
1279                                         num_dcs);
1280                 }
1281
1282                 SAFE_FREE(ip_list);
1283                 iplist_size = 0;
1284         }
1285
1286         /* Try standard netbios queries if no ADS */
1287         if (*num_dcs == 0) {
1288                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1289                        False);
1290
1291                 for ( i=0; i<iplist_size; i++ ) {
1292                         char addr[INET6_ADDRSTRLEN];
1293                         print_sockaddr(addr, sizeof(addr),
1294                                         &ip_list[i].ss);
1295                         add_one_dc_unique(mem_ctx,
1296                                         domain->name,
1297                                         addr,
1298                                         &ip_list[i].ss,
1299                                         dcs,
1300                                         num_dcs);
1301                 }
1302
1303                 SAFE_FREE(ip_list);
1304                 iplist_size = 0;
1305         }
1306
1307         return True;
1308 }
1309
1310 /*******************************************************************
1311  Find and make a connection to a DC in the given domain.
1312
1313  @param[in] mem_ctx talloc memory context to allocate from
1314  @param[in] domain domain to find a dc in
1315  @param[out] dcname NetBIOS or FQDN of DC that's connected to
1316  @param[out] pss DC Internet address and port
1317  @param[out] fd fd of the open socket connected to the newly found dc
1318  @return true when a DC connection is made, false otherwise
1319 *******************************************************************/
1320
1321 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1322                         struct winbindd_domain *domain,
1323                         fstring dcname, struct sockaddr_storage *pss, int *fd)
1324 {
1325         struct dc_name_ip *dcs = NULL;
1326         int num_dcs = 0;
1327
1328         const char **dcnames = NULL;
1329         int num_dcnames = 0;
1330
1331         struct sockaddr_storage *addrs = NULL;
1332         int num_addrs = 0;
1333
1334         int i, fd_index;
1335
1336         *fd = -1;
1337
1338  again:
1339         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1340                 return False;
1341
1342         for (i=0; i<num_dcs; i++) {
1343
1344                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1345                                     &dcnames, &num_dcnames)) {
1346                         return False;
1347                 }
1348                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1349                                       &addrs, &num_addrs)) {
1350                         return False;
1351                 }
1352
1353                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1354                                     &dcnames, &num_dcnames)) {
1355                         return False;
1356                 }
1357                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
1358                                       &addrs, &num_addrs)) {
1359                         return False;
1360                 }
1361         }
1362
1363         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1364                 return False;
1365
1366         if ((addrs == NULL) || (dcnames == NULL))
1367                 return False;
1368
1369         /* 5 second timeout. */
1370         if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
1371                 for (i=0; i<num_dcs; i++) {
1372                         char ab[INET6_ADDRSTRLEN];
1373                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1374                         DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
1375                                 "domain %s address %s. Error was %s\n",
1376                                 domain->name, ab, strerror(errno) ));
1377                         winbind_add_failed_connection_entry(domain,
1378                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1379                 }
1380                 return False;
1381         }
1382
1383         *pss = addrs[fd_index];
1384
1385         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1386                 /* Ok, we've got a name for the DC */
1387                 fstrcpy(dcname, dcnames[fd_index]);
1388                 return True;
1389         }
1390
1391         /* Try to figure out the name */
1392         if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1393                 return True;
1394         }
1395
1396         /* We can not continue without the DC's name */
1397         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1398                                     NT_STATUS_UNSUCCESSFUL);
1399
1400         /* Throw away all arrays as we're doing this again. */
1401         TALLOC_FREE(dcs);
1402         num_dcs = 0;
1403
1404         TALLOC_FREE(dcnames);
1405         num_dcnames = 0;
1406
1407         TALLOC_FREE(addrs);
1408         num_addrs = 0;
1409
1410         close(*fd);
1411         *fd = -1;
1412
1413         goto again;
1414 }
1415
1416 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1417                                    struct winbindd_cm_conn *new_conn)
1418 {
1419         TALLOC_CTX *mem_ctx;
1420         NTSTATUS result;
1421         char *saf_servername = saf_fetch( domain->name );
1422         int retries;
1423
1424         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1425                 SAFE_FREE(saf_servername);
1426                 set_domain_offline(domain);
1427                 return NT_STATUS_NO_MEMORY;
1428         }
1429
1430         /* we have to check the server affinity cache here since 
1431            later we selecte a DC based on response time and not preference */
1432
1433         /* Check the negative connection cache
1434            before talking to it. It going down may have
1435            triggered the reconnection. */
1436
1437         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1438
1439                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1440                         saf_servername, domain->name ));
1441
1442                 /* convert an ip address to a name */
1443                 if (is_ipaddress( saf_servername ) ) {
1444                         fstring saf_name;
1445                         struct sockaddr_storage ss;
1446
1447                         if (!interpret_string_addr(&ss, saf_servername,
1448                                                 AI_NUMERICHOST)) {
1449                                 return NT_STATUS_UNSUCCESSFUL;
1450                         }
1451                         if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1452                                 fstrcpy( domain->dcname, saf_name );
1453                         } else {
1454                                 winbind_add_failed_connection_entry(
1455                                         domain, saf_servername,
1456                                         NT_STATUS_UNSUCCESSFUL);
1457                         }
1458                 } else {
1459                         fstrcpy( domain->dcname, saf_servername );
1460                 }
1461
1462                 SAFE_FREE( saf_servername );
1463         }
1464
1465         for (retries = 0; retries < 3; retries++) {
1466                 int fd = -1;
1467                 bool retry = False;
1468
1469                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1470
1471                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1472                         domain->dcname, domain->name ));
1473
1474                 if (*domain->dcname 
1475                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1476                         && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1477                 {
1478                         struct sockaddr_storage *addrs = NULL;
1479                         int num_addrs = 0;
1480                         int dummy = 0;
1481
1482                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
1483                                 set_domain_offline(domain);
1484                                 talloc_destroy(mem_ctx);
1485                                 return NT_STATUS_NO_MEMORY;
1486                         }
1487                         if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
1488                                 set_domain_offline(domain);
1489                                 talloc_destroy(mem_ctx);
1490                                 return NT_STATUS_NO_MEMORY;
1491                         }
1492
1493                         /* 5 second timeout. */
1494                         if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1495                                 fd = -1;
1496                         }
1497                 }
1498
1499                 if ((fd == -1) 
1500                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1501                 {
1502                         /* This is the one place where we will
1503                            set the global winbindd offline state
1504                            to true, if a "WINBINDD_OFFLINE" entry
1505                            is found in the winbindd cache. */
1506                         set_global_winbindd_state_offline();
1507                         break;
1508                 }
1509
1510                 new_conn->cli = NULL;
1511
1512                 result = cm_prepare_connection(domain, fd, domain->dcname,
1513                         &new_conn->cli, &retry);
1514
1515                 if (!retry)
1516                         break;
1517         }
1518
1519         if (NT_STATUS_IS_OK(result)) {
1520
1521                 winbindd_set_locator_kdc_envs(domain);
1522
1523                 if (domain->online == False) {
1524                         /* We're changing state from offline to online. */
1525                         set_global_winbindd_state_online();
1526                 }
1527                 set_domain_online(domain);
1528         } else {
1529                 /* Ensure we setup the retry handler. */
1530                 set_domain_offline(domain);
1531         }
1532
1533         talloc_destroy(mem_ctx);
1534         return result;
1535 }
1536
1537 /* Close down all open pipes on a connection. */
1538
1539 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1540 {
1541         /* We're closing down a possibly dead
1542            connection. Don't have impossibly long (10s) timeouts. */
1543
1544         if (conn->cli) {
1545                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1546         }
1547
1548         if (conn->samr_pipe != NULL) {
1549                 TALLOC_FREE(conn->samr_pipe);
1550                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1551                 if (conn->cli) {
1552                         cli_set_timeout(conn->cli, 500);
1553                 }
1554         }
1555
1556         if (conn->lsa_pipe != NULL) {
1557                 TALLOC_FREE(conn->lsa_pipe);
1558                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1559                 if (conn->cli) {
1560                         cli_set_timeout(conn->cli, 500);
1561                 }
1562         }
1563
1564         if (conn->lsa_pipe_tcp != NULL) {
1565                 TALLOC_FREE(conn->lsa_pipe_tcp);
1566                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1567                 if (conn->cli) {
1568                         cli_set_timeout(conn->cli, 500);
1569                 }
1570         }
1571
1572         if (conn->netlogon_pipe != NULL) {
1573                 TALLOC_FREE(conn->netlogon_pipe);
1574                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1575                 if (conn->cli) {
1576                         cli_set_timeout(conn->cli, 500);
1577                 }
1578         }
1579
1580         if (conn->cli) {
1581                 cli_shutdown(conn->cli);
1582         }
1583
1584         conn->cli = NULL;
1585 }
1586
1587 void close_conns_after_fork(void)
1588 {
1589         struct winbindd_domain *domain;
1590
1591         for (domain = domain_list(); domain; domain = domain->next) {
1592                 if (domain->conn.cli == NULL)
1593                         continue;
1594
1595                 if (domain->conn.cli->fd == -1)
1596                         continue;
1597
1598                 close(domain->conn.cli->fd);
1599                 domain->conn.cli->fd = -1;
1600         }
1601 }
1602
1603 static bool connection_ok(struct winbindd_domain *domain)
1604 {
1605         if (domain->conn.cli == NULL) {
1606                 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1607                           "cli!\n", domain->dcname, domain->name));
1608                 return False;
1609         }
1610
1611         if (!domain->conn.cli->initialised) {
1612                 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1613                           "initialised!\n", domain->dcname, domain->name));
1614                 return False;
1615         }
1616
1617         if (domain->conn.cli->fd == -1) {
1618                 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1619                           "never started (fd == -1)\n", 
1620                           domain->dcname, domain->name));
1621                 return False;
1622         }
1623
1624         if (domain->online == False) {
1625                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1626                 return False;
1627         }
1628
1629         return True;
1630 }
1631
1632 /* Initialize a new connection up to the RPC BIND.
1633    Bypass online status check so always does network calls. */
1634
1635 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1636 {
1637         NTSTATUS result;
1638
1639         /* Internal connections never use the network. */
1640         if (domain->internal) {
1641                 domain->initialized = True;
1642                 return NT_STATUS_OK;
1643         }
1644
1645         if (connection_ok(domain)) {
1646                 if (!domain->initialized) {
1647                         set_dc_type_and_flags(domain);
1648                 }
1649                 return NT_STATUS_OK;
1650         }
1651
1652         invalidate_cm_connection(&domain->conn);
1653
1654         result = cm_open_connection(domain, &domain->conn);
1655
1656         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1657                 set_dc_type_and_flags(domain);
1658         }
1659
1660         return result;
1661 }
1662
1663 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1664 {
1665         if (domain->initialized && !domain->online) {
1666                 /* We check for online status elsewhere. */
1667                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1668         }
1669
1670         return init_dc_connection_network(domain);
1671 }
1672
1673 /******************************************************************************
1674  Set the trust flags (direction and forest location) for a domain
1675 ******************************************************************************/
1676
1677 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1678 {
1679         struct winbindd_domain *our_domain;
1680         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1681         struct netr_DomainTrustList trusts;
1682         int i;
1683         uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1684                         NETR_TRUST_FLAG_OUTBOUND |
1685                         NETR_TRUST_FLAG_INBOUND);
1686         struct rpc_pipe_client *cli;
1687         TALLOC_CTX *mem_ctx = NULL;
1688
1689         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1690
1691         /* Our primary domain doesn't need to worry about trust flags.
1692            Force it to go through the network setup */
1693         if ( domain->primary ) {                
1694                 return False;           
1695         }
1696
1697         our_domain = find_our_domain();
1698
1699         if ( !connection_ok(our_domain) ) {
1700                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1701                 return False;
1702         }
1703
1704         /* This won't work unless our domain is AD */
1705
1706         if ( !our_domain->active_directory ) {
1707                 return False;
1708         }
1709
1710         /* Use DsEnumerateDomainTrusts to get us the trust direction
1711            and type */
1712
1713         result = cm_connect_netlogon(our_domain, &cli);
1714
1715         if (!NT_STATUS_IS_OK(result)) {
1716                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1717                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1718                           domain->name, nt_errstr(result)));
1719                 return False;
1720         }
1721
1722         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1723                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1724                 return False;
1725         }       
1726
1727         result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
1728                                                       cli->desthost,
1729                                                       flags,
1730                                                       &trusts,
1731                                                       NULL);
1732         if (!NT_STATUS_IS_OK(result)) {
1733                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1734                         "failed to query trusted domain list: %s\n",
1735                         nt_errstr(result)));
1736                 talloc_destroy(mem_ctx);
1737                 return false;
1738         }
1739
1740         /* Now find the domain name and get the flags */
1741
1742         for ( i=0; i<trusts.count; i++ ) {
1743                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1744                         domain->domain_flags          = trusts.array[i].trust_flags;
1745                         domain->domain_type           = trusts.array[i].trust_type;
1746                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
1747
1748                         if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1749                                 domain->active_directory = True;
1750
1751                         /* This flag is only set if the domain is *our* 
1752                            primary domain and the primary domain is in
1753                            native mode */
1754
1755                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1756
1757                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1758                                   "native mode.\n", domain->name, 
1759                                   domain->native_mode ? "" : "NOT "));
1760
1761                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1762                                  "running active directory.\n", domain->name, 
1763                                  domain->active_directory ? "" : "NOT "));
1764
1765
1766                         domain->initialized = True;
1767
1768                         if ( !winbindd_can_contact_domain( domain) )
1769                                 domain->internal = True;
1770
1771                         break;
1772                 }               
1773         }
1774
1775         talloc_destroy( mem_ctx );
1776
1777         return domain->initialized;     
1778 }
1779
1780 /******************************************************************************
1781  We can 'sense' certain things about the DC by it's replies to certain
1782  questions.
1783
1784  This tells us if this particular remote server is Active Directory, and if it
1785  is native mode.
1786 ******************************************************************************/
1787
1788 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1789 {
1790         NTSTATUS                result;
1791         WERROR werr;
1792         TALLOC_CTX              *mem_ctx = NULL;
1793         struct rpc_pipe_client  *cli = NULL;
1794         struct policy_handle pol;
1795         union dssetup_DsRoleInfo info;
1796         union lsa_PolicyInformation *lsa_info = NULL;
1797
1798         if (!connection_ok(domain)) {
1799                 return;
1800         }
1801
1802         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1803                               domain->name);
1804         if (!mem_ctx) {
1805                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1806                 return;
1807         }
1808
1809         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1810
1811         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1812                                           &ndr_table_dssetup.syntax_id,
1813                                           &cli);
1814
1815         if (!NT_STATUS_IS_OK(result)) {
1816                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1817                           "PI_DSSETUP on domain %s: (%s)\n",
1818                           domain->name, nt_errstr(result)));
1819
1820                 /* if this is just a non-AD domain we need to continue
1821                  * identifying so that we can in the end return with
1822                  * domain->initialized = True - gd */
1823
1824                 goto no_dssetup;
1825         }
1826
1827         result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
1828                                                                   DS_ROLE_BASIC_INFORMATION,
1829                                                                   &info,
1830                                                                   &werr);
1831         TALLOC_FREE(cli);
1832
1833         if (!NT_STATUS_IS_OK(result)) {
1834                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1835                           "on domain %s failed: (%s)\n",
1836                           domain->name, nt_errstr(result)));
1837
1838                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1839                  * every opcode on the DSSETUP pipe, continue with
1840                  * no_dssetup mode here as well to get domain->initialized
1841                  * set - gd */
1842
1843                 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
1844                         goto no_dssetup;
1845                 }
1846
1847                 TALLOC_FREE(mem_ctx);
1848                 return;
1849         }
1850
1851         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1852             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1853                 domain->native_mode = True;
1854         } else {
1855                 domain->native_mode = False;
1856         }
1857
1858 no_dssetup:
1859         result = cli_rpc_pipe_open_noauth(domain->conn.cli,
1860                                           &ndr_table_lsarpc.syntax_id, &cli);
1861
1862         if (!NT_STATUS_IS_OK(result)) {
1863                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1864                           "PI_LSARPC on domain %s: (%s)\n",
1865                           domain->name, nt_errstr(result)));
1866                 TALLOC_FREE(cli);
1867                 TALLOC_FREE(mem_ctx);
1868                 return;
1869         }
1870
1871         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
1872                                          SEC_FLAG_MAXIMUM_ALLOWED, &pol);
1873
1874         if (NT_STATUS_IS_OK(result)) {
1875                 /* This particular query is exactly what Win2k clients use 
1876                    to determine that the DC is active directory */
1877                 result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
1878                                                      &pol,
1879                                                      LSA_POLICY_INFO_DNS,
1880                                                      &lsa_info);
1881         }
1882
1883         if (NT_STATUS_IS_OK(result)) {
1884                 domain->active_directory = True;
1885
1886                 if (lsa_info->dns.name.string) {
1887                         fstrcpy(domain->name, lsa_info->dns.name.string);
1888                 }
1889
1890                 if (lsa_info->dns.dns_domain.string) {
1891                         fstrcpy(domain->alt_name,
1892                                 lsa_info->dns.dns_domain.string);
1893                 }
1894
1895                 /* See if we can set some domain trust flags about
1896                    ourself */
1897
1898                 if (lsa_info->dns.dns_forest.string) {
1899                         fstrcpy(domain->forest_name,
1900                                 lsa_info->dns.dns_forest.string);
1901
1902                         if (strequal(domain->forest_name, domain->alt_name)) {
1903                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
1904                         }
1905                 }
1906
1907                 if (lsa_info->dns.sid) {
1908                         sid_copy(&domain->sid, lsa_info->dns.sid);
1909                 }
1910         } else {
1911                 domain->active_directory = False;
1912
1913                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
1914                                                 SEC_FLAG_MAXIMUM_ALLOWED,
1915                                                 &pol);
1916
1917                 if (!NT_STATUS_IS_OK(result)) {
1918                         goto done;
1919                 }
1920
1921                 result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
1922                                                     &pol,
1923                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1924                                                     &lsa_info);
1925
1926                 if (NT_STATUS_IS_OK(result)) {
1927
1928                         if (lsa_info->account_domain.name.string) {
1929                                 fstrcpy(domain->name,
1930                                         lsa_info->account_domain.name.string);
1931                         }
1932
1933                         if (lsa_info->account_domain.sid) {
1934                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
1935                         }
1936                 }
1937         }
1938 done:
1939
1940         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
1941                   domain->name, domain->native_mode ? "" : "NOT "));
1942
1943         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
1944                   domain->name, domain->active_directory ? "" : "NOT "));
1945
1946         domain->can_do_ncacn_ip_tcp = domain->active_directory;
1947
1948         TALLOC_FREE(cli);
1949
1950         TALLOC_FREE(mem_ctx);
1951
1952         domain->initialized = True;
1953 }
1954
1955 /**********************************************************************
1956  Set the domain_flags (trust attributes, domain operating modes, etc... 
1957 ***********************************************************************/
1958
1959 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1960 {
1961         /* we always have to contact our primary domain */
1962
1963         if ( domain->primary ) {
1964                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
1965                           "primary domain\n"));
1966                 set_dc_type_and_flags_connect( domain );
1967                 return;         
1968         }
1969
1970         /* Use our DC to get the information if possible */
1971
1972         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
1973                 /* Otherwise, fallback to contacting the 
1974                    domain directly */
1975                 set_dc_type_and_flags_connect( domain );
1976         }
1977
1978         return;
1979 }
1980
1981
1982
1983 /**********************************************************************
1984 ***********************************************************************/
1985
1986 static bool cm_get_schannel_creds(struct winbindd_domain *domain,
1987                                    struct netlogon_creds_CredentialState **ppdc)
1988 {
1989         NTSTATUS result;
1990         struct rpc_pipe_client *netlogon_pipe;
1991
1992         if (lp_client_schannel() == False) {
1993                 return False;
1994         }
1995
1996         result = cm_connect_netlogon(domain, &netlogon_pipe);
1997         if (!NT_STATUS_IS_OK(result)) {
1998                 return False;
1999         }
2000
2001         /* Return a pointer to the struct netlogon_creds_CredentialState from the
2002            netlogon pipe. */
2003
2004         if (!domain->conn.netlogon_pipe->dc) {
2005                 return false;
2006         }
2007
2008         *ppdc = domain->conn.netlogon_pipe->dc;
2009         return True;
2010 }
2011
2012 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2013                         struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2014 {
2015         struct winbindd_cm_conn *conn;
2016         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2017         struct netlogon_creds_CredentialState *p_creds;
2018         char *machine_password = NULL;
2019         char *machine_account = NULL;
2020         char *domain_name = NULL;
2021
2022         result = init_dc_connection(domain);
2023         if (!NT_STATUS_IS_OK(result)) {
2024                 return result;
2025         }
2026
2027         conn = &domain->conn;
2028
2029         if (conn->samr_pipe != NULL) {
2030                 goto done;
2031         }
2032
2033
2034         /*
2035          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2036          * sign and sealed pipe using the machine account password by
2037          * preference. If we can't - try schannel, if that fails, try
2038          * anonymous.
2039          */
2040
2041         if ((conn->cli->user_name[0] == '\0') ||
2042             (conn->cli->domain[0] == '\0') || 
2043             (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2044         {
2045                 result = get_trust_creds(domain, &machine_password,
2046                                          &machine_account, NULL);
2047                 if (!NT_STATUS_IS_OK(result)) {
2048                         DEBUG(10, ("cm_connect_sam: No no user available for "
2049                                    "domain %s, trying schannel\n", conn->cli->domain));
2050                         goto schannel;
2051                 }
2052                 domain_name = domain->name;
2053         } else {
2054                 machine_password = SMB_STRDUP(conn->cli->password);
2055                 machine_account = SMB_STRDUP(conn->cli->user_name);
2056                 domain_name = conn->cli->domain;
2057         }
2058
2059         if (!machine_password || !machine_account) {
2060                 result = NT_STATUS_NO_MEMORY;
2061                 goto done;
2062         }
2063
2064         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2065            authenticated SAMR pipe with sign & seal. */
2066         result = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2067                                                   &ndr_table_samr.syntax_id,
2068                                                   NCACN_NP,
2069                                                   DCERPC_AUTH_LEVEL_PRIVACY,
2070                                                   domain_name,
2071                                                   machine_account,
2072                                                   machine_password,
2073                                                   &conn->samr_pipe);
2074
2075         if (!NT_STATUS_IS_OK(result)) {
2076                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2077                           "pipe for domain %s using NTLMSSP "
2078                           "authenticated pipe: user %s\\%s. Error was "
2079                           "%s\n", domain->name, domain_name,
2080                           machine_account, nt_errstr(result)));
2081                 goto schannel;
2082         }
2083
2084         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2085                   "domain %s using NTLMSSP authenticated "
2086                   "pipe: user %s\\%s\n", domain->name,
2087                   domain_name, machine_account));
2088
2089         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2090                                       conn->samr_pipe->desthost,
2091                                       SEC_FLAG_MAXIMUM_ALLOWED,
2092                                       &conn->sam_connect_handle);
2093         if (NT_STATUS_IS_OK(result)) {
2094                 goto open_domain;
2095         }
2096         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_Connect2 "
2097                   "failed for domain %s, error was %s. Trying schannel\n",
2098                   domain->name, nt_errstr(result) ));
2099         TALLOC_FREE(conn->samr_pipe);
2100
2101  schannel:
2102
2103         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2104
2105         if (!cm_get_schannel_creds(domain, &p_creds)) {
2106                 /* If this call fails - conn->cli can now be NULL ! */
2107                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2108                            "for domain %s, trying anon\n", domain->name));
2109                 goto anonymous;
2110         }
2111         result = cli_rpc_pipe_open_schannel_with_key
2112                 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2113                  DCERPC_AUTH_LEVEL_PRIVACY,
2114                  domain->name, &p_creds, &conn->samr_pipe);
2115
2116         if (!NT_STATUS_IS_OK(result)) {
2117                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2118                           "domain %s using schannel. Error was %s\n",
2119                           domain->name, nt_errstr(result) ));
2120                 goto anonymous;
2121         }
2122         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2123                   "schannel.\n", domain->name ));
2124
2125         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2126                                       conn->samr_pipe->desthost,
2127                                       SEC_FLAG_MAXIMUM_ALLOWED,
2128                                       &conn->sam_connect_handle);
2129         if (NT_STATUS_IS_OK(result)) {
2130                 goto open_domain;
2131         }
2132         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_Connect2 failed "
2133                   "for domain %s, error was %s. Trying anonymous\n",
2134                   domain->name, nt_errstr(result) ));
2135         TALLOC_FREE(conn->samr_pipe);
2136
2137  anonymous:
2138
2139         /* Finally fall back to anonymous. */
2140         result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2141                                           &conn->samr_pipe);
2142
2143         if (!NT_STATUS_IS_OK(result)) {
2144                 goto done;
2145         }
2146
2147         result = rpccli_samr_Connect2(conn->samr_pipe, mem_ctx,
2148                                       conn->samr_pipe->desthost,
2149                                       SEC_FLAG_MAXIMUM_ALLOWED,
2150                                       &conn->sam_connect_handle);
2151         if (!NT_STATUS_IS_OK(result)) {
2152                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2153                           "for domain %s Error was %s\n",
2154                           domain->name, nt_errstr(result) ));
2155                 goto done;
2156         }
2157
2158  open_domain:
2159         result = rpccli_samr_OpenDomain(conn->samr_pipe,
2160                                         mem_ctx,
2161                                         &conn->sam_connect_handle,
2162                                         SEC_FLAG_MAXIMUM_ALLOWED,
2163                                         &domain->sid,
2164                                         &conn->sam_domain_handle);
2165
2166  done:
2167
2168         if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
2169                 /*
2170                  * if we got access denied, we might just have no access rights
2171                  * to talk to the remote samr server server (e.g. when we are a
2172                  * PDC and we are connecting a w2k8 pdc via an interdomain
2173                  * trust). In that case do not invalidate the whole connection
2174                  * stack
2175                  */
2176                 TALLOC_FREE(conn->samr_pipe);
2177                 ZERO_STRUCT(conn->sam_domain_handle);
2178                 return result;
2179         } else if (!NT_STATUS_IS_OK(result)) {
2180                 invalidate_cm_connection(conn);
2181                 return result;
2182         }
2183
2184         *cli = conn->samr_pipe;
2185         *sam_handle = conn->sam_domain_handle;
2186         SAFE_FREE(machine_password);
2187         SAFE_FREE(machine_account);
2188         return result;
2189 }
2190
2191 /**********************************************************************
2192  open an schanneld ncacn_ip_tcp connection to LSA
2193 ***********************************************************************/
2194
2195 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2196                             TALLOC_CTX *mem_ctx,
2197                             struct rpc_pipe_client **cli)
2198 {
2199         struct winbindd_cm_conn *conn;
2200         NTSTATUS status;
2201
2202         DEBUG(10,("cm_connect_lsa_tcp\n"));
2203
2204         status = init_dc_connection(domain);
2205         if (!NT_STATUS_IS_OK(status)) {
2206                 return status;
2207         }
2208
2209         conn = &domain->conn;
2210
2211         if (conn->lsa_pipe_tcp &&
2212             conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2213             conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2214                 goto done;
2215         }
2216
2217         TALLOC_FREE(conn->lsa_pipe_tcp);
2218
2219         status = cli_rpc_pipe_open_schannel(conn->cli,
2220                                             &ndr_table_lsarpc.syntax_id,
2221                                             NCACN_IP_TCP,
2222                                             DCERPC_AUTH_LEVEL_PRIVACY,
2223                                             domain->name,
2224                                             &conn->lsa_pipe_tcp);
2225         if (!NT_STATUS_IS_OK(status)) {
2226                 DEBUG(10,("cli_rpc_pipe_open_schannel failed: %s\n",
2227                         nt_errstr(status)));
2228                 goto done;
2229         }
2230
2231  done:
2232         if (!NT_STATUS_IS_OK(status)) {
2233                 TALLOC_FREE(conn->lsa_pipe_tcp);
2234                 return status;
2235         }
2236
2237         *cli = conn->lsa_pipe_tcp;
2238
2239         return status;
2240 }
2241
2242 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2243                         struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2244 {
2245         struct winbindd_cm_conn *conn;
2246         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2247         struct netlogon_creds_CredentialState *p_creds;
2248
2249         result = init_dc_connection(domain);
2250         if (!NT_STATUS_IS_OK(result))
2251                 return result;
2252
2253         conn = &domain->conn;
2254
2255         if (conn->lsa_pipe != NULL) {
2256                 goto done;
2257         }
2258
2259         if ((conn->cli->user_name[0] == '\0') ||
2260             (conn->cli->domain[0] == '\0') || 
2261             (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2262                 DEBUG(10, ("cm_connect_lsa: No no user available for "
2263                            "domain %s, trying schannel\n", conn->cli->domain));
2264                 goto schannel;
2265         }
2266
2267         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2268          * authenticated LSA pipe with sign & seal. */
2269         result = cli_rpc_pipe_open_spnego_ntlmssp
2270                 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2271                  DCERPC_AUTH_LEVEL_PRIVACY,
2272                  conn->cli->domain, conn->cli->user_name, conn->cli->password,
2273                  &conn->lsa_pipe);
2274
2275         if (!NT_STATUS_IS_OK(result)) {
2276                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2277                           "domain %s using NTLMSSP authenticated pipe: user "
2278                           "%s\\%s. Error was %s. Trying schannel.\n",
2279                           domain->name, conn->cli->domain,
2280                           conn->cli->user_name, nt_errstr(result)));
2281                 goto schannel;
2282         }
2283
2284         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2285                   "NTLMSSP authenticated pipe: user %s\\%s\n",
2286                   domain->name, conn->cli->domain, conn->cli->user_name ));
2287
2288         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2289                                         SEC_FLAG_MAXIMUM_ALLOWED,
2290                                         &conn->lsa_policy);
2291         if (NT_STATUS_IS_OK(result)) {
2292                 goto done;
2293         }
2294
2295         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2296                   "schannel\n"));
2297
2298         TALLOC_FREE(conn->lsa_pipe);
2299
2300  schannel:
2301
2302         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2303
2304         if (!cm_get_schannel_creds(domain, &p_creds)) {
2305                 /* If this call fails - conn->cli can now be NULL ! */
2306                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2307                            "for domain %s, trying anon\n", domain->name));
2308                 goto anonymous;
2309         }
2310         result = cli_rpc_pipe_open_schannel_with_key
2311                 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2312                  DCERPC_AUTH_LEVEL_PRIVACY,
2313                  domain->name, &p_creds, &conn->lsa_pipe);
2314
2315         if (!NT_STATUS_IS_OK(result)) {
2316                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2317                           "domain %s using schannel. Error was %s\n",
2318                           domain->name, nt_errstr(result) ));
2319                 goto anonymous;
2320         }
2321         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2322                   "schannel.\n", domain->name ));
2323
2324         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2325                                         SEC_FLAG_MAXIMUM_ALLOWED,
2326                                         &conn->lsa_policy);
2327         if (NT_STATUS_IS_OK(result)) {
2328                 goto done;
2329         }
2330
2331         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2332                   "anonymous\n"));
2333
2334         TALLOC_FREE(conn->lsa_pipe);
2335
2336  anonymous:
2337
2338         result = cli_rpc_pipe_open_noauth(conn->cli,
2339                                           &ndr_table_lsarpc.syntax_id,
2340                                           &conn->lsa_pipe);
2341         if (!NT_STATUS_IS_OK(result)) {
2342                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2343                 goto done;
2344         }
2345
2346         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2347                                         SEC_FLAG_MAXIMUM_ALLOWED,
2348                                         &conn->lsa_policy);
2349  done:
2350         if (!NT_STATUS_IS_OK(result)) {
2351                 invalidate_cm_connection(conn);
2352                 return result;
2353         }
2354
2355         *cli = conn->lsa_pipe;
2356         *lsa_policy = conn->lsa_policy;
2357         return result;
2358 }
2359
2360 /****************************************************************************
2361  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2362  session key stored in conn->netlogon_pipe->dc->sess_key.
2363 ****************************************************************************/
2364
2365 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2366                              struct rpc_pipe_client **cli)
2367 {
2368         struct winbindd_cm_conn *conn;
2369         NTSTATUS result;
2370
2371         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2372         uint8  mach_pwd[16];
2373         uint32  sec_chan_type;
2374         const char *account_name;
2375         struct rpc_pipe_client *netlogon_pipe = NULL;
2376
2377         *cli = NULL;
2378
2379         result = init_dc_connection(domain);
2380         if (!NT_STATUS_IS_OK(result)) {
2381                 return result;
2382         }
2383
2384         conn = &domain->conn;
2385
2386         if (conn->netlogon_pipe != NULL) {
2387                 *cli = conn->netlogon_pipe;
2388                 return NT_STATUS_OK;
2389         }
2390
2391         result = cli_rpc_pipe_open_noauth(conn->cli,
2392                                           &ndr_table_netlogon.syntax_id,
2393                                           &netlogon_pipe);
2394         if (!NT_STATUS_IS_OK(result)) {
2395                 return result;
2396         }
2397
2398         if ((!IS_DC) && (!domain->primary)) {
2399                 /* Clear the schannel request bit and drop down */
2400                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2401                 goto no_schannel;
2402         }
2403
2404         if (lp_client_schannel() != False) {
2405                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2406         }
2407
2408         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2409                                &sec_chan_type))
2410         {
2411                 TALLOC_FREE(netlogon_pipe);
2412                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2413         }
2414
2415         result = rpccli_netlogon_setup_creds(
2416                  netlogon_pipe,
2417                  domain->dcname, /* server name. */
2418                  domain->name,   /* domain name */
2419                  global_myname(), /* client name */
2420                  account_name,   /* machine account */
2421                  mach_pwd,       /* machine password */
2422                  sec_chan_type,  /* from get_trust_pw */
2423                  &neg_flags);
2424
2425         if (!NT_STATUS_IS_OK(result)) {
2426                 TALLOC_FREE(netlogon_pipe);
2427                 return result;
2428         }
2429
2430         if ((lp_client_schannel() == True) &&
2431                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2432                 DEBUG(3, ("Server did not offer schannel\n"));
2433                 TALLOC_FREE(netlogon_pipe);
2434                 return NT_STATUS_ACCESS_DENIED;
2435         }
2436
2437  no_schannel:
2438         if ((lp_client_schannel() == False) ||
2439                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2440                 /*
2441                  * NetSamLogonEx only works for schannel
2442                  */
2443                 domain->can_do_samlogon_ex = False;
2444
2445                 /* We're done - just keep the existing connection to NETLOGON
2446                  * open */
2447                 conn->netlogon_pipe = netlogon_pipe;
2448                 *cli = conn->netlogon_pipe;
2449                 return NT_STATUS_OK;
2450         }
2451
2452         /* Using the credentials from the first pipe, open a signed and sealed
2453            second netlogon pipe. The session key is stored in the schannel
2454            part of the new pipe auth struct.
2455         */
2456
2457         result = cli_rpc_pipe_open_schannel_with_key(
2458                 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2459                 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2460                 &conn->netlogon_pipe);
2461
2462         /* We can now close the initial netlogon pipe. */
2463         TALLOC_FREE(netlogon_pipe);
2464
2465         if (!NT_STATUS_IS_OK(result)) {
2466                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2467                           "was %s\n", nt_errstr(result)));
2468
2469                 /* make sure we return something besides OK */
2470                 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
2471         }
2472
2473         /*
2474          * Try NetSamLogonEx for AD domains
2475          */
2476         domain->can_do_samlogon_ex = domain->active_directory;
2477
2478         *cli = conn->netlogon_pipe;
2479         return NT_STATUS_OK;
2480 }