aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/net/host.h20
-rw-r--r--src/net/i2p_address.cpp7
-rw-r--r--src/net/tor_address.cpp7
-rw-r--r--tests/unit_tests/net.cpp22
4 files changed, 52 insertions, 4 deletions
diff --git a/src/net/host.h b/src/net/host.h
new file mode 100644
index 000000000..c96a7b434
--- /dev/null
+++ b/src/net/host.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <string>
+
+namespace net
+{
+ /*!
+ * \brief Canonicalize a hostname by converting letters to lowercase.
+ *
+ * \param host Hostname to canonicalize in-place.
+ */
+ inline void canonicalize_host(std::string& host) noexcept
+ {
+ for (char& c : host)
+ {
+ if ('A' <= c && c <= 'Z')
+ c = static_cast<char>(c - 'A' + 'a');
+ }
+ }
+}
diff --git a/src/net/i2p_address.cpp b/src/net/i2p_address.cpp
index 4e21085d0..e793048c0 100644
--- a/src/net/i2p_address.cpp
+++ b/src/net/i2p_address.cpp
@@ -36,6 +36,7 @@
#include <limits>
#include "net/error.h"
+#include "net/host.h"
#include "serialization/keyvalue_serialization.h"
#include "storages/portable_storage.h"
#include "string_tools_lexical.h"
@@ -105,10 +106,12 @@ namespace net
expect<i2p_address> i2p_address::make(const boost::string_ref address)
{
boost::string_ref host = address.substr(0, address.rfind(':'));
- MONERO_CHECK(host_check(host));
+ std::string normalized_host{host};
+ net::canonicalize_host(normalized_host);
+ MONERO_CHECK(host_check(normalized_host));
static_assert(b32_length + sizeof(tld) == sizeof(i2p_address::host_), "bad internal host size");
- return i2p_address{host};
+ return i2p_address{normalized_host};
}
bool i2p_address::_load(epee::serialization::portable_storage& src, epee::serialization::section* hparent)
diff --git a/src/net/tor_address.cpp b/src/net/tor_address.cpp
index ac36dbffd..35bd8e9a2 100644
--- a/src/net/tor_address.cpp
+++ b/src/net/tor_address.cpp
@@ -37,6 +37,7 @@
#include <limits>
#include "net/error.h"
+#include "net/host.h"
#include "serialization/keyvalue_serialization.h"
#include "storages/portable_storage.h"
#include "string_tools_lexical.h"
@@ -112,7 +113,9 @@ namespace net
const boost::string_ref port =
address.substr(host.size() + (host.size() == address.size() ? 0 : 1));
- MONERO_CHECK(host_check(host));
+ std::string normalized_host{host};
+ net::canonicalize_host(normalized_host);
+ MONERO_CHECK(host_check(normalized_host));
std::uint16_t porti = default_port;
if (!port.empty() && !epee::string_tools::get_xtype_from_string(porti, std::string{port}))
@@ -120,7 +123,7 @@ namespace net
static_assert(v2_length <= v3_length, "bad internal host size");
static_assert(v3_length + sizeof(tld) == sizeof(tor_address::host_), "bad internal host size");
- return tor_address{host, porti};
+ return tor_address{normalized_host, porti};
}
bool tor_address::_load(epee::serialization::portable_storage& src, epee::serialization::section* hparent)
diff --git a/tests/unit_tests/net.cpp b/tests/unit_tests/net.cpp
index 30e5f5589..9633f50e5 100644
--- a/tests/unit_tests/net.cpp
+++ b/tests/unit_tests/net.cpp
@@ -58,6 +58,7 @@
#include "crypto/crypto.h"
#include "net/dandelionpp.h"
#include "net/error.h"
+#include "net/host.h"
#include "net/i2p_address.h"
#include "net/net_utils_base.h"
#include "net/socks.h"
@@ -69,12 +70,23 @@
#include "serialization/keyvalue_serialization.h"
#include "storages/portable_storage.h"
+TEST(host, canonicalize_host)
+{
+ std::string host{"ABCdef123.ONION"};
+ net::canonicalize_host(host);
+ EXPECT_EQ("abcdef123.onion", host);
+}
+
namespace
{
static constexpr const char v2_onion[] =
"xmrto2bturnore26.onion";
static constexpr const char v3_onion[] =
"vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd.onion";
+ static constexpr const char v3_onion_upper[] =
+ "VWW6YBAL4BD7SZMGNCYRUUCPGFKQAHZDDI37KTCEO3AH7NGMCOPNPYYD.ONION";
+ static constexpr const char v3_onion_2[] =
+ "zpv4fa3szgel7vf6jdjeugizdclq2vzkelscs2bhbgnlldzzggcen3ad.onion";
}
TEST(tor_address, constants)
@@ -147,6 +159,10 @@ TEST(tor_address, valid)
EXPECT_STREQ(v3_onion, address1->str().c_str());
EXPECT_TRUE(address1->is_blockable());
+ const auto uppercase = net::tor_address::make(v3_onion_upper);
+ ASSERT_TRUE(uppercase.has_value());
+ EXPECT_EQ(*address1, *uppercase);
+
net::tor_address address2{*address1};
EXPECT_EQ(0u, address2.port());
@@ -532,6 +548,8 @@ namespace
{
static constexpr const char b32_i2p[] =
"vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopn.b32.i2p";
+ static constexpr const char b32_i2p_upper[] =
+ "VWW6YBAL4BD7SZMGNCYRUUCPGFKQAHZDDI37KTCEO3AH7NGMCOPN.B32.I2P";
static constexpr const char b32_i2p_2[] =
"xmrto2bturnore26xmrto2bturnore26xmrto2bturnore26xmr2.b32.i2p";
}
@@ -600,6 +618,10 @@ TEST(i2p_address, valid)
EXPECT_STREQ(b32_i2p, address1->str().c_str());
EXPECT_TRUE(address1->is_blockable());
+ const auto uppercase = net::i2p_address::make(b32_i2p_upper);
+ ASSERT_TRUE(uppercase.has_value());
+ EXPECT_EQ(*address1, *uppercase);
+
net::i2p_address address2{*address1};
EXPECT_EQ(1u, address2.port());