add string reason to auth messages

pull/1526/head
Jeff Becker 3 years ago
parent 2cb889013b
commit 5b2abce86f
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -57,20 +57,20 @@ namespace llarp::rpc
if (m_AuthWhitelist.count(from))
{
// explicitly whitelisted source
reply(service::AuthResult::eAuthAccepted);
reply({service::AuthResultCode::eAuthAccepted, "explicitly whitelisted"});
return;
}
if (not m_Conn.has_value())
{
// we don't have a connection to the backend so it's failed
reply(service::AuthResult::eAuthFailed);
reply({service::AuthResultCode::eAuthFailed, "remote has no connection to auth backend"});
return;
}
if (msg->proto != llarp::service::eProtocolAuth)
{
// not an auth message, reject
reply(service::AuthResult::eAuthRejected);
reply({service::AuthResultCode::eAuthRejected, "protocol error"});
return;
}
@ -82,13 +82,20 @@ namespace llarp::rpc
*m_Conn,
m_AuthMethod,
[self = shared_from_this(), reply](bool success, std::vector<std::string> data) {
service::AuthResult result = service::AuthResult::eAuthFailed;
service::AuthResult result{service::AuthResultCode::eAuthFailed, "no reason given"};
if (success and not data.empty())
{
const auto maybe = service::ParseAuthResult(data[0]);
if (maybe.has_value())
if (const auto maybe = service::ParseAuthResultCode(data[0]))
{
result = *maybe;
result.code = *maybe;
}
if (result.code == service::AuthResultCode::eAuthAccepted)
{
result.reason = "OK";
}
if (data.size() > 1)
{
result.reason = data[1];
}
}
reply(result);

@ -262,25 +262,23 @@ namespace llarp::rpc
reply(CreateJSONError("could not find exit"));
return;
}
auto onGoodResult = [r, reply]() {
auto onGoodResult = [r, reply](std::string reason) {
r->routePoker().Up();
reply(CreateJSONResponse("OK"));
reply(CreateJSONResponse(reason));
};
if (not shouldSendAuth)
{
onGoodResult();
onGoodResult("OK");
return;
}
ctx->AsyncSendAuth(
[onGoodResult, reply](service::AuthResult result) {
if (result != service::AuthResult::eAuthAccepted)
if (result.code != service::AuthResultCode::eAuthAccepted)
{
reply(CreateJSONError(
"authentication failed: "
+ service::AuthResultDescription(result)));
reply(CreateJSONError(result.reason));
return;
}
onGoodResult();
onGoodResult(result.reason);
});
},
5s);

