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