mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-26 03:03:22 -03:00
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 ssl::context* rpc_ssl_context = NULL;
|
||||||
static boost::thread_group* rpc_worker_group = NULL;
|
static boost::thread_group* rpc_worker_group = NULL;
|
||||||
static boost::asio::io_service::work *rpc_dummy_work = 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,
|
void RPCTypeCheck(const Array& params,
|
||||||
const list<Value_type>& typesExpected,
|
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;
|
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
|
// Make sure that IPv4-compatible and IPv4-mapped IPv6 addresses are treated as IPv4 addresses
|
||||||
if (address.is_v6()
|
if (address.is_v6()
|
||||||
&& (address.to_v6().is_v4_compatible()
|
&& (address.to_v6().is_v4_compatible()
|
||||||
|| address.to_v6().is_v4_mapped()))
|
|| 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()
|
if(address.is_v4())
|
||||||
|| address == asio::ip::address_v6::loopback()
|
{
|
||||||
|| (address.is_v4()
|
boost::asio::ip::address_v4::bytes_type bytes = address.to_v4().to_bytes();
|
||||||
// Check whether IPv4 addresses match 127.0.0.0/8 (loopback subnet)
|
netaddr.SetRaw(NET_IPV4, &bytes[0]);
|
||||||
&& (address.to_v4().to_ulong() & 0xff000000) == 0x7f000000))
|
}
|
||||||
return true;
|
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();
|
bool ClientAllowed(const boost::asio::ip::address& address)
|
||||||
const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
|
{
|
||||||
BOOST_FOREACH(string strAllow, vAllow)
|
CNetAddr netaddr = BoostAsioToCNetAddr(address);
|
||||||
if (WildcardMatch(strAddress, strAllow))
|
BOOST_FOREACH(const CSubNet &subnet, rpc_allow_subnets)
|
||||||
|
if (subnet.Match(netaddr))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -502,6 +512,31 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol,
|
||||||
|
|
||||||
void StartRPCThreads()
|
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"];
|
strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
|
||||||
if (((mapArgs["-rpcpassword"] == "") ||
|
if (((mapArgs["-rpcpassword"] == "") ||
|
||||||
(mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword())
|
(mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword())
|
||||||
|
|
Loading…
Add table
Reference in a new issue