Support secure RPC.

This commit is contained in:
JoelKatz
2013-06-12 12:49:27 -07:00
parent 353b0a30b5
commit 4de1dcae5e
7 changed files with 58 additions and 29 deletions

View File

@@ -7,11 +7,18 @@ SETUP_LOG (RPCDoor)
using namespace std;
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) :
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;
if (theConfig.RPC_SECURE != 0)
initSSLContext(mSSLContext, theConfig.RPC_SSL_KEY, theConfig.RPC_SSL_CERT, theConfig.RPC_SSL_CHAIN);
startListening();
}
@@ -22,10 +29,10 @@ RPCDoor::~RPCDoor()
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.async_accept(new_connection->getSocket(),
mAcceptor.async_accept(new_connection->getRawSocket(),
boost::bind(&RPCDoor::handleConnect, this, new_connection,
boost::asio::placeholders::error));
}
@@ -41,8 +48,7 @@ bool RPCDoor::isClientAllowed(const std::string& ip)
return false;
}
void RPCDoor::handleConnect(RPCServer::pointer new_connection,
const boost::system::error_code& error)
void RPCDoor::handleConnect(RPCServer::pointer new_connection, const boost::system::error_code& error)
{
bool delay = false;
if (!error)
@@ -50,7 +56,7 @@ void RPCDoor::handleConnect(RPCServer::pointer new_connection,
// Restrict callers by IP
try
{
if (!isClientAllowed(new_connection->getSocket().remote_endpoint().address().to_string()))
if (!isClientAllowed(new_connection->getRawSocket().remote_endpoint().address().to_string()))
{
startListening();
return;
@@ -62,7 +68,8 @@ void RPCDoor::handleConnect(RPCServer::pointer new_connection,
return;
}
new_connection->connected();
new_connection->getSocket().async_handshake(AutoSocket::ssl_socket::server,
boost::bind(&RPCServer::connected, new_connection));
}
else
{

View File

@@ -14,8 +14,9 @@ public:
~RPCDoor ();
private:
boost::asio::ip::tcp::acceptor mAcceptor;
boost::asio::deadline_timer mDelayTimer;
boost::asio::ip::tcp::acceptor mAcceptor;
boost::asio::deadline_timer mDelayTimer;
boost::asio::ssl::context mSSLContext;
void startListening();
void handleConnect(RPCServer::pointer new_connection,

View File

@@ -18,8 +18,8 @@
SETUP_LOG (RPCServer)
RPCServer::RPCServer(boost::asio::io_service& io_service , NetworkOPs* nopNetwork)
: mNetOps(nopNetwork), mSocket(io_service)
RPCServer::RPCServer(boost::asio::io_service& io_service, boost::asio::ssl::context& context, NetworkOPs* nopNetwork)
: mNetOps(nopNetwork), mSocket(io_service, context)
{
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));
}
static void dummy_handler()
{
;
}
void RPCServer::handle_read_line(const boost::system::error_code& e)
{
if (e)
@@ -62,8 +67,7 @@ void RPCServer::handle_read_line(const boost::system::error_code& e)
if (action == haDO_REQUEST)
{ // request with no body
WriteLog (lsWARNING, RPCServer) << "RPC HTTP request with no body";
boost::system::error_code ignore_ec;
mSocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_ec);
mSocket.async_shutdown(boost::bind(&dummy_handler));
return;
}
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))
{
WriteLog (lsWARNING, RPCServer) << "Illegal RPC request length " << rLen;
boost::system::error_code ignore_ec;
mSocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_ec);
mSocket.async_shutdown(boost::bind(&dummy_handler));
return;
}
@@ -99,10 +102,7 @@ void RPCServer::handle_read_line(const boost::system::error_code& e)
}
}
else
{
boost::system::error_code ignore_ec;
mSocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_ec);
}
mSocket.async_shutdown(boost::bind(&dummy_handler));
}
std::string RPCServer::handleRequest(const std::string& requestStr)
@@ -143,7 +143,7 @@ std::string RPCServer::handleRequest(const std::string& requestStr)
try
{
mRole = iAdminGet(jvRequest, mSocket.remote_endpoint().address().to_string());
mRole = iAdminGet(jvRequest, mSocket.PlainSocket().remote_endpoint().address().to_string());
}
catch (...)
{ // endpoint already disconnected
@@ -187,10 +187,7 @@ void RPCServer::handle_write(const boost::system::error_code& e)
{
HTTPRequestAction action = mHTTPRequest.requestDone(false);
if (action == haCLOSE_CONN)
{
boost::system::error_code ignored_ec;
mSocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
}
mSocket.async_shutdown(boost::bind(&dummy_handler));
else
{
boost::asio::async_read_until(mSocket, mLineBuffer, "\r\n",

View File

@@ -15,7 +15,7 @@ private:
NetworkOPs* mNetOps;
boost::asio::ip::tcp::socket mSocket;
AutoSocket mSocket;
boost::asio::streambuf mLineBuffer;
Blob mQueryVec;
@@ -26,7 +26,7 @@ private:
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& operator=(const RPCServer&); // no implementation
@@ -38,16 +38,21 @@ private:
std::string handleRequest(const std::string& requestStr);
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;
}
boost::asio::ip::tcp::socket& getRawSocket()
{
return mSocket.PlainSocket();
}
void connected();
};

View File

@@ -54,6 +54,8 @@ public:
bool getPublic() { return mPublic; };
boost::asio::ssl::context& getASIOContext() { return *mCtx; }
static void ssend(connection_ptr cpClient, message_ptr mpMessage)
{
try

View File

@@ -38,6 +38,10 @@
#define SECTION_RPC_USER "rpc_user"
#define SECTION_RPC_PASSWORD "rpc_password"
#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_KEY "sms_key"
#define SECTION_SMS_SECRET "sms_secret"
@@ -198,6 +202,7 @@ Config::Config()
PEER_PORT = SYSTEM_PEER_PORT;
RPC_PORT = 5001;
RPC_SECURE = 0;
WEBSOCKET_PORT = SYSTEM_WEBSOCKET_PORT;
WEBSOCKET_PUBLIC_PORT = SYSTEM_WEBSOCKET_PUBLIC_PORT;
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_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_DIR, SSL_VERIFY_DIR);
if (sectionSingleB(secConfig, SECTION_SSL_VERIFY, strTemp))

View File

@@ -137,6 +137,11 @@ public:
bool RPC_ALLOW_REMOTE;
Json::Value RPC_STARTUP;
int RPC_SECURE;
std::string RPC_SSL_CERT;
std::string RPC_SSL_CHAIN;
std::string RPC_SSL_KEY;
// Path searching
int PATH_SEARCH_SIZE;