hidden services sorta work

pull/13/head
Jeff Becker 6 years ago
parent a9b28e5407
commit e79708c1dc
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -82,7 +82,7 @@ testnet-clean: clean
rm -rf $(TESTNET_ROOT)
testnet-configure: testnet-clean
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON
testnet-build: testnet-configure
ninja

@ -21,12 +21,8 @@ namespace llarp
{
if(randomize)
Randomize();
}
AlignedBuffer(const AlignedBuffer& other)
{
for(size_t idx = 0; idx < (sz / 8); ++idx)
l[idx] = other.l[idx];
else
Zero();
}
AlignedBuffer(const byte_t* data)
@ -68,6 +64,24 @@ namespace llarp
return memcmp(l, other.l, sz) < 0;
}
bool
operator>(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) > 0;
}
bool
operator<=(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) <= 0;
}
bool
operator>=(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) >= 0;
}
AlignedBuffer
operator^(const AlignedBuffer& other) const
{
@ -110,7 +124,7 @@ namespace llarp
size_t idx = sz / 8;
while(idx)
{
if(l[idx--])
if(l[--idx])
return false;
}
return true;

@ -14,12 +14,13 @@ namespace llarp
return bencode_write_bytestring(buf, k, 1)
&& bencode_write_bytestring(buf, t, 1);
}
template < typename Obj_t >
bool
BEncodeWriteDictString(const char* k, const Obj_t& str, llarp_buffer_t* buf)
{
return bencode_write_bytestring(buf, k, 1)
&& bencode_write_bytestring(buf, str.c_str(), str.size());
&& bencode_write_bytestring(buf, str.data(), str.size());
}
template < typename Obj_t >
@ -149,11 +150,7 @@ namespace llarp
T item;
if(!item.BDecode(buf))
return false;
result.insert(item);
/*
if(!result.insert(item).second)
return false;
*/
return result.insert(item).second;
}
if(*buf->cur != 'e') // make sure we're at a list end
return false;

