mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Add basic ssl support for peer connections.
This commit is contained in:
@@ -8,10 +8,17 @@
|
||||
#include "Application.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
ConnectionPool::ConnectionPool() :
|
||||
iConnecting(0)
|
||||
{ ; }
|
||||
iConnecting(0),
|
||||
mCtx(boost::asio::ssl::context::sslv23)
|
||||
{
|
||||
mCtx.set_options(
|
||||
boost::asio::ssl::context::default_workarounds
|
||||
| boost::asio::ssl::context::no_sslv2
|
||||
| boost::asio::ssl::context::single_dh_use);
|
||||
|
||||
SSL_CTX_set_cipher_list(mCtx.native_handle(), "ALL:!LOW:!EXP:!MD5:@STRENGTH");
|
||||
}
|
||||
|
||||
|
||||
void ConnectionPool::start()
|
||||
@@ -80,7 +87,7 @@ bool ConnectionPool::connectTo(const std::string& strIp, int iPort)
|
||||
std::cerr << "ConnectionPool::connectTo: Connectting: "
|
||||
<< strIp << " " << iPort << std::endl;
|
||||
|
||||
Peer::pointer peer(Peer::create(theApp->getIOService()));
|
||||
Peer::pointer peer(Peer::create(theApp->getIOService(), mCtx));
|
||||
|
||||
mIpMap[ip] = peer;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef __CONNECTION_POOL__
|
||||
#define __CONNECTION_POOL__
|
||||
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include "Peer.h"
|
||||
@@ -27,6 +28,8 @@ private:
|
||||
// Non-thin peers which we are connected to.
|
||||
boost::unordered_map<NewcoinAddress, Peer::pointer> mConnectedMap;
|
||||
|
||||
boost::asio::ssl::context mCtx;
|
||||
|
||||
public:
|
||||
ConnectionPool();
|
||||
|
||||
|
||||
89
src/Peer.cpp
89
src/Peer.cpp
@@ -16,10 +16,8 @@
|
||||
#include "SerializedTransaction.h"
|
||||
#include "utils.h"
|
||||
|
||||
Peer::Peer(boost::asio::io_service& io_service)
|
||||
: mSocket(io_service),
|
||||
mCtx(boost::asio::ssl::context::sslv23),
|
||||
mSocketSsl(io_service, mCtx)
|
||||
Peer::Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx)
|
||||
: mSocketSsl(io_service, ctx)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -54,7 +52,7 @@ void Peer::handle_write(const boost::system::error_code& error, size_t bytes_tra
|
||||
void Peer::detach()
|
||||
{
|
||||
mSendQ.clear();
|
||||
mSocket.close();
|
||||
// mSocketSsl.close();
|
||||
|
||||
if (!mIpPort.first.empty()) {
|
||||
theApp->getConnectionPool().peerDisconnected(shared_from_this());
|
||||
@@ -86,30 +84,33 @@ void Peer::connect(const std::string strIp, int iPort)
|
||||
else
|
||||
{
|
||||
std::cerr << "Peer::connect: Connectting: " << mIpPort.first << " " << mIpPort.second << std::endl;
|
||||
#if 1
|
||||
boost::asio::async_connect(
|
||||
mSocket,
|
||||
itrEndpoint,
|
||||
boost::bind(
|
||||
&Peer::handleConnect,
|
||||
shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::iterator));
|
||||
#else
|
||||
// Connect via ssl.
|
||||
// XXX Why doesn't handler need an iterator?
|
||||
|
||||
boost::asio::async_connect(
|
||||
mSocketSsl.lowest_layer(),
|
||||
itrEndpoint,
|
||||
boost::bind(
|
||||
&Peer::handleConnect,
|
||||
shared_from_this(),
|
||||
boost::asio::placeholders::error));
|
||||
#endif
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::iterator));
|
||||
}
|
||||
}
|
||||
|
||||
// SSL connection.
|
||||
void Peer::handleStart(const boost::system::error_code& error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
std::cout << "Peer::handleStart: failed:" << error << std::endl;
|
||||
detach();
|
||||
}
|
||||
else
|
||||
{
|
||||
start_read_header();
|
||||
sendHello();
|
||||
}
|
||||
}
|
||||
|
||||
// Connect as client.
|
||||
void Peer::handleConnect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it)
|
||||
{
|
||||
if (error)
|
||||
@@ -121,15 +122,23 @@ void Peer::handleConnect(const boost::system::error_code& error, boost::asio::ip
|
||||
{
|
||||
std::cout << "Socket Connected." << std::endl;
|
||||
|
||||
start_read_header();
|
||||
sendHello();
|
||||
mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true));
|
||||
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none);
|
||||
|
||||
// XXX Do what?
|
||||
// mSocketSsl.set_verify_callback(boost::asio::ssl::rfc2818_verification(mDeqSites[0]), mShutdown);
|
||||
|
||||
mSocketSsl.async_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::client,
|
||||
boost::bind(&Peer::handleStart,
|
||||
shared_from_this(),
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
}
|
||||
|
||||
// Peer connected via door.
|
||||
// Connect as server.
|
||||
void Peer::connected(const boost::system::error_code& error)
|
||||
{
|
||||
boost::asio::ip::tcp::endpoint ep = mSocket.remote_endpoint();
|
||||
boost::asio::ip::tcp::endpoint ep = mSocketSsl.lowest_layer().remote_endpoint();
|
||||
int iPort = ep.port();
|
||||
std::string strIp = ep.address().to_string();
|
||||
|
||||
@@ -158,15 +167,23 @@ void Peer::connected(const boost::system::error_code& error)
|
||||
|
||||
mIpPort = make_pair(strIp, iPort);
|
||||
|
||||
start_read_header();
|
||||
sendHello();
|
||||
mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true));
|
||||
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none);
|
||||
|
||||
// XXX Do what?
|
||||
// mSocketSsl.set_verify_callback(boost::asio::ssl::rfc2818_verification(mDeqSites[0]), mShutdown);
|
||||
|
||||
mSocketSsl.async_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::server,
|
||||
boost::bind(&Peer::handleStart,
|
||||
shared_from_this(),
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
}
|
||||
|
||||
void Peer::sendPacketForce(PackedMessage::pointer packet)
|
||||
{
|
||||
mSendingPacket=packet;
|
||||
boost::asio::async_write(mSocket, boost::asio::buffer(packet->getBuffer()),
|
||||
boost::asio::async_write(mSocketSsl, boost::asio::buffer(packet->getBuffer()),
|
||||
boost::bind(&Peer::handle_write, shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
@@ -194,7 +211,7 @@ void Peer::start_read_header()
|
||||
#endif
|
||||
mReadbuf.clear();
|
||||
mReadbuf.resize(HEADER_SIZE);
|
||||
boost::asio::async_read(mSocket, boost::asio::buffer(mReadbuf),
|
||||
boost::asio::async_read(mSocketSsl, boost::asio::buffer(mReadbuf),
|
||||
boost::bind(&Peer::handle_read_header, shared_from_this(), boost::asio::placeholders::error));
|
||||
}
|
||||
|
||||
@@ -205,13 +222,13 @@ void Peer::start_read_body(unsigned msg_len)
|
||||
// read into the body.
|
||||
//
|
||||
mReadbuf.resize(HEADER_SIZE + msg_len);
|
||||
boost::asio::async_read(mSocket, boost::asio::buffer(&mReadbuf[HEADER_SIZE], msg_len),
|
||||
boost::asio::async_read(mSocketSsl, boost::asio::buffer(&mReadbuf[HEADER_SIZE], msg_len),
|
||||
boost::bind(&Peer::handle_read_body, shared_from_this(), boost::asio::placeholders::error));
|
||||
}
|
||||
|
||||
void Peer::handle_read_header(const boost::system::error_code& error)
|
||||
{
|
||||
if(!error)
|
||||
if (!error)
|
||||
{
|
||||
unsigned msg_len = PackedMessage::getLength(mReadbuf);
|
||||
// WRITEME: Compare to maximum message length, abort if too large
|
||||
@@ -225,13 +242,13 @@ void Peer::handle_read_header(const boost::system::error_code& error)
|
||||
else
|
||||
{
|
||||
detach();
|
||||
std::cout << "Peer::connected Error: " << error << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
||||
std::cout << "Peer::handle_read_header: Error: " << error << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
||||
}
|
||||
}
|
||||
|
||||
void Peer::handle_read_body(const boost::system::error_code& error)
|
||||
{
|
||||
if(!error)
|
||||
if (!error)
|
||||
{
|
||||
processReadBuffer();
|
||||
start_read_header();
|
||||
@@ -239,7 +256,7 @@ void Peer::handle_read_body(const boost::system::error_code& error)
|
||||
else
|
||||
{
|
||||
detach();
|
||||
std::cout << "Peer::connected Error: " << error << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
||||
std::cout << "Peer::handle_read_body: Error: " << error << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,7 +377,7 @@ void Peer::processReadBuffer()
|
||||
}
|
||||
break;
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
case newcoin::mtPROPOSE_LEDGER:
|
||||
{
|
||||
newcoin::TM msg;
|
||||
@@ -396,9 +413,7 @@ void Peer::processReadBuffer()
|
||||
else std::cout << "pars error: " << type << std::endl;
|
||||
}
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
case newcoin::mtGET_OBJECT:
|
||||
{
|
||||
newcoin::TMGetObjectByHash msg;
|
||||
|
||||
16
src/Peer.h
16
src/Peer.h
@@ -34,12 +34,10 @@ public:
|
||||
void handleConnect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it);
|
||||
|
||||
private:
|
||||
bool bRegistered;
|
||||
|
||||
boost::asio::ip::tcp::socket mSocket;
|
||||
boost::asio::ssl::context mCtx;
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> mSocketSsl;
|
||||
|
||||
void handleStart(const boost::system::error_code& error);
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<uint8_t> mReadbuf;
|
||||
@@ -47,7 +45,7 @@ protected:
|
||||
PackedMessage::pointer mSendingPacket;
|
||||
std::bitset<32> mPeerBits;
|
||||
|
||||
Peer(boost::asio::io_service& io_service);
|
||||
Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx);
|
||||
|
||||
void handle_write(const boost::system::error_code& error, size_t bytes_transferred);
|
||||
//void handle_read(const boost::system::error_code& error, size_t bytes_transferred);
|
||||
@@ -85,14 +83,14 @@ public:
|
||||
|
||||
//bool operator == (const Peer& other);
|
||||
|
||||
static pointer create(boost::asio::io_service& io_service)
|
||||
static pointer create(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx)
|
||||
{
|
||||
return pointer(new Peer(io_service));
|
||||
return pointer(new Peer(io_service, ctx));
|
||||
}
|
||||
|
||||
boost::asio::ip::tcp::socket& getSocket()
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::lowest_layer_type& getSocket()
|
||||
{
|
||||
return mSocket;
|
||||
return mSocketSsl.lowest_layer();
|
||||
}
|
||||
|
||||
void connect(const std::string strIp, int iPort);
|
||||
|
||||
@@ -4,23 +4,55 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/mem_fn.hpp>
|
||||
//#include <boost/log/trivial.hpp>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace boost::asio::ip;
|
||||
|
||||
PeerDoor::PeerDoor(boost::asio::io_service& io_service) :
|
||||
mAcceptor(io_service, tcp::endpoint(address().from_string(theConfig.PEER_IP), theConfig.PEER_PORT))
|
||||
// Generate DH for SSL connection.
|
||||
static DH* handleTmpDh(SSL* ssl, int is_export, int keylength)
|
||||
{
|
||||
cout << "Opening peer door on port: " << theConfig.PEER_PORT << endl;
|
||||
// We don't care if for export or what length was requested. Always do 512.
|
||||
static DH* mDh512 = 0;
|
||||
|
||||
if (!mDh512)
|
||||
{
|
||||
int iCodes;
|
||||
|
||||
do {
|
||||
mDh512 = DH_generate_parameters(512, DH_GENERATOR_5, NULL, NULL);
|
||||
iCodes = 0;
|
||||
DH_check(mDh512, &iCodes);
|
||||
} while (iCodes & (DH_CHECK_P_NOT_PRIME|DH_CHECK_P_NOT_SAFE_PRIME|DH_UNABLE_TO_CHECK_GENERATOR|DH_NOT_SUITABLE_GENERATOR));
|
||||
}
|
||||
|
||||
return mDh512;
|
||||
}
|
||||
|
||||
PeerDoor::PeerDoor(boost::asio::io_service& io_service) :
|
||||
mAcceptor(io_service, tcp::endpoint(address().from_string(theConfig.PEER_IP), theConfig.PEER_PORT)),
|
||||
mCtx(boost::asio::ssl::context::sslv23)
|
||||
{
|
||||
mCtx.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(mCtx.native_handle(), handleTmpDh);
|
||||
SSL_CTX_set_cipher_list(mCtx.native_handle(), "ALL:!LOW:!EXP:!MD5:@STRENGTH");
|
||||
|
||||
cerr << "Peer port: " << theConfig.PEER_IP << " " << theConfig.PEER_PORT << endl;
|
||||
|
||||
startListening();
|
||||
}
|
||||
|
||||
void PeerDoor::startListening()
|
||||
{
|
||||
Peer::pointer new_connection = Peer::create(mAcceptor.get_io_service());
|
||||
Peer::pointer new_connection = Peer::create(mAcceptor.get_io_service(), mCtx);
|
||||
|
||||
mAcceptor.async_accept(new_connection->getSocket(),
|
||||
boost::bind(&PeerDoor::handleConnect, this, new_connection,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <set>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
|
||||
#include "Peer.h"
|
||||
|
||||
@@ -11,10 +12,12 @@ Handles incoming connections from other Peers
|
||||
|
||||
class PeerDoor
|
||||
{
|
||||
boost::asio::ip::tcp::acceptor mAcceptor;
|
||||
void startListening();
|
||||
void handleConnect(Peer::pointer new_connection,
|
||||
const boost::system::error_code& error);
|
||||
private:
|
||||
boost::asio::ip::tcp::acceptor mAcceptor;
|
||||
boost::asio::ssl::context mCtx;
|
||||
|
||||
void startListening();
|
||||
void handleConnect(Peer::pointer new_connection, const boost::system::error_code& error);
|
||||
|
||||
public:
|
||||
PeerDoor(boost::asio::io_service& io_service);
|
||||
|
||||
@@ -10,7 +10,7 @@ using namespace boost::asio::ip;
|
||||
RPCDoor::RPCDoor(boost::asio::io_service& io_service) :
|
||||
mAcceptor(io_service, tcp::endpoint(address::from_string(theConfig.RPC_IP), theConfig.RPC_PORT))
|
||||
{
|
||||
cout << "Opening rpc door on port: " << theConfig.RPC_PORT << endl;
|
||||
cerr << "RPC port: " << theConfig.RPC_IP << " " << theConfig.RPC_PORT << endl;
|
||||
startListening();
|
||||
}
|
||||
|
||||
@@ -47,3 +47,4 @@ void RPCDoor::handleConnect(RPCServer::pointer new_connection,
|
||||
|
||||
startListening();
|
||||
}
|
||||
// vim:ts=4
|
||||
|
||||
Reference in New Issue
Block a user