rpc: Use netmasks instead of wildcards for IP address matching
`-rpcallowip` currently has a wacky wildcard-based format. After this commit it will accept the more standard format, for example: - Ranges with netmask 127.0.0.0/255.255.255.0, ::/0 - Ranges with cidr 12.3.4.5/24, 12:34:56:78:9a:bc:de:00/112 - Loose IPs ::1, 127.0.0.1 Trying to use the old *?-based format will result in an error message at launch.
This commit is contained in:
parent
e16be73753
commit
ee21912510
1 changed files with 47 additions and 12 deletions
|
@ -38,6 +38,7 @@ static map<string, boost::shared_ptr<deadline_timer> > deadlineTimers;
|
|||
static ssl::context* rpc_ssl_context = NULL;
|
||||
static boost::thread_group* rpc_worker_group = NULL;
|
||||
static boost::asio::io_service::work *rpc_dummy_work = NULL;
|
||||
static std::vector<CSubNet> rpc_allow_subnets; //!< List of subnets to allow RPC connections from
|
||||
|
||||
void RPCTypeCheck(const Array& params,
|
||||
const list<Value_type>& typesExpected,
|
||||
|
@ -358,25 +359,34 @@ void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
|
|||
stream << HTTPReply(nStatus, strReply, false) << std::flush;
|
||||
}
|
||||
|
||||
bool ClientAllowed(const boost::asio::ip::address& address)
|
||||
// Convert boost::asio address to CNetAddr
|
||||
static CNetAddr BoostAsioToCNetAddr(boost::asio::ip::address address)
|
||||
{
|
||||
CNetAddr netaddr;
|
||||
// Make sure that IPv4-compatible and IPv4-mapped IPv6 addresses are treated as IPv4 addresses
|
||||
if (address.is_v6()
|
||||
&& (address.to_v6().is_v4_compatible()
|
||||
|| address.to_v6().is_v4_mapped()))
|
||||
return ClientAllowed(address.to_v6().to_v4());
|
||||
address = address.to_v6().to_v4();
|
||||
|
||||
if (address == asio::ip::address_v4::loopback()
|
||||
|| address == asio::ip::address_v6::loopback()
|
||||
|| (address.is_v4()
|
||||
// Check whether IPv4 addresses match 127.0.0.0/8 (loopback subnet)
|
||||
&& (address.to_v4().to_ulong() & 0xff000000) == 0x7f000000))
|
||||
return true;
|
||||
if(address.is_v4())
|
||||
{
|
||||
boost::asio::ip::address_v4::bytes_type bytes = address.to_v4().to_bytes();
|
||||
netaddr.SetRaw(NET_IPV4, &bytes[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::asio::ip::address_v6::bytes_type bytes = address.to_v6().to_bytes();
|
||||
netaddr.SetRaw(NET_IPV6, &bytes[0]);
|
||||
}
|
||||
return netaddr;
|
||||
}
|
||||
|
||||
const string strAddress = address.to_string();
|
||||
const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
|
||||
BOOST_FOREACH(string strAllow, vAllow)
|
||||
if (WildcardMatch(strAddress, strAllow))
|
||||
bool ClientAllowed(const boost::asio::ip::address& address)
|
||||
{
|
||||
CNetAddr netaddr = BoostAsioToCNetAddr(address);
|
||||
BOOST_FOREACH(const CSubNet &subnet, rpc_allow_subnets)
|
||||
if (subnet.Match(netaddr))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -502,6 +512,31 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol,
|
|||
|
||||
void StartRPCThreads()
|
||||
{
|
||||
rpc_allow_subnets.clear();
|
||||
rpc_allow_subnets.push_back(CSubNet("127.0.0.0/8")); // always allow IPv4 local subnet
|
||||
rpc_allow_subnets.push_back(CSubNet("::1")); // always allow IPv6 localhost
|
||||
if (mapMultiArgs.count("-rpcallowip"))
|
||||
{
|
||||
const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
|
||||
BOOST_FOREACH(string strAllow, vAllow)
|
||||
{
|
||||
CSubNet subnet(strAllow);
|
||||
if(!subnet.IsValid())
|
||||
{
|
||||
uiInterface.ThreadSafeMessageBox(
|
||||
strprintf("Invalid -rpcallowip subnet specification: %s", strAllow),
|
||||
"", CClientUIInterface::MSG_ERROR);
|
||||
StartShutdown();
|
||||
return;
|
||||
}
|
||||
rpc_allow_subnets.push_back(subnet);
|
||||
}
|
||||
}
|
||||
std::string strAllowed;
|
||||
BOOST_FOREACH(const CSubNet &subnet, rpc_allow_subnets)
|
||||
strAllowed += subnet.ToString() + " ";
|
||||
LogPrint("rpc", "Allowing RPC connections from: %s\n", strAllowed);
|
||||
|
||||
strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
|
||||
if (((mapArgs["-rpcpassword"] == "") ||
|
||||
(mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword())
|
||||
|
|
Loading…
Reference in a new issue