@ -19,8 +19,7 @@ namespace llarp
Bucket(const Key_t& us) : nodes(XorMetric(us)){};
bool
GetRandomNodeExcluding(Key_t& result,
const std::set< Key_t >& exclude) const
GetRandomNodeExcluding(Key_t& result, std::set< Key_t > exclude) const
{
std::vector< Key_t > candidates;
for(const auto& item : nodes)
@ -53,7 +52,7 @@ namespace llarp
bool
FindCloseExcluding(const Key_t& target, Key_t& result,
const std::set< Key_t >& exclude) const
std::set< Key_t > exclude) const
{
Key_t maxdist;
maxdist.Fill(0xff);
@ -61,8 +60,9 @@ namespace llarp
mindist.Fill(0xff);
for(const auto& item : nodes)
{
if(exclude.find(item.first) != exclude.end())
if(exclude.count(item.first))
continue;
auto curDist = item.first ^ target;
if(curDist < mindist)
{

@ -6,6 +6,7 @@
#include <llarp/dht/bucket.hpp>
#include <llarp/dht/key.hpp>
#include <llarp/dht/message.hpp>
#include <llarp/dht/messages/findintro.hpp>
#include <llarp/dht/node.hpp>
#include <llarp/dht/search_job.hpp>
#include <llarp/service/IntroSet.hpp>
@ -60,7 +61,43 @@ namespace llarp
void
LookupIntroSetForPath(const service::Address& addr, uint64_t txid,
const llarp::PathID_t& path, const Key_t& askpeer);
const llarp::PathID_t& path, Key_t askpeer);
template < typename Job, typename Result >
void
TryLookupAgain(Job* j, Result r, uint64_t R)
{
const Key_t targetKey = j->target.ToKey();
Key_t askpeer;
std::set< Key_t > exclude = j->asked;
if(!nodes->FindCloseExcluding(targetKey, askpeer, exclude))
{
j->Exausted();
delete j;
return;
}
if((OurKey() ^ targetKey) < (askpeer ^ targetKey))
{
j->Exausted();
delete j;
return;
}
auto id = ++ids;
TXOwner ownerKey;
ownerKey.node = askpeer;
ownerKey.txid = id;
SearchJob job(j->whoasked, j->txid, r, [j]() { delete j; });
pendingTX[ownerKey] = job;
auto msg = new FindIntroMessage(id, j->target);
msg->R = R;
llarp::LogInfo("asking ", askpeer, " for ", j->target.ToString(),
" with txid=", id);
DHTSendTo(askpeer, msg);
j->asked.insert(std::move(askpeer));
}
void
DHTSendTo(const Key_t& peer, IMessage* msg);
void
LookupIntroSetRelayed(const Key_t& requester, uint64_t txid,

@ -21,16 +21,14 @@ namespace llarp
relayed = relay;
}
FindIntroMessage(const Key_t& from, const llarp::service::Tag& tag,
uint64_t txid)
: IMessage(from), N(tag), T(txid)
FindIntroMessage(const llarp::service::Tag& tag, uint64_t txid)
: IMessage({}), N(tag), T(txid)
{
S.Zero();
}
FindIntroMessage(const Key_t& from, const llarp::service::Address& addr,
uint64_t txid)
: IMessage(from), S(addr), T(txid)
FindIntroMessage(uint64_t txid, const llarp::service::Address& addr)
: IMessage({}), S(addr), T(txid)
{
N.Zero();
}

@ -8,11 +8,13 @@ namespace llarp
{
struct GotRouterMessage : public IMessage
{
GotRouterMessage(const Key_t& from) : IMessage(from)
GotRouterMessage(const Key_t& from, bool tunneled)
: IMessage(from), relayed(tunneled)
{
}
GotRouterMessage(const Key_t& from, uint64_t id, const llarp_rc* result)
: IMessage(from), txid(id)
GotRouterMessage(const Key_t& from, uint64_t id, const llarp_rc* result,
bool tunneled)
: IMessage(from), txid(id), relayed(tunneled)
{
if(result)
{
@ -37,6 +39,7 @@ namespace llarp
std::vector< llarp_rc > R;
uint64_t txid = 0;
uint64_t version = 0;
bool relayed = false;
};
} // namespace dht
} // namespace llarp

@ -18,9 +18,11 @@ namespace llarp
{
const static uint64_t JobTimeout = 30000;
typedef std::function< void(
typedef std::function< bool(
const std::vector< llarp::service::IntroSet >&) >
IntroSetHookFunc;
typedef std::function< void(void) > DoneFunc;
SearchJob();
/// for routers
SearchJob(const Key_t& requester, uint64_t requesterTX,
@ -29,15 +31,15 @@ namespace llarp
/// for introsets
SearchJob(const Key_t& requester, uint64_t requesterTX,
const Key_t& target, const std::set< Key_t >& excludes,
IntroSetHookFunc found);
IntroSetHookFunc found, DoneFunc done);
// for introsets via tag
SearchJob(const Key_t& requester, uint64_t requseterTX,
IntroSetHookFunc found);
IntroSetHookFunc found, DoneFunc done);
void
FoundRouter(const llarp_rc* router) const;
void
bool
FoundIntros(
const std::vector< llarp::service::IntroSet >& introset) const;
@ -50,6 +52,7 @@ namespace llarp
// only set if looking up router
llarp_router_lookup_job* job = nullptr;
IntroSetHookFunc foundIntroHook;
DoneFunc onDone;
llarp_time_t started;
Key_t requester;
uint64_t requesterTX;

@ -1,7 +1,7 @@
#ifndef LLARP_IWP_H_
#define LLARP_IWP_H_
#ifndef LLARP_IWP_HPP
#define LLARP_IWP_HPP
#include <llarp/crypto.h>
#include "router.hpp"
#include <string>
struct llarp_iwp_args
{
@ -9,7 +9,7 @@ struct llarp_iwp_args
struct llarp_logic* logic;
struct llarp_threadpool* cryptoworker;
struct llarp_router* router;
const char* keyfile;
std::string keyfile;
};
#endif

@ -1,5 +1,5 @@
#pragma once
#include <llarp/iwp.h>
#include <llarp/iwp.hpp>
#include <llarp/threading.hpp>
#include "llarp/iwp/establish_job.hpp"
#include "router.hpp"
@ -26,7 +26,7 @@ struct llarp_link
llarp_link *parent = nullptr;
llarp_udp_io udp;
llarp::Addr addr;
char keyfile[255];
std::string keyfile;
uint32_t timeout_job_id;
const char *

@ -358,6 +358,9 @@ namespace llarp
PathSet*
GetLocalPathSet(const PathID_t& id);
routing::IMessageHandler*
GetHandler(const PathID_t& id);
bool
ForwardLRCM(const RouterID& nextHop,
std::deque< EncryptedFrame >& frames);

@ -78,6 +78,19 @@ namespace llarp
return false;
}
/// override me in subtype
virtual bool
HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg)
{
return false;
}
virtual routing::IMessageHandler*
GetDHTHandler()
{
return nullptr;
}
Path*
GetEstablishedPathClosestTo(const RouterID& router) const;
@ -87,6 +100,9 @@ namespace llarp
Path*
GetPathByRouter(const RouterID& router) const;
Path*
GetPathByID(const PathID_t& id) const;
bool
GetCurrentIntroductions(
std::set< llarp::service::Introduction >& intros) const;

@ -19,9 +19,6 @@ namespace llarp
bool
IsValid(llarp_shorthash_func hashfunc) const;
bool
BDecode(llarp_buffer_t* buf);
bool
DecodeKey(llarp_buffer_t k, llarp_buffer_t* val);

@ -10,14 +10,58 @@ namespace llarp
{
struct ServiceInfo : public llarp::IBEncodeMessage
{
private:
llarp::PubKey enckey;
llarp::PubKey signkey;
uint64_t version = 0;
VanityNonce vanity;
ServiceInfo();
public:
ServiceInfo() = default;
ServiceInfo(const ServiceInfo&& other)
{
enckey = std::move(other.enckey);
signkey = std::move(other.signkey);
version = std::move(other.version);
vanity = std::move(other.vanity);
m_CachedAddr = std::move(other.m_CachedAddr);
}
ServiceInfo(const ServiceInfo& other)
{
enckey = other.enckey;
signkey = other.signkey;
version = other.version;
vanity = other.vanity;
m_CachedAddr = other.m_CachedAddr;
}
void
RandomizeVanity()
{
vanity.Randomize();
}
bool
Verify(llarp_crypto* crypto, llarp_buffer_t payload,
const Signature& sig) const
{
return crypto->verify(signkey, payload, sig);
}
byte_t*
EncryptionPublicKey()
{
return enckey;
}
~ServiceInfo();
bool
Update(const byte_t* enc, const byte_t* sign)
{
enckey = enc;
signkey = sign;
return UpdateAddr();
}
bool
operator==(const ServiceInfo& other) const
@ -26,6 +70,12 @@ namespace llarp
&& version == other.version && vanity == other.vanity;
}
bool
operator!=(const ServiceInfo& other) const
{
return !(*this == other);
}
ServiceInfo&
operator=(const ServiceInfo& other)
{
@ -50,7 +100,7 @@ namespace llarp
<< " v=" << i.version << " x=" << i.vanity << "]";
}
/// compute .loki address
/// .loki address
std::string
Name() const;
@ -70,9 +120,9 @@ namespace llarp
bool
BDecode(llarp_buffer_t* buf)
{
if(!IBEncodeMessage::BDecode(buf))
return false;
return CalculateAddress(m_CachedAddr);
if(IBEncodeMessage::BDecode(buf))
return CalculateAddress(m_CachedAddr.data());
return false;
}
bool

@ -25,6 +25,29 @@ namespace llarp
llarp::PoW* W = nullptr;
llarp::Signature Z;
IntroSet() = default;
IntroSet(const IntroSet&& other)
{
A = std::move(other.A);
I = std::move(other.I);
version = std::move(other.version);
topic = std::move(other.topic);
W = std::move(other.W);
Z = std::move(other.Z);
}
IntroSet(const IntroSet& other)
{
A = other.A;
I = other.I;
version = other.version;
topic = other.topic;
if(other.W)
W = new llarp::PoW(*other.W);
Z = other.Z;
}
~IntroSet();
IntroSet&
@ -73,6 +96,23 @@ namespace llarp
return out << " V=" << i.version << " Z=" << i.Z;
}
bool
IsNewerThan(const IntroSet& other) const
{
return GetNewestIntro().expiresAt > other.GetNewestIntro().expiresAt;
}
Introduction
GetNewestIntro() const
{
Introduction i;
i.expiresAt = 0;
for(const auto& intro : I)
if(intro.expiresAt > i.expiresAt)
i = intro;
return i;
}
bool
HasExpiredIntros(llarp_time_t now) const;

@ -2,13 +2,14 @@
#define LLARP_SERVICE_ADDRESS_HPP
#include <llarp/aligned.hpp>
#include <llarp/dht/key.hpp>
#include <llarp/router_id.hpp>
#include <string>
namespace llarp
{
namespace service
{
struct Address : public llarp::AlignedBuffer< 32 >
struct Address
{
std::string
ToString() const;
@ -16,28 +17,152 @@ namespace llarp
bool
FromString(const std::string& str);
Address() : llarp::AlignedBuffer< 32 >()
Address()
{
Zero();
}
Address(const byte_t* data) : llarp::AlignedBuffer< 32 >(data)
Address(const Address& other)
{
memcpy(b, other.b, 32);
}
struct Hash
byte_t& operator[](size_t idx)
{
size_t
operator()(const Address& addr) const
return b[idx];
}
const byte_t& operator[](size_t idx) const
{
return b[idx];
}
bool
BEncode(llarp_buffer_t* buf) const
{
return bencode_write_bytestring(buf, b, 32);
}
bool
BDecode(llarp_buffer_t* buf)
{
llarp_buffer_t strbuf;
if(!bencode_read_string(buf, &strbuf))
return false;
if(strbuf.sz != 32)
{
size_t idx = 0;
memcpy(&idx, addr, sizeof(idx));
return idx;
llarp::LogErrorTag("Address::BDecode",
"bdecode buffer size missmatch ", strbuf.sz,
"!=32");
return false;
}
};
memcpy(b, strbuf.base, 32);
return true;
}
operator const dht::Key_t() const
size_t
size() const
{
return 32;
}
bool
IsZero() const
{
size_t sz = 4;
while(sz)
{
if(l[--sz])
return false;
}
return true;
}
void
Zero()
{
size_t sz = 4;
while(sz)
{
l[--sz] = 0;
}
}
bool
operator<(const Address& other) const
{
return memcmp(data(), other.data(), 32) < 0;
}
friend std::ostream&
operator<<(std::ostream& out, const Address& self)
{
return out << self.ToString();
}
bool
operator==(const Address& other) const
{
return memcmp(data(), other.data(), 32) == 0;
}
bool
operator!=(const Address& other) const
{
return !(*this == other);
}
Address&
operator=(const Address& other)
{
memcpy(data(), other.data(), 32);
return *this;
}
const dht::Key_t
ToKey() const
{
return dht::Key_t(data());
}
const RouterID
ToRouter() const
{
return RouterID(data());
}
const byte_t*
data() const
{
return b;
}
byte_t*
data()
{
return b;
}
const uint64_t*
data_l() const
{
return l;
}
struct Hash
{
size_t
operator()(const Address& buf) const
{
return *buf.data_l();
}
};
private:
union {
byte_t b[32];
uint64_t l[4];
};
};
} // namespace service

@ -67,6 +67,9 @@ namespace llarp
bool
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
bool
HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg);
bool
HandleHiddenServiceFrame(const llarp::service::ProtocolFrame* msg);
@ -90,6 +93,10 @@ namespace llarp
// override me in subclass
}
/// ensure that we know a router, looks up if it doesn't
void
EnsureRouterIsKnown(const RouterID& router);
Identity*
GetIdentity()
{
@ -136,9 +143,6 @@ namespace llarp
bool
SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop);
bool
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
bool
HandleHiddenServiceFrame(const ProtocolFrame* frame);
@ -149,6 +153,9 @@ namespace llarp
Name() const;
private:
bool
OnIntroSetUpdate(const IntroSet* i);
void
EncryptAndSendTo(llarp_buffer_t payload);
@ -227,6 +234,9 @@ namespace llarp
IsolateNetwork();
private:
bool
OnOutboundLookup(const IntroSet* i); /* */
static bool
SetupIsolatedNetwork(void* user);
@ -252,6 +262,9 @@ namespace llarp
m_RemoteSessions;
std::unordered_map< Address, PathEnsureHook, Address::Hash >
m_PendingServiceLookups;
std::unordered_map< RouterID, uint64_t, RouterID::Hash > m_PendingRouters;
uint64_t m_CurrentPublishTX = 0;
llarp_time_t m_LastPublish = 0;
llarp_time_t m_LastPublishAttempt = 0;

