I2PControl through SSL

This commit is contained in:
orignal 2015-11-23 13:22:02 -05:00
parent d015538bb4
commit c9d03a8094
2 changed files with 34 additions and 16 deletions

View File

@ -27,15 +27,24 @@ namespace client
I2PControlService::I2PControlService (int port): I2PControlService::I2PControlService (int port):
m_Password (I2P_CONTROL_DEFAULT_PASSWORD), m_IsRunning (false), m_Thread (nullptr), m_Password (I2P_CONTROL_DEFAULT_PASSWORD), m_IsRunning (false), m_Thread (nullptr),
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)), m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
m_SSLContext (m_Service, boost::asio::ssl::context::sslv23),
m_ShutdownTimer (m_Service) m_ShutdownTimer (m_Service)
{ {
// certificate
auto path = GetPath (); auto path = GetPath ();
if (!boost::filesystem::exists (path)) if (!boost::filesystem::exists (path))
{ {
if (!boost::filesystem::create_directory (path)) if (!boost::filesystem::create_directory (path))
LogPrint (eLogError, "Failed to create i2pcontrol directory"); LogPrint (eLogError, "Failed to create i2pcontrol directory");
} }
if (!boost::filesystem::exists (path / I2P_CONTROL_KEY_FILE) ||
!boost::filesystem::exists (path / I2P_CONTROL_CERT_FILE))
// create new certificate
CreateCertificate ();
m_SSLContext.use_certificate_chain_file ((path / I2P_CONTROL_CERT_FILE).string ());
m_SSLContext.use_private_key_file ((path / I2P_CONTROL_KEY_FILE).string (), boost::asio::ssl::context::pem);
// handlers
m_MethodHandlers[I2P_CONTROL_METHOD_AUTHENTICATE] = &I2PControlService::AuthenticateHandler; m_MethodHandlers[I2P_CONTROL_METHOD_AUTHENTICATE] = &I2PControlService::AuthenticateHandler;
m_MethodHandlers[I2P_CONTROL_METHOD_ECHO] = &I2PControlService::EchoHandler; m_MethodHandlers[I2P_CONTROL_METHOD_ECHO] = &I2PControlService::EchoHandler;
m_MethodHandlers[I2P_CONTROL_METHOD_I2PCONTROL] = &I2PControlService::I2PControlHandler; m_MethodHandlers[I2P_CONTROL_METHOD_I2PCONTROL] = &I2PControlService::I2PControlHandler;
@ -108,27 +117,34 @@ namespace client
void I2PControlService::Accept () void I2PControlService::Accept ()
{ {
auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (m_Service); auto newSocket = std::make_shared<ssl_socket> (m_Service, m_SSLContext);
m_Acceptor.async_accept (*newSocket, std::bind (&I2PControlService::HandleAccept, this, m_Acceptor.async_accept (newSocket->lowest_layer(), std::bind (&I2PControlService::HandleAccept, this,
std::placeholders::_1, newSocket)); std::placeholders::_1, newSocket));
} }
void I2PControlService::HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket) void I2PControlService::HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket)
{ {
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
Accept (); Accept ();
if (!ecode) if (!ecode)
{ {
LogPrint (eLogInfo, "New I2PControl request from ", socket->remote_endpoint ()); LogPrint (eLogInfo, "New I2PControl request from ", socket->lowest_layer ().remote_endpoint ());
std::this_thread::sleep_for (std::chrono::milliseconds(5)); boost::system::error_code ec;
ReadRequest (socket); socket->handshake (boost::asio::ssl::stream_base::client, ec);
if (!ec)
{
std::this_thread::sleep_for (std::chrono::milliseconds(5));
ReadRequest (socket);
}
else
LogPrint (eLogError, "I2PControl handshake error: ", ecode.message ());
} }
else else
LogPrint (eLogError, "I2PControl accept error: ", ecode.message ()); LogPrint (eLogError, "I2PControl accept error: ", ecode.message ());
} }
void I2PControlService::ReadRequest (std::shared_ptr<boost::asio::ip::tcp::socket> socket) void I2PControlService::ReadRequest (std::shared_ptr<ssl_socket> socket)
{ {
auto request = std::make_shared<I2PControlBuffer>(); auto request = std::make_shared<I2PControlBuffer>();
socket->async_read_some ( socket->async_read_some (
@ -142,7 +158,7 @@ namespace client
} }
void I2PControlService::HandleRequestReceived (const boost::system::error_code& ecode, void I2PControlService::HandleRequestReceived (const boost::system::error_code& ecode,
size_t bytes_transferred, std::shared_ptr<boost::asio::ip::tcp::socket> socket, size_t bytes_transferred, std::shared_ptr<ssl_socket> socket,
std::shared_ptr<I2PControlBuffer> buf) std::shared_ptr<I2PControlBuffer> buf)
{ {
if (ecode) if (ecode)
@ -218,7 +234,7 @@ namespace client
ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value; ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value;
} }
void I2PControlService::SendResponse (std::shared_ptr<boost::asio::ip::tcp::socket> socket, void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket,
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml) std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml)
{ {
size_t len = response.str ().length (), offset = 0; size_t len = response.str ().length (), offset = 0;
@ -245,11 +261,10 @@ namespace client
} }
void I2PControlService::HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, void I2PControlService::HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred,
std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<I2PControlBuffer> buf) std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf)
{ {
if (ecode) if (ecode)
LogPrint (eLogError, "I2PControl write error: ", ecode.message ()); LogPrint (eLogError, "I2PControl write error: ", ecode.message ());
socket->close ();
} }
// handlers // handlers

View File

@ -10,6 +10,7 @@
#include <map> #include <map>
#include <set> #include <set>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include "util.h" #include "util.h"
@ -74,6 +75,7 @@ namespace client
class I2PControlService class I2PControlService
{ {
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
public: public:
I2PControlService (int port); I2PControlService (int port);
@ -86,14 +88,14 @@ namespace client
void Run (); void Run ();
void Accept (); void Accept ();
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket); void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket);
void ReadRequest (std::shared_ptr<boost::asio::ip::tcp::socket> socket); void ReadRequest (std::shared_ptr<ssl_socket> socket);
void HandleRequestReceived (const boost::system::error_code& ecode, size_t bytes_transferred, void HandleRequestReceived (const boost::system::error_code& ecode, size_t bytes_transferred,
std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<I2PControlBuffer> buf); std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf);
void SendResponse (std::shared_ptr<boost::asio::ip::tcp::socket> socket, void SendResponse (std::shared_ptr<ssl_socket> socket,
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml); std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml);
void HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, void HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred,
std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<I2PControlBuffer> buf); std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf);
boost::filesystem::path GetPath () const { return i2p::util::filesystem::GetDefaultDataDir() / I2P_CONTROL_PATH; }; boost::filesystem::path GetPath () const { return i2p::util::filesystem::GetDefaultDataDir() / I2P_CONTROL_PATH; };
void CreateCertificate (); void CreateCertificate ();
@ -147,6 +149,7 @@ namespace client
boost::asio::io_service m_Service; boost::asio::io_service m_Service;
boost::asio::ip::tcp::acceptor m_Acceptor; boost::asio::ip::tcp::acceptor m_Acceptor;
boost::asio::ssl::context m_SSLContext;
boost::asio::deadline_timer m_ShutdownTimer; boost::asio::deadline_timer m_ShutdownTimer;
std::set<std::string> m_Tokens; std::set<std::string> m_Tokens;