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

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

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

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

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

@ -12,12 +12,42 @@
namespace llarp namespace llarp
{ {
void 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)}; 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) if (ipv4_port.size() != 6)
throw std::runtime_error{ throw std::runtime_error{
@ -34,7 +64,7 @@ namespace llarp
if (!_addr.is_public()) if (!_addr.is_public())
throw std::runtime_error{"Invalid RC: IPv4 address is not a publicly routable IP"}; 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) if (ipv6_port->size() != 18)
throw std::runtime_error{ throw std::runtime_error{
@ -55,22 +85,22 @@ namespace llarp
_addr6.reset(); _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) if (netid != ACTIVE_NETID)
throw std::runtime_error{ throw std::runtime_error{
"Invalid RC netid: expected {}, got {}; this is an RC for a different network!"_format( "Invalid RC netid: expected {}, got {}; this is an RC for a different network!"_format(
ACTIVE_NETID, netid)}; ACTIVE_NETID, netid)};
auto pubkey = data.require<std::string_view>("p"); auto pubkey = btdc.require<std::string_view>("p");
if (pubkey.size() != 32) if (pubkey.size() != 32)
throw std::runtime_error{ throw std::runtime_error{
"Invalid RC pubkey: expected 32 bytes, got {}"_format(pubkey.size())}; "Invalid RC pubkey: expected 32 bytes, got {}"_format(pubkey.size())};
std::memcpy(_router_id.data(), pubkey.data(), 32); 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) if (ver.size() != 3)
throw std::runtime_error{ throw std::runtime_error{
@ -120,106 +150,6 @@ namespace llarp
return obj; 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 bool
RouterContact::is_public_addressable() const RouterContact::is_public_addressable() const
{ {

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

@ -34,43 +34,6 @@ namespace llarp
return RemoteRC{view()}; 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 void
LocalRC::bt_sign(oxenc::bt_dict_producer& btdp) 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 bool
RemoteRC::read(const fs::path& fname) RemoteRC::read(const fs::path& fname)
{ {
ustring buf; _payload.resize(MAX_RC_SIZE);
buf.resize(MAX_RC_SIZE);
try try
{ {
auto nread = util::file_to_buffer(fname, buf.data(), buf.size()); auto nread = util::file_to_buffer(fname, _payload.data(), _payload.size());
buf.resize(nread); _payload.resize(nread);
oxenc::bt_dict_consumer btdc{buf}; oxenc::bt_dict_consumer btdc{_payload};
bt_load(btdc); bt_load(btdc);
bt_verify(btdc); bt_verify(btdc);
_payload = buf;
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {

Loading…
Cancel
Save