@ -82,7 +82,7 @@ namespace llarp
BEncode(llarp_buffer_t* buf) const;
bool
Verify(llarp_crypto* c, byte_t* signingkey) const;
Verify(llarp_crypto* c, const ServiceInfo& from) const;
bool
HandleMessage(llarp::routing::IMessageHandler* h, llarp_router* r) const;

@ -13,7 +13,6 @@ namespace llarp
{
Tag() : llarp::AlignedBuffer< 16 >()
{
Zero();
}
Tag(const byte_t* d) : llarp::AlignedBuffer< 16 >(d)
@ -36,17 +35,26 @@ namespace llarp
return *this;
}
llarp::dht::Key_t
Key() const
Tag&
operator=(const std::string& str)
{
llarp::dht::Key_t k;
crypto_generichash(k, 32, data(), 16, nullptr, 0);
return k;
#ifndef MIN
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
memcpy(data(), str.data(), MIN(16UL, str.size()));
#undef MIN
#endif
return *this;
}
std::string
ToString() const;
bool
Empty() const
{
return ToString().empty();
}
struct Hash
{
std::size_t

@ -51,18 +51,52 @@ namespace llarp
struct PathLookupJob
{
Key_t whoasked;
service::Address target;
uint64_t txid;
PathID_t pathID;
llarp_router *m_router;
std::set< service::IntroSet > localIntroSets;
std::set< Key_t > asked;
int m_TriesLeft = 5;
uint64_t R = 0;
PathLookupJob(llarp_router *r, const PathID_t &localpath, uint64_t tx)
: txid(tx), pathID(localpath), m_router(r)
{
whoasked = r->dht->impl.OurKey();
}
void
TryAgain()
{
--m_TriesLeft;
auto &dht = m_router->dht->impl;
llarp::LogInfo("try lookup again");
dht.TryLookupAgain(
this,
std::bind(&PathLookupJob::OnResult, this, std::placeholders::_1),
R);
}
void
Exausted()
{
llarp::LogWarn("Exausted peers for lookup");
auto path =
m_router->paths.GetByUpstream(m_router->dht->impl.OurKey(), pathID);
if(path)
{
llarp::routing::DHTMessage msg;
msg.M.push_back(new llarp::dht::GotIntroMessage(
std::vector< service::IntroSet >(), txid));
path->SendRoutingMessage(&msg, m_router);
}
else
llarp::LogError("no path for lookup pathid=", pathID);
}
bool
OnResult(const std::vector< service::IntroSet > &results)
{
auto path =
@ -73,23 +107,35 @@ namespace llarp
{
localIntroSets.insert(introset);
}
llarp::routing::DHTMessage msg;
auto sz = localIntroSets.size();
std::vector< service::IntroSet > intros(sz);
for(const auto &i : localIntroSets)
if(sz || target.IsZero() || m_TriesLeft == 0)
{
intros[--sz] = i;
llarp::routing::DHTMessage msg;
std::vector< service::IntroSet > intros(sz);
for(const auto &i : localIntroSets)
{
intros[--sz] = i;
}
llarp::LogInfo("found ", sz, " introsets for txid=", txid);
msg.M.push_back(new llarp::dht::GotIntroMessage(intros, txid));
path->SendRoutingMessage(&msg, m_router);
}
else if(!target.IsZero())
{
if(m_TriesLeft)
{
TryAgain();
return false;
}
}
llarp::LogInfo("found ", sz, " introsets for txid=", txid);
msg.M.push_back(new llarp::dht::GotIntroMessage(intros, txid));
path->SendRoutingMessage(&msg, m_router);
}
else
{
llarp::LogWarn("no local path for reply on PathTagLookupJob pathid=",
pathID);
}
delete this;
return true;
}
};
@ -110,8 +156,10 @@ namespace llarp
TXOwner ownerKey;
ownerKey.node = peer;
ownerKey.txid = id;
SearchJob job(from, txid,
[](const std::vector< service::IntroSet > &) {});
SearchJob job(
from, txid,
[](const std::vector< service::IntroSet > &) -> bool { return true; },
[]() {});
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(peer);
msg->msgs.push_back(new PublishIntroMessage(introset, id, S, E));
@ -130,12 +178,14 @@ namespace llarp
j->localIntroSets = FindRandomIntroSetsWithTag(tag);
SearchJob job(
OurKey(), txid,
std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1));
std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1),
[j]() { delete j; });
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage({}, tag, id);
auto dhtmsg = new FindIntroMessage(tag, id);
dhtmsg->R = 5;
j->R = 5;
msg->msgs.push_back(dhtmsg);
llarp::LogInfo("asking ", askpeer, " for tag ", tag.ToString(), " with ",
j->localIntroSets.size(), " local tags txid=", txid);
@ -144,24 +194,29 @@ namespace llarp
void
Context::LookupIntroSetForPath(const service::Address &addr, uint64_t txid,
const llarp::PathID_t &path,
const Key_t &askpeer)
const llarp::PathID_t &path, Key_t askpeer)
{
auto id = ++ids;
TXOwner ownerKey;
ownerKey.node = askpeer;
ownerKey.txid = id;
PathLookupJob *j = new PathLookupJob(router, path, txid);
j->target = addr;
j->R = 5;
j->asked.emplace(askpeer);
Key_t us = OurKey();
j->asked.emplace(us);
SearchJob job(
OurKey(), txid,
std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1));
std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1),
[j]() { delete j; });
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage(addr, id);
auto dhtmsg = new FindIntroMessage(id, addr);
dhtmsg->R = 5;
msg->msgs.push_back(dhtmsg);
llarp::LogInfo("askng ", askpeer, " for ", addr.ToString(),
llarp::LogInfo("asking ", askpeer, " for ", addr.ToString(),
" with txid=", id);
router->SendToOrQueue(askpeer, msg);
}
@ -213,7 +268,8 @@ namespace llarp
if(target == ourKey)
{
// we are the target, give them our RC
replies.push_back(new GotRouterMessage(requester, txid, &router->rc));
replies.push_back(
new GotRouterMessage(requester, txid, &router->rc, false));
return;
}
Key_t next;
@ -223,8 +279,8 @@ namespace llarp
if(next == target)
{
// we know it
replies.push_back(
new GotRouterMessage(requester, txid, nodes->nodes[target].rc));
replies.push_back(new GotRouterMessage(
requester, txid, nodes->nodes[target].rc, false));
}
else if(recursive) // are we doing a recursive lookup?
{
@ -234,7 +290,8 @@ namespace llarp
// so we won't ask neighboor recursively, tell them we don't have it
llarp::LogInfo("we aren't closer to ", target, " than ", next,
" so we end it here");
replies.push_back(new GotRouterMessage(requester, txid, nullptr));
replies.push_back(
new GotRouterMessage(requester, txid, nullptr, false));
}
else
{
@ -250,7 +307,8 @@ namespace llarp
llarp::LogInfo("we don't have ", target,
" and this was an iterative request so telling ",
requester, " that we don't have it");
replies.push_back(new GotRouterMessage(requester, txid, nullptr));
replies.push_back(
new GotRouterMessage(requester, txid, nullptr, false));
}
}
else
@ -259,7 +317,8 @@ namespace llarp
llarp::LogInfo("we don't have ", target,
" and have no closer peers so telling ", requester,
" that we don't have it");
replies.push_back(new GotRouterMessage(requester, txid, nullptr));
replies.push_back(
new GotRouterMessage(requester, txid, nullptr, false));
}
}
@ -334,6 +393,14 @@ namespace llarp
{1000, this, &handle_cleaner_timer});
}
void
Context::DHTSendTo(const Key_t &peer, IMessage *msg)
{
auto m = new llarp::DHTImmeidateMessage(peer);
m->msgs.push_back(msg);
router->SendToOrQueue(peer, m);
}
bool
Context::RelayRequestForPath(const llarp::PathID_t &id, const IMessage *msg)
{
@ -351,34 +418,75 @@ namespace llarp
/// handles replying with a GIM for a lookup
struct IntroSetInformJob
{
service::Address target;
uint64_t R = 0;
int m_TriesLeft = 5;
std::set< service::IntroSet > localIntroSets;
Key_t replyNode;
std::set< Key_t > asked;
Key_t whoasked;
uint64_t txid;
llarp_router *m_Router;
IntroSetInformJob(llarp_router *r, const Key_t &replyTo, uint64_t id)
: replyNode(replyTo), txid(id), m_Router(r)
: whoasked(replyTo), txid(id), m_Router(r)
{
}
void
Exausted()
{
auto msg = new llarp::DHTImmeidateMessage(whoasked);
msg->msgs.push_back(new GotIntroMessage({}, txid));
m_Router->SendToOrQueue(whoasked, msg);
}
void
TryAgain()
{
--m_TriesLeft;
llarp::LogInfo("try lookup again");
auto &dht = m_Router->dht->impl;
dht.TryLookupAgain(this,
std::bind(&IntroSetInformJob::OnResult, this,
std::placeholders::_1),
R);
}
bool
OnResult(const std::vector< llarp::service::IntroSet > &results)
{
for(const auto &introset : results)
{
localIntroSets.insert(introset);
localIntroSets.insert(std::move(introset));
}
if(replyNode != m_Router->dht->impl.OurKey())
if(whoasked != m_Router->dht->impl.OurKey())
{
std::vector< service::IntroSet > reply;
for(const auto &introset : localIntroSets)
size_t sz = localIntroSets.size();
if(sz || target.IsZero() || m_TriesLeft == 0)
{
reply.push_back(introset);
std::vector< service::IntroSet > reply;
for(const auto &introset : localIntroSets)
{
reply.push_back(std::move(introset));
}
localIntroSets.clear();
auto msg = new llarp::DHTImmeidateMessage(whoasked);
msg->msgs.push_back(new GotIntroMessage(reply, txid));
m_Router->SendToOrQueue(whoasked, msg);
}
auto msg = new llarp::DHTImmeidateMessage(replyNode);
msg->msgs.push_back(new GotIntroMessage(reply, txid));
m_Router->SendToOrQueue(replyNode, msg);
else if(!target.IsZero())
{
if(m_TriesLeft)
{
TryAgain();
return false;
}
}
}
else
{
llarp::LogWarn("we asked for something without a path?");
}
delete this;
return true;
}
};
@ -397,11 +505,12 @@ namespace llarp
j->localIntroSets = include;
SearchJob job(
whoasked, txid,
std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1));
std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1),
[j]() { delete j; });
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage({}, tag, id);
auto dhtmsg = new FindIntroMessage(tag, id);
dhtmsg->R = R;
msg->msgs.push_back(dhtmsg);
router->SendToOrQueue(askpeer, msg);
@ -420,15 +529,22 @@ namespace llarp
ownerKey.node = askpeer;
ownerKey.txid = id;
IntroSetInformJob *j = new IntroSetInformJob(router, whoasked, txid);
j->target = addr;
for(const auto &item : excludes)
j->asked.emplace(item);
j->R = R;
SearchJob job(
whoasked, txid, addr, excludes,
std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1));
whoasked, txid, addr.ToKey(), {},
std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1),
[j]() { delete j; });
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage({}, addr, id);
auto dhtmsg = new FindIntroMessage(id, addr);
dhtmsg->R = R;
msg->msgs.push_back(dhtmsg);
llarp::LogInfo("asking ", askpeer, " for ", addr.ToString(),
" on request of ", whoasked);
router->SendToOrQueue(askpeer, msg);
}

