Merge pull request #388 from majestrate/staging

[breaking protocol change] handle case with no convotags from new session
This commit is contained in:
Jeff 2019-03-08 11:02:27 -05:00 committed by GitHub
commit 916b47c1c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 115 additions and 23 deletions

View File

@ -230,12 +230,12 @@ namespace llarp
{
if(state == eClose)
return true;
if(now < lastActive)
if(now <= lastActive)
return false;
auto dlt = now - lastActive;
if(dlt >= sessionTimeout)
{
LogInfo("session timeout reached for ", remoteAddr);
LogInfo("session timeout reached for ", remoteAddr, " dlt=", dlt);
return true;
}
return false;

View File

@ -293,7 +293,7 @@ namespace llarp
{
auto path = r->pathContext().GetPathForTransfer(msg->P);
llarp::routing::DataDiscardMessage discarded(msg->P, msg->S);
if(!path)
if(path == nullptr || msg->T.F != info.txID)
{
return SendRoutingMessage(&discarded, r);
}

View File

@ -978,12 +978,43 @@ namespace llarp
return false;
}
void
Endpoint::RemoveConvoTag(const ConvoTag& t)
{
m_Sessions.erase(t);
}
bool
Endpoint::HandleHiddenServiceFrame(path::Path* p,
const ProtocolFrame* frame)
{
return frame->AsyncDecryptAndVerify(EndpointLogic(), Crypto(), p->RXID(),
Worker(), m_Identity, m_DataHandler);
if(frame->R)
{
// handle discard
ServiceInfo si;
if(!GetSenderFor(frame->T, si))
return false;
// verify source
if(!frame->Verify(Crypto(), si))
return false;
// remove convotag it doesn't exist
RemoveConvoTag(frame->T);
return true;
}
if(!frame->AsyncDecryptAndVerify(EndpointLogic(), Crypto(), p->RXID(),
Worker(), m_Identity, m_DataHandler))
{
// send discard
ProtocolFrame f;
f.R = 1;
f.T = frame->T;
f.F = p->intro.pathID;
if(!f.Sign(Crypto(), m_Identity))
return false;
const routing::PathTransferMessage d(f, frame->F);
return p->SendRoutingMessage(&d, router);
}
return true;
}
Endpoint::SendContext::SendContext(const ServiceInfo& ident,
@ -1298,16 +1329,17 @@ namespace llarp
{
// TODO: check expiration of our end
ProtocolMessage m(f.T);
m.proto = t;
m.introReply = p->intro;
PutReplyIntroFor(f.T, m.introReply);
m.sender = m_Identity.pub;
m.PutBuffer(data);
f.N.Randomize();
f.S = GetSeqNoForConvo(f.T);
f.C.Zero();
transfer.Y.Randomize();
transfer.P = remoteIntro.pathID;
m.proto = t;
m.introReply = p->intro;
m.sender = m_Identity.pub;
f.F = m.introReply.pathID;
f.S = GetSeqNoForConvo(f.T);
transfer.P = remoteIntro.pathID;
if(!f.EncryptAndSign(Router()->crypto(), m, K, m_Identity))
{
llarp::LogError("failed to encrypt and sign");
@ -1826,6 +1858,14 @@ namespace llarp
{
if(markedBad)
return false;
if(path::Builder::ShouldBuildMore(now))
return true;
return !ReadyToSend();
}
bool
Endpoint::ShouldBuildMore(llarp_time_t now) const
{
bool should = path::Builder::ShouldBuildMore(now);
// determine newest intro
Introduction intro;
@ -1875,17 +1915,14 @@ namespace llarp
if(m_DataHandler->GetCachedSessionKeyFor(f.T, shared))
{
ProtocolMessage m;
m.proto = t;
if(!m_DataHandler->GetReplyIntroFor(f.T, m.introReply))
{
m_DataHandler->PutReplyIntroFor(f.T, path->intro);
m.introReply = path->intro;
}
m_DataHandler->PutIntroFor(f.T, remoteIntro);
m.sender = m_Endpoint->m_Identity.pub;
m_DataHandler->PutReplyIntroFor(f.T, path->intro);
m.proto = t;
m.introReply = path->intro;
f.F = m.introReply.pathID;
m.sender = m_Endpoint->m_Identity.pub;
m.tag = f.T;
m.PutBuffer(payload);
m.tag = f.T;
if(!f.EncryptAndSign(crypto, m, shared, m_Endpoint->m_Identity))
{
llarp::LogError("failed to sign");

View File

@ -261,6 +261,9 @@ namespace llarp
static void
HandlePathDead(void*);
bool
ShouldBuildMore(llarp_time_t now) const override;
/// context needed to initiate an outbound hidden service session
struct OutboundContext : public path::Builder, public SendContext
{
@ -390,6 +393,9 @@ namespace llarp
bool
GetIntroFor(const ConvoTag& remote, Introduction& intro) const override;
void
RemoveConvoTag(const ConvoTag& remote) override;
void
PutReplyIntroFor(const ConvoTag& remote,
const Introduction& intro) override;

View File

@ -25,6 +25,9 @@ namespace llarp
PutCachedSessionKeyFor(const ConvoTag& remote,
const SharedSecret& secret) = 0;
virtual void
RemoveConvoTag(const ConvoTag& remote) = 0;
virtual void
PutSenderFor(const ConvoTag& remote, const ServiceInfo& si) = 0;

View File

@ -105,11 +105,23 @@ namespace llarp
if(!BEncodeWriteDictEntry("C", C, buf))
return false;
}
if(!BEncodeWriteDictEntry("D", D, buf))
return false;
if(!BEncodeWriteDictEntry("N", N, buf))
if(D.size() > 0)
{
if(!BEncodeWriteDictEntry("D", D, buf))
return false;
}
if(!BEncodeWriteDictEntry("F", F, buf))
return false;
if(!N.IsZero())
{
if(!BEncodeWriteDictEntry("N", N, buf))
return false;
}
if(R)
{
if(!BEncodeWriteDictInt("R", R, buf))
return false;
}
if(!T.IsZero())
{
if(!BEncodeWriteDictEntry("T", T, buf))
@ -137,12 +149,16 @@ namespace llarp
}
if(!BEncodeMaybeReadDictEntry("D", D, read, key, val))
return false;
if(!BEncodeMaybeReadDictEntry("F", F, read, key, val))
return false;
if(!BEncodeMaybeReadDictEntry("C", C, read, key, val))
return false;
if(!BEncodeMaybeReadDictEntry("N", N, read, key, val))
return false;
if(!BEncodeMaybeReadDictInt("S", S, read, key, val))
return false;
if(!BEncodeMaybeReadDictInt("R", R, read, key, val))
return false;
if(!BEncodeMaybeReadDictEntry("T", T, read, key, val))
return false;
if(!BEncodeMaybeReadVersion("V", version, LLARP_PROTO_VERSION, read, key,
@ -164,6 +180,25 @@ namespace llarp
return msg.BDecode(buf);
}
bool
ProtocolFrame::Sign(llarp::Crypto* crypto, const Identity& localIdent)
{
Z.Zero();
std::array< byte_t, MAX_PROTOCOL_MESSAGE_SIZE > tmp;
llarp_buffer_t buf(tmp);
// encode
if(!BEncode(&buf))
{
llarp::LogError("message too big to encode");
return false;
}
// rewind
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// sign
return localIdent.Sign(crypto, Z, buf);
}
bool
ProtocolFrame::EncryptAndSign(llarp::Crypto* crypto,
const ProtocolMessage& msg,
@ -304,9 +339,11 @@ namespace llarp
{
C = other.C;
D = other.D;
F = other.F;
N = other.N;
Z = other.Z;
T = other.T;
R = other.R;
S = other.S;
version = other.version;
return *this;

View File

@ -65,16 +65,20 @@ namespace llarp
using Encrypted_t = Encrypted< 2048 >;
PQCipherBlock C;
Encrypted_t D;
uint64_t R;
KeyExchangeNonce N;
Signature Z;
PathID_t F;
service::ConvoTag T;
ProtocolFrame(const ProtocolFrame& other)
: routing::IMessage()
, C(other.C)
, D(other.D)
, R(other.R)
, N(other.N)
, Z(other.Z)
, F(other.F)
, T(other.T)
{
S = other.S;
@ -104,6 +108,9 @@ namespace llarp
EncryptAndSign(Crypto* c, const ProtocolMessage& msg,
const SharedSecret& sharedkey, const Identity& localIdent);
bool
Sign(Crypto* c, const Identity& localIdent);
bool
AsyncDecryptAndVerify(Logic* logic, Crypto* c, const PathID_t& srcpath,
llarp_threadpool* worker,
@ -125,9 +132,11 @@ namespace llarp
{
C.Zero();
D.Clear();
F.Zero();
T.Zero();
N.Zero();
Z.Zero();
R = 0;
}
bool