pull/384/head
Jeff Becker 5 years ago
parent 4dbeae63ee
commit eceb55623c
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -110,25 +110,34 @@ namespace llarp
bool
BaseSession::HandleGotExit(llarp::path::Path* p, llarp_time_t b)
{
BaseSession* self = this;
m_LastUse = router->Now();
m_LastUse = router->Now();
if(b == 0)
llarp::LogInfo("obtained an exit via ", p->Endpoint());
else
self = nullptr;
if(IsReady())
CallPendingCallbacks(true);
return true;
}
for(auto& f : m_PendingCallbacks)
f(self);
void
BaseSession::CallPendingCallbacks(bool success)
{
if(success)
{
for(auto& f : m_PendingCallbacks)
f(this);
}
else
{
for(auto& f : m_PendingCallbacks)
f(nullptr);
}
m_PendingCallbacks.clear();
return true;
}
bool
BaseSession::Stop()
{
for(auto& f : m_PendingCallbacks)
f(nullptr);
m_PendingCallbacks.clear();
CallPendingCallbacks(false);
auto sendExitClose = [&](llarp::path::Path* p) {
if(p->SupportsAnyRoles(llarp::path::ePathRoleExit))
{
@ -199,7 +208,8 @@ namespace llarp
bool
BaseSession::IsReady() const
{
return AvailablePaths(llarp::path::ePathRoleExit) > 0;
const size_t expect = (1 + (m_NumPaths / 2));
return AvailablePaths(llarp::path::ePathRoleExit) >= expect;
}
bool

@ -49,6 +49,12 @@ namespace llarp
bool
Flush();
path::PathRole
GetRoles() const override
{
return path::ePathRoleExit;
}
/// send close and stop session
bool
Stop() override;
@ -116,6 +122,9 @@ namespace llarp
llarp_time_t m_LastUse;
std::vector< SessionReadyFunc > m_PendingCallbacks;
void
CallPendingCallbacks(bool success);
};
struct ExitSession final : public BaseSession

@ -343,12 +343,6 @@ namespace llarp
}
else if(addr.FromString(qname, ".snode"))
{
if(HasPathToSNode(addr.as_array()))
{
msg.AddINReply(ObtainIPForAddr(addr, true));
reply(msg);
return true;
}
dns::Message *replyMsg = new dns::Message(std::move(msg));
EnsurePathToSNode(addr.as_array(),
[=](const RouterID &remote, exit::BaseSession *s) {

@ -6,62 +6,149 @@ namespace llarp
{
namespace iwp
{
std::array< byte_t, 6 > OuterMessage::obtain_flow_id_magic =
std::array< byte_t, 6 >{'n', 'e', 't', 'i', 'd', '?'};
std::array< byte_t, 6 > OuterMessage::give_flow_id_magic =
std::array< byte_t, 6 >{'n', 'e', 't', 'i', 'd', '!'};
OuterMessage::OuterMessage()
{
Clear();
}
OuterMessage::~OuterMessage()
{
}
void
OuterMessage::Clear()
{
command = 0;
flow.Zero();
netid.Zero();
nextFlowID.Zero();
rejectReason.clear();
reject.fill(0);
N.Zero();
X.Zero();
Xsize = 0;
Z.Zero();
Zsig.Zero();
Zhash.Zero();
pubkey.Zero();
magic.fill(0);
uinteger = 0;
A.reset();
}
void
OuterMessage::CreateReject(const char* msg, llarp_time_t now,
const PubKey& pk)
{
Clear();
std::copy_n(msg, std::min(strlen(msg), reject.size()), reject.begin());
uinteger = now;
pubkey = pk;
}
bool
OuterMessage::Encode(llarp_buffer_t* buf) const
{
if(buf->size_left() < 2)
return false;
*buf->cur = command;
buf->cur++;
*buf->cur = '=';
buf->cur++;
switch(command)
{
case eOCMD_ObtainFlowID:
case eOCMD_GiveFlowID:
if(!buf->write(reject.begin(), reject.end()))
return false;
if(!buf->write(give_flow_id_magic.begin(), give_flow_id_magic.end()))
return false;
if(!buf->write(flow.begin(), flow.end()))
return false;
if(!buf->write(pubkey.begin(), pubkey.end()))
return false;
return buf->write(Zsig.begin(), Zsig.end());
default:
return false;
}
}
bool
OuterMessage::Decode(llarp_buffer_t* buf)
{
if(buf->size_left() < 34)
static constexpr size_t header_size = 2;
if(buf->size_left() < header_size)
return false;
command = *buf->cur;
++buf->cur;
if(*buf->cur != '=')
return false;
std::copy_n(flow.begin(), 32, buf->cur);
buf->cur += 32;
++buf->cur;
switch(command)
{
case eOCMD_ObtainFlowID:
if(buf->size_left() < 40)
if(!buf->read_into(magic.begin(), magic.end()))
return false;
if(!buf->read_into(netid.begin(), netid.end()))
return false;
if(!buf->read_uint64(uinteger))
return false;
if(!buf->read_into(pubkey.begin(), pubkey.end()))
return false;
if(buf->size_left() <= Zsig.size())
return false;
buf->cur += 32;
std::copy_n(netid.begin(), 8, buf->cur);
return true;
Xsize = buf->size_left() - Zsig.size();
if(!buf->read_into(X.begin(), X.begin() + Xsize))
return false;
return buf->read_into(Zsig.begin(), Zsig.end());
case eOCMD_GiveFlowID:
if(buf->size_left() < 32)
if(!buf->read_into(magic.begin(), magic.end()))
return false;
if(!buf->read_into(flow.begin(), flow.end()))
return false;
if(!buf->read_into(pubkey.begin(), pubkey.end()))
return false;
std::copy_n(nextFlowID.begin(), 32, buf->cur);
return true;
buf->cur += buf->size_left() - Zsig.size();
return buf->read_into(Zsig.begin(), Zsig.end());
case eOCMD_Reject:
rejectReason = std::string(buf->cur, buf->base + buf->sz);
return true;
if(!buf->read_into(reject.begin(), reject.end()))
return false;
if(!buf->read_uint64(uinteger))
return false;
if(!buf->read_into(pubkey.begin(), pubkey.end()))
return false;
buf->cur += buf->size_left() - Zsig.size();
return buf->read_into(Zsig.begin(), Zsig.end());
case eOCMD_SessionNegotiate:
// explicit fallthrough
if(!buf->read_into(flow.begin(), flow.end()))
return false;
if(!buf->read_into(pubkey.begin(), pubkey.end()))
return false;
if(!buf->read_uint64(uinteger))
return false;
if(buf->size_left() == Zsig.size() + 32)
{
A.reset(new AlignedBuffer< 32 >());
if(!buf->read_into(A->begin(), A->end()))
return false;
}
return buf->read_into(Zsig.begin(), Zsig.end());
case eOCMD_TransmitData:
if(buf->size_left() <= 56)
if(!buf->read_into(flow.begin(), flow.end()))
return false;
std::copy_n(N.begin(), N.size(), buf->cur);
buf->cur += N.size();
Xsize = buf->size_left() - Z.size();
if(Xsize > X.size())
if(!buf->read_into(N.begin(), N.end()))
return false;
std::copy_n(X.begin(), Xsize, buf->cur);
buf->cur += Xsize;
std::copy_n(Z.begin(), Z.size(), buf->cur);
return true;
if(buf->size_left() <= Zhash.size())
return false;
Xsize = buf->size_left() - Zhash.size();
if(!buf->read_into(X.begin(), X.begin() + Xsize))
return false;
return buf->read_into(Zhash.begin(), Zhash.end());
default:
return false;
}
@ -73,6 +160,7 @@ namespace llarp
TimeoutHandler t, SessionClosedHandler closed)
: ILinkLayer(enckey, getrc, h, sign, est, reneg, t, closed), crypto(c)
{
m_FlowCookie.Randomize();
}
LinkLayer::~LinkLayer()
@ -118,8 +206,9 @@ namespace llarp
LinkLayer::RecvFrom(const Addr& from, const void* pkt, size_t sz)
{
m_OuterMsg.Clear();
llarp_buffer_t buf(pkt, sz);
if(!m_OuterMsg.Decode(&buf))
llarp_buffer_t sigbuf(pkt, sz);
llarp_buffer_t decodebuf(pkt, sz);
if(!m_OuterMsg.Decode(&decodebuf))
{
LogError("failed to decode outer message");
return;
@ -128,13 +217,27 @@ namespace llarp
switch(m_OuterMsg.command)
{
case eOCMD_ObtainFlowID:
sigbuf.sz -= m_OuterMsg.Zsig.size();
if(!crypto->verify(m_OuterMsg.pubkey, sigbuf, m_OuterMsg.Zsig))
{
LogError("failed to verify signature on '",
(char)m_OuterMsg.command, "' message from ", from);
return;
}
if(!ShouldSendFlowID(from))
return; // drop
{
SendReject(from, "no flo 4u :^)");
return;
}
if(m_OuterMsg.netid == ourNetID)
SendFlowID(from, m_OuterMsg.flow);
{
if(GenFlowIDFor(m_OuterMsg.pubkey, from, m_OuterMsg.flow))
SendFlowID(from, m_OuterMsg.flow);
else
SendReject(from, "genflow fail");
}
else
SendReject(from, m_OuterMsg.flow, "bad net id");
SendReject(from, "bad netid");
}
}
@ -156,6 +259,35 @@ namespace llarp
(void)flow;
}
bool
LinkLayer::VerifyFlowID(const PubKey& pk, const Addr& from,
const FlowID_t& flow) const
{
FlowID_t expected;
if(!GenFlowIDFor(pk, from, expected))
return false;
return expected == flow;
}
bool
LinkLayer::GenFlowIDFor(const PubKey& pk, const Addr& from,
FlowID_t& flow) const
{
std::array< byte_t, 128 > tmp = {0};
if(inet_ntop(AF_INET6, from.addr6(), (char*)tmp.data(), tmp.size())
== nullptr)
return false;
std::copy_n(pk.begin(), pk.size(), tmp.begin() + 64);
std::copy_n(m_FlowCookie.begin(), m_FlowCookie.size(),
tmp.begin() + 64 + pk.size());
llarp_buffer_t buf(tmp);
ShortHash h;
if(!crypto->shorthash(h, buf))
return false;
std::copy_n(h.begin(), flow.size(), flow.begin());
return true;
}
bool
LinkLayer::ShouldSendFlowID(const Addr& to) const
{
@ -165,12 +297,33 @@ namespace llarp
}
void
LinkLayer::SendReject(const Addr& to, const FlowID_t& flow, const char* msg)
LinkLayer::SendReject(const Addr& to, const char* msg)
{
// TODO: implement me
(void)to;
(void)flow;
(void)msg;
if(strlen(msg) > 14)
{
throw std::logic_error("reject message too big");
}
std::array< byte_t, 120 > pkt;
auto now = Now();
PubKey pk = GetOurRC().pubkey;
OuterMessage m;
m.CreateReject(msg, now, pk);
llarp_buffer_t encodebuf(pkt);
if(!m.Encode(&encodebuf))
{
LogError("failed to encode reject message to ", to);
return;
}
llarp_buffer_t signbuf(pkt.data(), pkt.size() - m.Zsig.size());
if(!Sign(m.Zsig, signbuf))
{
LogError("failed to sign reject messsage to ", to);
return;
}
std::copy_n(m.Zsig.begin(), m.Zsig.size(),
pkt.begin() + (pkt.size() - m.Zsig.size()));
llarp_buffer_t pktbuf(pkt);
SendTo_LL(to, pktbuf);
}
std::unique_ptr< ILinkLayer >

@ -8,6 +8,7 @@
#include <link/server.hpp>
#include <link/session.hpp>
#include <array>
#include <bitset>
#include <deque>
@ -46,15 +47,35 @@ namespace llarp
byte_t command;
FlowID_t flow;
OuterMessage();
~OuterMessage();
// static members
static std::array< byte_t, 6 > obtain_flow_id_magic;
static std::array< byte_t, 6 > give_flow_id_magic;
void
CreateReject(const char *msg, llarp_time_t now, const PubKey &pk);
// optional memebers follow
std::array< byte_t, 6 > magic;
NetID netid;
FlowID_t nextFlowID;
std::string rejectReason;
// either timestamp or counter
uint64_t uinteger;
std::array< byte_t, 14 > reject;
AlignedBuffer< 24 > N;
// TODO: compute optimal size
AlignedBuffer< 1440 > X;
PubKey pubkey;
std::unique_ptr< AlignedBuffer< 32 > > A;
static constexpr size_t ipv6_mtu = 1280;
static constexpr size_t overhead_size = 16 + 24 + 32;
static constexpr size_t payload_size = ipv6_mtu - overhead_size;
AlignedBuffer< payload_size > X;
size_t Xsize;
ShortHash Z;
ShortHash Zhash;
Signature Zsig;
/// encode to buffer
bool
@ -64,10 +85,6 @@ namespace llarp
bool
Decode(llarp_buffer_t *buf);
/// verify signature if needed
bool
Verify(const SharedSecret &K) const;
/// clear members
void
Clear();
@ -264,20 +281,23 @@ namespace llarp
uint16_t
Rank() const override;
/// verify that a new flow id matches addresses and old flow id
/// verify that a new flow id matches addresses and pubkey
bool
VerifyFlowID(const FlowID_t &newID, const Addr &from,
const FlowID_t &oldID) const;
VerifyFlowID(const PubKey &pk, const Addr &from,
const FlowID_t &flow) const;
void
RecvFrom(const llarp::Addr &from, const void *buf, size_t sz) override;
private:
bool
GenFlowIDFor(const PubKey &pk, const Addr &from, FlowID_t &flow) const;
bool
ShouldSendFlowID(const Addr &from) const;
void
SendReject(const Addr &to, const FlowID_t &flow, const char *msg);
SendReject(const Addr &to, const char *msg);
void
SendFlowID(const Addr &to, const FlowID_t &flow);

@ -223,12 +223,23 @@ namespace llarp
void
ILinkLayer::Tick(llarp_time_t now)
{
Lock l(m_AuthedLinksMutex);
auto itr = m_AuthedLinks.begin();
while(itr != m_AuthedLinks.end())
{
itr->second->Tick(now);
++itr;
Lock l(m_AuthedLinksMutex);
auto itr = m_AuthedLinks.begin();
while(itr != m_AuthedLinks.end())
{
itr->second->Tick(now);
++itr;
}
}
{
Lock l(m_PendingMutex);
auto itr = m_Pending.begin();
while(itr != m_Pending.end())
{
itr->second->Tick(now);
++itr;
}
}
}

@ -93,7 +93,7 @@ namespace llarp
}
void
SendTo_LL(const llarp::Addr& to, llarp_buffer_t pkt)
SendTo_LL(const llarp::Addr& to, const llarp_buffer_t& pkt)
{
llarp_ev_udp_sendto(&m_udp, to, pkt);
}

@ -70,9 +70,11 @@ namespace llarp
bool
RouterProfile::IsGood(uint64_t chances) const
{
return connectTimeoutCount <= connectGoodCount
/// N chances
&& (pathSuccessCount * chances) >= pathFailCount;
if(connectTimeoutCount > 3)
return connectTimeoutCount <= connectGoodCount
&& (pathSuccessCount * chances) >= pathFailCount;
else
return (pathSuccessCount * chances) >= pathFailCount;
}
bool

@ -1223,7 +1223,10 @@ namespace llarp
auto itr = range.first;
while(itr != range.second)
{
itr->second->AddReadyHook(std::bind(h, snode, std::placeholders::_1));
if(itr->second->IsReady())
h(snode, itr->second.get());
else
itr->second->AddReadyHook(std::bind(h, snode, std::placeholders::_1));
++itr;
}
}
@ -1749,7 +1752,7 @@ namespace llarp
{
// we can safely set remoteIntro to the next one
SwapIntros();
llarp::LogInfo(Name(), "swapped intro");
llarp::LogInfo(Name(), " swapped intro");
}
}
// lookup router in intro if set and unknown
@ -1767,6 +1770,10 @@ namespace llarp
// send control message if we look too quiet
if(now - lastGoodSend > (sendTimeout / 2))
{
if(!GetNewestPathByRouter(remoteIntro.router))
{
BuildOneAlignedTo(remoteIntro.router);
}
Encrypted< 64 > tmp;
tmp.Randomize();
llarp_buffer_t buf(tmp.data(), tmp.size());
@ -1864,7 +1871,6 @@ namespace llarp
{
llarp::LogError("cannot encrypt and send: no path for intro ",
remoteIntro);
return;
}

@ -43,6 +43,16 @@ llarp_buffer_t::put_uint16(uint16_t i)
return true;
}
bool
llarp_buffer_t::put_uint64(uint64_t i)
{
if(size_left() < sizeof(uint64_t))
return false;
htobe64buf(cur, i);
cur += sizeof(uint64_t);
return true;
}
bool
llarp_buffer_t::put_uint32(uint32_t i)
{
@ -73,6 +83,16 @@ llarp_buffer_t::read_uint32(uint32_t& i)
return true;
}
bool
llarp_buffer_t::read_uint64(uint64_t& i)
{
if(size_left() < sizeof(uint64_t))
return false;
i = bufbe64toh(cur);
cur += sizeof(uint64_t);
return true;
}
size_t
llarp_buffer_t::read_until(char delim, byte_t* result, size_t resultsize)
{

@ -12,6 +12,7 @@
#include <stdlib.h>
#include <string.h>
#include <utility>
#include <algorithm>
/**
* buffer.h
@ -116,6 +117,10 @@ struct llarp_buffer_t
size_t
size_left() const;
template < typename OutputIt >
bool
read_into(OutputIt begin, OutputIt end);
template < typename InputIt >
bool
write(InputIt begin, InputIt end);
@ -136,11 +141,17 @@ struct llarp_buffer_t
bool
put_uint32(uint32_t i);
bool
put_uint64(uint64_t i);
bool
read_uint16(uint16_t &i);
bool
read_uint32(uint32_t &i);
bool
read_uint64(uint64_t &i);
size_t
read_until(char delim, byte_t *result, size_t resultlen);
@ -153,6 +164,20 @@ struct llarp_buffer_t
bool
operator==(const llarp_buffer_t &buff, const char *data);
template < typename OutputIt >
bool
llarp_buffer_t::read_into(OutputIt begin, OutputIt end)
{
auto dist = std::distance(begin, end);
if(static_cast< decltype(dist) >(size_left()) >= dist)
{
std::copy_n(cur, dist, begin);
cur += dist;
return true;
}
return false;
}
template < typename InputIt >
bool
llarp_buffer_t::write(InputIt begin, InputIt end)

Loading…
Cancel
Save