exit authentication (initial)

pull/1306/head
Jeff Becker 4 years ago
parent be01808a6b
commit 61c5808765
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -0,0 +1,58 @@
#include "endpoint_rpc.hpp"
#include <service/endpoint.hpp>
namespace llarp::rpc
{
EndpointAuthRPC::EndpointAuthRPC(
std::string url, std::string method, LMQ_ptr lmq, Endpoint_ptr endpoint)
: m_URL(std::move(url))
, m_Method(std::move(method))
, m_LMQ(std::move(lmq))
, m_Endpoint(std::move(endpoint))
{
}
void
EndpointAuthRPC::Start()
{
m_LMQ->connect_remote(
m_URL,
[self = shared_from_this()](lokimq::ConnectionID c) {
self->m_Conn = std::move(c);
LogInfo("connected to endpoint auth server via ", c);
},
[self = shared_from_this()](lokimq::ConnectionID, std::string_view fail) {
LogWarn("failed to connect to endpoint auth server: ", fail);
self->m_Endpoint->RouterLogic()->call_later(1s, [self]() { self->Start(); });
});
}
void
EndpointAuthRPC::AuthenticateAsync(
llarp::service::Address from, std::function<void(service::AuthResult)> hook)
{
if (not m_Conn.has_value())
{
m_Endpoint->RouterLogic()->Call([hook]() { hook(service::AuthResult::eAuthFailed); });
return;
}
// call method with 1 parameter: the loki address of the remote
m_LMQ->send(
*m_Conn,
m_AuthMethod,
[self = shared_from_this(), hook](bool success, std::vector<std::string> data) {
service::AuthResult result = service::AuthResult::eAuthFailed;
if (success and not data.empty())
{
const auto maybe = service::ParseAuthResult(data[0]);
if (maybe.has_value())
{
result = *maybe;
}
}
self->m_Endpoint->RouterLogic()->Call([hook, result]() { hook(result); });
},
from.ToString());
} // namespace llarp::rpc
} // namespace llarp::rpc

@ -0,0 +1,35 @@
#pragma once
#include <service/auth.hpp>
namespace llarp::service
{
struct Endpoint;
}
namespace llarp::rpc
{
struct EndpointAuthRPC : public llarp::service::IAuthPolicy,
public std::enable_shared_from_this<EndpointAuthRPC>
{
using LMQ_ptr = std::shared_ptr<lokimq::LokiMQ>;
using Endpoint_ptr = std::shared_ptr<llarp::service::Endpoint>;
explicit EndpointAuthRPC(
std::string url, std::string method, LMQ_ptr lmq, Endpoint_ptr endpoint);
~EndpointAuthRPC() = default;
void
AuthenticateAsync(
llarp::service::Address from,
service::ConvoTag tag,
std::function<void(service::AuthResult)> hook) override;
private:
const std::string m_AuthURL;
const std::string m_AuthMethod;
LMQ_ptr m_LMQ;
Endpoint_ptr m_Endpoint;
std::optional<lokimq::ConnectionID> m_Conn;
};
} // namespace llarp::rpc

@ -0,0 +1,20 @@
#include "auth.hpp"
#include <unordered_map>
namespace llarp::service
{
/// maybe get auth result from string
std::optional<AuthResult>
ParseAuthResult(std::string data)
{
static thread_local std::unordered_map<std::string, AuthResult> values = {
{"OKAY", AuthResult::eAuthAccepted},
{"REJECT", AuthResult::eAuthRejected},
{"PAYME", AuthResult::eAuthPaymentRequired},
{"LIMITED", AuthResult::eAuthRateLimit}};
auto itr = values.find(data);
if (itr == values.end())
return std::nullopt;
return itr->second;
}
} // namespace llarp::service

@ -0,0 +1,39 @@
#pragma once
#include <optional>
#include <string>
#include <funcional>
#include "address.hpp"
#include "handler.hpp"
namespace llarp::service
{
/// authentication status
enum class AuthResult
{
/// explicitly accepted
eAuthAccepted,
/// explicitly rejected
eAuthRejected,
/// attempt failed
eAuthFailed,
/// attempt rate limited
eAuthRateLimit,
/// need mo munny
eAuthPaymentRequired
};
/// maybe get auth result from string
std::optional<AuthResult>
ParseAuthResult(std::string data);
struct IAuthPolicy
{
~IAuthPolicy() = default;
/// asynchronously determine if we accept new convotag from remote service, call hook with
/// result later
virtual void
AuthenticateAsync(
service::Address from, service::ConvoTag tag, std::function<void(AuthResult)> hook) = 0;
};
} // namespace llarp::service

