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