mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-21 11:35:53 +00:00
Support secure RPC.
This commit is contained in:
@@ -7,11 +7,18 @@ SETUP_LOG (RPCDoor)
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace boost::asio::ip;
|
using namespace boost::asio::ip;
|
||||||
|
|
||||||
|
extern void initSSLContext(boost::asio::ssl::context& context,
|
||||||
|
std::string key_file, std::string cert_file, std::string chain_file);
|
||||||
|
|
||||||
RPCDoor::RPCDoor(boost::asio::io_service& io_service) :
|
RPCDoor::RPCDoor(boost::asio::io_service& io_service) :
|
||||||
mAcceptor(io_service, tcp::endpoint(address::from_string(theConfig.RPC_IP), theConfig.RPC_PORT)),
|
mAcceptor(io_service, tcp::endpoint(address::from_string(theConfig.RPC_IP), theConfig.RPC_PORT)),
|
||||||
mDelayTimer(io_service)
|
mDelayTimer(io_service), mSSLContext(boost::asio::ssl::context::sslv23)
|
||||||
{
|
{
|
||||||
WriteLog (lsINFO, RPCDoor) << "RPC port: " << theConfig.RPC_IP << " " << theConfig.RPC_PORT << " allow remote: " << theConfig.RPC_ALLOW_REMOTE;
|
WriteLog (lsINFO, RPCDoor) << "RPC port: " << theConfig.RPC_IP << " " << theConfig.RPC_PORT << " allow remote: " << theConfig.RPC_ALLOW_REMOTE;
|
||||||
|
|
||||||
|
if (theConfig.RPC_SECURE != 0)
|
||||||
|
initSSLContext(mSSLContext, theConfig.RPC_SSL_KEY, theConfig.RPC_SSL_CERT, theConfig.RPC_SSL_CHAIN);
|
||||||
|
|
||||||
startListening();
|
startListening();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,10 +29,10 @@ RPCDoor::~RPCDoor()
|
|||||||
|
|
||||||
void RPCDoor::startListening()
|
void RPCDoor::startListening()
|
||||||
{
|
{
|
||||||
RPCServer::pointer new_connection = RPCServer::create(mAcceptor.get_io_service(), &theApp->getOPs());
|
RPCServer::pointer new_connection = RPCServer::create(mAcceptor.get_io_service(), mSSLContext, &theApp->getOPs());
|
||||||
mAcceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
mAcceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
||||||
|
|
||||||
mAcceptor.async_accept(new_connection->getSocket(),
|
mAcceptor.async_accept(new_connection->getRawSocket(),
|
||||||
boost::bind(&RPCDoor::handleConnect, this, new_connection,
|
boost::bind(&RPCDoor::handleConnect, this, new_connection,
|
||||||
boost::asio::placeholders::error));
|
boost::asio::placeholders::error));
|
||||||
}
|
}
|
||||||
@@ -41,8 +48,7 @@ bool RPCDoor::isClientAllowed(const std::string& ip)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RPCDoor::handleConnect(RPCServer::pointer new_connection,
|
void RPCDoor::handleConnect(RPCServer::pointer new_connection, const boost::system::error_code& error)
|
||||||
const boost::system::error_code& error)
|
|
||||||
{
|
{
|
||||||
bool delay = false;
|
bool delay = false;
|
||||||
if (!error)
|
if (!error)
|
||||||
@@ -50,7 +56,7 @@ void RPCDoor::handleConnect(RPCServer::pointer new_connection,
|
|||||||
// Restrict callers by IP
|
// Restrict callers by IP
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!isClientAllowed(new_connection->getSocket().remote_endpoint().address().to_string()))
|
if (!isClientAllowed(new_connection->getRawSocket().remote_endpoint().address().to_string()))
|
||||||
{
|
{
|
||||||
startListening();
|
startListening();
|
||||||
return;
|
return;
|
||||||
@@ -62,7 +68,8 @@ void RPCDoor::handleConnect(RPCServer::pointer new_connection,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_connection->connected();
|
new_connection->getSocket().async_handshake(AutoSocket::ssl_socket::server,
|
||||||
|
boost::bind(&RPCServer::connected, new_connection));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ public:
|
|||||||
~RPCDoor ();
|
~RPCDoor ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::asio::ip::tcp::acceptor mAcceptor;
|
boost::asio::ip::tcp::acceptor mAcceptor;
|
||||||
boost::asio::deadline_timer mDelayTimer;
|
boost::asio::deadline_timer mDelayTimer;
|
||||||
|
boost::asio::ssl::context mSSLContext;
|
||||||
|
|
||||||
void startListening();
|
void startListening();
|
||||||
void handleConnect(RPCServer::pointer new_connection,
|
void handleConnect(RPCServer::pointer new_connection,
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
SETUP_LOG (RPCServer)
|
SETUP_LOG (RPCServer)
|
||||||
|
|
||||||
RPCServer::RPCServer(boost::asio::io_service& io_service , NetworkOPs* nopNetwork)
|
RPCServer::RPCServer(boost::asio::io_service& io_service, boost::asio::ssl::context& context, NetworkOPs* nopNetwork)
|
||||||
: mNetOps(nopNetwork), mSocket(io_service)
|
: mNetOps(nopNetwork), mSocket(io_service, context)
|
||||||
{
|
{
|
||||||
mRole = RPCHandler::GUEST;
|
mRole = RPCHandler::GUEST;
|
||||||
}
|
}
|
||||||
@@ -52,6 +52,11 @@ void RPCServer::handle_read_req(const boost::system::error_code& e)
|
|||||||
boost::bind(&RPCServer::handle_write, shared_from_this(), boost::asio::placeholders::error));
|
boost::bind(&RPCServer::handle_write, shared_from_this(), boost::asio::placeholders::error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dummy_handler()
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
void RPCServer::handle_read_line(const boost::system::error_code& e)
|
void RPCServer::handle_read_line(const boost::system::error_code& e)
|
||||||
{
|
{
|
||||||
if (e)
|
if (e)
|
||||||
@@ -62,8 +67,7 @@ void RPCServer::handle_read_line(const boost::system::error_code& e)
|
|||||||
if (action == haDO_REQUEST)
|
if (action == haDO_REQUEST)
|
||||||
{ // request with no body
|
{ // request with no body
|
||||||
WriteLog (lsWARNING, RPCServer) << "RPC HTTP request with no body";
|
WriteLog (lsWARNING, RPCServer) << "RPC HTTP request with no body";
|
||||||
boost::system::error_code ignore_ec;
|
mSocket.async_shutdown(boost::bind(&dummy_handler));
|
||||||
mSocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_ec);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (action == haREAD_LINE)
|
else if (action == haREAD_LINE)
|
||||||
@@ -78,8 +82,7 @@ void RPCServer::handle_read_line(const boost::system::error_code& e)
|
|||||||
if ((rLen < 0) || (rLen > RPC_MAXIMUM_QUERY))
|
if ((rLen < 0) || (rLen > RPC_MAXIMUM_QUERY))
|
||||||
{
|
{
|
||||||
WriteLog (lsWARNING, RPCServer) << "Illegal RPC request length " << rLen;
|
WriteLog (lsWARNING, RPCServer) << "Illegal RPC request length " << rLen;
|
||||||
boost::system::error_code ignore_ec;
|
mSocket.async_shutdown(boost::bind(&dummy_handler));
|
||||||
mSocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_ec);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,10 +102,7 @@ void RPCServer::handle_read_line(const boost::system::error_code& e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
mSocket.async_shutdown(boost::bind(&dummy_handler));
|
||||||
boost::system::error_code ignore_ec;
|
|
||||||
mSocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_ec);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RPCServer::handleRequest(const std::string& requestStr)
|
std::string RPCServer::handleRequest(const std::string& requestStr)
|
||||||
@@ -143,7 +143,7 @@ std::string RPCServer::handleRequest(const std::string& requestStr)
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mRole = iAdminGet(jvRequest, mSocket.remote_endpoint().address().to_string());
|
mRole = iAdminGet(jvRequest, mSocket.PlainSocket().remote_endpoint().address().to_string());
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{ // endpoint already disconnected
|
{ // endpoint already disconnected
|
||||||
@@ -187,10 +187,7 @@ void RPCServer::handle_write(const boost::system::error_code& e)
|
|||||||
{
|
{
|
||||||
HTTPRequestAction action = mHTTPRequest.requestDone(false);
|
HTTPRequestAction action = mHTTPRequest.requestDone(false);
|
||||||
if (action == haCLOSE_CONN)
|
if (action == haCLOSE_CONN)
|
||||||
{
|
mSocket.async_shutdown(boost::bind(&dummy_handler));
|
||||||
boost::system::error_code ignored_ec;
|
|
||||||
mSocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
boost::asio::async_read_until(mSocket, mLineBuffer, "\r\n",
|
boost::asio::async_read_until(mSocket, mLineBuffer, "\r\n",
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ private:
|
|||||||
|
|
||||||
NetworkOPs* mNetOps;
|
NetworkOPs* mNetOps;
|
||||||
|
|
||||||
boost::asio::ip::tcp::socket mSocket;
|
AutoSocket mSocket;
|
||||||
|
|
||||||
boost::asio::streambuf mLineBuffer;
|
boost::asio::streambuf mLineBuffer;
|
||||||
Blob mQueryVec;
|
Blob mQueryVec;
|
||||||
@@ -26,7 +26,7 @@ private:
|
|||||||
|
|
||||||
int mRole;
|
int mRole;
|
||||||
|
|
||||||
RPCServer(boost::asio::io_service& io_service, NetworkOPs* nopNetwork);
|
RPCServer(boost::asio::io_service& io_service, boost::asio::ssl::context& ssl_context, NetworkOPs* nopNetwork);
|
||||||
|
|
||||||
RPCServer(const RPCServer&); // no implementation
|
RPCServer(const RPCServer&); // no implementation
|
||||||
RPCServer& operator=(const RPCServer&); // no implementation
|
RPCServer& operator=(const RPCServer&); // no implementation
|
||||||
@@ -38,16 +38,21 @@ private:
|
|||||||
std::string handleRequest(const std::string& requestStr);
|
std::string handleRequest(const std::string& requestStr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static pointer create(boost::asio::io_service& io_service, NetworkOPs* mNetOps)
|
static pointer create(boost::asio::io_service& io_service, boost::asio::ssl::context& context, NetworkOPs* mNetOps)
|
||||||
{
|
{
|
||||||
return pointer(new RPCServer(io_service, mNetOps));
|
return pointer(new RPCServer(io_service, context, mNetOps));
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::ip::tcp::socket& getSocket()
|
AutoSocket& getSocket()
|
||||||
{
|
{
|
||||||
return mSocket;
|
return mSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::asio::ip::tcp::socket& getRawSocket()
|
||||||
|
{
|
||||||
|
return mSocket.PlainSocket();
|
||||||
|
}
|
||||||
|
|
||||||
void connected();
|
void connected();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ public:
|
|||||||
|
|
||||||
bool getPublic() { return mPublic; };
|
bool getPublic() { return mPublic; };
|
||||||
|
|
||||||
|
boost::asio::ssl::context& getASIOContext() { return *mCtx; }
|
||||||
|
|
||||||
static void ssend(connection_ptr cpClient, message_ptr mpMessage)
|
static void ssend(connection_ptr cpClient, message_ptr mpMessage)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -38,6 +38,10 @@
|
|||||||
#define SECTION_RPC_USER "rpc_user"
|
#define SECTION_RPC_USER "rpc_user"
|
||||||
#define SECTION_RPC_PASSWORD "rpc_password"
|
#define SECTION_RPC_PASSWORD "rpc_password"
|
||||||
#define SECTION_RPC_STARTUP "rpc_startup"
|
#define SECTION_RPC_STARTUP "rpc_startup"
|
||||||
|
#define SECTION_RPC_SECURE "rpc_secure"
|
||||||
|
#define SECTION_RPC_SSL_CERT "rpc_ssl_cert"
|
||||||
|
#define SECTION_RPC_SSL_CHAIN "rpc_ssl_chain"
|
||||||
|
#define SECTION_RPC_SSL_KEY "rpc_ssl_key"
|
||||||
#define SECTION_SMS_FROM "sms_from"
|
#define SECTION_SMS_FROM "sms_from"
|
||||||
#define SECTION_SMS_KEY "sms_key"
|
#define SECTION_SMS_KEY "sms_key"
|
||||||
#define SECTION_SMS_SECRET "sms_secret"
|
#define SECTION_SMS_SECRET "sms_secret"
|
||||||
@@ -198,6 +202,7 @@ Config::Config()
|
|||||||
|
|
||||||
PEER_PORT = SYSTEM_PEER_PORT;
|
PEER_PORT = SYSTEM_PEER_PORT;
|
||||||
RPC_PORT = 5001;
|
RPC_PORT = 5001;
|
||||||
|
RPC_SECURE = 0;
|
||||||
WEBSOCKET_PORT = SYSTEM_WEBSOCKET_PORT;
|
WEBSOCKET_PORT = SYSTEM_WEBSOCKET_PORT;
|
||||||
WEBSOCKET_PUBLIC_PORT = SYSTEM_WEBSOCKET_PUBLIC_PORT;
|
WEBSOCKET_PUBLIC_PORT = SYSTEM_WEBSOCKET_PUBLIC_PORT;
|
||||||
WEBSOCKET_PUBLIC_SECURE = 1;
|
WEBSOCKET_PUBLIC_SECURE = 1;
|
||||||
@@ -408,6 +413,13 @@ void Config::load()
|
|||||||
sectionSingleB(secConfig, SECTION_WEBSOCKET_SSL_CHAIN, WEBSOCKET_SSL_CHAIN);
|
sectionSingleB(secConfig, SECTION_WEBSOCKET_SSL_CHAIN, WEBSOCKET_SSL_CHAIN);
|
||||||
sectionSingleB(secConfig, SECTION_WEBSOCKET_SSL_KEY, WEBSOCKET_SSL_KEY);
|
sectionSingleB(secConfig, SECTION_WEBSOCKET_SSL_KEY, WEBSOCKET_SSL_KEY);
|
||||||
|
|
||||||
|
if (sectionSingleB(secConfig, SECTION_RPC_SECURE, strTemp))
|
||||||
|
RPC_SECURE = boost::lexical_cast<int>(strTemp);
|
||||||
|
sectionSingleB(secConfig, SECTION_RPC_SSL_CERT, RPC_SSL_CERT);
|
||||||
|
sectionSingleB(secConfig, SECTION_RPC_SSL_CHAIN, RPC_SSL_CHAIN);
|
||||||
|
sectionSingleB(secConfig, SECTION_RPC_SSL_KEY, RPC_SSL_KEY);
|
||||||
|
|
||||||
|
|
||||||
sectionSingleB(secConfig, SECTION_SSL_VERIFY_FILE, SSL_VERIFY_FILE);
|
sectionSingleB(secConfig, SECTION_SSL_VERIFY_FILE, SSL_VERIFY_FILE);
|
||||||
sectionSingleB(secConfig, SECTION_SSL_VERIFY_DIR, SSL_VERIFY_DIR);
|
sectionSingleB(secConfig, SECTION_SSL_VERIFY_DIR, SSL_VERIFY_DIR);
|
||||||
if (sectionSingleB(secConfig, SECTION_SSL_VERIFY, strTemp))
|
if (sectionSingleB(secConfig, SECTION_SSL_VERIFY, strTemp))
|
||||||
|
|||||||
@@ -137,6 +137,11 @@ public:
|
|||||||
bool RPC_ALLOW_REMOTE;
|
bool RPC_ALLOW_REMOTE;
|
||||||
Json::Value RPC_STARTUP;
|
Json::Value RPC_STARTUP;
|
||||||
|
|
||||||
|
int RPC_SECURE;
|
||||||
|
std::string RPC_SSL_CERT;
|
||||||
|
std::string RPC_SSL_CHAIN;
|
||||||
|
std::string RPC_SSL_KEY;
|
||||||
|
|
||||||
// Path searching
|
// Path searching
|
||||||
int PATH_SEARCH_SIZE;
|
int PATH_SEARCH_SIZE;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user