@ -853,6 +853,19 @@ namespace llarp
return false;
}
void
Endpoint::AsyncAuthConvoTag(Address addr, ConvoTag tag, std::function<void(AuthStatus)> hook)
{
if (m_AuthPolicy)
{
m_AuthPolicy->AuthenticateAsync(std::move(addr), std::move(tag), std::move(hook));
}
else
{
RouterLogic()->Call([hook]() { hook(AuthStatus::eAuthSuccess); });
}
}
void
Endpoint::RemoveConvoTag(const ConvoTag& t)
{
@ -876,8 +889,7 @@ namespace llarp
RemoveConvoTag(frame.T);
return true;
}
if (!frame.AsyncDecryptAndVerify(
EndpointLogic(), p, CryptoWorker(), m_Identity, m_DataHandler))
if (!frame.AsyncDecryptAndVerify(EndpointLogic(), p, CryptoWorker(), m_Identity, this))
{
// send discard
ProtocolFrame f;

@ -20,6 +20,8 @@
#include <util/compare_ptr.hpp>
#include <util/thread/logic.hpp>
#include "auth.hpp"
// minimum time between introset shifts
#ifndef MIN_SHIFT_INTERVAL
#define MIN_SHIFT_INTERVAL 5s
@ -177,6 +179,9 @@ namespace llarp
bool
HandleHiddenServiceFrame(path::Path_ptr p, const service::ProtocolFrame& msg);
void
SetEndpointAuth(std::shared_ptr<IAuthPolicy> policy);
// virtual huint128_t
// ObtainIPForAddr(const AlignedBuffer< 32 >& addr, bool serviceNode) = 0;
@ -353,6 +358,12 @@ namespace llarp
virtual void
IntroSetPublished();
void
AsyncAuthConvoTag(Address addr, ConvoTag tag, std::function<void(AuthStatus)> hook);
void
SendAuthReject(path::Path_ptr path, PathID_t replyPath, ConvoTag tag, AuthStatus st);
uint64_t
GenTXID();
@ -446,6 +457,7 @@ namespace llarp
ConvoMap& Sessions();
// clang-format on
thread::Queue<RecvDataEvent> m_RecvQueue;
std::shared_ptr<IAuthPolicy> m_AuthPolicy;
};
using Endpoint_ptr = std::shared_ptr<Endpoint>;

