diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj index d3ab2c7e53..6af88cb577 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj +++ b/Builds/VisualStudio2012/RippleD.vcxproj @@ -31,12 +31,6 @@ true true - - true - true - true - true - true true @@ -1371,7 +1365,6 @@ - diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters index 78b06af64d..a8f2710c79 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters @@ -849,9 +849,6 @@ [1] Ripple\ripple_app\boost - - [1] Ripple\ripple_app\boost - [1] Ripple\ripple_asio\sockets @@ -1619,9 +1616,6 @@ [1] Ripple\ripple_app\boost - - [1] Ripple\ripple_app\boost - [1] Ripple\ripple_basics\utility diff --git a/modules/ripple_app/boost/ripple_SslContext.cpp b/modules/ripple_app/boost/ripple_SslContext.cpp deleted file mode 100644 index e3f66260b5..0000000000 --- a/modules/ripple_app/boost/ripple_SslContext.cpp +++ /dev/null @@ -1,110 +0,0 @@ -//------------------------------------------------------------------------------ -/* - Copyright (c) 2011-2013, OpenCoin, Inc. -*/ -//============================================================================== - -namespace basio -{ - -SslContext* SslContext::New () -{ - return new SslContext; -} - -SslContext::~SslContext () -{ -} - -SslContext::operator boost::asio::ssl::context& () -{ - return *m_impl; -} - -SslContext::SslContext () - : m_impl (new boost::asio::ssl::context (boost::asio::ssl::context::sslv23)) -{ -} - -// VFALCO TODO Can we call this function from the ctor of PeerDoor as well? -// Or can we move the common code to a new function? -// -void SslContext::initializeFromFile ( - boost::asio::ssl::context& context, - std::string key_file, - std::string cert_file, - std::string chain_file) -{ - SSL_CTX* sslContext = context.native_handle (); - - context.set_options (boost::asio::ssl::context::default_workarounds | - boost::asio::ssl::context::no_sslv2 | - boost::asio::ssl::context::single_dh_use); - - bool cert_set = false; - - if (!cert_file.empty ()) - { - boost::system::error_code error; - context.use_certificate_file (cert_file, boost::asio::ssl::context::pem, error); - - if (error) - throw std::runtime_error ("Unable to use certificate file"); - - cert_set = true; - } - - if (!chain_file.empty ()) - { - // VFALCO Replace fopen() with RAII - FILE* f = fopen (chain_file.c_str (), "r"); - - if (!f) - throw std::runtime_error ("Unable to open chain file"); - - try - { - for (;;) - { - X509* x = PEM_read_X509 (f, NULL, NULL, NULL); - - if (x == NULL) - break; - - if (!cert_set) - { - if (SSL_CTX_use_certificate (sslContext, x) != 1) - throw std::runtime_error ("Unable to get certificate from chain file"); - - cert_set = true; - } - else if (SSL_CTX_add_extra_chain_cert (sslContext, x) != 1) - { - X509_free (x); - throw std::runtime_error ("Unable to add chain certificate"); - } - } - - fclose (f); - } - catch (...) - { - fclose (f); - throw; - } - } - - if (!key_file.empty ()) - { - boost::system::error_code error; - context.use_private_key_file (key_file, boost::asio::ssl::context::pem, error); - - if (error) - throw std::runtime_error ("Unable to use private key file"); - } - - if (SSL_CTX_check_private_key (sslContext) != 1) - throw std::runtime_error ("Private key not valid"); -} - -} diff --git a/modules/ripple_app/boost/ripple_SslContext.h b/modules/ripple_app/boost/ripple_SslContext.h deleted file mode 100644 index f19c01f707..0000000000 --- a/modules/ripple_app/boost/ripple_SslContext.h +++ /dev/null @@ -1,39 +0,0 @@ -//------------------------------------------------------------------------------ -/* - Copyright (c) 2011-2013, OpenCoin, Inc. -*/ -//============================================================================== - -#ifndef RIPPLE_SSLCONTEXT_H_INCLUDED -#define RIPPLE_SSLCONTEXT_H_INCLUDED - -namespace basio -{ - -/** Hides a boost::asio::ssl::context implementation. -*/ -class SslContext -{ -public: - static SslContext* New (); - - virtual ~SslContext (); - - operator boost::asio::ssl::context& (); - - static void initializeFromFile ( - boost::asio::ssl::context& context, - std::string key_file, - std::string cert_file, - std::string chain_file); - -private: - SslContext (); - -private: - beast::ScopedPointer m_impl; -}; - -} - -#endif diff --git a/modules/ripple_app/main/ripple_Application.cpp b/modules/ripple_app/main/ripple_Application.cpp index 7d233a5622..1ea5327085 100644 --- a/modules/ripple_app/main/ripple_Application.cpp +++ b/modules/ripple_app/main/ripple_Application.cpp @@ -577,7 +577,7 @@ public: } else { - m_wsSSLContext = RippleSSLContext::createBare (); + m_wsSSLContext = RippleSSLContext::createWebSocket (); } // Create private listening WebSocket socket @@ -627,7 +627,7 @@ public: { try { - mRPCDoor = new RPCDoor (m_mainService, m_rpcServerHandler); + mRPCDoor = RPCDoor::New (m_mainService, m_rpcServerHandler); } catch (const std::exception& e) { diff --git a/modules/ripple_app/ripple_app.cpp b/modules/ripple_app/ripple_app.cpp index 436bf6d74b..39b0bd5f7d 100644 --- a/modules/ripple_app/ripple_app.cpp +++ b/modules/ripple_app/ripple_app.cpp @@ -158,7 +158,6 @@ namespace ripple #include "main/ripple_LocalCredentials.h" #include "websocket/WSDoor.h" #include "boost/ripple_IoService.h" - #include "boost/ripple_SslContext.h" #include "main/ripple_Application.h" #include "rpc/RPCHandler.h" #include "tx/TransactionQueue.h" @@ -296,7 +295,6 @@ static const uint64 tenTo17m1 = tenTo17 - 1; #include "data/ripple_DBInit.cpp" #include "boost/ripple_IoService.cpp" -#include "boost/ripple_SslContext.cpp" #endif @@ -334,7 +332,6 @@ static const uint64 tenTo17m1 = tenTo17 - 1; #include "tx/PaymentTransactor.cpp" #include "tx/RegularKeySetTransactor.cpp" #include "paths/ripple_RippleState.cpp" -#include "rpc/RPCDoor.cpp" #include "tx/TransactionCheck.cpp" #include "tx/TransactionMaster.cpp" #include "tx/TransactionQueue.cpp" @@ -354,16 +351,16 @@ static const uint64 tenTo17m1 = tenTo17 - 1; namespace ripple { -#include "peers/ripple_Peer.cpp" -#include "main/ripple_Application.cpp" -#include "tx/OfferCreateTransactor.cpp" -#include "misc/ripple_Validations.cpp" - -#include "main/ripple_LocalCredentials.cpp" -#include "tx/WalletAddTransactor.cpp" -#include "ledger/ripple_AcceptedLedgerTx.cpp" -#include "misc/ripple_FeeVote.cpp" #include "ledger/LedgerTiming.cpp" +#include "ledger/ripple_AcceptedLedgerTx.cpp" +#include "main/ripple_Application.cpp" +#include "main/ripple_LocalCredentials.cpp" +#include "misc/ripple_FeeVote.cpp" +#include "misc/ripple_Validations.cpp" +#include "peers/ripple_Peer.cpp" +#include "rpc/RPCDoor.cpp" +#include "tx/OfferCreateTransactor.cpp" +#include "tx/WalletAddTransactor.cpp" #endif diff --git a/modules/ripple_app/rpc/RPCDoor.cpp b/modules/ripple_app/rpc/RPCDoor.cpp index cb2233ddff..5997725b9a 100644 --- a/modules/ripple_app/rpc/RPCDoor.cpp +++ b/modules/ripple_app/rpc/RPCDoor.cpp @@ -6,96 +6,123 @@ SETUP_LOG (RPCDoor) -RPCDoor::RPCDoor (boost::asio::io_service& io_service, RPCServer::Handler& handler) - : m_rpcServerHandler (handler) - , mAcceptor (io_service, - boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string (getConfig ().getRpcIP ()), getConfig ().getRpcPort ())) - , mDelayTimer (io_service) - , mSSLContext (boost::asio::ssl::context::sslv23) +class RPCDoorImp : public RPCDoor, public LeakChecked { - WriteLog (lsINFO, RPCDoor) << "RPC port: " << getConfig ().getRpcAddress().toRawUTF8() << " allow remote: " << getConfig ().RPC_ALLOW_REMOTE; - - if (getConfig ().RPC_SECURE != 0) +public: + RPCDoorImp (boost::asio::io_service& io_service, RPCServer::Handler& handler) + : m_rpcServerHandler (handler) + , mAcceptor (io_service, + boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string (getConfig ().getRpcIP ()), getConfig ().getRpcPort ())) + , mDelayTimer (io_service) + , m_sslContext ((getConfig ().RPC_SECURE == 0) ? + RippleSSLContext::createBare () : + RippleSSLContext::createAuthenticated ( + getConfig ().RPC_SSL_KEY, + getConfig ().RPC_SSL_CERT, + getConfig ().RPC_SSL_CHAIN)) { - // VFALCO TODO This could be a method of theConfig - // - basio::SslContext::initializeFromFile ( - mSSLContext, - getConfig ().RPC_SSL_KEY, - getConfig ().RPC_SSL_CERT, - getConfig ().RPC_SSL_CHAIN); + WriteLog (lsINFO, RPCDoor) << "RPC port: " << getConfig ().getRpcAddress().toRawUTF8() << " allow remote: " << getConfig ().RPC_ALLOW_REMOTE; + + startListening (); } - startListening (); -} + //-------------------------------------------------------------------------- -RPCDoor::~RPCDoor () -{ - WriteLog (lsINFO, RPCDoor) << "RPC port: " << getConfig ().getRpcAddress().toRawUTF8() << " allow remote: " << getConfig ().RPC_ALLOW_REMOTE; -} - -void RPCDoor::startListening () -{ - RPCServer::pointer new_connection = RPCServer::New (mAcceptor.get_io_service (), mSSLContext, m_rpcServerHandler); - mAcceptor.set_option (boost::asio::ip::tcp::acceptor::reuse_address (true)); - - mAcceptor.async_accept (new_connection->getRawSocket (), - boost::bind (&RPCDoor::handleConnect, this, new_connection, - boost::asio::placeholders::error)); -} - -bool RPCDoor::isClientAllowed (const std::string& ip) -{ - if (getConfig ().RPC_ALLOW_REMOTE) - return true; - - // VFALCO TODO Represent ip addresses as a structure. Use isLoopback() member here - // - if (ip == "127.0.0.1") - return true; - - return false; -} - -void RPCDoor::handleConnect (RPCServer::pointer new_connection, const boost::system::error_code& error) -{ - bool delay = false; - - if (!error) + ~RPCDoorImp () { - // Restrict callers by IP - try + WriteLog (lsINFO, RPCDoor) << + "RPC port: " << getConfig ().getRpcAddress().toRawUTF8() << + " allow remote: " << getConfig ().RPC_ALLOW_REMOTE; + } + + //-------------------------------------------------------------------------- + + void startListening () + { + RPCServer::pointer new_connection = RPCServer::New ( + mAcceptor.get_io_service (), m_sslContext->get (), m_rpcServerHandler); + + mAcceptor.set_option (boost::asio::ip::tcp::acceptor::reuse_address (true)); + + mAcceptor.async_accept (new_connection->getRawSocket (), + boost::bind (&RPCDoorImp::handleConnect, this, new_connection, + boost::asio::placeholders::error)); + } + + //-------------------------------------------------------------------------- + + bool isClientAllowed (const std::string& ip) + { + if (getConfig ().RPC_ALLOW_REMOTE) + return true; + + // VFALCO TODO Represent ip addresses as a structure. Use isLoopback() member here + // + if (ip == "127.0.0.1") + return true; + + return false; + } + + //-------------------------------------------------------------------------- + + void handleConnect (RPCServer::pointer new_connection, boost::system::error_code const& error) + { + bool delay = false; + + if (!error) { - if (! isClientAllowed (new_connection->getRemoteAddressText ())) + // Restrict callers by IP + // VFALCO NOTE Prevent exceptions from being thrown at all. + try { + if (! isClientAllowed (new_connection->getRemoteAddressText ())) + { + startListening (); + return; + } + } + catch (...) + { + // client may have disconnected startListening (); return; } + + new_connection->getSocket ().async_handshake (AutoSocket::ssl_socket::server, + boost::bind (&RPCServer::connected, new_connection)); } - catch (...) + else { - // client may have disconnected - startListening (); - return; + if (error == boost::system::errc::too_many_files_open) + delay = true; + + WriteLog (lsINFO, RPCDoor) << "RPCDoorImp::handleConnect Error: " << error; } - new_connection->getSocket ().async_handshake (AutoSocket::ssl_socket::server, - boost::bind (&RPCServer::connected, new_connection)); - } - else - { - if (error == boost::system::errc::too_many_files_open) - delay = true; - - WriteLog (lsINFO, RPCDoor) << "RPCDoor::handleConnect Error: " << error; + if (delay) + { + mDelayTimer.expires_from_now (boost::posix_time::milliseconds (1000)); + mDelayTimer.async_wait (boost::bind (&RPCDoorImp::startListening, this)); + } + else + { + startListening (); + } } - if (delay) - { - mDelayTimer.expires_from_now (boost::posix_time::milliseconds (1000)); - mDelayTimer.async_wait (boost::bind (&RPCDoor::startListening, this)); - } - else - startListening (); +private: + RPCServer::Handler& m_rpcServerHandler; + boost::asio::ip::tcp::acceptor mAcceptor; + boost::asio::deadline_timer mDelayTimer; + ScopedPointer m_sslContext; +}; + +//------------------------------------------------------------------------------ + +RPCDoor* RPCDoor::New (boost::asio::io_service& io_service, RPCServer::Handler& handler) +{ + ScopedPointer result (new RPCDoorImp (io_service, handler)); + + return result.release (); } -// vim:ts=4 diff --git a/modules/ripple_app/rpc/RPCDoor.h b/modules/ripple_app/rpc/RPCDoor.h index c9d1562e69..4990da43b4 100644 --- a/modules/ripple_app/rpc/RPCDoor.h +++ b/modules/ripple_app/rpc/RPCDoor.h @@ -7,29 +7,14 @@ #ifndef RIPPLE_RPCDOOR_H #define RIPPLE_RPCDOOR_H -/* -Handles incoming connections from people making RPC Requests +/** Listening socket for RPC requests. */ - -class RPCDoor : LeakChecked +class RPCDoor { public: - explicit RPCDoor ( - boost::asio::io_service& io_service, - RPCServer::Handler& handler); - ~RPCDoor (); + static RPCDoor* New (boost::asio::io_service& io_service, RPCServer::Handler& handler); -private: - RPCServer::Handler& m_rpcServerHandler; - boost::asio::ip::tcp::acceptor mAcceptor; - boost::asio::deadline_timer mDelayTimer; - boost::asio::ssl::context mSSLContext; - - void startListening (); - void handleConnect (RPCServer::pointer new_connection, - const boost::system::error_code& error); - - bool isClientAllowed (const std::string& ip); + virtual ~RPCDoor () { } }; #endif diff --git a/modules/ripple_asio/sockets/RippleSSLContext.cpp b/modules/ripple_asio/sockets/RippleSSLContext.cpp index 0ef7159c3f..1dd1dbcce5 100644 --- a/modules/ripple_asio/sockets/RippleSSLContext.cpp +++ b/modules/ripple_asio/sockets/RippleSSLContext.cpp @@ -14,14 +14,6 @@ public: : RippleSSLContext (m_context) , m_context (boost::asio::ssl::context::sslv23) { - m_context.set_options ( - boost::asio::ssl::context::default_workarounds | - boost::asio::ssl::context::no_sslv2 | - boost::asio::ssl::context::single_dh_use); - - SSL_CTX_set_tmp_dh_callback ( - m_context.native_handle (), - tmp_dh_handler); } ~RippleSSLContextImp () @@ -70,8 +62,25 @@ public: //-------------------------------------------------------------------------- + // Does common initialization for all but the bare context type. + void initCommon () + { + m_context.set_options ( + boost::asio::ssl::context::default_workarounds | + boost::asio::ssl::context::no_sslv2 | + boost::asio::ssl::context::single_dh_use); + + SSL_CTX_set_tmp_dh_callback ( + m_context.native_handle (), + tmp_dh_handler); + } + + //-------------------------------------------------------------------------- + void initAnonymous (String const& cipherList) { + initCommon (); + int const result = SSL_CTX_set_cipher_list ( m_context.native_handle (), cipherList.toStdString ().c_str ()); @@ -85,6 +94,8 @@ public: void initAuthenticated ( std::string key_file, std::string cert_file, std::string chain_file) { + initCommon (); + SSL_CTX* const ssl = m_context.native_handle (); bool cert_set = false; @@ -241,6 +252,7 @@ RippleSSLContext::RippleSSLContext (ContextType& context) : SSLContext (context) { } + RippleSSLContext* RippleSSLContext::createBare () { ScopedPointer context (new RippleSSLContextImp ()); @@ -248,6 +260,15 @@ RippleSSLContext* RippleSSLContext::createBare () return context.release (); } +RippleSSLContext* RippleSSLContext::createWebSocket () +{ + ScopedPointer context (new RippleSSLContextImp ()); + + context->initCommon (); + + return context.release (); +} + RippleSSLContext* RippleSSLContext::createAnonymous (String const& cipherList) { ScopedPointer context (new RippleSSLContextImp ()); diff --git a/modules/ripple_asio/sockets/RippleSSLContext.h b/modules/ripple_asio/sockets/RippleSSLContext.h index 6310450b47..48f7ff47d2 100644 --- a/modules/ripple_asio/sockets/RippleSSLContext.h +++ b/modules/ripple_asio/sockets/RippleSSLContext.h @@ -25,11 +25,16 @@ public: */ static std::string getRawDHParams (int keySize); - /** Creates a bare context. - This is for WebSocket connections that don't use certificates. + /** Creates a bare SSL context with just sslv23 set. + This is used for RPC connections. */ static RippleSSLContext* createBare (); + /** Creates a suitable for WebSocket without authentication. + This is for WebSocket connections that don't use certificates. + */ + static RippleSSLContext* createWebSocket (); + /** Create a context that allows anonymous connections. No certificates are required. Peers use this context. If the cipher list is invalid, a fatal error is raised.