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