rc parsing

- new btdc method used to ensure no junk at the end of our bt data
- DRYed out the RC code
- check inbound bootstraps against all registered routers, not just whitelist
- libquic vbump
pull/2232/head
dr7ana 5 months ago
parent 4251172707
commit 22879b64ed

@ -1 +1 @@
Subproject commit 78b46d4f4df45747b70918386672228ead2c7ed3
Subproject commit b35cab3a310cf358580ef9f418553f71436766ab

@ -230,15 +230,16 @@ namespace llarp
if (_router.is_bootstrap_seed())
{
if (node_db->whitelist().count(other))
if (node_db->registered_routers().count(other))
{
log::critical(logcat, "Saving bootstrap seed requester...");
auto [it, b] = node_db->seeds().emplace(other);
result |= b;
auto [it, b] = node_db->seeds().insert(other);
result &= b;
}
log::critical(
logcat,
"Bootstrap seed node was {} to confirm remote is white-listed; {}successfully "
"Bootstrap seed node was {} to confirm remote is registered; {}successfully "
"saved RID",
result ? "able" : "unable",
result ? "" : "un");
@ -323,6 +324,8 @@ namespace llarp
}
else
{
log::critical(logcat, "Searching for RID:{} in pending conns...", rid);
if (auto itr = ep.pending_conns.find(rid); itr != ep.pending_conns.end())
{
ep.connid_map.emplace(scid, rid);

@ -808,10 +808,10 @@ namespace llarp
if (whitelist.empty())
return;
registered_routers.clear();
registered_routers.insert(whitelist.begin(), whitelist.end());
registered_routers.insert(greylist.begin(), greylist.end());
registered_routers.insert(greenlist.begin(), greenlist.end());
_registered_routers.clear();
_registered_routers.insert(whitelist.begin(), whitelist.end());
_registered_routers.insert(greylist.begin(), greylist.end());
_registered_routers.insert(greenlist.begin(), greenlist.end());
router_whitelist.clear();
router_whitelist.insert(whitelist.begin(), whitelist.end());
@ -820,10 +820,8 @@ namespace llarp
router_greenlist.clear();
router_greenlist.insert(greenlist.begin(), greenlist.end());
log::info(
logcat,
"lokinet service node whitelist now has {} active router RIDs",
router_whitelist.size());
log::critical(
logcat, "Service node whitelist now has {} active router RIDs", router_whitelist.size());
}
std::optional<RouterID>

@ -150,7 +150,7 @@ namespace llarp
std::set<RouterID> router_greenlist{};
// All registered relays (service nodes)
std::set<RouterID> registered_routers;
std::set<RouterID> _registered_routers;
// timing (note: Router holds the variables for last rc and rid request times)
std::unordered_map<RouterID, rc_time> last_rc_update_times;
// if populated from a config file, lists specific exclusively used as path first-hops
@ -372,10 +372,16 @@ namespace llarp
return router_greylist;
}
std::set<RouterID>&
registered_routers()
{
return _registered_routers;
}
const std::set<RouterID>&
get_registered_routers() const
registered_routers() const
{
return registered_routers;
return _registered_routers;
}
const std::set<RemoteRC>&

@ -476,7 +476,7 @@ namespace llarp
Router::appears_registered() const
{
return _is_service_node and have_snode_whitelist()
and node_db()->get_registered_routers().count(pubkey());
and node_db()->registered_routers().count(pubkey());
}
bool
@ -866,17 +866,11 @@ namespace llarp
{
log::critical(logcat, "Regenerating and gossiping RC...");
<<<<<<< Updated upstream
router_contact.resign();
save_rc();
=======
auto view = router_contact.view();
>>>>>>> Stashed changes
_link_manager->gossip_rc(
router_contact.router_id(),
router_contact.router_id(),
std::string{oxen::quic::to_sv(router_contact.view())});
local_rid(), local_rid(), std::string{oxen::quic::to_sv(router_contact.view())});
last_rc_gossip = now_timepoint;

@ -187,10 +187,10 @@ namespace llarp
return client_router_connections;
}
RouterID
const RouterID&
local_rid() const
{
return RouterID{pubkey()};
return router_contact.router_id();
}
bool

