diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index a49c8a1ca..9d825eb8c 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -696,6 +696,16 @@ bool t_command_parser_executor::ban(const std::vector& args) std::ifstream ifs(ban_list_path.string()); for (std::string line; std::getline(ifs, line); ) { + // ignore comments after '#' character + const size_t pound_idx = line.find('#'); + if (pound_idx != std::string::npos) + line.resize(pound_idx); + + // trim whitespace and ignore empty lines + boost::trim(line); + if (line.empty()) + continue; + auto subnet = net::get_ipv4_subnet_address(line); if (subnet) { diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 662e598e8..a34cf2e9d 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -527,6 +527,16 @@ namespace nodetool std::istringstream iss(banned_ips); for (std::string line; std::getline(iss, line); ) { + // ignore comments after '#' character + const size_t pound_idx = line.find('#'); + if (pound_idx != std::string::npos) + line.resize(pound_idx); + + // trim whitespace and ignore empty lines + boost::trim(line); + if (line.empty()) + continue; + auto subnet = net::get_ipv4_subnet_address(line); if (subnet) { diff --git a/tests/data/node/banlist_1.txt b/tests/data/node/banlist_1.txt new file mode 100644 index 000000000..7cc94ca62 --- /dev/null +++ b/tests/data/node/banlist_1.txt @@ -0,0 +1,17 @@ +# magicfolk +255.255.255.0 # Saruman the White +128.128.128.0 # Gandalf the Gray +150.75.0.0 # Radagast the Brown +99.98.0.0/16 # All of Misty Mountain + +# personal enemies +1.2.3.4 # this woman used to give me swirlies +6.7.8.9 # I just don't like the cut of his jib +1.0.0.7#Literally James Bond, he wrecked my aston martin +100.98.1.13 # Earl from HOA +100.98.1.0/24 #The rest of the HOA for good measure +# + +#7.7.7.7 +#^^^We're chill now, she's truly an angel + diff --git a/tests/unit_tests/node_server.cpp b/tests/unit_tests/node_server.cpp index 39178884c..a8b615ec4 100644 --- a/tests/unit_tests/node_server.cpp +++ b/tests/unit_tests/node_server.cpp @@ -35,6 +35,7 @@ #include "cryptonote_core/i_core_events.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" #include "cryptonote_protocol/cryptonote_protocol_handler.inl" +#include "unit_tests_utils.h" #include #define MAKE_IPV4_ADDRESS(a,b,c,d) epee::net_utils::ipv4_network_address{MAKE_IP(a,b,c,d),0} @@ -114,6 +115,18 @@ static bool is_blocked(Server &server, const epee::net_utils::network_address &a return true; } } + + if (address.get_type_id() != epee::net_utils::address_type::ipv4) + return false; + + const epee::net_utils::ipv4_network_address ipv4_address = address.as(); + + // check if in a blocked ipv4 subnet + const std::map subnets = server.get_blocked_subnets(); + for (const auto &subnet : subnets) + if (subnet.first.matches(ipv4_address)) + return true; + return false; } @@ -266,6 +279,78 @@ TEST(ban, ignores_port) ASSERT_FALSE(is_blocked(server,MAKE_IPV4_ADDRESS_PORT(1,2,3,4,6))); } +TEST(ban, file_banlist) +{ + test_core pr_core; + cryptonote::t_cryptonote_protocol_handler cprotocol(pr_core, NULL); + Server server(cprotocol); + cprotocol.set_p2p_endpoint(&server); + + auto create_node_dir = [](){ + boost::system::error_code ec; + auto path = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path("daemon-%%%%%%%%%%%%%%%%", ec); + if (ec) + return boost::filesystem::path{}; + auto success = boost::filesystem::create_directory(path, ec); + if (!ec && success) + return path; + return boost::filesystem::path{}; + }; + const auto node_dir = create_node_dir(); + ASSERT_TRUE(!node_dir.empty()); + auto auto_remove_node_dir = epee::misc_utils::create_scope_leave_handler([&node_dir](){ + boost::filesystem::remove_all(node_dir); + }); + + boost::program_options::variables_map vm; + boost::program_options::store( + boost::program_options::command_line_parser({ + "--data-dir", + node_dir.string(), + "--ban-list", + (unit_test::data_dir / "node" / "banlist_1.txt").string() + }).options([]{ + boost::program_options::options_description options_description{}; + cryptonote::core::init_options(options_description); + Server::init_options(options_description); + return options_description; + }()).run(), + vm + ); + + ASSERT_TRUE(server.init(vm)); + + // Test cases (look in the banlist_1.txt file) + + // magicfolk + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(255,255,255,0,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(128,128,128,0,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(150,75,0,0,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,0,0,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,0,255,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,1,0,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,1,0,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,255,255,9999)) ); + EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,99,0,0,9999)) ); + + // personal enemies + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(1,2,3,4,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(6,7,8,9,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(1,0,0,7,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(1,0,0,7,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,1,13,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,1,0,9999)) ); + EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,1,255,9999)) ); + EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,2,0,9999)) ); + EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,0,255,9999)) ); + + // angel + EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(007,007,007,007,9999)) ); + + // random IP + EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(145,036,205,235,9999)) ); +} + TEST(node_server, bind_same_p2p_port) { struct test_data_t