@ -49,15 +49,7 @@ namespace llarp
dec->msg = new FindRouterMessage(dec->From);
break;
case 'S':
if(dec->relayed)
{
llarp::LogWarn(
"GotRouterMessage found when parsing relayed DHT "
"message");
return false;
}
else
dec->msg = new GotRouterMessage(dec->From);
dec->msg = new GotRouterMessage(dec->From, dec->relayed);
break;
case 'I':
dec->msg = new PublishIntroMessage();

@ -57,9 +57,8 @@ namespace llarp
// message id
if(!BEncodeWriteDictMsgType(buf, "A", "F"))
return false;
if(N.IsZero())
if(N.Empty())
{
return false;
// r5n counter
if(!BEncodeWriteDictInt("R", R, buf))
return false;
@ -103,8 +102,9 @@ namespace llarp
}
Key_t peer;
std::set< Key_t > exclude = {dht.OurKey(), From};
if(N.ToString().empty())
if(N.Empty())
{
llarp::LogInfo("lookup ", S.ToString());
const auto introset = dht.GetIntroSetByServiceAddress(S);
if(introset)
{
@ -114,22 +114,34 @@ namespace llarp
}
else
{
if(R == 0 && !relayed)
if(R == 0)
{
// we are iterative and don't have it, reply with a direct reply
// we don't have it, reply with a direct reply
llarp::LogInfo("dont have intro set and no recursion");
replies.push_back(new GotIntroMessage({}, T));
}
else
{
const auto& us = dht.OurKey();
auto target = S.ToKey();
// we are recursive
if(dht.nodes->FindCloseExcluding(S, peer, exclude))
if(dht.nodes->FindCloseExcluding(target, peer, exclude))
{
if(relayed)
dht.LookupIntroSetForPath(S, T, pathID, peer);
else if(R >= 1)
dht.LookupIntroSet(S, From, T, peer, R - 1);
else
dht.LookupIntroSet(S, From, T, peer, 0);
{
if((us ^ target) < (peer ^ target))
{
// we are not closer than our peer to the target so don't
// revurse
replies.push_back(new GotIntroMessage({}, T));
}
else if(R >= 1)
dht.LookupIntroSet(S, From, T, peer, R - 1, exclude);
else
dht.LookupIntroSet(S, From, T, peer, 0, exclude);
}
}
else
{

@ -45,8 +45,8 @@ namespace llarp
{
if(llarp_rc_verify_sig(&self->router->crypto, &job->result))
{
reply.M.push_back(
new GotRouterMessage(job->target, self->txid, &job->result));
reply.M.push_back(new GotRouterMessage(job->target, self->txid,
&job->result, false));
}
llarp_rc_free(&job->result);
llarp_rc_clear(&job->result);
@ -54,7 +54,7 @@ namespace llarp
else
{
reply.M.push_back(
new GotRouterMessage(job->target, self->txid, nullptr));
new GotRouterMessage(job->target, self->txid, nullptr, false));
}
self->SendReply(&reply);
// TODO: is this okay?
@ -74,7 +74,8 @@ namespace llarp
auto path = dht.router->paths.GetByUpstream(K, pathID);
if(path)
{
replies.push_back(new GotRouterMessage(K, txid, &dht.router->rc));
replies.push_back(
new GotRouterMessage(K, txid, &dht.router->rc, false));
return true;
}
return false;

@ -39,8 +39,11 @@ namespace llarp
auto pending = dht.FindPendingTX(From, T);
if(pending)
{
pending->FoundIntros(I);
dht.RemovePendingLookup(From, T);
if(pending->FoundIntros(I))
{
dht.RemovePendingLookup(From, T);
llarp::LogInfo("removed pending tx from ", From, " txid=", T);
}
return true;
}
else

@ -61,7 +61,15 @@ namespace llarp
GotRouterMessage::HandleMessage(llarp_dht_context *ctx,
std::vector< IMessage * > &replies) const
{
auto &dht = ctx->impl;
auto &dht = ctx->impl;
if(relayed)
{
auto pathset = ctx->impl.router->paths.GetLocalPathSet(pathID);
if(pathset)
{
return pathset->HandleGotRouterMessage(this);
}
}
SearchJob *pending = dht.FindPendingTX(From, txid);
if(pending)
{
@ -71,7 +79,7 @@ namespace llarp
if(pending->requester != dht.OurKey())
{
replies.push_back(new GotRouterMessage(
pending->target, pending->requesterTX, &R[0]));
pending->target, pending->requesterTX, &R[0], false));
}
}
else
@ -101,7 +109,7 @@ namespace llarp
if(pending->requester != dht.OurKey())
{
replies.push_back(new GotRouterMessage(
pending->target, pending->requesterTX, nullptr));
pending->target, pending->requesterTX, nullptr, false));
}
}
}

