s3-messages: only include messages.h where needed.
[vlendec/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 "librpc/gen_ndr/messaging.h"
73 #include "libsmb/clidgram.h"
74 #include "ads.h"
75 #include "secrets.h"
76 #include "../libcli/security/security.h"
77 #include "passdb.h"
78 #include "messages.h"
79
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         fstrcpy((*cli)->desthost, controller);
820         (*cli)->use_kerberos = True;
821
822         peeraddr_len = sizeof(peeraddr);
823
824         if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0)) {
825                 DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
826                         strerror(errno)));
827                 result = NT_STATUS_UNSUCCESSFUL;
828                 goto done;
829         }
830
831         if ((peeraddr_len != sizeof(struct sockaddr_in))
832 #ifdef HAVE_IPV6
833             && (peeraddr_len != sizeof(struct sockaddr_in6))
834 #endif
835             ) {
836                 DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
837                         peeraddr_len));
838                 result = NT_STATUS_UNSUCCESSFUL;
839                 goto done;
840         }
841
842         if ((peeraddr_in->sin_family != PF_INET)
843 #ifdef HAVE_IPV6
844             && (peeraddr_in->sin_family != PF_INET6)
845 #endif
846             ) {
847                 DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
848                         peeraddr_in->sin_family));
849                 result = NT_STATUS_UNSUCCESSFUL;
850                 goto done;
851         }
852
853         result = cli_negprot(*cli);
854
855         if (!NT_STATUS_IS_OK(result)) {
856                 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
857                 goto done;
858         }
859
860         if (!is_dc_trusted_domain_situation(domain->name) &&
861             (*cli)->protocol >= PROTOCOL_NT1 &&
862             (*cli)->capabilities & CAP_EXTENDED_SECURITY)
863         {
864                 ADS_STATUS ads_status;
865
866                 result = get_trust_creds(domain, &machine_password,
867                                          &machine_account,
868                                          &machine_krb5_principal);
869                 if (!NT_STATUS_IS_OK(result)) {
870                         goto anon_fallback;
871                 }
872
873                 if (lp_security() == SEC_ADS) {
874
875                         /* Try a krb5 session */
876
877                         (*cli)->use_kerberos = True;
878                         DEBUG(5, ("connecting to %s from %s with kerberos principal "
879                                   "[%s] and realm [%s]\n", controller, global_myname(),
880                                   machine_krb5_principal, domain->alt_name));
881
882                         winbindd_set_locator_kdc_envs(domain);
883
884                         ads_status = cli_session_setup_spnego(*cli,
885                                                               machine_krb5_principal, 
886                                                               machine_password,
887                                                               lp_workgroup(),
888                                                               domain->alt_name);
889
890                         if (!ADS_ERR_OK(ads_status)) {
891                                 DEBUG(4,("failed kerberos session setup with %s\n",
892                                          ads_errstr(ads_status)));
893                         }
894
895                         result = ads_ntstatus(ads_status);
896                         if (NT_STATUS_IS_OK(result)) {
897                                 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
898                                 result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
899                                 if (!NT_STATUS_IS_OK(result)) {
900                                         goto done;
901                                 }
902                                 goto session_setup_done;
903                         }
904                 }
905
906                 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
907                 (*cli)->use_kerberos = False;
908
909                 DEBUG(5, ("connecting to %s from %s with username "
910                           "[%s]\\[%s]\n",  controller, global_myname(),
911                           lp_workgroup(), machine_account));
912
913                 ads_status = cli_session_setup_spnego(*cli,
914                                                       machine_account, 
915                                                       machine_password, 
916                                                       lp_workgroup(),
917                                                       NULL);
918                 if (!ADS_ERR_OK(ads_status)) {
919                         DEBUG(4, ("authenticated session setup failed with %s\n",
920                                 ads_errstr(ads_status)));
921                 }
922
923                 result = ads_ntstatus(ads_status);
924                 if (NT_STATUS_IS_OK(result)) {
925                         /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
926                         result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
927                         if (!NT_STATUS_IS_OK(result)) {
928                                 goto done;
929                         }
930                         goto session_setup_done;
931                 }
932         }
933
934         /* Fall back to non-kerberos session setup with auth_user */
935
936         (*cli)->use_kerberos = False;
937
938         cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
939
940         if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
941             (strlen(ipc_username) > 0)) {
942
943                 /* Only try authenticated if we have a username */
944
945                 DEBUG(5, ("connecting to %s from %s with username "
946                           "[%s]\\[%s]\n",  controller, global_myname(),
947                           ipc_domain, ipc_username));
948
949                 if (NT_STATUS_IS_OK(cli_session_setup(
950                                             *cli, ipc_username,
951                                             ipc_password, strlen(ipc_password)+1,
952                                             ipc_password, strlen(ipc_password)+1,
953                                             ipc_domain))) {
954                         /* Successful logon with given username. */
955                         result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
956                         if (!NT_STATUS_IS_OK(result)) {
957                                 goto done;
958                         }
959                         goto session_setup_done;
960                 } else {
961                         DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
962                                 ipc_domain, ipc_username ));
963                 }
964         }
965
966  anon_fallback:
967
968         /* Fall back to anonymous connection, this might fail later */
969         DEBUG(10,("cm_prepare_connection: falling back to anonymous "
970                 "connection for DC %s\n",
971                 controller ));
972
973         if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
974                                               NULL, 0, ""))) {
975                 DEBUG(5, ("Connected anonymously\n"));
976                 result = cli_init_creds(*cli, "", "", "");
977                 if (!NT_STATUS_IS_OK(result)) {
978                         goto done;
979                 }
980                 goto session_setup_done;
981         }
982
983         result = cli_nt_error(*cli);
984
985         if (NT_STATUS_IS_OK(result))
986                 result = NT_STATUS_UNSUCCESSFUL;
987
988         /* We can't session setup */
989
990         goto done;
991
992  session_setup_done:
993
994         /* cache the server name for later connections */
995
996         saf_store( domain->name, (*cli)->desthost );
997         if (domain->alt_name && (*cli)->use_kerberos) {
998                 saf_store( domain->alt_name, (*cli)->desthost );
999         }
1000
1001         winbindd_set_locator_kdc_envs(domain);
1002
1003         result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
1004
1005         if (!NT_STATUS_IS_OK(result)) {
1006                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1007                 goto done;
1008         }
1009
1010         TALLOC_FREE(mutex);
1011         *retry = False;
1012
1013         /* set the domain if empty; needed for schannel connections */
1014         if ( !(*cli)->domain[0] ) {
1015                 result = cli_set_domain((*cli), domain->name);
1016                 if (!NT_STATUS_IS_OK(result)) {
1017                         return result;
1018                 }
1019         }
1020
1021         result = NT_STATUS_OK;
1022
1023  done:
1024         TALLOC_FREE(mutex);
1025         SAFE_FREE(machine_account);
1026         SAFE_FREE(machine_password);
1027         SAFE_FREE(machine_krb5_principal);
1028         SAFE_FREE(ipc_username);
1029         SAFE_FREE(ipc_domain);
1030         SAFE_FREE(ipc_password);
1031
1032         if (!NT_STATUS_IS_OK(result)) {
1033                 winbind_add_failed_connection_entry(domain, controller, result);
1034                 if ((*cli) != NULL) {
1035                         cli_shutdown(*cli);
1036                         *cli = NULL;
1037                 }
1038         }
1039
1040         return result;
1041 }
1042
1043 /*******************************************************************
1044  Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1045  array.
1046
1047  Keeps the list unique by not adding duplicate entries.
1048
1049  @param[in] mem_ctx talloc memory context to allocate from
1050  @param[in] domain_name domain of the DC
1051  @param[in] dcname name of the DC to add to the list
1052  @param[in] pss Internet address and port pair to add to the list
1053  @param[in,out] dcs array of dc_name_ip structures to add to
1054  @param[in,out] num_dcs number of dcs returned in the dcs array
1055  @return true if the list was added to, false otherwise
1056 *******************************************************************/
1057
1058 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1059                               const char *dcname, struct sockaddr_storage *pss,
1060                               struct dc_name_ip **dcs, int *num)
1061 {
1062         int i = 0;
1063
1064         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1065                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1066                 return False;
1067         }
1068
1069         /* Make sure there's no duplicates in the list */
1070         for (i=0; i<*num; i++)
1071                 if (sockaddr_equal(
1072                             (struct sockaddr *)(void *)&(*dcs)[i].ss,
1073                             (struct sockaddr *)(void *)pss))
1074                         return False;
1075
1076         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1077
1078         if (*dcs == NULL)
1079                 return False;
1080
1081         fstrcpy((*dcs)[*num].name, dcname);
1082         (*dcs)[*num].ss = *pss;
1083         *num += 1;
1084         return True;
1085 }
1086
1087 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1088                                   struct sockaddr_storage *pss, uint16 port,
1089                                   struct sockaddr_storage **addrs, int *num)
1090 {
1091         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1092
1093         if (*addrs == NULL) {
1094                 *num = 0;
1095                 return False;
1096         }
1097
1098         (*addrs)[*num] = *pss;
1099         set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1100
1101         *num += 1;
1102         return True;
1103 }
1104
1105 /*******************************************************************
1106  convert an ip to a name
1107 *******************************************************************/
1108
1109 static bool dcip_to_name(TALLOC_CTX *mem_ctx,
1110                 const struct winbindd_domain *domain,
1111                 struct sockaddr_storage *pss,
1112                 fstring name )
1113 {
1114         struct ip_service ip_list;
1115         uint32_t nt_version = NETLOGON_NT_VERSION_1;
1116         NTSTATUS status;
1117         const char *dc_name;
1118
1119         ip_list.ss = *pss;
1120         ip_list.port = 0;
1121
1122 #ifdef HAVE_ADS
1123         /* For active directory servers, try to get the ldap server name.
1124            None of these failures should be considered critical for now */
1125
1126         if (lp_security() == SEC_ADS) {
1127                 ADS_STRUCT *ads;
1128                 ADS_STATUS ads_status;
1129                 char addr[INET6_ADDRSTRLEN];
1130
1131                 print_sockaddr(addr, sizeof(addr), pss);
1132
1133                 ads = ads_init(domain->alt_name, domain->name, addr);
1134                 ads->auth.flags |= ADS_AUTH_NO_BIND;
1135
1136                 ads_status = ads_connect(ads);
1137                 if (ADS_ERR_OK(ads_status)) {
1138                         /* We got a cldap packet. */
1139                         fstrcpy(name, ads->config.ldap_server_name);
1140                         namecache_store(name, 0x20, 1, &ip_list);
1141
1142                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
1143
1144                         if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1145                                 if (ads_closest_dc(ads)) {
1146                                         char *sitename = sitename_fetch(ads->config.realm);
1147
1148                                         /* We're going to use this KDC for this realm/domain.
1149                                            If we are using sites, then force the krb5 libs
1150                                            to use this KDC. */
1151
1152                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1153                                                                         domain->name,
1154                                                                         sitename,
1155                                                                         pss,
1156                                                                         name);
1157
1158                                         SAFE_FREE(sitename);
1159                                 } else {
1160                                         /* use an off site KDC */
1161                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1162                                                                         domain->name,
1163                                                                         NULL,
1164                                                                         pss,
1165                                                                         name);
1166                                 }
1167                                 winbindd_set_locator_kdc_envs(domain);
1168
1169                                 /* Ensure we contact this DC also. */
1170                                 saf_store( domain->name, name);
1171                                 saf_store( domain->alt_name, name);
1172                         }
1173
1174                         ads_destroy( &ads );
1175                         return True;
1176                 }
1177
1178                 ads_destroy( &ads );
1179         }
1180 #endif
1181
1182         status = nbt_getdc(winbind_messaging_context(), pss, domain->name,
1183                            &domain->sid, nt_version, mem_ctx, &nt_version,
1184                            &dc_name, NULL);
1185         if (NT_STATUS_IS_OK(status)) {
1186                 fstrcpy(name, dc_name);
1187                 namecache_store(name, 0x20, 1, &ip_list);
1188                 return True;
1189         }
1190
1191         /* try node status request */
1192
1193         if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) {
1194                 namecache_store(name, 0x20, 1, &ip_list);
1195                 return True;
1196         }
1197         return False;
1198 }
1199
1200 /*******************************************************************
1201  Retrieve a list of IP addresses for domain controllers.
1202
1203  The array is sorted in the preferred connection order.
1204
1205  @param[in] mem_ctx talloc memory context to allocate from
1206  @param[in] domain domain to retrieve DCs for
1207  @param[out] dcs array of dcs that will be returned
1208  @param[out] num_dcs number of dcs returned in the dcs array
1209  @return always true
1210 *******************************************************************/
1211
1212 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1213                     struct dc_name_ip **dcs, int *num_dcs)
1214 {
1215         fstring dcname;
1216         struct  sockaddr_storage ss;
1217         struct  ip_service *ip_list = NULL;
1218         int     iplist_size = 0;
1219         int     i;
1220         bool    is_our_domain;
1221         enum security_types sec = (enum security_types)lp_security();
1222
1223         is_our_domain = strequal(domain->name, lp_workgroup());
1224
1225         /* If not our domain, get the preferred DC, by asking our primary DC */
1226         if ( !is_our_domain
1227                 && get_dc_name_via_netlogon(domain, dcname, &ss)
1228                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1229                        num_dcs) )
1230         {
1231                 char addr[INET6_ADDRSTRLEN];
1232                 print_sockaddr(addr, sizeof(addr), &ss);
1233                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1234                            dcname, addr));
1235                 return True;
1236         }
1237
1238         if (sec == SEC_ADS) {
1239                 char *sitename = NULL;
1240
1241                 /* We need to make sure we know the local site before
1242                    doing any DNS queries, as this will restrict the
1243                    get_sorted_dc_list() call below to only fetching
1244                    DNS records for the correct site. */
1245
1246                 /* Find any DC to get the site record.
1247                    We deliberately don't care about the
1248                    return here. */
1249
1250                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1251
1252                 sitename = sitename_fetch(domain->alt_name);
1253                 if (sitename) {
1254
1255                         /* Do the site-specific AD dns lookup first. */
1256                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list,
1257                                &iplist_size, True);
1258
1259                         /* Add ips to the DC array.  We don't look up the name
1260                            of the DC in this function, but we fill in the char*
1261                            of the ip now to make the failed connection cache
1262                            work */
1263                         for ( i=0; i<iplist_size; i++ ) {
1264                                 char addr[INET6_ADDRSTRLEN];
1265                                 print_sockaddr(addr, sizeof(addr),
1266                                                 &ip_list[i].ss);
1267                                 add_one_dc_unique(mem_ctx,
1268                                                 domain->name,
1269                                                 addr,
1270                                                 &ip_list[i].ss,
1271                                                 dcs,
1272                                                 num_dcs);
1273                         }
1274
1275                         SAFE_FREE(ip_list);
1276                         SAFE_FREE(sitename);
1277                         iplist_size = 0;
1278                 }
1279
1280                 /* Now we add DCs from the main AD DNS lookup. */
1281                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list,
1282                         &iplist_size, True);
1283
1284                 for ( i=0; i<iplist_size; i++ ) {
1285                         char addr[INET6_ADDRSTRLEN];
1286                         print_sockaddr(addr, sizeof(addr),
1287                                         &ip_list[i].ss);
1288                         add_one_dc_unique(mem_ctx,
1289                                         domain->name,
1290                                         addr,
1291                                         &ip_list[i].ss,
1292                                         dcs,
1293                                         num_dcs);
1294                 }
1295
1296                 SAFE_FREE(ip_list);
1297                 iplist_size = 0;
1298         }
1299
1300         /* Try standard netbios queries if no ADS */
1301         if (*num_dcs == 0) {
1302                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size,
1303                        False);
1304
1305                 for ( i=0; i<iplist_size; i++ ) {
1306                         char addr[INET6_ADDRSTRLEN];
1307                         print_sockaddr(addr, sizeof(addr),
1308                                         &ip_list[i].ss);
1309                         add_one_dc_unique(mem_ctx,
1310                                         domain->name,
1311                                         addr,
1312                                         &ip_list[i].ss,
1313                                         dcs,
1314                                         num_dcs);
1315                 }
1316
1317                 SAFE_FREE(ip_list);
1318                 iplist_size = 0;
1319         }
1320
1321         return True;
1322 }
1323
1324 /*******************************************************************
1325  Find and make a connection to a DC in the given domain.
1326
1327  @param[in] mem_ctx talloc memory context to allocate from
1328  @param[in] domain domain to find a dc in
1329  @param[out] dcname NetBIOS or FQDN of DC that's connected to
1330  @param[out] pss DC Internet address and port
1331  @param[out] fd fd of the open socket connected to the newly found dc
1332  @return true when a DC connection is made, false otherwise
1333 *******************************************************************/
1334
1335 static bool find_new_dc(TALLOC_CTX *mem_ctx,
1336                         struct winbindd_domain *domain,
1337                         fstring dcname, struct sockaddr_storage *pss, int *fd)
1338 {
1339         struct dc_name_ip *dcs = NULL;
1340         int num_dcs = 0;
1341
1342         const char **dcnames = NULL;
1343         int num_dcnames = 0;
1344
1345         struct sockaddr_storage *addrs = NULL;
1346         int num_addrs = 0;
1347
1348         int i;
1349         size_t fd_index;
1350
1351         NTSTATUS status;
1352
1353         *fd = -1;
1354
1355  again:
1356         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
1357                 return False;
1358
1359         for (i=0; i<num_dcs; i++) {
1360
1361                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1362                                     &dcnames, &num_dcnames)) {
1363                         return False;
1364                 }
1365                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 445,
1366                                       &addrs, &num_addrs)) {
1367                         return False;
1368                 }
1369         }
1370
1371         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1372                 return False;
1373
1374         if ((addrs == NULL) || (dcnames == NULL))
1375                 return False;
1376
1377         status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1378                                      num_addrs, 0, fd, &fd_index, NULL);
1379         if (!NT_STATUS_IS_OK(status)) {
1380                 for (i=0; i<num_dcs; i++) {
1381                         char ab[INET6_ADDRSTRLEN];
1382                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1383                         DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
1384                                 "domain %s address %s. Error was %s\n",
1385                                    domain->name, ab, nt_errstr(status) ));
1386                         winbind_add_failed_connection_entry(domain,
1387                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1388                 }
1389                 return False;
1390         }
1391
1392         *pss = addrs[fd_index];
1393
1394         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1395                 /* Ok, we've got a name for the DC */
1396                 fstrcpy(dcname, dcnames[fd_index]);
1397                 return True;
1398         }
1399
1400         /* Try to figure out the name */
1401         if (dcip_to_name(mem_ctx, domain, pss, dcname)) {
1402                 return True;
1403         }
1404
1405         /* We can not continue without the DC's name */
1406         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1407                                     NT_STATUS_UNSUCCESSFUL);
1408
1409         /* Throw away all arrays as we're doing this again. */
1410         TALLOC_FREE(dcs);
1411         num_dcs = 0;
1412
1413         TALLOC_FREE(dcnames);
1414         num_dcnames = 0;
1415
1416         TALLOC_FREE(addrs);
1417         num_addrs = 0;
1418
1419         close(*fd);
1420         *fd = -1;
1421
1422         goto again;
1423 }
1424
1425 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1426 {
1427         return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1428                                           domain_name);
1429 }
1430
1431 static void store_current_dc_in_gencache(const char *domain_name,
1432                                          const char *dc_name,
1433                                          struct cli_state *cli)
1434 {
1435         char addr[INET6_ADDRSTRLEN];
1436         char *key = NULL;
1437         char *value = NULL;
1438
1439         if (cli == NULL) {
1440                 return;
1441         }
1442         if (cli->fd == -1) {
1443                 return;
1444         }
1445         get_peer_addr(cli->fd, addr, sizeof(addr));
1446
1447         key = current_dc_key(talloc_tos(), domain_name);
1448         if (key == NULL) {
1449                 goto done;
1450         }
1451
1452         value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1453         if (value == NULL) {
1454                 goto done;
1455         }
1456
1457         gencache_set(key, value, 0x7fffffff);
1458 done:
1459         TALLOC_FREE(value);
1460         TALLOC_FREE(key);
1461 }
1462
1463 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1464                                     const char *domain_name,
1465                                     char **p_dc_name, char **p_dc_ip)
1466 {
1467         char *key, *value, *p;
1468         bool ret = false;
1469         char *dc_name = NULL;
1470         char *dc_ip = NULL;
1471
1472         key = current_dc_key(talloc_tos(), domain_name);
1473         if (key == NULL) {
1474                 goto done;
1475         }
1476         if (!gencache_get(key, &value, NULL)) {
1477                 goto done;
1478         }
1479         p = strchr(value, ' ');
1480         if (p == NULL) {
1481                 goto done;
1482         }
1483         dc_ip = talloc_strndup(mem_ctx, value, p - value);
1484         if (dc_ip == NULL) {
1485                 goto done;
1486         }
1487         dc_name = talloc_strdup(mem_ctx, p+1);
1488         if (dc_name == NULL) {
1489                 goto done;
1490         }
1491
1492         if (p_dc_ip != NULL) {
1493                 *p_dc_ip = dc_ip;
1494                 dc_ip = NULL;
1495         }
1496         if (p_dc_name != NULL) {
1497                 *p_dc_name = dc_name;
1498                 dc_name = NULL;
1499         }
1500         ret = true;
1501 done:
1502         TALLOC_FREE(dc_name);
1503         TALLOC_FREE(dc_ip);
1504         TALLOC_FREE(key);
1505         return ret;
1506 }
1507
1508 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1509                                    struct winbindd_cm_conn *new_conn)
1510 {
1511         TALLOC_CTX *mem_ctx;
1512         NTSTATUS result;
1513         char *saf_servername = saf_fetch( domain->name );
1514         int retries;
1515
1516         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1517                 SAFE_FREE(saf_servername);
1518                 set_domain_offline(domain);
1519                 return NT_STATUS_NO_MEMORY;
1520         }
1521
1522         /* we have to check the server affinity cache here since 
1523            later we select a DC based on response time and not preference */
1524
1525         /* Check the negative connection cache
1526            before talking to it. It going down may have
1527            triggered the reconnection. */
1528
1529         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1530
1531                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1532                         saf_servername, domain->name ));
1533
1534                 /* convert an ip address to a name */
1535                 if (is_ipaddress( saf_servername ) ) {
1536                         fstring saf_name;
1537                         struct sockaddr_storage ss;
1538
1539                         if (!interpret_string_addr(&ss, saf_servername,
1540                                                 AI_NUMERICHOST)) {
1541                                 return NT_STATUS_UNSUCCESSFUL;
1542                         }
1543                         if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) {
1544                                 fstrcpy( domain->dcname, saf_name );
1545                         } else {
1546                                 winbind_add_failed_connection_entry(
1547                                         domain, saf_servername,
1548                                         NT_STATUS_UNSUCCESSFUL);
1549                         }
1550                 } else {
1551                         fstrcpy( domain->dcname, saf_servername );
1552                 }
1553
1554                 SAFE_FREE( saf_servername );
1555         }
1556
1557         for (retries = 0; retries < 3; retries++) {
1558                 int fd = -1;
1559                 bool retry = False;
1560
1561                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1562
1563                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1564                         domain->dcname, domain->name ));
1565
1566                 if (*domain->dcname 
1567                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1568                         && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true)))
1569                 {
1570                         NTSTATUS status;
1571
1572                         status = smbsock_connect(&domain->dcaddr, 0,
1573                                                  NULL, -1, NULL, -1,
1574                                                  &fd, NULL);
1575                         if (!NT_STATUS_IS_OK(status)) {
1576                                 fd = -1;
1577                         }
1578                 }
1579
1580                 if ((fd == -1) 
1581                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1582                 {
1583                         /* This is the one place where we will
1584                            set the global winbindd offline state
1585                            to true, if a "WINBINDD_OFFLINE" entry
1586                            is found in the winbindd cache. */
1587                         set_global_winbindd_state_offline();
1588                         break;
1589                 }
1590
1591                 new_conn->cli = NULL;
1592
1593                 result = cm_prepare_connection(domain, fd, domain->dcname,
1594                         &new_conn->cli, &retry);
1595
1596                 if (!retry)
1597                         break;
1598         }
1599
1600         if (NT_STATUS_IS_OK(result)) {
1601
1602                 winbindd_set_locator_kdc_envs(domain);
1603
1604                 if (domain->online == False) {
1605                         /* We're changing state from offline to online. */
1606                         set_global_winbindd_state_online();
1607                 }
1608                 set_domain_online(domain);
1609
1610                 /*
1611                  * Much as I hate global state, this seems to be the point
1612                  * where we can be certain that we have a proper connection to
1613                  * a DC. wbinfo --dc-info needs that information, store it in
1614                  * gencache with a looong timeout. This will need revisiting
1615                  * once we start to connect to multiple DCs, wbcDcInfo is
1616                  * already prepared for that.
1617                  */
1618                 store_current_dc_in_gencache(domain->name, domain->dcname,
1619                                              new_conn->cli);
1620         } else {
1621                 /* Ensure we setup the retry handler. */
1622                 set_domain_offline(domain);
1623         }
1624
1625         talloc_destroy(mem_ctx);
1626         return result;
1627 }
1628
1629 /* Close down all open pipes on a connection. */
1630
1631 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1632 {
1633         NTSTATUS result;
1634
1635         /* We're closing down a possibly dead
1636            connection. Don't have impossibly long (10s) timeouts. */
1637
1638         if (conn->cli) {
1639                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1640         }
1641
1642         if (conn->samr_pipe != NULL) {
1643                 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1644                         dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1645                                           talloc_tos(),
1646                                           &conn->sam_connect_handle,
1647                                           &result);
1648                 }
1649                 TALLOC_FREE(conn->samr_pipe);
1650                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1651                 if (conn->cli) {
1652                         cli_set_timeout(conn->cli, 500);
1653                 }
1654         }
1655
1656         if (conn->lsa_pipe != NULL) {
1657                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1658                         dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1659                                          talloc_tos(),
1660                                          &conn->lsa_policy,
1661                                          &result);
1662                 }
1663                 TALLOC_FREE(conn->lsa_pipe);
1664                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1665                 if (conn->cli) {
1666                         cli_set_timeout(conn->cli, 500);
1667                 }
1668         }
1669
1670         if (conn->lsa_pipe_tcp != NULL) {
1671                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1672                         dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1673                                          talloc_tos(),
1674                                          &conn->lsa_policy,
1675                                          &result);
1676                 }
1677                 TALLOC_FREE(conn->lsa_pipe_tcp);
1678                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1679                 if (conn->cli) {
1680                         cli_set_timeout(conn->cli, 500);
1681                 }
1682         }
1683
1684         if (conn->netlogon_pipe != NULL) {
1685                 TALLOC_FREE(conn->netlogon_pipe);
1686                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1687                 if (conn->cli) {
1688                         cli_set_timeout(conn->cli, 500);
1689                 }
1690         }
1691
1692         if (conn->cli) {
1693                 cli_shutdown(conn->cli);
1694         }
1695
1696         conn->cli = NULL;
1697 }
1698
1699 void close_conns_after_fork(void)
1700 {
1701         struct winbindd_domain *domain;
1702
1703         for (domain = domain_list(); domain; domain = domain->next) {
1704                 struct cli_state *cli = domain->conn.cli;
1705
1706                 /*
1707                  * first close the low level SMB TCP connection
1708                  * so that we don't generate any SMBclose
1709                  * requests in invalidate_cm_connection()
1710                  */
1711                 if (cli && cli->fd != -1) {
1712                         close(domain->conn.cli->fd);
1713                         domain->conn.cli->fd = -1;
1714                 }
1715
1716                 invalidate_cm_connection(&domain->conn);
1717         }
1718 }
1719
1720 static bool connection_ok(struct winbindd_domain *domain)
1721 {
1722         bool ok;
1723
1724         ok = cli_state_is_connected(domain->conn.cli);
1725         if (!ok) {
1726                 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1727                           domain->dcname, domain->name));
1728                 return False;
1729         }
1730
1731         if (domain->online == False) {
1732                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1733                 return False;
1734         }
1735
1736         return True;
1737 }
1738
1739 /* Initialize a new connection up to the RPC BIND.
1740    Bypass online status check so always does network calls. */
1741
1742 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
1743 {
1744         NTSTATUS result;
1745
1746         /* Internal connections never use the network. */
1747         if (domain->internal) {
1748                 domain->initialized = True;
1749                 return NT_STATUS_OK;
1750         }
1751
1752         if (!winbindd_can_contact_domain(domain)) {
1753                 invalidate_cm_connection(&domain->conn);
1754                 domain->initialized = True;
1755                 return NT_STATUS_OK;
1756         }
1757
1758         if (connection_ok(domain)) {
1759                 if (!domain->initialized) {
1760                         set_dc_type_and_flags(domain);
1761                 }
1762                 return NT_STATUS_OK;
1763         }
1764
1765         invalidate_cm_connection(&domain->conn);
1766
1767         result = cm_open_connection(domain, &domain->conn);
1768
1769         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1770                 set_dc_type_and_flags(domain);
1771         }
1772
1773         return result;
1774 }
1775
1776 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1777 {
1778         if (domain->internal) {
1779                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1780         }
1781
1782         if (domain->initialized && !domain->online) {
1783                 /* We check for online status elsewhere. */
1784                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1785         }
1786
1787         return init_dc_connection_network(domain);
1788 }
1789
1790 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
1791 {
1792         NTSTATUS status;
1793
1794         status = init_dc_connection(domain);
1795         if (!NT_STATUS_IS_OK(status)) {
1796                 return status;
1797         }
1798
1799         if (!domain->internal && domain->conn.cli == NULL) {
1800                 /* happens for trusted domains without inbound trust */
1801                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
1802         }
1803
1804         return NT_STATUS_OK;
1805 }
1806
1807 /******************************************************************************
1808  Set the trust flags (direction and forest location) for a domain
1809 ******************************************************************************/
1810
1811 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
1812 {
1813         struct winbindd_domain *our_domain;
1814         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1815         WERROR werr;
1816         struct netr_DomainTrustList trusts;
1817         int i;
1818         uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
1819                         NETR_TRUST_FLAG_OUTBOUND |
1820                         NETR_TRUST_FLAG_INBOUND);
1821         struct rpc_pipe_client *cli;
1822         TALLOC_CTX *mem_ctx = NULL;
1823         struct dcerpc_binding_handle *b;
1824
1825         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
1826
1827         /* Our primary domain doesn't need to worry about trust flags.
1828            Force it to go through the network setup */
1829         if ( domain->primary ) {                
1830                 return False;           
1831         }
1832
1833         our_domain = find_our_domain();
1834
1835         if ( !connection_ok(our_domain) ) {
1836                 DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
1837                 return False;
1838         }
1839
1840         /* This won't work unless our domain is AD */
1841
1842         if ( !our_domain->active_directory ) {
1843                 return False;
1844         }
1845
1846         /* Use DsEnumerateDomainTrusts to get us the trust direction
1847            and type */
1848
1849         result = cm_connect_netlogon(our_domain, &cli);
1850
1851         if (!NT_STATUS_IS_OK(result)) {
1852                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
1853                           "a connection to %s for PIPE_NETLOGON (%s)\n", 
1854                           domain->name, nt_errstr(result)));
1855                 return False;
1856         }
1857
1858         b = cli->binding_handle;
1859
1860         if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
1861                 DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
1862                 return False;
1863         }       
1864
1865         result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1866                                                       cli->desthost,
1867                                                       flags,
1868                                                       &trusts,
1869                                                       &werr);
1870         if (!NT_STATUS_IS_OK(result)) {
1871                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1872                         "failed to query trusted domain list: %s\n",
1873                         nt_errstr(result)));
1874                 talloc_destroy(mem_ctx);
1875                 return false;
1876         }
1877         if (!W_ERROR_IS_OK(werr)) {
1878                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
1879                         "failed to query trusted domain list: %s\n",
1880                         win_errstr(werr)));
1881                 talloc_destroy(mem_ctx);
1882                 return false;
1883         }
1884
1885         /* Now find the domain name and get the flags */
1886
1887         for ( i=0; i<trusts.count; i++ ) {
1888                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
1889                         domain->domain_flags          = trusts.array[i].trust_flags;
1890                         domain->domain_type           = trusts.array[i].trust_type;
1891                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
1892
1893                         if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
1894                                 domain->active_directory = True;
1895
1896                         /* This flag is only set if the domain is *our* 
1897                            primary domain and the primary domain is in
1898                            native mode */
1899
1900                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
1901
1902                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
1903                                   "native mode.\n", domain->name, 
1904                                   domain->native_mode ? "" : "NOT "));
1905
1906                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
1907                                  "running active directory.\n", domain->name, 
1908                                  domain->active_directory ? "" : "NOT "));
1909
1910
1911                         domain->initialized = True;
1912
1913                         break;
1914                 }               
1915         }
1916
1917         talloc_destroy( mem_ctx );
1918
1919         return domain->initialized;     
1920 }
1921
1922 /******************************************************************************
1923  We can 'sense' certain things about the DC by it's replies to certain
1924  questions.
1925
1926  This tells us if this particular remote server is Active Directory, and if it
1927  is native mode.
1928 ******************************************************************************/
1929
1930 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
1931 {
1932         NTSTATUS status, result;
1933         WERROR werr;
1934         TALLOC_CTX              *mem_ctx = NULL;
1935         struct rpc_pipe_client  *cli = NULL;
1936         struct policy_handle pol;
1937         union dssetup_DsRoleInfo info;
1938         union lsa_PolicyInformation *lsa_info = NULL;
1939
1940         if (!connection_ok(domain)) {
1941                 return;
1942         }
1943
1944         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1945                               domain->name);
1946         if (!mem_ctx) {
1947                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
1948                 return;
1949         }
1950
1951         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
1952
1953         status = cli_rpc_pipe_open_noauth(domain->conn.cli,
1954                                           &ndr_table_dssetup.syntax_id,
1955                                           &cli);
1956
1957         if (!NT_STATUS_IS_OK(status)) {
1958                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
1959                           "PI_DSSETUP on domain %s: (%s)\n",
1960                           domain->name, nt_errstr(status)));
1961
1962                 /* if this is just a non-AD domain we need to continue
1963                  * identifying so that we can in the end return with
1964                  * domain->initialized = True - gd */
1965
1966                 goto no_dssetup;
1967         }
1968
1969         status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
1970                                                                   DS_ROLE_BASIC_INFORMATION,
1971                                                                   &info,
1972                                                                   &werr);
1973         TALLOC_FREE(cli);
1974
1975         if (NT_STATUS_IS_OK(status)) {
1976                 result = werror_to_ntstatus(werr);
1977         }
1978         if (!NT_STATUS_IS_OK(status)) {
1979                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
1980                           "on domain %s failed: (%s)\n",
1981                           domain->name, nt_errstr(status)));
1982
1983                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
1984                  * every opcode on the DSSETUP pipe, continue with
1985                  * no_dssetup mode here as well to get domain->initialized
1986                  * set - gd */
1987
1988                 if (NT_STATUS_V(status) == DCERPC_FAULT_OP_RNG_ERROR) {
1989                         goto no_dssetup;
1990                 }
1991
1992                 TALLOC_FREE(mem_ctx);
1993                 return;
1994         }
1995
1996         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
1997             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
1998                 domain->native_mode = True;
1999         } else {
2000                 domain->native_mode = False;
2001         }
2002
2003 no_dssetup:
2004         status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2005                                           &ndr_table_lsarpc.syntax_id, &cli);
2006
2007         if (!NT_STATUS_IS_OK(status)) {
2008                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2009                           "PI_LSARPC on domain %s: (%s)\n",
2010                           domain->name, nt_errstr(status)));
2011                 TALLOC_FREE(cli);
2012                 TALLOC_FREE(mem_ctx);
2013                 return;
2014         }
2015
2016         status = rpccli_lsa_open_policy2(cli, mem_ctx, True,
2017                                          SEC_FLAG_MAXIMUM_ALLOWED, &pol);
2018
2019         if (NT_STATUS_IS_OK(status)) {
2020                 /* This particular query is exactly what Win2k clients use 
2021                    to determine that the DC is active directory */
2022                 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2023                                                      &pol,
2024                                                      LSA_POLICY_INFO_DNS,
2025                                                      &lsa_info,
2026                                                      &result);
2027         }
2028
2029         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2030                 domain->active_directory = True;
2031
2032                 if (lsa_info->dns.name.string) {
2033                         fstrcpy(domain->name, lsa_info->dns.name.string);
2034                 }
2035
2036                 if (lsa_info->dns.dns_domain.string) {
2037                         fstrcpy(domain->alt_name,
2038                                 lsa_info->dns.dns_domain.string);
2039                 }
2040
2041                 /* See if we can set some domain trust flags about
2042                    ourself */
2043
2044                 if (lsa_info->dns.dns_forest.string) {
2045                         fstrcpy(domain->forest_name,
2046                                 lsa_info->dns.dns_forest.string);
2047
2048                         if (strequal(domain->forest_name, domain->alt_name)) {
2049                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2050                         }
2051                 }
2052
2053                 if (lsa_info->dns.sid) {
2054                         sid_copy(&domain->sid, lsa_info->dns.sid);
2055                 }
2056         } else {
2057                 domain->active_directory = False;
2058
2059                 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2060                                                 SEC_FLAG_MAXIMUM_ALLOWED,
2061                                                 &pol);
2062
2063                 if (!NT_STATUS_IS_OK(status)) {
2064                         goto done;
2065                 }
2066
2067                 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2068                                                     &pol,
2069                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2070                                                     &lsa_info,
2071                                                     &result);
2072                 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2073
2074                         if (lsa_info->account_domain.name.string) {
2075                                 fstrcpy(domain->name,
2076                                         lsa_info->account_domain.name.string);
2077                         }
2078
2079                         if (lsa_info->account_domain.sid) {
2080                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2081                         }
2082                 }
2083         }
2084 done:
2085
2086         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2087                   domain->name, domain->native_mode ? "" : "NOT "));
2088
2089         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2090                   domain->name, domain->active_directory ? "" : "NOT "));
2091
2092         domain->can_do_ncacn_ip_tcp = domain->active_directory;
2093         domain->can_do_validation6 = domain->active_directory;
2094
2095         TALLOC_FREE(cli);
2096
2097         TALLOC_FREE(mem_ctx);
2098
2099         domain->initialized = True;
2100 }
2101
2102 /**********************************************************************
2103  Set the domain_flags (trust attributes, domain operating modes, etc... 
2104 ***********************************************************************/
2105
2106 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2107 {
2108         /* we always have to contact our primary domain */
2109
2110         if ( domain->primary ) {
2111                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2112                           "primary domain\n"));
2113                 set_dc_type_and_flags_connect( domain );
2114                 return;         
2115         }
2116
2117         /* Use our DC to get the information if possible */
2118
2119         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2120                 /* Otherwise, fallback to contacting the 
2121                    domain directly */
2122                 set_dc_type_and_flags_connect( domain );
2123         }
2124
2125         return;
2126 }
2127
2128
2129
2130 /**********************************************************************
2131 ***********************************************************************/
2132
2133 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2134                                    struct netlogon_creds_CredentialState **ppdc)
2135 {
2136         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2137         struct rpc_pipe_client *netlogon_pipe;
2138
2139         if (lp_client_schannel() == False) {
2140                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2141         }
2142
2143         result = cm_connect_netlogon(domain, &netlogon_pipe);
2144         if (!NT_STATUS_IS_OK(result)) {
2145                 return result;
2146         }
2147
2148         /* Return a pointer to the struct netlogon_creds_CredentialState from the
2149            netlogon pipe. */
2150
2151         if (!domain->conn.netlogon_pipe->dc) {
2152                 return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
2153         }
2154
2155         *ppdc = domain->conn.netlogon_pipe->dc;
2156         return NT_STATUS_OK;
2157 }
2158
2159 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2160                         struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2161 {
2162         struct winbindd_cm_conn *conn;
2163         NTSTATUS status, result;
2164         struct netlogon_creds_CredentialState *p_creds;
2165         char *machine_password = NULL;
2166         char *machine_account = NULL;
2167         char *domain_name = NULL;
2168
2169         if (sid_check_is_domain(&domain->sid)) {
2170                 return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2171         }
2172
2173         status = init_dc_connection_rpc(domain);
2174         if (!NT_STATUS_IS_OK(status)) {
2175                 return status;
2176         }
2177
2178         conn = &domain->conn;
2179
2180         if (rpccli_is_connected(conn->samr_pipe)) {
2181                 goto done;
2182         }
2183
2184         TALLOC_FREE(conn->samr_pipe);
2185
2186         /*
2187          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2188          * sign and sealed pipe using the machine account password by
2189          * preference. If we can't - try schannel, if that fails, try
2190          * anonymous.
2191          */
2192
2193         if ((conn->cli->user_name[0] == '\0') ||
2194             (conn->cli->domain[0] == '\0') || 
2195             (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
2196         {
2197                 status = get_trust_creds(domain, &machine_password,
2198                                          &machine_account, NULL);
2199                 if (!NT_STATUS_IS_OK(status)) {
2200                         DEBUG(10, ("cm_connect_sam: No no user available for "
2201                                    "domain %s, trying schannel\n", conn->cli->domain));
2202                         goto schannel;
2203                 }
2204                 domain_name = domain->name;
2205         } else {
2206                 machine_password = SMB_STRDUP(conn->cli->password);
2207                 machine_account = SMB_STRDUP(conn->cli->user_name);
2208                 domain_name = conn->cli->domain;
2209         }
2210
2211         if (!machine_password || !machine_account) {
2212                 status = NT_STATUS_NO_MEMORY;
2213                 goto done;
2214         }
2215
2216         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2217            authenticated SAMR pipe with sign & seal. */
2218         status = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
2219                                                   &ndr_table_samr.syntax_id,
2220                                                   NCACN_NP,
2221                                                   DCERPC_AUTH_LEVEL_PRIVACY,
2222                                                   domain_name,
2223                                                   machine_account,
2224                                                   machine_password,
2225                                                   &conn->samr_pipe);
2226
2227         if (!NT_STATUS_IS_OK(status)) {
2228                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2229                           "pipe for domain %s using NTLMSSP "
2230                           "authenticated pipe: user %s\\%s. Error was "
2231                           "%s\n", domain->name, domain_name,
2232                           machine_account, nt_errstr(status)));
2233                 goto schannel;
2234         }
2235
2236         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2237                   "domain %s using NTLMSSP authenticated "
2238                   "pipe: user %s\\%s\n", domain->name,
2239                   domain_name, machine_account));
2240
2241         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2242                                       conn->samr_pipe->desthost,
2243                                       SEC_FLAG_MAXIMUM_ALLOWED,
2244                                       &conn->sam_connect_handle,
2245                                       &result);
2246         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2247                 goto open_domain;
2248         }
2249         if (NT_STATUS_IS_OK(status)) {
2250                 status = result;
2251         }
2252
2253         DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2254                   "failed for domain %s, error was %s. Trying schannel\n",
2255                   domain->name, nt_errstr(status) ));
2256         TALLOC_FREE(conn->samr_pipe);
2257
2258  schannel:
2259
2260         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2261
2262         status = cm_get_schannel_creds(domain, &p_creds);
2263         if (!NT_STATUS_IS_OK(status)) {
2264                 /* If this call fails - conn->cli can now be NULL ! */
2265                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2266                            "for domain %s (error %s), trying anon\n",
2267                         domain->name,
2268                         nt_errstr(status) ));
2269                 goto anonymous;
2270         }
2271         status = cli_rpc_pipe_open_schannel_with_key
2272                 (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP,
2273                  DCERPC_AUTH_LEVEL_PRIVACY,
2274                  domain->name, &p_creds, &conn->samr_pipe);
2275
2276         if (!NT_STATUS_IS_OK(status)) {
2277                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2278                           "domain %s using schannel. Error was %s\n",
2279                           domain->name, nt_errstr(status) ));
2280                 goto anonymous;
2281         }
2282         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2283                   "schannel.\n", domain->name ));
2284
2285         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2286                                       conn->samr_pipe->desthost,
2287                                       SEC_FLAG_MAXIMUM_ALLOWED,
2288                                       &conn->sam_connect_handle,
2289                                       &result);
2290         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2291                 goto open_domain;
2292         }
2293         if (NT_STATUS_IS_OK(status)) {
2294                 status = result;
2295         }
2296         DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2297                   "for domain %s, error was %s. Trying anonymous\n",
2298                   domain->name, nt_errstr(status) ));
2299         TALLOC_FREE(conn->samr_pipe);
2300
2301  anonymous:
2302
2303         /* Finally fall back to anonymous. */
2304         status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id,
2305                                           &conn->samr_pipe);
2306
2307         if (!NT_STATUS_IS_OK(status)) {
2308                 goto done;
2309         }
2310
2311         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2312                                       conn->samr_pipe->desthost,
2313                                       SEC_FLAG_MAXIMUM_ALLOWED,
2314                                       &conn->sam_connect_handle,
2315                                       &result);
2316         if (!NT_STATUS_IS_OK(status)) {
2317                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2318                           "for domain %s Error was %s\n",
2319                           domain->name, nt_errstr(status) ));
2320                 goto done;
2321         }
2322         if (!NT_STATUS_IS_OK(result)) {
2323                 status = result;
2324                 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2325                           "for domain %s Error was %s\n",
2326                           domain->name, nt_errstr(result)));
2327                 goto done;
2328         }
2329
2330  open_domain:
2331         status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2332                                         mem_ctx,
2333                                         &conn->sam_connect_handle,
2334                                         SEC_FLAG_MAXIMUM_ALLOWED,
2335                                         &domain->sid,
2336                                         &conn->sam_domain_handle,
2337                                         &result);
2338         if (!NT_STATUS_IS_OK(status)) {
2339                 goto done;
2340         }
2341
2342         status = result;
2343  done:
2344
2345         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2346                 /*
2347                  * if we got access denied, we might just have no access rights
2348                  * to talk to the remote samr server server (e.g. when we are a
2349                  * PDC and we are connecting a w2k8 pdc via an interdomain
2350                  * trust). In that case do not invalidate the whole connection
2351                  * stack
2352                  */
2353                 TALLOC_FREE(conn->samr_pipe);
2354                 ZERO_STRUCT(conn->sam_domain_handle);
2355                 return status;
2356         } else if (!NT_STATUS_IS_OK(status)) {
2357                 invalidate_cm_connection(conn);
2358                 return status;
2359         }
2360
2361         *cli = conn->samr_pipe;
2362         *sam_handle = conn->sam_domain_handle;
2363         SAFE_FREE(machine_password);
2364         SAFE_FREE(machine_account);
2365         return status;
2366 }
2367
2368 /**********************************************************************
2369  open an schanneld ncacn_ip_tcp connection to LSA
2370 ***********************************************************************/
2371
2372 NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2373                             TALLOC_CTX *mem_ctx,
2374                             struct rpc_pipe_client **cli)
2375 {
2376         struct winbindd_cm_conn *conn;
2377         struct netlogon_creds_CredentialState *creds;
2378         NTSTATUS status;
2379
2380         DEBUG(10,("cm_connect_lsa_tcp\n"));
2381
2382         status = init_dc_connection_rpc(domain);
2383         if (!NT_STATUS_IS_OK(status)) {
2384                 return status;
2385         }
2386
2387         conn = &domain->conn;
2388
2389         if (conn->lsa_pipe_tcp &&
2390             conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2391             conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
2392             rpccli_is_connected(conn->lsa_pipe_tcp)) {
2393                 goto done;
2394         }
2395
2396         TALLOC_FREE(conn->lsa_pipe_tcp);
2397
2398         status = cm_get_schannel_creds(domain, &creds);
2399         if (!NT_STATUS_IS_OK(status)) {
2400                 goto done;
2401         }
2402
2403         status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
2404                                                      &ndr_table_lsarpc.syntax_id,
2405                                                      NCACN_IP_TCP,
2406                                                      DCERPC_AUTH_LEVEL_PRIVACY,
2407                                                      domain->name,
2408                                                      &creds,
2409                                                      &conn->lsa_pipe_tcp);
2410         if (!NT_STATUS_IS_OK(status)) {
2411                 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2412                         nt_errstr(status)));
2413                 goto done;
2414         }
2415
2416  done:
2417         if (!NT_STATUS_IS_OK(status)) {
2418                 TALLOC_FREE(conn->lsa_pipe_tcp);
2419                 return status;
2420         }
2421
2422         *cli = conn->lsa_pipe_tcp;
2423
2424         return status;
2425 }
2426
2427 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2428                         struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2429 {
2430         struct winbindd_cm_conn *conn;
2431         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2432         struct netlogon_creds_CredentialState *p_creds;
2433
2434         result = init_dc_connection_rpc(domain);
2435         if (!NT_STATUS_IS_OK(result))
2436                 return result;
2437
2438         conn = &domain->conn;
2439
2440         if (rpccli_is_connected(conn->lsa_pipe)) {
2441                 goto done;
2442         }
2443
2444         TALLOC_FREE(conn->lsa_pipe);
2445
2446         if ((conn->cli->user_name[0] == '\0') ||
2447             (conn->cli->domain[0] == '\0') || 
2448             (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
2449                 DEBUG(10, ("cm_connect_lsa: No no user available for "
2450                            "domain %s, trying schannel\n", conn->cli->domain));
2451                 goto schannel;
2452         }
2453
2454         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
2455          * authenticated LSA pipe with sign & seal. */
2456         result = cli_rpc_pipe_open_spnego_ntlmssp
2457                 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2458                  DCERPC_AUTH_LEVEL_PRIVACY,
2459                  conn->cli->domain, conn->cli->user_name, conn->cli->password,
2460                  &conn->lsa_pipe);
2461
2462         if (!NT_STATUS_IS_OK(result)) {
2463                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2464                           "domain %s using NTLMSSP authenticated pipe: user "
2465                           "%s\\%s. Error was %s. Trying schannel.\n",
2466                           domain->name, conn->cli->domain,
2467                           conn->cli->user_name, nt_errstr(result)));
2468                 goto schannel;
2469         }
2470
2471         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2472                   "NTLMSSP authenticated pipe: user %s\\%s\n",
2473                   domain->name, conn->cli->domain, conn->cli->user_name ));
2474
2475         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2476                                         SEC_FLAG_MAXIMUM_ALLOWED,
2477                                         &conn->lsa_policy);
2478         if (NT_STATUS_IS_OK(result)) {
2479                 goto done;
2480         }
2481
2482         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2483                   "schannel\n"));
2484
2485         TALLOC_FREE(conn->lsa_pipe);
2486
2487  schannel:
2488
2489         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2490
2491         result = cm_get_schannel_creds(domain, &p_creds);
2492         if (!NT_STATUS_IS_OK(result)) {
2493                 /* If this call fails - conn->cli can now be NULL ! */
2494                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
2495                            "for domain %s (error %s), trying anon\n",
2496                         domain->name,
2497                         nt_errstr(result) ));
2498                 goto anonymous;
2499         }
2500         result = cli_rpc_pipe_open_schannel_with_key
2501                 (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP,
2502                  DCERPC_AUTH_LEVEL_PRIVACY,
2503                  domain->name, &p_creds, &conn->lsa_pipe);
2504
2505         if (!NT_STATUS_IS_OK(result)) {
2506                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2507                           "domain %s using schannel. Error was %s\n",
2508                           domain->name, nt_errstr(result) ));
2509                 goto anonymous;
2510         }
2511         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
2512                   "schannel.\n", domain->name ));
2513
2514         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2515                                         SEC_FLAG_MAXIMUM_ALLOWED,
2516                                         &conn->lsa_policy);
2517         if (NT_STATUS_IS_OK(result)) {
2518                 goto done;
2519         }
2520
2521         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
2522                   "anonymous\n"));
2523
2524         TALLOC_FREE(conn->lsa_pipe);
2525
2526  anonymous:
2527
2528         result = cli_rpc_pipe_open_noauth(conn->cli,
2529                                           &ndr_table_lsarpc.syntax_id,
2530                                           &conn->lsa_pipe);
2531         if (!NT_STATUS_IS_OK(result)) {
2532                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
2533                 goto done;
2534         }
2535
2536         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
2537                                         SEC_FLAG_MAXIMUM_ALLOWED,
2538                                         &conn->lsa_policy);
2539  done:
2540         if (!NT_STATUS_IS_OK(result)) {
2541                 invalidate_cm_connection(conn);
2542                 return result;
2543         }
2544
2545         *cli = conn->lsa_pipe;
2546         *lsa_policy = conn->lsa_policy;
2547         return result;
2548 }
2549
2550 /****************************************************************************
2551  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
2552  session key stored in conn->netlogon_pipe->dc->sess_key.
2553 ****************************************************************************/
2554
2555 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
2556                              struct rpc_pipe_client **cli)
2557 {
2558         struct winbindd_cm_conn *conn;
2559         NTSTATUS result;
2560
2561         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2562         uint8  mach_pwd[16];
2563         enum netr_SchannelType sec_chan_type;
2564         const char *account_name;
2565         struct rpc_pipe_client *netlogon_pipe = NULL;
2566
2567         *cli = NULL;
2568
2569         result = init_dc_connection_rpc(domain);
2570         if (!NT_STATUS_IS_OK(result)) {
2571                 return result;
2572         }
2573
2574         conn = &domain->conn;
2575
2576         if (rpccli_is_connected(conn->netlogon_pipe)) {
2577                 *cli = conn->netlogon_pipe;
2578                 return NT_STATUS_OK;
2579         }
2580
2581         TALLOC_FREE(conn->netlogon_pipe);
2582
2583         result = cli_rpc_pipe_open_noauth(conn->cli,
2584                                           &ndr_table_netlogon.syntax_id,
2585                                           &netlogon_pipe);
2586         if (!NT_STATUS_IS_OK(result)) {
2587                 return result;
2588         }
2589
2590         if ((!IS_DC) && (!domain->primary)) {
2591                 /* Clear the schannel request bit and drop down */
2592                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
2593                 goto no_schannel;
2594         }
2595
2596         if (lp_client_schannel() != False) {
2597                 neg_flags |= NETLOGON_NEG_SCHANNEL;
2598         }
2599
2600         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
2601                                &sec_chan_type))
2602         {
2603                 TALLOC_FREE(netlogon_pipe);
2604                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2605         }
2606
2607         result = rpccli_netlogon_setup_creds(
2608                  netlogon_pipe,
2609                  domain->dcname, /* server name. */
2610                  domain->name,   /* domain name */
2611                  global_myname(), /* client name */
2612                  account_name,   /* machine account */
2613                  mach_pwd,       /* machine password */
2614                  sec_chan_type,  /* from get_trust_pw */
2615                  &neg_flags);
2616
2617         if (!NT_STATUS_IS_OK(result)) {
2618                 TALLOC_FREE(netlogon_pipe);
2619                 return result;
2620         }
2621
2622         if ((lp_client_schannel() == True) &&
2623                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2624                 DEBUG(3, ("Server did not offer schannel\n"));
2625                 TALLOC_FREE(netlogon_pipe);
2626                 return NT_STATUS_ACCESS_DENIED;
2627         }
2628
2629  no_schannel:
2630         if ((lp_client_schannel() == False) ||
2631                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
2632                 /*
2633                  * NetSamLogonEx only works for schannel
2634                  */
2635                 domain->can_do_samlogon_ex = False;
2636
2637                 /* We're done - just keep the existing connection to NETLOGON
2638                  * open */
2639                 conn->netlogon_pipe = netlogon_pipe;
2640                 *cli = conn->netlogon_pipe;
2641                 return NT_STATUS_OK;
2642         }
2643
2644         /* Using the credentials from the first pipe, open a signed and sealed
2645            second netlogon pipe. The session key is stored in the schannel
2646            part of the new pipe auth struct.
2647         */
2648
2649         result = cli_rpc_pipe_open_schannel_with_key(
2650                 conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
2651                 DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc,
2652                 &conn->netlogon_pipe);
2653
2654         /* We can now close the initial netlogon pipe. */
2655         TALLOC_FREE(netlogon_pipe);
2656
2657         if (!NT_STATUS_IS_OK(result)) {
2658                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
2659                           "was %s\n", nt_errstr(result)));
2660
2661                 invalidate_cm_connection(conn);
2662                 return result;
2663         }
2664
2665         /*
2666          * Always try netr_LogonSamLogonEx. We will fall back for NT4
2667          * which gives DCERPC_FAULT_OP_RNG_ERROR (function not
2668          * supported). We used to only try SamLogonEx for AD, but
2669          * Samba DCs can also do it. And because we don't distinguish
2670          * between Samba and NT4, always try it once.
2671          */
2672         domain->can_do_samlogon_ex = true;
2673
2674         *cli = conn->netlogon_pipe;
2675         return NT_STATUS_OK;
2676 }
2677
2678 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
2679                             void *private_data,
2680                             uint32_t msg_type,
2681                             struct server_id server_id,
2682                             DATA_BLOB *data)
2683 {
2684         struct winbindd_domain *domain;
2685         char *freeit = NULL;
2686         char *addr;
2687
2688         if ((data == NULL)
2689             || (data->data == NULL)
2690             || (data->length == 0)
2691             || (data->data[data->length-1] != '\0')) {
2692                 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
2693                           "string\n"));
2694                 return;
2695         }
2696
2697         addr = (char *)data->data;
2698         DEBUG(10, ("IP %s dropped\n", addr));
2699
2700         if (!is_ipaddress(addr)) {
2701                 char *slash;
2702                 /*
2703                  * Some code sends us ip addresses with the /netmask
2704                  * suffix
2705                  */
2706                 slash = strchr(addr, '/');
2707                 if (slash == NULL) {
2708                         DEBUG(1, ("invalid msg_ip_dropped message: %s",
2709                                   addr));
2710                         return;
2711                 }
2712                 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
2713                 if (freeit == NULL) {
2714                         DEBUG(1, ("talloc failed\n"));
2715                         return;
2716                 }
2717                 addr = freeit;
2718                 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
2719         }
2720
2721         for (domain = domain_list(); domain != NULL; domain = domain->next) {
2722                 char sockaddr[INET6_ADDRSTRLEN];
2723                 if (domain->conn.cli == NULL) {
2724                         continue;
2725                 }
2726                 if (domain->conn.cli->fd == -1) {
2727                         continue;
2728                 }
2729                 client_socket_addr(domain->conn.cli->fd, sockaddr,
2730                                    sizeof(sockaddr));
2731                 if (strequal(sockaddr, addr)) {
2732                         close(domain->conn.cli->fd);
2733                         domain->conn.cli->fd = -1;
2734                 }
2735         }
2736         TALLOC_FREE(freeit);
2737 }