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