@ -24,8 +24,9 @@ namespace llarp
SearchJob::SearchJob(const Key_t &asker, uint64_t tx, const Key_t &key,
const std::set< Key_t > &excludes,
IntroSetHookFunc foundIntroset)
IntroSetHookFunc foundIntroset, DoneFunc done)
: foundIntroHook(foundIntroset)
, onDone(done)
, started(llarp_time_now_ms())
, requester(asker)
, requesterTX(tx)
@ -35,8 +36,9 @@ namespace llarp
}
SearchJob::SearchJob(const Key_t &asker, uint64_t tx,
IntroSetHookFunc found)
IntroSetHookFunc found, DoneFunc done)
: foundIntroHook(found)
, onDone(done)
, started(llarp_time_now_ms())
, requester(asker)
, requesterTX(tx)
@ -44,12 +46,16 @@ namespace llarp
target.Zero();
}
void
bool
SearchJob::FoundIntros(
const std::vector< llarp::service::IntroSet > &introsets) const
{
if(foundIntroHook)
foundIntroHook(introsets);
if(foundIntroHook && foundIntroHook(introsets))
{
onDone();
return true;
}
return foundIntroHook == nullptr;
}
void

@ -6,9 +6,9 @@ llarp_link::llarp_link(const llarp_iwp_args& args)
, crypto(args.crypto)
, logic(args.logic)
, worker(args.cryptoworker)
, keyfile(args.keyfile)
, m_name("IWP")
{
strncpy(keyfile, args.keyfile, sizeof(keyfile));
iwp = llarp_async_iwp_new(crypto, logic, worker);
pumpingLogic.store(false);
}
@ -206,15 +206,23 @@ llarp_link::PumpLogic()
void
llarp_link::RemoveSession(llarp_link_session* s)
{
lock_t lock(m_sessions_Mutex);
auto itr = m_sessions.find(s->addr);
if(itr != m_sessions.end())
{
UnmapAddr(s->addr);
s->done();
m_sessions.erase(itr);
delete s;
lock_t lock(m_sessions_Mutex);
auto itr = m_sessions.find(s->addr);
if(itr != m_sessions.end())
{
UnmapAddr(s->addr);
s->done();
m_sessions.erase(itr);
}
}
{
lock_t lock(m_PendingSessions_Mutex);
auto itr = m_PendingSessions.find(s->addr);
if(itr != m_PendingSessions.end())
m_PendingSessions.erase(itr);
}
delete s;
}
uint8_t*
@ -230,7 +238,7 @@ llarp_link::ensure_privkey()
std::error_code ec;
if(!fs::exists(keyfile, ec))
{
if(!keygen(keyfile))
if(!keygen(keyfile.c_str()))
return false;
}
std::ifstream f(keyfile);

