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