X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fwinbindd%2Fwinbindd_cm.c;h=ace0160a1cf80bbbbdbe772d6952357606a544d2;hb=68ea47c27830b831e1be9725dff86bc3e17107cf;hp=85630502734a0ca872f51ca1c20c1eb70b59a418;hpb=c53a52a264c51d87190623ac2c9595e05c8e8695;p=mat%2Fsamba.git diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 8563050273..ace0160a1c 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -76,6 +76,9 @@ #include "../libcli/security/security.h" #include "passdb.h" #include "messages.h" +#include "auth/gensec/gensec.h" +#include "../libcli/smb/smbXcli_base.h" +#include "lib/param/loadparm.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -187,7 +190,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) struct dc_name_ip *dcs = NULL; int num_dcs = 0; TALLOC_CTX *mem_ctx = NULL; - pid_t parent_pid = sys_getpid(); + pid_t parent_pid = getpid(); char *lfile = NULL; NTSTATUS status; @@ -205,7 +208,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) domain->dc_probe_pid = (pid_t)-1; } - domain->dc_probe_pid = sys_fork(); + domain->dc_probe_pid = fork(); if (domain->dc_probe_pid == (pid_t)-1) { DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno))); @@ -241,7 +244,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) messaging_send_buf(winbind_messaging_context(), pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE, - (uint8 *)domain->name, + (const uint8_t *)domain->name, strlen(domain->name)+1); _exit(1); } @@ -253,7 +256,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) messaging_send_buf(winbind_messaging_context(), pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE, - (uint8 *)domain->name, + (const uint8_t *)domain->name, strlen(domain->name)+1); _exit(1); } @@ -263,7 +266,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) messaging_send_buf(winbind_messaging_context(), pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE, - (uint8 *)domain->name, + (const uint8_t *)domain->name, strlen(domain->name)+1); _exit(0); } @@ -274,7 +277,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) messaging_send_buf(winbind_messaging_context(), pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE, - (uint8 *)domain->name, + (const uint8_t *)domain->name, strlen(domain->name)+1); _exit(0); } @@ -283,8 +286,8 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) Handler triggered if we're offline to try and detect a DC. ****************************************************************/ -static void check_domain_online_handler(struct event_context *ctx, - struct timed_event *te, +static void check_domain_online_handler(struct tevent_context *ctx, + struct tevent_timer *te, struct timeval now, void *private_data) { @@ -337,6 +340,46 @@ static void calc_new_online_timeout_check(struct winbindd_domain *domain) } } +void winbind_msg_domain_offline(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + const char *domain_name = (const char *)data->data; + struct winbindd_domain *domain; + + domain = find_domain_from_name_noinit(domain_name); + if (domain == NULL) { + return; + } + + domain->online = false; + + DEBUG(10, ("Domain %s is marked as offline now.\n", + domain_name)); +} + +void winbind_msg_domain_online(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + const char *domain_name = (const char *)data->data; + struct winbindd_domain *domain; + + domain = find_domain_from_name_noinit(domain_name); + if (domain == NULL) { + return; + } + + domain->online = true; + + DEBUG(10, ("Domain %s is marked as online now.\n", + domain_name)); +} + /**************************************************************** Set domain offline and also add handler to put us back online if we detect a DC. @@ -344,6 +387,8 @@ static void calc_new_online_timeout_check(struct winbindd_domain *domain) void set_domain_offline(struct winbindd_domain *domain) { + pid_t parent_pid = getppid(); + DEBUG(10,("set_domain_offline: called for domain %s\n", domain->name )); @@ -377,7 +422,7 @@ void set_domain_offline(struct winbindd_domain *domain) calc_new_online_timeout_check(domain); - domain->check_online_event = event_add_timed(winbind_event_context(), + domain->check_online_event = tevent_add_timer(winbind_event_context(), NULL, timeval_current_ofs(domain->check_online_timeout,0), check_domain_online_handler, @@ -391,6 +436,15 @@ void set_domain_offline(struct winbindd_domain *domain) DEBUG(10,("set_domain_offline: added event handler for domain %s\n", domain->name )); + /* Send a message to the parent that the domain is offline. */ + if (parent_pid > 1 && !domain->internal) { + messaging_send_buf(winbind_messaging_context(), + pid_to_procid(parent_pid), + MSG_WINBIND_DOMAIN_OFFLINE, + (uint8 *)domain->name, + strlen(domain->name) + 1); + } + /* Send an offline message to the idmap child when our primary domain goes offline */ @@ -401,7 +455,7 @@ void set_domain_offline(struct winbindd_domain *domain) messaging_send_buf(winbind_messaging_context(), pid_to_procid(idmap->pid), MSG_WINBIND_OFFLINE, - (uint8 *)domain->name, + (const uint8_t *)domain->name, strlen(domain->name)+1); } } @@ -415,6 +469,8 @@ void set_domain_offline(struct winbindd_domain *domain) static void set_domain_online(struct winbindd_domain *domain) { + pid_t parent_pid = getppid(); + DEBUG(10,("set_domain_online: called for domain %s\n", domain->name )); @@ -466,6 +522,15 @@ static void set_domain_online(struct winbindd_domain *domain) domain->online = True; + /* Send a message to the parent that the domain is online. */ + if (parent_pid > 1 && !domain->internal) { + messaging_send_buf(winbind_messaging_context(), + pid_to_procid(parent_pid), + MSG_WINBIND_DOMAIN_ONLINE, + (uint8 *)domain->name, + strlen(domain->name) + 1); + } + /* Send an online message to the idmap child when our primary domain comes online */ @@ -476,7 +541,7 @@ static void set_domain_online(struct winbindd_domain *domain) messaging_send_buf(winbind_messaging_context(), pid_to_procid(idmap->pid), MSG_WINBIND_ONLINE, - (uint8 *)domain->name, + (const uint8_t *)domain->name, strlen(domain->name)+1); } } @@ -533,7 +598,7 @@ void set_domain_online_request(struct winbindd_domain *domain) TALLOC_FREE(domain->check_online_event); - domain->check_online_event = event_add_timed(winbind_event_context(), + domain->check_online_event = tevent_add_timer(winbind_event_context(), NULL, tev, check_domain_online_handler, @@ -558,7 +623,7 @@ static void winbind_add_failed_connection_entry( /* If this was the saf name for the last thing we talked to, remove it. */ saf_delete(domain->name); - if (*domain->alt_name) { + if (domain->alt_name != NULL) { add_failed_connection_entry(domain->alt_name, server, result); saf_delete(domain->alt_name); } @@ -662,13 +727,23 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, talloc_destroy(mem_ctx); return false; } - if (strlen(domain->alt_name) == 0) { - fstrcpy(domain->alt_name, - domain_info->domain_name); + if (domain->alt_name == NULL) { + domain->alt_name = talloc_strdup(domain, + domain_info->domain_name); + if (domain->alt_name == NULL) { + DEBUG(0, ("talloc_strdup failed\n")); + talloc_destroy(mem_ctx); + return false; + } } - if (strlen(domain->forest_name) == 0) { - fstrcpy(domain->forest_name, - domain_info->forest_name); + if (domain->forest_name == NULL) { + domain->forest_name = talloc_strdup(domain, + domain_info->forest_name); + if (domain->forest_name == NULL) { + DEBUG(0, ("talloc_strdup failed\n")); + talloc_destroy(mem_ctx); + return false; + } } } } else { @@ -764,7 +839,10 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - strupper_m(*machine_krb5_principal); + if (!strupper_m(*machine_krb5_principal)) { + SAFE_FREE(*machine_krb5_principal); + return NT_STATUS_INVALID_PARAMETER; + } } return NT_STATUS_OK; @@ -781,6 +859,8 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, struct cli_state **cli, bool *retry) { + bool try_spnego = false; + bool try_ipc_auth = false; char *machine_password = NULL; char *machine_krb5_principal = NULL; char *machine_account = NULL; @@ -823,17 +903,23 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, cli_set_timeout(*cli, 10000); /* 10 seconds */ - result = cli_negprot(*cli, PROTOCOL_NT1); + result = smbXcli_negprot((*cli)->conn, (*cli)->timeout, + lp_cli_minprotocol(), + lp_cli_maxprotocol()); if (!NT_STATUS_IS_OK(result)) { DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result))); goto done; } - if (!is_dc_trusted_domain_situation(domain->name) && - cli_state_protocol(*cli) >= PROTOCOL_NT1 && - cli_state_capabilities(*cli) & CAP_EXTENDED_SECURITY) - { + if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 && + smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) { + try_spnego = true; + } else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) { + try_spnego = true; + } + + if (!is_dc_trusted_domain_situation(domain->name) && try_spnego) { result = get_trust_creds(domain, &machine_password, &machine_account, &machine_krb5_principal); @@ -910,9 +996,16 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); - sec_mode = cli_state_security_mode(*cli); - if (((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) && - (strlen(ipc_username) > 0)) { + sec_mode = smb1cli_conn_server_security_mode((*cli)->conn); + + try_ipc_auth = false; + if (try_spnego) { + try_ipc_auth = true; + } else if (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) { + try_ipc_auth = true; + } + + if (try_ipc_auth && (strlen(ipc_username) > 0)) { /* Only try authenticated if we have a username */ @@ -959,6 +1052,17 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, session_setup_done: + /* + * This should be a short term hack until + * dynamic re-authentication is implemented. + * + * See Bug 9175 - winbindd doesn't recover from + * NT_STATUS_NETWORK_SESSION_EXPIRED + */ + if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) { + smbXcli_session_set_disconnect_expired((*cli)->smb2.session); + } + /* cache the server name for later connections */ saf_store(domain->name, controller); @@ -982,6 +1086,9 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, if ( !(*cli)->domain[0] ) { result = cli_set_domain((*cli), domain->name); if (!NT_STATUS_IS_OK(result)) { + SAFE_FREE(ipc_username); + SAFE_FREE(ipc_domain); + SAFE_FREE(ipc_password); return result; } } @@ -1077,12 +1184,13 @@ static bool add_sockaddr_to_array(TALLOC_CTX *mem_ctx, static bool dcip_to_name(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, struct sockaddr_storage *pss, - fstring name ) + char **name) { struct ip_service ip_list; uint32_t nt_version = NETLOGON_NT_VERSION_1; NTSTATUS status; const char *dc_name; + fstring nbtname; ip_list.ss = *pss; ip_list.port = 0; @@ -1104,14 +1212,18 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, ads_status = ads_connect(ads); if (ADS_ERR_OK(ads_status)) { /* We got a cldap packet. */ - fstrcpy(name, ads->config.ldap_server_name); - namecache_store(name, 0x20, 1, &ip_list); + *name = talloc_strdup(mem_ctx, + ads->config.ldap_server_name); + if (*name == NULL) { + return false; + } + namecache_store(*name, 0x20, 1, &ip_list); DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags)); if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) { if (ads_closest_dc(ads)) { - char *sitename = sitename_fetch(ads->config.realm); + char *sitename = sitename_fetch(mem_ctx, ads->config.realm); /* We're going to use this KDC for this realm/domain. If we are using sites, then force the krb5 libs @@ -1121,22 +1233,22 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, domain->name, sitename, pss, - name); + *name); - SAFE_FREE(sitename); + TALLOC_FREE(sitename); } else { /* use an off site KDC */ create_local_private_krb5_conf_for_domain(domain->alt_name, domain->name, NULL, pss, - name); + *name); } winbindd_set_locator_kdc_envs(domain); /* Ensure we contact this DC also. */ - saf_store( domain->name, name); - saf_store( domain->alt_name, name); + saf_store(domain->name, *name); + saf_store(domain->alt_name, *name); } ads_destroy( &ads ); @@ -1144,23 +1256,35 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, } ads_destroy( &ads ); + return false; } #endif - status = nbt_getdc(winbind_messaging_context(), pss, domain->name, + status = nbt_getdc(winbind_messaging_context(), 10, pss, domain->name, &domain->sid, nt_version, mem_ctx, &nt_version, &dc_name, NULL); if (NT_STATUS_IS_OK(status)) { - fstrcpy(name, dc_name); - namecache_store(name, 0x20, 1, &ip_list); + *name = talloc_strdup(mem_ctx, dc_name); + if (*name == NULL) { + return false; + } + namecache_store(*name, 0x20, 1, &ip_list); return True; } /* try node status request */ - if ( name_status_find(domain->name, 0x1c, 0x20, pss, name) ) { - namecache_store(name, 0x20, 1, &ip_list); - return True; + if (name_status_find(domain->name, 0x1c, 0x20, pss, nbtname) ) { + namecache_store(nbtname, 0x20, 1, &ip_list); + + if (name != NULL) { + *name = talloc_strdup(mem_ctx, nbtname); + if (*name == NULL) { + return false; + } + } + + return true; } return False; } @@ -1217,7 +1341,7 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, get_dc_name(domain->name, domain->alt_name, dcname, &ss); - sitename = sitename_fetch(domain->alt_name); + sitename = sitename_fetch(mem_ctx, domain->alt_name); if (sitename) { /* Do the site-specific AD dns lookup first. */ @@ -1241,7 +1365,7 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, } SAFE_FREE(ip_list); - SAFE_FREE(sitename); + TALLOC_FREE(sitename); iplist_size = 0; } @@ -1265,10 +1389,17 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, iplist_size = 0; } - /* Try standard netbios queries if no ADS */ + /* Try standard netbios queries if no ADS and fall back to DNS queries + * if alt_name is available */ if (*num_dcs == 0) { get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, - False); + false); + if (iplist_size == 0) { + if (domain->alt_name != NULL) { + get_sorted_dc_list(domain->alt_name, NULL, &ip_list, + &iplist_size, true); + } + } for ( i=0; iconn)); key = current_dc_key(talloc_tos(), domain_name); if (key == NULL) { @@ -1440,7 +1574,7 @@ bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx, if (key == NULL) { goto done; } - if (!gencache_get(key, &value, NULL)) { + if (!gencache_get(key, mem_ctx, &value, NULL)) { goto done; } p = strchr(value, ' '); @@ -1469,6 +1603,7 @@ done: TALLOC_FREE(dc_name); TALLOC_FREE(dc_ip); TALLOC_FREE(key); + TALLOC_FREE(value); return ret; } @@ -1477,15 +1612,16 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, { TALLOC_CTX *mem_ctx; NTSTATUS result; - char *saf_servername = saf_fetch( domain->name ); + char *saf_servername; int retries; if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) { - SAFE_FREE(saf_servername); set_domain_offline(domain); return NT_STATUS_NO_MEMORY; } + saf_servername = saf_fetch(mem_ctx, domain->name ); + /* we have to check the server affinity cache here since later we select a DC based on response time and not preference */ @@ -1500,37 +1636,46 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, /* convert an ip address to a name */ if (is_ipaddress( saf_servername ) ) { - fstring saf_name; + char *dcname = NULL; struct sockaddr_storage ss; if (!interpret_string_addr(&ss, saf_servername, AI_NUMERICHOST)) { + TALLOC_FREE(mem_ctx); return NT_STATUS_UNSUCCESSFUL; } - if (dcip_to_name(mem_ctx, domain, &ss, saf_name )) { - strlcpy(domain->dcname, saf_name, sizeof(domain->dcname)); + if (dcip_to_name(mem_ctx, domain, &ss, &dcname)) { + domain->dcname = talloc_strdup(domain, + dcname); + if (domain->dcname == NULL) { + TALLOC_FREE(mem_ctx); + return NT_STATUS_NO_MEMORY; + } } else { winbind_add_failed_connection_entry( domain, saf_servername, NT_STATUS_UNSUCCESSFUL); } } else { - fstrcpy( domain->dcname, saf_servername ); + domain->dcname = talloc_strdup(domain, saf_servername); + if (domain->dcname == NULL) { + TALLOC_FREE(mem_ctx); + return NT_STATUS_NO_MEMORY; + } } - - SAFE_FREE( saf_servername ); } for (retries = 0; retries < 3; retries++) { int fd = -1; bool retry = False; + char *dcname = NULL; result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n", - domain->dcname, domain->name )); + domain->dcname ? domain->dcname : "", domain->name )); - if (*domain->dcname + if (domain->dcname != NULL && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname)) && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true))) { @@ -1544,8 +1689,8 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, } } - if ((fd == -1) - && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd)) + if ((fd == -1) && + !find_new_dc(mem_ctx, domain, &dcname, &domain->dcaddr, &fd)) { /* This is the one place where we will set the global winbindd offline state @@ -1554,11 +1699,24 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, set_global_winbindd_state_offline(); break; } + if (dcname != NULL) { + talloc_free(domain->dcname); + + domain->dcname = talloc_move(domain, &dcname); + if (domain->dcname == NULL) { + result = NT_STATUS_NO_MEMORY; + break; + } + } new_conn->cli = NULL; result = cm_prepare_connection(domain, fd, domain->dcname, &new_conn->cli, &retry); + if (!NT_STATUS_IS_OK(result)) { + /* Don't leak the smb connection socket */ + close(fd); + } if (!retry) break; @@ -1675,7 +1833,7 @@ void close_conns_after_fork(void) * requests in invalidate_cm_connection() */ if (cli_state_is_connected(domain->conn.cli)) { - cli_state_disconnect(domain->conn.cli); + smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK); } invalidate_cm_connection(&domain->conn); @@ -1723,12 +1881,6 @@ static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain) return NT_STATUS_OK; } - if (!winbindd_can_contact_domain(domain)) { - invalidate_cm_connection(&domain->conn); - domain->initialized = True; - return NT_STATUS_OK; - } - if (connection_ok(domain)) { if (!domain->initialized) { set_dc_type_and_flags(domain); @@ -1881,6 +2033,8 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) "running active directory.\n", domain->name, domain->active_directory ? "" : "NOT ")); + domain->can_do_ncacn_ip_tcp = domain->active_directory; + domain->can_do_validation6 = domain->active_directory; domain->initialized = True; @@ -1925,7 +2079,7 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name )); status = cli_rpc_pipe_open_noauth(domain->conn.cli, - &ndr_table_dssetup.syntax_id, + &ndr_table_dssetup, &cli); if (!NT_STATUS_IS_OK(status)) { @@ -1976,7 +2130,7 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) no_dssetup: status = cli_rpc_pipe_open_noauth(domain->conn.cli, - &ndr_table_lsarpc.syntax_id, &cli); + &ndr_table_lsarpc, &cli); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to " @@ -2004,20 +2158,35 @@ no_dssetup: domain->active_directory = True; if (lsa_info->dns.name.string) { - fstrcpy(domain->name, lsa_info->dns.name.string); + talloc_free(domain->name); + domain->name = talloc_strdup(domain, + lsa_info->dns.name.string); + if (domain->name == NULL) { + goto done; + } } if (lsa_info->dns.dns_domain.string) { - fstrcpy(domain->alt_name, - lsa_info->dns.dns_domain.string); + talloc_free(domain->alt_name); + domain->alt_name = + talloc_strdup(domain, + lsa_info->dns.dns_domain.string); + if (domain->alt_name == NULL) { + goto done; + } } /* See if we can set some domain trust flags about ourself */ if (lsa_info->dns.dns_forest.string) { - fstrcpy(domain->forest_name, - lsa_info->dns.dns_forest.string); + talloc_free(domain->forest_name); + domain->forest_name = + talloc_strdup(domain, + lsa_info->dns.dns_forest.string); + if (domain->forest_name == NULL) { + goto done; + } if (strequal(domain->forest_name, domain->alt_name)) { domain->domain_flags |= NETR_TRUST_FLAG_TREEROOT; @@ -2046,8 +2215,10 @@ no_dssetup: if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) { if (lsa_info->account_domain.name.string) { - fstrcpy(domain->name, - lsa_info->account_domain.name.string); + talloc_free(domain->name); + domain->name = + talloc_strdup(domain, + lsa_info->account_domain.name.string); } if (lsa_info->account_domain.sid) { @@ -2138,9 +2309,9 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, struct netlogon_creds_CredentialState *p_creds; char *machine_password = NULL; char *machine_account = NULL; - char *domain_name = NULL; + const char *domain_name = NULL; - if (sid_check_is_domain(&domain->sid)) { + if (sid_check_is_our_sam(&domain->sid)) { return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle); } @@ -2189,14 +2360,16 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, /* We have an authenticated connection. Use a NTLMSSP SPNEGO authenticated SAMR pipe with sign & seal. */ - status = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, - &ndr_table_samr.syntax_id, - NCACN_NP, - DCERPC_AUTH_LEVEL_PRIVACY, - domain_name, - machine_account, - machine_password, - &conn->samr_pipe); + status = cli_rpc_pipe_open_spnego(conn->cli, + &ndr_table_samr, + NCACN_NP, + GENSEC_OID_NTLMSSP, + DCERPC_AUTH_LEVEL_PRIVACY, + smbXcli_conn_remote_name(conn->cli->conn), + domain_name, + machine_account, + machine_password, + &conn->samr_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("cm_connect_sam: failed to connect to SAMR " @@ -2243,7 +2416,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, goto anonymous; } status = cli_rpc_pipe_open_schannel_with_key - (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP, + (conn->cli, &ndr_table_samr, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &p_creds, &conn->samr_pipe); @@ -2275,7 +2448,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, anonymous: /* Finally fall back to anonymous. */ - status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id, + status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr, &conn->samr_pipe); if (!NT_STATUS_IS_OK(status)) { @@ -2375,7 +2548,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, } status = cli_rpc_pipe_open_schannel_with_key(conn->cli, - &ndr_table_lsarpc.syntax_id, + &ndr_table_lsarpc, NCACN_IP_TCP, DCERPC_AUTH_LEVEL_PRIVACY, domain->name, @@ -2427,9 +2600,11 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, /* We have an authenticated connection. Use a NTLMSSP SPNEGO * authenticated LSA pipe with sign & seal. */ - result = cli_rpc_pipe_open_spnego_ntlmssp - (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP, + result = cli_rpc_pipe_open_spnego + (conn->cli, &ndr_table_lsarpc, NCACN_NP, + GENSEC_OID_NTLMSSP, DCERPC_AUTH_LEVEL_PRIVACY, + smbXcli_conn_remote_name(conn->cli->conn), conn->cli->domain, conn->cli->user_name, conn->cli->password, &conn->lsa_pipe); @@ -2472,7 +2647,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, goto anonymous; } result = cli_rpc_pipe_open_schannel_with_key - (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP, + (conn->cli, &ndr_table_lsarpc, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &p_creds, &conn->lsa_pipe); @@ -2500,10 +2675,9 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, anonymous: result = cli_rpc_pipe_open_noauth(conn->cli, - &ndr_table_lsarpc.syntax_id, + &ndr_table_lsarpc, &conn->lsa_pipe); if (!NT_STATUS_IS_OK(result)) { - result = NT_STATUS_PIPE_NOT_AVAILABLE; goto done; } @@ -2521,6 +2695,42 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, return result; } +/**************************************************************************** +Open a LSA connection to a DC, suiteable for LSA lookup calls. +****************************************************************************/ + +NTSTATUS cm_connect_lsat(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + struct rpc_pipe_client **cli, + struct policy_handle *lsa_policy) +{ + NTSTATUS status; + + if (domain->can_do_ncacn_ip_tcp) { + status = cm_connect_lsa_tcp(domain, mem_ctx, cli); + if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || + NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) || + NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) { + invalidate_cm_connection(&domain->conn); + status = cm_connect_lsa_tcp(domain, mem_ctx, cli); + } + if (NT_STATUS_IS_OK(status)) { + return status; + } + + /* + * we tried twice to connect via ncan_ip_tcp and schannel and + * failed - maybe it is a trusted domain we can't connect to ? + * do not try tcp next time - gd + */ + domain->can_do_ncacn_ip_tcp = false; + } + + status = cm_connect_lsa(domain, mem_ctx, cli, lsa_policy); + + return status; +} + /**************************************************************************** Open the netlogon pipe to this DC. Use schannel if specified in client conf. session key stored in conn->netlogon_pipe->dc->sess_key. @@ -2532,8 +2742,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct winbindd_cm_conn *conn; NTSTATUS result; - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; - uint8 mach_pwd[16]; + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; + uint8_t mach_pwd[16]; enum netr_SchannelType sec_chan_type; const char *account_name; struct rpc_pipe_client *netlogon_pipe = NULL; @@ -2555,7 +2765,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, TALLOC_FREE(conn->netlogon_pipe); result = cli_rpc_pipe_open_noauth(conn->cli, - &ndr_table_netlogon.syntax_id, + &ndr_table_netlogon, &netlogon_pipe); if (!NT_STATUS_IS_OK(result)) { return result; @@ -2621,7 +2831,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, */ result = cli_rpc_pipe_open_schannel_with_key( - conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP, + conn->cli, &ndr_table_netlogon, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc, &conn->netlogon_pipe); @@ -2700,10 +2910,10 @@ void winbind_msg_ip_dropped(struct messaging_context *msg_ctx, } print_sockaddr(sockaddr, sizeof(sockaddr), - cli_state_local_sockaddr(domain->conn.cli)); + smbXcli_conn_local_sockaddr(domain->conn.cli->conn)); if (strequal(sockaddr, addr)) { - cli_state_disconnect(domain->conn.cli); + smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK); } } TALLOC_FREE(freeit);