@ -1,9 +1,9 @@
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include <llarp/iwp.h>
#include <algorithm>
#include <llarp/crypto.hpp>
#include <llarp/iwp.hpp>
#include <llarp/iwp/server.hpp>
#include <llarp/iwp/session.hpp>
#include "address_info.hpp"

@ -23,7 +23,7 @@ namespace llarp
}
}
template < typename T, size_t align = 8 >
template < typename T, size_t align = 128 >
void
DumpBuffer(const T &buff)
{

@ -132,7 +132,7 @@ struct llarp_nodedb
llarp_rc entry;
llarp::Zero(&entry, sizeof(entry));
llarp_rc_copy(&entry, rc);
entries[pk] = entry;
entries.insert(std::make_pair(pk, entry));
if(llarp_rc_bencode(&entry, &buf))
{
@ -273,8 +273,9 @@ disk_threadworker_setRC(void *user)
llarp_async_verify_rc *verify_request =
static_cast< llarp_async_verify_rc * >(user);
verify_request->valid = verify_request->nodedb->setRC(&verify_request->rc);
llarp_logic_queue_job(verify_request->logic,
{verify_request, &logic_threadworker_callback});
if(verify_request->logic)
llarp_logic_queue_job(verify_request->logic,
{verify_request, &logic_threadworker_callback});
}
// we run the crypto verify in the crypto threadpool worker

@ -263,6 +263,29 @@ namespace llarp
builder->Tick(now, m_Router);
}
routing::IMessageHandler*
PathContext::GetHandler(const PathID_t& id)
{
routing::IMessageHandler* h = nullptr;
auto pathset = GetLocalPathSet(id);
if(pathset)
{
h = pathset->GetPathByID(id);
}
if(h)
return h;
RouterID us(OurRouterID());
auto& map = m_TransitPaths;
std::unique_lock< std::mutex > lock(map.first);
auto range = map.second.equal_range(id);
for(auto i = range.first; i != range.second; ++i)
{
if(i->second->info.upstream == us)
return i->second;
}
return nullptr;
}
void
PathContext::AddPathBuilder(llarp_pathbuilder_context* ctx)
{
@ -366,7 +389,10 @@ namespace llarp
msg->X = buf;
msg->Y = Y;
msg->pathid = TXID();
return r->SendToOrQueue(Upstream(), msg);
if(r->SendToOrQueue(Upstream(), msg))
return true;
llarp::LogError("send to ", Upstream(), " failed");
return false;
}
bool
@ -411,7 +437,11 @@ namespace llarp
byte_t tmp[MAX_LINK_MSG_SIZE / 2];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!msg->BEncode(&buf))
{
llarp::LogError("Bencode failed");
llarp::DumpBuffer(buf);
return false;
}
// make nonce
TunnelNonce N;
N.Randomize();