@ -12,12 +12,42 @@
namespace llarp
{
void
RouterContact::bt_load(oxenc::bt_dict_consumer& data)
RouterContact::bt_verify(oxenc::bt_dict_consumer& btdc, bool reject_expired) const
{
if (int rc_ver = data.require<uint8_t>(""); rc_ver != RC_VERSION)
btdc.require_signature("~", [this, reject_expired](ustring_view msg, ustring_view sig) {
if (sig.size() != 64)
throw std::runtime_error{"Invalid signature: not 64 bytes"};
if (reject_expired and is_expired(time_now_ms()))
throw std::runtime_error{"Rejecting expired RemoteRC!"};
// TODO: revisit if this is needed; detail from previous implementation
const auto* net = net::Platform::Default_ptr();
if (net->IsBogon(addr().in4()) and BLOCK_BOGONS)
{
auto err = "Unable to verify expired RemoteRC address!";
log::info(logcat, err);
throw std::runtime_error{err};
}
if (not crypto::verify(router_id(), msg, sig))
throw std::runtime_error{"Failed to verify RemoteRC signature"};
});
if (not btdc.is_finished())
throw std::runtime_error{"RouterContact has some fucked up shit at the end"};
btdc.finish();
}
void
RouterContact::bt_load(oxenc::bt_dict_consumer& btdc)
{
if (int rc_ver = btdc.require<uint8_t>(""); rc_ver != RC_VERSION)
throw std::runtime_error{"Invalid RC: do not know how to parse v{} RCs"_format(rc_ver)};
auto ipv4_port = data.require<std::string_view>("4");
auto ipv4_port = btdc.require<std::string_view>("4");
if (ipv4_port.size() != 6)
throw std::runtime_error{
@ -34,7 +64,7 @@ namespace llarp
if (!_addr.is_public())
throw std::runtime_error{"Invalid RC: IPv4 address is not a publicly routable IP"};
if (auto ipv6_port = data.maybe<std::string_view>("6"))
if (auto ipv6_port = btdc.maybe<std::string_view>("6"))
{
if (ipv6_port->size() != 18)
throw std::runtime_error{
@ -55,22 +85,22 @@ namespace llarp
_addr6.reset();
}
auto netid = data.maybe<std::string_view>("i").value_or(llarp::LOKINET_DEFAULT_NETID);
auto netid = btdc.maybe<std::string_view>("i").value_or(llarp::LOKINET_DEFAULT_NETID);
if (netid != ACTIVE_NETID)
throw std::runtime_error{
"Invalid RC netid: expected {}, got {}; this is an RC for a different network!"_format(
ACTIVE_NETID, netid)};
auto pubkey = data.require<std::string_view>("p");
auto pubkey = btdc.require<std::string_view>("p");
if (pubkey.size() != 32)
throw std::runtime_error{
"Invalid RC pubkey: expected 32 bytes, got {}"_format(pubkey.size())};
std::memcpy(_router_id.data(), pubkey.data(), 32);
_timestamp = rc_time{std::chrono::seconds{data.require<uint64_t>("t")}};
_timestamp = rc_time{std::chrono::seconds{btdc.require<uint64_t>("t")}};
auto ver = data.require<ustring_view>("v");
auto ver = btdc.require<ustring_view>("v");
if (ver.size() != 3)
throw std::runtime_error{
@ -120,106 +150,6 @@ namespace llarp
return obj;
}
bool
RouterContact::BDecode(llarp_buffer_t* buf)
{
// TODO: unfuck all of this
(void)buf;
// clear();
// if (*buf->cur == 'd') // old format
// {
// return DecodeVersion_0(buf);
// }
// else if (*buf->cur != 'l') // if not dict, should be new format and start with list
// {
// return false;
// }
// try
// {
// std::string_view buf_view(reinterpret_cast<char*>(buf->cur), buf->size_left());
// oxenc::bt_list_consumer btlist(buf_view);
// uint64_t outer_version = btlist.consume_integer<uint64_t>();
// if (outer_version == 1)
// {
// bool decode_result = DecodeVersion_1(btlist);
// // advance the llarp_buffer_t since lokimq serialization is unaware of it.
// // FIXME: this is broken (current_buffer got dropped), but the whole thing is getting
// // replaced.
// // buf->cur += btlist.
// // current_buffer().data() - buf_view.data() + 1;
// return decode_result;
// }
// else
// {
// log::warning(logcat, "Received RouterContact with unkown version ({})", outer_version);
// return false;
// }
// }
// catch (const std::exception& e)
// {
// log::debug(logcat, "RouterContact::BDecode failed: {}", e.what());
// }
return false;
}
bool
RouterContact::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf)
{
bool read = false;
(void)key;
// TOFIX: fuck everything about llarp_buffer_t
// if (!BEncodeMaybeReadDictEntry("a", addr, read, key, buf))
// return false;
// if (!BEncodeMaybeReadDictEntry("i", netID, read, key, buf))
// return false;
// if (!BEncodeMaybeReadDictEntry("k", _router_id, read, key, buf))
// return false;
// if (key.startswith("r"))
// {
// RouterVersion r;
// if (not r.BDecode(buf))
// return false;
// routerVersion = r;
// return true;
// }
// if (not BEncodeMaybeReadDictList("s", srvRecords, read, key, buf))
// return false;
// if (!BEncodeMaybeReadDictEntry("p", enckey, read, key, buf))
// return false;
// if (!BEncodeMaybeReadDictInt("u", _timestamp, read, key, buf))
// return false;
// if (!BEncodeMaybeReadDictInt("v", version, read, key, buf))
// return false;
// if (key.startswith("x") and serializeExit)
// {
// return bencode_discard(buf);
// }
// if (!BEncodeMaybeReadDictEntry("z", signature, read, key, buf))
// return false;
return read or bencode_discard(buf);
}
bool
RouterContact::is_public_addressable() const
{

@ -167,12 +167,6 @@ namespace llarp
clear()
{}
bool
BDecode(llarp_buffer_t* buf);
bool
decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf);
bool
is_public_addressable() const;
@ -201,6 +195,9 @@ namespace llarp
bool
is_obsolete_bootstrap() const;
void
bt_verify(oxenc::bt_dict_consumer& data, bool reject_expired = false) const;
void
bt_load(oxenc::bt_dict_consumer& data);
};
@ -233,7 +230,6 @@ namespace llarp
public:
LocalRC() = default;
explicit LocalRC(std::string payload, const SecretKey sk);
~LocalRC() = default;
RemoteRC
@ -309,9 +305,6 @@ namespace llarp
struct RemoteRC final : public RouterContact
{
private:
void
bt_verify(oxenc::bt_dict_consumer& data, bool reject_expired = false) const;
explicit RemoteRC(oxenc::bt_dict_consumer btdc);
public:

@ -34,43 +34,6 @@ namespace llarp
return RemoteRC{view()};
}
LocalRC::LocalRC(std::string payload, const SecretKey sk) : _secret_key{std::move(sk)}
{
_router_id = llarp::seckey_to_pubkey(_secret_key);
try
{
oxenc::bt_dict_consumer btdc{payload};
bt_load(btdc);
btdc.require_signature("~", [this](ustring_view msg, ustring_view sig) {
if (sig.size() != 64)
throw std::runtime_error{"Invalid signature: not 64 bytes"};
if (is_expired(time_now_ms()))
throw std::runtime_error{"Unable to verify expired RemoteRC!"};
// TODO: revisit if this is needed; detail from previous implementation
const auto* net = net::Platform::Default_ptr();
if (net->IsBogon(addr().in4()) and BLOCK_BOGONS)
{
auto err = "Unable to verify expired LocalRC!";
log::info(logcat, err);
throw std::runtime_error{err};
}
if (not crypto::verify(router_id(), msg, sig))
throw std::runtime_error{"Failed to verify LocalRC"};
});
}
catch (const std::exception& e)
{
log::warning(logcat, "Failed to parse LocalRC: {}", e.what());
throw;
}
}
void
LocalRC::bt_sign(oxenc::bt_dict_producer& btdp)
{

@ -26,47 +26,19 @@ namespace llarp
}
}
void
RemoteRC::bt_verify(oxenc::bt_dict_consumer& data, bool reject_expired) const
{
data.require_signature("~", [this, reject_expired](ustring_view msg, ustring_view sig) {
if (sig.size() != 64)
throw std::runtime_error{"Invalid signature: not 64 bytes"};
if (reject_expired and is_expired(time_now_ms()))
throw std::runtime_error{"Rejecting expired RemoteRC!"};
// TODO: revisit if this is needed; detail from previous implementation
const auto* net = net::Platform::Default_ptr();
if (net->IsBogon(addr().in4()) and BLOCK_BOGONS)
{
auto err = "Unable to verify expired RemoteRC address!";
log::info(logcat, err);
throw std::runtime_error{err};
}
if (not crypto::verify(router_id(), msg, sig))
throw std::runtime_error{"Failed to verify RemoteRC signature"};
});
}
bool
RemoteRC::read(const fs::path& fname)
{
ustring buf;
buf.resize(MAX_RC_SIZE);
_payload.resize(MAX_RC_SIZE);
try
{
auto nread = util::file_to_buffer(fname, buf.data(), buf.size());
buf.resize(nread);
auto nread = util::file_to_buffer(fname, _payload.data(), _payload.size());
_payload.resize(nread);
oxenc::bt_dict_consumer btdc{buf};
oxenc::bt_dict_consumer btdc{_payload};
bt_load(btdc);
bt_verify(btdc);
_payload = buf;
}
catch (const std::exception& e)
{

Loading…
Cancel
Save