mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Better admin IP management in .cfg (RIPD-820):
* Deprecate rpc_admin_allow section from configuration file
* New port-specific setting 'admin':
* Comma-separated list of IP addresses that are allowed administrative
privileges (subject to username & password authentication if configured)
* 127.0.0.1 is no longer a default admin IP.
* 0.0.0.0 may be specified to indicate "any IP" but cannot be combined
with other IP addresses.
This commit is contained in:
committed by
Vinnie Falco
parent
97623d20c5
commit
6d79004d4f
@@ -26,7 +26,7 @@ bool
|
||||
passwordUnrequiredOrSentCorrect (HTTP::Port const& port,
|
||||
Json::Value const& params) {
|
||||
|
||||
assert(port.allow_admin);
|
||||
assert(! port.admin_ip.empty ());
|
||||
bool const passwordRequired = (!port.admin_user.empty() ||
|
||||
!port.admin_password.empty());
|
||||
|
||||
@@ -38,29 +38,28 @@ passwordUnrequiredOrSentCorrect (HTTP::Port const& port,
|
||||
}
|
||||
|
||||
bool
|
||||
ipAllowed (beast::IP::Endpoint const& remoteIp,
|
||||
std::vector<beast::IP::Endpoint> const& adminAllow)
|
||||
ipAllowed (beast::IP::Address const& remoteIp,
|
||||
std::vector<beast::IP::Address> const& adminIp)
|
||||
{
|
||||
return std::find(adminAllow.begin(), adminAllow.end(),
|
||||
remoteIp.at_port(0)) != adminAllow.end();
|
||||
return std::find_if (adminIp.begin (), adminIp.end (),
|
||||
[&remoteIp](beast::IP::Address const& ip) { return ip.is_any () ||
|
||||
ip == remoteIp; }) != adminIp.end ();
|
||||
}
|
||||
|
||||
bool
|
||||
isAdmin (HTTP::Port const& port, Json::Value const& params,
|
||||
beast::IP::Endpoint const& remoteIp,
|
||||
std::vector<beast::IP::Endpoint> const& adminAllow)
|
||||
beast::IP::Address const& remoteIp)
|
||||
{
|
||||
return (port.allow_admin && ipAllowed(remoteIp, adminAllow)) &&
|
||||
passwordUnrequiredOrSentCorrect(port, params);
|
||||
return ipAllowed (remoteIp, port.admin_ip) &&
|
||||
passwordUnrequiredOrSentCorrect (port, params);
|
||||
}
|
||||
|
||||
Role
|
||||
requestRole (Role const& required, HTTP::Port const& port,
|
||||
Json::Value const& params, beast::IP::Endpoint const& remoteIp,
|
||||
std::vector<beast::IP::Endpoint> const& adminAllow)
|
||||
Json::Value const& params, beast::IP::Endpoint const& remoteIp)
|
||||
{
|
||||
Role role (Role::GUEST);
|
||||
if (isAdmin(port, params, remoteIp, adminAllow))
|
||||
if (isAdmin(port, params, remoteIp.address ()))
|
||||
role = Role::ADMIN;
|
||||
if (required == Role::ADMIN && role != required)
|
||||
role = Role::FORBID;
|
||||
|
||||
@@ -291,7 +291,6 @@ ServerHandlerImp::processRequest (
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
auto const& admin_allow = getConfig().RPC_ADMIN_ALLOW;
|
||||
auto role = Role::FORBID;
|
||||
auto required = RPC::roleRequired(id.asString());
|
||||
|
||||
@@ -300,12 +299,12 @@ ServerHandlerImp::processRequest (
|
||||
jsonRPC["params"][Json::UInt(0)].isObject())
|
||||
{
|
||||
role = requestRole(required, port, jsonRPC["params"][Json::UInt(0)],
|
||||
remoteIPAddress, admin_allow);
|
||||
remoteIPAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
role = requestRole(required, port, Json::objectValue,
|
||||
remoteIPAddress, admin_allow);
|
||||
remoteIPAddress);
|
||||
}
|
||||
|
||||
Resource::Consumer usage;
|
||||
@@ -521,7 +520,7 @@ struct ParsedPort
|
||||
|
||||
boost::optional<boost::asio::ip::address> ip;
|
||||
boost::optional<std::uint16_t> port;
|
||||
boost::optional<bool> allow_admin;
|
||||
boost::optional<std::vector<beast::IP::Address>> admin_ip;
|
||||
};
|
||||
|
||||
void
|
||||
@@ -579,19 +578,35 @@ parse_Port (ParsedPort& port, Section const& section, std::ostream& log)
|
||||
auto const result = section.find("admin");
|
||||
if (result.second)
|
||||
{
|
||||
if (result.first == "no")
|
||||
std::stringstream ss (result.first);
|
||||
std::string ip;
|
||||
bool has_any (false);
|
||||
|
||||
port.admin_ip.emplace ();
|
||||
while (std::getline (ss, ip, ','))
|
||||
{
|
||||
port.allow_admin = false;
|
||||
}
|
||||
else if (result.first == "allow")
|
||||
{
|
||||
port.allow_admin = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << "Invalid value '" << result.first <<
|
||||
"' for key 'admin' in [" << section.name() << "]\n";
|
||||
throw std::exception();
|
||||
beast::IP::Address const addr(
|
||||
beast::IP::Endpoint::from_string_altform (ip).address ());
|
||||
|
||||
if (addr.is_any ())
|
||||
{
|
||||
has_any = true;
|
||||
}
|
||||
else if (is_unspecified (addr))
|
||||
{
|
||||
log << "Invalid value '" << ip << "' for key 'admin' in ["
|
||||
<< section.name() << "]\n";
|
||||
throw std::exception ();
|
||||
}
|
||||
|
||||
if (has_any && ! port.admin_ip->empty ())
|
||||
{
|
||||
log << "IP specified with 0.0.0.0 '" << ip <<
|
||||
"' for key 'admin' in [" << section.name () << "]\n";
|
||||
throw std::exception ();
|
||||
}
|
||||
|
||||
port.admin_ip->emplace_back (addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -629,11 +644,9 @@ to_Port(ParsedPort const& parsed, std::ostream& log)
|
||||
throw std::exception();
|
||||
}
|
||||
p.port = *parsed.port;
|
||||
|
||||
if (! parsed.allow_admin)
|
||||
p.allow_admin = false;
|
||||
else
|
||||
p.allow_admin = *parsed.allow_admin;
|
||||
|
||||
if (parsed.admin_ip)
|
||||
p.admin_ip = *parsed.admin_ip;
|
||||
|
||||
if (parsed.protocol.empty())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user