From 88f868c5be60d2f3facf4fcae82d8515ea364951 Mon Sep 17 00:00:00 2001 From: sowle Date: Sun, 6 Oct 2019 00:27:35 +0300 Subject: [PATCH 1/7] === build number: 66 -> 67 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index 2897ba35..e68df5ce 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -7,6 +7,6 @@ #define PROJECT_REVISION "2" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 66 +#define PROJECT_VERSION_BUILD_NO 67 #define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO) #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]" From 64d0d1a4eae76fb020f736c3e78053a287079e45 Mon Sep 17 00:00:00 2001 From: sowle Date: Mon, 7 Oct 2019 08:18:58 +0300 Subject: [PATCH 2/7] fixed testnet synchronization --- src/currency_core/blockchain_storage.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 2b68f647..67ca688a 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -363,13 +363,16 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro //------------------------------------------------------------------ bool blockchain_storage::set_lost_tx_unmixable_for_height(uint64_t height) { +#ifndef TESTNET if (height == 75738) return set_lost_tx_unmixable(); +#endif return true; } //------------------------------------------------------------------ bool blockchain_storage::set_lost_tx_unmixable() { +#ifndef TESTNET if (m_db_blocks.size() > 75738) { crypto::hash tx_id_1 = epee::string_tools::parse_tpod_from_hex_string("c2a2229d614e7c026433efbcfdbd0be1f68d9b419220336df3e2c209f5d57314"); @@ -393,11 +396,13 @@ bool blockchain_storage::set_lost_tx_unmixable() } m_db_transactions.set(tx_id_2, tx2_local_entry); } +#endif return true; } //------------------------------------------------------------------ void blockchain_storage::patch_out_if_needed(txout_to_key& out, const crypto::hash& tx_id, uint64_t n) const { +#ifndef TESTNET static crypto::hash tx_id_1 = epee::string_tools::parse_tpod_from_hex_string("c2a2229d614e7c026433efbcfdbd0be1f68d9b419220336df3e2c209f5d57314"); static crypto::hash tx_id_2 = epee::string_tools::parse_tpod_from_hex_string("647f936c6ffbd136f5c95d9a90ad554bdb4c01541c6eb5755ad40b984d80da67"); @@ -408,6 +413,7 @@ void blockchain_storage::patch_out_if_needed(txout_to_key& out, const crypto::h { out.mix_attr = CURRENCY_TO_KEY_OUT_FORCED_NO_MIX; } +#endif } //------------------------------------------------------------------ void blockchain_storage::store_db_solo_options_values() From e3cc89846e4fd60221c0032e3aa954d465d4c42a Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 9 Oct 2019 16:01:33 +0300 Subject: [PATCH 3/7] wallet: make sure there's enough disk space on load, store and wallet generation (simplewallet + GUI) #57 --- src/wallet/wallet2.cpp | 89 +++++++++++++++++++++++++++++++++++++----- src/wallet/wallet2.h | 35 +++++++++-------- 2 files changed, 97 insertions(+), 27 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 5095a56f..1352b1f1 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -28,6 +28,8 @@ using namespace epee; #include "version.h" using namespace currency; +#define MINIMUM_REQUIRED_WALLET_FREE_SPACE_BYTES (100*1024*1024) // 100 MB + #undef LOG_DEFAULT_CHANNEL #define LOG_DEFAULT_CHANNEL "wallet" ENABLE_CHANNEL_BY_DEFAULT("wallet") @@ -1965,6 +1967,9 @@ void wallet2::generate(const std::wstring& path, const std::string& pass) WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(validate_password(pass), "new wallet generation failed: password contains forbidden characters") clear(); prepare_file_names(path); + + check_for_free_space_and_throw_if_it_lacks(m_wallet_file); + m_password = pass; m_account.generate(); init_log_prefix(); @@ -2000,6 +2005,9 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password) { clear(); prepare_file_names(wallet_); + + check_for_free_space_and_throw_if_it_lacks(m_wallet_file); + m_password = password; std::string keys_buff; @@ -2058,35 +2066,55 @@ void wallet2::store(const std::wstring& path_to_save, const std::string& passwor { LOG_PRINT_L0("(before storing: pending_key_images: " << m_pending_key_images.size() << ", pki file elements: " << m_pending_key_images_file_container.size() << ", tx_keys: " << m_tx_keys.size() << ")"); + check_for_free_space_and_throw_if_it_lacks(path_to_save); + + std::string ascii_path_to_save = epee::string_encoding::convert_to_ansii(path_to_save); + //prepare data std::string keys_buff; bool r = store_keys(keys_buff, password); - CHECK_AND_ASSERT_THROW_MES(r, "failed to store_keys for wallet " << epee::string_encoding::convert_to_ansii(m_wallet_file)); - - wallet_file_binary_header wbh = AUTO_VAL_INIT(wbh); + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(r, "failed to store_keys for wallet " << ascii_path_to_save); //store data - + wallet_file_binary_header wbh = AUTO_VAL_INIT(wbh); wbh.m_signature = WALLET_FILE_SIGNATURE; wbh.m_cb_keys = keys_buff.size(); //@#@ change it to proper wbh.m_cb_body = 1000; - std::string header_buff((const char*)&wbh, sizeof(wbh)); + uint64_t ts = m_core_runtime_config.get_core_time(); + + // save to tmp file, then rename + boost::filesystem::path tmp_file_path = boost::filesystem::path(path_to_save); + tmp_file_path += L".newtmp_" + std::to_wstring(ts); - //std::ofstream data_file; boost::filesystem::ofstream data_file; - data_file.open(path_to_save, std::ios_base::binary | std::ios_base::out | std::ios::trunc); - CHECK_AND_ASSERT_THROW_MES(!data_file.fail(), "failed to open binary wallet file for saving: " << epee::string_encoding::convert_to_ansii(m_wallet_file)); + data_file.open(tmp_file_path, std::ios_base::binary | std::ios_base::out | std::ios::trunc); + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(!data_file.fail(), "failed to open binary wallet file for saving: " << tmp_file_path.string()); data_file << header_buff << keys_buff; - WLT_LOG_L0("Storing to file..."); + + WLT_LOG_L0("Storing to " << tmp_file_path.string() << " ..."); r = tools::portble_serialize_obj_to_stream(*this, data_file); - CHECK_AND_ASSERT_THROW_MES(r, "failed to portble_serialize_obj_to_stream for wallet " << epee::string_encoding::convert_to_ansii(m_wallet_file)); + if (!r) + { + boost::filesystem::remove(tmp_file_path); // remove tmp file if smth went wrong + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(false, "portble_serialize_obj_to_stream failed for wallet " << tmp_file_path.string()); + } data_file.flush(); data_file.close(); + + // for the sake of safety perform a double-renaming: wallet file -> old tmp, new tmp -> wallet file, remove old tmp + + boost::filesystem::path tmp_old_file_path = boost::filesystem::path(path_to_save); + tmp_old_file_path += L".oldtmp_" + std::to_wstring(ts); + + if (boost::filesystem::is_regular_file(path_to_save)) + boost::filesystem::rename(path_to_save, tmp_old_file_path); + boost::filesystem::rename(tmp_file_path, path_to_save); + boost::filesystem::remove(tmp_old_file_path); } //---------------------------------------------------------------------------------------------------- void wallet2::store_watch_only(const std::wstring& path_to_save, const std::string& password) const @@ -2134,6 +2162,47 @@ void wallet2::store_watch_only(const std::wstring& path_to_save, const std::stri wo.store(path_to_save, password); } //---------------------------------------------------------------------------------------------------- +void wallet2::check_for_free_space_and_throw_if_it_lacks(const std::wstring& wallet_filename, uint64_t exact_size_needed_if_known /* = UINT64_MAX */) +{ + namespace fs = boost::filesystem; + + try + { + fs::path wallet_file_path(wallet_filename); + fs::path base_path = wallet_file_path.parent_path(); + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(fs::is_directory(base_path), "directory does not exist: " << base_path.string()); + + uint64_t min_free_size = exact_size_needed_if_known; + if (min_free_size == UINT64_MAX) + { + // if exact size needed is unknown -- determine it as + // twice the original wallet file size or MINIMUM_REQUIRED_WALLET_FREE_SPACE_BYTES, which one is bigger + min_free_size = MINIMUM_REQUIRED_WALLET_FREE_SPACE_BYTES; + if (fs::is_regular_file(wallet_file_path)) + min_free_size = std::max(min_free_size, 2 * fs::file_size(wallet_file_path)); + } + else + { + min_free_size += 1024 * 1024 * 10; // add a little for FS overhead and so + } + + fs::space_info si = fs::space(base_path); + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(si.available > min_free_size, "free space at " << base_path.string() << " is too low: " << si.available << ", required minimum is: " << min_free_size); + } + catch (tools::error::wallet_common_error&) + { + throw; + } + catch (std::exception& e) + { + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(false, "failed to determine free space: " << e.what()); + } + catch (...) + { + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(false, "failed to determine free space: unknown exception"); + } +} +//---------------------------------------------------------------------------------------------------- uint64_t wallet2::unlocked_balance() const { uint64_t stub = 0; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 7d5cf1ba..e1fd1d63 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -47,22 +47,22 @@ ENABLE_CHANNEL_BY_DEFAULT("wallet"); // wallet-specific logging functions -#define WLT_LOG_L0(msg) LOG_PRINT_L0("[W:" << m_log_prefix << "]" << msg) -#define WLT_LOG_L1(msg) LOG_PRINT_L1("[W:" << m_log_prefix << "]" << msg) -#define WLT_LOG_L2(msg) LOG_PRINT_L2("[W:" << m_log_prefix << "]" << msg) -#define WLT_LOG_L3(msg) LOG_PRINT_L3("[W:" << m_log_prefix << "]" << msg) -#define WLT_LOG_L4(msg) LOG_PRINT_L4("[W:" << m_log_prefix << "]" << msg) -#define WLT_LOG_ERROR(msg) LOG_ERROR("[W:" << m_log_prefix << "]" << msg) -#define WLT_LOG_BLUE(msg, log_level) LOG_PRINT_BLUE("[W:" << m_log_prefix << "]" << msg, log_level) -#define WLT_LOG_CYAN(msg, log_level) LOG_PRINT_CYAN("[W:" << m_log_prefix << "]" << msg, log_level) -#define WLT_LOG_GREEN(msg, log_level) LOG_PRINT_GREEN("[W:" << m_log_prefix << "]" << msg, log_level) -#define WLT_LOG_MAGENTA(msg, log_level) LOG_PRINT_MAGENTA("[W:" << m_log_prefix << "]" << msg, log_level) -#define WLT_LOG_RED(msg, log_level) LOG_PRINT_RED("[W:" << m_log_prefix << "]" << msg, log_level) -#define WLT_LOG_YELLOW(msg, log_level) LOG_PRINT_YELLOW("[W:" << m_log_prefix << "]" << msg, log_level) -#define WLT_CHECK_AND_ASSERT_MES(expr, ret, msg) CHECK_AND_ASSERT_MES(expr, ret, "[W:" << m_log_prefix << "]" << msg) -#define WLT_CHECK_AND_ASSERT_MES_NO_RET(expr, msg) CHECK_AND_ASSERT_MES_NO_RET(expr, "[W:" << m_log_prefix << "]" << msg) -#define WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(cond, msg) THROW_IF_FALSE_WALLET_INT_ERR_EX(cond, "[W:" << m_log_prefix << "]" << msg) -#define WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(cond, msg) THROW_IF_FALSE_WALLET_CMN_ERR_EX(cond, "[W:" << m_log_prefix << "]" << msg) +#define WLT_LOG_L0(msg) LOG_PRINT_L0("[W:" << m_log_prefix << "] " << msg) +#define WLT_LOG_L1(msg) LOG_PRINT_L1("[W:" << m_log_prefix << "] " << msg) +#define WLT_LOG_L2(msg) LOG_PRINT_L2("[W:" << m_log_prefix << "] " << msg) +#define WLT_LOG_L3(msg) LOG_PRINT_L3("[W:" << m_log_prefix << "] " << msg) +#define WLT_LOG_L4(msg) LOG_PRINT_L4("[W:" << m_log_prefix << "] " << msg) +#define WLT_LOG_ERROR(msg) LOG_ERROR("[W:" << m_log_prefix << "] " << msg) +#define WLT_LOG_BLUE(msg, log_level) LOG_PRINT_BLUE("[W:" << m_log_prefix << "] " << msg, log_level) +#define WLT_LOG_CYAN(msg, log_level) LOG_PRINT_CYAN("[W:" << m_log_prefix << "] " << msg, log_level) +#define WLT_LOG_GREEN(msg, log_level) LOG_PRINT_GREEN("[W:" << m_log_prefix << "] " << msg, log_level) +#define WLT_LOG_MAGENTA(msg, log_level) LOG_PRINT_MAGENTA("[W:" << m_log_prefix << "] " << msg, log_level) +#define WLT_LOG_RED(msg, log_level) LOG_PRINT_RED("[W:" << m_log_prefix << "] " << msg, log_level) +#define WLT_LOG_YELLOW(msg, log_level) LOG_PRINT_YELLOW("[W:" << m_log_prefix << "] " << msg, log_level) +#define WLT_CHECK_AND_ASSERT_MES(expr, ret, msg) CHECK_AND_ASSERT_MES(expr, ret, "[W:" << m_log_prefix << "] " << msg) +#define WLT_CHECK_AND_ASSERT_MES_NO_RET(expr, msg) CHECK_AND_ASSERT_MES_NO_RET(expr, "[W:" << m_log_prefix << "] " << msg) +#define WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(cond, msg) THROW_IF_FALSE_WALLET_INT_ERR_EX(cond, "[W:" << m_log_prefix << "] " << msg) +#define WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(cond, msg) THROW_IF_FALSE_WALLET_CMN_ERR_EX(cond, "[W:" << m_log_prefix << "] " << msg) class test_generator; @@ -729,6 +729,7 @@ namespace tools std::string get_log_prefix() const { return m_log_prefix; } static uint64_t get_max_unlock_time_from_receive_indices(const currency::transaction& tx, const money_transfer2_details& td); + private: void add_transfers_to_expiration_list(const std::vector& selected_transfers, uint64_t expiration, uint64_t change_amount, const crypto::hash& related_tx_id); void remove_transfer_from_expiration_list(uint64_t transfer_index); @@ -840,7 +841,7 @@ private: void exception_handler(); void exception_handler() const; uint64_t get_minimum_allowed_fee_for_contract(const crypto::hash& ms_id); - + void check_for_free_space_and_throw_if_it_lacks(const std::wstring& path, uint64_t exact_size_needed_if_known = UINT64_MAX); From 02c04aa30051566a958ee8f1ace67b34c9c270fb Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 10 Oct 2019 11:12:28 +0300 Subject: [PATCH 4/7] p2p: filter out old clients by version + unittest #128 --- .../currency_protocol_handler.inl | 3 +- src/p2p/net_node.inl | 6 +++ src/version.h.in | 40 +++++++++++++++ tests/unit_tests/p2p_client_version.cpp | 51 +++++++++++++++++++ 4 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 tests/unit_tests/p2p_client_version.cpp diff --git a/src/currency_protocol/currency_protocol_handler.inl b/src/currency_protocol/currency_protocol_handler.inl index e4588490..a5ee5b1f 100644 --- a/src/currency_protocol/currency_protocol_handler.inl +++ b/src/currency_protocol/currency_protocol_handler.inl @@ -174,7 +174,8 @@ namespace currency "That means that current software is outdated, please updated it." << "Current heigh lay under checkpoints on remote host, so it is not possible validate this transactions on local host, disconnecting.", LOG_LEVEL_0); return false; - }else if (m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() < hshd.last_checkpoint_height) + } + else if (m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() < hshd.last_checkpoint_height) { LOG_PRINT_MAGENTA("Remote node have longer checkpoints zone( " << hshd.last_checkpoint_height << ") " << "that local (" << m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() << ")" << diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 2ce7099c..72cadef1 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -483,6 +483,12 @@ namespace nodetool return; } + if (!check_remote_client_version(rsp.payload_data.client_version)) + { + LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE Failed, wrong client version: " << rsp.payload_data.client_version << ", closing connection."); + return; + } + if(!handle_maintainers_entry(rsp.maintrs_entry)) { LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong maintainers entry!, closing connection."); diff --git a/src/version.h.in b/src/version.h.in index e68df5ce..61d98d65 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,3 +1,4 @@ +#pragma once #include "misc_language.h" #define BUILD_COMMIT_ID "@VERSION@" @@ -10,3 +11,42 @@ #define PROJECT_VERSION_BUILD_NO 67 #define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO) #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]" + + + +inline bool check_remote_client_version(const std::string& client_ver) +{ + std::string v = client_ver.substr(0, client_ver.find('[')); // remove commit id + v = v.substr(0, v.rfind('.')); // remove build number + + int v_major = 0, v_minor = 0, v_revision = 0; + + size_t dot_pos = v.find('.'); + if (dot_pos == std::string::npos || !epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_major)) + return false; + + v = v.substr(dot_pos + 1); + dot_pos = v.find('.'); + if (!epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_minor)) + return false; + + if (dot_pos != std::string::npos) + { + // revision + v = v.substr(dot_pos + 1); + if (!epee::string_tools::string_to_num_fast(v, v_revision)) + return false; + } + + // got v_major, v_minor, v_revision + + // allow 1.1.x and greater + + if (v_major < 1) + return false; + + if (v_major == 1 && v_minor < 1) + return false; + + return true; +} diff --git a/tests/unit_tests/p2p_client_version.cpp b/tests/unit_tests/p2p_client_version.cpp new file mode 100644 index 00000000..73b44559 --- /dev/null +++ b/tests/unit_tests/p2p_client_version.cpp @@ -0,0 +1,51 @@ +// Copyright (c) 2019 Zano Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "gtest/gtest.h" +#include "version.h" + +TEST(p2p_client_version, test_1) +{ + // good + + ASSERT_TRUE(check_remote_client_version("10.101.999.28391[deadbeef31337-dirty]")); + ASSERT_TRUE(check_remote_client_version("1.1.9.237[aabcd]")); + ASSERT_TRUE(check_remote_client_version("3.0.2.7[aa00bcd]")); + ASSERT_TRUE(check_remote_client_version("1.4.2.7[aabcd]")); + ASSERT_TRUE(check_remote_client_version("1.1.2.67[88f868c]")); + + ASSERT_TRUE(check_remote_client_version("1.1.2.67[88f868c]")); + ASSERT_TRUE(check_remote_client_version("1.1.2.67[26c00a8]")); + ASSERT_TRUE(check_remote_client_version("1.1.2.67[26c00a8-dirty]")); + + ASSERT_TRUE(check_remote_client_version("1.1.0.65[40ba8cd]")); + ASSERT_TRUE(check_remote_client_version("1.1.0.63[b0f376b]")); + + ASSERT_TRUE(check_remote_client_version("1.1.0.58[14bd668]")); + ASSERT_TRUE(check_remote_client_version("1.1.0.58[9920eb7]")); + ASSERT_TRUE(check_remote_client_version("1.1.0.58[e0d4ad8]")); + + ASSERT_TRUE(check_remote_client_version("1.1.0.57[b77b915]")); + ASSERT_TRUE(check_remote_client_version("1.1.0.57[7dd61ae]")); + ASSERT_TRUE(check_remote_client_version("1.1.0.57[7dd61ae-dirty]")); + + ASSERT_TRUE(check_remote_client_version("1.1.0.57")); + + // bad + + ASSERT_FALSE(check_remote_client_version("")); + ASSERT_FALSE(check_remote_client_version(" ")); + + ASSERT_FALSE(check_remote_client_version("1.0.999")); + + ASSERT_FALSE(check_remote_client_version("1.0.40[f77f0d7]")); + ASSERT_FALSE(check_remote_client_version("1.0.40[734b726]")); + ASSERT_FALSE(check_remote_client_version("1.0.41[488e369]")); + + ASSERT_FALSE(check_remote_client_version("1.0.40[469]")); + ASSERT_FALSE(check_remote_client_version("1.0.39[f77f0d7]")); + ASSERT_FALSE(check_remote_client_version("1.0.38[f77f0d7-dirty]")); + ASSERT_FALSE(check_remote_client_version("1.0.37[7dd61ae-dirty]")); + ASSERT_FALSE(check_remote_client_version("0.0.500[000]")); +} From 609969799e0f8b7a5a7dc225b1377d300f101f69 Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 10 Oct 2019 16:22:34 +0300 Subject: [PATCH 5/7] p2p: check_remote_client_version() moved to more appropriate place --- src/common/util.cpp | 37 +++++++++++++++++++++++ src/common/util.h | 2 ++ src/p2p/net_node.inl | 2 +- src/version.h.in | 39 ------------------------- tests/unit_tests/p2p_client_version.cpp | 4 ++- 5 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/common/util.cpp b/src/common/util.cpp index 999c5401..6fa15854 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -658,4 +658,41 @@ std::string get_nix_version_display_string() return static_cast(in.tellg()); } + bool check_remote_client_version(const std::string& client_ver) + { + std::string v = client_ver.substr(0, client_ver.find('[')); // remove commit id + v = v.substr(0, v.rfind('.')); // remove build number + + int v_major = 0, v_minor = 0, v_revision = 0; + + size_t dot_pos = v.find('.'); + if (dot_pos == std::string::npos || !epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_major)) + return false; + + v = v.substr(dot_pos + 1); + dot_pos = v.find('.'); + if (!epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_minor)) + return false; + + if (dot_pos != std::string::npos) + { + // revision + v = v.substr(dot_pos + 1); + if (!epee::string_tools::string_to_num_fast(v, v_revision)) + return false; + } + + // got v_major, v_minor, v_revision + + // allow 1.1.x and greater + + if (v_major < 1) + return false; + + if (v_major == 1 && v_minor < 1) + return false; + + return true; + } + } // namespace tools diff --git a/src/common/util.h b/src/common/util.h index 3360c345..87138ef0 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -30,6 +30,8 @@ namespace tools std::string get_default_user_dir(); std::string get_current_username(); std::string get_os_version_string(); + bool check_remote_client_version(const std::string& client_ver); + bool create_directories_if_necessary(const std::string& path); std::error_code replace_file(const std::string& replacement_name, const std::string& replaced_name); diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 72cadef1..93ee7a61 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -483,7 +483,7 @@ namespace nodetool return; } - if (!check_remote_client_version(rsp.payload_data.client_version)) + if (!tools::check_remote_client_version(rsp.payload_data.client_version)) { LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE Failed, wrong client version: " << rsp.payload_data.client_version << ", closing connection."); return; diff --git a/src/version.h.in b/src/version.h.in index 61d98d65..bbd5c6c5 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -11,42 +11,3 @@ #define PROJECT_VERSION_BUILD_NO 67 #define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO) #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]" - - - -inline bool check_remote_client_version(const std::string& client_ver) -{ - std::string v = client_ver.substr(0, client_ver.find('[')); // remove commit id - v = v.substr(0, v.rfind('.')); // remove build number - - int v_major = 0, v_minor = 0, v_revision = 0; - - size_t dot_pos = v.find('.'); - if (dot_pos == std::string::npos || !epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_major)) - return false; - - v = v.substr(dot_pos + 1); - dot_pos = v.find('.'); - if (!epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_minor)) - return false; - - if (dot_pos != std::string::npos) - { - // revision - v = v.substr(dot_pos + 1); - if (!epee::string_tools::string_to_num_fast(v, v_revision)) - return false; - } - - // got v_major, v_minor, v_revision - - // allow 1.1.x and greater - - if (v_major < 1) - return false; - - if (v_major == 1 && v_minor < 1) - return false; - - return true; -} diff --git a/tests/unit_tests/p2p_client_version.cpp b/tests/unit_tests/p2p_client_version.cpp index 73b44559..3761e36a 100644 --- a/tests/unit_tests/p2p_client_version.cpp +++ b/tests/unit_tests/p2p_client_version.cpp @@ -3,10 +3,12 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "gtest/gtest.h" -#include "version.h" +#include "common/util.h" TEST(p2p_client_version, test_1) { + using namespace tools; + // good ASSERT_TRUE(check_remote_client_version("10.101.999.28391[deadbeef31337-dirty]")); From adc08088aac7ddd7a77a118cce3debad72848cfd Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 10 Oct 2019 23:47:15 +0300 Subject: [PATCH 6/7] p2p: fix for filtering old clients mechanism #128 --- src/p2p/net_node.inl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 93ee7a61..4fa28d74 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -485,7 +485,7 @@ namespace nodetool if (!tools::check_remote_client_version(rsp.payload_data.client_version)) { - LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE Failed, wrong client version: " << rsp.payload_data.client_version << ", closing connection."); + LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong client version: " << rsp.payload_data.client_version << ", closing connection."); return; } @@ -1310,6 +1310,14 @@ namespace nodetool return 1; } + if (!tools::check_remote_client_version(rsp.payload_data.client_version)) + { + LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE: wrong client version: " << rsp.payload_data.client_version << ", closing connection."); + drop_connection(context); + add_ip_fail(context.m_remote_ip); + return 1; + } + if(!handle_maintainers_entry(arg.maintrs_entry)) { LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong maintainers entry!, closing connection."); From 47d61b64244235911d754994897289bbab5511aa Mon Sep 17 00:00:00 2001 From: sowle Date: Fri, 11 Oct 2019 00:02:41 +0300 Subject: [PATCH 7/7] p2p: fix for filtering old clients mechanism #128 (2) --- src/p2p/net_node.inl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 4fa28d74..d81eaeea 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -1310,9 +1310,9 @@ namespace nodetool return 1; } - if (!tools::check_remote_client_version(rsp.payload_data.client_version)) + if (!tools::check_remote_client_version(arg.payload_data.client_version)) { - LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE: wrong client version: " << rsp.payload_data.client_version << ", closing connection."); + LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE: wrong client version: " << arg.payload_data.client_version << ", closing connection."); drop_connection(context); add_ip_fail(context.m_remote_ip); return 1;