Merge pull request #1160 from majestrate/dns-rebinding-fix-2020-03-04

add llarp.admin.die rpc call to gracefully kill router
pull/1162/head
Jeff 4 years ago committed by GitHub
commit abff5c35cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -37,6 +37,10 @@ namespace abyss
bool
ShouldClose(llarp_time_t now) const;
/// return true if the host header is correct
virtual bool
ValidateHost(const std::string& host) const = 0;
private:
ConnImpl* m_Impl;
};

@ -192,6 +192,7 @@ namespace abyss
authgen << ", " << opt.first << "=" << opt.second;
}
m_SendHeaders.clear();
m_SendHeaders.emplace("Host", "localhost");
m_SendHeaders.emplace("Authorization", authgen.str());
SendRequest();
return true;
@ -320,6 +321,7 @@ namespace abyss
std::string body;
std::stringstream ss;
body = m_RequestBody.dump();
m_SendHeaders.emplace("Host", "localhost");
m_SendHeaders.emplace("Content-Type", "application/json");
m_SendHeaders.emplace("Content-Length", std::to_string(body.size()));
m_SendHeaders.emplace("Accept", "application/json");

@ -96,7 +96,8 @@ namespace abyss
{
// TODO: header whitelist
return name == string_view("content-type")
|| name == string_view("content-length");
|| name == string_view("content-length")
|| name == string_view("host");
}
bool
@ -162,6 +163,17 @@ namespace abyss
{
m_BodyParser.reset(json::MakeParser(contentLength));
}
itr = Header.Headers.find("host");
if(itr == Header.Headers.end())
{
return WriteResponseSimple(400, "Bad Request", "text/plain",
"no host header provided");
}
if(not handler->ValidateHost(itr->second))
{
return WriteResponseSimple(400, "Bad Request", "text/plain",
"invalid host header");
}
}
if(!m_BodyParser->FeedData(buf, sz))
{

@ -285,12 +285,16 @@ namespace llarp
struct Handler : public ::abyss::httpd::IRPCHandler
{
std::string expectedHostname;
AbstractRouter* router;
std::unordered_map< std::string, std::function< Response() > > m_dispatch;
Handler(::abyss::httpd::ConnImpl* conn, AbstractRouter* r)
Handler(::abyss::httpd::ConnImpl* conn, AbstractRouter* r,
std::string hostname)
: ::abyss::httpd::IRPCHandler(conn)
, expectedHostname(std::move(hostname))
, router(r)
, m_dispatch{
{"llarp.admin.die", [=]() { return KillRouter(); }},
{"llarp.admin.wakeup", [=]() { return StartRouter(); }},
{"llarp.admin.link.neighbor",
[=]() { return ListNeighbors(); }},
@ -304,6 +308,12 @@ namespace llarp
~Handler() override = default;
bool
ValidateHost(const std::string& host) const override
{
return host == "localhost" || host == expectedHostname;
}
Response
StartRouter() const
{
@ -317,6 +327,15 @@ namespace llarp
return router->ExtractStatus();
}
Response
KillRouter() const
{
if(not router->IsRunning())
return {{"error", "already stopping"}};
router->Stop();
return {{"status", "OK"}};
}
Response
ListExitLevels() const
{
@ -416,11 +435,15 @@ namespace llarp
: ::abyss::httpd::BaseReqHandler(reqtimeout), router(r)
{
}
std::string expectedHostname;
AbstractRouter* router;
::abyss::httpd::IRPCHandler*
CreateHandler(::abyss::httpd::ConnImpl* conn) override
{
return new Handler(conn, router);
return new Handler(conn, router, expectedHostname);
}
};
@ -447,15 +470,20 @@ namespace llarp
sockaddr_in saddr;
saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
saddr.sin_family = AF_INET;
saddr.sin_port = 0;
saddr.sin_port = 1190;
auto idx = addr.find_first_of(':');
if(idx != std::string::npos)
{
_handler.expectedHostname = addr.substr(0, idx);
Addr netaddr{addr.substr(0, idx), addr.substr(1 + idx)};
saddr.sin_addr.s_addr = netaddr.ton();
saddr.sin_port = htons(netaddr.port());
}
else
{
_handler.expectedHostname = addr;
}
return _handler.ServeAsync(router->netloop(), router->logic(),
(const sockaddr*)&saddr);
}

@ -107,6 +107,12 @@ struct ServerHandler : public abyss::httpd::IRPCHandler
{
}
bool
ValidateHost(const std::string & /*hostname */) const override
{
return true;
}
Response
HandleJSONRPC(Method_t method, const Params& /*params*/)
{

Loading…
Cancel
Save