add file auth for tokens

pull/1830/head
Jeff 2 years ago committed by Jeff
parent 9a6bfe6013
commit a082ba4e77

@ -317,7 +317,7 @@ namespace llarp
ClientOnly,
Comment{
"Set the endpoint authentication mechanism.",
"none/whitelist/lmq",
"none/whitelist/lmq/file",
},
[this](std::string arg) {
if (arg.empty())
@ -366,13 +366,30 @@ namespace llarp
m_AuthWhitelist.emplace(std::move(addr));
});
conf.defineOption<fs::path>(
"network",
"auth-file",
ClientOnly,
MultiValue,
Comment{
"Read auth tokens from file to accept endpoint auth",
"Can be provided multiple times",
},
[this](fs::path arg) {
if (not fs::exists(arg))
throw std::invalid_argument{
stringify("cannot load auth file ", arg, " as it does not seem to exist")};
m_AuthFiles.emplace(std::move(arg));
});
conf.defineOption<std::string>(
"network",
"auth-static",
ClientOnly,
MultiValue,
Comment{
"manually add a static auth code to accept for endpoint auth",
"Manually add a static auth code to accept for endpoint auth",
"Can be provided multiple times",
},
[this](std::string arg) { m_AuthStaticTokens.emplace(std::move(arg)); });

@ -119,6 +119,7 @@ namespace llarp
std::optional<std::string> m_AuthMethod;
std::unordered_set<service::Address> m_AuthWhitelist;
std::unordered_set<std::string> m_AuthStaticTokens;
std::set<fs::path> m_AuthFiles;
std::vector<llarp::dns::SRVData> m_SRVRecords;

@ -174,7 +174,11 @@ namespace llarp
LogInfo(Name(), " setting to be not reachable by default");
}
if (conf.m_AuthType != service::AuthType::eAuthTypeNone)
if (conf.m_AuthType == service::AuthType::eAuthTypeFile)
{
m_AuthPolicy = service::MakeFileAuthPolicy(m_router, conf.m_AuthFiles);
}
else if (conf.m_AuthType != service::AuthType::eAuthTypeNone)
{
std::string url, method;
if (conf.m_AuthUrl.has_value() and conf.m_AuthMethod.has_value())

@ -1,6 +1,11 @@
#include "auth.hpp"
#include <unordered_map>
#include <llarp/router/abstractrouter.hpp>
#include "protocol.hpp"
#include <llarp/util/str.hpp>
#include <llarp/util/fs.hpp>
namespace llarp::service
{
/// maybe get auth result from string
@ -22,6 +27,7 @@ namespace llarp::service
ParseAuthType(std::string data)
{
std::unordered_map<std::string, AuthType> values = {
{"file", AuthType::eAuthTypeFile},
{"lmq", AuthType::eAuthTypeLMQ},
{"whitelist", AuthType::eAuthTypeWhitelist},
{"none", AuthType::eAuthTypeNone}};
@ -58,4 +64,90 @@ namespace llarp::service
}
}
class FileAuthPolicy : public IAuthPolicy, public std::enable_shared_from_this<FileAuthPolicy>
{
const std::set<fs::path> m_Files;
AbstractRouter* const m_Router;
mutable util::Mutex m_Access;
std::unordered_set<ConvoTag> m_Pending;
/// returns an auth result for a auth info challange, opens every file until it finds a token
/// matching it
/// this is expected to be done in the IO thread
AuthResult
CheckFiles(const AuthInfo& info) const
{
for (const auto& f : m_Files)
{
fs::ifstream i{f};
std::string line{};
while (std::getline(i, line))
{
// split off comments
const auto parts = split_any(line, "#;", true);
if (auto part = parts[0]; not parts.empty() and not parts[0].empty())
{
// split off whitespaces
if (TrimWhitespace(part) == info.token)
return AuthResult{AuthResultCode::eAuthAccepted, "accepted by whitelist"};
}
}
}
return AuthResult{AuthResultCode::eAuthRejected, "rejected by whitelist"};
}
public:
FileAuthPolicy(AbstractRouter* r, std::set<fs::path> files)
: m_Files{std::move(files)}, m_Router{r}
{}
void
AuthenticateAsync(
std::shared_ptr<ProtocolMessage> msg, std::function<void(AuthResult)> hook) override
{
auto reply = m_Router->loop()->make_caller(
[tag = msg->tag, hook, self = shared_from_this()](AuthResult result) {
{
util::Lock _lock{self->m_Access};
self->m_Pending.erase(tag);
}
hook(result);
});
{
util::Lock _lock{m_Access};
m_Pending.emplace(msg->tag);
}
if (msg->proto == ProtocolType::Auth)
{
m_Router->QueueDiskIO(
[self = shared_from_this(),
auth = AuthInfo{std::string{
reinterpret_cast<const char*>(msg->payload.data()), msg->payload.size()}},
reply]() {
try
{
reply(self->CheckFiles(auth));
}
catch (std::exception& ex)
{
reply(AuthResult{AuthResultCode::eAuthFailed, ex.what()});
}
});
}
else
reply(AuthResult{AuthResultCode::eAuthRejected, "protocol error"});
}
bool
AsyncAuthPending(ConvoTag tag) const override
{
util::Lock _lock{m_Access};
return m_Pending.count(tag);
}
};
std::shared_ptr<IAuthPolicy>
MakeFileAuthPolicy(AbstractRouter* r, std::set<fs::path> files)
{
return std::make_shared<FileAuthPolicy>(r, std::move(files));
}
} // namespace llarp::service

@ -71,7 +71,9 @@ namespace llarp::service
/// manual whitelist
eAuthTypeWhitelist,
/// LMQ server
eAuthTypeLMQ
eAuthTypeLMQ,
/// plain file
eAuthTypeFile,
};
/// get an auth type from a string
@ -79,4 +81,8 @@ namespace llarp::service
AuthType
ParseAuthType(std::string arg);
/// make an IAuthPolicy that reads out of a static file
std::shared_ptr<IAuthPolicy>
MakeFileAuthPolicy(AbstractRouter*, std::set<fs::path> files);
} // namespace llarp::service

Loading…
Cancel
Save