s4:dns_server: no-op dns updates with ACCESS_DENIED should be ignored
[samba.git] / source3 / winbindd / winbindd_cm.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon connection manager
5
6    Copyright (C) Tim Potter                2001
7    Copyright (C) Andrew Bartlett           2002
8    Copyright (C) Gerald (Jerry) Carter     2003-2005.
9    Copyright (C) Volker Lendecke           2004-2005
10    Copyright (C) Jeremy Allison            2006
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 /*
27    We need to manage connections to domain controllers without having to
28    mess up the main winbindd code with other issues.  The aim of the
29    connection manager is to:
30
31        - make connections to domain controllers and cache them
32        - re-establish connections when networks or servers go down
33        - centralise the policy on connection timeouts, domain controller
34          selection etc
35        - manage re-entrancy for when winbindd becomes able to handle
36          multiple outstanding rpc requests
37
38    Why not have connection management as part of the rpc layer like tng?
39    Good question.  This code may morph into libsmb/rpc_cache.c or something
40    like that but at the moment it's simply staying as part of winbind.  I
41    think the TNG architecture of forcing every user of the rpc layer to use
42    the connection caching system is a bad idea.  It should be an optional
43    method of using the routines.
44
45    The TNG design is quite good but I disagree with some aspects of the
46    implementation. -tpot
47
48  */
49
50 /*
51    TODO:
52
53      - I'm pretty annoyed by all the make_nmb_name() stuff.  It should be
54        moved down into another function.
55
56      - Take care when destroying cli_structs as they can be shared between
57        various sam handles.
58
59  */
60
61 #include "includes.h"
62 #include "winbindd.h"
63 #include "libsmb/namequery.h"
64 #include "../libcli/auth/libcli_auth.h"
65 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
66 #include "rpc_client/cli_pipe.h"
67 #include "rpc_client/cli_netlogon.h"
68 #include "../librpc/gen_ndr/ndr_samr_c.h"
69 #include "../librpc/gen_ndr/ndr_lsa_c.h"
70 #include "rpc_client/cli_lsarpc.h"
71 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
72 #include "libads/sitename_cache.h"
73 #include "libsmb/libsmb.h"
74 #include "libsmb/clidgram.h"
75 #include "ads.h"
76 #include "secrets.h"
77 #include "../libcli/security/security.h"
78 #include "passdb.h"
79 #include "messages.h"
80 #include "auth/gensec/gensec.h"
81 #include "../libcli/smb/smbXcli_base.h"
82 #include "libcli/auth/netlogon_creds_cli.h"
83 #include "auth.h"
84 #include "rpc_server/rpc_ncacn_np.h"
85 #include "auth/credentials/credentials.h"
86 #include "lib/param/param.h"
87 #include "lib/gencache.h"
88 #include "lib/util/string_wrappers.h"
89 #include "lib/global_contexts.h"
90 #include "librpc/gen_ndr/ndr_winbind_c.h"
91
92 #undef DBGC_CLASS
93 #define DBGC_CLASS DBGC_WINBIND
94
95 struct dc_name_ip {
96         fstring name;
97         struct sockaddr_storage ss;
98 };
99
100 extern struct winbindd_methods reconnect_methods;
101
102 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc);
103 static void set_dc_type_and_flags( struct winbindd_domain *domain );
104 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain );
105 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
106                     struct dc_name_ip **dcs, int *num_dcs,
107                     uint32_t request_flags);
108
109 void winbind_msg_domain_offline(struct messaging_context *msg_ctx,
110                                 void *private_data,
111                                 uint32_t msg_type,
112                                 struct server_id server_id,
113                                 DATA_BLOB *data)
114 {
115         const char *domain_name = (const char *)data->data;
116         struct winbindd_domain *domain;
117
118         domain = find_domain_from_name_noinit(domain_name);
119         if (domain == NULL) {
120                 DBG_DEBUG("Domain %s not found!\n", domain_name);
121                 return;
122         }
123
124         DBG_DEBUG("Domain %s was %s, change to offline now.\n",
125                   domain_name,
126                   domain->online ? "online" : "offline");
127
128         domain->online = false;
129 }
130
131 void winbind_msg_domain_online(struct messaging_context *msg_ctx,
132                                 void *private_data,
133                                 uint32_t msg_type,
134                                 struct server_id server_id,
135                                 DATA_BLOB *data)
136 {
137         const char *domain_name = (const char *)data->data;
138         struct winbindd_domain *domain;
139
140         domain = find_domain_from_name_noinit(domain_name);
141         if (domain == NULL) {
142                 return;
143         }
144
145         SMB_ASSERT(wb_child_domain() == NULL);
146
147         DBG_DEBUG("Domain %s was %s, marking as online now!\n",
148                   domain_name,
149                   domain->online ? "online" : "offline");
150
151         domain->online = true;
152 }
153
154 /****************************************************************
155  Set domain offline and also add handler to put us back online
156  if we detect a DC.
157 ****************************************************************/
158
159 void set_domain_offline(struct winbindd_domain *domain)
160 {
161         pid_t parent_pid = getppid();
162
163         DEBUG(10,("set_domain_offline: called for domain %s\n",
164                 domain->name ));
165
166         if (domain->internal) {
167                 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
168                         domain->name ));
169                 return;
170         }
171
172         domain->online = False;
173
174         /* Offline domains are always initialized. They're
175            re-initialized when they go back online. */
176
177         domain->initialized = True;
178
179         /* Send a message to the parent that the domain is offline. */
180         if (parent_pid > 1 && !domain->internal) {
181                 messaging_send_buf(global_messaging_context(),
182                                    pid_to_procid(parent_pid),
183                                    MSG_WINBIND_DOMAIN_OFFLINE,
184                                    (uint8_t *)domain->name,
185                                    strlen(domain->name) + 1);
186         }
187
188         /* Send an offline message to the idmap child when our
189            primary domain goes offline */
190         if ( domain->primary ) {
191                 pid_t idmap_pid = idmap_child_pid();
192
193                 if (idmap_pid != 0) {
194                         messaging_send_buf(global_messaging_context(),
195                                            pid_to_procid(idmap_pid),
196                                            MSG_WINBIND_OFFLINE,
197                                            (const uint8_t *)domain->name,
198                                            strlen(domain->name)+1);
199                 }
200         }
201
202         return;
203 }
204
205 /****************************************************************
206  Set domain online - if allowed.
207 ****************************************************************/
208
209 static void set_domain_online(struct winbindd_domain *domain)
210 {
211         pid_t parent_pid = getppid();
212
213         DEBUG(10,("set_domain_online: called for domain %s\n",
214                 domain->name ));
215
216         if (domain->internal) {
217                 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
218                         domain->name ));
219                 return;
220         }
221
222         if (get_global_winbindd_state_offline()) {
223                 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
224                         domain->name ));
225                 return;
226         }
227
228         winbindd_set_locator_kdc_envs(domain);
229
230         /* If we are waiting to get a krb5 ticket, trigger immediately. */
231         ccache_regain_all_now();
232
233         /* Ok, we're out of any startup mode now... */
234         domain->startup = False;
235
236         if (domain->online == False) {
237                 /* We were offline - now we're online. We default to
238                    using the MS-RPC backend if we started offline,
239                    and if we're going online for the first time we
240                    should really re-initialize the backends and the
241                    checks to see if we're talking to an AD or NT domain.
242                 */
243
244                 domain->initialized = False;
245
246                 /* 'reconnect_methods' is the MS-RPC backend. */
247                 if (domain->backend == &reconnect_methods) {
248                         domain->backend = NULL;
249                 }
250         }
251
252         domain->online = True;
253
254         /* Send a message to the parent that the domain is online. */
255         if (parent_pid > 1 && !domain->internal) {
256                 messaging_send_buf(global_messaging_context(),
257                                    pid_to_procid(parent_pid),
258                                    MSG_WINBIND_DOMAIN_ONLINE,
259                                    (uint8_t *)domain->name,
260                                    strlen(domain->name) + 1);
261         }
262
263         /* Send an online message to the idmap child when our
264            primary domain comes online */
265
266         if ( domain->primary ) {
267                 pid_t idmap_pid = idmap_child_pid();
268
269                 if (idmap_pid != 0) {
270                         messaging_send_buf(global_messaging_context(),
271                                            pid_to_procid(idmap_pid),
272                                            MSG_WINBIND_ONLINE,
273                                            (const uint8_t *)domain->name,
274                                            strlen(domain->name)+1);
275                 }
276         }
277
278         return;
279 }
280
281 /****************************************************************
282  Requested to set a domain online.
283 ****************************************************************/
284
285 void set_domain_online_request(struct winbindd_domain *domain)
286 {
287         NTSTATUS status;
288
289         SMB_ASSERT(wb_child_domain() || idmap_child());
290
291         DEBUG(10,("set_domain_online_request: called for domain %s\n",
292                 domain->name ));
293
294         if (get_global_winbindd_state_offline()) {
295                 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
296                         domain->name ));
297                 return;
298         }
299
300         if (domain->internal) {
301                 DEBUG(10, ("set_domain_online_request: Internal domains are "
302                            "always online\n"));
303                 return;
304         }
305
306         /*
307          * This call takes care of setting the online flag to true if we
308          * connected, or tell the parent to ping us back if false. Bypasses
309          * online check so always does network calls.
310          */
311         status = init_dc_connection_network(domain, true);
312         DBG_DEBUG("init_dc_connection_network(), returned %s, called for "
313                   "domain %s (online = %s)\n",
314                   nt_errstr(status),
315                   domain->name,
316                   domain->online ? "true" : "false");
317 }
318
319 /****************************************************************
320  Add -ve connection cache entries for domain and realm.
321 ****************************************************************/
322
323 static void winbind_add_failed_connection_entry(
324         const struct winbindd_domain *domain,
325         const char *server,
326         NTSTATUS result)
327 {
328         add_failed_connection_entry(domain->name, server, result);
329         /* If this was the saf name for the last thing we talked to,
330            remove it. */
331         saf_delete(domain->name);
332         if (domain->alt_name != NULL) {
333                 add_failed_connection_entry(domain->alt_name, server, result);
334                 saf_delete(domain->alt_name);
335         }
336         winbindd_unset_locator_kdc_env(domain);
337 }
338
339 /* Choose between anonymous or authenticated connections.  We need to use
340    an authenticated connection if DCs have the RestrictAnonymous registry
341    entry set > 0, or the "Additional restrictions for anonymous
342    connections" set in the win2k Local Security Policy.
343
344    Caller to free() result in domain, username, password
345 */
346
347 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
348 {
349         *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
350         *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
351         *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
352
353         if (*username && **username) {
354
355                 if (!*domain || !**domain)
356                         *domain = smb_xstrdup(lp_workgroup());
357
358                 if (!*password || !**password)
359                         *password = smb_xstrdup("");
360
361                 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
362                           *domain, *username));
363
364         } else {
365                 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
366                 *username = smb_xstrdup("");
367                 *domain = smb_xstrdup("");
368                 *password = smb_xstrdup("");
369         }
370 }
371
372 static NTSTATUS cm_get_ipc_credentials(TALLOC_CTX *mem_ctx,
373                                        struct cli_credentials **_creds)
374 {
375
376         TALLOC_CTX *frame = talloc_stackframe();
377         NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
378         struct loadparm_context *lp_ctx;
379         char *username = NULL;
380         char *netbios_domain = NULL;
381         char *password = NULL;
382         struct cli_credentials *creds = NULL;
383         bool ok;
384
385         cm_get_ipc_userpass(&username, &netbios_domain, &password);
386
387         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
388         if (lp_ctx == NULL) {
389                 DEBUG(1, ("loadparm_init_s3 failed\n"));
390                 status = NT_STATUS_INTERNAL_ERROR;
391                 goto fail;
392         }
393
394         creds = cli_credentials_init(mem_ctx);
395         if (creds == NULL) {
396                 status = NT_STATUS_NO_MEMORY;
397                 goto fail;
398         }
399
400         ok = cli_credentials_set_conf(creds, lp_ctx);
401         if (!ok) {
402                 status = NT_STATUS_INTERNAL_ERROR;
403                 goto fail;
404         }
405
406         cli_credentials_set_kerberos_state(creds,
407                                            CRED_USE_KERBEROS_DISABLED,
408                                            CRED_SPECIFIED);
409
410         ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
411         if (!ok) {
412                 status = NT_STATUS_NO_MEMORY;
413                 goto fail;
414         }
415
416         ok = cli_credentials_set_username(creds, username, CRED_SPECIFIED);
417         if (!ok) {
418                 status = NT_STATUS_NO_MEMORY;
419                 goto fail;
420         }
421
422         ok = cli_credentials_set_password(creds, password, CRED_SPECIFIED);
423         if (!ok) {
424                 status = NT_STATUS_NO_MEMORY;
425                 goto fail;
426         }
427
428         *_creds = creds;
429         creds = NULL;
430         status = NT_STATUS_OK;
431  fail:
432         TALLOC_FREE(creds);
433         SAFE_FREE(username);
434         SAFE_FREE(netbios_domain);
435         SAFE_FREE(password);
436         TALLOC_FREE(frame);
437         return status;
438 }
439
440 static bool cm_is_ipc_credentials(struct cli_credentials *creds)
441 {
442         TALLOC_CTX *frame = talloc_stackframe();
443         char *ipc_account = NULL;
444         char *ipc_domain = NULL;
445         char *ipc_password = NULL;
446         const char *creds_account = NULL;
447         const char *creds_domain = NULL;
448         const char *creds_password = NULL;
449         bool ret = false;
450
451         cm_get_ipc_userpass(&ipc_account, &ipc_domain, &ipc_password);
452
453         creds_account = cli_credentials_get_username(creds);
454         creds_domain = cli_credentials_get_domain(creds);
455         creds_password = cli_credentials_get_password(creds);
456
457         if (!strequal(ipc_domain, creds_domain)) {
458                 goto done;
459         }
460
461         if (!strequal(ipc_account, creds_account)) {
462                 goto done;
463         }
464
465         if (!strcsequal(ipc_password, creds_password)) {
466                 goto done;
467         }
468
469         ret = true;
470  done:
471         SAFE_FREE(ipc_account);
472         SAFE_FREE(ipc_domain);
473         SAFE_FREE(ipc_password);
474         TALLOC_FREE(frame);
475         return ret;
476 }
477
478 static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
479                                      fstring dcname,
480                                      struct sockaddr_storage *dc_ss,
481                                      uint32_t request_flags)
482 {
483         struct winbindd_domain *our_domain = NULL;
484         struct rpc_pipe_client *netlogon_pipe = NULL;
485         NTSTATUS result;
486         WERROR werr;
487         TALLOC_CTX *mem_ctx;
488         unsigned int orig_timeout;
489         const char *tmp = NULL;
490         const char *p;
491         struct dcerpc_binding_handle *b;
492
493         /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
494          * moment.... */
495
496         if (IS_DC) {
497                 return False;
498         }
499
500         if (domain->primary) {
501                 return False;
502         }
503
504         our_domain = find_our_domain();
505
506         if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
507                 return False;
508         }
509
510         result = cm_connect_netlogon(our_domain, &netlogon_pipe);
511         if (!NT_STATUS_IS_OK(result)) {
512                 talloc_destroy(mem_ctx);
513                 return False;
514         }
515
516         b = netlogon_pipe->binding_handle;
517
518         /* This call can take a long time - allow the server to time out.
519            35 seconds should do it. */
520
521         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
522
523         if (our_domain->active_directory) {
524                 struct netr_DsRGetDCNameInfo *domain_info = NULL;
525
526                 /*
527                  * TODO request flags are not respected in the server
528                  * (and in some cases, like REQUIRE_PDC, causes an error)
529                  */
530                 result = dcerpc_netr_DsRGetDCName(b,
531                                                   mem_ctx,
532                                                   our_domain->dcname,
533                                                   domain->name,
534                                                   NULL,
535                                                   NULL,
536                                                   request_flags|DS_RETURN_DNS_NAME,
537                                                   &domain_info,
538                                                   &werr);
539                 if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
540                         tmp = talloc_strdup(
541                                 mem_ctx, domain_info->dc_unc);
542                         if (tmp == NULL) {
543                                 DBG_ERR("talloc_strdup failed for dc_unc[%s]\n",
544                                         domain_info->dc_unc);
545                                 talloc_destroy(mem_ctx);
546                                 return false;
547                         }
548                         if (domain->alt_name == NULL) {
549                                 domain->alt_name = talloc_strdup(domain,
550                                                                  domain_info->domain_name);
551                                 if (domain->alt_name == NULL) {
552                                         DBG_ERR("talloc_strdup failed for "
553                                                 "domain_info->domain_name[%s]\n",
554                                                 domain_info->domain_name);
555                                         talloc_destroy(mem_ctx);
556                                         return false;
557                                 }
558                         }
559                         if (domain->forest_name == NULL) {
560                                 domain->forest_name = talloc_strdup(domain,
561                                                                     domain_info->forest_name);
562                                 if (domain->forest_name == NULL) {
563                                         DBG_ERR("talloc_strdup failed for "
564                                                 "domain_info->forest_name[%s]\n",
565                                                 domain_info->forest_name);
566                                         talloc_destroy(mem_ctx);
567                                         return false;
568                                 }
569                         }
570                 }
571         } else {
572                 result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
573                                                   our_domain->dcname,
574                                                   domain->name,
575                                                   &tmp,
576                                                   &werr);
577         }
578
579         /* And restore our original timeout. */
580         rpccli_set_timeout(netlogon_pipe, orig_timeout);
581
582         if (!NT_STATUS_IS_OK(result)) {
583                 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
584                         nt_errstr(result)));
585                 talloc_destroy(mem_ctx);
586                 return false;
587         }
588
589         if (!W_ERROR_IS_OK(werr)) {
590                 DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
591                            win_errstr(werr)));
592                 talloc_destroy(mem_ctx);
593                 return false;
594         }
595
596         /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
597         p = strip_hostname(tmp);
598
599         fstrcpy(dcname, p);
600
601         talloc_destroy(mem_ctx);
602
603         DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
604
605         if (!resolve_name(dcname, dc_ss, 0x20, true)) {
606                 return False;
607         }
608
609         return True;
610 }
611
612 /**
613  * Helper function to assemble trust password and account name
614  */
615 NTSTATUS winbindd_get_trust_credentials(struct winbindd_domain *domain,
616                                         TALLOC_CTX *mem_ctx,
617                                         bool netlogon,
618                                         bool allow_ipc_fallback,
619                                         struct cli_credentials **_creds)
620 {
621         const struct winbindd_domain *creds_domain = NULL;
622         struct cli_credentials *creds;
623         NTSTATUS status;
624         bool force_machine_account = false;
625
626         /* If we are a DC and this is not our own domain */
627
628         if (!domain->active_directory) {
629                 if (!netlogon) {
630                         /*
631                          * For non active directory domains
632                          * we can only use NTLMSSP for SMB.
633                          *
634                          * But the trust account is not allowed
635                          * to use SMB with NTLMSSP.
636                          */
637                         force_machine_account = true;
638                 }
639         }
640
641         if (IS_DC && !force_machine_account) {
642                 creds_domain = domain;
643         } else {
644                 creds_domain = find_our_domain();
645                 if (creds_domain == NULL) {
646                         return NT_STATUS_INVALID_SERVER_STATE;
647                 }
648         }
649
650         status = pdb_get_trust_credentials(creds_domain->name,
651                                            creds_domain->alt_name,
652                                            mem_ctx,
653                                            &creds);
654         if (!NT_STATUS_IS_OK(status)) {
655                 goto ipc_fallback;
656         }
657
658         if (creds_domain != domain) {
659                 /*
660                  * We can only use schannel against a direct trust
661                  */
662                 cli_credentials_set_secure_channel_type(creds,
663                                                         SEC_CHAN_NULL);
664         }
665
666         *_creds = creds;
667         return NT_STATUS_OK;
668
669  ipc_fallback:
670         if (netlogon) {
671                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
672         }
673
674         if (!allow_ipc_fallback) {
675                 return status;
676         }
677
678         status = cm_get_ipc_credentials(mem_ctx, &creds);
679         if (!NT_STATUS_IS_OK(status)) {
680                 return status;
681         }
682
683         *_creds = creds;
684         return NT_STATUS_OK;
685 }
686
687 /************************************************************************
688  Given a fd with a just-connected TCP connection to a DC, open a connection
689  to the pipe.
690 ************************************************************************/
691
692 static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
693                                       const int sockfd,
694                                       const char *controller,
695                                       struct cli_state **cli,
696                                       bool *retry)
697 {
698         bool try_ipc_auth = false;
699         const char *machine_principal = NULL;
700         const char *machine_realm = NULL;
701         const char *machine_account = NULL;
702         const char *machine_domain = NULL;
703         int flags = 0;
704         struct cli_credentials *creds = NULL;
705
706         struct named_mutex *mutex;
707
708         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
709         NTSTATUS tmp_status;
710         NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
711
712         enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
713
714         if (IS_DC) {
715                 if (domain->secure_channel_type == SEC_CHAN_NULL) {
716                         /*
717                          * Make sure we don't even try to
718                          * connect to a foreign domain
719                          * without a direct outbound trust.
720                          */
721                         close(sockfd);
722                         return NT_STATUS_NO_TRUST_LSA_SECRET;
723                 }
724
725                 /*
726                  * As AD DC we only use netlogon and lsa
727                  * using schannel over an anonymous transport
728                  * (ncacn_ip_tcp or ncacn_np).
729                  *
730                  * Currently we always establish the SMB connection,
731                  * even if we don't use it, because we later use ncacn_ip_tcp.
732                  *
733                  * As we won't use the SMB connection there's no
734                  * need to try kerberos. And NT4 domains expect
735                  * an anonymous IPC$ connection anyway.
736                  */
737                 smb_sign_client_connections = SMB_SIGNING_OFF;
738         }
739
740         if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
741                 /*
742                  * If we are connecting to our own AD domain, require
743                  * smb signing to disrupt MITM attacks
744                  */
745                 if (domain->primary && lp_security() == SEC_ADS) {
746                         smb_sign_client_connections = SMB_SIGNING_REQUIRED;
747                 /*
748                  * If we are in or are an AD domain and connecting to another
749                  * AD domain in our forest
750                  * then require smb signing to disrupt MITM attacks
751                  */
752                 } else if ((lp_security() == SEC_ADS)
753                            && domain->active_directory
754                            && (domain->domain_trust_attribs
755                                & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
756                         smb_sign_client_connections = SMB_SIGNING_REQUIRED;
757                 }
758         }
759
760         DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
761                 controller, domain->name ));
762
763         *retry = True;
764
765         mutex = grab_named_mutex(talloc_tos(), controller,
766                                  WINBIND_SERVER_MUTEX_WAIT_TIME);
767         if (mutex == NULL) {
768                 close(sockfd);
769                 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
770                          controller));
771                 result = NT_STATUS_POSSIBLE_DEADLOCK;
772                 goto done;
773         }
774
775         /*
776          * cm_prepare_connection() is responsible that sockfd does not leak.
777          * Once cli_state_create() returns with success, the
778          * smbXcli_conn_destructor() makes sure that close(sockfd) is finally
779          * called. Till that, close(sockfd) must be called on every unsuccessful
780          * return.
781          */
782         *cli = cli_state_create(NULL, sockfd, controller,
783                                 smb_sign_client_connections, flags);
784         if (*cli == NULL) {
785                 close(sockfd);
786                 DEBUG(1, ("Could not cli_initialize\n"));
787                 result = NT_STATUS_NO_MEMORY;
788                 goto done;
789         }
790
791         cli_set_timeout(*cli, 10000); /* 10 seconds */
792
793         set_socket_options(sockfd, lp_socket_options());
794
795         result = smbXcli_negprot((*cli)->conn,
796                                  (*cli)->timeout,
797                                  lp_client_ipc_min_protocol(),
798                                  lp_client_ipc_max_protocol(),
799                                  NULL,
800                                  NULL,
801                                  NULL);
802
803         if (!NT_STATUS_IS_OK(result)) {
804                 DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
805                 goto done;
806         }
807
808         if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
809             smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
810                 try_ipc_auth = true;
811         } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
812                 try_ipc_auth = true;
813         } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
814                 /*
815                  * If we are forcing on SMB signing, then we must
816                  * require authentication unless this is a one-way
817                  * trust, and we have no stored user/password
818                  */
819                 try_ipc_auth = true;
820         }
821
822         if (IS_DC) {
823                 /*
824                  * As AD DC we only use netlogon and lsa
825                  * using schannel over an anonymous transport
826                  * (ncacn_ip_tcp or ncacn_np).
827                  *
828                  * Currently we always establish the SMB connection,
829                  * even if we don't use it, because we later use ncacn_ip_tcp.
830                  *
831                  * As we won't use the SMB connection there's no
832                  * need to try kerberos. And NT4 domains expect
833                  * an anonymous IPC$ connection anyway.
834                  */
835                 try_ipc_auth = false;
836         }
837
838         if (try_ipc_auth) {
839                 result = winbindd_get_trust_credentials(domain,
840                                                         talloc_tos(),
841                                                         false, /* netlogon */
842                                                         true, /* ipc_fallback */
843                                                         &creds);
844                 if (!NT_STATUS_IS_OK(result)) {
845                         DBG_WARNING("winbindd_get_trust_credentials(%s) "
846                                     "failed: %s\n",
847                                     domain->name,
848                                     nt_errstr(result));
849                         goto done;
850                 }
851         } else {
852                 /*
853                  * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
854                  * would try and authentication with our machine
855                  * account password and fail.  This is very rare in
856                  * the modern world however
857                  */
858                 creds = cli_credentials_init_anon(talloc_tos());
859                 if (creds == NULL) {
860                         result = NT_STATUS_NO_MEMORY;
861                         DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
862                                   domain->name, nt_errstr(result)));
863                         goto done;
864                 }
865         }
866
867         machine_principal = cli_credentials_get_principal(creds,
868                                                         talloc_tos());
869         machine_realm = cli_credentials_get_realm(creds);
870         machine_account = cli_credentials_get_username(creds);
871         machine_domain = cli_credentials_get_domain(creds);
872
873         DEBUG(5, ("connecting to %s (%s, %s) with account [%s\\%s] principal "
874                   "[%s] and realm [%s]\n",
875                   controller, domain->name, domain->alt_name,
876                   machine_domain, machine_account,
877                   machine_principal, machine_realm));
878
879         if (cli_credentials_is_anonymous(creds)) {
880                 goto anon_fallback;
881         }
882
883         winbindd_set_locator_kdc_envs(domain);
884
885         result = cli_session_setup_creds(*cli, creds);
886         if (NT_STATUS_IS_OK(result)) {
887                 goto session_setup_done;
888         }
889
890         DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
891                   controller,
892                   cli_credentials_get_unparsed_name(creds, talloc_tos()),
893                   nt_errstr(result)));
894
895         /*
896          * If we are not going to validate the connection
897          * with SMB signing, then allow us to fall back to
898          * anonymous
899          */
900         if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
901             || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
902             || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
903             || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_COMPUTER_NAME)
904             || NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_DOMAIN)
905             || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
906             || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
907         {
908                 if (!cm_is_ipc_credentials(creds)) {
909                         goto ipc_fallback;
910                 }
911
912                 if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
913                         goto done;
914                 }
915
916                 goto anon_fallback;
917         }
918
919         goto done;
920
921  ipc_fallback:
922         TALLOC_FREE(creds);
923         tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
924         if (!NT_STATUS_IS_OK(tmp_status)) {
925                 result = tmp_status;
926                 goto done;
927         }
928
929         if (cli_credentials_is_anonymous(creds)) {
930                 goto anon_fallback;
931         }
932
933         machine_account = cli_credentials_get_username(creds);
934         machine_domain = cli_credentials_get_domain(creds);
935
936         DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
937                   "[%s]\\[%s]\n",  controller, lp_netbios_name(),
938                   machine_domain, machine_account));
939
940         result = cli_session_setup_creds(*cli, creds);
941         if (NT_STATUS_IS_OK(result)) {
942                 goto session_setup_done;
943         }
944
945         DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
946                   controller,
947                   cli_credentials_get_unparsed_name(creds, talloc_tos()),
948                   nt_errstr(result)));
949
950         /*
951          * If we are not going to validate the connection
952          * with SMB signing, then allow us to fall back to
953          * anonymous
954          */
955         if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
956             || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
957             || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
958             || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_COMPUTER_NAME)
959             || NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_DOMAIN)
960             || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
961             || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
962         {
963                 goto anon_fallback;
964         }
965
966         goto done;
967
968  anon_fallback:
969         TALLOC_FREE(creds);
970
971         if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
972                 goto done;
973         }
974
975         /* Fall back to anonymous connection, this might fail later */
976         DEBUG(5,("cm_prepare_connection: falling back to anonymous "
977                 "connection for DC %s\n",
978                 controller ));
979
980         result = cli_session_setup_anon(*cli);
981         if (NT_STATUS_IS_OK(result)) {
982                 DEBUG(5, ("Connected anonymously\n"));
983                 goto session_setup_done;
984         }
985
986         DEBUG(1, ("anonymous session setup to %s failed with %s\n",
987                   controller, nt_errstr(result)));
988
989         /* We can't session setup */
990         goto done;
991
992  session_setup_done:
993         TALLOC_FREE(creds);
994
995         /*
996          * This should be a short term hack until
997          * dynamic re-authentication is implemented.
998          *
999          * See Bug 9175 - winbindd doesn't recover from
1000          * NT_STATUS_NETWORK_SESSION_EXPIRED
1001          */
1002         if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
1003                 smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
1004         }
1005
1006         result = cli_tree_connect(*cli, "IPC$", "IPC", NULL);
1007         if (!NT_STATUS_IS_OK(result)) {
1008                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
1009                 goto done;
1010         }
1011         tcon_status = result;
1012
1013         /* cache the server name for later connections */
1014
1015         saf_store(domain->name, controller);
1016         if (domain->alt_name) {
1017                 saf_store(domain->alt_name, controller);
1018         }
1019
1020         winbindd_set_locator_kdc_envs(domain);
1021
1022         TALLOC_FREE(mutex);
1023         *retry = False;
1024
1025         result = NT_STATUS_OK;
1026
1027  done:
1028         TALLOC_FREE(mutex);
1029         TALLOC_FREE(creds);
1030
1031         if (NT_STATUS_IS_OK(result)) {
1032                 result = tcon_status;
1033         }
1034
1035         if (!NT_STATUS_IS_OK(result)) {
1036                 DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
1037                           controller, nt_errstr(result)));
1038                 winbind_add_failed_connection_entry(domain, controller, result);
1039                 if ((*cli) != NULL) {
1040                         cli_shutdown(*cli);
1041                         *cli = NULL;
1042                 }
1043         }
1044
1045         return result;
1046 }
1047
1048 /*******************************************************************
1049  Add a dcname and sockaddr_storage pair to the end of a dc_name_ip
1050  array.
1051
1052  Keeps the list unique by not adding duplicate entries.
1053
1054  @param[in] mem_ctx talloc memory context to allocate from
1055  @param[in] domain_name domain of the DC
1056  @param[in] dcname name of the DC to add to the list
1057  @param[in] pss Internet address and port pair to add to the list
1058  @param[in,out] dcs array of dc_name_ip structures to add to
1059  @param[in,out] num_dcs number of dcs returned in the dcs array
1060  @return true if the list was added to, false otherwise
1061 *******************************************************************/
1062
1063 static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
1064                               const char *dcname, struct sockaddr_storage *pss,
1065                               struct dc_name_ip **dcs, int *num)
1066 {
1067         int i = 0;
1068
1069         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
1070                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
1071                 return False;
1072         }
1073
1074         /* Make sure there's no duplicates in the list */
1075         for (i=0; i<*num; i++)
1076                 if (sockaddr_equal(
1077                             (struct sockaddr *)(void *)&(*dcs)[i].ss,
1078                             (struct sockaddr *)(void *)pss))
1079                         return False;
1080
1081         *dcs = talloc_realloc(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
1082
1083         if (*dcs == NULL)
1084                 return False;
1085
1086         fstrcpy((*dcs)[*num].name, dcname);
1087         (*dcs)[*num].ss = *pss;
1088         *num += 1;
1089         return True;
1090 }
1091
1092 static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
1093                                   struct sockaddr_storage *pss, uint16_t port,
1094                                   struct sockaddr_storage **addrs, int *num)
1095 {
1096         *addrs = talloc_realloc(mem_ctx, *addrs, struct sockaddr_storage, (*num)+1);
1097
1098         if (*addrs == NULL) {
1099                 *num = 0;
1100                 return False;
1101         }
1102
1103         (*addrs)[*num] = *pss;
1104         set_sockaddr_port((struct sockaddr *)&(*addrs)[*num], port);
1105
1106         *num += 1;
1107         return True;
1108 }
1109
1110 #ifdef HAVE_ADS
1111 static bool dcip_check_name_ads(const struct winbindd_domain *domain,
1112                                 struct samba_sockaddr *sa,
1113                                 uint32_t request_flags,
1114                                 TALLOC_CTX *mem_ctx,
1115                                 char **namep)
1116 {
1117         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1118         char *name = NULL;
1119         ADS_STRUCT *ads = NULL;
1120         ADS_STATUS ads_status;
1121         char addr[INET6_ADDRSTRLEN];
1122
1123         print_sockaddr(addr, sizeof(addr), &sa->u.ss);
1124         D_DEBUG("Trying to figure out the DC name for domain '%s' at IP '%s'.\n",
1125                 domain->name,
1126                 addr);
1127
1128         ads = ads_init(tmp_ctx,
1129                        domain->alt_name,
1130                        domain->name,
1131                        addr,
1132                        ADS_SASL_PLAIN);
1133         if (ads == NULL) {
1134                 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1135                 goto out;
1136         }
1137         ads->config.flags |= request_flags;
1138         ads->server.no_fallback = true;
1139
1140         ads_status = ads_connect_cldap_only(ads);
1141         if (!ADS_ERR_OK(ads_status)) {
1142                 goto out;
1143         }
1144
1145         /* We got a cldap packet. */
1146         name = talloc_strdup(tmp_ctx, ads->config.ldap_server_name);
1147         if (name == NULL) {
1148                 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1149                 goto out;
1150         }
1151         namecache_store(name, 0x20, 1, sa);
1152
1153         DBG_DEBUG("CLDAP flags = 0x%"PRIx32"\n", ads->config.flags);
1154
1155         if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
1156                 if (ads_closest_dc(ads)) {
1157                         char *sitename = sitename_fetch(tmp_ctx,
1158                                                         ads->config.realm);
1159
1160                         /* We're going to use this KDC for this realm/domain.
1161                            If we are using sites, then force the krb5 libs
1162                            to use this KDC. */
1163
1164                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1165                                                         domain->name,
1166                                                         sitename,
1167                                                         &sa->u.ss);
1168
1169                         TALLOC_FREE(sitename);
1170                 } else {
1171                         /* use an off site KDC */
1172                         create_local_private_krb5_conf_for_domain(domain->alt_name,
1173                                                         domain->name,
1174                                                         NULL,
1175                                                         &sa->u.ss);
1176                 }
1177                 winbindd_set_locator_kdc_envs(domain);
1178
1179                 /* Ensure we contact this DC also. */
1180                 saf_store(domain->name, name);
1181                 saf_store(domain->alt_name, name);
1182         }
1183
1184         D_DEBUG("DC name for domain '%s' at IP '%s' is '%s'\n",
1185                 domain->name,
1186                 addr,
1187                 name);
1188         *namep = talloc_move(mem_ctx, &name);
1189
1190 out:
1191         TALLOC_FREE(tmp_ctx);
1192
1193         return ADS_ERR_OK(ads_status) ? true : false;
1194 }
1195 #endif
1196
1197 /*******************************************************************
1198  convert an ip to a name
1199  For an AD Domain, it checks the requirements of the request flags.
1200 *******************************************************************/
1201
1202 static bool dcip_check_name(TALLOC_CTX *mem_ctx,
1203                             const struct winbindd_domain *domain,
1204                             struct sockaddr_storage *pss,
1205                             char **name, uint32_t request_flags)
1206 {
1207         struct samba_sockaddr sa = {0};
1208         uint32_t nt_version = NETLOGON_NT_VERSION_1;
1209         NTSTATUS status;
1210         const char *dc_name;
1211         fstring nbtname;
1212 #ifdef HAVE_ADS
1213         bool is_ad_domain = false;
1214 #endif
1215         bool ok = sockaddr_storage_to_samba_sockaddr(&sa, pss);
1216         if (!ok) {
1217                 return false;
1218         }
1219
1220 #ifdef HAVE_ADS
1221         /* For active directory servers, try to get the ldap server name.
1222            None of these failures should be considered critical for now */
1223
1224         if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
1225                 is_ad_domain = true;
1226         } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1227                 is_ad_domain = domain->active_directory;
1228         }
1229
1230         if (is_ad_domain) {
1231                 return dcip_check_name_ads(domain,
1232                                            &sa,
1233                                            request_flags,
1234                                            mem_ctx,
1235                                            name);
1236         }
1237 #endif
1238
1239         {
1240                 size_t len = strlen(lp_netbios_name());
1241                 char my_acct_name[len+2];
1242
1243                 snprintf(my_acct_name,
1244                          sizeof(my_acct_name),
1245                          "%s$",
1246                          lp_netbios_name());
1247
1248                 status = nbt_getdc(global_messaging_context(), 10, &sa.u.ss,
1249                                    domain->name, &domain->sid,
1250                                    my_acct_name, ACB_WSTRUST,
1251                                    nt_version, mem_ctx, &nt_version,
1252                                    &dc_name, NULL);
1253         }
1254         if (NT_STATUS_IS_OK(status)) {
1255                 *name = talloc_strdup(mem_ctx, dc_name);
1256                 if (*name == NULL) {
1257                         return false;
1258                 }
1259                 namecache_store(*name, 0x20, 1, &sa);
1260                 return True;
1261         }
1262
1263         /* try node status request */
1264
1265         if (name_status_find(domain->name, 0x1c, 0x20, &sa.u.ss, nbtname) ) {
1266                 namecache_store(nbtname, 0x20, 1, &sa);
1267
1268                 if (name != NULL) {
1269                         *name = talloc_strdup(mem_ctx, nbtname);
1270                         if (*name == NULL) {
1271                                 return false;
1272                         }
1273                 }
1274
1275                 return true;
1276         }
1277         return False;
1278 }
1279
1280 /*******************************************************************
1281  Retrieve a list of IP addresses for domain controllers.
1282
1283  The array is sorted in the preferred connection order.
1284
1285  @param[in] mem_ctx talloc memory context to allocate from
1286  @param[in] domain domain to retrieve DCs for
1287  @param[out] dcs array of dcs that will be returned
1288  @param[out] num_dcs number of dcs returned in the dcs array
1289  @return always true
1290 *******************************************************************/
1291
1292 static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1293                     struct dc_name_ip **dcs, int *num_dcs,
1294                     uint32_t request_flags)
1295 {
1296         fstring dcname;
1297         struct  sockaddr_storage ss;
1298         struct  samba_sockaddr *sa_list = NULL;
1299         size_t     salist_size = 0;
1300         size_t     i;
1301         bool    is_our_domain;
1302         enum security_types sec = (enum security_types)lp_security();
1303
1304         is_our_domain = strequal(domain->name, lp_workgroup());
1305
1306         /* If not our domain, get the preferred DC, by asking our primary DC */
1307         if ( !is_our_domain
1308                 && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
1309                 && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
1310                        num_dcs) )
1311         {
1312                 char addr[INET6_ADDRSTRLEN];
1313                 print_sockaddr(addr, sizeof(addr), &ss);
1314                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
1315                            dcname, addr));
1316                 return True;
1317         }
1318
1319         if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
1320                 char *sitename = NULL;
1321
1322                 /* We need to make sure we know the local site before
1323                    doing any DNS queries, as this will restrict the
1324                    get_sorted_dc_list() call below to only fetching
1325                    DNS records for the correct site. */
1326
1327                 /* Find any DC to get the site record.
1328                    We deliberately don't care about the
1329                    return here. */
1330
1331                 get_dc_name(domain->name, domain->alt_name, dcname, &ss);
1332
1333                 sitename = sitename_fetch(mem_ctx, domain->alt_name);
1334                 if (sitename) {
1335
1336                         /* Do the site-specific AD dns lookup first. */
1337                         (void)get_sorted_dc_list(mem_ctx,
1338                                         domain->alt_name,
1339                                         sitename,
1340                                         &sa_list,
1341                                         &salist_size,
1342                                         true);
1343
1344                         /* Add ips to the DC array.  We don't look up the name
1345                            of the DC in this function, but we fill in the char*
1346                            of the ip now to make the failed connection cache
1347                            work */
1348                         for ( i=0; i<salist_size; i++ ) {
1349                                 char addr[INET6_ADDRSTRLEN];
1350                                 print_sockaddr(addr, sizeof(addr),
1351                                                 &sa_list[i].u.ss);
1352                                 add_one_dc_unique(mem_ctx,
1353                                                 domain->name,
1354                                                 addr,
1355                                                 &sa_list[i].u.ss,
1356                                                 dcs,
1357                                                 num_dcs);
1358                         }
1359
1360                         TALLOC_FREE(sa_list);
1361                         TALLOC_FREE(sitename);
1362                         salist_size = 0;
1363                 }
1364
1365                 /* Now we add DCs from the main AD DNS lookup. */
1366                 (void)get_sorted_dc_list(mem_ctx,
1367                                 domain->alt_name,
1368                                 NULL,
1369                                 &sa_list,
1370                                 &salist_size,
1371                                 true);
1372
1373                 for ( i=0; i<salist_size; i++ ) {
1374                         char addr[INET6_ADDRSTRLEN];
1375                         print_sockaddr(addr, sizeof(addr),
1376                                         &sa_list[i].u.ss);
1377                         add_one_dc_unique(mem_ctx,
1378                                         domain->name,
1379                                         addr,
1380                                         &sa_list[i].u.ss,
1381                                         dcs,
1382                                         num_dcs);
1383                 }
1384
1385                 TALLOC_FREE(sa_list);
1386                 salist_size = 0;
1387         }
1388
1389         /* Try standard netbios queries if no ADS and fall back to DNS queries
1390          * if alt_name is available */
1391         if (*num_dcs == 0) {
1392                 (void)get_sorted_dc_list(mem_ctx,
1393                                         domain->name,
1394                                         NULL,
1395                                         &sa_list,
1396                                         &salist_size,
1397                                         false);
1398                 if (salist_size == 0) {
1399                         if (domain->alt_name != NULL) {
1400                                 (void)get_sorted_dc_list(mem_ctx,
1401                                                 domain->alt_name,
1402                                                 NULL,
1403                                                 &sa_list,
1404                                                 &salist_size,
1405                                                 true);
1406                         }
1407                 }
1408
1409                 for ( i=0; i<salist_size; i++ ) {
1410                         char addr[INET6_ADDRSTRLEN];
1411                         print_sockaddr(addr, sizeof(addr),
1412                                         &sa_list[i].u.ss);
1413                         add_one_dc_unique(mem_ctx,
1414                                         domain->name,
1415                                         addr,
1416                                         &sa_list[i].u.ss,
1417                                         dcs,
1418                                         num_dcs);
1419                 }
1420
1421                 TALLOC_FREE(sa_list);
1422                 salist_size = 0;
1423         }
1424
1425         return True;
1426 }
1427
1428 static bool connect_preferred_dc(TALLOC_CTX *mem_ctx,
1429                                  struct winbindd_domain *domain,
1430                                  uint32_t request_flags,
1431                                  int *fd)
1432 {
1433         char *saf_servername = NULL;
1434         NTSTATUS status;
1435         bool ok;
1436
1437         /*
1438          * We have to check the server affinity cache here since later we select
1439          * a DC based on response time and not preference.
1440          */
1441         if (domain->force_dc) {
1442                 saf_servername = domain->dcname;
1443         } else {
1444                 saf_servername = saf_fetch(mem_ctx, domain->name);
1445         }
1446
1447         /*
1448          * Check the negative connection cache before talking to it. It going
1449          * down may have triggered the reconnection.
1450          */
1451         if (saf_servername != NULL) {
1452                 status = check_negative_conn_cache(domain->name,
1453                                                    saf_servername);
1454                 if (!NT_STATUS_IS_OK(status)) {
1455                         saf_servername = NULL;
1456                 }
1457         }
1458
1459         if (saf_servername != NULL) {
1460                 DBG_DEBUG("saf_servername is '%s' for domain %s\n",
1461                           saf_servername, domain->name);
1462
1463                 /* convert an ip address to a name */
1464                 if (is_ipaddress(saf_servername)) {
1465                         ok = interpret_string_addr(&domain->dcaddr,
1466                                                    saf_servername,
1467                                                    AI_NUMERICHOST);
1468                         if (!ok) {
1469                                 return false;
1470                         }
1471                 } else {
1472                         ok = resolve_name(saf_servername,
1473                                           &domain->dcaddr,
1474                                           0x20,
1475                                           true);
1476                         if (!ok) {
1477                                 goto fail;
1478                         }
1479                 }
1480
1481                 TALLOC_FREE(domain->dcname);
1482                 ok = dcip_check_name(domain,
1483                                      domain,
1484                                      &domain->dcaddr,
1485                                      &domain->dcname,
1486                                      request_flags);
1487                 if (!ok) {
1488                         goto fail;
1489                 }
1490         }
1491
1492         if (domain->dcname == NULL) {
1493                 return false;
1494         }
1495
1496         status = check_negative_conn_cache(domain->name, domain->dcname);
1497         if (!NT_STATUS_IS_OK(status)) {
1498                 return false;
1499         }
1500
1501         status = smbsock_connect(&domain->dcaddr, 0,
1502                                  NULL, -1, NULL, -1,
1503                                  fd, NULL, 10);
1504         if (!NT_STATUS_IS_OK(status)) {
1505                 winbind_add_failed_connection_entry(domain,
1506                                                     domain->dcname,
1507                                                     NT_STATUS_UNSUCCESSFUL);
1508                 return false;
1509         }
1510         return true;
1511
1512 fail:
1513         winbind_add_failed_connection_entry(domain,
1514                                             saf_servername,
1515                                             NT_STATUS_UNSUCCESSFUL);
1516         return false;
1517
1518 }
1519
1520 /*******************************************************************
1521  Find and make a connection to a DC in the given domain.
1522
1523  @param[in] mem_ctx talloc memory context to allocate from
1524  @param[in] domain domain to find a dc in
1525  @param[out] fd fd of the open socket connected to the newly found dc
1526  @return true when a DC connection is made, false otherwise
1527 *******************************************************************/
1528
1529 static bool find_dc(TALLOC_CTX *mem_ctx,
1530                     struct winbindd_domain *domain,
1531                     uint32_t request_flags,
1532                     int *fd)
1533 {
1534         struct dc_name_ip *dcs = NULL;
1535         int num_dcs = 0;
1536
1537         const char **dcnames = NULL;
1538         size_t num_dcnames = 0;
1539
1540         struct sockaddr_storage *addrs = NULL;
1541         int num_addrs = 0;
1542
1543         int i;
1544         size_t fd_index;
1545
1546         NTSTATUS status;
1547         bool ok;
1548
1549         *fd = -1;
1550
1551         D_NOTICE("First try to connect to the closest DC (using server "
1552                  "affinity cache). If this fails, try to lookup the DC using "
1553                  "DNS afterwards.\n");
1554         ok = connect_preferred_dc(mem_ctx, domain, request_flags, fd);
1555         if (ok) {
1556                 return true;
1557         }
1558
1559         if (domain->force_dc) {
1560                 return false;
1561         }
1562
1563  again:
1564         D_DEBUG("Retrieving a list of IP addresses for DCs.\n");
1565         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs, request_flags) || (num_dcs == 0))
1566                 return False;
1567
1568         D_DEBUG("Retrieved IP addresses for %d DCs.\n", num_dcs);
1569         for (i=0; i<num_dcs; i++) {
1570
1571                 if (!add_string_to_array(mem_ctx, dcs[i].name,
1572                                     &dcnames, &num_dcnames)) {
1573                         return False;
1574                 }
1575                 if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, TCP_SMB_PORT,
1576                                       &addrs, &num_addrs)) {
1577                         return False;
1578                 }
1579         }
1580
1581         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
1582                 return False;
1583
1584         if ((addrs == NULL) || (dcnames == NULL))
1585                 return False;
1586
1587         D_DEBUG("Trying to establish a connection to one of the %d DCs "
1588                 "(timeout of 10 sec for each DC).\n",
1589                 num_dcs);
1590         status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
1591                                      num_addrs, 0, 10, fd, &fd_index, NULL);
1592         if (!NT_STATUS_IS_OK(status)) {
1593                 for (i=0; i<num_dcs; i++) {
1594                         char ab[INET6_ADDRSTRLEN];
1595                         print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
1596                         DBG_DEBUG("smbsock_any_connect failed for "
1597                                 "domain %s address %s. Error was %s\n",
1598                                    domain->name, ab, nt_errstr(status));
1599                         winbind_add_failed_connection_entry(domain,
1600                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
1601                 }
1602                 return False;
1603         }
1604         D_NOTICE("Successfully connected to DC '%s'.\n", dcs[fd_index].name);
1605
1606         domain->dcaddr = addrs[fd_index];
1607
1608         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
1609                 /* Ok, we've got a name for the DC */
1610                 TALLOC_FREE(domain->dcname);
1611                 domain->dcname = talloc_strdup(domain, dcnames[fd_index]);
1612                 if (domain->dcname == NULL) {
1613                         return false;
1614                 }
1615                 return true;
1616         }
1617
1618         /* Try to figure out the name */
1619         TALLOC_FREE(domain->dcname);
1620         ok = dcip_check_name(domain,
1621                              domain,
1622                              &domain->dcaddr,
1623                              &domain->dcname,
1624                              request_flags);
1625         if (ok) {
1626                 return true;
1627         }
1628
1629         /* We can not continue without the DC's name */
1630         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1631                                     NT_STATUS_UNSUCCESSFUL);
1632
1633         /* Throw away all arrays as we're doing this again. */
1634         TALLOC_FREE(dcs);
1635         num_dcs = 0;
1636
1637         TALLOC_FREE(dcnames);
1638         num_dcnames = 0;
1639
1640         TALLOC_FREE(addrs);
1641         num_addrs = 0;
1642
1643         if (*fd != -1) {
1644                 close(*fd);
1645                 *fd = -1;
1646         }
1647
1648         /*
1649          * This should not be an infinite loop, since get_dcs() will not return
1650          * the DC added to the negative connection cache in the above
1651          * winbind_add_failed_connection_entry() call.
1652          */
1653         goto again;
1654 }
1655
1656 static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
1657 {
1658         return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
1659                                           domain_name);
1660 }
1661
1662 static void store_current_dc_in_gencache(const char *domain_name,
1663                                          const char *dc_name,
1664                                          struct cli_state *cli)
1665 {
1666         char addr[INET6_ADDRSTRLEN];
1667         char *key = NULL;
1668         char *value = NULL;
1669
1670         if (!cli_state_is_connected(cli)) {
1671                 return;
1672         }
1673
1674         print_sockaddr(addr, sizeof(addr),
1675                        smbXcli_conn_remote_sockaddr(cli->conn));
1676
1677         key = current_dc_key(talloc_tos(), domain_name);
1678         if (key == NULL) {
1679                 goto done;
1680         }
1681
1682         value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
1683         if (value == NULL) {
1684                 goto done;
1685         }
1686
1687         gencache_set(key, value, 0x7fffffff);
1688 done:
1689         TALLOC_FREE(value);
1690         TALLOC_FREE(key);
1691 }
1692
1693 bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
1694                                     const char *domain_name,
1695                                     char **p_dc_name, char **p_dc_ip)
1696 {
1697         char *key, *p;
1698         char *value = NULL;
1699         bool ret = false;
1700         char *dc_name = NULL;
1701         char *dc_ip = NULL;
1702
1703         key = current_dc_key(talloc_tos(), domain_name);
1704         if (key == NULL) {
1705                 goto done;
1706         }
1707         if (!gencache_get(key, mem_ctx, &value, NULL)) {
1708                 goto done;
1709         }
1710         p = strchr(value, ' ');
1711         if (p == NULL) {
1712                 goto done;
1713         }
1714         dc_ip = talloc_strndup(mem_ctx, value, p - value);
1715         if (dc_ip == NULL) {
1716                 goto done;
1717         }
1718         dc_name = talloc_strdup(mem_ctx, p+1);
1719         if (dc_name == NULL) {
1720                 goto done;
1721         }
1722
1723         if (p_dc_ip != NULL) {
1724                 *p_dc_ip = dc_ip;
1725                 dc_ip = NULL;
1726         }
1727         if (p_dc_name != NULL) {
1728                 *p_dc_name = dc_name;
1729                 dc_name = NULL;
1730         }
1731         ret = true;
1732 done:
1733         TALLOC_FREE(dc_name);
1734         TALLOC_FREE(dc_ip);
1735         TALLOC_FREE(key);
1736         TALLOC_FREE(value);
1737         return ret;
1738 }
1739
1740 NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
1741                                const struct ndr_interface_table *table,
1742                                struct rpc_pipe_client **ret_pipe)
1743 {
1744         struct rpc_pipe_client *cli = NULL;
1745         const struct auth_session_info *session_info = NULL;
1746         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1747
1748
1749         session_info = get_session_info_system();
1750         SMB_ASSERT(session_info != NULL);
1751
1752         status = rpc_pipe_open_local_np(
1753                 mem_ctx, table, NULL, NULL, NULL, NULL, session_info, &cli);
1754         if (!NT_STATUS_IS_OK(status)) {
1755                 return status;
1756         }
1757
1758         if (ret_pipe) {
1759                 *ret_pipe = cli;
1760         }
1761
1762         return NT_STATUS_OK;
1763 }
1764
1765 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1766                                    struct winbindd_cm_conn *new_conn,
1767                                    bool need_rw_dc)
1768 {
1769         TALLOC_CTX *mem_ctx;
1770         NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1771         int retries;
1772         uint32_t request_flags = need_rw_dc ? DS_WRITABLE_REQUIRED : 0;
1773         int fd = -1;
1774         bool retry = false;
1775         bool seal_pipes = true;
1776
1777         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1778                 set_domain_offline(domain);
1779                 return NT_STATUS_NO_MEMORY;
1780         }
1781
1782         D_NOTICE("Creating connection to domain controller. This is a start of "
1783                  "a new connection or a DC failover. The failover only happens "
1784                  "if the domain has more than one DC. We will try to connect 3 "
1785                  "times at most.\n");
1786         for (retries = 0; retries < 3; retries++) {
1787                 bool found_dc;
1788
1789                 D_DEBUG("Attempt %d/3: DC '%s' of domain '%s'.\n",
1790                         retries,
1791                         domain->dcname ? domain->dcname : "",
1792                         domain->name);
1793
1794                 found_dc = find_dc(mem_ctx, domain, request_flags, &fd);
1795                 if (!found_dc) {
1796                         /* This is the one place where we will
1797                            set the global winbindd offline state
1798                            to true, if a "WINBINDD_OFFLINE" entry
1799                            is found in the winbindd cache. */
1800                         set_global_winbindd_state_offline();
1801                         result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1802                         break;
1803                 }
1804
1805                 new_conn->cli = NULL;
1806
1807                 result = cm_prepare_connection(domain, fd, domain->dcname,
1808                         &new_conn->cli, &retry);
1809                 if (NT_STATUS_IS_OK(result)) {
1810                         break;
1811                 }
1812                 if (!retry) {
1813                         break;
1814                 }
1815         }
1816
1817         if (!NT_STATUS_IS_OK(result)) {
1818                 /* Ensure we setup the retry handler. */
1819                 set_domain_offline(domain);
1820                 goto out;
1821         }
1822
1823         winbindd_set_locator_kdc_envs(domain);
1824
1825         if (domain->online == False) {
1826                 /* We're changing state from offline to online. */
1827                 set_global_winbindd_state_online();
1828         }
1829         set_domain_online(domain);
1830
1831         /*
1832          * Much as I hate global state, this seems to be the point
1833          * where we can be certain that we have a proper connection to
1834          * a DC. wbinfo --dc-info needs that information, store it in
1835          * gencache with a looong timeout. This will need revisiting
1836          * once we start to connect to multiple DCs, wbcDcInfo is
1837          * already prepared for that.
1838          */
1839         store_current_dc_in_gencache(domain->name, domain->dcname,
1840                                      new_conn->cli);
1841
1842         seal_pipes = lp_winbind_sealed_pipes();
1843         seal_pipes = lp_parm_bool(-1, "winbind sealed pipes",
1844                                   domain->name,
1845                                   seal_pipes);
1846
1847         if (seal_pipes) {
1848                 new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1849         } else {
1850                 new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1851         }
1852
1853 out:
1854         talloc_destroy(mem_ctx);
1855         return result;
1856 }
1857
1858 /* Close down all open pipes on a connection. */
1859
1860 void invalidate_cm_connection(struct winbindd_domain *domain)
1861 {
1862         NTSTATUS result;
1863         struct winbindd_cm_conn *conn = &domain->conn;
1864
1865         domain->sequence_number = DOM_SEQUENCE_NONE;
1866         domain->last_seq_check = 0;
1867         domain->last_status = NT_STATUS_SERVER_DISABLED;
1868
1869         /* We're closing down a possibly dead
1870            connection. Don't have impossibly long (10s) timeouts. */
1871
1872         if (conn->cli) {
1873                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1874         }
1875
1876         if (conn->samr_pipe != NULL) {
1877                 if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
1878                         dcerpc_samr_Close(conn->samr_pipe->binding_handle,
1879                                           talloc_tos(),
1880                                           &conn->sam_connect_handle,
1881                                           &result);
1882                 }
1883                 TALLOC_FREE(conn->samr_pipe);
1884                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1885                 if (conn->cli) {
1886                         cli_set_timeout(conn->cli, 500);
1887                 }
1888         }
1889
1890         if (conn->lsa_pipe != NULL) {
1891                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1892                         dcerpc_lsa_Close(conn->lsa_pipe->binding_handle,
1893                                          talloc_tos(),
1894                                          &conn->lsa_policy,
1895                                          &result);
1896                 }
1897                 TALLOC_FREE(conn->lsa_pipe);
1898                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1899                 if (conn->cli) {
1900                         cli_set_timeout(conn->cli, 500);
1901                 }
1902         }
1903
1904         if (conn->lsa_pipe_tcp != NULL) {
1905                 if (is_valid_policy_hnd(&conn->lsa_policy)) {
1906                         dcerpc_lsa_Close(conn->lsa_pipe_tcp->binding_handle,
1907                                          talloc_tos(),
1908                                          &conn->lsa_policy,
1909                                          &result);
1910                 }
1911                 TALLOC_FREE(conn->lsa_pipe_tcp);
1912                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1913                 if (conn->cli) {
1914                         cli_set_timeout(conn->cli, 500);
1915                 }
1916         }
1917
1918         if (conn->netlogon_pipe != NULL) {
1919                 TALLOC_FREE(conn->netlogon_pipe);
1920                 /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1921                 if (conn->cli) {
1922                         cli_set_timeout(conn->cli, 500);
1923                 }
1924         }
1925
1926         conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1927         TALLOC_FREE(conn->netlogon_creds_ctx);
1928
1929         if (conn->cli) {
1930                 cli_shutdown(conn->cli);
1931         }
1932
1933         conn->cli = NULL;
1934 }
1935
1936 void close_conns_after_fork(void)
1937 {
1938         struct winbindd_domain *domain;
1939         struct winbindd_cli_state *cli_state;
1940
1941         for (domain = domain_list(); domain; domain = domain->next) {
1942                 /*
1943                  * first close the low level SMB TCP connection
1944                  * so that we don't generate any SMBclose
1945                  * requests in invalidate_cm_connection()
1946                  */
1947                 if (cli_state_is_connected(domain->conn.cli)) {
1948                         smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
1949                 }
1950
1951                 invalidate_cm_connection(domain);
1952         }
1953
1954         for (cli_state = winbindd_client_list();
1955              cli_state != NULL;
1956              cli_state = cli_state->next) {
1957                 if (cli_state->sock >= 0) {
1958                         close(cli_state->sock);
1959                         cli_state->sock = -1;
1960                 }
1961         }
1962 }
1963
1964 static bool connection_ok(struct winbindd_domain *domain)
1965 {
1966         bool ok;
1967
1968         ok = cli_state_is_connected(domain->conn.cli);
1969         if (!ok) {
1970                 DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n",
1971                           domain->dcname, domain->name));
1972                 return False;
1973         }
1974
1975         if (!domain->online) {
1976                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1977                 return False;
1978         }
1979
1980         return True;
1981 }
1982
1983 /* Initialize a new connection up to the RPC BIND.
1984    Bypass online status check so always does network calls. */
1985
1986 static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain, bool need_rw_dc)
1987 {
1988         NTSTATUS result;
1989         bool skip_connection = domain->internal;
1990         if (need_rw_dc && domain->rodc) {
1991                 skip_connection = false;
1992         }
1993
1994         /* Internal connections never use the network. */
1995         if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
1996                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1997         }
1998
1999         /* Still ask the internal LSA and SAMR server about the local domain */
2000         if (skip_connection || connection_ok(domain)) {
2001                 if (!domain->initialized) {
2002                         set_dc_type_and_flags(domain);
2003                 }
2004                 return NT_STATUS_OK;
2005         }
2006
2007         invalidate_cm_connection(domain);
2008
2009         if (!domain->primary && !domain->initialized) {
2010                 /*
2011                  * Before we connect to a trust, work out if it is an
2012                  * AD domain by asking our own domain.
2013                  */
2014                 set_dc_type_and_flags_trustinfo(domain);
2015         }
2016
2017         result = cm_open_connection(domain, &domain->conn, need_rw_dc);
2018
2019         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
2020                 set_dc_type_and_flags(domain);
2021         }
2022
2023         return result;
2024 }
2025
2026 NTSTATUS init_dc_connection(struct winbindd_domain *domain, bool need_rw_dc)
2027 {
2028         if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
2029                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2030         }
2031
2032         SMB_ASSERT(wb_child_domain() || idmap_child());
2033
2034         return init_dc_connection_network(domain, need_rw_dc);
2035 }
2036
2037 static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain, bool need_rw_dc)
2038 {
2039         NTSTATUS status;
2040
2041         status = init_dc_connection(domain, need_rw_dc);
2042         if (!NT_STATUS_IS_OK(status)) {
2043                 return status;
2044         }
2045
2046         if (!domain->internal && domain->conn.cli == NULL) {
2047                 /* happens for trusted domains without inbound trust */
2048                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2049         }
2050
2051         return NT_STATUS_OK;
2052 }
2053
2054 /******************************************************************************
2055  Set the trust flags (direction and forest location) for a domain
2056 ******************************************************************************/
2057
2058 static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
2059 {
2060         struct winbindd_domain *our_domain;
2061         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2062         WERROR werr;
2063         struct netr_DomainTrustList trusts;
2064         int i;
2065         uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST |
2066                         NETR_TRUST_FLAG_OUTBOUND |
2067                         NETR_TRUST_FLAG_INBOUND);
2068         struct rpc_pipe_client *cli;
2069         TALLOC_CTX *mem_ctx = NULL;
2070         struct dcerpc_binding_handle *b;
2071
2072         if (IS_DC) {
2073                 /*
2074                  * On a DC we loaded all trusts
2075                  * from configuration and never learn
2076                  * new domains.
2077                  */
2078                 return true;
2079         }
2080
2081         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
2082
2083         /* Our primary domain doesn't need to worry about trust flags.
2084            Force it to go through the network setup */
2085         if ( domain->primary ) {
2086                 return False;
2087         }
2088
2089         mem_ctx = talloc_stackframe();
2090         our_domain = find_our_domain();
2091         if (our_domain->internal) {
2092                 result = init_dc_connection(our_domain, false);
2093                 if (!NT_STATUS_IS_OK(result)) {
2094                         DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2095                                  "Not able to make a connection to our domain: %s\n",
2096                                   nt_errstr(result)));
2097                         TALLOC_FREE(mem_ctx);
2098                         return false;
2099                 }
2100         }
2101
2102         /* This won't work unless our domain is AD */
2103         if ( !our_domain->active_directory ) {
2104                 TALLOC_FREE(mem_ctx);
2105                 return False;
2106         }
2107
2108         if (our_domain->internal) {
2109                 result = wb_open_internal_pipe(mem_ctx, &ndr_table_netlogon, &cli);
2110         } else if (!connection_ok(our_domain)) {
2111                 DEBUG(3,("set_dc_type_and_flags_trustinfo: "
2112                          "No connection to our domain!\n"));
2113                 TALLOC_FREE(mem_ctx);
2114                 return False;
2115         } else {
2116                 result = cm_connect_netlogon(our_domain, &cli);
2117         }
2118
2119         if (!NT_STATUS_IS_OK(result)) {
2120                 DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
2121                           "a connection to %s for PIPE_NETLOGON (%s)\n",
2122                           domain->name, nt_errstr(result)));
2123                 TALLOC_FREE(mem_ctx);
2124                 return False;
2125         }
2126         b = cli->binding_handle;
2127
2128         /* Use DsEnumerateDomainTrusts to get us the trust direction and type. */
2129         result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
2130                                                       cli->desthost,
2131                                                       flags,
2132                                                       &trusts,
2133                                                       &werr);
2134         if (!NT_STATUS_IS_OK(result)) {
2135                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2136                         "failed to query trusted domain list: %s\n",
2137                         nt_errstr(result)));
2138                 TALLOC_FREE(mem_ctx);
2139                 return false;
2140         }
2141         if (!W_ERROR_IS_OK(werr)) {
2142                 DEBUG(0,("set_dc_type_and_flags_trustinfo: "
2143                         "failed to query trusted domain list: %s\n",
2144                         win_errstr(werr)));
2145                 TALLOC_FREE(mem_ctx);
2146                 return false;
2147         }
2148
2149         /* Now find the domain name and get the flags */
2150
2151         for ( i=0; i<trusts.count; i++ ) {
2152                 if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
2153                         domain->domain_flags          = trusts.array[i].trust_flags;
2154                         domain->domain_type           = trusts.array[i].trust_type;
2155                         domain->domain_trust_attribs  = trusts.array[i].trust_attributes;
2156
2157                         if ( domain->domain_type == LSA_TRUST_TYPE_UPLEVEL )
2158                                 domain->active_directory = True;
2159
2160                         /* This flag is only set if the domain is *our*
2161                            primary domain and the primary domain is in
2162                            native mode */
2163
2164                         domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
2165
2166                         DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
2167                                   "native mode.\n", domain->name,
2168                                   domain->native_mode ? "" : "NOT "));
2169
2170                         DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
2171                                  "running active directory.\n", domain->name,
2172                                  domain->active_directory ? "" : "NOT "));
2173
2174                         domain->can_do_ncacn_ip_tcp = domain->active_directory;
2175
2176                         domain->initialized = True;
2177
2178                         break;
2179                 }
2180         }
2181
2182         TALLOC_FREE(mem_ctx);
2183
2184         return domain->initialized;
2185 }
2186
2187 /******************************************************************************
2188  We can 'sense' certain things about the DC by it's replies to certain
2189  questions.
2190
2191  This tells us if this particular remote server is Active Directory, and if it
2192  is native mode.
2193 ******************************************************************************/
2194
2195 static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
2196 {
2197         NTSTATUS status, result;
2198         NTSTATUS close_status = NT_STATUS_UNSUCCESSFUL;
2199         WERROR werr;
2200         TALLOC_CTX              *mem_ctx = NULL;
2201         struct rpc_pipe_client  *cli = NULL;
2202         struct policy_handle pol = { .handle_type = 0 };
2203         union dssetup_DsRoleInfo info;
2204         union lsa_PolicyInformation *lsa_info = NULL;
2205         union lsa_revision_info out_revision_info = {
2206                 .info1 = {
2207                         .revision = 0,
2208                 },
2209         };
2210         uint32_t out_version = 0;
2211
2212         if (!domain->internal && !connection_ok(domain)) {
2213                 return;
2214         }
2215
2216         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
2217                               domain->name);
2218         if (!mem_ctx) {
2219                 DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
2220                 return;
2221         }
2222
2223         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
2224
2225         if (domain->internal) {
2226                 status = wb_open_internal_pipe(mem_ctx,
2227                                                &ndr_table_dssetup,
2228                                                &cli);
2229         } else {
2230                 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2231                                                   &ndr_table_dssetup,
2232                                                   &cli);
2233         }
2234
2235         if (!NT_STATUS_IS_OK(status)) {
2236                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2237                           "PI_DSSETUP on domain %s: (%s)\n",
2238                           domain->name, nt_errstr(status)));
2239
2240                 /* if this is just a non-AD domain we need to continue
2241                  * identifying so that we can in the end return with
2242                  * domain->initialized = True - gd */
2243
2244                 goto no_dssetup;
2245         }
2246
2247         status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(cli->binding_handle, mem_ctx,
2248                                                                   DS_ROLE_BASIC_INFORMATION,
2249                                                                   &info,
2250                                                                   &werr);
2251         TALLOC_FREE(cli);
2252
2253         if (NT_STATUS_IS_OK(status)) {
2254                 result = werror_to_ntstatus(werr);
2255         }
2256         if (!NT_STATUS_IS_OK(status)) {
2257                 DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
2258                           "on domain %s failed: (%s)\n",
2259                           domain->name, nt_errstr(status)));
2260
2261                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
2262                  * every opcode on the DSSETUP pipe, continue with
2263                  * no_dssetup mode here as well to get domain->initialized
2264                  * set - gd */
2265
2266                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
2267                         goto no_dssetup;
2268                 }
2269
2270                 TALLOC_FREE(mem_ctx);
2271                 return;
2272         }
2273
2274         if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
2275             !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
2276                 domain->native_mode = True;
2277         } else {
2278                 domain->native_mode = False;
2279         }
2280
2281 no_dssetup:
2282         if (domain->internal) {
2283                 status = wb_open_internal_pipe(mem_ctx,
2284                                                &ndr_table_lsarpc,
2285                                                &cli);
2286         } else {
2287                 status = cli_rpc_pipe_open_noauth(domain->conn.cli,
2288                                                   &ndr_table_lsarpc, &cli);
2289         }
2290         if (!NT_STATUS_IS_OK(status)) {
2291                 DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
2292                           "PI_LSARPC on domain %s: (%s)\n",
2293                           domain->name, nt_errstr(status)));
2294                 TALLOC_FREE(cli);
2295                 TALLOC_FREE(mem_ctx);
2296                 return;
2297         }
2298
2299         status = dcerpc_lsa_open_policy_fallback(cli->binding_handle,
2300                                                  mem_ctx,
2301                                                  cli->srv_name_slash,
2302                                                  true,
2303                                                  SEC_FLAG_MAXIMUM_ALLOWED,
2304                                                  &out_version,
2305                                                  &out_revision_info,
2306                                                  &pol,
2307                                                  &result);
2308
2309         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2310                 /* This particular query is exactly what Win2k clients use
2311                    to determine that the DC is active directory */
2312                 status = dcerpc_lsa_QueryInfoPolicy2(cli->binding_handle, mem_ctx,
2313                                                      &pol,
2314                                                      LSA_POLICY_INFO_DNS,
2315                                                      &lsa_info,
2316                                                      &result);
2317         }
2318
2319         /*
2320          * If the status and result will not be OK we will fallback to
2321          * OpenPolicy.
2322          */
2323         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2324                 domain->active_directory = True;
2325
2326                 if (lsa_info->dns.name.string) {
2327                         if (!strequal(domain->name, lsa_info->dns.name.string))
2328                         {
2329                                 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2330                                           "for domain %s claimed it was a DC "
2331                                           "for domain %s, refusing to "
2332                                           "initialize\n",
2333                                           domain->name,
2334                                           lsa_info->dns.name.string));
2335                                 TALLOC_FREE(cli);
2336                                 TALLOC_FREE(mem_ctx);
2337                                 return;
2338                         }
2339                         talloc_free(domain->name);
2340                         domain->name = talloc_strdup(domain,
2341                                                      lsa_info->dns.name.string);
2342                         if (domain->name == NULL) {
2343                                 goto done;
2344                         }
2345                 }
2346
2347                 if (lsa_info->dns.dns_domain.string) {
2348                         if (domain->alt_name != NULL &&
2349                             !strequal(domain->alt_name,
2350                                       lsa_info->dns.dns_domain.string))
2351                         {
2352                                 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2353                                           "for domain %s (%s) claimed it was "
2354                                           "a DC for domain %s, refusing to "
2355                                           "initialize\n",
2356                                           domain->alt_name, domain->name,
2357                                           lsa_info->dns.dns_domain.string));
2358                                 TALLOC_FREE(cli);
2359                                 TALLOC_FREE(mem_ctx);
2360                                 return;
2361                         }
2362                         talloc_free(domain->alt_name);
2363                         domain->alt_name =
2364                                 talloc_strdup(domain,
2365                                               lsa_info->dns.dns_domain.string);
2366                         if (domain->alt_name == NULL) {
2367                                 goto done;
2368                         }
2369                 }
2370
2371                 /* See if we can set some domain trust flags about
2372                    ourself */
2373
2374                 if (lsa_info->dns.dns_forest.string) {
2375                         talloc_free(domain->forest_name);
2376                         domain->forest_name =
2377                                 talloc_strdup(domain,
2378                                               lsa_info->dns.dns_forest.string);
2379                         if (domain->forest_name == NULL) {
2380                                 goto done;
2381                         }
2382
2383                         if (strequal(domain->forest_name, domain->alt_name)) {
2384                                 domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT;
2385                         }
2386                 }
2387
2388                 if (lsa_info->dns.sid) {
2389                         if (!is_null_sid(&domain->sid) &&
2390                             !dom_sid_equal(&domain->sid,
2391                                            lsa_info->dns.sid))
2392                         {
2393                                 struct dom_sid_buf buf1, buf2;
2394                                 DEBUG(1, ("set_dc_type_and_flags_connect: DC "
2395                                           "for domain %s (%s) claimed it was "
2396                                           "a DC for domain %s, refusing to "
2397                                           "initialize\n",
2398                                           dom_sid_str_buf(&domain->sid, &buf1),
2399                                           domain->name,
2400                                           dom_sid_str_buf(lsa_info->dns.sid,
2401                                                           &buf2)));
2402                                 TALLOC_FREE(cli);
2403                                 TALLOC_FREE(mem_ctx);
2404                                 return;
2405                         }
2406                         sid_copy(&domain->sid, lsa_info->dns.sid);
2407                 }
2408         } else {
2409                 domain->active_directory = False;
2410
2411                 status = rpccli_lsa_open_policy(cli, mem_ctx, True,
2412                                                 SEC_FLAG_MAXIMUM_ALLOWED,
2413                                                 &pol);
2414
2415                 if (!NT_STATUS_IS_OK(status)) {
2416                         goto done;
2417                 }
2418
2419                 status = dcerpc_lsa_QueryInfoPolicy(cli->binding_handle, mem_ctx,
2420                                                     &pol,
2421                                                     LSA_POLICY_INFO_ACCOUNT_DOMAIN,
2422                                                     &lsa_info,
2423                                                     &result);
2424                 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2425
2426                         if (lsa_info->account_domain.name.string) {
2427                                 if (!strequal(domain->name,
2428                                         lsa_info->account_domain.name.string))
2429                                 {
2430                                         DEBUG(1,
2431                                               ("set_dc_type_and_flags_connect: "
2432                                                "DC for domain %s claimed it was"
2433                                                " a DC for domain %s, refusing "
2434                                                "to initialize\n", domain->name,
2435                                                lsa_info->
2436                                                 account_domain.name.string));
2437                                         TALLOC_FREE(cli);
2438                                         TALLOC_FREE(mem_ctx);
2439                                         return;
2440                                 }
2441                                 talloc_free(domain->name);
2442                                 domain->name =
2443                                         talloc_strdup(domain,
2444                                                       lsa_info->account_domain.name.string);
2445                         }
2446
2447                         if (lsa_info->account_domain.sid) {
2448                                 if (!is_null_sid(&domain->sid) &&
2449                                     !dom_sid_equal(&domain->sid,
2450                                                 lsa_info->account_domain.sid))
2451                                 {
2452                                         struct dom_sid_buf buf1, buf2;
2453                                         DEBUG(1,
2454                                               ("set_dc_type_and_flags_connect: "
2455                                                "DC for domain %s (%s) claimed "
2456                                                "it was a DC for domain %s, "
2457                                                "refusing to initialize\n",
2458                                                dom_sid_str_buf(
2459                                                        &domain->sid, &buf1),
2460                                                domain->name,
2461                                                dom_sid_str_buf(
2462                                                 lsa_info->account_domain.sid,
2463                                                 &buf2)));
2464                                         TALLOC_FREE(cli);
2465                                         TALLOC_FREE(mem_ctx);
2466                                         return;
2467                                 }
2468                                 sid_copy(&domain->sid, lsa_info->account_domain.sid);
2469                         }
2470                 }
2471         }
2472 done:
2473         if (is_valid_policy_hnd(&pol)) {
2474                 dcerpc_lsa_Close(cli->binding_handle,
2475                                  mem_ctx,
2476                                  &pol,
2477                                  &close_status);
2478         }
2479
2480         DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
2481                   domain->name, domain->native_mode ? "" : "NOT "));
2482
2483         DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
2484                   domain->name, domain->active_directory ? "" : "NOT "));
2485
2486         domain->can_do_ncacn_ip_tcp = domain->active_directory;
2487
2488         TALLOC_FREE(cli);
2489
2490         TALLOC_FREE(mem_ctx);
2491
2492         domain->initialized = True;
2493 }
2494
2495 /**********************************************************************
2496  Set the domain_flags (trust attributes, domain operating modes, etc...
2497 ***********************************************************************/
2498
2499 static void set_dc_type_and_flags( struct winbindd_domain *domain )
2500 {
2501         if (IS_DC) {
2502                 /*
2503                  * On a DC we loaded all trusts
2504                  * from configuration and never learn
2505                  * new domains.
2506                  */
2507                 return;
2508         }
2509
2510         /* we always have to contact our primary domain */
2511
2512         if ( domain->primary || domain->internal) {
2513                 DEBUG(10,("set_dc_type_and_flags: setting up flags for "
2514                           "primary or internal domain\n"));
2515                 set_dc_type_and_flags_connect( domain );
2516                 return;
2517         }
2518
2519         /* Use our DC to get the information if possible */
2520
2521         if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
2522                 /* Otherwise, fallback to contacting the
2523                    domain directly */
2524                 set_dc_type_and_flags_connect( domain );
2525         }
2526
2527         return;
2528 }
2529
2530
2531
2532 /**********************************************************************
2533 ***********************************************************************/
2534
2535 static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
2536                                    struct netlogon_creds_cli_context **ppdc)
2537 {
2538         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2539         struct rpc_pipe_client *netlogon_pipe;
2540
2541         *ppdc = NULL;
2542
2543         if ((!IS_DC) && (!domain->primary)) {
2544                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
2545         }
2546
2547         if (domain->conn.netlogon_creds_ctx != NULL) {
2548                 *ppdc = domain->conn.netlogon_creds_ctx;
2549                 return NT_STATUS_OK;
2550         }
2551
2552         result = cm_connect_netlogon_secure(domain, &netlogon_pipe, ppdc);
2553         if (!NT_STATUS_IS_OK(result)) {
2554                 return result;
2555         }
2556
2557         return NT_STATUS_OK;
2558 }
2559
2560 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2561                         bool need_rw_dc,
2562                         struct rpc_pipe_client **cli, struct policy_handle *sam_handle)
2563 {
2564         struct winbindd_cm_conn *conn;
2565         NTSTATUS status, result;
2566         struct netlogon_creds_cli_context *p_creds;
2567         struct cli_credentials *creds = NULL;
2568         bool retry = false; /* allow one retry attempt for expired session */
2569         const char *remote_name = NULL;
2570         const struct sockaddr_storage *remote_sockaddr = NULL;
2571         bool sealed_pipes = true;
2572         bool strong_key = true;
2573
2574         if (sid_check_is_our_sam(&domain->sid)) {
2575                 if (domain->rodc == false || need_rw_dc == false) {
2576                         return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
2577                 }
2578         }
2579
2580         if (IS_AD_DC) {
2581                 /*
2582                  * In theory we should not use SAMR within
2583                  * winbindd at all, but that's a larger task to
2584                  * remove this and avoid breaking existing
2585                  * setups.
2586                  *
2587                  * At least as AD DC we have the restriction
2588                  * to avoid SAMR against trusted domains,
2589                  * as there're no existing setups.
2590                  */
2591                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
2592         }
2593
2594 retry:
2595         status = init_dc_connection_rpc(domain, need_rw_dc);
2596         if (!NT_STATUS_IS_OK(status)) {
2597                 return status;
2598         }
2599
2600         conn = &domain->conn;
2601
2602         if (rpccli_is_connected(conn->samr_pipe)) {
2603                 goto done;
2604         }
2605
2606         TALLOC_FREE(conn->samr_pipe);
2607
2608         /*
2609          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
2610          * sign and sealed pipe using the machine account password by
2611          * preference. If we can't - try schannel, if that fails, try
2612          * anonymous.
2613          */
2614
2615         result = winbindd_get_trust_credentials(domain,
2616                                                 talloc_tos(),
2617                                                 false, /* netlogon */
2618                                                 true, /* ipc_fallback */
2619                                                 &creds);
2620         if (!NT_STATUS_IS_OK(result)) {
2621                 DEBUG(10, ("cm_connect_sam: No user available for "
2622                            "domain %s, trying schannel\n", domain->name));
2623                 goto schannel;
2624         }
2625
2626         if (cli_credentials_is_anonymous(creds)) {
2627                 goto anonymous;
2628         }
2629
2630         remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2631         remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2632
2633         /*
2634          * We have an authenticated connection. Use a SPNEGO
2635          * authenticated SAMR pipe with sign & seal.
2636          */
2637         status = cli_rpc_pipe_open_with_creds(conn->cli,
2638                                               &ndr_table_samr,
2639                                               NCACN_NP,
2640                                               DCERPC_AUTH_TYPE_SPNEGO,
2641                                               conn->auth_level,
2642                                               remote_name,
2643                                               remote_sockaddr,
2644                                               creds,
2645                                               &conn->samr_pipe);
2646
2647         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2648             && !retry) {
2649                 invalidate_cm_connection(domain);
2650                 retry = true;
2651                 goto retry;
2652         }
2653
2654         if (!NT_STATUS_IS_OK(status)) {
2655                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
2656                           "pipe for domain %s using NTLMSSP "
2657                           "authenticated pipe: user %s. Error was "
2658                           "%s\n", domain->name,
2659                           cli_credentials_get_unparsed_name(creds, talloc_tos()),
2660                           nt_errstr(status)));
2661                 goto schannel;
2662         }
2663
2664         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
2665                   "domain %s using NTLMSSP authenticated "
2666                   "pipe: user %s\n", domain->name,
2667                   cli_credentials_get_unparsed_name(creds, talloc_tos())));
2668
2669         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2670                                       conn->samr_pipe->desthost,
2671                                       SEC_FLAG_MAXIMUM_ALLOWED,
2672                                       &conn->sam_connect_handle,
2673                                       &result);
2674
2675         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2676                 invalidate_cm_connection(domain);
2677                 TALLOC_FREE(conn->samr_pipe);
2678                 retry = true;
2679                 goto retry;
2680         }
2681
2682         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2683                 goto open_domain;
2684         }
2685         if (NT_STATUS_IS_OK(status)) {
2686                 status = result;
2687         }
2688
2689         DEBUG(10,("cm_connect_sam: ntlmssp-sealed dcerpc_samr_Connect2 "
2690                   "failed for domain %s, error was %s. Trying schannel\n",
2691                   domain->name, nt_errstr(status) ));
2692         TALLOC_FREE(conn->samr_pipe);
2693
2694  schannel:
2695
2696         /* Fall back to schannel if it's a W2K pre-SP1 box. */
2697
2698         status = cm_get_schannel_creds(domain, &p_creds);
2699         if (!NT_STATUS_IS_OK(status)) {
2700                 /* If this call fails - conn->cli can now be NULL ! */
2701                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
2702                            "for domain %s (error %s), trying anon\n",
2703                         domain->name,
2704                         nt_errstr(status) ));
2705                 goto anonymous;
2706         }
2707         TALLOC_FREE(creds);
2708         status = cli_rpc_pipe_open_schannel_with_creds(
2709                 conn->cli, &ndr_table_samr, NCACN_NP, p_creds,
2710                 remote_name,
2711                 remote_sockaddr,
2712                 &conn->samr_pipe);
2713
2714         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2715             && !retry) {
2716                 invalidate_cm_connection(domain);
2717                 retry = true;
2718                 goto retry;
2719         }
2720
2721         if (!NT_STATUS_IS_OK(status)) {
2722                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
2723                           "domain %s using schannel. Error was %s\n",
2724                           domain->name, nt_errstr(status) ));
2725                 goto anonymous;
2726         }
2727         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
2728                   "schannel.\n", domain->name ));
2729
2730         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2731                                       conn->samr_pipe->desthost,
2732                                       SEC_FLAG_MAXIMUM_ALLOWED,
2733                                       &conn->sam_connect_handle,
2734                                       &result);
2735
2736         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2737                 invalidate_cm_connection(domain);
2738                 TALLOC_FREE(conn->samr_pipe);
2739                 retry = true;
2740                 goto retry;
2741         }
2742
2743         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2744                 goto open_domain;
2745         }
2746         if (NT_STATUS_IS_OK(status)) {
2747                 status = result;
2748         }
2749         DEBUG(10,("cm_connect_sam: schannel-sealed dcerpc_samr_Connect2 failed "
2750                   "for domain %s, error was %s. Trying anonymous\n",
2751                   domain->name, nt_errstr(status) ));
2752         TALLOC_FREE(conn->samr_pipe);
2753
2754  anonymous:
2755
2756         sealed_pipes = lp_winbind_sealed_pipes();
2757         sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
2758                                     domain->name,
2759                                     sealed_pipes);
2760         strong_key = lp_require_strong_key();
2761         strong_key = lp_parm_bool(-1, "require strong key",
2762                                   domain->name,
2763                                   strong_key);
2764
2765         /* Finally fall back to anonymous. */
2766         if (sealed_pipes || strong_key) {
2767                 status = NT_STATUS_DOWNGRADE_DETECTED;
2768                 DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
2769                           "without connection level security, "
2770                           "must set 'winbind sealed pipes:%s = false' and "
2771                           "'require strong key:%s = false' to proceed: %s\n",
2772                           domain->name, domain->name, domain->name,
2773                           nt_errstr(status)));
2774                 goto done;
2775         }
2776         status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
2777                                           &conn->samr_pipe);
2778
2779         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
2780             && !retry) {
2781                 invalidate_cm_connection(domain);
2782                 retry = true;
2783                 goto retry;
2784         }
2785
2786         if (!NT_STATUS_IS_OK(status)) {
2787                 goto done;
2788         }
2789
2790         status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
2791                                       conn->samr_pipe->desthost,
2792                                       SEC_FLAG_MAXIMUM_ALLOWED,
2793                                       &conn->sam_connect_handle,
2794                                       &result);
2795
2796         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
2797                 invalidate_cm_connection(domain);
2798                 TALLOC_FREE(conn->samr_pipe);
2799                 retry = true;
2800                 goto retry;
2801         }
2802
2803         if (!NT_STATUS_IS_OK(status)) {
2804                 DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
2805                           "for domain %s Error was %s\n",
2806                           domain->name, nt_errstr(status) ));
2807                 goto done;
2808         }
2809         if (!NT_STATUS_IS_OK(result)) {
2810                 status = result;
2811                 DEBUG(10,("cm_connect_sam: dcerpc_samr_Connect2 failed "
2812                           "for domain %s Error was %s\n",
2813                           domain->name, nt_errstr(result)));
2814                 goto done;
2815         }
2816
2817  open_domain:
2818         status = dcerpc_samr_OpenDomain(conn->samr_pipe->binding_handle,
2819                                         mem_ctx,
2820                                         &conn->sam_connect_handle,
2821                                         SEC_FLAG_MAXIMUM_ALLOWED,
2822                                         &domain->sid,
2823                                         &conn->sam_domain_handle,
2824                                         &result);
2825         if (!NT_STATUS_IS_OK(status)) {
2826                 goto done;
2827         }
2828
2829         status = result;
2830  done:
2831
2832         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2833                 /*
2834                  * if we got access denied, we might just have no access rights
2835                  * to talk to the remote samr server server (e.g. when we are a
2836                  * PDC and we are connecting a w2k8 pdc via an interdomain
2837                  * trust). In that case do not invalidate the whole connection
2838                  * stack
2839                  */
2840                 TALLOC_FREE(conn->samr_pipe);
2841                 ZERO_STRUCT(conn->sam_domain_handle);
2842                 return status;
2843         } else if (!NT_STATUS_IS_OK(status)) {
2844                 invalidate_cm_connection(domain);
2845                 return status;
2846         }
2847
2848         *cli = conn->samr_pipe;
2849         *sam_handle = conn->sam_domain_handle;
2850         return status;
2851 }
2852
2853 /**********************************************************************
2854  open an schanneld ncacn_ip_tcp connection to LSA
2855 ***********************************************************************/
2856
2857 static NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
2858                                    TALLOC_CTX *mem_ctx,
2859                                    struct rpc_pipe_client **cli)
2860 {
2861         struct winbindd_cm_conn *conn;
2862         struct netlogon_creds_cli_context *p_creds = NULL;
2863         NTSTATUS status;
2864         const char *remote_name = NULL;
2865         const struct sockaddr_storage *remote_sockaddr = NULL;
2866
2867         DEBUG(10,("cm_connect_lsa_tcp\n"));
2868
2869         status = init_dc_connection_rpc(domain, false);
2870         if (!NT_STATUS_IS_OK(status)) {
2871                 return status;
2872         }
2873
2874         conn = &domain->conn;
2875
2876         /*
2877          * rpccli_is_connected handles more error cases
2878          */
2879         if (rpccli_is_connected(conn->lsa_pipe_tcp) &&
2880             conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
2881             conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2882                 goto done;
2883         }
2884
2885         TALLOC_FREE(conn->lsa_pipe_tcp);
2886
2887         status = cm_get_schannel_creds(domain, &p_creds);
2888         if (!NT_STATUS_IS_OK(status)) {
2889                 goto done;
2890         }
2891
2892         remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2893         remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2894
2895         status = cli_rpc_pipe_open_schannel_with_creds(
2896                         conn->cli,
2897                         &ndr_table_lsarpc,
2898                         NCACN_IP_TCP,
2899                         p_creds,
2900                         remote_name,
2901                         remote_sockaddr,
2902                         &conn->lsa_pipe_tcp);
2903         if (!NT_STATUS_IS_OK(status)) {
2904                 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
2905                         nt_errstr(status)));
2906                 goto done;
2907         }
2908
2909  done:
2910         if (!NT_STATUS_IS_OK(status)) {
2911                 TALLOC_FREE(conn->lsa_pipe_tcp);
2912                 return status;
2913         }
2914
2915         *cli = conn->lsa_pipe_tcp;
2916
2917         return status;
2918 }
2919
2920 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
2921                         struct rpc_pipe_client **cli, struct policy_handle *lsa_policy)
2922 {
2923         struct winbindd_cm_conn *conn;
2924         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2925         struct netlogon_creds_cli_context *p_creds;
2926         struct cli_credentials *creds = NULL;
2927         bool retry = false; /* allow one retry attempt for expired session */
2928         const char *remote_name = NULL;
2929         const struct sockaddr_storage *remote_sockaddr = NULL;
2930         bool sealed_pipes = true;
2931         bool strong_key = true;
2932
2933 retry:
2934         result = init_dc_connection_rpc(domain, false);
2935         if (!NT_STATUS_IS_OK(result))
2936                 return result;
2937
2938         conn = &domain->conn;
2939
2940         if (rpccli_is_connected(conn->lsa_pipe)) {
2941                 goto done;
2942         }
2943
2944         TALLOC_FREE(conn->lsa_pipe);
2945
2946         if (IS_DC) {
2947                 /*
2948                  * Make sure we only use schannel as AD DC.
2949                  */
2950                 goto schannel;
2951         }
2952
2953         result = winbindd_get_trust_credentials(domain,
2954                                                 talloc_tos(),
2955                                                 false, /* netlogon */
2956                                                 true, /* ipc_fallback */
2957                                                 &creds);
2958         if (!NT_STATUS_IS_OK(result)) {
2959                 DEBUG(10, ("cm_connect_lsa: No user available for "
2960                            "domain %s, trying schannel\n", domain->name));
2961                 goto schannel;
2962         }
2963
2964         if (cli_credentials_is_anonymous(creds)) {
2965                 goto anonymous;
2966         }
2967
2968         remote_name = smbXcli_conn_remote_name(conn->cli->conn);
2969         remote_sockaddr = smbXcli_conn_remote_sockaddr(conn->cli->conn);
2970
2971         /*
2972          * We have an authenticated connection. Use a SPNEGO
2973          * authenticated LSA pipe with sign & seal.
2974          */
2975         result = cli_rpc_pipe_open_with_creds
2976                 (conn->cli, &ndr_table_lsarpc, NCACN_NP,
2977                  DCERPC_AUTH_TYPE_SPNEGO,
2978                  conn->auth_level,
2979                  remote_name,
2980                  remote_sockaddr,
2981                  creds,
2982                  &conn->lsa_pipe);
2983
2984         if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
2985             && !retry) {
2986                 invalidate_cm_connection(domain);
2987                 retry = true;
2988                 goto retry;
2989         }
2990
2991         if (!NT_STATUS_IS_OK(result)) {
2992                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
2993                           "domain %s using NTLMSSP authenticated pipe: user "
2994                           "%s. Error was %s. Trying schannel.\n",
2995                           domain->name,
2996                           cli_credentials_get_unparsed_name(creds, talloc_tos()),
2997                           nt_errstr(result)));
2998                 goto schannel;
2999         }
3000
3001         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3002                   "NTLMSSP authenticated pipe: user %s\n",
3003                   domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3004
3005         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3006                                         SEC_FLAG_MAXIMUM_ALLOWED,
3007                                         &conn->lsa_policy);
3008         if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3009                 invalidate_cm_connection(domain);
3010                 TALLOC_FREE(conn->lsa_pipe);
3011                 retry = true;
3012                 goto retry;
3013         }
3014
3015         if (NT_STATUS_IS_OK(result)) {
3016                 goto done;
3017         }
3018
3019         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3020                   "schannel\n"));
3021
3022         TALLOC_FREE(conn->lsa_pipe);
3023
3024  schannel:
3025
3026         /* Fall back to schannel if it's a W2K pre-SP1 box. */
3027
3028         result = cm_get_schannel_creds(domain, &p_creds);
3029         if (!NT_STATUS_IS_OK(result)) {
3030                 /* If this call fails - conn->cli can now be NULL ! */
3031                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
3032                            "for domain %s (error %s), trying anon\n",
3033                         domain->name,
3034                         nt_errstr(result) ));
3035                 goto anonymous;
3036         }
3037
3038         TALLOC_FREE(creds);
3039         result = cli_rpc_pipe_open_schannel_with_creds(
3040                 conn->cli, &ndr_table_lsarpc, NCACN_NP, p_creds,
3041                 remote_name,
3042                 remote_sockaddr,
3043                 &conn->lsa_pipe);
3044
3045         if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3046             && !retry) {
3047                 invalidate_cm_connection(domain);
3048                 retry = true;
3049                 goto retry;
3050         }
3051
3052         if (!NT_STATUS_IS_OK(result)) {
3053                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
3054                           "domain %s using schannel. Error was %s\n",
3055                           domain->name, nt_errstr(result) ));
3056                 goto anonymous;
3057         }
3058         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
3059                   "schannel.\n", domain->name ));
3060
3061         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3062                                         SEC_FLAG_MAXIMUM_ALLOWED,
3063                                         &conn->lsa_policy);
3064
3065         if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3066                 invalidate_cm_connection(domain);
3067                 TALLOC_FREE(conn->lsa_pipe);
3068                 retry = true;
3069                 goto retry;
3070         }
3071
3072         if (NT_STATUS_IS_OK(result)) {
3073                 goto done;
3074         }
3075
3076         if (IS_DC) {
3077                 /*
3078                  * Make sure we only use schannel as AD DC.
3079                  */
3080                 goto done;
3081         }
3082
3083         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
3084                   "anonymous\n"));
3085
3086         TALLOC_FREE(conn->lsa_pipe);
3087
3088  anonymous:
3089
3090         if (IS_DC) {
3091                 /*
3092                  * Make sure we only use schannel as AD DC.
3093                  */
3094                 goto done;
3095         }
3096
3097         sealed_pipes = lp_winbind_sealed_pipes();
3098         sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
3099                                     domain->name,
3100                                     sealed_pipes);
3101         strong_key = lp_require_strong_key();
3102         strong_key = lp_parm_bool(-1, "require strong key",
3103                                   domain->name,
3104                                   strong_key);
3105
3106         /* Finally fall back to anonymous. */
3107         if (sealed_pipes || strong_key) {
3108                 result = NT_STATUS_DOWNGRADE_DETECTED;
3109                 DEBUG(1, ("Unwilling to make LSA connection to domain %s "
3110                           "without connection level security, "
3111                           "must set 'winbind sealed pipes:%s = false' and "
3112                           "'require strong key:%s = false' to proceed: %s\n",
3113                           domain->name, domain->name, domain->name,
3114                           nt_errstr(result)));
3115                 goto done;
3116         }
3117
3118         result = cli_rpc_pipe_open_noauth(conn->cli,
3119                                           &ndr_table_lsarpc,
3120                                           &conn->lsa_pipe);
3121
3122         if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
3123             && !retry) {
3124                 invalidate_cm_connection(domain);
3125                 retry = true;
3126                 goto retry;
3127         }
3128
3129         if (!NT_STATUS_IS_OK(result)) {
3130                 goto done;
3131         }
3132
3133         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
3134                                         SEC_FLAG_MAXIMUM_ALLOWED,
3135                                         &conn->lsa_policy);
3136
3137         if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
3138                 invalidate_cm_connection(domain);
3139                 TALLOC_FREE(conn->lsa_pipe);
3140                 retry = true;
3141                 goto retry;
3142         }
3143
3144  done:
3145         if (!NT_STATUS_IS_OK(result)) {
3146                 invalidate_cm_connection(domain);
3147                 return result;
3148         }
3149
3150         *cli = conn->lsa_pipe;
3151         *lsa_policy = conn->lsa_policy;
3152         return result;
3153 }
3154
3155 /****************************************************************************
3156 Open a LSA connection to a DC, suitable for LSA lookup calls.
3157 ****************************************************************************/
3158
3159 NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
3160                          TALLOC_CTX *mem_ctx,
3161                          struct rpc_pipe_client **cli,
3162                          struct policy_handle *lsa_policy)
3163 {
3164         NTSTATUS status;
3165
3166         if (domain->can_do_ncacn_ip_tcp) {
3167                 status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3168                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3169                     NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3170                     NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3171                         invalidate_cm_connection(domain);
3172                         status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
3173                 }
3174                 if (NT_STATUS_IS_OK(status)) {
3175                         return status;
3176                 }
3177
3178                 /*
3179                  * we tried twice to connect via ncan_ip_tcp and schannel and
3180                  * failed - maybe it is a trusted domain we can't connect to ?
3181                  * do not try tcp next time - gd
3182                  *
3183                  * This also prevents NETLOGON over TCP
3184                  */
3185                 domain->can_do_ncacn_ip_tcp = false;
3186         }
3187
3188         status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy);
3189
3190         return status;
3191 }
3192
3193 /****************************************************************************
3194  Open the netlogon pipe to this DC.
3195 ****************************************************************************/
3196
3197 static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
3198                                               enum dcerpc_transport_t transport,
3199                                               struct rpc_pipe_client **cli)
3200 {
3201         struct messaging_context *msg_ctx = global_messaging_context();
3202         struct winbindd_cm_conn *conn;
3203         NTSTATUS result;
3204         enum netr_SchannelType sec_chan_type;
3205         struct cli_credentials *creds = NULL;
3206
3207         *cli = NULL;
3208
3209         if (IS_DC) {
3210                 if (domain->secure_channel_type == SEC_CHAN_NULL) {
3211                         /*
3212                          * Make sure we don't even try to
3213                          * connect to a foreign domain
3214                          * without a direct outbound trust.
3215                          */
3216                         return NT_STATUS_NO_TRUST_LSA_SECRET;
3217                 }
3218         }
3219
3220         result = init_dc_connection_rpc(domain, domain->rodc);
3221         if (!NT_STATUS_IS_OK(result)) {
3222                 return result;
3223         }
3224
3225         conn = &domain->conn;
3226
3227         if (rpccli_is_connected(conn->netlogon_pipe)) {
3228                 *cli = conn->netlogon_pipe;
3229                 return NT_STATUS_OK;
3230         }
3231
3232         TALLOC_FREE(conn->netlogon_pipe);
3233         TALLOC_FREE(conn->netlogon_creds_ctx);
3234
3235         result = winbindd_get_trust_credentials(domain,
3236                                                 talloc_tos(),
3237                                                 true, /* netlogon */
3238                                                 false, /* ipc_fallback */
3239                                                 &creds);
3240         if (!NT_STATUS_IS_OK(result)) {
3241                 DBG_DEBUG("No user available for domain %s when trying "
3242                           "schannel\n", domain->name);
3243                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3244         }
3245
3246         if (cli_credentials_is_anonymous(creds)) {
3247                 DBG_WARNING("get_trust_credential only gave anonymous for %s, "
3248                             "unable to make get NETLOGON credentials\n",
3249                             domain->name);
3250                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3251         }
3252
3253         sec_chan_type = cli_credentials_get_secure_channel_type(creds);
3254         if (sec_chan_type == SEC_CHAN_NULL) {
3255                 const char *remote_name =
3256                         smbXcli_conn_remote_name(conn->cli->conn);
3257                 const struct sockaddr_storage *remote_sockaddr =
3258                         smbXcli_conn_remote_sockaddr(conn->cli->conn);
3259
3260                 if (transport == NCACN_IP_TCP) {
3261                         DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL "
3262                                    "for %s, deny NCACN_IP_TCP and let the "
3263                                    "caller fallback to NCACN_NP.\n",
3264                                    domain->name);
3265                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3266                 }
3267
3268                 DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
3269                            "fallback to noauth on NCACN_NP.\n",
3270                            domain->name);
3271
3272                 result = cli_rpc_pipe_open_noauth_transport(
3273                         conn->cli,
3274                         transport,
3275                         &ndr_table_netlogon,
3276                         remote_name,
3277                         remote_sockaddr,
3278                         &conn->netlogon_pipe);
3279                 if (!NT_STATUS_IS_OK(result)) {
3280                         invalidate_cm_connection(domain);
3281                         return result;
3282                 }
3283
3284                 *cli = conn->netlogon_pipe;
3285                 return NT_STATUS_OK;
3286         }
3287
3288         result = rpccli_create_netlogon_creds_ctx(creds,
3289                                                   domain->dcname,
3290                                                   msg_ctx,
3291                                                   domain,
3292                                                   &conn->netlogon_creds_ctx);
3293         if (!NT_STATUS_IS_OK(result)) {
3294                 DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
3295                           "unable to create NETLOGON credentials: %s\n",
3296                           domain->name, nt_errstr(result)));
3297                 return result;
3298         }
3299
3300         result = rpccli_connect_netlogon(
3301                 conn->cli, transport,
3302                 conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
3303                 &conn->netlogon_pipe);
3304         conn->netlogon_force_reauth = false;
3305         if (!NT_STATUS_IS_OK(result)) {
3306                 DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
3307                           nt_errstr(result));
3308                 return result;
3309         }
3310
3311         *cli = conn->netlogon_pipe;
3312         return NT_STATUS_OK;
3313 }
3314
3315 /****************************************************************************
3316 Open a NETLOGON connection to a DC, suitable for SamLogon calls.
3317 ****************************************************************************/
3318
3319 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
3320                              struct rpc_pipe_client **cli)
3321 {
3322         NTSTATUS status;
3323
3324         status = init_dc_connection_rpc(domain, domain->rodc);
3325         if (!NT_STATUS_IS_OK(status)) {
3326                 return status;
3327         }
3328
3329         if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
3330                 status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3331                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
3332                     NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
3333                     NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3334                         invalidate_cm_connection(domain);
3335                         status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
3336                 }
3337                 if (NT_STATUS_IS_OK(status)) {
3338                         return status;
3339                 }
3340
3341                 /*
3342                  * we tried twice to connect via ncan_ip_tcp and schannel and
3343                  * failed - maybe it is a trusted domain we can't connect to ?
3344                  * do not try tcp next time - gd
3345                  *
3346                  * This also prevents LSA over TCP
3347                  */
3348                 domain->can_do_ncacn_ip_tcp = false;
3349         }
3350
3351         status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3352         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
3353                 /*
3354                  * SMB2 session expired, needs reauthentication. Drop
3355                  * connection and retry.
3356                  */
3357                 invalidate_cm_connection(domain);
3358                 status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
3359         }
3360
3361         return status;
3362 }
3363
3364 NTSTATUS cm_connect_netlogon_secure(struct winbindd_domain *domain,
3365                                     struct rpc_pipe_client **cli,
3366                                     struct netlogon_creds_cli_context **ppdc)
3367 {
3368         NTSTATUS status;
3369
3370         if (domain->secure_channel_type == SEC_CHAN_NULL) {
3371                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3372         }
3373
3374         status = cm_connect_netlogon(domain, cli);
3375         if (!NT_STATUS_IS_OK(status)) {
3376                 return status;
3377         }
3378
3379         if (domain->conn.netlogon_creds_ctx == NULL) {
3380                 return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
3381         }
3382
3383         *ppdc = domain->conn.netlogon_creds_ctx;
3384         return NT_STATUS_OK;
3385 }
3386
3387 void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
3388                             void *private_data,
3389                             uint32_t msg_type,
3390                             struct server_id server_id,
3391                             DATA_BLOB *data)
3392 {
3393         struct winbindd_domain *domain;
3394         char *freeit = NULL;
3395         char *addr;
3396
3397         if ((data == NULL)
3398             || (data->data == NULL)
3399             || (data->length == 0)
3400             || (data->data[data->length-1] != '\0')) {
3401                 DEBUG(1, ("invalid msg_ip_dropped message: not a valid "
3402                           "string\n"));
3403                 return;
3404         }
3405
3406         addr = (char *)data->data;
3407         DEBUG(10, ("IP %s dropped\n", addr));
3408
3409         if (!is_ipaddress(addr)) {
3410                 char *slash;
3411                 /*
3412                  * Some code sends us ip addresses with the /netmask
3413                  * suffix
3414                  */
3415                 slash = strchr(addr, '/');
3416                 if (slash == NULL) {
3417                         DEBUG(1, ("invalid msg_ip_dropped message: %s\n",
3418                                   addr));
3419                         return;
3420                 }
3421                 freeit = talloc_strndup(talloc_tos(), addr, slash-addr);
3422                 if (freeit == NULL) {
3423                         DEBUG(1, ("talloc failed\n"));
3424                         return;
3425                 }
3426                 addr = freeit;
3427                 DEBUG(10, ("Stripped /netmask to IP %s\n", addr));
3428         }
3429
3430         for (domain = domain_list(); domain != NULL; domain = domain->next) {
3431                 char sockaddr[INET6_ADDRSTRLEN];
3432
3433                 if (!cli_state_is_connected(domain->conn.cli)) {
3434                         continue;
3435                 }
3436
3437                 print_sockaddr(sockaddr, sizeof(sockaddr),
3438                                smbXcli_conn_local_sockaddr(domain->conn.cli->conn));
3439
3440                 if (strequal(sockaddr, addr)) {
3441                         smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
3442                 }
3443         }
3444         TALLOC_FREE(freeit);
3445 }
3446
3447 void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx,
3448                                void *private_data,
3449                                uint32_t msg_type,
3450                                struct server_id server_id,
3451                                DATA_BLOB *data)
3452 {
3453         struct winbindd_domain *domain;
3454
3455         for (domain = domain_list(); domain; domain = domain->next) {
3456                 if (domain->internal) {
3457                         continue;
3458                 }
3459                 invalidate_cm_connection(domain);
3460         }
3461 }