@ -16,8 +16,7 @@ namespace llarp
if (conf.m_keyfile.has_value())
m_Keyfile = conf.m_keyfile->string();
m_SnodeBlacklist = conf.m_snodeBlacklist;
m_ExitEnabled = conf.m_AllowExit;
m_ExitNode = conf.m_exitNode;
// TODO:
/*
if (k == "on-up")

@ -245,14 +245,14 @@ namespace llarp
std::shared_ptr<Logic> logic;
std::shared_ptr<ProtocolMessage> msg;
const Identity& m_LocalIdentity;
IDataHandler* handler;
Endpoint* handler;
const ProtocolFrame frame;
const Introduction fromIntro;
AsyncFrameDecrypt(
std::shared_ptr<Logic> l,
const Identity& localIdent,
IDataHandler* h,
Endpoint* h,
std::shared_ptr<ProtocolMessage> m,
const ProtocolFrame& f,
const Introduction& recvIntro)
@ -266,9 +266,8 @@ namespace llarp
}
static void
Work(void* user)
Work(std::shared_ptr<AsyncFrameDecrypt> self)
{
auto* self = static_cast<AsyncFrameDecrypt*>(user);
auto crypto = CryptoManager::instance();
SharedSecret K;
SharedSecret sharedKey;
@ -278,7 +277,6 @@ namespace llarp
{
LogError("pqke failed C=", self->frame.C);
self->msg.reset();
delete self;
return;
}
// decrypt
@ -289,7 +287,6 @@ namespace llarp
LogError("failed to decode inner protocol message");
DumpBuffer(*buf);
self->msg.reset();
delete self;
return;
}
// verify signature of outer message after we parsed the inner message
@ -303,7 +300,6 @@ namespace llarp
Dump<MAX_PROTOCOL_MESSAGE_SIZE>(self->frame);
Dump<MAX_PROTOCOL_MESSAGE_SIZE>(*self->msg);
self->msg.reset();
delete self;
return;
}
@ -312,7 +308,6 @@ namespace llarp
LogError("dropping duplicate convo tag T=", self->msg->tag);
// TODO: send convotag reset
self->msg.reset();
delete self;
return;
}
@ -326,7 +321,6 @@ namespace llarp
LogError("x25519 key exchange failed");
Dump<MAX_PROTOCOL_MESSAGE_SIZE>(self->frame);
self->msg.reset();
delete self;
return;
}
std::array<byte_t, 64> tmp;
@ -336,17 +330,29 @@ namespace llarp
std::copy(sharedSecret.begin(), sharedSecret.end(), tmp.begin() + 32);
crypto->shorthash(sharedKey, llarp_buffer_t(tmp));
self->handler->PutIntroFor(self->msg->tag, self->msg->introReply);
self->handler->PutReplyIntroFor(self->msg->tag, self->fromIntro);
self->handler->PutSenderFor(self->msg->tag, self->msg->sender, true);
self->handler->PutCachedSessionKeyFor(self->msg->tag, sharedKey);
self->msg->handler = self->handler;
std::shared_ptr<ProtocolMessage> msg = std::move(self->msg);
path::Path_ptr path = std::move(self->path);
const PathID_t from = self->frame.F;
LogicCall(self->logic, [=]() { ProtocolMessage::ProcessAsync(path, from, msg); });
delete self;
msg->handler = self->handler;
self->handler->AsyncAuthConvoTag(
msg->sender,
msg->tag,
[path, msg, from, handler = self->handler, fromIntro = self->fromIntro, sharedKey](
AuthStatus st) {
if (st == AuthStatus::eAuthSuccess)
{
handler->PutIntroFor(msg->tag, msg->introReply);
handler->PutReplyIntroFor(msg->tag, fromIntro);
handler->PutSenderFor(msg->tag, msg->sender, true);
handler->PutCachedSessionKeyFor(msg->tag, sharedKey);
ProtocolMessage::ProcessAsync(path, from, msg);
}
else
{
handler->SendAuthReject(path, from, msg->tag, st);
}
});
}
};
@ -378,7 +384,7 @@ namespace llarp
path::Path_ptr recvPath,
const std::shared_ptr<llarp::thread::ThreadPool>& worker,
const Identity& localIdent,
IDataHandler* handler) const
Endpoint* handler) const
{
auto msg = std::make_shared<ProtocolMessage>();
msg->handler = handler;
@ -386,25 +392,24 @@ namespace llarp
{
LogInfo("Got protocol frame with new convo");
// we need to dh
auto dh = new AsyncFrameDecrypt(logic, localIdent, handler, msg, *this, recvPath->intro);
auto dh = std::make_shared<AsyncFrameDecrypt>(
logic, localIdent, handler, msg, *this, recvPath->intro);
dh->path = recvPath;
worker->addJob(std::bind(&AsyncFrameDecrypt::Work, dh));
return true;
}
auto v = new AsyncDecrypt();
auto v = std::make_shared<AsyncDecrypt>();
if (!handler->GetCachedSessionKeyFor(T, v->shared))
{
LogError("No cached session for T=", T);
delete v;
return false;
return true;
}
if (!handler->GetSenderFor(T, v->si))
{
LogError("No sender for T=", T);
delete v;
return false;
}
v->frame = *this;
@ -412,13 +417,11 @@ namespace llarp
if (not v->frame.Verify(v->si))
{
LogError("Signature failure from ", v->si.Addr());
delete v;
return;
}
if (not v->frame.DecryptPayloadInto(v->shared, *msg))
{
LogError("failed to decrypt message");
delete v;
return;
}
RecvDataEvent ev;
@ -426,7 +429,6 @@ namespace llarp
ev.pathid = v->frame.F;
ev.msg = std::move(msg);
msg->handler->QueueRecvData(std::move(ev));
delete v;
});
return true;
}

@ -125,7 +125,7 @@ namespace llarp
path::Path_ptr fromPath,
const std::shared_ptr<llarp::thread::ThreadPool>& worker,
const Identity& localIdent,
IDataHandler* handler) const;
Endpoint* handler) const;
bool
DecryptPayloadInto(const SharedSecret& sharedkey, ProtocolMessage& into) const;

Loading…
Cancel
Save