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