diff --git a/src/cpp/ripple/RPCDoor.cpp b/src/cpp/ripple/RPCDoor.cpp index 9033681e51..62f3b1a49b 100644 --- a/src/cpp/ripple/RPCDoor.cpp +++ b/src/cpp/ripple/RPCDoor.cpp @@ -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 { diff --git a/src/cpp/ripple/RPCDoor.h b/src/cpp/ripple/RPCDoor.h index ddb6a97684..5b86a104b8 100644 --- a/src/cpp/ripple/RPCDoor.h +++ b/src/cpp/ripple/RPCDoor.h @@ -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, diff --git a/src/cpp/ripple/RPCServer.cpp b/src/cpp/ripple/RPCServer.cpp index bdb374036b..8336df025f 100644 --- a/src/cpp/ripple/RPCServer.cpp +++ b/src/cpp/ripple/RPCServer.cpp @@ -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", diff --git a/src/cpp/ripple/RPCServer.h b/src/cpp/ripple/RPCServer.h index 5bf2e0898b..7855144185 100644 --- a/src/cpp/ripple/RPCServer.h +++ b/src/cpp/ripple/RPCServer.h @@ -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(); }; diff --git a/src/cpp/ripple/WSHandler.h b/src/cpp/ripple/WSHandler.h index 17fdad72bd..4a15da9a4e 100644 --- a/src/cpp/ripple/WSHandler.h +++ b/src/cpp/ripple/WSHandler.h @@ -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 diff --git a/src/cpp/ripple/ripple_Config.cpp b/src/cpp/ripple/ripple_Config.cpp index 6cd103f10e..0d29503b7f 100644 --- a/src/cpp/ripple/ripple_Config.cpp +++ b/src/cpp/ripple/ripple_Config.cpp @@ -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(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)) diff --git a/src/cpp/ripple/ripple_Config.h b/src/cpp/ripple/ripple_Config.h index 998c6a1b14..1cc23b4f6d 100644 --- a/src/cpp/ripple/ripple_Config.h +++ b/src/cpp/ripple/ripple_Config.h @@ -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;