mirror of
https://github.com/monero-project/monero.git
synced 2026-06-12 19:11:36 -07:00
net: canonicalize Tor and I2P hostnames
This commit is contained in:
@@ -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 (u8'A' <= c && c <= u8'Z')
|
||||
c = static_cast<char>(c - u8'A' + u8'a');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
@@ -111,14 +112,16 @@ 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}))
|
||||
return {net::error::invalid_port};
|
||||
|
||||
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)
|
||||
|
||||
@@ -57,6 +57,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"
|
||||
@@ -68,12 +69,21 @@
|
||||
#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";
|
||||
}
|
||||
@@ -146,6 +156,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());
|
||||
@@ -448,6 +462,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";
|
||||
}
|
||||
@@ -516,6 +532,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());
|
||||
|
||||
Reference in New Issue
Block a user