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 bool
ShouldClose(llarp_time_t now) const; ShouldClose(llarp_time_t now) const;
/// return true if the host header is correct
virtual bool
ValidateHost(const std::string& host) const = 0;
private: private:
ConnImpl* m_Impl; ConnImpl* m_Impl;
}; };

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

@ -96,7 +96,8 @@ namespace abyss
{ {
// TODO: header whitelist // TODO: header whitelist
return name == string_view("content-type") return name == string_view("content-type")
|| name == string_view("content-length"); || name == string_view("content-length")
|| name == string_view("host");
} }
bool bool
@ -162,6 +163,17 @@ namespace abyss
{ {
m_BodyParser.reset(json::MakeParser(contentLength)); 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)) if(!m_BodyParser->FeedData(buf, sz))
{ {

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

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

Loading…
Cancel
Save