@ -4,45 +4,26 @@
namespace llarp::service
{
/// maybe get auth result from string
std::optional<AuthResult>
ParseAuthResult(std::string data)
std::optional<AuthResultCode>
ParseAuthResultCode(std::string data)
{
static std::unordered_map<std::string, AuthResult> values = {
{"OKAY", AuthResult::eAuthAccepted},
{"REJECT", AuthResult::eAuthRejected},
{"PAYME", AuthResult::eAuthPaymentRequired},
{"LIMITED", AuthResult::eAuthRateLimit}};
std::unordered_map<std::string, AuthResultCode> values = {
{"OKAY", AuthResultCode::eAuthAccepted},
{"REJECT", AuthResultCode::eAuthRejected},
{"PAYME", AuthResultCode::eAuthPaymentRequired},
{"LIMITED", AuthResultCode::eAuthRateLimit}};
auto itr = values.find(data);
if (itr == values.end())
return std::nullopt;
return itr->second;
}
std::string
AuthResultDescription(AuthResult auth)
{
switch (auth)
{
case AuthResult::eAuthAccepted:
return "accepted";
case AuthResult::eAuthRejected:
return "rejected";
case AuthResult::eAuthPaymentRequired:
return "payment required";
case AuthResult::eAuthRateLimit:
return "rate limit hit";
default:
return "unknown";
}
}
AuthType
ParseAuthType(std::string data)
{
static std::unordered_map<std::string, AuthType> values = {
{"lmq", AuthType::eAuthTypeLMQ},
{"whitelist", AuthType::eAuthTypeWhitelist},
{"none", AuthType::eAuthTypeNone}};
std::unordered_map<std::string, AuthType> values = {{"lmq", AuthType::eAuthTypeLMQ},
{"whitelist", AuthType::eAuthTypeWhitelist},
{"none", AuthType::eAuthTypeNone}};
const auto itr = values.find(data);
if (itr == values.end())
throw std::invalid_argument("no such auth type: " + data);

@ -8,8 +8,8 @@
namespace llarp::service
{
/// authentication status
enum AuthResult
/// authentication status code
enum AuthResultCode
{
/// explicitly accepted
eAuthAccepted = 0,
@ -23,12 +23,16 @@ namespace llarp::service
eAuthPaymentRequired = 4
};
std::string
AuthResultDescription(AuthResult result);
/// auth result object with code and reason
struct AuthResult
{
AuthResultCode code;
std::string reason;
};
/// maybe get auth result from string
std::optional<AuthResult>
ParseAuthResult(std::string data);
std::optional<AuthResultCode>
ParseAuthResultCode(std::string data);
struct IAuthPolicy
{

@ -1062,7 +1062,7 @@ namespace llarp
}
else
{
RouterLogic()->Call([hook]() { hook(AuthResult::eAuthAccepted); });
RouterLogic()->Call([hook]() { hook({AuthResultCode::eAuthAccepted, "OK"}); });
}
}
@ -1074,14 +1074,18 @@ namespace llarp
if (m_AuthPolicy == nullptr)
return;
ProtocolFrame f;
f.R = result;
f.R = result.code;
f.T = tag;
f.F = path->intro.pathID;
if (result == AuthResult::eAuthAccepted)
if (result.code == AuthResultCode::eAuthAccepted)
{
ProtocolMessage msg;
std::array<byte_t, 2> tmp{'d', 'e'};
msg.PutBuffer(tmp);
std::vector<byte_t> reason{};
reason.resize(result.reason.size());
std::copy_n(result.reason.c_str(), reason.size(), reason.data());
msg.PutBuffer(reason);
f.N.Randomize();
f.C.Zero();
msg.proto = eProtocolAuth;

@ -539,26 +539,42 @@ namespace llarp
return false;
// remove convotag it doesn't exist
LogWarn("remove convotag T=", frame.T);
AuthResult result{eAuthFailed, "unknown reason"};
SharedSecret sessionKey{};
if (m_DataHandler->GetCachedSessionKeyFor(frame.T, sessionKey))
{
ProtocolMessage msg{};
if (frame.DecryptPayloadInto(sessionKey, msg))
{
if (msg.proto == eProtocolAuth and not msg.payload.empty())
{
result.reason = std::string{reinterpret_cast<const char*>(msg.payload.data()),
msg.payload.size()};
}
}
}
m_Endpoint->RemoveConvoTag(frame.T);
if (authResultListener)
{
switch (frame.R)
{
case 1:
authResultListener(eAuthRejected);
break;
case 2:
authResultListener(eAuthFailed);
result.code = eAuthRejected;
break;
case 3:
authResultListener(eAuthRateLimit);
result.code = eAuthRateLimit;
break;
case 4:
authResultListener(eAuthPaymentRequired);
result.code = eAuthPaymentRequired;
break;
default:
authResultListener(eAuthFailed);
result.code = eAuthFailed;
break;
}
authResultListener(result);
authResultListener = nullptr;
}
return true;
@ -568,7 +584,15 @@ namespace llarp
{
std::function<void(AuthResult)> handler = authResultListener;
authResultListener = nullptr;
hook = [handler](std::shared_ptr<ProtocolMessage>) { handler(AuthResult::eAuthAccepted); };
hook = [handler](std::shared_ptr<ProtocolMessage> msg) {
AuthResult result{AuthResultCode::eAuthAccepted, "OK"};
if (msg->proto == eProtocolAuth and not msg->payload.empty())
{
result.reason = std::string{reinterpret_cast<const char*>(msg->payload.data()),
msg->payload.size()};
}
handler(result);
};
}
const auto& ident = m_Endpoint->GetIdentity();
if (not frame.AsyncDecryptAndVerify(m_Endpoint->EndpointLogic(), p, ident, m_Endpoint, hook))

@ -366,7 +366,7 @@ namespace llarp
msg,
[path, msg, from, handler = self->handler, fromIntro = self->fromIntro, sharedKey](
AuthResult result) {
if (result == AuthResult::eAuthAccepted)
if (result.code == AuthResultCode::eAuthAccepted)
{
handler->PutIntroFor(msg->tag, msg->introReply);
handler->PutReplyIntroFor(msg->tag, fromIntro);

@ -115,12 +115,12 @@ namespace llarp
if (maybe.has_value())
{
// send auth message
const llarp_buffer_t authdata(maybe->token);
const llarp_buffer_t authdata{maybe->token};
AsyncGenIntro(authdata, eProtocolAuth);
authResultListener = resultHandler;
}
else
resultHandler(AuthResult::eAuthFailed);
resultHandler({AuthResultCode::eAuthFailed, "no auth for given endpoint"});
}
void

Loading…
Cancel
Save