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 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22*/ 23 24/* 25 We need to manage connections to domain controllers without having to 26 mess up the main winbindd code with other issues. The aim of the 27 connection manager is to: 28 29 - make connections to domain controllers and cache them 30 - re-establish connections when networks or servers go down 31 - centralise the policy on connection timeouts, domain controller 32 selection etc 33 - manage re-entrancy for when winbindd becomes able to handle 34 multiple outstanding rpc requests 35 36 Why not have connection management as part of the rpc layer like tng? 37 Good question. This code may morph into libsmb/rpc_cache.c or something 38 like that but at the moment it's simply staying as part of winbind. I 39 think the TNG architecture of forcing every user of the rpc layer to use 40 the connection caching system is a bad idea. It should be an optional 41 method of using the routines. 42 43 The TNG design is quite good but I disagree with some aspects of the 44 implementation. -tpot 45 46 */ 47 48/* 49 TODO: 50 51 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be 52 moved down into another function. 53 54 - Take care when destroying cli_structs as they can be shared between 55 various sam handles. 56 57 */ 58 59#include "includes.h" 60#include "winbindd.h" 61 62#undef DBGC_CLASS 63#define DBGC_CLASS DBGC_WINBIND 64 65/* Global list of connections. Initially a DLIST but can become a hash 66 table or whatever later. */ 67 68struct winbindd_cm_conn { 69 struct winbindd_cm_conn *prev, *next; 70 fstring domain; 71 fstring controller; 72 fstring pipe_name; 73 struct cli_state *cli; 74 POLICY_HND pol; 75}; 76 77static struct winbindd_cm_conn *cm_conns = NULL; 78 79static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain, 80 const char *pipe_name, 81 struct winbindd_cm_conn **conn_out); 82 83/* Choose between anonymous or authenticated connections. We need to use 84 an authenticated connection if DCs have the RestrictAnonymous registry 85 entry set > 0, or the "Additional restrictions for anonymous 86 connections" set in the win2k Local Security Policy. 87 88 Caller to free() result in domain, username, password 89*/ 90 91static void cm_get_ipc_userpass(char **username, char **domain, char **password) 92{ 93 *username = secrets_fetch(SECRETS_AUTH_USER, NULL); 94 *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL); 95 *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL); 96 97 if (*username && **username) { 98 99 if (!*domain || !**domain) 100 *domain = smb_xstrdup(lp_workgroup()); 101 102 if (!*password || !**password) 103 *password = smb_xstrdup(""); 104 105 DEBUG(3, ("IPC$ connections done by user %s\\%s\n", 106 *domain, *username)); 107 108 } else { 109 DEBUG(3, ("IPC$ connections done anonymously\n")); 110 *username = smb_xstrdup(""); 111 *domain = smb_xstrdup(""); 112 *password = smb_xstrdup(""); 113 } 114} 115 116/* 117 setup for schannel on any pipes opened on this connection 118*/ 119static NTSTATUS setup_schannel( struct cli_state *cli, const char *domain ) 120{ 121 NTSTATUS ret; 122 uchar trust_password[16]; 123 uint32 sec_channel_type; 124 DOM_SID sid; 125 time_t lct; 126 127 /* use the domain trust password if we're on a DC 128 and this is not our domain */ 129 130 if ( IS_DC && !strequal(domain, lp_workgroup()) ) { 131 char *pass = NULL; 132 133 if ( !secrets_fetch_trusted_domain_password( domain, 134 &pass, &sid, &lct) ) 135 { 136 return NT_STATUS_UNSUCCESSFUL; 137 } 138 139 sec_channel_type = SEC_CHAN_DOMAIN; 140 E_md4hash(pass, trust_password); 141 SAFE_FREE( pass ); 142 143 } else { 144 if (!secrets_fetch_trust_account_password(lp_workgroup(), 145 trust_password, NULL, &sec_channel_type)) 146 { 147 return NT_STATUS_UNSUCCESSFUL; 148 } 149 } 150 151 ret = cli_nt_setup_netsec(cli, sec_channel_type, 152 AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN, trust_password); 153 154 return ret; 155} 156 157static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain, 158 fstring dcname, struct in_addr *dc_ip) 159{ 160 struct winbindd_domain *our_domain; 161 NTSTATUS result; 162 struct winbindd_cm_conn *conn; 163 TALLOC_CTX *mem_ctx; 164 165 fstring tmp; 166 char *p; 167 168 if (IS_DC) 169 return False; 170 171 if (domain->primary) 172 return False; 173 174 if ((our_domain = find_our_domain()) == NULL) 175 return False; 176 177 result = get_connection_from_cache(our_domain, PIPE_NETLOGON, &conn); 178 if (!NT_STATUS_IS_OK(result)) 179 return False; 180 181 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) 182 return False; 183 184 result = cli_netlogon_getdcname(conn->cli, mem_ctx, domain->name, tmp); 185 186 talloc_destroy(mem_ctx); 187 188 if (!NT_STATUS_IS_OK(result)) 189 return False; 190 191 /* cli_netlogon_getdcname gives us a name with \\ */ 192 p = tmp; 193 if (*p == '\\') p+=1; 194 if (*p == '\\') p+=1; 195 196 fstrcpy(dcname, p); 197 198 if (!resolve_name(dcname, dc_ip, 0x20)) 199 return False; 200 201 return True; 202} 203 204/************************************************************************ 205 Given a fd with a just-connected TCP connection to a DC, open a connection 206 to the pipe. 207************************************************************************/ 208 209static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, 210 const int sockfd, 211 const int pipe_index, 212 const char *controller, 213 struct cli_state **cli, 214 BOOL *retry) 215{ 216 char *machine_password, *machine_krb5_principal; 217 char *ipc_username, *ipc_domain, *ipc_password; 218 219 BOOL got_mutex; 220 BOOL add_failed_connection = True; 221 222 NTSTATUS result = NT_STATUS_UNSUCCESSFUL; 223 224 struct sockaddr peeraddr; 225 socklen_t peeraddr_len; 226 227 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr; 228 229 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, 230 NULL); 231 232 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), 233 lp_realm()) == -1) { 234 SAFE_FREE(machine_password); 235 return NT_STATUS_NO_MEMORY; 236 } 237 238 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); 239 240 *retry = True; 241 242 got_mutex = secrets_named_mutex(controller, 243 WINBIND_SERVER_MUTEX_WAIT_TIME); 244 245 if (!got_mutex) { 246 DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", 247 controller)); 248 result = NT_STATUS_POSSIBLE_DEADLOCK; 249 goto done; 250 } 251 252 if ((*cli = cli_initialise(NULL)) == NULL) { 253 DEBUG(1, ("Could not cli_initialize\n")); 254 result = NT_STATUS_NO_MEMORY; 255 goto done; 256 } 257 258 (*cli)->timeout = 10000; /* 10 seconds */ 259 (*cli)->fd = sockfd; 260 fstrcpy((*cli)->desthost, controller); 261 (*cli)->use_kerberos = True; 262 263 peeraddr_len = sizeof(peeraddr); 264 265 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) || 266 (peeraddr_len != sizeof(struct sockaddr_in)) || 267 (peeraddr_in->sin_family != PF_INET)) 268 { 269 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno))); 270 goto done; 271 } 272 273 if (ntohs(peeraddr_in->sin_port) == 139) { 274 struct nmb_name calling; 275 struct nmb_name called; 276 277 make_nmb_name(&calling, global_myname(), 0x0); 278 make_nmb_name(&called, "*SMBSERVER", 0x20); 279 280 if (!cli_session_request(*cli, &calling, &called)) { 281 DEBUG(8, ("cli_session_request failed for %s\n", 282 controller)); 283 goto done; 284 } 285 } 286 287 cli_setup_signing_state(*cli, Undefined); 288 289 if (!cli_negprot(*cli)) { 290 DEBUG(1, ("cli_negprot failed\n")); 291 cli_shutdown(*cli); 292 goto done; 293 } 294 295 /* Krb5 session */ 296 297 if ((lp_security() == SEC_ADS) 298 && ((*cli)->protocol >= PROTOCOL_NT1 && 299 (*cli)->capabilities & CAP_EXTENDED_SECURITY)) { 300 301 ADS_STATUS ads_status; 302 (*cli)->use_kerberos = True; 303 DEBUG(5, ("connecting to %s from %s with kerberos principal " 304 "[%s]\n", controller, global_myname(), 305 machine_krb5_principal)); 306 307 ads_status = cli_session_setup_spnego(*cli, 308 machine_krb5_principal, 309 machine_password, 310 lp_workgroup()); 311 312 if (!ADS_ERR_OK(ads_status)) 313 DEBUG(4,("failed kerberos session setup with %s\n", 314 ads_errstr(ads_status))); 315 316 result = ads_ntstatus(ads_status); 317 } 318 319 if (NT_STATUS_IS_OK(result)) 320 goto session_setup_done; 321 322 /* Fall back to non-kerberos session setup */ 323 324 (*cli)->use_kerberos = False; 325 326 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) && 327 (strlen(ipc_username) > 0)) { 328 329 /* Only try authenticated if we have a username */ 330 331 DEBUG(5, ("connecting to %s from %s with username " 332 "[%s]\\[%s]\n", controller, global_myname(), 333 ipc_domain, ipc_username)); 334 335 if (cli_session_setup(*cli, ipc_username, 336 ipc_password, strlen(ipc_password)+1, 337 ipc_password, strlen(ipc_password)+1, 338 ipc_domain)) { 339 DEBUG(5, ("authenticated session setup failed\n")); 340 goto session_setup_done; 341 } 342 } 343 344 /* Fall back to anonymous connection, this might fail later */ 345 346 if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) { 347 DEBUG(5, ("Connected anonymously\n")); 348 goto session_setup_done; 349 } 350 351 result = cli_nt_error(*cli); 352 353 if (NT_STATUS_IS_OK(result)) 354 result = NT_STATUS_UNSUCCESSFUL; 355 356 /* We can't session setup */ 357 358 goto done; 359 360 session_setup_done: 361 362 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) { 363 364 result = cli_nt_error(*cli); 365 366 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result))); 367 368 if (NT_STATUS_IS_OK(result)) 369 result = NT_STATUS_UNSUCCESSFUL; 370 371 cli_shutdown(*cli); 372 goto done; 373 } 374 375 secrets_named_mutex_release(controller); 376 got_mutex = False; 377 *retry = False; 378 379 if (domain->primary || IS_DC) { 380 NTSTATUS status = setup_schannel( *cli, domain->name ); 381 if (!NT_STATUS_IS_OK(status)) { 382 DEBUG(3,("schannel refused - continuing without " 383 "schannel (%s)\n", nt_errstr(status))); 384 } 385 } 386 387 /* set the domain if empty; needed for schannel connections */ 388 if ( !*(*cli)->domain ) 389 fstrcpy( (*cli)->domain, domain->name ); 390 391 if ( !cli_nt_session_open (*cli, pipe_index) ) { 392 393 result = NT_STATUS_PIPE_NOT_AVAILABLE; 394 395 /* This might be a NT4 DC */ 396 if ( is_win2k_pipe(pipe_index) ) 397 add_failed_connection = False; 398 399 cli_shutdown(*cli); 400 goto done; 401 } 402 403 result = NT_STATUS_OK; 404 add_failed_connection = False; 405 406 done: 407 if (got_mutex) 408 secrets_named_mutex_release(controller); 409 410 SAFE_FREE(machine_password); 411 SAFE_FREE(machine_krb5_principal); 412 SAFE_FREE(ipc_username); 413 SAFE_FREE(ipc_domain); 414 SAFE_FREE(ipc_password); 415 416 if (add_failed_connection) 417 add_failed_connection_entry(domain->name, controller, result); 418 419 return result; 420} 421 422struct dc_name_ip { 423 fstring name; 424 struct in_addr ip; 425}; 426 427static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name, 428 const char *dcname, struct in_addr ip, 429 struct dc_name_ip **dcs, int *num) 430{ 431 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) 432 return False; 433 434 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1); 435 436 if (*dcs == NULL) 437 return False; 438 439 fstrcpy((*dcs)[*num].name, dcname); 440 (*dcs)[*num].ip = ip; 441 *num += 1; 442 return True; 443} 444 445static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx, 446 struct in_addr ip, uint16 port, 447 struct sockaddr_in **addrs, int *num) 448{ 449 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1); 450 451 if (*addrs == NULL) 452 return False; 453 454 (*addrs)[*num].sin_family = PF_INET; 455 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip); 456 (*addrs)[*num].sin_port = htons(port); 457 458 *num += 1; 459 return True; 460} 461 462/******************************************************************* 463 convert an ip to a name 464*******************************************************************/ 465 466static void dcip_to_name( const char *domainname, const char *realm, struct in_addr ip, fstring name ) 467{ 468 /* try node status request first */ 469 470 if ( name_status_find(domainname, 0x1c, 0x20, ip, name) ) 471 return; 472 473 /* backup in case the ads stuff fails */ 474 475 fstrcpy( name, inet_ntoa(ip) ); 476 477#ifdef WITH_ADS 478 /* for active directory servers, try to get the ldap server name. 479 None of these failure should be considered critical for now */ 480 481 if ( lp_security() == SEC_ADS ) 482 { 483 ADS_STRUCT *ads; 484 ADS_STATUS status; 485 486 ads = ads_init( realm, domainname, NULL ); 487 ads->auth.flags |= ADS_AUTH_NO_BIND; 488 489 if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) ) { 490 ads_destroy( &ads ); 491 return; 492 } 493 494 status = ads_server_info(ads); 495 if ( !ADS_ERR_OK(status) ) { 496 ads_destroy( &ads ); 497 return; 498 } 499 500 fstrcpy(name, ads->config.ldap_server_name); 501 502 ads_destroy( &ads ); 503 } 504#endif 505 506 return; 507} 508 509 510/******************************************************************* 511 Retreive a list of IP address for domain controllers. Fill in 512 the dcs[] with results. 513*******************************************************************/ 514 515static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, 516 struct dc_name_ip **dcs, int *num_dcs) 517{ 518 fstring dcname; 519 struct in_addr ip; 520 struct ip_service *ip_list = NULL; 521 int iplist_size = 0; 522 int i; 523 BOOL is_our_domain; 524 525 526 is_our_domain = strequal(domain->name, lp_workgroup()); 527 528 if ( !is_our_domain 529 && get_dc_name_via_netlogon(domain, dcname, &ip) 530 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) ) 531 { 532 return True; 533 } 534 535 if ( is_our_domain 536 && must_use_pdc(domain->name) 537 && get_pdc_ip(domain->name, &ip)) 538 { 539 if (add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip), ip, dcs, num_dcs)) 540 return True; 541 } 542 543 /* try standard netbios queries first */ 544 545 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False); 546 547 /* check for security = ads and use DNS if we can */ 548 549 if ( iplist_size==0 && lp_security() == SEC_ADS ) 550 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True); 551 552 /* now add to the dc array. We'll wait until the last minute 553 to look up the name of the DC. But we fill in the char* for 554 the ip now in to make the failed connection cache work */ 555 556 for ( i=0; i<iplist_size; i++ ) { 557 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip), 558 ip_list[i].ip, dcs, num_dcs); 559 } 560 561 SAFE_FREE( ip_list ); 562 563 return True; 564} 565 566static BOOL find_new_dc(TALLOC_CTX *mem_ctx, 567 const struct winbindd_domain *domain, 568 fstring dcname, struct sockaddr_in *addr, int *fd) 569{ 570 struct dc_name_ip *dcs = NULL; 571 int num_dcs = 0; 572 573 const char **dcnames = NULL; 574 int num_dcnames = 0; 575 576 struct sockaddr_in *addrs = NULL; 577 int num_addrs = 0; 578 579 int i, fd_index; 580 581 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0)) 582 return False; 583 584 for (i=0; i<num_dcs; i++) { 585 586 add_string_to_array(mem_ctx, dcs[i].name, 587 &dcnames, &num_dcnames); 588 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445, 589 &addrs, &num_addrs); 590 591 add_string_to_array(mem_ctx, dcs[i].name, 592 &dcnames, &num_dcnames); 593 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139, 594 &addrs, &num_addrs); 595 } 596 597 if ((num_dcnames == 0) || (num_dcnames != num_addrs)) 598 return False; 599 600 if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) ) 601 { 602 for (i=0; i<num_dcs; i++) { 603 add_failed_connection_entry(domain->name, 604 dcs[i].name, NT_STATUS_UNSUCCESSFUL); 605 } 606 return False; 607 } 608 609 *addr = addrs[fd_index]; 610 611 /* if we have no name on the server or just an IP address for 612 the name, now try to get the name */ 613 614 if ( is_ipaddress(dcnames[fd_index]) || *dcnames[fd_index] == '\0' ) 615 dcip_to_name( domain->name, domain->alt_name, addr->sin_addr, dcname ); 616 else 617 fstrcpy(dcname, dcnames[fd_index]); 618 619 return True; 620} 621 622static NTSTATUS cm_open_connection(struct winbindd_domain *domain, 623 const int pipe_index, 624 struct winbindd_cm_conn *new_conn) 625{ 626 TALLOC_CTX *mem_ctx; 627 NTSTATUS result; 628 629 int retries; 630 631 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) 632 return NT_STATUS_NO_MEMORY; 633 634 for (retries = 0; retries < 3; retries++) { 635 636 int fd = -1; 637 BOOL retry; 638 639 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; 640 641 if ((strlen(domain->dcname) > 0) && 642 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, 643 domain->dcname))) { 644 int dummy; 645 if (!open_any_socket_out(&domain->dcaddr, 1, 10000, 646 &dummy, &fd)) { 647 fd = -1; 648 } 649 } 650 651 if ((fd == -1) && 652 !find_new_dc(mem_ctx, domain, domain->dcname, 653 &domain->dcaddr, &fd)) 654 break; 655 656 new_conn->cli = NULL; 657 658 result = cm_prepare_connection(domain, fd, pipe_index, 659 domain->dcname, 660 &new_conn->cli, &retry); 661 662 if (NT_STATUS_IS_OK(result)) { 663 fstrcpy(new_conn->domain, domain->name); 664 /* Initialise SMB connection */ 665 fstrcpy(new_conn->pipe_name, 666 get_pipe_name_from_index(pipe_index)); 667 break; 668 } 669 670 if (!retry) 671 break; 672 } 673 674 talloc_destroy(mem_ctx); 675 return result; 676} 677 678/************************************************************************ 679 Wrapper around statuc cm_open_connection to retreive a freshly 680 setup cli_state struct 681************************************************************************/ 682 683NTSTATUS cm_fresh_connection(struct winbindd_domain *domain, const int pipe_index, 684 struct cli_state **cli) 685{ 686 NTSTATUS result; 687 struct winbindd_cm_conn conn; 688 689 result = cm_open_connection( domain, pipe_index, &conn ); 690 691 if ( NT_STATUS_IS_OK(result) ) 692 *cli = conn.cli; 693 694 return result; 695} 696 697/* Return true if a connection is still alive */ 698 699static BOOL connection_ok(struct winbindd_cm_conn *conn) 700{ 701 if (!conn) { 702 smb_panic("Invalid parameter passed to connection_ok(): conn was NULL!\n"); 703 return False; 704 } 705 706 if (!conn->cli) { 707 DEBUG(3, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n", 708 conn->controller, conn->domain, conn->pipe_name)); 709 return False; 710 } 711 712 if (!conn->cli->initialised) { 713 DEBUG(3, ("Connection to %s for domain %s (pipe %s) was never initialised!\n", 714 conn->controller, conn->domain, conn->pipe_name)); 715 return False; 716 } 717 718 if (conn->cli->fd == -1) { 719 DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n", 720 conn->controller, conn->domain, conn->pipe_name)); 721 return False; 722 } 723 724 return True; 725} 726 727/* Search the cache for a connection. If there is a broken one, 728 shut it down properly and return NULL. */ 729 730static void find_cm_connection(struct winbindd_domain *domain, const char *pipe_name, 731 struct winbindd_cm_conn **conn_out) 732{ 733 struct winbindd_cm_conn *conn; 734 735 for (conn = cm_conns; conn; ) { 736 if (strequal(conn->domain, domain->name) && 737 strequal(conn->pipe_name, pipe_name)) { 738 if (!connection_ok(conn)) { 739 /* Dead connection - remove it. */ 740 struct winbindd_cm_conn *conn_temp = conn->next; 741 if (conn->cli) 742 cli_shutdown(conn->cli); 743 DLIST_REMOVE(cm_conns, conn); 744 SAFE_FREE(conn); 745 conn = conn_temp; /* Keep the loop moving */ 746 continue; 747 } else { 748 break; 749 } 750 } 751 conn = conn->next; 752 } 753 754 *conn_out = conn; 755} 756 757/* Initialize a new connection up to the RPC BIND. */ 758 759static NTSTATUS new_cm_connection(struct winbindd_domain *domain, const char *pipe_name, 760 struct winbindd_cm_conn **conn_out) 761{ 762 struct winbindd_cm_conn *conn; 763 NTSTATUS result; 764 765 if (!(conn = SMB_MALLOC_P(struct winbindd_cm_conn))) 766 return NT_STATUS_NO_MEMORY; 767 768 ZERO_STRUCTP(conn); 769 770 if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) { 771 DEBUG(3, ("Could not open a connection to %s for %s (%s)\n", 772 domain->name, pipe_name, nt_errstr(result))); 773 SAFE_FREE(conn); 774 return result; 775 } 776 DLIST_ADD(cm_conns, conn); 777 778 *conn_out = conn; 779 return NT_STATUS_OK; 780} 781 782/* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */ 783 784static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain, const char *pipe_name, 785 struct winbindd_cm_conn **conn_out) 786{ 787 find_cm_connection(domain, pipe_name, conn_out); 788 789 if (*conn_out != NULL) 790 return NT_STATUS_OK; 791 792 return new_cm_connection(domain, pipe_name, conn_out); 793} 794 795/********************************************************************************** 796 We can 'sense' certain things about the DC by it's replies to certain questions. 797 798 This tells us if this particular remote server is Active Directory, and if it is 799 native mode. 800**********************************************************************************/ 801 802void set_dc_type_and_flags( struct winbindd_domain *domain ) 803{ 804 NTSTATUS result; 805 struct winbindd_cm_conn conn; 806 DS_DOMINFO_CTR ctr; 807 TALLOC_CTX *mem_ctx = NULL; 808 809 ZERO_STRUCT( conn ); 810 ZERO_STRUCT( ctr ); 811 812 domain->native_mode = False; 813 domain->active_directory = False; 814 815 if (domain->internal) { 816 domain->initialized = True; 817 return; 818 } 819 820 if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) { 821 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection to %s for PIPE_LSARPC (%s)\n", 822 domain->name, nt_errstr(result))); 823 domain->initialized = True; 824 return; 825 } 826 827 if ( conn.cli ) { 828 if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli, 829 conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) { 830 goto done; 831 } 832 } 833 834 if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) 835 && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) ) 836 domain->native_mode = True; 837 838 /* Cheat - shut down the DS pipe, and open LSA */ 839 840 cli_nt_session_close(conn.cli); 841 842 if ( cli_nt_session_open (conn.cli, PI_LSARPC) ) { 843 char *domain_name = NULL; 844 char *dns_name = NULL; 845 DOM_SID *dom_sid = NULL; 846 847 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n", domain->name); 848 if (!mem_ctx) { 849 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n")); 850 return; 851 } 852 853 result = cli_lsa_open_policy2(conn.cli, mem_ctx, True, 854 SEC_RIGHTS_MAXIMUM_ALLOWED, 855 &conn.pol); 856 857 if (NT_STATUS_IS_OK(result)) { 858 /* This particular query is exactly what Win2k clients use 859 to determine that the DC is active directory */ 860 result = cli_lsa_query_info_policy2(conn.cli, mem_ctx, 861 &conn.pol, 862 12, &domain_name, 863 &dns_name, NULL, 864 NULL, &dom_sid); 865 } 866 867 if (NT_STATUS_IS_OK(result)) { 868 if (domain_name) 869 fstrcpy(domain->name, domain_name); 870 871 if (dns_name) 872 fstrcpy(domain->alt_name, dns_name); 873 874 if (dom_sid) 875 sid_copy(&domain->sid, dom_sid); 876 877 domain->active_directory = True; 878 } else { 879 880 result = cli_lsa_open_policy(conn.cli, mem_ctx, True, 881 SEC_RIGHTS_MAXIMUM_ALLOWED, 882 &conn.pol); 883 884 if (!NT_STATUS_IS_OK(result)) 885 goto done; 886 887 result = cli_lsa_query_info_policy(conn.cli, mem_ctx, 888 &conn.pol, 5, &domain_name, 889 &dom_sid); 890 891 if (NT_STATUS_IS_OK(result)) { 892 if (domain_name) 893 fstrcpy(domain->name, domain_name); 894 895 if (dom_sid) 896 sid_copy(&domain->sid, dom_sid); 897 } 898 } 899 } 900 901done: 902 903 DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name, 904 domain->active_directory ? "ADS" : "NT4", 905 domain->native_mode ? "native mode" : 906 ((domain->active_directory && !domain->native_mode) ? "mixed mode" : ""))); 907 908 /* close the connection; no other calls use this pipe and it is called only 909 on reestablishing the domain list --jerry */ 910 911 if ( conn.cli ) 912 cli_shutdown( conn.cli ); 913 914 talloc_destroy(mem_ctx); 915 916 domain->initialized = True; 917 918 return; 919} 920 921 922 923/* Return a LSA policy handle on a domain */ 924 925NTSTATUS cm_get_lsa_handle(struct winbindd_domain *domain, CLI_POLICY_HND **return_hnd) 926{ 927 struct winbindd_cm_conn *conn; 928 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; 929 NTSTATUS result; 930 static CLI_POLICY_HND hnd; 931 932 /* Look for existing connections */ 933 934 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) 935 return result; 936 937 /* This *shitty* code needs scrapping ! JRA */ 938 939 if (policy_handle_is_valid(&conn->pol)) { 940 hnd.pol = conn->pol; 941 hnd.cli = conn->cli; 942 *return_hnd = &hnd; 943 944 return NT_STATUS_OK; 945 } 946 947 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, 948 des_access, &conn->pol); 949 950 if (!NT_STATUS_IS_OK(result)) { 951 /* Hit the cache code again. This cleans out the old connection and gets a new one */ 952 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */ 953 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) 954 return result; 955 956 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, 957 des_access, &conn->pol); 958 } 959 960 if (!NT_STATUS_IS_OK(result)) { 961 cli_shutdown(conn->cli); 962 DLIST_REMOVE(cm_conns, conn); 963 SAFE_FREE(conn); 964 return result; 965 } 966 } 967 968 hnd.pol = conn->pol; 969 hnd.cli = conn->cli; 970 971 *return_hnd = &hnd; 972 973 return NT_STATUS_OK; 974} 975 976/* Return a SAM policy handle on a domain */ 977 978NTSTATUS cm_get_sam_handle(struct winbindd_domain *domain, CLI_POLICY_HND **return_hnd) 979{ 980 struct winbindd_cm_conn *conn; 981 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; 982 NTSTATUS result; 983 static CLI_POLICY_HND hnd; 984 985 /* Look for existing connections */ 986 987 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) 988 return result; 989 990 /* This *shitty* code needs scrapping ! JRA */ 991 992 if (policy_handle_is_valid(&conn->pol)) { 993 hnd.pol = conn->pol; 994 hnd.cli = conn->cli; 995 996 *return_hnd = &hnd; 997 998 return NT_STATUS_OK; 999 } 1000 1001 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx, 1002 des_access, &conn->pol); 1003 1004 if (!NT_STATUS_IS_OK(result)) { 1005 /* Hit the cache code again. This cleans out the old connection and gets a new one */ 1006 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */ 1007 1008 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) 1009 return result; 1010 1011 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx, 1012 des_access, &conn->pol); 1013 } 1014 1015 if (!NT_STATUS_IS_OK(result)) { 1016 1017 cli_shutdown(conn->cli); 1018 DLIST_REMOVE(cm_conns, conn); 1019 SAFE_FREE(conn); 1020 1021 return result; 1022 } 1023 } 1024 1025 hnd.pol = conn->pol; 1026 hnd.cli = conn->cli; 1027 1028 *return_hnd = &hnd; 1029 1030 return NT_STATUS_OK; 1031} 1032 1033/* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the 1034 netlogon pipe as no handle is returned. */ 1035 1036NTSTATUS cm_get_netlogon_cli(struct winbindd_domain *domain, 1037 const unsigned char *trust_passwd, 1038 uint32 sec_channel_type, 1039 BOOL fresh, 1040 struct cli_state **cli) 1041{ 1042 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; 1043 struct winbindd_cm_conn *conn; 1044 fstring lock_name; 1045 BOOL got_mutex; 1046 1047 if (!cli) 1048 return NT_STATUS_INVALID_PARAMETER; 1049 1050 /* Open an initial conection - keep the mutex. */ 1051 1052 find_cm_connection(domain, PIPE_NETLOGON, &conn); 1053 1054 if ( fresh && (conn != NULL) ) { 1055 cli_shutdown(conn->cli); 1056 conn->cli = NULL; 1057 1058 conn = NULL; 1059 1060 /* purge connection from cache */ 1061 find_cm_connection(domain, PIPE_NETLOGON, &conn); 1062 if (conn != NULL) { 1063 DEBUG(0,("Could not purge connection\n")); 1064 return NT_STATUS_UNSUCCESSFUL; 1065 } 1066 } 1067 1068 if (conn != NULL) { 1069 *cli = conn->cli; 1070 return NT_STATUS_OK; 1071 } 1072 1073 result = new_cm_connection(domain, PIPE_NETLOGON, &conn); 1074 1075 if (!NT_STATUS_IS_OK(result)) 1076 return result; 1077 1078 fstr_sprintf(lock_name, "NETLOGON\\%s", conn->controller); 1079 1080 if (!(got_mutex = secrets_named_mutex(lock_name, WINBIND_SERVER_MUTEX_WAIT_TIME))) { 1081 DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", conn->controller)); 1082 } 1083 1084 if ( sec_channel_type == SEC_CHAN_DOMAIN ) 1085 fstr_sprintf(conn->cli->mach_acct, "%s$", lp_workgroup()); 1086 1087 /* This must be the remote domain (not ours) for schannel */ 1088 1089 fstrcpy( conn->cli->domain, domain->name); 1090 1091 result = cli_nt_establish_netlogon(conn->cli, sec_channel_type, trust_passwd); 1092 1093 if (got_mutex) 1094 secrets_named_mutex_release(lock_name); 1095 1096 if (!NT_STATUS_IS_OK(result)) { 1097 cli_shutdown(conn->cli); 1098 DLIST_REMOVE(cm_conns, conn); 1099 SAFE_FREE(conn); 1100 return result; 1101 } 1102 1103 *cli = conn->cli; 1104 1105 return result; 1106} 1107 1108/* Dump the current connection status */ 1109 1110static void dump_conn_list(void) 1111{ 1112 struct winbindd_cm_conn *con; 1113 1114 DEBUG(0, ("\tDomain Controller Pipe\n")); 1115 1116 for(con = cm_conns; con; con = con->next) { 1117 char *msg; 1118 1119 /* Display pipe info */ 1120 1121 if (asprintf(&msg, "\t%-15s %-15s %-16s", con->domain, con->controller, con->pipe_name) < 0) { 1122 DEBUG(0, ("Error: not enough memory!\n")); 1123 } else { 1124 DEBUG(0, ("%s\n", msg)); 1125 SAFE_FREE(msg); 1126 } 1127 } 1128} 1129 1130void winbindd_cm_status(void) 1131{ 1132 /* List open connections */ 1133 1134 DEBUG(0, ("winbindd connection manager status:\n")); 1135 1136 if (cm_conns) 1137 dump_conn_list(); 1138 else 1139 DEBUG(0, ("\tNo active connections\n")); 1140} 1141 1142/* Close all cached connections */ 1143 1144void winbindd_cm_flush(void) 1145{ 1146 struct winbindd_cm_conn *conn, tmp; 1147 1148 /* Flush connection cache */ 1149 1150 for (conn = cm_conns; conn; conn = conn->next) { 1151 1152 if (!connection_ok(conn)) 1153 continue; 1154 1155 DEBUG(10, ("Closing connection to %s on %s\n", 1156 conn->pipe_name, conn->controller)); 1157 1158 if (conn->cli) 1159 cli_shutdown(conn->cli); 1160 1161 tmp.next = conn->next; 1162 1163 DLIST_REMOVE(cm_conns, conn); 1164 SAFE_FREE(conn); 1165 conn = &tmp; 1166 } 1167 1168 /* Flush failed connection cache */ 1169 1170 flush_negative_conn_cache(); 1171} 1172