@ -81,6 +81,19 @@ namespace llarp
return nullptr;
}
Path*
PathSet::GetPathByID(const PathID_t& id) const
{
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
{
if(itr->second->RXID() == id)
return itr->second;
++itr;
}
return nullptr;
}
size_t
PathSet::NumInStatus(PathStatus st) const
{

@ -9,13 +9,6 @@ namespace llarp
{
}
bool
PoW::BDecode(llarp_buffer_t* buf)
{
// TODO: implement me
return false;
}
bool
PoW::DecodeKey(llarp_buffer_t k, llarp_buffer_t* val)
{
@ -27,7 +20,9 @@ namespace llarp
PoW::BEncode(llarp_buffer_t* buf) const
{
// TODO: implement me
return false;
if(!bencode_start_dict(buf))
return false;
return bencode_end(buf);
}
bool

@ -1,6 +1,6 @@
#include "router.hpp"
#include <llarp/iwp.h>
#include <llarp/proto.h>
#include <llarp/iwp.hpp>
#include <llarp/link_message.hpp>
#include "llarp/iwp/establish_job.hpp"
#include "llarp/iwp/server.hpp"
@ -745,10 +745,10 @@ llarp_router::InitOutboundLink()
return true;
llarp_iwp_args args = {
&crypto, logic, tp, this, transport_keyfile.string().c_str(),
&crypto, logic, tp, this, transport_keyfile.string(),
};
auto link = new(std::nothrow) llarp_link(args);
auto link = new llarp_link(args);
auto afs = {AF_INET, AF_INET6};
@ -1093,6 +1093,7 @@ namespace llarp
const char *key, const char *val)
{
llarp_router *self = static_cast< llarp_router * >(iter->user);
int af;
uint16_t proto;
if(StrEq(val, "eth"))
@ -1117,17 +1118,15 @@ namespace llarp
{
if(!StrEq(key, "*"))
{
llarp::LogInfo("interface specific binding activated");
llarp_iwp_args args = {
&self->crypto,
self->logic,
self->tp,
self,
self->transport_keyfile.string().c_str(),
self->transport_keyfile.string(),
};
link = new(std::nothrow) llarp_link(args);
llarp::LogInfo("interface specific binding activated");
link = new llarp_link(args);
if(link)
{

@ -161,7 +161,6 @@ namespace llarp
bool
Identity::BEncode(llarp_buffer_t* buf) const
{
/// TODO: implement me
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictEntry("e", enckey, buf))
@ -195,10 +194,8 @@ namespace llarp
{
crypto->encryption_keygen(enckey);
crypto->identity_keygen(signkey);
pub.enckey = llarp::seckey_topublic(enckey);
pub.signkey = llarp::seckey_topublic(signkey);
pub.vanity.Zero();
pub.UpdateAddr();
pub.Update(llarp::seckey_topublic(enckey),
llarp::seckey_topublic(signkey));
}
bool
@ -273,7 +270,7 @@ namespace llarp
// rewind and resize buffer
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
return crypto->verify(A.signkey, buf, Z);
return A.Verify(crypto, buf, Z);
}
bool

@ -68,7 +68,6 @@ namespace llarp
{
if(context)
{
llarp::LogInfo("BEEP");
byte_t tmp[128] = {0};
memcpy(tmp, "BEEP", 4);
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
@ -441,7 +440,7 @@ namespace llarp
Endpoint::CachedTagResult::BuildRequestMessage()
{
llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage();
msg->M.push_back(new llarp::dht::FindIntroMessage({}, tag, txid));
msg->M.push_back(new llarp::dht::FindIntroMessage(tag, txid));
lastRequest = llarp_time_now_ms();
parent->PutLookup(this, txid);
return msg;
@ -450,7 +449,7 @@ namespace llarp
bool
Endpoint::PublishIntroSet(llarp_router* r)
{
auto path = GetEstablishedPathClosestTo(m_Identity.pub.Addr());
auto path = GetEstablishedPathClosestTo(m_Identity.pub.Addr().ToRouter());
if(path)
{
m_CurrentPublishTX = llarp_randint();
@ -496,12 +495,13 @@ namespace llarp
struct HiddenServiceAddressLookup : public IServiceLookup
{
Address remote;
Endpoint* endpoint;
typedef std::function< bool(const IntroSet*) > HandlerFunc;
HandlerFunc handle;
HiddenServiceAddressLookup(Endpoint* p, const Address& addr, uint64_t tx)
: IServiceLookup(p, tx), remote(addr), endpoint(p)
HiddenServiceAddressLookup(Endpoint* p, HandlerFunc h,
const Address& addr, uint64_t tx)
: IServiceLookup(p, tx), remote(addr), handle(h)
{
llarp::LogInfo("New hidden service lookup for ", addr.ToString());
}
bool
@ -512,12 +512,13 @@ namespace llarp
{
llarp::LogInfo("hidden service lookup for ", remote.ToString(),
" success");
endpoint->PutNewOutboundContext(*results.begin());
handle(&*results.begin());
}
else
{
llarp::LogInfo("no response in hidden service lookup for ",
remote.ToString());
handle(nullptr);
}
delete this;
return true;
@ -527,7 +528,10 @@ namespace llarp
BuildRequestMessage()
{
llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage();
msg->M.push_back(new llarp::dht::FindIntroMessage(remote, txid));
auto FIM = new llarp::dht::FindIntroMessage(txid, remote);
FIM->R = 5;
msg->M.push_back(FIM);
llarp::LogInfo("build request for ", remote);
return msg;
}
};
@ -543,7 +547,7 @@ namespace llarp
Endpoint::PutNewOutboundContext(const llarp::service::IntroSet& introset)
{
Address addr;
introset.A.CalculateAddress(addr);
introset.A.CalculateAddress(addr.data());
// only add new session if it's not there
if(m_RemoteSessions.find(addr) == m_RemoteSessions.end())
@ -562,6 +566,55 @@ namespace llarp
}
}
bool
Endpoint::HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg)
{
bool success = false;
if(msg->R.size() == 1)
{
auto itr = m_PendingRouters.find(msg->R[0].pubkey);
if(itr == m_PendingRouters.end())
return false;
llarp_async_verify_rc* job = new llarp_async_verify_rc;
job->nodedb = m_Router->nodedb;
job->cryptoworker = m_Router->tp;
job->diskworker = m_Router->disk;
job->logic = nullptr;
job->hook = nullptr;
llarp_rc_clear(&job->rc);
llarp_rc_copy(&job->rc, &msg->R[0]);
llarp_nodedb_async_verify(job);
return true;
}
return success;
}
void
Endpoint::EnsureRouterIsKnown(const RouterID& router)
{
if(!llarp_nodedb_get_rc(m_Router->nodedb, router))
{
if(m_PendingRouters.find(router) == m_PendingRouters.end())
{
auto path = GetEstablishedPathClosestTo(router);
routing::DHTMessage msg;
auto txid = GenTXID();
msg.M.push_back(
new dht::FindRouterMessage({}, dht::Key_t(router), txid));
if(path->SendRoutingMessage(&msg, m_Router))
{
llarp::LogInfo(Name(), " looking up ", router);
m_PendingRouters.insert(std::make_pair(router, txid));
}
else
{
llarp::LogError("failed to send request for router lookup");
}
}
}
}
void
Endpoint::HandlePathBuilt(path::Path* p)
{
@ -597,11 +650,20 @@ namespace llarp
return m_Parent->HandleHiddenServiceFrame(frame);
}
bool
Endpoint::OnOutboundLookup(const IntroSet* introset)
{
if(!introset)
return false;
PutNewOutboundContext(*introset);
return true;
}
bool
Endpoint::EnsurePathToService(const Address& remote, PathEnsureHook hook,
llarp_time_t timeoutMS)
{
auto path = GetEstablishedPathClosestTo(remote);
auto path = GetEstablishedPathClosestTo(remote.ToRouter());
if(!path)
{
llarp::LogWarn("No outbound path for lookup yet");
@ -627,10 +689,15 @@ namespace llarp
m_PendingServiceLookups.insert(std::make_pair(remote, hook));
HiddenServiceAddressLookup* job =
new HiddenServiceAddressLookup(this, remote, GenTXID());
HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup(
this,
std::bind(&Endpoint::OnOutboundLookup, this, std::placeholders::_1),
remote, GenTXID());
return job->SendRequestViaPath(path, Router());
if(job->SendRequestViaPath(path, Router()))
return true;
llarp::LogError("send via path failed");
return false;
}
Endpoint::OutboundContext::OutboundContext(const IntroSet& intro,
@ -649,51 +716,27 @@ namespace llarp
{
}
void
Endpoint::OutboundContext::ShiftIntroduction()
bool
Endpoint::OutboundContext::OnIntroSetUpdate(const IntroSet* i)
{
for(const auto& intro : currentIntroSet.I)
if(i && i->IsNewerThan(currentIntroSet))
{
if(intro.expiresAt > selectedIntro.expiresAt)
{
selectedIntro = intro;
}
currentIntroSet = *i;
}
return true;
}
bool
Endpoint::OutboundContext::HandleGotIntroMessage(
const llarp::dht::GotIntroMessage* msg)
void
Endpoint::OutboundContext::ShiftIntroduction()
{
if(msg->T != m_UpdateIntrosetTX)
{
llarp::LogError("unwarrented introset message txid=", msg->T);
return false;
}
auto crypto = m_Parent->Crypto();
if(msg->I.size() == 1)
for(const auto& intro : currentIntroSet.I)
{
// found intro set
const auto& introset = msg->I[0];
if(introset.VerifySignature(crypto) && currentIntroSet.A == introset.A)
{
// update
currentIntroSet = introset;
// reset tx
m_UpdateIntrosetTX = 0;
// shift to newest intro
// TODO: check timestamp on introset to make sure it's new enough
ShiftIntroduction();
return true;
}
else
m_Parent->EnsureRouterIsKnown(selectedIntro.router);
if(intro.expiresAt > selectedIntro.expiresAt)
{
llarp::LogError("Signature Error for intro set ", introset);
return false;
selectedIntro = intro;
}
}
llarp::LogError("Bad number of intro sets in response");
return false;
}
void
@ -761,7 +804,8 @@ namespace llarp
// set our introduction
self->msg.introReply = self->intro;
// derive session key
self->crypto->dh_server(self->sharedKey, self->remote.enckey,
self->crypto->dh_server(self->sharedKey,
self->remote.EncryptionPublicKey(),
self->m_LocalIdentity->enckey, self->frame.N);
// encrypt and sign
@ -827,17 +871,18 @@ namespace llarp
void
Endpoint::OutboundContext::UpdateIntroSet()
{
auto path = GetEstablishedPathClosestTo(currentIntroSet.A.Addr());
auto addr = currentIntroSet.A.Addr();
auto path = m_Parent->GetEstablishedPathClosestTo(addr.ToRouter());
if(path)
{
if(m_UpdateIntrosetTX == 0)
{
m_UpdateIntrosetTX = llarp_randint();
routing::DHTMessage msg;
msg.M.push_back(new llarp::dht::FindIntroMessage(
currentIntroSet.A.Addr(), m_UpdateIntrosetTX));
path->SendRoutingMessage(&msg, m_Parent->Router());
}
HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup(
m_Parent,
std::bind(&Endpoint::OutboundContext::OnIntroSetUpdate, this,
std::placeholders::_1),
addr, m_Parent->GenTXID());
if(!job->SendRequestViaPath(path, m_Parent->Router()))
llarp::LogError("send via path failed");
}
else
{
@ -924,7 +969,8 @@ namespace llarp
msg.sender = m_Parent->m_Identity.pub;
msg.PutBuffer(payload);
if(!f.EncryptAndSign(crypto, &msg, shared, currentIntroSet.A.signkey))
if(!f.EncryptAndSign(crypto, &msg, shared,
m_Parent->m_Identity.signkey))
{
llarp::LogError("failed to sign");
return;

@ -6,16 +6,6 @@ namespace llarp
{
namespace service
{
ServiceInfo::ServiceInfo()
{
vanity.Zero();
m_CachedAddr.Zero();
}
ServiceInfo::~ServiceInfo()
{
}
bool
ServiceInfo::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val)
{
@ -56,7 +46,7 @@ namespace llarp
if(m_CachedAddr.IsZero())
{
Address addr;
CalculateAddress(addr);
CalculateAddress(addr.data());
return addr.ToString();
}
return m_CachedAddr.ToString();
@ -65,9 +55,10 @@ namespace llarp
bool
ServiceInfo::CalculateAddress(byte_t* addr) const
{
byte_t tmp[128];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
assert(BEncode(&buf));
byte_t tmp[256] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!BEncode(&buf))
return false;
return crypto_generichash(addr, 32, buf.base, buf.cur - buf.base, nullptr,
0)
!= -1;
@ -76,7 +67,7 @@ namespace llarp
bool
ServiceInfo::UpdateAddr()
{
return CalculateAddress(m_CachedAddr);
return CalculateAddress(m_CachedAddr.data());
}
} // namespace service

@ -94,8 +94,6 @@ namespace llarp
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "H"))
return false;
if(!BEncodeWriteDictEntry("D", D, buf))
return false;
if(S == 0)
@ -261,7 +259,7 @@ namespace llarp
llarp::LogError("No sender for T=", T);
return false;
}
if(!Verify(crypto, si.signkey))
if(!Verify(crypto, si))
{
llarp::LogError("Signature failure");
return false;
@ -289,7 +287,7 @@ namespace llarp
}
bool
ProtocolFrame::Verify(llarp_crypto* crypto, byte_t* signkey) const
ProtocolFrame::Verify(llarp_crypto* crypto, const ServiceInfo& from) const
{
ProtocolFrame copy(*this);
// save signature
@ -305,7 +303,7 @@ namespace llarp
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// verify
result = crypto->verify(Z, buf, signkey);
result = from.Verify(crypto, buf, Z);
}
// restore signature
return result;

@ -21,7 +21,7 @@ struct HiddenServiceTest : public ::testing::Test
SetUp()
{
ident.RegenerateKeys(Crypto());
ident.pub.vanity.Randomize();
ident.pub.RandomizeVanity();
ident.pub.UpdateAddr();
}
};
@ -29,7 +29,7 @@ struct HiddenServiceTest : public ::testing::Test
TEST_F(HiddenServiceTest, TestGenerateIntroSet)
{
llarp::service::Address addr;
ASSERT_TRUE(ident.pub.CalculateAddress(addr));
ASSERT_TRUE(ident.pub.CalculateAddress(addr.data()));
llarp::service::IntroSet I;
while(I.I.size() < 10)
{

Loading…
Cancel
Save