X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fwinbindd%2Fwinbindd_cm.c;h=d7111da62c4f1cc1efc29db7dbff42a957eb6e6d;hb=57d306d22e1027149c20029118f3c39e70e8a8a5;hp=9fdd058ddb8b1be69336a937a761f7bf1c78fdee;hpb=de14fd942aaaa4e18bae7fc7cb109d9a60b12648;p=mat%2Fsamba.git diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 9fdd058ddb..d7111da62c 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -340,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. @@ -347,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 )); @@ -394,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 */ @@ -418,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 )); @@ -469,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 */ @@ -561,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); } @@ -665,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 { @@ -768,7 +840,7 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, } if (!strupper_m(*machine_krb5_principal)) { - SAFE_FREE(machine_krb5_principal); + SAFE_FREE(*machine_krb5_principal); return NT_STATUS_INVALID_PARAMETER; } } @@ -831,8 +903,9 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, cli_set_timeout(*cli, 10000); /* 10 seconds */ - result = smbXcli_negprot((*cli)->conn, (*cli)->timeout, PROTOCOL_CORE, - PROTOCOL_LATEST); + 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))); @@ -1013,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; } } @@ -1108,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; @@ -1135,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 @@ -1152,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 ); @@ -1183,16 +1264,27 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx, &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; } @@ -1249,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. */ @@ -1273,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; } @@ -1341,7 +1433,7 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, static bool find_new_dc(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, - fstring dcname, struct sockaddr_storage *pss, int *fd) + char **dcname, struct sockaddr_storage *pss, int *fd) { struct dc_name_ip *dcs = NULL; int num_dcs = 0; @@ -1400,8 +1492,11 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) { /* Ok, we've got a name for the DC */ - fstrcpy(dcname, dcnames[fd_index]); - return True; + *dcname = talloc_strdup(mem_ctx, dcnames[fd_index]); + if (*dcname == NULL) { + return false; + } + return true; } /* Try to figure out the name */ @@ -1470,7 +1565,8 @@ bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx, const char *domain_name, char **p_dc_name, char **p_dc_ip) { - char *key, *value, *p; + char *key, *p; + char *value = NULL; bool ret = false; char *dc_name = NULL; char *dc_ip = NULL; @@ -1479,7 +1575,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, ' '); @@ -1508,6 +1604,7 @@ done: TALLOC_FREE(dc_name); TALLOC_FREE(dc_ip); TALLOC_FREE(key); + TALLOC_FREE(value); return ret; } @@ -1516,15 +1613,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 */ @@ -1539,37 +1637,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))) { @@ -1583,8 +1690,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 @@ -1593,6 +1700,15 @@ 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; @@ -1964,7 +2080,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)) { @@ -2015,7 +2131,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 " @@ -2043,20 +2159,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; @@ -2085,8 +2216,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) { @@ -2177,7 +2310,7 @@ 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_our_sam(&domain->sid)) { return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle); @@ -2284,7 +2417,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); @@ -2316,7 +2449,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)) { @@ -2416,7 +2549,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, @@ -2515,7 +2648,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); @@ -2543,10 +2676,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; } @@ -2583,11 +2715,16 @@ NTSTATUS cm_connect_lsat(struct winbindd_domain *domain, invalidate_cm_connection(&domain->conn); status = cm_connect_lsa_tcp(domain, mem_ctx, cli); } - if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_IS_OK(status)) { return status; } - return NT_STATUS_OK; + /* + * 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); @@ -2629,7 +2766,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; @@ -2645,6 +2782,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, neg_flags |= NETLOGON_NEG_SCHANNEL; } + no_schannel: if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name, &sec_chan_type)) { @@ -2674,7 +2812,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return NT_STATUS_ACCESS_DENIED; } - no_schannel: if ((lp_client_schannel() == False) || ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { /* @@ -2695,7 +2832,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);