mirror of https://github.com/oxen-io/lokinet
commit
1939ba0b3d
@ -1,121 +0,0 @@
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "exit_info.hpp"
|
||||
|
||||
#include <llarp/util/bencode.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
bool
|
||||
ExitInfo::bt_encode(llarp_buffer_t* buf) const
|
||||
{
|
||||
SockAddr exitaddr = ipAddress.createSockAddr();
|
||||
const auto* exitaddr6 = static_cast<const sockaddr_in6*>(exitaddr);
|
||||
|
||||
SockAddr netmaskaddr = netmask.createSockAddr();
|
||||
const auto* netmaskaddr6 = static_cast<const sockaddr_in6*>(netmaskaddr);
|
||||
|
||||
char tmp[128] = {0};
|
||||
if (!bencode_start_dict(buf))
|
||||
return false;
|
||||
|
||||
if (!inet_ntop(AF_INET6, &exitaddr6->sin6_addr, tmp, sizeof(tmp)))
|
||||
return false;
|
||||
if (!BEncodeWriteDictString("a", std::string(tmp), buf))
|
||||
return false;
|
||||
|
||||
if (!inet_ntop(AF_INET6, &netmaskaddr6->sin6_addr, tmp, sizeof(tmp)))
|
||||
return false;
|
||||
if (!BEncodeWriteDictString("b", std::string(tmp), buf))
|
||||
return false;
|
||||
|
||||
if (!BEncodeWriteDictEntry("k", pubkey, buf))
|
||||
return false;
|
||||
|
||||
if (!BEncodeWriteDictInt("v", version, buf))
|
||||
return false;
|
||||
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
static bool
|
||||
bdecode_ip_string(llarp_buffer_t* buf, in6_addr& ip)
|
||||
{
|
||||
char tmp[128] = {0};
|
||||
llarp_buffer_t strbuf;
|
||||
if (!bencode_read_string(buf, &strbuf))
|
||||
return false;
|
||||
|
||||
if (strbuf.sz >= sizeof(tmp))
|
||||
return false;
|
||||
|
||||
memcpy(tmp, strbuf.base, strbuf.sz);
|
||||
tmp[strbuf.sz] = 0;
|
||||
return inet_pton(AF_INET6, tmp, &ip.s6_addr[0]) == 1;
|
||||
}
|
||||
|
||||
bool
|
||||
ExitInfo::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if (!BEncodeMaybeReadDictEntry("k", pubkey, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictInt("v", version, read, k, buf))
|
||||
return false;
|
||||
if (k.startswith("a"))
|
||||
{
|
||||
in6_addr tmp;
|
||||
if (not bdecode_ip_string(buf, tmp))
|
||||
return false;
|
||||
|
||||
SockAddr addr(tmp);
|
||||
ipAddress = IpAddress(addr);
|
||||
return true;
|
||||
}
|
||||
if (k.startswith("b"))
|
||||
{
|
||||
in6_addr tmp;
|
||||
if (not bdecode_ip_string(buf, tmp))
|
||||
return false;
|
||||
SockAddr addr(tmp);
|
||||
netmask = IpAddress(addr);
|
||||
return true;
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
std::string
|
||||
ExitInfo::ToString() const
|
||||
{
|
||||
/*
|
||||
// TODO: derive these from ipAdress
|
||||
throw std::runtime_error("FIXME: need in6_addr and netmask from IpAddress");
|
||||
in6_addr address;
|
||||
in6_addr netmask;
|
||||
|
||||
Printer printer(stream, level, spaces);
|
||||
|
||||
std::ostringstream ss;
|
||||
char tmp[128] = {0};
|
||||
|
||||
if (inet_ntop(AF_INET6, (void*)&address, tmp, sizeof(tmp)))
|
||||
ss << tmp;
|
||||
else
|
||||
return stream;
|
||||
ss << std::string("/");
|
||||
#if defined(ANDROID)
|
||||
snprintf(tmp, sizeof(tmp), "%zu", llarp::bits::count_array_bits(netmask.s6_addr));
|
||||
ss << tmp;
|
||||
#else
|
||||
ss << std::to_string(llarp::bits::count_array_bits(netmask.s6_addr));
|
||||
#endif
|
||||
printer.printValue(ss.str());
|
||||
*/
|
||||
return fmt::format("[Exit {}]", ipAddress.ToString());
|
||||
}
|
||||
|
||||
} // namespace llarp
|
@ -1,51 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ip_address.hpp"
|
||||
|
||||
#include <llarp/crypto/types.hpp>
|
||||
#include <llarp/util/bencode.hpp>
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
/**
|
||||
* exit_info.h
|
||||
*
|
||||
* utilities for handling exits on the llarp network
|
||||
*/
|
||||
|
||||
/// Exit info model
|
||||
namespace llarp
|
||||
{
|
||||
/// deprecated don't use me , this is only for backwards compat
|
||||
struct ExitInfo
|
||||
{
|
||||
IpAddress ipAddress;
|
||||
IpAddress netmask;
|
||||
PubKey pubkey;
|
||||
uint64_t version = llarp::constants::proto_version;
|
||||
|
||||
ExitInfo() = default;
|
||||
|
||||
ExitInfo(const PubKey& pk, const IpAddress& address) : ipAddress(address), pubkey(pk)
|
||||
{}
|
||||
|
||||
bool
|
||||
bt_encode(llarp_buffer_t* buf) const;
|
||||
|
||||
bool
|
||||
BDecode(llarp_buffer_t* buf)
|
||||
{
|
||||
return bencode_decode_dict(*this, buf);
|
||||
}
|
||||
|
||||
bool
|
||||
decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf);
|
||||
|
||||
std::string
|
||||
ToString() const;
|
||||
};
|
||||
|
||||
template <>
|
||||
constexpr inline bool IsToStringFormattable<ExitInfo> = true;
|
||||
|
||||
} // namespace llarp
|
@ -0,0 +1,138 @@
|
||||
#include "constants/version.hpp"
|
||||
#include "crypto/crypto.hpp"
|
||||
#include "net/net.hpp"
|
||||
#include "router_contact.hpp"
|
||||
#include "util/bencode.hpp"
|
||||
#include "util/buffer.hpp"
|
||||
#include "util/file.hpp"
|
||||
#include "util/time.hpp"
|
||||
|
||||
#include <oxenc/bt_serialize.h>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
LocalRC
|
||||
LocalRC::make(const SecretKey secret, oxen::quic::Address local)
|
||||
{
|
||||
return *new LocalRC{secret, local};
|
||||
}
|
||||
|
||||
LocalRC::LocalRC(const SecretKey secret, oxen::quic::Address local)
|
||||
: _secret_key{std::move(secret)}
|
||||
{
|
||||
_router_id = llarp::seckey_to_pubkey(_secret_key);
|
||||
_addr = std::move(local);
|
||||
_addr6.emplace(&_addr.in6());
|
||||
resign();
|
||||
}
|
||||
|
||||
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 RemoteRC!";
|
||||
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"};
|
||||
});
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
log::warning(logcat, "Failed to parse LocalRC: {}", e.what());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LocalRC::bt_sign(oxenc::bt_dict_producer& btdp)
|
||||
{
|
||||
_signature.clear();
|
||||
|
||||
btdp.append_signature("~", [this](ustring_view to_sign) {
|
||||
std::array<unsigned char, 64> sig;
|
||||
|
||||
if (!crypto::sign(const_cast<unsigned char*>(sig.data()), _secret_key, to_sign))
|
||||
throw std::runtime_error{"Failed to sign RC"};
|
||||
|
||||
_signature = {sig.data(), sig.size()};
|
||||
return sig;
|
||||
});
|
||||
|
||||
_payload = btdp.view<unsigned char>();
|
||||
}
|
||||
|
||||
void
|
||||
LocalRC::bt_encode(oxenc::bt_dict_producer& btdp)
|
||||
{
|
||||
btdp.append("", RC_VERSION);
|
||||
|
||||
std::array<unsigned char, 18> buf;
|
||||
|
||||
{
|
||||
if (not _addr.is_ipv4())
|
||||
throw std::runtime_error{"Unable to encode RC: addr is not IPv4"};
|
||||
|
||||
auto in4 = _addr.in4();
|
||||
|
||||
std::memcpy(buf.data(), &in4.sin_addr.s_addr, 4);
|
||||
std::memcpy(buf.data() + 4, &in4.sin_port, 2);
|
||||
|
||||
btdp.append("4", ustring_view{buf.data(), 6});
|
||||
}
|
||||
|
||||
if (_addr6)
|
||||
{
|
||||
if (not _addr.is_ipv6())
|
||||
throw std::runtime_error{"Unable to encode RC: addr6 is set but is not IPv6"};
|
||||
|
||||
auto in6 = _addr.in6();
|
||||
|
||||
std::memcpy(buf.data(), &in6.sin6_addr.s6_addr, 16);
|
||||
std::memcpy(buf.data() + 16, &in6.sin6_port, 2);
|
||||
|
||||
btdp.append("6", ustring_view{buf.data(), 18});
|
||||
}
|
||||
|
||||
if (ACTIVE_NETID != llarp::LOKINET_DEFAULT_NETID)
|
||||
btdp.append("i", ACTIVE_NETID);
|
||||
|
||||
btdp.append("p", _router_id.ToView());
|
||||
|
||||
btdp.append("t", _timestamp.time_since_epoch().count());
|
||||
|
||||
static_assert(llarp::LOKINET_VERSION.size() == 3);
|
||||
btdp.append(
|
||||
"v", std::string_view{reinterpret_cast<const char*>(llarp::LOKINET_VERSION.data()), 3});
|
||||
|
||||
bt_sign(btdp);
|
||||
}
|
||||
|
||||
void
|
||||
LocalRC::resign()
|
||||
{
|
||||
set_systime_timestamp();
|
||||
oxenc::bt_dict_producer btdp;
|
||||
bt_encode(btdp);
|
||||
bt_sign(btdp);
|
||||
}
|
||||
} // namespace llarp
|
@ -0,0 +1,106 @@
|
||||
#include "constants/version.hpp"
|
||||
#include "crypto/crypto.hpp"
|
||||
#include "net/net.hpp"
|
||||
#include "router_contact.hpp"
|
||||
#include "util/bencode.hpp"
|
||||
#include "util/buffer.hpp"
|
||||
#include "util/file.hpp"
|
||||
#include "util/time.hpp"
|
||||
|
||||
#include <oxenc/bt_serialize.h>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
RemoteRC::RemoteRC(oxenc::bt_dict_consumer btdc)
|
||||
{
|
||||
try
|
||||
{
|
||||
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 RemoteRC!";
|
||||
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"};
|
||||
});
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
log::warning(logcat, "Failed to parse RemoteRC: {}", e.what());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
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 (is_expired(time_now_ms()) and reject_expired)
|
||||
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 RemoteRC!";
|
||||
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"};
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteRC::read(const fs::path& fname)
|
||||
{
|
||||
ustring buf;
|
||||
buf.reserve(MAX_RC_SIZE);
|
||||
|
||||
try
|
||||
{
|
||||
util::file_to_buffer(fname, buf.data(), MAX_RC_SIZE);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
log::error(logcat, "Failed to read RC from {}: {}", fname, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
oxenc::bt_dict_consumer btdc{buf};
|
||||
bt_load(btdc);
|
||||
bt_verify(btdc);
|
||||
|
||||
_payload = buf;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteRC::verify() const
|
||||
{
|
||||
oxenc::bt_dict_consumer btdc{_payload};
|
||||
bt_verify(btdc);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace llarp
|
Loading…
Reference in New Issue