diff --git a/libs/parser/parser.hpp b/libs/parser/parser.hpp index ed6bd0ab00..94b2faa6e7 100644 --- a/libs/parser/parser.hpp +++ b/libs/parser/parser.hpp @@ -32,7 +32,7 @@ namespace parser { * @param s * @return */ - bool isIntNumber(const std::string& s); + bool isIntNumber(const std::string &s); /** * Parse the first command in the line @@ -51,7 +51,7 @@ namespace parser { template nonstd::optional parseValue(std::string word) { std::stringstream ss(word); - if (not isIntNumber(word)){ + if (not isIntNumber(word)) { return nonstd::nullopt; } T val; @@ -62,6 +62,21 @@ namespace parser { } } + template + void split(const std::string &s, char delim, Out result) { + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) { + *(result++) = item; + } + } + + std::vector split(const std::string &s, char delim) { + std::vector elems; + split(s, delim, std::back_inserter(elems)); + return elems; + } + } // namespace parser #endif // IROHA_PARSER_HPP diff --git a/libs/validator/CMakeLists.txt b/libs/validator/CMakeLists.txt index c9e16c818c..ca369f0949 100644 --- a/libs/validator/CMakeLists.txt +++ b/libs/validator/CMakeLists.txt @@ -18,4 +18,5 @@ add_library(validator ) target_link_libraries(validator boost + optional ) diff --git a/libs/validator/address_validator.hpp b/libs/validator/address_validator.hpp index 9aeb6b281c..cc59395e6f 100644 --- a/libs/validator/address_validator.hpp +++ b/libs/validator/address_validator.hpp @@ -18,8 +18,10 @@ #ifndef IROHA_ADDRESS_VALIDATOR_HPP #define IROHA_ADDRESS_VALIDATOR_HPP +#include #include #include +#include "parser/parser.hpp" namespace iroha { namespace validator { @@ -29,7 +31,7 @@ namespace iroha { * @param address * @return true if address is valid */ - bool is_valid_ipv4(const std::string &address) { + bool isValidIpV4(const std::string &address) { std::regex valid_ipv4( R"#((^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3})#" R"#(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])):)#" @@ -44,16 +46,41 @@ namespace iroha { * 2. every label should be split by dots * 3. label may contain letters, numbers and dashes * 4. address may contain single label without dots (i.e. localhost:8080) + * 5. labels should not have more than 63 characters length * @param address * @return true if address is valid */ - bool is_valid_hostname(const std::string &address) { - std::regex valid_hostname( - R"#(^([a-zA-Z]+[a-zA-Z\-]+[a-zA-Z0-9]*\.?))#" - R"#((([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*)#" - R"#(([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]):)#" - R"#((6553[0-5]|655[0-2]\d|65[0-4]\d\d|6[0-4]\d{3}|[1-5]\d{4}|[1-9]\d{0,3}|0)$)#"); - return std::regex_match(address, valid_hostname); + bool isValidHostname(const std::string &address) { + // get domain and port + auto domain_and_port = ::parser::split(address, ':'); + // should have exactly two parts: labels and port + if (domain_and_port.size() != 2) { + return false; + } + + auto labels = ::parser::split(domain_and_port[0], '.'); + // should have at least one label + if (labels.empty()) { + return false; + } + + std::regex valid_label_regex( + R"#((([a-zA-Z0-9]*[a-zA-Z]+[a-zA-Z0-9]+|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])))#"); + // check if all labels are valid using valid_label_regex + if (not std::all_of( + labels.begin(), labels.end(), [valid_label_regex](auto label) { + return label.size() < 64 + && std::regex_match(label, valid_label_regex); + })) { + return false; + } + std::cout << "here" << std::endl; + // get port + auto port = domain_and_port[1]; + + std::regex valid_port_regex( + R"#(^(6553[0-5]|655[0-2]\d|65[0-4]\d\d|6[0-4]\d{3}|[1-5]\d{4}|[1-9]\d{0,3}|0)$)#"); + return std::regex_match(port, valid_port_regex); } } // namespace validator diff --git a/shared_model/validators/commands_validator.hpp b/shared_model/validators/commands_validator.hpp index 8464a24c77..1d4e886236 100644 --- a/shared_model/validators/commands_validator.hpp +++ b/shared_model/validators/commands_validator.hpp @@ -265,8 +265,8 @@ namespace shared_model { void validatePeerAddress( ReasonsGroupType &reason, const interface::AddPeer::AddressType &address) const { - if (not(iroha::validator::is_valid_ipv4(address) - or iroha::validator::is_valid_hostname(address))) { + if (not(iroha::validator::isValidIpV4(address) + or iroha::validator::isValidHostname(address))) { reason.second.push_back("Wrongly formed PeerAddress: " + address); } } diff --git a/test/module/libs/validator/address_validator_test.cpp b/test/module/libs/validator/address_validator_test.cpp index 291cb7a9dc..f6d6dbbf96 100644 --- a/test/module/libs/validator/address_validator_test.cpp +++ b/test/module/libs/validator/address_validator_test.cpp @@ -27,7 +27,7 @@ TEST(AddressValidatorTest, ValidIpV4AddressTest) { auto valid_addresses = { "0.0.0.0:0", "255.255.255.255:65535", "192.168.0.1:8080"}; for (std::string valid_address : valid_addresses) { - ASSERT_TRUE(iroha::validator::is_valid_ipv4(valid_address)); + ASSERT_TRUE(iroha::validator::isValidIpV4(valid_address)); } } @@ -40,7 +40,7 @@ TEST(AddressValidatorTest, InvalidIpV4AddressTest) { auto invalid_addresses = { "-0.0.0.0:0", "256.256.256.255:65535", "192.168.0.1:65536"}; for (std::string invalid_address : invalid_addresses) { - ASSERT_FALSE(iroha::validator::is_valid_ipv4(invalid_address)); + ASSERT_FALSE(iroha::validator::isValidIpV4(invalid_address)); } } @@ -50,12 +50,14 @@ TEST(AddressValidatorTest, InvalidIpV4AddressTest) { * @then true is returned */ TEST(AddressValidatorTest, ValidHostnameTest) { - auto valid_addresses = {"abc.efg:0", - "abc.efg.hij:65535", - "a-hyphen.ru:8080", - "altplus.com.jp:80"}; + auto valid_addresses = { + "abc.efg:0", + "abc.efg.hij:65535", + "a-hyphen.ru-i:8080", + "altplus.com.jp:80", + "maxLabelLengthIs63paddingPaddingPaddingPaddingPaddingPaddingPad:8080"}; for (std::string valid_address : valid_addresses) { - ASSERT_TRUE(iroha::validator::is_valid_hostname(valid_address)); + ASSERT_TRUE(iroha::validator::isValidHostname(valid_address)); } } @@ -65,13 +67,17 @@ TEST(AddressValidatorTest, ValidHostnameTest) { * @then false is returned */ TEST(AddressValidatorTest, InvalidHostnameTest) { - auto invalid_addresses = {"9.start.with.non.letter:0", - "-startWithDash:65535", - "@.is.not.allowed:8080", - "no space is allowed:80", - "some\u2063host:123" - "endWith-:909"}; + auto invalid_addresses = { + "9.start.with.non.letter:0", + "-startWithDash:65535", + "@.is.not.allowed:8080", + "no space is allowed:80", + "some\u2063host:123", + "endWith-:909", + "aLabelMustNotExceeds63charactersALabelMustNotExceeds63characters:9090", + "", + ":6565"}; for (std::string invalid_address : invalid_addresses) { - ASSERT_FALSE(iroha::validator::is_valid_hostname(invalid_address)); + ASSERT_FALSE(iroha::validator::isValidHostname(invalid_address)); } }